summaryrefslogtreecommitdiffstats
path: root/bin/git_gpush.pm
diff options
context:
space:
mode:
authorOswald Buddenhagen <oswald.buddenhagen@gmx.de>2023-04-17 14:37:07 +0200
committerOswald Buddenhagen <oswald.buddenhagen@gmx.de>2024-01-09 16:38:50 +0000
commit1cea198216f7890b4f021eb28f519f38b545e426 (patch)
treedcb29ea19f74c21073b02faea101aaeb5af49e90 /bin/git_gpush.pm
parentfe6bc746516a655cd593869a1f9581c773873d3c (diff)
gpush/gpick: revamp querying value of HEAD
don't invoke git symbolic-ref on-demand, but just load it up in-process in load_state(), which is a lot cheaper. in conjunction with the local branch heads which we already loaded up, we can simplify quite some code at no runtime cost. this also fixes the corner case of _parse_local_rev_sym() returning the tip of the wrong branch for a plain HEAD revspec when the $from revspec refers to another branch than HEAD does. Change-Id: Iffcb153f5888293c7df7a62dc692bb6196b18c93 Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
Diffstat (limited to 'bin/git_gpush.pm')
-rw-r--r--bin/git_gpush.pm42
1 files changed, 34 insertions, 8 deletions
diff --git a/bin/git_gpush.pm b/bin/git_gpush.pm
index 8d32121..4d6ceaf 100644
--- a/bin/git_gpush.pm
+++ b/bin/git_gpush.pm
@@ -454,6 +454,10 @@ sub load_config()
# branches & remotes #
######################
+# Info extracted from $GITDIR/HEAD.
+our $head_branch; # May be undef.
+our $head_commit;
+
# The name of the local branch we're working with (not necessarily the
# current branch). May be undef.
our $local_branch;
@@ -486,6 +490,14 @@ sub update_excludes()
@upstream_excludes = map { "^$_" } keys %heads;
}
+sub resolve_head($)
+{
+ my ($source) = @_;
+
+ return $source if ($source ne "HEAD");
+ return $head_branch // "";
+}
+
sub find_gerrit_remote($)
{
my ($remotes) = @_;
@@ -1092,6 +1104,25 @@ sub load_refs(@)
update_refs(0, \@updates);
}
+sub load_head()
+{
+ open(my $hf, $gitdir."/HEAD") or fail("Repository has no HEAD!?\n");
+ chomp(my $hd = <$hf>);
+ close($hf);
+ if ($hd =~ s/^ref: //) {
+ $head_branch = $hd;
+ $hd =~ s,^refs/heads/,,;
+ $head_commit = $local_refs{$hd};
+ fail("HEAD points to invalid branch $head_branch.\n")
+ if (!defined($head_commit));
+ print "HEAD points to branch $head_branch, commit $head_commit.\n"
+ if ($debug);
+ } else {
+ $head_commit = $hd;
+ print "HEAD points to commit $head_commit.\n" if ($debug);
+ }
+}
+
sub load_state($)
{
my ($all) = @_;
@@ -1099,6 +1130,7 @@ sub load_state($)
print "Loading state ...\n" if ($debug);
load_state_file();
load_refs($all ? "refs/gpush/" : "refs/gpush/i*", "refs/heads/", "refs/remotes/");
+ load_head();
}
##########################
@@ -1370,8 +1402,6 @@ sub visit_local_commits($;$)
my $analyzed_local_branch = 0;
# SHA1 of the local branch's merge base with upstream.
our $local_base;
-# SHA1 of the local branch's tip.
-our $local_tip;
# Mapping of Change-Ids to commits on the local branch.
our %changeid2local; # { change-id => SHA1 }
@@ -1408,11 +1438,7 @@ sub analyze_local_branch($)
$seen{$changeid} = $commit;
}
- # Iff we have a detached HEAD, we don't know the tip yet, because
- # we resolve only named branches. In other cases, this is a no-op.
- $local_tip = $$raw_commits[-1]{id};
-
- my $commits = get_commits_free($local_tip);
+ my $commits = get_commits_free($$raw_commits[-1]{id});
$local_base = $$commits[0]{parents}[0];
@@ -1538,7 +1564,7 @@ sub _parse_local_rev_sym($$)
my $out;
if ($rev eq 'HEAD') {
fail("HEAD is not valid for base revspecs.\n") if ($scope == SPEC_BASE);
- $out = $local_tip;
+ $out = $head_commit;
} elsif ($rev eq 'ROOT') {
fail("ROOT is not valid for tip revspecs.\n") if ($scope == SPEC_TIP);
return ($rev, 1);