#!/usr/bin/perl -w
+# dgit
+# Integration between git and Debian-style archives
+#
+# Copyright (C)2013 Ian Jackson
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
use strict;
use IO::Handle;
our $remotename = 'dgit';
-sub mainbranch () { return "$suite"; }
-sub uploadbranch () { return "upload/$suite"; }
+sub mainbranch () { return "dgit/$suite"; }
+sub uploadbranch () { return "dgit/$suite.upload"; }
+sub lref ($) { return "refs/heads/$_[0]"; }
+sub rref ($) { return "refs/remotes/$remotename/$_[0]"; }
our $ua;
return $r+0;
}
-our ($dsc_hash,$lastupl_hash);
+our ($dsc_hash,$upload_hash);
our $ud = '.git/dgit/unpack';
$authline =~ m/^[^<>]+ \<\S+\> \d+ [-+]\d+$/ or die $authline;
open C, ">../commit.tmp" or die $!;
print C "tree $tree\n" or die $!;
- print C "parent $lastupl_hash\n" or die $! if defined $lastupl_hash;
+ print C "parent $upload_hash\n" or die $! if defined $upload_hash;
print C <<END or die $!;
author $authline
committer $authline
cmdoutput qw(git log -n2), $commithash;
# ... gives git a chance to complain if our commit is malformed
my $outputhash = $commithash;
- if (defined $lastupl_hash) {
+ if (defined $upload_hash) {
chdir "$ud/$dir" or die $!;
- runcmd qw(git reset --hard), $lastupl_hash;
+ runcmd qw(git reset --hard), $upload_hash;
runcmd qw(sh -ec), 'dpkg-parsechangelog >>../changelogold.tmp';
my $oldclogp = Dpkg::Control::Hash->new();
$oldclogp->parse('../changelogold.tmp','previous changelog') or die;
return $outputhash;
}
-my $lastupl_ref = "refs/remotes/$remotename/upload/$suite";
+sub rev_parse ($) {
+ return cmdoutput qw(git rev-parse --), "$_[0]~0";
+}
+
+sub is_fast_fwd ($$) {
+ my ($ancestor,$child) = @_;
+ my $mb = cmdoutput qw(git merge-base), $dsc_hash, $upload_hash;
+ return rev_parse($mb) eq rev_parse($ancestor);
+}
sub fetch_from_archive () {
- # ensures that $lastupl_ref is what is actually in the archive,
+ # ensures that rref(uploadbranch()) is what is actually in the archive,
# one way or another
- $!=0; $lastupl_hash = `git show-ref --heads $lastupl_ref`;
+ my $upload_ref = rref(uploadbranch());
+ $!=0; $upload_hash = `git show-ref --heads $upload_ref`;
die $! if $!;
- die $? unless ($?==0 && chomp $lastupl_hash)
- or ($?==128 && !length $lastupl_hash);
+ die $? unless ($?==0 && chomp $upload_hash)
+ or ($?==128 && !length $upload_hash);
my $hash;
if (defined $dsc_hash) {
+ die "missing git history even though dsc has hash"
+ unless length $upload_hash;
$hash = $dsc_hash;
} else {
$hash = generate_commit_from_dsc();
}
- if ($lastupl_hash) {
- my $mb = cmdoutput qw(git merge-base), $dsc_hash, $lastupl_hash;
+ if (length $upload_hash) {
die "not fast forward on last upload branch!".
" (archive's version left in DGIT_ARCHIVE)"
- unless $mb eq $lastupl_hash;
+ unless is_fast_fwd($dsc_hash, $upload_hash);
}
- if ($lastupl_ref ne $hash) {
- cmdoutput qw(git update-ref -m), 'dgit fetch', $lastupl_ref, $hash;
+ if ($upload_hash ne $hash) {
+ cmdoutput qw(git update-ref -m), 'dgit fetch', $upload_ref, $hash;
}
}
$alioth_git, $dstdir;
chdir "$dstdir" or die "$dstdir $!";
fetch_from_archive();
- runcmd qw(git reset --hard), $lastupl_ref;
+ runcmd qw(git reset --hard), rref(uploadbranch());
} 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 -q);
open H, "> .git/HEAD" or die $!;
- print H "ref: refs/heads/$suite\n" or die $!;
+ print H "ref: ".lref(mainbranch())."\n" or die $!;
close H or die $!;
runcmd qw(git remote add), $remotename, $alioth_git;
runcmd "git config branch.$suite.remote $remotename";
- runcmd "git config branch.$suite.merge refs/heads/$suite";
+ runcmd "git config branch.$suite.merge ".lref(mainbranch());
my $newhash = generate_commit_from_dsc();
runcmd qw(git reset --hard), $newhash;
}
}
sub fetch () {
-
+ if (check_for_git()) {
+ runcmd qw(git fetch -p),$remotename,
+ '+refs/heads/*:refs/remotes/origin/*';
+ }
+ fetch_from_archive();
+}
+
+sub pull () {
+ fetch();
+ runcmd qw(git merge),lref(uploadbranch());
}
sub push () {
chdir '../../../..' or die $!;
runcmd qw(git diff --exit-code), $tree;
runcmd qw(git fetch), $alioth_git,
- map { "$_:refs/remotes/$remotename/$_" }
+ map { lref($_).":".rref($_) }
(mainbranch(), uploadbranch());
-
die <<END;
+ if (!is_fast_fwd(mainbranch
+xxx introduce remote_lref
+xxx use remote_lref everywhere
+
fetch from alioth
do fast forward check and maybe fake merge
push to uploading