chiark / gitweb /
wip
[dgit.git] / dgit
diff --git a/dgit b/dgit
index 9411afc0cdc53e488131c3244778f101025cf8e9..f8bae1d0b2cf1664d939fb4f82ceda16ce09eb5f 100755 (executable)
--- a/dgit
+++ b/dgit
@@ -20,8 +20,10 @@ our $aliothpath = '/git/dgit-test';
 our $alioth_git = 'git+ssh://$aliothname/$aliothpath';
 our $alioth_sshtestbodge = [$aliothname,$aliothpath];
 
+our $remotename = 'dgit';
+
 sub mainbranch () { return "$suite"; }
-sub uploadingbranch () { return "uploading/$suite"; }
+sub uploadbranch () { return "upload/$suite"; }
 
 our $ua;
 
@@ -122,7 +124,7 @@ sub generate_commit_from_dsc () {
     chomp $tree or die;
     runcmd qw(sh -ec), 'dpkg-parsechangelog >../changelog.tmp';
     my $clogp = Dpkg::Control::Hash->new();
-    $clogp->parse('../changelog.tmp','changelog');
+    $clogp->parse('../changelog.tmp','changelog') or die;
     my $date = cmdoutput qw(date), '+%s %z', qw(-d),$clogp->{Date};
     my $author = $clogp->{Maintainer};
     $author =~ s#,.*##ms;
@@ -136,24 +138,67 @@ author $authline
 committer $authline
 
 $clogp->{Changes}
-# generated by dgit
+# imported by dgit from the archive
 END
     close C or die $!;
+    print "synthesised git commit from .dsc $clogp->{Version}\n";
     my $commithash = runcmd qw(git hash-object -w -t commit ../commit.tmp);
     chdir '../../..' or die $!;
+    cmdoutput qw(git update-ref -m),"dgit synthesise $clogp->{Version}",
+              'DGIT_ARCHIVE', $hash;
+    cmdoutput qw(git log -n2), $commithash;
+    # ... gives git a chance to complain if our commit is malformed
+    my $outputhash = $commithash;
+    if (defined $lastupl_hash) {
+       chdir $ud or die $!;
+       runcmd qw(git reset --hard), $lastupl_hash;
+       runcmd qw(sh -ec), 'dpkg-parsechangelog >>../changelogold.tmp';
+       my $oldclogp = Dpkg::Control::Hash->new();
+       $oldclogp->parse('../changelogold.tmp','previous changelog') or die;
+       $vcmp = version_compare_string($oldclogp->{Version}, $clogp->{Version});
+       if ($vcmp < 0) {
+           # git upload/ is earlier vsn than archive, use archive
+       } elsif ($vcmp >= 0) {
+           print STDERR <<END or die $!;
+Version actually in archive:    $clogp->{Version} (older)
+Last allegedly pushed/uploaded: $oldclogp->{Version} (newer or same)
+Perhaps the upload is stuck in incoming.  Using the version from git.
+END
+       } else {
+           die "version in archive is same as version in git".
+               " to-be-uploaded (upload/) branch but archive".
+               " version hash no commit hash?!\n";
+        }
+       chdir '../../..' or die $!;
+    }
     remove_tree($ud);
-    cmdoutput qw(git log -n1), $commithash;
-    return $commithash;
+    return $outputhash;
 }
 
+my $lastupl_ref = "refs/remotes/$remotename/upload/$suite";
+
 sub fetch_from_archive () {
+    # ensures that $lastupl_ref is what is actually in the archive,
+    #  one way or another
+    $!=0; $lastupl_hash = `git show-ref --heads $lastupl_ref`;
+    die $! if $!;
+    die $? unless ($?==0 && chomp $lastupl_hash) 
+       or ($?==128 && !length $lastupl_hash);
     my $hash;
     if (defined $dsc_hash) {
        $hash = $dsc_hash;
     } else {
        $hash = generate_commit_from_dsc();
     }
-    cmdoutput qw(git update-ref FETCH_HEAD) $hash;
+    if ($lastupl_hash) {
+       my $mb = cmdoutput qw(git merge-base), $dsc_hash, $lastupl_hash;
+       die "not fast forward on last upload branch!"
+           " (archive's version left in DGIT_ARCHIVE)"
+           unless $mb eq $lastupl_hash;
+    }
+    if ($lastupl_ref ne $hash) {
+       cmdoutput qw(git update-ref -m), 'dgit fetch', $lastupl_ref, $hash;
+    }
 }
 
 #sub combine () {
@@ -182,30 +227,39 @@ sub clone () {
     if (defined $dsc_hash) {
        $dsc_hash =~ m/\w+/ or die "$dsc_hash $?";
        $dsc_hash = $&;
+       print "last upload to archive specified git hash\n";
+    } else {
+       print "last upload to archive has NO git hash\n";
     }
     my $dstdir = "$package";
     if (check_for_git()) {
-       runcmd qw(git clone --origin dgit -b), $suite, '--',
+       print "cloning existing git history\n";
+       runcmd qw(git clone --origin),$remotename, qw(-b), $suite, '--',
            $alioth_git, $dstdir;
        chdir "$dstdir" or die "$dstdir $!";
-       update_from_archive();
+       record_suite_origin();
+       fetch_from_archive();
+       runcmd qw(git reset --hard), $lastupl_ref;
     } else {
+       die "missing git history even though dsc has hash" if defined $dsc_hash;
+       print "starting new git history\n";
        mkdir $dstdir or die "$dstdir $!";
        chdir "$dstdir" or die "$dstdir $!";
        runcmd qw(git init);
        open H, "> .git/refs/HEAD" or die $!;
        print H "ref: refs/heads/$suite\n" or die $!;
        close H or die $!;
-       runcmd qw(git remote add dgit), $alioth_git;
-       runcmd "git config branch.$suite.remote dgit";
+       runcmd qw(git remote add), $remotename, $alioth_git;
+       record_suite_origin();
+       runcmd "git config branch.$suite.remote $remotename";
        runcmd "git config branch.$suite.merge refs/heads/$suite";
-       update_from_archive();
+       my $newhash = generate_commit_from_dsc();
+       runcmd "git reset --hard", $newhash;
     }
 }
 
 sub fetch () {
-    my ($archive_or_mirror, $suite, $package) = @_;
-    my $dsc = get_archive_dsc();
+    
 }
     
 print Dumper(get_archive_dsc());