File Coverage

blib/lib/NVMPL/Platform/Windows.pm
Criterion Covered Total %
statement 24 69 34.7
branch 0 22 0.0
condition 0 5 0.0
subroutine 8 13 61.5
pod 0 5 0.0
total 32 114 28.0


line stmt bran cond sub pod time code
1             package NVMPL::Platform::Windows;
2 1     1   1385 use strict;
  1         3  
  1         46  
3 1     1   6 use warnings;
  1         2  
  1         57  
4 1     1   7 use feature 'say';
  1         2  
  1         108  
5 1     1   7 use File::Spec;
  1         3  
  1         50  
6 1     1   6 use File::Path qw(make_path remove_tree);
  1         3  
  1         81  
7 1     1   8 use File::Copy qw(move);
  1         2  
  1         56  
8 1     1   7 use Archive::Zip qw(AZ_OK);
  1         2  
  1         119  
9 1     1   10 use NVMPL::Utils qw(log_info log_warn log_error);
  1         2  
  1         1182  
10              
11             # ---------------------------------------------------------
12             # Create a directory junction (mklink /J)
13             # ---------------------------------------------------------
14              
15             sub create_junction {
16 0     0 0   my ($target, $link) = @_;
17              
18 0 0 0       if (-e $link || -l $link) {
19 0 0         unlink $link or log_warn("Could not remove existing link: $!");
20             }
21              
22 0           my $cmd = qq(cmd /C mklink /J "$link" "$target");
23 0 0 0       system($cmd) == 0
24             or log_error("Failed to create junction: $!") and return 0;
25            
26 0           log_info("Created junction: $link -> $target");
27 0           return 1;
28             }
29              
30             # ---------------------------------------------------------
31             # Remove a version directory safely
32             # ---------------------------------------------------------
33              
34             sub remove_version_dir {
35 0     0 0   my ($dir) = @_;
36 0 0         if (-d $dir) {
37 0           remove_tree($dir, { safe => 1 });
38 0           log_info("Removed directory: $dir");
39 0           return 1;
40             } else {
41 0           log_warn("Directory not found: $dir");
42 0           return 0;
43             }
44             }
45              
46             # ---------------------------------------------------------
47             # Extract a .zip archive into target directory
48             # ---------------------------------------------------------
49              
50             sub extract_zip {
51 0     0 0   my ($archive, $target_dir) = @_;
52              
53 0           log_info("Extracting $archive to $target_dir");
54 0 0         make_path($target_dir) unless -d $target_dir;
55              
56 0           my $zip = Archive::Zip->new();
57 0           my $status = $zip->read($archive);
58 0 0         if ($status != AZ_OK) {
59 0           log_error("Failed to read zip file: $archive");
60 0           return 0;
61             }
62              
63 0           my $ok = $zip->extractTree('', "$target_dir//");
64 0 0         unless ($ok == AZ_OK) {
65 0           log_error("Failed to extract zip file to $target_dir");
66 0           return 0;
67             }
68              
69 0 0         opendir(my $dh, $target_dir) or return 1;
70 0 0         my @subdirs = grep { /^node-v/ && -d "$target_dir//$_" } readdir($dh);
  0            
71 0           closedir $dh;
72              
73 0 0         if (@subdirs == 1) {
74 0           my $inner = "$target_dir//$subdirs[0]";
75 0 0         system("xcopy \"$inner\" \"$target_dir\" /E /I /Y >NUL") == 0
76             or log_warn("Could not flatten directory: $inner");
77 0           remove_tree($inner, { safe => 1 });
78             }
79 0           log_info("Extraction complete");
80 0           return 1;
81             }
82              
83             # ---------------------------------------------------------
84             # Get Node binary path for current version
85             # ---------------------------------------------------------
86              
87             sub node_bin_path {
88 0     0 0   my ($base_install_dir) = @_;
89 0           return File::Spec->catfile($base_install_dir, 'versions', 'current', 'bin');
90             }
91              
92             # ---------------------------------------------------------
93             # Print PowerShell snippet to set PATH
94             # ---------------------------------------------------------
95              
96             sub export_path_snippet {
97 0     0 0   my ($base_install_dir) = @_;
98 0           my $bin = node_bin_path($base_install_dir);
99 0           say 'To use this Node version in PowerShell, run:';
100 0           say " \$Env:PATH = \"$bin;\" + \$Env:PATH";
101 0           say '';
102 0           say 'Or in cmd.exe, run:';
103 0           say " set PATH=$bin;%PATH%";
104             }
105              
106             1;