X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=dgit.git;a=blobdiff_plain;f=dgit;h=a051622d1617310b3e5555307d2de534a3c024a5;hp=f8b4fddabf46a87e7ce4b210ef24f6f83800b964;hb=6a8f914beb77ec4cc36ed0aecb0e5da31a450418;hpb=75d9628d62edf12c3b57c8d7d1ca614f5cc0fb17 diff --git a/dgit b/dgit index f8b4fdda..a051622d 100755 --- a/dgit +++ b/dgit @@ -111,7 +111,7 @@ sub lref () { return "refs/heads/".lbranch(); } sub lrref () { return "refs/remotes/$remotename/".server_branch($csuite); } sub rrref () { return server_ref($csuite); } -sub lrfetchrefs () { return "refs/dgit-fetch/$isuite"; } +sub lrfetchrefs () { return "refs/dgit-fetch/$csuite"; } sub stripepoch ($) { my ($vsn) = @_; @@ -448,6 +448,7 @@ our %defcfg = ('dgit.default.distro' => 'debian', 'dgit-distro.debian.git-user-force' => 'dgit', 'dgit-distro.debian.git-proto' => 'git+ssh://', 'dgit-distro.debian.git-path' => '/dgit/debian/repos', + 'dgit-distro.debian.git-create' => 'true', 'dgit-distro.debian.git-check' => 'ssh-cmd', 'dgit-distro.debian.archive-query-url', 'https://api.ftp-master.debian.org/', # 'dgit-distro.debian.archive-query-tls-key', @@ -484,20 +485,35 @@ our %defcfg = ('dgit.default.distro' => 'debian', 'dgit-distro.test-dummy.upload-host' => 'test-dummy', ); +sub git_get_config ($) { + my ($c) = @_; + + our %git_get_config_memo; + if (exists $git_get_config_memo{$c}) { + return $git_get_config_memo{$c}; + } + + my $v; + my @cmd = (@git, qw(config --), $c); + { + local ($debuglevel) = $debuglevel-2; + $v = cmdoutput_errok @cmd; + }; + if ($?==0) { + } elsif ($?==256) { + $v = undef; + } else { + failedcmd @cmd; + } + $git_get_config_memo{$c} = $v; + return $v; +} + sub cfg { foreach my $c (@_) { return undef if $c =~ /RETURN-UNDEF/; - my @cmd = (@git, qw(config --), $c); - my $v; - { - local ($debuglevel) = $debuglevel-2; - $v = cmdoutput_errok @cmd; - }; - if ($?==0) { - return $v; - } elsif ($?!=256) { - failedcmd @cmd; - } + my $v = git_get_config($c); + return $v if defined $v; my $dv = $defcfg{$c}; return $dv if defined $dv; } @@ -1020,7 +1036,7 @@ sub check_for_git () { my ($usedistro,) = access_distros(); $instead_distro= cfg("dgit-distro.$usedistro.diverts.$divert"); $instead_distro =~ s{^/}{ access_basedistro()."/" }e; - printdebug "diverting $divert so using distro $instead_distro\n"; + progress "diverting to $divert (using config for $instead_distro)"; return check_for_git(); } failedcmd @cmd unless $r =~ m/^[01]$/; @@ -1343,12 +1359,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 -q), 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 +1492,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 () { + 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 +1534,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 +1553,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"; } @@ -1768,7 +1838,6 @@ sub dopush ($) { my $tag_obj_hash = cmdoutput @git, qw(hash-object -w -t tag), $tagobjfn; runcmd_ordryrun @git, qw(verify-tag), $tag_obj_hash; runcmd_ordryrun_local @git, qw(update-ref), "refs/tags/$tag", $tag_obj_hash; - runcmd_ordryrun @git, qw(tag -v --), $tag; if (!check_for_git()) { create_remote_git_repo(); @@ -2579,8 +2648,18 @@ sub quilt_fixup_editor () { sub clean_tree () { if ($cleanmode eq 'dpkg-source') { runcmd_ordryrun_local @dpkgbuildpackage, qw(-T clean); + } elsif ($cleanmode eq 'dpkg-source-d') { + runcmd_ordryrun_local @dpkgbuildpackage, qw(-d -T clean); } elsif ($cleanmode eq 'git') { runcmd_ordryrun_local @git, qw(clean -xdf); + } elsif ($cleanmode eq 'git-ff') { + runcmd_ordryrun_local @git, qw(clean -xdff); + } elsif ($cleanmode eq 'check') { + my $leftovers = cmdoutput @git, qw(clean -xdn); + if (length $leftovers) { + print STDERR $leftovers, "\n" or die $!; + fail "tree contains uncommitted files and --clean=check specified"; + } } elsif ($cleanmode eq 'none') { } else { die "$cleanmode ?"; @@ -2675,6 +2754,9 @@ sub build_source { if ($cleanmode eq 'dpkg-source') { runcmd_ordryrun_local (@dpkgbuildpackage, qw(-us -uc -S)), changesopts(); + } elsif ($cleanmode eq 'dpkg-source-d') { + runcmd_ordryrun_local (@dpkgbuildpackage, qw(-us -uc -S -d)), + changesopts(); } else { my $pwd = must_getcwd(); my $leafdir = basename $pwd; @@ -2699,7 +2781,7 @@ sub cmd_sbuild { changedir ".."; my $pat = "${package}_".(stripepoch $version)."_*.changes"; if (act_local()) { - stat_exist $dscfn or fail "$dscfn (in parent directory): $!"; + stat_exists $dscfn or fail "$dscfn (in parent directory): $!"; stat_exists $sourcechanges or fail "$sourcechanges (in parent directory): $!"; foreach my $cf (glob $pat) { @@ -2748,6 +2830,11 @@ sub cmd_clone_dgit_repos_server { exec @cmd or fail "exec git clone: $!\n"; } +sub cmd_setup_mergechangelogs { + badusage "no arguments allowed to dgit setup-mergechangelogs" if @ARGV; + setup_mergechangelogs(); +} + #---------- argument parsing and main program ---------- sub cmd_version { @@ -2812,7 +2899,7 @@ sub parseopts () { } elsif (m/^--build-products-dir=(.*)/s) { push @ropts, $_; $buildproductsdir = $1; - } elsif (m/^--clean=(dpkg-source|git|none)$/s) { + } elsif (m/^--clean=(dpkg-source(?:-d)?|git|git-ff|check|none)$/s) { push @ropts, $_; $cleanmode = $1; } elsif (m/^--clean=(.*)$/s) { @@ -2884,9 +2971,18 @@ sub parseopts () { } elsif (s/^-wg$//s) { push @ropts, $&; $cleanmode = 'git'; + } elsif (s/^-wgf$//s) { + push @ropts, $&; + $cleanmode = 'git-ff'; } elsif (s/^-wd$//s) { push @ropts, $&; $cleanmode = 'dpkg-source'; + } elsif (s/^-wdd$//s) { + push @ropts, $&; + $cleanmode = 'dpkg-source-d'; + } elsif (s/^-wc$//s) { + push @ropts, $&; + $cleanmode = 'check'; } else { badusage "unknown short option \`$_'"; }