diff options
Diffstat (limited to 'perl')
-rw-r--r-- | perl/Git.pm | 31 | ||||
-rw-r--r-- | perl/Git/SVN.pm | 36 | ||||
-rw-r--r-- | perl/Git/SVN/Editor.pm | 12 | ||||
-rw-r--r-- | perl/Git/SVN/Fetcher.pm | 15 | ||||
-rw-r--r-- | perl/Git/SVN/Migration.pm | 37 |
5 files changed, 82 insertions, 49 deletions
diff --git a/perl/Git.pm b/perl/Git.pm index ce7e4e8da3..b2732822af 100644 --- a/perl/Git.pm +++ b/perl/Git.pm @@ -59,7 +59,7 @@ require Exporter; command_bidi_pipe command_close_bidi_pipe version exec_path html_path hash_object git_cmd_try remote_refs prompt - get_tz_offset + get_tz_offset get_record credential credential_read credential_write temp_acquire temp_is_locked temp_release temp_reset temp_path); @@ -538,6 +538,20 @@ sub get_tz_offset { return sprintf("%s%02d%02d", $sign, (gmtime(abs($t - $gm)))[2,1]); } +=item get_record ( FILEHANDLE, INPUT_RECORD_SEPARATOR ) + +Read one record from FILEHANDLE delimited by INPUT_RECORD_SEPARATOR, +removing any trailing INPUT_RECORD_SEPARATOR. + +=cut + +sub get_record { + my ($fh, $rs) = @_; + local $/ = $rs; + my $rec = <$fh>; + chomp $rec if defined $rs; + $rec; +} =item prompt ( PROMPT , ISPASSWORD ) @@ -871,6 +885,8 @@ Return an array of mailboxes extracted from a string. =cut +# Very close to Mail::Address's parser, but we still have minor +# differences in some cases (see t9000 for examples). sub parse_mailboxes { my $re_comment = qr/\((?:[^)]*)\)/; my $re_quote = qr/"(?:[^\"\\]|\\.)*"/; @@ -879,6 +895,7 @@ sub parse_mailboxes { # divide the string in tokens of the above form my $re_token = qr/(?:$re_quote|$re_word|$re_comment|\S)/; my @tokens = map { $_ =~ /\s*($re_token)\s*/g } @_; + my $end_of_addr_seen = 0; # add a delimiter to simplify treatment for the last mailbox push @tokens, ","; @@ -888,10 +905,10 @@ sub parse_mailboxes { if ($token =~ /^[,;]$/) { # if buffer still contains undeterminated strings # append it at the end of @address or @phrase - if (@address) { - push @address, @buffer; - } else { + if ($end_of_addr_seen) { push @phrase, @buffer; + } else { + push @address, @buffer; } my $str_phrase = join ' ', @phrase; @@ -915,16 +932,16 @@ sub parse_mailboxes { push @addr_list, $str_mailbox if ($str_mailbox); @phrase = @address = @comment = @buffer = (); + $end_of_addr_seen = 0; } elsif ($token =~ /^\(/) { push @comment, $token; } elsif ($token eq "<") { push @phrase, (splice @address), (splice @buffer); } elsif ($token eq ">") { + $end_of_addr_seen = 1; push @address, (splice @buffer); - } elsif ($token eq "@") { + } elsif ($token eq "@" && !$end_of_addr_seen) { push @address, (splice @buffer), "@"; - } elsif ($token eq ".") { - push @address, (splice @buffer), "."; } else { push @buffer, $token; } diff --git a/perl/Git/SVN.pm b/perl/Git/SVN.pm index 018beb85a0..711d2687a3 100644 --- a/perl/Git/SVN.pm +++ b/perl/Git/SVN.pm @@ -807,10 +807,15 @@ sub get_fetch_range { (++$min, $max); } +sub svn_dir { + command_oneline(qw(rev-parse --git-path svn)); +} + sub tmp_config { my (@args) = @_; - my $old_def_config = "$ENV{GIT_DIR}/svn/config"; - my $config = "$ENV{GIT_DIR}/svn/.metadata"; + my $svn_dir = svn_dir(); + my $old_def_config = "$svn_dir/config"; + my $config = "$svn_dir/.metadata"; if (! -f $config && -f $old_def_config) { rename $old_def_config, $config or die "Failed rename $old_def_config => $config: $!\n"; @@ -1658,7 +1663,17 @@ sub tie_for_persistent_memoization { if ($memo_backend > 0) { tie %$hash => 'Git::SVN::Memoize::YAML', "$path.yaml"; } else { - tie %$hash => 'Memoize::Storable', "$path.db", 'nstore'; + # first verify that any existing file can actually be loaded + # (it may have been saved by an incompatible version) + my $db = "$path.db"; + if (-e $db) { + use Storable qw(retrieve); + + if (!eval { retrieve($db); 1 }) { + unlink $db or die "unlink $db failed: $!"; + } + } + tie %$hash => 'Memoize::Storable', $db, 'nstore'; } } @@ -1671,7 +1686,7 @@ sub tie_for_persistent_memoization { return if $memoized; $memoized = 1; - my $cache_path = "$ENV{GIT_DIR}/svn/.caches/"; + my $cache_path = svn_dir() . '/.caches/'; mkpath([$cache_path]) unless -d $cache_path; my %lookup_svn_merge_cache; @@ -1712,7 +1727,7 @@ sub tie_for_persistent_memoization { sub clear_memoized_mergeinfo_caches { die "Only call this method in non-memoized context" if ($memoized); - my $cache_path = "$ENV{GIT_DIR}/svn/.caches/"; + my $cache_path = svn_dir() . '/.caches/'; return unless -d $cache_path; for my $cache_file (("$cache_path/lookup_svn_merge", @@ -2446,12 +2461,13 @@ sub _new { "refs/remotes/$prefix$default_ref_id"; } $_[1] = $repo_id; - my $dir = "$ENV{GIT_DIR}/svn/$ref_id"; + my $svn_dir = svn_dir(); + my $dir = "$svn_dir/$ref_id"; - # Older repos imported by us used $GIT_DIR/svn/foo instead of - # $GIT_DIR/svn/refs/remotes/foo when tracking refs/remotes/foo + # Older repos imported by us used $svn_dir/foo instead of + # $svn_dir/refs/remotes/foo when tracking refs/remotes/foo if ($ref_id =~ m{^refs/remotes/(.+)}) { - my $old_dir = "$ENV{GIT_DIR}/svn/$1"; + my $old_dir = "$svn_dir/$1"; if (-d $old_dir && ! -d $dir) { $dir = $old_dir; } @@ -2461,7 +2477,7 @@ sub _new { mkpath([$dir]); my $obj = bless { ref_id => $ref_id, dir => $dir, index => "$dir/index", - config => "$ENV{GIT_DIR}/svn/config", + config => "$svn_dir/config", map_root => "$dir/.rev_map", repo_id => $repo_id }, $class; # Ensure it gets canonicalized diff --git a/perl/Git/SVN/Editor.pm b/perl/Git/SVN/Editor.pm index 4c4199afec..0df16ed726 100644 --- a/perl/Git/SVN/Editor.pm +++ b/perl/Git/SVN/Editor.pm @@ -7,7 +7,9 @@ use SVN::Delta; use Carp qw/croak/; use Git qw/command command_oneline command_noisy command_output_pipe command_input_pipe command_close_pipe - command_bidi_pipe command_close_bidi_pipe/; + command_bidi_pipe command_close_bidi_pipe + get_record/; + BEGIN { @ISA = qw(SVN::Delta::Editor); } @@ -57,11 +59,9 @@ sub generate_diff { push @diff_tree, "-l$_rename_limit" if defined $_rename_limit; push @diff_tree, $tree_a, $tree_b; my ($diff_fh, $ctx) = command_output_pipe(@diff_tree); - local $/ = "\0"; my $state = 'meta'; my @mods; - while (<$diff_fh>) { - chomp $_; # this gets rid of the trailing "\0" + while (defined($_ = get_record($diff_fh, "\0"))) { if ($state eq 'meta' && /^:(\d{6})\s(\d{6})\s ($::sha1)\s($::sha1)\s ([MTCRAD])\d*$/xo) { @@ -173,9 +173,7 @@ sub rmdirs { my ($fh, $ctx) = command_output_pipe(qw/ls-tree --name-only -r -z/, $self->{tree_b}); - local $/ = "\0"; - while (<$fh>) { - chomp; + while (defined($_ = get_record($fh, "\0"))) { my @dn = split m#/#, $_; while (pop @dn) { delete $rm->{join '/', @dn}; diff --git a/perl/Git/SVN/Fetcher.pm b/perl/Git/SVN/Fetcher.pm index d8c21ad915..64e900a0e9 100644 --- a/perl/Git/SVN/Fetcher.pm +++ b/perl/Git/SVN/Fetcher.pm @@ -9,7 +9,8 @@ use Carp qw/croak/; use File::Basename qw/dirname/; use Git qw/command command_oneline command_noisy command_output_pipe command_input_pipe command_close_pipe - command_bidi_pipe command_close_bidi_pipe/; + command_bidi_pipe command_close_bidi_pipe + get_record/; BEGIN { @ISA = qw(SVN::Delta::Editor); } @@ -86,11 +87,9 @@ sub _mark_empty_symlinks { my $printed_warning; chomp(my $empty_blob = `git hash-object -t blob --stdin < /dev/null`); my ($ls, $ctx) = command_output_pipe(qw/ls-tree -r -z/, $cmt); - local $/ = "\0"; my $pfx = defined($switch_path) ? $switch_path : $git_svn->path; $pfx .= '/' if length($pfx); - while (<$ls>) { - chomp; + while (defined($_ = get_record($ls, "\0"))) { s/\A100644 blob $empty_blob\t//o or next; unless ($printed_warning) { print STDERR "Scanning for empty symlinks, ", @@ -179,9 +178,7 @@ sub delete_entry { my ($ls, $ctx) = command_output_pipe(qw/ls-tree -r --name-only -z/, $tree); - local $/ = "\0"; - while (<$ls>) { - chomp; + while (defined($_ = get_record($ls, "\0"))) { my $rmpath = "$gpath/$_"; $self->{gii}->remove($rmpath); print "\tD\t$rmpath\n" unless $::_q; @@ -247,9 +244,7 @@ sub add_directory { my ($ls, $ctx) = command_output_pipe(qw/ls-tree -r --name-only -z/, $self->{c}); - local $/ = "\0"; - while (<$ls>) { - chomp; + while (defined($_ = get_record($ls, "\0"))) { $self->{gii}->remove($_); print "\tD\t$_\n" unless $::_q; push @deleted_gpath, $gpath; diff --git a/perl/Git/SVN/Migration.pm b/perl/Git/SVN/Migration.pm index cf6ffa7581..dc90f6a621 100644 --- a/perl/Git/SVN/Migration.pm +++ b/perl/Git/SVN/Migration.pm @@ -44,7 +44,9 @@ use Git qw( command_noisy command_output_pipe command_close_pipe + command_oneline ); +use Git::SVN; sub migrate_from_v0 { my $git_dir = $ENV{GIT_DIR}; @@ -55,7 +57,9 @@ sub migrate_from_v0 { chomp; my ($id, $orig_ref) = ($_, $_); next unless $id =~ s#^refs/heads/(.+)-HEAD$#$1#; - next unless -f "$git_dir/$id/info/url"; + my $info_url = command_oneline(qw(rev-parse --git-path), + "$id/info/url"); + next unless -f $info_url; my $new_ref = "refs/remotes/$id"; if (::verify_ref("$new_ref^0")) { print STDERR "W: $orig_ref is probably an old ", @@ -82,7 +86,7 @@ sub migrate_from_v1 { my $git_dir = $ENV{GIT_DIR}; my $migrated = 0; return $migrated unless -d $git_dir; - my $svn_dir = "$git_dir/svn"; + my $svn_dir = Git::SVN::svn_dir(); # just in case somebody used 'svn' as their $id at some point... return $migrated if -d $svn_dir && ! -f "$svn_dir/info/url"; @@ -97,27 +101,28 @@ sub migrate_from_v1 { my $x = $_; next unless $x =~ s#^refs/remotes/##; chomp $x; - next unless -f "$git_dir/$x/info/url"; - my $u = eval { ::file_to_s("$git_dir/$x/info/url") }; + my $info_url = command_oneline(qw(rev-parse --git-path), + "$x/info/url"); + next unless -f $info_url; + my $u = eval { ::file_to_s($info_url) }; next unless $u; - my $dn = dirname("$git_dir/svn/$x"); + my $dn = dirname("$svn_dir/$x"); mkpath([$dn]) unless -d $dn; if ($x eq 'svn') { # they used 'svn' as GIT_SVN_ID: - mkpath(["$git_dir/svn/svn"]); + mkpath(["$svn_dir/svn"]); print STDERR " - $git_dir/$x/info => ", - "$git_dir/svn/$x/info\n"; - rename "$git_dir/$x/info", "$git_dir/svn/$x/info" or + "$svn_dir/$x/info\n"; + rename "$git_dir/$x/info", "$svn_dir/$x/info" or croak "$!: $x"; # don't worry too much about these, they probably # don't exist with repos this old (save for index, # and we can easily regenerate that) foreach my $f (qw/unhandled.log index .rev_db/) { - rename "$git_dir/$x/$f", "$git_dir/svn/$x/$f"; + rename "$git_dir/$x/$f", "$svn_dir/$x/$f"; } } else { - print STDERR " - $git_dir/$x => $git_dir/svn/$x\n"; - rename "$git_dir/$x", "$git_dir/svn/$x" or - croak "$!: $x"; + print STDERR " - $git_dir/$x => $svn_dir/$x\n"; + rename "$git_dir/$x", "$svn_dir/$x" or croak "$!: $x"; } $migrated++; } @@ -139,9 +144,10 @@ sub read_old_urls { push @dir, $_; } } + my $svn_dir = Git::SVN::svn_dir(); foreach (@dir) { my $x = $_; - $x =~ s!^\Q$ENV{GIT_DIR}\E/svn/!!o; + $x =~ s!^\Q$svn_dir\E/!!o; read_old_urls($l_map, $x, $_); } } @@ -150,7 +156,7 @@ sub migrate_from_v2 { my @cfg = command(qw/config -l/); return if grep /^svn-remote\..+\.url=/, @cfg; my %l_map; - read_old_urls(\%l_map, '', "$ENV{GIT_DIR}/svn"); + read_old_urls(\%l_map, '', Git::SVN::svn_dir()); my $migrated = 0; require Git::SVN; @@ -239,7 +245,8 @@ sub minimize_connections { } } if (@emptied) { - my $file = $ENV{GIT_CONFIG} || "$ENV{GIT_DIR}/config"; + my $file = $ENV{GIT_CONFIG} || + command_oneline(qw(rev-parse --git-path config)); print STDERR <<EOF; The following [svn-remote] sections in your config file ($file) are empty and can be safely removed: |