Update GPG key for signing flatpaks.
[pspp] / git-import-tar
index 5d92e4cd4c8d667e12b60941814d6306706ca7b6..13d70b1aa4e8aa07858f3c73aa8a60c1c4597fec 100755 (executable)
@@ -5,22 +5,25 @@ use warnings;
 use Getopt::Long qw(:config bundling no_ignore_case);
 
 my $help = 0;
-my $build_binary = 1;
-my $batch = 0;
-my $builddir;
-my $build_number;
-GetOptions ("h|help" => \$help);
+my $message_file;
+my $message;
+GetOptions ("F=s" => \$message_file,
+           "m=s" => \$message,
+           "h|help" => \$help);
 
 usage () if $help;
 
 sub usage {
     print <<EOF;
-$0, for importing a tarball as a Git branch or tag
-usage: $0 [OPTIONS] TARBALL REFNAME
-where TARBALL is the name of a tarball
-  and REF is a Git tag (refs/tags/...) or branch (refs/heads/...).
+$0, for importing a tarball as a Git branch
+usage: $0 [OPTIONS] TARBALL BRANCH
+where TARBALL is the name of a tarball and BRANCH is a branch to create or
+update.  (If you want it to be a normal user-visible Git branch then BRANCH
+should start with "refs/heads".)
 
 Options:
+  -F FILE           Read commit message from FILE.
+  -m MESSAGE        Use MESSAGE as commit message.
   --help            Print this usage message and exit
 EOF
     exit(0);
@@ -29,18 +32,34 @@ EOF
 die "$0: exactly two nonoption arguments are required (use --help for help)\n"
   if @ARGV != 2;
 
-our $tarball = $ARGV[0];
-our $refname = $ARGV[1];
-die "$0: \"$refname\" does not start with refs/tags or refs/heads\n"
-  if $refname !~ /^refs/(tags|heads)/;
+our ($tarball, $branch) = @ARGV;
 
-my $branch = $ENV{'branch'};
-$branch = "refs/heads/$branch" if $branch !~ m(/);
-my $new_branch = system("git rev-parse --verify $branch >/dev/null 2>&1") != 0;
+my $new_branch = system ("git rev-parse --verify $branch >/dev/null 2>&1") != 0;
 
-open(MESSAGE, '<', $ARGV[0]) or die "$ARGV[0]: open: $!\n";
-my $message = join('', <MESSAGE>);
-close(MESSAGE);
+if (defined ($message_file)) {
+    open (MESSAGE, '<', $message_file)
+      or die "$0: failed to open \"$message_file\": $!\n";
+    $message .= join ('', <MESSAGE>);
+    close (MESSAGE);
+} elsif (!defined ($message)) {
+    $message = "Import of $tarball.\n";
+}
+
+if (! -e $tarball) {
+    die "$0: $tarball: not found\n";
+} elsif ($tarball =~ /gz$/) {
+    open (TARBALL, "-|", "zcat $tarball")
+      or die "$0: \"zcat $tarball\" failed to start: $!\n";
+} else {
+    open (TARBALL, '<', $tarball)
+      or die "$0: failed to open \"$tarball\": $!\n";
+}
+
+my $committer_ident = `git var GIT_COMMITTER_IDENT`;
+chomp $committer_ident;
+
+open (GFI, "|-", "git fast-import --date-format=raw --quiet")
+  or die "$0: \"git fast-import\" failed to start: $!\n";
 
 my $mark = 1;
 our $offset = 0;
@@ -48,7 +67,7 @@ my @commit;
 my @metadata;
 my @gitignore;
 for (;;) {
-    my (%member) = read_tar_header();
+    my (%member) = read_tar_header ();
     last if !%member;
     next if $member{NAME} eq '.'; # Skip root directory.
 
@@ -61,45 +80,47 @@ for (;;) {
         push(@commit, "M $gitmode :$mark $member{NAME}\n");
 
         my $size = $member{SIZE};
-        print "blob\n";
-        print "mark :", $mark++, "\n";
-        print "data $size\n";
+        print GFI "blob\n";
+        print GFI "mark :", $mark++, "\n";
+        print GFI "data $size\n";
         my $remaining = $size;
         while ($remaining > 0) {
             my $chunk = $remaining > 65536 ? 65536 : $remaining;
-            my $data = read_fully($chunk);
-            print $data;
+            my $data = read_fully ($chunk);
+            print GFI $data;
             $remaining -= $chunk;
         }
         read_fully(512 - $size % 512) if $size % 512;
-        print "\n";
+        print GFI "\n";
     } elsif ($type eq 'l') {
         push(@commit, "M 120000 :$mark $member{NAME}\n");
 
-        print "blob\n";
-        print "mark :", $mark++, "\n";
-        print "data ", length($member{LINKNAME}), "\n";
-        print $member{LINKNAME}, "\n";
+        print GFI "blob\n";
+        print GFI "mark :", $mark++, "\n";
+        print GFI "data ", length($member{LINKNAME}), "\n";
+        print GFI $member{LINKNAME}, "\n";
     } elsif ($type eq 'd') {
         # We don't do anything about directories.  In particular,
         # ignoring them is a bad idea because files added under them
         # will then also be ignored.
     } else {
-       print STDERR "$member{NAME}: Git cannot represent tar member of type '$type', ignoring\n"
+       print STDERR "$0: tar member $member{NAME} has type '$type' that Git cannot represent, ignoring\n"
     }
 }
 
 my $commit = $mark++;
-print "commit $branch\n";
-print "mark :$commit\n";
-print "committer $ENV{GIT_COMMITTER_NAME} <$ENV{GIT_COMMITTER_EMAIL}> ",
-  time(), " +0000\n";
-print "data ", length($message), "\n";
-print $message, "\n";
-print "merge $branch^0\n" if !$new_branch;
-print "deleteall\n";
-print $_ foreach @commit;
-print "\n";
+print GFI "commit $branch\n";
+print GFI "mark :$commit\n";
+print GFI "committer $committer_ident\n";
+print GFI "data ", length($message), "\n";
+print GFI $message, "\n";
+print GFI "merge $branch^0\n" if !$new_branch;
+print GFI "deleteall\n";
+print GFI $_ foreach @commit;
+print GFI "\n";
+
+close (TARBALL) or die "$0: \"zcat $tarball\" exited with status $?\n";
+close (GFI) or die "$0: \"git fast-import\" exited with status $?\n";
 
 sub check_header {
     my ($header) = @_;
@@ -125,7 +146,7 @@ sub read_fully {
     my $data = '';
     while (length($data) < $nbytes) {
         my $chunk = $nbytes - length($data);
-        my $bytes_read = sysread(STDIN, $data, $chunk, length($data));
+        my $bytes_read = sysread (TARBALL, $data, $chunk, length($data));
         $offset += $bytes_read;
         fail("$tarball: read error: $!") if !defined($bytes_read);
         fail("$tarball: unexpected end of file") if !$bytes_read;
@@ -200,7 +221,6 @@ sub read_tar_header {
 
     # Get other information.
     my ($mode) = oct(substr($header, 100, 8));
-    my ($mtime) = oct(substr($header, 136, 12));
 
     if ($type !~ /[-hlcbdp]/) {
         # Read and discard any data.
@@ -216,7 +236,6 @@ sub read_tar_header {
     return (TYPE => $type,
             NAME => $name,
             MODE => $mode,
-            MTIME => $mtime,
             SIZE => $size,
             LINKNAME => $linkname,
             TYPE => $type);