Merge branch 'svn-wt' of git://bogomips.org/git-svn

* 'svn-wt' of git://bogomips.org/git-svn:
  git-svn: "git worktree" awareness
  git-svn: reduce scope of input record separator change
This commit is contained in:
Junio C Hamano 2016-10-27 15:03:35 -07:00
commit 251641b771
6 changed files with 69 additions and 48 deletions

View file

@ -44,6 +44,7 @@
command_close_pipe
command_bidi_pipe
command_close_bidi_pipe
get_record
);
BEGIN {
@ -1699,7 +1700,7 @@ sub cmd_gc {
"files will not be compressed.\n";
}
File::Find::find({ wanted => \&gc_directory, no_chdir => 1},
"$ENV{GIT_DIR}/svn");
Git::SVN::svn_dir());
}
########################### utility functions #########################
@ -1733,7 +1734,7 @@ sub post_fetch_checkout {
return unless verify_ref('HEAD^0');
return if $ENV{GIT_DIR} !~ m#^(?:.*/)?\.git$#;
my $index = $ENV{GIT_INDEX_FILE} || "$ENV{GIT_DIR}/index";
my $index = command_oneline(qw(rev-parse --git-path index));
return if -f $index;
return if command_oneline(qw/rev-parse --is-inside-work-tree/) eq 'false';
@ -1835,8 +1836,9 @@ sub get_tree_from_treeish {
sub get_commit_entry {
my ($treeish) = shift;
my %log_entry = ( log => '', tree => get_tree_from_treeish($treeish) );
my $commit_editmsg = "$ENV{GIT_DIR}/COMMIT_EDITMSG";
my $commit_msg = "$ENV{GIT_DIR}/COMMIT_MSG";
my @git_path = qw(rev-parse --git-path);
my $commit_editmsg = command_oneline(@git_path, 'COMMIT_EDITMSG');
my $commit_msg = command_oneline(@git_path, 'COMMIT_MSG');
open my $log_fh, '>', $commit_editmsg or croak $!;
my $type = command_oneline(qw/cat-file -t/, $treeish);
@ -1880,10 +1882,9 @@ sub get_commit_entry {
{
require Encode;
# SVN requires messages to be UTF-8 when entering the repo
local $/;
open $log_fh, '<', $commit_msg or croak $!;
binmode $log_fh;
chomp($log_entry{log} = <$log_fh>);
chomp($log_entry{log} = get_record($log_fh, undef));
my $enc = Git::config('i18n.commitencoding') || 'UTF-8';
my $msg = $log_entry{log};

View file

@ -59,7 +59,7 @@ =head1 SYNOPSIS
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 )

View file

@ -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";
@ -1671,7 +1676,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 +1717,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 +2451,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 +2467,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

View file

@ -7,7 +7,9 @@ package Git::SVN::Editor;
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};

View file

@ -9,7 +9,8 @@ package Git::SVN::Fetcher;
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;

View file

@ -44,7 +44,9 @@ package Git::SVN::Migration;
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: