summaryrefslogtreecommitdiff
path: root/git-debrebase
diff options
context:
space:
mode:
authorIan Jackson <ijackson@chiark.greenend.org.uk>2018-08-19 12:35:12 +0100
committerIan Jackson <ijackson@chiark.greenend.org.uk>2018-08-19 15:53:19 +0100
commit3284d0c936a2580f5c2d9356ca3a9d8ec0548866 (patch)
treee8c4136bf8334f0f9ec7bf31b3724aa74a57d2e9 /git-debrebase
parent67a6338276dd0d5d81e3fff493a00dbc83e270b6 (diff)
git-debrebase: Prep for avoid read-tree in walk when not rewriting
Because the git index is a flat list of files, not a directory hierarchy, git-read-tree can be very slow. We want to avoid it if possible. Introduce a new way of working, where we defer calls to read-tree. In detail: * $read_tree_upstream and $read_tree_debian, which are the only ways that walk invokes read-tree, simply record their argument; * The actual read-tree is done just before the write-tree and commit generation. read_tree_upstream, conveniently, does both halves, if it gets both arguments. * Put all of the read-tree and commit regeneration in a branch triggered if we are rewriting or "trying to be careful". Right now we are always careful, but I have tested this with a hack setting $opt_careful to 0, and the performance on the example branch in #905995 is much improved: 3.4s rather than 77s for `git-debrebase'. This is not suitable for enabling in its current form. I want to actuallly abolish the $opt_careful, and, instead, check with get_differs or git-cat-file that the tree segments, and the parent lists, are identical. When we do that we won't be checking any more that the commit generation can generate identical commits when not rewriting. But it doesn't really matter much any more provided the commits are well-formed and right, and the test suite will check that. Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
Diffstat (limited to 'git-debrebase')
-rwxr-xr-xgit-debrebase65
1 files changed, 34 insertions, 31 deletions
diff --git a/git-debrebase b/git-debrebase
index 1e205c6..3d4bb60 100755
--- a/git-debrebase
+++ b/git-debrebase
@@ -50,9 +50,11 @@ usages:
See git-debrebase(1), git-debrebase(5), dgit-maint-debrebase(7) (in dgit).
END
-our ($opt_force, $opt_noop_ok, @opt_anchors);
+our ($opt_force, $opt_careful, $opt_noop_ok, @opt_anchors);
our ($opt_defaultcmd_interactive);
+$opt_careful = 1;
+
our $us = qw(git-debrebase);
our $wrecknoteprefix = 'refs/debrebase/wreckage';
@@ -1434,17 +1436,11 @@ sub walk ($;$$$) {
in_workarea sub {
mkdir $rd or $!==EEXIST or die $!;
my $current_method;
- runcmd @git, qw(read-tree), $build;
-
- my $read_tree_upstream = sub {
- my ($treeish) = @_;
- read_tree_upstream $treeish, 0, $build;
- };
+ my $want_tree_debian = $build;
+ my $want_tree_upstream = $build;
- my $read_tree_debian = sub {
- my ($treeish) = @_;
- read_tree_debian($treeish);
- };
+ my $read_tree_upstream = sub { ($want_tree_upstream) = @_; };
+ my $read_tree_debian = sub { ($want_tree_debian) = @_; };
foreach my $cl (qw(Debian), (reverse @brw_cl),
{ SpecialMethod => 'RecordBreakwaterTip' },
@@ -1533,27 +1529,34 @@ sub walk ($;$$$) {
printdebug "WALK REWRITING NOW cl=$cl procd=$procd\n";
}
}
- my $newtree = cmdoutput @git, qw(write-tree);
- my $ch = $cl->{Hdr};
- $ch =~ s{^tree .*}{tree $newtree}m or confess "$ch ?";
- $ch =~ s{^parent .*\n}{}mg;
- $ch =~ s{(?=^author)}{
- join '', map { "parent $_\n" } @parents
- }me or confess "$ch ?";
- if ($rewriting) {
- $ch =~ s{^committer .*$}{$committer_authline}m
- or confess "$ch ?";
+ if ($rewriting || $opt_careful) {
+ read_tree_upstream $want_tree_upstream, 0, $want_tree_debian;
+
+ my $newtree = cmdoutput @git, qw(write-tree);
+ my $ch = $cl->{Hdr};
+ $ch =~ s{^tree .*}{tree $newtree}m or confess "$ch ?";
+ $ch =~ s{^parent .*\n}{}mg;
+ $ch =~ s{(?=^author)}{
+ join '', map { "parent $_\n" } @parents
+ }me or confess "$ch ?";
+ if ($rewriting) {
+ $ch =~ s{^committer .*$}{$committer_authline}m
+ or confess "$ch ?";
+ }
+ my $cf = "$rd/m$rewriting";
+ open CD, ">", $cf or die $!;
+ print CD $ch, "\n", $cl->{Msg} or die $!;
+ close CD or die $!;
+ my @cmd = (@git, qw(hash-object));
+ push @cmd, qw(-w) if $rewriting;
+ push @cmd, qw(-t commit), $cf;
+ my $newcommit = cmdoutput @cmd;
+ confess "$ch ?" unless $rewriting
+ or $newcommit eq $cl->{CommitId};
+ $build = $newcommit;
+ } else {
+ $build = $cl->{CommitId};
}
- my $cf = "$rd/m$rewriting";
- open CD, ">", $cf or die $!;
- print CD $ch, "\n", $cl->{Msg} or die $!;
- close CD or die $!;
- my @cmd = (@git, qw(hash-object));
- push @cmd, qw(-w) if $rewriting;
- push @cmd, qw(-t commit), $cf;
- my $newcommit = cmdoutput @cmd;
- confess "$ch ?" unless $rewriting or $newcommit eq $cl->{CommitId};
- $build = $newcommit;
if (grep { $method eq $_ } qw(DgitImportUpstreamUpdate)) {
$last_anchor = $cur;
}