Index: locker/update-system/bin/build-update
===================================================================
--- locker/update-system/bin/build-update	(revision 446)
+++ locker/update-system/bin/build-update	(revision 446)
@@ -0,0 +1,111 @@
+#!/usr/athena/bin/perl
+
+use File::Spec::Functions qw(:ALL);
+use File::Copy;
+use File::Path;
+use Data::Dumper;
+use Getopt::Long;
+use Cwd;
+use strict;
+use warnings;
+
+my $scriptsdev = "";
+
+GetOptions(
+#"redo-delete" => \$redodelete,
+#	   "redo-add" => \$redoadd,
+#	   "redo-replace" => \$redoreplace,
+#	   "redo-diff" => \$redodiff,
+#	   "redo-all" => sub {$redodelete = $redoadd = $redoreplace = $redodiff = 1;},
+	   "dev" => sub {$scriptsdev = "dev";},
+		  );
+
+if (@ARGV < 3) {
+  print STDERR "Usage: $0 package oldversion newversion\n";
+  exit(1);
+}
+
+my ($package, $oldversion, $newversion) = @ARGV;
+my ($old, $new, $updatename) = ($package.'-'.$oldversion, $package.'-'.$newversion, $package.'-'.$oldversion.'-to-'.$newversion);
+
+my $proposaldir = $updatename.".proposal";
+my $outdir = catdir("/mit/scripts/deploy$scriptsdev/updates/", $updatename);
+
+(-d $proposaldir) or die "Can't find $proposaldir, did you run propose-update?\n";
+(-d $outdir || mkdir($outdir)) or die "mkdir($outdir) failed: $!";
+
+my $olddir = catdir($proposaldir,$old);
+my $newdir = catdir($proposaldir,$new);
+(-d $olddir && -d $newdir) or die "Packages not unpacked?\n";
+
+sub readFileList($) {
+  my ($list) = @_;
+  open(LIST, $list) or die "Can't read $list: $!\n";
+  my @files = map { chomp; s|$newdir\/?||g; [split(' ', $_, 2)] } <LIST>;
+  close(LIST);
+  return @files;
+}
+
+my @todelete = readFileList(catfile($proposaldir, "files.delete"));
+my @toadd = readFileList(catfile($proposaldir, "files.add"));
+my @toreplace = readFileList(catfile($proposaldir, "files.replace"));
+
+open(CHECKMD5, ">", catfile($outdir, "check.md5")) or die "Can't open check.md5: $!";
+print CHECKMD5 map { join(" ", @{$_})."\n" } @todelete, @toreplace;
+close(CHECKMD5);
+
+open(ABSENT, ">", catfile($outdir, "oldfiles.absent")) or die "Can't open oldfiles.absent: $!";
+print ABSENT map { $_->[1]."\n" } @toadd;
+close(ABSENT);
+
+open(DELETE, ">", catfile($outdir, "files.delete")) or die "Can't open files.delete: $!";
+print DELETE map { $_->[1]."\n" } @todelete, @toreplace;
+close(DELETE);
+
+my $outfiledir = catdir($outdir, "newfiles");
+(-d $outfiledir || mkdir($outfiledir)) or die "Can't mkdir($outfiledir)\n";
+
+foreach my $file (@toadd, @toreplace) {
+  my $filename = $file->[1];
+  my $src = catfile($newdir, $filename);
+  my $dest = catfile($outfiledir, $filename);
+  my (undef, $dir, undef) = splitpath($dest);
+  mkpath($dir);
+  copy($src, $dest) or die "Couldn't copy $filename from $src to $dest: $!";
+}
+
+copy(catfile($proposaldir, "update.diff"), catfile($outdir, "update.diff")) or die "Couldn't copy update.diff: $!";
+
+open (SCRIPT, ">", catfile($outdir, "update")) or die "Couldn't write update: $!";
+printf SCRIPT <<'EOF', $updatename, $new;
+#!/bin/bash
+set -e -o noclobber
+
+die () { echo "$1" >&2; exit 1; }
+
+patchdir=$(dirname "$0")
+
+>.scripts-security-upd-lock || die "error: Unable to obtain update lock."
+
+echo "[$PWD] begin dry run"
+
+xargs -n1 test ! -e <"$patchdir/oldfiles.absent" || die "error: Conflicting files exist."
+md5sum -c "$patchdir/check.md5" || die "error: MD5 check failed."
+patch -stN --dry-run --no-backup-if-mismatch -p1 <"$patchdir/update.diff" || due "error: Patch dry run failed."
+
+echo "[$PWD] dry run OK, applying update"
+
+mv .scripts-version .scripts-version.old
+patch -stN --no-backup-if-mismatch -p1 <"$patchdir/update.diff" || :
+xargs rm -f <"$patchdir/files.delete"
+cp -a "$patchdir/newfiles/." .
+(cat .scripts-version.old; date; echo "%s"; echo "%s") >>.scripts-version
+rm -f .scripts-version.old
+
+rm -f .scripts-security-upd-lock
+
+echo "[$PWD] done"
+
+exit 0
+EOF
+chmod 0755, catfile($outdir, "update");
Index: locker/update-system/bin/propose-update
===================================================================
--- locker/update-system/bin/propose-update	(revision 411)
+++ locker/update-system/bin/propose-update	(revision 446)
@@ -34,9 +34,9 @@
 
 unpackPackage($old, $olddir);
-unpackPackage($old, $newdir);
+unpackPackage($new, $newdir);
 
 sub unpackPackage($$) {
   my ($package, $dir) = @_;
-  print "Extracting $package to $dir...";
+  print STDERR "Extracting $package to $dir... ";
   if (-d $dir) {
     warn "$dir already exists; assuming unpacking was successful";
@@ -113,5 +113,7 @@
 my (@todelete, @toadd, @changed);
 my @comp = compareDirectories(\@oldfiles, \@newfiles);
-print Dumper(@comp);
+open(DIFF, ">", catfile($outdir, "diff.pl"));
+print DIFF Dumper(@comp);
+close(DIFF);
 @todelete = @{$comp[0]};
 @toadd = @{$comp[1]};
@@ -124,13 +126,15 @@
 	}
 	close(TODELETE);
-}
+	printf "Wrote %d filenames to files.delete\n", scalar(@todelete);
+} else { printf "Not overwriting existing files.delete\n"; }
 
 if ($redoadd or ! -e catfile($outdir, "files.add")) {
 	open(TOADD, ">", catfile($outdir, "files.add")) or die "Can't open files.add: $!";
 	foreach my $file (@toadd) {
-	  printf TOADD "%s # MD5 = %s\n", $file->[1], $file->[0];
+	  printf TOADD "%s %s\n", $file->[0], $file->[1];
 	}
 	close(TOADD);
-}
+	printf "Wrote %d filenames to files.add\n", scalar(@toadd);
+} else { printf "Not overwriting existing files.add\n"; }
 
 my @toreplace;
@@ -148,6 +152,21 @@
 	open(TOREPLACE, ">", catfile($outdir, "files.replace")) or die "Can't open files.replace: $!";
 	foreach my $file (@toreplace) {
-		printf TOREPLACE "%s %s\n", $file->[2][0], $file->[0];
+		printf TOREPLACE "%s %s\n", $file->[1][0], $file->[0];
 	}
 	close(TOREPLACE);
-}
+	printf "Wrote %d filenames to files.replace\n", scalar(@toreplace);
+} else { printf "Not overwriting existing files.replace\n"; }
+
+if ($redodiff or ! -e catfile($outdir, "update.diff")) {
+    open(DIFF, ">", catfile($outdir, "update.diff")) or die "Can't open update.diff: $!";
+    foreach my $file (@topatch) {
+	my $filename = $file->[0];
+	my $oldfile = catfile($olddir, $file->[1][1]);
+	my $newfile = catfile($newdir, $file->[2][1]);
+	my $cmd = "diff -urN $oldfile $newfile";
+	print DIFF "$cmd\n";
+	print DIFF `$cmd`;
+    }
+    close(DIFF);
+    printf "Wrote %d diffs to update.diff\n", scalar(@topatch);
+} else { printf "Not overwriting existing update.patch\n"; }
