Skip to content

Instantly share code, notes, and snippets.

@timdp
Last active February 7, 2016 02:24
Show Gist options
  • Save timdp/9134239 to your computer and use it in GitHub Desktop.
Save timdp/9134239 to your computer and use it in GitHub Desktop.
update-packages.pl
#!/usr/bin/perl
use 5.010;
use strict;
use warnings;
use Carp;
use File::Basename;
use File::Slurp;
use File::Spec;
use JSON;
my ( $base_path, $max_depth ) = @ARGV;
$base_path = File::Spec->rel2abs( $base_path || '.' );
$max_depth //= 0;
say "Discovering packages under $base_path ...";
my @results;
find_packages( $base_path, $max_depth, \@results );
say "Updating ", scalar(@results), " package(s) ...";
my %sect2opt = ( 'dependencies' => 'save', 'devDependencies' => 'save-dev' );
foreach my $path (@results) {
say "Entering $path ...";
chdir $path or croak "$path: $!";
my $json = read_file( 'package.json', binmode => ':utf8' );
my $data = decode_json($json);
my %links;
if ($^O =~ /^MSWin/) {
open(my $ph, '-|', 'dir /b /al node_modules') or croak $!;
my @junctions = <$ph>;
close($ph);
chomp(@junctions);
%links = map { $_ => undef } @junctions;
} else {
opendir(my $dh, 'node_modules') or croak $!;
my @entries = readdir($dh);
closedir($dh);
%links = map { $_ => undef }
grep { $_ ne '.' && $_ ne '..' && -l "node_modules/$_" } @entries;
}
while ( my ( $sect, $opt ) = each %sect2opt ) {
next unless exists $data->{$sect};
my @packages = grep { !exists $links{$_} } keys %{ $data->{$sect} };
run_command( 'npm uninstall ' . join( ' ', @packages ) );
foreach my $package ( @packages ) {
run_command( "npm install --$opt $package" );
}
}
}
say "Done.";
sub run_command {
my ( $cmd ) = @_;
say "Running $cmd ...";
my $status = system( $cmd );
if ($status) {
croak "Command failed: $status";
}
}
sub find_packages {
my ( $path, $depth_rem, $results ) = @_;
push @$results, $path if ( -f "$path/package.json" );
opendir( my $dh, $path ) or croak "$path: $!";
my @entries = readdir($dh);
closedir($dh);
foreach my $e (@entries) {
next if ( $e eq '.' || $e eq '..' || $e eq 'node_modules' );
my $full_path = "$path/$e";
find_packages( $full_path, $depth_rem - 1, $results )
if ( -d $full_path && $depth_rem );
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment