~ubuntu-branches/ubuntu/intrepid/git-core/intrepid-updates

« back to all changes in this revision

Viewing changes to git-svn.perl

  • Committer: Package Import Robot
  • Author(s): Gerrit Pape
  • Date: 2007-10-04 08:27:01 UTC
  • mfrom: (1.1.23)
  • Revision ID: package-import@ubuntu.com-20071004082701-rsd058ontoqz4i30
Tags: 1:1.5.3.4-1
new upstream point release (closes: #445188).

Show diffs side-by-side

added added

removed removed

Lines of Context:
38
38
use Git;
39
39
 
40
40
BEGIN {
41
 
        my $s;
 
41
        # import functions from Git into our packages, en masse
 
42
        no strict 'refs';
42
43
        foreach (qw/command command_oneline command_noisy command_output_pipe
43
44
                    command_input_pipe command_close_pipe/) {
44
 
                $s .= "*SVN::Git::Editor::$_ = *SVN::Git::Fetcher::$_ = ".
45
 
                      "*Git::SVN::Migration::$_ = ".
46
 
                      "*Git::SVN::Log::$_ = *Git::SVN::$_ = *$_ = *Git::$_; ";
 
45
                for my $package ( qw(SVN::Git::Editor SVN::Git::Fetcher
 
46
                        Git::SVN::Migration Git::SVN::Log Git::SVN),
 
47
                        __PACKAGE__) {
 
48
                        *{"${package}::$_"} = \&{"Git::$_"};
 
49
                }
47
50
        }
48
 
        eval $s;
49
51
}
50
52
 
51
53
my ($SVN);
75
77
                   \$Git::SVN::_repack_flags,
76
78
                %remote_opts );
77
79
 
78
 
my ($_trunk, $_tags, $_branches);
 
80
my ($_trunk, $_tags, $_branches, $_stdlayout);
79
81
my %icv;
80
82
my %init_opts = ( 'template=s' => \$_template, 'shared:s' => \$_shared,
81
83
                  'trunk|T=s' => \$_trunk, 'tags|t=s' => \$_tags,
82
84
                  'branches|b=s' => \$_branches, 'prefix=s' => \$_prefix,
 
85
                  'stdlayout|s' => \$_stdlayout,
83
86
                  'minimize-url|m' => \$Git::SVN::_minimize_url,
84
87
                  'no-metadata' => sub { $icv{noMetadata} = 1 },
85
88
                  'use-svm-props' => sub { $icv{useSvmProps} = 1 },
290
293
sub cmd_clone {
291
294
        my ($url, $path) = @_;
292
295
        if (!defined $path &&
293
 
            (defined $_trunk || defined $_branches || defined $_tags) &&
 
296
            (defined $_trunk || defined $_branches || defined $_tags ||
 
297
             defined $_stdlayout) &&
294
298
            $url !~ m#^[a-z\+]+://#) {
295
299
                $path = $url;
296
300
        }
300
304
}
301
305
 
302
306
sub cmd_init {
 
307
        if (defined $_stdlayout) {
 
308
                $_trunk = 'trunk' if (!defined $_trunk);
 
309
                $_tags = 'tags' if (!defined $_tags);
 
310
                $_branches = 'branches' if (!defined $_branches);
 
311
        }
303
312
        if (defined $_trunk || defined $_branches || defined $_tags) {
304
313
                return cmd_multi_init(@_);
305
314
        }
368
377
        $head ||= 'HEAD';
369
378
        my @refs;
370
379
        my ($url, $rev, $uuid, $gs) = working_head_info($head, \@refs);
 
380
        print "Committing to $url ...\n";
371
381
        unless ($gs) {
372
382
                die "Unable to determine upstream SVN information from ",
373
383
                    "$head history\n";
374
384
        }
375
 
        my $c = $refs[-1];
376
385
        my $last_rev;
377
 
        foreach my $d (@refs) {
378
 
                if (!verify_ref("$d~1")) {
379
 
                        fatal "Commit $d\n",
380
 
                              "has no parent commit, and therefore ",
381
 
                              "nothing to diff against.\n",
382
 
                              "You should be working from a repository ",
383
 
                              "originally created by git-svn\n";
384
 
                }
 
386
        my ($linear_refs, $parents) = linearize_history($gs, \@refs);
 
387
        if ($_no_rebase && scalar(@$linear_refs) > 1) {
 
388
                warn "Attempting to commit more than one change while ",
 
389
                     "--no-rebase is enabled.\n",
 
390
                     "If these changes depend on each other, re-running ",
 
391
                     "without --no-rebase will be required."
 
392
        }
 
393
        foreach my $d (@$linear_refs) {
385
394
                unless (defined $last_rev) {
386
395
                        (undef, $last_rev, undef) = cmt_metadata("$d~1");
387
396
                        unless (defined $last_rev) {
392
401
                if ($_dry_run) {
393
402
                        print "diff-tree $d~1 $d\n";
394
403
                } else {
 
404
                        my $cmt_rev;
395
405
                        my %ed_opts = ( r => $last_rev,
396
406
                                        log => get_commit_entry($d)->{log},
397
407
                                        ra => Git::SVN::Ra->new($gs->full_url),
399
409
                                        tree_b => $d,
400
410
                                        editor_cb => sub {
401
411
                                               print "Committed r$_[0]\n";
402
 
                                               $last_rev = $_[0]; },
 
412
                                               $cmt_rev = $_[0];
 
413
                                        },
403
414
                                        svn_path => '');
404
415
                        if (!SVN::Git::Editor->new(\%ed_opts)->apply_diff) {
405
416
                                print "No changes\n$d~1 == $d\n";
406
 
                        }
407
 
                }
408
 
        }
409
 
        return if $_dry_run;
410
 
        unless ($gs) {
411
 
                warn "Could not determine fetch information for $url\n",
412
 
                     "Will not attempt to fetch and rebase commits.\n",
413
 
                     "This probably means you have useSvmProps and should\n",
414
 
                     "now resync your SVN::Mirror repository.\n";
415
 
                return;
416
 
        }
417
 
        $_fetch_all ? $gs->fetch_all : $gs->fetch;
418
 
        unless ($_no_rebase) {
419
 
                # we always want to rebase against the current HEAD, not any
420
 
                # head that was passed to us
421
 
                my @diff = command('diff-tree', 'HEAD', $gs->refname, '--');
422
 
                my @finish;
423
 
                if (@diff) {
424
 
                        @finish = rebase_cmd();
425
 
                        print STDERR "W: HEAD and ", $gs->refname, " differ, ",
426
 
                                     "using @finish:\n", "@diff";
427
 
                } else {
428
 
                        print "No changes between current HEAD and ",
429
 
                              $gs->refname, "\nResetting to the latest ",
430
 
                              $gs->refname, "\n";
431
 
                        @finish = qw/reset --mixed/;
432
 
                }
433
 
                command_noisy(@finish, $gs->refname);
 
417
                        } elsif ($parents->{$d} && @{$parents->{$d}}) {
 
418
                                $gs->{inject_parents_dcommit}->{$cmt_rev} =
 
419
                                                               $parents->{$d};
 
420
                        }
 
421
                        $_fetch_all ? $gs->fetch_all : $gs->fetch;
 
422
                        next if $_no_rebase;
 
423
 
 
424
                        # we always want to rebase against the current HEAD,
 
425
                        # not any head that was passed to us
 
426
                        my @diff = command('diff-tree', 'HEAD',
 
427
                                           $gs->refname, '--');
 
428
                        my @finish;
 
429
                        if (@diff) {
 
430
                                @finish = rebase_cmd();
 
431
                                print STDERR "W: HEAD and ", $gs->refname,
 
432
                                             " differ, using @finish:\n",
 
433
                                             "@diff";
 
434
                        } else {
 
435
                                print "No changes between current HEAD and ",
 
436
                                      $gs->refname,
 
437
                                      "\nResetting to the latest ",
 
438
                                      $gs->refname, "\n";
 
439
                                @finish = qw/reset --mixed/;
 
440
                        }
 
441
                        command_noisy(@finish, $gs->refname);
 
442
                        $last_rev = $cmt_rev;
 
443
                }
434
444
        }
435
445
}
436
446
 
594
604
        my $index = $ENV{GIT_INDEX_FILE} || "$ENV{GIT_DIR}/index";
595
605
        return if -f $index;
596
606
 
597
 
        chomp(my $bare = `git config --bool --get core.bare`);
598
 
        return if $bare eq 'true';
 
607
        return if command_oneline(qw/rev-parse --is-inside-work-tree/) eq 'false';
599
608
        return if command_oneline(qw/rev-parse --is-inside-git-dir/) eq 'true';
600
609
        command_noisy(qw/read-tree -m -u -v HEAD HEAD/);
601
610
        print STDERR "Checked out HEAD:\n  ",
743
752
        my $log = $cmd eq 'log';
744
753
        while (<$authors>) {
745
754
                chomp;
746
 
                next unless /^(\S+?|\(no author\))\s*=\s*(.+?)\s*<(.+)>\s*$/;
 
755
                next unless /^(.+?|\(no author\))\s*=\s*(.+?)\s*<(.+)>\s*$/;
747
756
                my ($user, $name, $email) = ($1, $2, $3);
748
757
                if ($log) {
749
758
                        $Git::SVN::Log::rusers{"$name <$email>"} = $user;
785
794
 
786
795
sub extract_metadata {
787
796
        my $id = shift or return (undef, undef, undef);
788
 
        my ($url, $rev, $uuid) = ($id =~ /^git-svn-id:\s(\S+?)\@(\d+)
 
797
        my ($url, $rev, $uuid) = ($id =~ /^\s*git-svn-id:\s+(.*)\@(\d+)
789
798
                                                        \s([a-f\d\-]+)$/x);
790
799
        if (!defined $rev || !$uuid || !$url) {
791
800
                # some of the original repositories I made had
792
801
                # identifiers like this:
793
 
                ($rev, $uuid) = ($id =~/^git-svn-id:\s(\d+)\@([a-f\d\-]+)/);
 
802
                ($rev, $uuid) = ($id =~/^\s*git-svn-id:\s(\d+)\@([a-f\d\-]+)/);
794
803
        }
795
804
        return ($url, $rev, $uuid);
796
805
}
802
811
 
803
812
sub working_head_info {
804
813
        my ($head, $refs) = @_;
805
 
        my ($fh, $ctx) = command_output_pipe('rev-list', $head);
806
 
        while (my $hash = <$fh>) {
807
 
                chomp($hash);
808
 
                my ($url, $rev, $uuid) = cmt_metadata($hash);
 
814
        my ($fh, $ctx) = command_output_pipe('log', '--no-color', $head);
 
815
        my $hash;
 
816
        my %max;
 
817
        while (<$fh>) {
 
818
                if ( m{^commit ($::sha1)$} ) {
 
819
                        unshift @$refs, $hash if $hash and $refs;
 
820
                        $hash = $1;
 
821
                        next;
 
822
                }
 
823
                next unless s{^\s*(git-svn-id:)}{$1};
 
824
                my ($url, $rev, $uuid) = extract_metadata($_);
809
825
                if (defined $url && defined $rev) {
 
826
                        next if $max{$url} and $max{$url} < $rev;
810
827
                        if (my $gs = Git::SVN->find_by_url($url)) {
811
828
                                my $c = $gs->rev_db_get($rev);
812
829
                                if ($c && $c eq $hash) {
813
830
                                        close $fh; # break the pipe
814
831
                                        return ($url, $rev, $uuid, $gs);
 
832
                                } else {
 
833
                                        $max{$url} ||= $gs->rev_db_max;
815
834
                                }
816
835
                        }
817
836
                }
818
 
                unshift @$refs, $hash if $refs;
819
837
        }
820
838
        command_close_pipe($fh, $ctx);
821
839
        (undef, undef, undef, undef);
822
840
}
823
841
 
 
842
sub read_commit_parents {
 
843
        my ($parents, $c) = @_;
 
844
        chomp(my $p = command_oneline(qw/rev-list --parents -1/, $c));
 
845
        $p =~ s/^($c)\s*// or die "rev-list --parents -1 $c failed!\n";
 
846
        @{$parents->{$c}} = split(/ /, $p);
 
847
}
 
848
 
 
849
sub linearize_history {
 
850
        my ($gs, $refs) = @_;
 
851
        my %parents;
 
852
        foreach my $c (@$refs) {
 
853
                read_commit_parents(\%parents, $c);
 
854
        }
 
855
 
 
856
        my @linear_refs;
 
857
        my %skip = ();
 
858
        my $last_svn_commit = $gs->last_commit;
 
859
        foreach my $c (reverse @$refs) {
 
860
                next if $c eq $last_svn_commit;
 
861
                last if $skip{$c};
 
862
 
 
863
                unshift @linear_refs, $c;
 
864
                $skip{$c} = 1;
 
865
 
 
866
                # we only want the first parent to diff against for linear
 
867
                # history, we save the rest to inject when we finalize the
 
868
                # svn commit
 
869
                my $fp_a = verify_ref("$c~1");
 
870
                my $fp_b = shift @{$parents{$c}} if $parents{$c};
 
871
                if (!$fp_a || !$fp_b) {
 
872
                        die "Commit $c\n",
 
873
                            "has no parent commit, and therefore ",
 
874
                            "nothing to diff against.\n",
 
875
                            "You should be working from a repository ",
 
876
                            "originally created by git-svn\n";
 
877
                }
 
878
                if ($fp_a ne $fp_b) {
 
879
                        die "$c~1 = $fp_a, however parsing commit $c ",
 
880
                            "revealed that:\n$c~1 = $fp_b\nBUG!\n";
 
881
                }
 
882
 
 
883
                foreach my $p (@{$parents{$c}}) {
 
884
                        $skip{$p} = 1;
 
885
                }
 
886
        }
 
887
        (\@linear_refs, \%parents);
 
888
}
 
889
 
824
890
package Git::SVN;
825
891
use strict;
826
892
use warnings;
846
912
        # some options are read globally, but can be overridden locally
847
913
        # per [svn-remote "..."] section.  Command-line options will *NOT*
848
914
        # override options set in an [svn-remote "..."] section
849
 
        my $e;
850
 
        foreach (qw/follow_parent no_metadata use_svm_props
851
 
                    use_svnsync_props/) {
852
 
                my $key = $_;
 
915
        no strict 'refs';
 
916
        for my $option (qw/follow_parent no_metadata use_svm_props
 
917
                           use_svnsync_props/) {
 
918
                my $key = $option;
853
919
                $key =~ tr/_//d;
854
 
                $e .= "sub $_ {
855
 
                        my (\$self) = \@_;
856
 
                        return \$self->{-$_} if exists \$self->{-$_};
857
 
                        my \$k = \"svn-remote.\$self->{repo_id}\.$key\";
858
 
                        eval { command_oneline(qw/config --get/, \$k) };
859
 
                        if (\$@) {
860
 
                                \$self->{-$_} = \$Git::SVN::_$_;
 
920
                my $prop = "-$option";
 
921
                *$option = sub {
 
922
                        my ($self) = @_;
 
923
                        return $self->{$prop} if exists $self->{$prop};
 
924
                        my $k = "svn-remote.$self->{repo_id}.$key";
 
925
                        eval { command_oneline(qw/config --get/, $k) };
 
926
                        if ($@) {
 
927
                                $self->{$prop} = ${"Git::SVN::_$option"};
861
928
                        } else {
862
 
                                my \$v = command_oneline(qw/config --bool/,\$k);
863
 
                                \$self->{-$_} = \$v eq 'false' ? 0 : 1;
 
929
                                my $v = command_oneline(qw/config --bool/,$k);
 
930
                                $self->{$prop} = $v eq 'false' ? 0 : 1;
864
931
                        }
865
 
                        return \$self->{-$_} }\n";
 
932
                        return $self->{$prop};
 
933
                }
866
934
        }
867
 
        $e .= "1;\n";
868
 
        eval $e or die $@;
869
935
}
870
936
 
871
937
my %LOCKFILES;
879
945
        foreach (command(qw#for-each-ref --format=%(refname) refs/remotes#)) {
880
946
                next unless m#^refs/remotes/$ref->{regex}$#;
881
947
                my $p = $1;
882
 
                my $pathname = $path->full_path($p);
883
 
                my $refname = $ref->full_path($p);
 
948
                my $pathname = desanitize_refname($path->full_path($p));
 
949
                my $refname = desanitize_refname($ref->full_path($p));
884
950
                if (my $existing = $fetch->{$pathname}) {
885
951
                        if ($existing ne $refname) {
886
952
                                die "Refspec conflict:\n",
967
1033
        my $r = {};
968
1034
        foreach (grep { s/^svn-remote\.// } command(qw/config -l/)) {
969
1035
                if (m!^(.+)\.fetch=\s*(.*)\s*:\s*refs/remotes/(.+)\s*$!) {
970
 
                        $r->{$1}->{fetch}->{$2} = $3;
 
1036
                        my ($remote, $local_ref, $remote_ref) = ($1, $2, $3);
 
1037
                        $local_ref =~ s{^/}{};
 
1038
                        $r->{$remote}->{fetch}->{$local_ref} = $remote_ref;
971
1039
                } elsif (m!^(.+)\.url=\s*(.*)\s*$!) {
972
1040
                        $r->{$1}->{url} = $2;
973
1041
                } elsif (m!^(.+)\.(branches|tags)=
1087
1155
        unless ($no_write) {
1088
1156
                command_noisy('config',
1089
1157
                              "svn-remote.$self->{repo_id}.url", $url);
 
1158
                $self->{path} =~ s{^/}{};
1090
1159
                command_noisy('config', '--add',
1091
1160
                              "svn-remote.$self->{repo_id}.fetch",
1092
1161
                              "$self->{path}:".$self->refname);
1177
1246
        $self;
1178
1247
}
1179
1248
 
1180
 
sub refname { "refs/remotes/$_[0]->{ref_id}" }
 
1249
sub refname {
 
1250
        my ($refname) = "refs/remotes/$_[0]->{ref_id}" ;
 
1251
 
 
1252
        # It cannot end with a slash /, we'll throw up on this because
 
1253
        # SVN can't have directories with a slash in their name, either:
 
1254
        if ($refname =~ m{/$}) {
 
1255
                die "ref: '$refname' ends with a trailing slash, this is ",
 
1256
                    "not permitted by git nor Subversion\n";
 
1257
        }
 
1258
 
 
1259
        # It cannot have ASCII control character space, tilde ~, caret ^,
 
1260
        # colon :, question-mark ?, asterisk *, space, or open bracket [
 
1261
        # anywhere.
 
1262
        #
 
1263
        # Additionally, % must be escaped because it is used for escaping
 
1264
        # and we want our escaped refname to be reversible
 
1265
        $refname =~ s{([ \%~\^:\?\*\[\t])}{uc sprintf('%%%02x',ord($1))}eg;
 
1266
 
 
1267
        # no slash-separated component can begin with a dot .
 
1268
        # /.* becomes /%2E*
 
1269
        $refname =~ s{/\.}{/%2E}g;
 
1270
 
 
1271
        # It cannot have two consecutive dots .. anywhere
 
1272
        # .. becomes %2E%2E
 
1273
        $refname =~ s{\.\.}{%2E%2E}g;
 
1274
 
 
1275
        return $refname;
 
1276
}
 
1277
 
 
1278
sub desanitize_refname {
 
1279
        my ($refname) = @_;
 
1280
        $refname =~ s{%(?:([0-9A-F]{2}))}{chr hex($1)}eg;
 
1281
        return $refname;
 
1282
}
1181
1283
 
1182
1284
sub svm_uuid {
1183
1285
        my ($self) = @_;
1457
1559
        my (@args) = @_;
1458
1560
        my $old_def_config = "$ENV{GIT_DIR}/svn/config";
1459
1561
        my $config = "$ENV{GIT_DIR}/svn/.metadata";
1460
 
        if (-e $old_def_config && ! -e $config) {
 
1562
        if (! -f $config && -f $old_def_config) {
1461
1563
                rename $old_def_config, $config or
1462
1564
                       die "Failed rename $old_def_config => $config: $!\n";
1463
1565
        }
1541
1643
        if (my $cur = ::verify_ref($self->refname.'^0')) {
1542
1644
                push @tmp, $cur;
1543
1645
        }
 
1646
        if (my $ipd = $self->{inject_parents_dcommit}) {
 
1647
                if (my $commit = delete $ipd->{$log_entry->{revision}}) {
 
1648
                        push @tmp, @$commit;
 
1649
                }
 
1650
        }
1544
1651
        push @tmp, $_ foreach (@{$log_entry->{parents}}, @tmp);
1545
1652
        while (my $p = shift @tmp) {
1546
1653
                next if $seen{$p};
1964
2071
                return;
1965
2072
        }
1966
2073
        print "Rebuilding $db_path ...\n";
1967
 
        my ($rev_list, $ctx) = command_output_pipe("rev-list", $self->refname);
 
2074
        my ($log, $ctx) = command_output_pipe("log", '--no-color', $self->refname);
1968
2075
        my $latest;
1969
2076
        my $full_url = $self->full_url;
1970
2077
        remove_username($full_url);
1971
2078
        my $svn_uuid;
1972
 
        while (<$rev_list>) {
1973
 
                chomp;
1974
 
                my $c = $_;
1975
 
                die "Non-SHA1: $c\n" unless $c =~ /^$::sha1$/o;
1976
 
                my ($url, $rev, $uuid) = ::cmt_metadata($c);
 
2079
        my $c;
 
2080
        while (<$log>) {
 
2081
                if ( m{^commit ($::sha1)$} ) {
 
2082
                        $c = $1;
 
2083
                        next;
 
2084
                }
 
2085
                next unless s{^\s*(git-svn-id:)}{$1};
 
2086
                my ($url, $rev, $uuid) = ::extract_metadata($_);
1977
2087
                remove_username($url);
1978
2088
 
1979
2089
                # ignore merges (from set-tree)
1991
2101
                $self->rev_db_set($rev, $c);
1992
2102
                print "r$rev = $c\n";
1993
2103
        }
1994
 
        command_close_pipe($rev_list, $ctx);
 
2104
        command_close_pipe($log, $ctx);
1995
2105
        print "Done rebuilding $db_path\n";
1996
2106
}
1997
2107
 
2654
2764
 
2655
2765
sub url_path {
2656
2766
        my ($self, $path) = @_;
 
2767
        if ($self->{url} =~ m#^https?://#) {
 
2768
                $path =~ s/([^a-zA-Z0-9_.-])/uc sprintf("%%%02x",ord($1))/eg;
 
2769
        }
2657
2770
        $self->{url} . '/' . $self->repo_path($path);
2658
2771
}
2659
2772
 
2895
3008
use vars qw/@ISA $config_dir $_log_window_size/;
2896
3009
use strict;
2897
3010
use warnings;
2898
 
my ($can_do_switch, %ignored_err, $RA);
 
3011
my ($ra_invalid, $can_do_switch, %ignored_err, $RA);
2899
3012
 
2900
3013
BEGIN {
2901
3014
        # enforce temporary pool usage for some simple functions
2902
 
        my $e;
2903
 
        foreach (qw/rev_proplist get_latest_revnum get_uuid get_repos_root/) {
2904
 
                $e .= "sub $_ {
2905
 
                        my \$self = shift;
2906
 
                        my \$pool = SVN::Pool->new;
2907
 
                        my \@ret = \$self->SUPER::$_(\@_,\$pool);
2908
 
                        \$pool->clear;
2909
 
                        wantarray ? \@ret : \$ret[0]; }\n";
 
3015
        no strict 'refs';
 
3016
        for my $f (qw/rev_proplist get_latest_revnum get_uuid get_repos_root/) {
 
3017
                my $SUPER = "SUPER::$f";
 
3018
                *$f = sub {
 
3019
                        my $self = shift;
 
3020
                        my $pool = SVN::Pool->new;
 
3021
                        my @ret = $self->$SUPER(@_,$pool);
 
3022
                        $pool->clear;
 
3023
                        wantarray ? @ret : $ret[0];
 
3024
                };
2910
3025
        }
2911
 
 
2912
 
        eval "$e; 1;" or die $@;
2913
3026
}
2914
3027
 
2915
3028
sub new {
2923
3036
            SVN::Client::get_ssl_server_trust_file_provider(),
2924
3037
            SVN::Client::get_simple_prompt_provider(
2925
3038
              \&Git::SVN::Prompt::simple, 2),
 
3039
            SVN::Client::get_ssl_client_cert_file_provider(),
2926
3040
            SVN::Client::get_ssl_client_cert_prompt_provider(
2927
3041
              \&Git::SVN::Prompt::ssl_client_cert, 2),
2928
3042
            SVN::Client::get_ssl_client_cert_pw_prompt_provider(
2934
3048
              \&Git::SVN::Prompt::username, 2),
2935
3049
          ]);
2936
3050
        my $config = SVN::Core::config_get_config($config_dir);
 
3051
        $RA = undef;
2937
3052
        my $self = SVN::Ra->new(url => $url, auth => $baton,
2938
3053
                              config => $config,
2939
3054
                              pool => SVN::Pool->new,
3054
3169
                        $self->{url} = $full_url;
3055
3170
                        $reparented = 1;
3056
3171
                } else {
 
3172
                        $_[0] = undef;
 
3173
                        $self = undef;
 
3174
                        $RA = undef;
3057
3175
                        $ra = Git::SVN::Ra->new($full_url);
 
3176
                        $ra_invalid = 1;
3058
3177
                }
3059
3178
        }
3060
3179
        $ra ||= $self;
3072
3191
        $editor->{git_commit_ok};
3073
3192
}
3074
3193
 
3075
 
sub gs_fetch_loop_common {
3076
 
        my ($self, $base, $head, $gsv, $globs) = @_;
3077
 
        return if ($base > $head);
3078
 
        my $inc = $_log_window_size;
3079
 
        my ($min, $max) = ($base, $head < $base + $inc ? $head : $base + $inc);
 
3194
sub longest_common_path {
 
3195
        my ($gsv, $globs) = @_;
3080
3196
        my %common;
3081
3197
        my $common_max = scalar @$gsv;
3082
3198
 
3108
3224
                        last;
3109
3225
                }
3110
3226
        }
 
3227
        $longest_path;
 
3228
}
 
3229
 
 
3230
sub gs_fetch_loop_common {
 
3231
        my ($self, $base, $head, $gsv, $globs) = @_;
 
3232
        return if ($base > $head);
 
3233
        my $inc = $_log_window_size;
 
3234
        my ($min, $max) = ($base, $head < $base + $inc ? $head : $base + $inc);
 
3235
        my $longest_path = longest_common_path($gsv, $globs);
 
3236
        my $ra_url = $self->{url};
3111
3237
        while (1) {
3112
3238
                my %revs;
3113
3239
                my $err;
3169
3295
                                        "$g->{t}-maxRev";
3170
3296
                                Git::SVN::tmp_config($k, $r);
3171
3297
                        }
 
3298
                        if ($ra_invalid) {
 
3299
                                $_[0] = undef;
 
3300
                                $self = undef;
 
3301
                                $RA = undef;
 
3302
                                $self = Git::SVN::Ra->new($ra_url);
 
3303
                                $ra_invalid = undef;
 
3304
                        }
3172
3305
                }
3173
3306
                # pre-fill the .rev_db since it'll eventually get filled in
3174
3307
                # with '0' x40 if something new gets committed
3387
3520
sub git_svn_log_cmd {
3388
3521
        my ($r_min, $r_max, @args) = @_;
3389
3522
        my $head = 'HEAD';
 
3523
        my (@files, @log_opts);
3390
3524
        foreach my $x (@args) {
3391
 
                last if $x eq '--';
3392
 
                next unless ::verify_ref("$x^0");
3393
 
                $head = $x;
3394
 
                last;
 
3525
                if ($x eq '--' || @files) {
 
3526
                        push @files, $x;
 
3527
                } else {
 
3528
                        if (::verify_ref("$x^0")) {
 
3529
                                $head = $x;
 
3530
                        } else {
 
3531
                                push @log_opts, $x;
 
3532
                        }
 
3533
                }
3395
3534
        }
3396
3535
 
3397
3536
        my ($url, $rev, $uuid, $gs) = ::working_head_info($head);
3401
3540
        push @cmd, '-r' unless $non_recursive;
3402
3541
        push @cmd, qw/--raw --name-status/ if $verbose;
3403
3542
        push @cmd, '--color' if log_use_color();
3404
 
        return @cmd unless defined $r_max;
3405
 
        if ($r_max == $r_min) {
 
3543
        push @cmd, @log_opts;
 
3544
        if (defined $r_max && $r_max == $r_min) {
3406
3545
                push @cmd, '--max-count=1';
3407
3546
                if (my $c = $gs->rev_db_get($r_max)) {
3408
3547
                        push @cmd, $c;
3409
3548
                }
3410
 
        } else {
 
3549
        } elsif (defined $r_max) {
3411
3550
                my ($c_min, $c_max);
3412
3551
                $c_max = $gs->rev_db_get($r_max);
3413
3552
                $c_min = $gs->rev_db_get($r_min);
3423
3562
                        push @cmd, $c_min;
3424
3563
                }
3425
3564
        }
3426
 
        return @cmd;
 
3565
        return (@cmd, @files);
3427
3566
}
3428
3567
 
3429
3568
# adapted from pager.c
3437
3576
}
3438
3577
 
3439
3578
sub run_pager {
3440
 
        return unless -t *STDOUT;
 
3579
        return unless -t *STDOUT && defined $pager;
3441
3580
        pipe my $rfd, my $wfd or return;
3442
3581
        defined(my $pid = fork) or ::fatal "Can't fork: $!\n";
3443
3582
        if (!$pid) {
3588
3727
        }
3589
3728
 
3590
3729
        config_pager();
3591
 
        @args = (git_svn_log_cmd($r_min, $r_max, @args), @args);
 
3730
        @args = git_svn_log_cmd($r_min, $r_max, @args);
3592
3731
        my $log = command_output_pipe(@args);
3593
3732
        run_pager();
3594
3733
        my (@k, $c, $d, $stat);