summaryrefslogtreecommitdiffstats
path: root/bin/git-ggc
diff options
context:
space:
mode:
authorOswald Buddenhagen <oswald.buddenhagen@qt.io>2014-11-06 17:32:49 +0100
committerOswald Buddenhagen <oswald.buddenhagen@gmx.de>2020-03-05 18:08:43 +0000
commite85de6b3a59133000f36e92f0ce4dc553bcad586 (patch)
tree6c74c894735aa4ac4ec82e555e6265bfddd9615c /bin/git-ggc
parent2739e65faf8ee8c7fd03e9b5022b068037e42113 (diff)
gpick: accept ranges in remote change specifications as well
Change-Id: I5f99c82181c6364d9b1c8eb9370fd1025f959cd8 Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@gmx.de>
Diffstat (limited to 'bin/git-ggc')
-rwxr-xr-xbin/git-ggc39
1 files changed, 38 insertions, 1 deletions
diff --git a/bin/git-ggc b/bin/git-ggc
index 60b0d9c..ea71bce 100755
--- a/bin/git-ggc
+++ b/bin/git-ggc
@@ -100,6 +100,7 @@ sub get_gerrit_config()
}
my %gerrit2change;
+my %change2gerrits;
my %change2active;
sub query_gerrit_pull($)
@@ -121,6 +122,7 @@ sub query_gerrit_pull($)
print "$changeid is ".($active ? "" : "NOT ")."active on $branch.\n" if ($debug);
$change2active{$changeid} ||= $active;
$gerrit2change{$key} = $changeid;
+ push @{$change2gerrits{$changeid}}, $key;
}
close_process($status);
}
@@ -157,6 +159,7 @@ sub perform_gc()
print "Loading refs ...\n" if ($debug);
my %zaps; # { sequence-number => [ state-ref, ... ] }
my %fzaps; # { gerrit-number => [ fetched-ref, ... ] }
+ my %fsha1s; # { gerrit-number => [ fetched-sha1, ... ] }
my @local_refs; # These define which Changes are still active.
my %remote_refs; # Used for quickly validating upstreams.
my $branches = open_cmd_pipe(0, "git", "for-each-ref", "--format=%(objectname) %(refname)",
@@ -166,11 +169,13 @@ sub perform_gc()
$remote_refs{$_} = 1;
} elsif (s,^.{40} refs/heads/,,) {
push @local_refs, $_;
- } elsif (s,^.{40} refs/gpush/,,) {
+ } elsif (s,^(.{40}) refs/gpush/,,) {
+ my $sha1 = $1;
if (m,^i(\d+)_.*$,) {
push @{$zaps{$1}}, $_;
} elsif (m,^g(\d+)_.*$,) {
push @{$fzaps{$1}}, $_;
+ push @{$fsha1s{$1}}, $sha1;
} elsif (!m,^state(-new)?$,) {
print "Keeping unrecognized '$_'.\n" if ($debug);
}
@@ -241,7 +246,11 @@ sub perform_gc()
}
}
+ print "Visiting fetched PatchSets ...\n" if ($debug);
+ visit_local_commits([ map { @$_ } values %fsha1s ]);
+
# Keep all fetched PatchSets that correspond with kept Changes.
+ my %visit_gs;
foreach my $key (sort keys %fzaps) {
my $changeid = $gerrit2change{$key};
if (!defined($changeid)) {
@@ -251,10 +260,38 @@ sub perform_gc()
print "Keeping fetched $key ($changeid): corresponds with kept Change.\n"
if ($verbose);
delete $fzaps{$key};
+ $visit_gs{$key} = 1;
next;
}
}
}
+ # Keep all fetched PatchSets that are ancestors of other kept
+ # PatchSets, recursively.
+ my (%seen_gs, %seen_sha1s);
+ while (%visit_gs) {
+ foreach my $key (sort keys %visit_gs) {
+ delete $visit_gs{$key};
+ $seen_gs{$key} = 1;
+ foreach my $sha1 (@{$fsha1s{$key}}) {
+ while (!defined($seen_sha1s{$sha1})) {
+ $seen_sha1s{$sha1} = 1;
+ my $commit = $commit_by_id{$sha1};
+ last if (!$commit); # Hit bottom of series.
+ my $changeid = $$commit{changeid};
+ my $ngs = $change2gerrits{$changeid};
+ last if (!$ngs); # Not queried, probably hit base.
+ foreach my $nkey (@$ngs) {
+ next if (defined($seen_gs{$nkey}));
+ print "Keeping fetched $nkey ($changeid): referenced transitively.\n"
+ if ($verbose);
+ delete $fzaps{$nkey};
+ $visit_gs{$nkey} = 1;
+ }
+ $sha1 = get_1st_parent($commit);
+ }
+ }
+ }
+ }
# We completely bypass the regular state handling when it comes
# to refs, as we want to also prune refs in our namespace that