chiark / gitweb /
dgit: Set up a merge driver for debian/changelog. Closes:#769291.
[dgit.git] / dgit
diff --git a/dgit b/dgit
index 47e05f79727dda47e76dc230851300c97d26b0fc..73184fbd7ff75ea30cebe73ec512fef24e6dfa6a 100755 (executable)
--- a/dgit
+++ b/dgit
@@ -1343,12 +1343,33 @@ sub ensure_we_have_orig () {
 }
 
 sub git_fetch_us () {
-    runcmd_ordryrun_local @git, qw(fetch),access_giturl(),fetchspec();
-    if (deliberately_not_fast_forward) {
-       runcmd_ordryrun_local @git, qw(fetch -p), access_giturl(),
-           map { "+refs/$_/*:".lrfetchrefs."/$_/*" }
-           qw(tags heads);
-    }
+    my @specs = (fetchspec());
+    push @specs,
+        map { "+refs/$_/*:".lrfetchrefs."/$_/*" }
+        qw(tags heads);
+    runcmd_ordryrun_local @git, qw(fetch -p -n), access_giturl(), @specs;
+
+    my %here;
+    my $tagpat = debiantag('*',access_basedistro);
+
+    git_for_each_ref("refs/tags/".$tagpat, sub {
+       my ($objid,$objtype,$fullrefname,$reftail) = @_;
+       printdebug "currently $fullrefname=$objid\n";
+       $here{$fullrefname} = $objid;
+    });
+    git_for_each_ref(lrfetchrefs."/tags/".$tagpat, sub {
+       my ($objid,$objtype,$fullrefname,$reftail) = @_;
+       my $lref = "refs".substr($fullrefname, length lrfetchrefs);
+       printdebug "offered $lref=$objid\n";
+       if (!defined $here{$lref}) {
+           my @upd = (@git, qw(update-ref), $lref, $objid, '');
+           runcmd_ordryrun_local @upd;
+       } elsif ($here{$lref} eq $objid) {
+       } else {
+           print STDERR \
+               "Not updateting $lref from $here{$lref} to $objid.\n";
+       }
+    });
 }
 
 sub fetch_from_archive () {
@@ -1455,6 +1476,38 @@ END
     return 1;
 }
 
+sub set_local_git_config ($$) {
+    my ($k, $v) = @_;
+    runcmd @git, qw(config), $k, $v;
+}
+
+sub setup_mergechangelogs () {
+    my $driver = 'dpkg-mergechangelogs';
+    my $cb = "merge.$driver";
+    my $attrs = '.git/info/attributes';
+    ensuredir '.git/info';
+
+    open NATTRS, ">", "$attrs.new" or die "$attrs.new $!";
+    if (!open ATTRS, "<", $attrs) {
+       $!==ENOENT or die "$attrs: $!";
+    } else {
+       while (<ATTRS>) {
+           chomp;
+           next if m{^debian/changelog\s};
+           print NATTRS $_, "\n" or die $!;
+       }
+       ATTRS->error and die $!;
+       close ATTRS;
+    }
+    print NATTRS "debian/changelog merge=$driver\n" or die $!;
+    close NATTRS;
+
+    set_local_git_config "$cb.name", 'debian/changelog merge driver';
+    set_local_git_config "$cb.driver", 'dpkg-mergechangelogs -m %O %A %B %A';
+
+    rename "$attrs.new", "$attrs" or die "$attrs: $!";
+}
+
 sub clone ($) {
     my ($dstdir) = @_;
     canonicalise_suite();
@@ -1465,7 +1518,7 @@ sub clone ($) {
     runcmd @git, qw(init -q);
     my $giturl = access_giturl(1);
     if (defined $giturl) {
-       runcmd @git, qw(config), "remote.$remotename.fetch", fetchspec();
+       set_local_git_config "remote.$remotename.fetch", fetchspec();
        open H, "> .git/HEAD" or die $!;
        print H "ref: ".lref()."\n" or die $!;
        close H or die $!;
@@ -1484,6 +1537,7 @@ sub clone ($) {
        $vcsgiturl =~ s/\s+-b\s+\S+//g;
        runcmd @git, qw(remote add vcs-git), $vcsgiturl;
     }
+    setup_mergechangelogs();
     runcmd @git, qw(reset --hard), lrref();
     printdone "ready for work in $dstdir";
 }