@matheusbsbs / matheus-bagliano / commits / 2beec89733
Fork 0

git-svn: do a partial rebuild if rev_map is out-of-date

Suppose you're using git-svn to work with a certain SVN repository. Since you don't like 'git-svn fetch' to take forever, and you don't want to accidentally interrupt it and end up corrupting your repository, you set up a remote Git repository to mirror the SVN repository, which does its own 'git-svn fetch' on a cronjob; now you can 'git-fetch' from the Git mirror into your local repository, and still dcommit to SVN when you have changes to push. After you do this, though, git-svn will get very confused if you ever try to do 'git-svn fetch' in your local repository again, since its rev_map will differ from the branch's head, and it will be unable to fetch new commits from SVN because of the metadata conflict. But all the necessary metadata are there in the Git commit message; git-svn already knows how to rebuild rev_map files that get blown away, by using the metadata. This patch teaches git-svn do a partial rebuild of the rev_map to match the true state of the branch, if it ever is used to fetch again. This will only work for projects not using either noMetadata or useSvmProps configuration options; if you are using these options, git-svn will fall back to the previous behaviour. Signed-off-by: Deskin Miller <deskinm@umich.edu> Acked-by: Eric Wong <normalperson@yhbt.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Deskin Miller committed Sep 15, 2008 at 21:12 UTC 2beec8973394e29353a9dccee45657870852ba33
2 files changed +20 -6
git-svn.perl
+19 -5
@@ -2626,9 +2626,9 @@ sub rebuild_from_rev_db {
2626 sub rebuild {
2627 my ($self) = @_;
2628 my $map_path = $self->map_path;
2629 - return if (-e $map_path && ! -z $map_path);
2629 + my $partial = (-e $map_path && ! -z $map_path);
2630 return unless ::verify_ref($self->refname.'^0');
2631 - if ($self->use_svm_props || $self->no_metadata) {
2631 + if (!$partial && ($self->use_svm_props || $self->no_metadata)) {
2632 my $rev_db = $self->rev_db_path;
2633 $self->rebuild_from_rev_db($rev_db);
2634 if ($self->use_svm_props) {
@@ -2638,10 +2638,13 @@ sub rebuild {
2638 $self->unlink_rev_db_symlink;
2639 return;
2640 }
2641 - print "Rebuilding $map_path ...\n";
2641 + print "Rebuilding $map_path ...\n" if (!$partial);
2642 + my ($base_rev, $head) = ($partial ? $self->rev_map_max_norebuild(1) :
2643 + (undef, undef));
2644 my ($log, $ctx) =
2645 command_output_pipe(qw/rev-list --pretty=raw --no-color --reverse/,
2644 - $self->refname, '--');
2646 + ($head ? "$head.." : "") . $self->refname,
2647 + '--');
2648 my $metadata_url = $self->metadata_url;
2649 remove_username($metadata_url);
2650 my $svn_uuid = $self->ra_uuid;
@@ -2664,12 +2667,17 @@ sub rebuild {
2667 ($metadata_url && $url && ($url ne $metadata_url))) {
2668 next;
2669 }
2670 + if ($partial && $head) {
2671 + print "Partial-rebuilding $map_path ...\n";
2672 + print "Currently at $base_rev = $head\n";
2673 + $head = undef;
2674 + }
2675
2676 $self->rev_map_set($rev, $c);
2677 print "r$rev = $c\n";
2678 }
2679 command_close_pipe($log, $ctx);
2672 - print "Done rebuilding $map_path\n";
2680 + print "Done rebuilding $map_path\n" if (!$partial || !$head);
2681 my $rev_db_path = $self->rev_db_path;
2682 if (-f $self->rev_db_path) {
2683 unlink $self->rev_db_path or croak "unlink: $!";
@@ -2809,6 +2817,12 @@ sub rev_map_set {
2817 sub rev_map_max {
2818 my ($self, $want_commit) = @_;
2819 $self->rebuild;
2820 + my ($r, $c) = $self->rev_map_max_norebuild($want_commit);
2821 + $want_commit ? ($r, $c) : $r;
2822 +}
2823 +
2824 +sub rev_map_max_norebuild {
2825 + my ($self, $want_commit) = @_;
2826 my $map_path = $self->map_path;
2827 stat $map_path or return $want_commit ? (0, undef) : 0;
2828 sysopen(my $fh, $map_path, O_RDONLY) or croak "open: $!";
t/t9127-git-svn-partial-rebuild.sh
+1 -1
@@ -49,7 +49,7 @@ test_expect_success 'make full git mirror of SVN' '
49 )
50 '
51
52 -test_expect_failure 'fetch from git mirror and partial-rebuild' '
52 +test_expect_success 'fetch from git mirror and partial-rebuild' '
53 git config --add remote.origin.url "file://$PWD/mirror/.git" &&
54 git config --add remote.origin.fetch refs/remotes/*:refs/remotes/* &&
55 git fetch origin &&