chiark / gitweb /
nailing-cargo: Support for alternative Cargo.lock
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Sun, 10 May 2020 23:30:40 +0000 (00:30 +0100)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Sun, 10 May 2020 23:30:40 +0000 (00:30 +0100)
Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
nailing-cargo

index 64f84ba025dab86172de0551ac42b25cf8bc372a..36d652eaf6a1facb26c634bfd0d6cd2e7df9199e 100755 (executable)
@@ -82,6 +82,7 @@ our $lockfile = "../.nailing-cargo.lock";
 
 our $cargo_lock_update;
 our $cargo_manifest_args;
+our $alt_cargo_lock;
 
 our @configs;
 our $verbose=1;
@@ -247,6 +248,32 @@ sub readnail () {
   }
 }
 
+our @alt_cargo_lock_stat;
+
+sub consider_alt_cargo_lock () {
+  my @ck = qw(alt_cargo_lock);
+  # User should *either* have Cargo.lock in .gitignore,
+  # or expect to commit Cargo.lock.example ($alt_cargo_lock)
+
+  $alt_cargo_lock = (cfg_uc @ck) // Types::Serialiser::true;
+
+  if (Types::Serialiser::is_bool $alt_cargo_lock) {
+    if (!$alt_cargo_lock) { $alt_cargo_lock = undef; return; }
+    $alt_cargo_lock = 'Cargo.lock.example';
+  }
+
+  if (ref($alt_cargo_lock) || $alt_cargo_lock =~ m{/}) {
+    badcfg @ck, "expected boolean, or leafname";
+  }
+
+  if (!stat_exists $alt_cargo_lock, "alt_cargo_lock") {
+    $alt_cargo_lock = undef;
+    return;
+  }
+  
+  @alt_cargo_lock_stat = stat _;
+}
+
 our $oot_dir;      # oot.dir or "Build"
 
 sub consider_oot () {
@@ -474,14 +501,35 @@ END {
     foreach my $mf (keys %manifests) {
       eval { uninstall1($mf,1); 1; } or warn "$@";
     }
+    unaltcargolock(1) or warn "$@";
   }
 }
 
+our $cleanup_remove_cargo_lock;
 sub makebackups () {
   foreach my $mf (keys %manifests) {
     link "$mf", "$mf.unnailed" or $!==EEXIST
       or die "$self: make backup link $mf.unnailed: $!\n";
   }
+
+  if (defined $alt_cargo_lock) {
+    print STDERR "$self: using alt_cargo_lock `$alt_cargo_lock'..."
+      if $verbose>=3;
+    if (link $alt_cargo_lock, 'Cargo.lock') {
+      print STDERR " linked\n" if $verbose>=3;
+    } elsif ($! != EEXIST) {
+      print STDERR "\n" if $verbose>=3;
+      die "$self: make \`Cargo.lock' available as \`$alt_cargo_lock': $!\n";
+    } else {
+      print STDERR "checking quality." if $verbose>=3;
+      my @lock_stat = stat 'Cargo.lock'
+       or die "$self: stat Cargo.lock (for alt check: $!\n";
+      same_file(\@alt_cargo_lock_stat, \@lock_stat)
+       or die
+"$self: \`Cargo.lock' and alt file \`$alt_cargo_lock' both exist and are not the same file!\n";
+    }
+    $cleanup_remove_cargo_lock = 1;
+  }
 }
 
 sub nailed ($) {
@@ -548,12 +596,21 @@ sub uninstall1 ($$) {
     or die "$self: failed to restore: rename $unnailed back to $mf: $!\n";
 }
 
+sub unaltcargolock ($) {
+  my ($enoentok) = @_;
+  return unless $cleanup_remove_cargo_lock;
+  die 'internal error!' unless defined $alt_cargo_lock;
+  unlink 'Cargo.lock' or ($enoentok && $!==ENOENT) or die
+ "$self: cleanup: remove \`Cargo.lock' in favour of \`$alt_cargo_lock': $!\n";
+}
+
 sub uninstall () {
   foreach my $mf (keys %manifests) {
     my $nailed = nailed($mf);
     link $mf, $nailed or die "$self: preserve (link) $mf as $nailed: $!\n";
     uninstall1($mf,0);
   }
+  unaltcargolock(0);
 }
 
 while (@ARGV && $ARGV[0] =~ m/^-/) {
@@ -594,6 +651,7 @@ die "$self: need command to run\n" unless @ARGV || $noact;
 
 takelock();
 readnail();
+consider_alt_cargo_lock();
 consider_oot();
 readorigs();
 calculate();
@@ -622,8 +680,9 @@ $want_uninstall = 1;
 makebackups();
 install();
 
-printf STDERR "$self: nailed (%s manifests, %s packages)\n",
-  (scalar keys %manifests), (scalar keys %packagemap)
+printf STDERR "$self: nailed (%s manifests, %s packages)%s\n",
+  (scalar keys %manifests), (scalar keys %packagemap),
+  (defined($alt_cargo_lock) and ", using `$alt_cargo_lock'")
   if $verbose;
 
 print STDERR "$self: invoking: @display_cmd\n" if $verbose;