summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Jackson <ijackson@chiark.greenend.org.uk>2018-02-18 13:36:27 +0000
committerIan Jackson <ijackson@chiark.greenend.org.uk>2018-06-16 16:06:59 +0100
commit5320239ed0ef59ac44b83abeb80999dc2f4810fd (patch)
tree189e5c28cf37f8ed6615ceddfb632503b242484c
parent89dc73a3211b6bdc5c70dc878ca5408f8d136577 (diff)
git-debrebase: do most ref updates together, atomically
Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
-rwxr-xr-xgit-debrebase69
1 files changed, 42 insertions, 27 deletions
diff --git a/git-debrebase b/git-debrebase
index a5329b6..9f7eabe 100755
--- a/git-debrebase
+++ b/git-debrebase
@@ -157,6 +157,28 @@ sub fresh_workarea () {
in_workarea sub { playtree_setup };
}
+our @deferred_updates;
+our @deferred_update_messages;
+
+sub run_deferred_updates ($) {
+ my ($mrest) = @_;
+
+ my @upd_cmd = (@git, qw(update-ref --stdin -m), "debrebase: $mrest");
+ debugcmd '>|', @upd_cmd;
+ open U, "|-", @upd_cmd or die $!;
+ foreach (@deferred_updates) {
+ printdebug ">= ", $_, "\n";
+ print U $_, "\n" or die $!;
+ }
+ printdebug ">\$\n";
+ close U or failedcmd @upd_cmd;
+
+ print $_, "\n" foreach @deferred_update_messages;
+
+ @deferred_updates = ();
+ @deferred_update_messages = ();
+}
+
sub get_differs ($$) {
my ($x,$y) = @_;
# This resembles quiltify_trees_differ, in dgit, a bit.
@@ -840,7 +862,8 @@ sub get_head () {
sub update_head ($$$) {
my ($old, $new, $mrest) = @_;
- runcmd @git, qw(update-ref -m), "debrebase: $mrest", 'HEAD', $new, $old;
+ push @deferred_updates, "update HEAD $new $old";
+ run_deferred_updates $mrest;
}
sub update_head_checkout ($$$) {
@@ -870,8 +893,8 @@ sub cmd_launder_v0 () {
sub defaultcmd_rebase () {
my $old = get_head();
- my ($status, $message) = record_ffq_prev();
- if ($status eq 'written' || $status eq 'exists') {
+ my ($status, $message) = record_ffq_prev_deferred();
+ if ($status eq 'deferred' || $status eq 'exists') {
} else {
fproblem $status, "could not record ffq-prev: $message";
fproblems_maybe_bail();
@@ -909,17 +932,18 @@ sub ffq_prev_branchinfo () {
return ('branch', undef, $current, $ffq_prev);
}
-sub record_ffq_prev () {
+sub record_ffq_prev_deferred () {
# => ('status', "message")
# 'status' may be
- # written message is undef
+ # deferred message is undef
# exists
# detached
# weird-symref
# notbranch
# if not ff from some branch we should be ff from, is an fproblem
- # if "written", will have printed something about that to stdout,
- # and also some messages about ff checks
+ # if "deferred", will have added something about that to
+ # @deferred_update_messages, and also maybe printed (already)
+ # some messages about ff checks
my ($status, $message, $current, $ffq_prev) = ffq_prev_branchinfo();
return ($status, $message) unless $status eq 'branch';
@@ -985,10 +1009,10 @@ sub record_ffq_prev () {
}
fproblems_maybe_bail();
- runcmd @git, qw(update-ref -m), "record current head for preservation",
- $ffq_prev, $currentval, $git_null_obj;
- print "Recorded current head for preservation\n" or die $!;
- return ('written', undef);
+
+ push @deferred_updates, "update $ffq_prev $currentval $git_null_obj";
+ push @deferred_update_messages, "Recorded current head for preservation";
+ return ('deferred', undef);
}
sub cmd_new_upstream_v0 () {
@@ -1171,10 +1195,11 @@ END
sub cmd_record_ffq_prev () {
badusage "no arguments allowed" if @ARGV;
- my ($status, $msg) = record_ffq_prev();
+ my ($status, $msg) = record_ffq_prev_deferred();
if ($status eq 'exists' && $opt_noop_ok) {
print "Previous head already recorded\n" or die $!;
- } elsif ($status eq 'written') {
+ } elsif ($status eq 'deferred') {
+ run_deferred_updates 'record-ffq-prev';
} else {
fail "Could not preserve: $msg";
}
@@ -1199,6 +1224,8 @@ sub cmd_stitch () {
if (!$prev) {
fail "No ffq-prev to stitch." unless $opt_noop_ok;
}
+ push @deferred_updates, "delete $ffq_prev $prev";
+
my $old_head = get_head();
if (is_fast_fwd $old_head, $prev) {
my $differs = get_differs $old_head, $prev;
@@ -1206,9 +1233,7 @@ sub cmd_stitch () {
# ffq-prev is ahead of us, and the only tree changes it has
# are possibly addition of things in debian/patches/.
# Just wind forwards rather than making a pointless pseudomerge.
- update_head_checkout $old_head, $prev,
- "debrebase: stitch (fast forward)";
- runcmd @git, qw(update-ref -d), $ffq_prev; # should be atomic
+ update_head_checkout $old_head, $prev, "stitch (fast forward)";
return;
}
}
@@ -1217,17 +1242,7 @@ sub cmd_stitch () {
'Declare fast forward / record previous work',
"[git-debrebase pseudomerge: stitch$prose]",
];
- my @upd_cmd = (@git, qw(update-ref --stdin -m), "debrebase: stitch");
- debugcmd '>|', @upd_cmd;
- open U, "|-", @upd_cmd or die $!;
- my $u = <<END;
-update HEAD $new_head $old_head
-delete $ffq_prev $prev
-END
- printdebug ">= ", $_, "\n" foreach split /\n/, $u;
- print U $u;
- printdebug ">\$\n";
- close U or failedcmd @upd_cmd;
+ update_head $old_head, $new_head, "stitch";
}
sub cmd_convert_from_gbp () {