зеркало из https://github.com/microsoft/git.git
svn: allow branches outside of refs/remotes
It may be convenient for some users to store svn remote tracking branches outside of the refs/remotes/ heirarchy. To accomplish this feat, this patch includes the entire path to the ref in $r->{'refname'} in &read_all_remotes and tries to change references to this entry so the new value makes sense. [ew: fixed backwards compatibility, long lines] Signed-off-by: Adam Brewster <adambrewster@gmail.com> Signed-off-by: Eric Wong <normalperson@yhbt.net>
This commit is contained in:
Родитель
b186a261b1
Коммит
6f5748e14c
83
git-svn.perl
83
git-svn.perl
|
@ -909,7 +909,7 @@ sub cmd_multi_init {
|
|||
}
|
||||
do_git_init_db();
|
||||
if (defined $_trunk) {
|
||||
my $trunk_ref = $_prefix . 'trunk';
|
||||
my $trunk_ref = 'refs/remotes/' . $_prefix . 'trunk';
|
||||
# try both old-style and new-style lookups:
|
||||
my $gs_trunk = eval { Git::SVN->new($trunk_ref) };
|
||||
unless ($gs_trunk) {
|
||||
|
@ -1654,23 +1654,23 @@ sub resolve_local_globs {
|
|||
return unless defined $glob_spec;
|
||||
my $ref = $glob_spec->{ref};
|
||||
my $path = $glob_spec->{path};
|
||||
foreach (command(qw#for-each-ref --format=%(refname) refs/remotes#)) {
|
||||
next unless m#^refs/remotes/$ref->{regex}$#;
|
||||
foreach (command(qw#for-each-ref --format=%(refname) refs/#)) {
|
||||
next unless m#^$ref->{regex}$#;
|
||||
my $p = $1;
|
||||
my $pathname = desanitize_refname($path->full_path($p));
|
||||
my $refname = desanitize_refname($ref->full_path($p));
|
||||
if (my $existing = $fetch->{$pathname}) {
|
||||
if ($existing ne $refname) {
|
||||
die "Refspec conflict:\n",
|
||||
"existing: refs/remotes/$existing\n",
|
||||
" globbed: refs/remotes/$refname\n";
|
||||
"existing: $existing\n",
|
||||
" globbed: $refname\n";
|
||||
}
|
||||
my $u = (::cmt_metadata("refs/remotes/$refname"))[0];
|
||||
my $u = (::cmt_metadata("$refname"))[0];
|
||||
$u =~ s!^\Q$url\E(/|$)!! or die
|
||||
"refs/remotes/$refname: '$url' not found in '$u'\n";
|
||||
"$refname: '$url' not found in '$u'\n";
|
||||
if ($pathname ne $u) {
|
||||
warn "W: Refspec glob conflict ",
|
||||
"(ref: refs/remotes/$refname):\n",
|
||||
"(ref: $refname):\n",
|
||||
"expected path: $pathname\n",
|
||||
" real path: $u\n",
|
||||
"Continuing ahead with $u\n";
|
||||
|
@ -1748,33 +1748,35 @@ sub read_all_remotes {
|
|||
my $use_svm_props = eval { command_oneline(qw/config --bool
|
||||
svn.useSvmProps/) };
|
||||
$use_svm_props = $use_svm_props eq 'true' if $use_svm_props;
|
||||
my $svn_refspec = qr{\s*/?(.*?)\s*:\s*(.+?)\s*};
|
||||
foreach (grep { s/^svn-remote\.// } command(qw/config -l/)) {
|
||||
if (m!^(.+)\.fetch=\s*(.*)\s*:\s*(.+)\s*$!) {
|
||||
my ($remote, $local_ref, $_remote_ref) = ($1, $2, $3);
|
||||
die("svn-remote.$remote: remote ref '$_remote_ref' "
|
||||
. "must start with 'refs/remotes/'\n")
|
||||
unless $_remote_ref =~ m{^refs/remotes/(.+)};
|
||||
my $remote_ref = $1;
|
||||
$local_ref =~ s{^/}{};
|
||||
if (m!^(.+)\.fetch=$svn_refspec$!) {
|
||||
my ($remote, $local_ref, $remote_ref) = ($1, $2, $3);
|
||||
die("svn-remote.$remote: remote ref '$remote_ref' "
|
||||
. "must start with 'refs/'\n")
|
||||
unless $remote_ref =~ m{^refs/};
|
||||
$r->{$remote}->{fetch}->{$local_ref} = $remote_ref;
|
||||
$r->{$remote}->{svm} = {} if $use_svm_props;
|
||||
} elsif (m!^(.+)\.usesvmprops=\s*(.*)\s*$!) {
|
||||
$r->{$1}->{svm} = {};
|
||||
} elsif (m!^(.+)\.url=\s*(.*)\s*$!) {
|
||||
$r->{$1}->{url} = $2;
|
||||
} elsif (m!^(.+)\.(branches|tags)=
|
||||
(.*):refs/remotes/(.+)\s*$/!x) {
|
||||
my ($p, $g) = ($3, $4);
|
||||
} elsif (m!^(.+)\.(branches|tags)=$svn_refspec$!) {
|
||||
my ($remote, $t, $local_ref, $remote_ref) =
|
||||
($1, $2, $3, $4);
|
||||
die("svn-remote.$remote: remote ref '$remote_ref' ($t) "
|
||||
. "must start with 'refs/'\n")
|
||||
unless $remote_ref =~ m{^refs/};
|
||||
my $rs = {
|
||||
t => $2,
|
||||
remote => $1,
|
||||
path => Git::SVN::GlobSpec->new($p),
|
||||
ref => Git::SVN::GlobSpec->new($g) };
|
||||
t => $t,
|
||||
remote => $remote,
|
||||
path => Git::SVN::GlobSpec->new($local_ref),
|
||||
ref => Git::SVN::GlobSpec->new($remote_ref) };
|
||||
if (length($rs->{ref}->{right}) != 0) {
|
||||
die "The '*' glob character must be the last ",
|
||||
"character of '$g'\n";
|
||||
"character of '$remote_ref'\n";
|
||||
}
|
||||
push @{ $r->{$1}->{$2} }, $rs;
|
||||
push @{ $r->{$remote}->{$t} }, $rs;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1882,9 +1884,9 @@ sub init_remote_config {
|
|||
}
|
||||
}
|
||||
my ($xrepo_id, $xpath) = find_ref($self->refname);
|
||||
if (defined $xpath) {
|
||||
if (!$no_write && defined $xpath) {
|
||||
die "svn-remote.$xrepo_id.fetch already set to track ",
|
||||
"$xpath:refs/remotes/", $self->refname, "\n";
|
||||
"$xpath:", $self->refname, "\n";
|
||||
}
|
||||
unless ($no_write) {
|
||||
command_noisy('config',
|
||||
|
@ -1959,7 +1961,7 @@ sub find_ref {
|
|||
my ($ref_id) = @_;
|
||||
foreach (command(qw/config -l/)) {
|
||||
next unless m!^svn-remote\.(.+)\.fetch=
|
||||
\s*(.*)\s*:\s*refs/remotes/(.+)\s*$!x;
|
||||
\s*/?(.*?)\s*:\s*(.+?)\s*$!x;
|
||||
my ($repo_id, $path, $ref) = ($1, $2, $3);
|
||||
if ($ref eq $ref_id) {
|
||||
$path = '' if ($path =~ m#^\./?#);
|
||||
|
@ -1976,16 +1978,16 @@ sub new {
|
|||
if (!defined $repo_id) {
|
||||
die "Could not find a \"svn-remote.*.fetch\" key ",
|
||||
"in the repository configuration matching: ",
|
||||
"refs/remotes/$ref_id\n";
|
||||
"$ref_id\n";
|
||||
}
|
||||
}
|
||||
my $self = _new($class, $repo_id, $ref_id, $path);
|
||||
if (!defined $self->{path} || !length $self->{path}) {
|
||||
my $fetch = command_oneline('config', '--get',
|
||||
"svn-remote.$repo_id.fetch",
|
||||
":refs/remotes/$ref_id\$") or
|
||||
":$ref_id\$") or
|
||||
die "Failed to read \"svn-remote.$repo_id.fetch\" ",
|
||||
"\":refs/remotes/$ref_id\$\" in config\n";
|
||||
"\":$ref_id\$\" in config\n";
|
||||
($self->{path}, undef) = split(/\s*:\s*/, $fetch);
|
||||
}
|
||||
$self->{url} = command_oneline('config', '--get',
|
||||
|
@ -1996,7 +1998,7 @@ sub new {
|
|||
}
|
||||
|
||||
sub refname {
|
||||
my ($refname) = "refs/remotes/$_[0]->{ref_id}" ;
|
||||
my ($refname) = $_[0]->{ref_id} ;
|
||||
|
||||
# It cannot end with a slash /, we'll throw up on this because
|
||||
# SVN can't have directories with a slash in their name, either:
|
||||
|
@ -3331,12 +3333,23 @@ sub _new {
|
|||
}
|
||||
unless (defined $ref_id && length $ref_id) {
|
||||
$_prefix = '' unless defined($_prefix);
|
||||
$_[2] = $ref_id = $_prefix . $Git::SVN::default_ref_id;
|
||||
$_[2] = $ref_id =
|
||||
"refs/remotes/$_prefix$Git::SVN::default_ref_id";
|
||||
}
|
||||
$_[1] = $repo_id;
|
||||
my $dir = "$ENV{GIT_DIR}/svn/$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
|
||||
if ($ref_id =~ m{^refs/remotes/(.*)}) {
|
||||
my $old_dir = "$ENV{GIT_DIR}/svn/$1";
|
||||
if (-d $old_dir && ! -d $dir) {
|
||||
$dir = $old_dir;
|
||||
}
|
||||
}
|
||||
|
||||
$_[3] = $path = '' unless (defined $path);
|
||||
mkpath(["$ENV{GIT_DIR}/svn"]);
|
||||
mkpath([$dir]);
|
||||
bless {
|
||||
ref_id => $ref_id, dir => $dir, index => "$dir/index",
|
||||
path => $path, config => "$ENV{GIT_DIR}/svn/config",
|
||||
|
@ -5509,7 +5522,7 @@ sub minimize_connections {
|
|||
my $pfx = "svn-remote.$x->{old_repo_id}";
|
||||
|
||||
my $old_fetch = quotemeta("$x->{old_path}:".
|
||||
"refs/remotes/$x->{ref_id}");
|
||||
"$x->{ref_id}");
|
||||
command_noisy(qw/config --unset/,
|
||||
"$pfx.fetch", '^'. $old_fetch . '$');
|
||||
delete $r->{$x->{old_repo_id}}->
|
||||
|
@ -5578,7 +5591,7 @@ sub new {
|
|||
my ($class, $glob) = @_;
|
||||
my $re = $glob;
|
||||
$re =~ s!/+$!!g; # no need for trailing slashes
|
||||
$re =~ m!^([^*]*)(\*(?:/\*)*)([^*]*)$!;
|
||||
$re =~ m!^([^*]*)(\*(?:/\*)*)(.*)$!;
|
||||
my $temp = $re;
|
||||
my ($left, $right) = ($1, $3);
|
||||
$re = $2;
|
||||
|
|
|
@ -14,7 +14,7 @@ if ! test_have_prereq PERL; then
|
|||
fi
|
||||
|
||||
GIT_DIR=$PWD/.git
|
||||
GIT_SVN_DIR=$GIT_DIR/svn/git-svn
|
||||
GIT_SVN_DIR=$GIT_DIR/svn/refs/remotes/git-svn
|
||||
SVN_TREE=$GIT_SVN_DIR/svn-tree
|
||||
|
||||
svn >/dev/null 2>&1
|
||||
|
|
|
@ -172,11 +172,11 @@ test_expect_success "follow-parent is atomic" '
|
|||
git update-ref refs/remotes/flunk@18 refs/remotes/stunk~2 &&
|
||||
git update-ref -d refs/remotes/stunk &&
|
||||
git config --unset svn-remote.svn.fetch stunk &&
|
||||
mkdir -p "$GIT_DIR"/svn/flunk@18 &&
|
||||
rev_map=$(cd "$GIT_DIR"/svn/stunk && ls .rev_map*) &&
|
||||
dd if="$GIT_DIR"/svn/stunk/$rev_map \
|
||||
of="$GIT_DIR"/svn/flunk@18/$rev_map bs=24 count=1 &&
|
||||
rm -rf "$GIT_DIR"/svn/stunk &&
|
||||
mkdir -p "$GIT_DIR"/svn/refs/remotes/flunk@18 &&
|
||||
rev_map=$(cd "$GIT_DIR"/svn/refs/remotes/stunk && ls .rev_map*) &&
|
||||
dd if="$GIT_DIR"/svn/refs/remotes/stunk/$rev_map \
|
||||
of="$GIT_DIR"/svn/refs/remotes/flunk@18/$rev_map bs=24 count=1 &&
|
||||
rm -rf "$GIT_DIR"/svn/refs/remotes/stunk &&
|
||||
git svn init --minimize-url -i flunk "$svnrepo"/flunk &&
|
||||
git svn fetch -i flunk &&
|
||||
git svn init --minimize-url -i stunk "$svnrepo"/stunk &&
|
||||
|
|
|
@ -16,9 +16,7 @@ test_expect_success 'setup old-looking metadata' '
|
|||
cd .. &&
|
||||
git svn init "$svnrepo" &&
|
||||
git svn fetch &&
|
||||
mv "$GIT_DIR"/svn/* "$GIT_DIR"/ &&
|
||||
mv "$GIT_DIR"/svn/.metadata "$GIT_DIR"/ &&
|
||||
rmdir "$GIT_DIR"/svn &&
|
||||
rm -rf "$GIT_DIR"/svn &&
|
||||
git update-ref refs/heads/git-svn-HEAD refs/${remotes_git_svn} &&
|
||||
git update-ref refs/heads/svn-HEAD refs/${remotes_git_svn} &&
|
||||
git update-ref -d refs/${remotes_git_svn} refs/${remotes_git_svn}
|
||||
|
@ -87,7 +85,7 @@ test_expect_success 'migrate --minimize on old inited layout' '
|
|||
rm -rf "$GIT_DIR"/svn &&
|
||||
for i in `cat fetch.out`; do
|
||||
path=`expr $i : "\([^:]*\):.*$"`
|
||||
ref=`expr $i : "[^:]*:refs/remotes/\(.*\)$"`
|
||||
ref=`expr $i : "[^:]*:\(refs/remotes/.*\)$"`
|
||||
if test -z "$ref"; then continue; fi
|
||||
if test -n "$path"; then path="/$path"; fi
|
||||
( mkdir -p "$GIT_DIR"/svn/$ref/info/ &&
|
||||
|
@ -107,16 +105,16 @@ test_expect_success 'migrate --minimize on old inited layout' '
|
|||
|
||||
test_expect_success ".rev_db auto-converted to .rev_map.UUID" '
|
||||
git svn fetch -i trunk &&
|
||||
test -z "$(ls "$GIT_DIR"/svn/trunk/.rev_db.* 2>/dev/null)" &&
|
||||
expect="$(ls "$GIT_DIR"/svn/trunk/.rev_map.*)" &&
|
||||
test -z "$(ls "$GIT_DIR"/svn/refs/remotes/trunk/.rev_db.* 2>/dev/null)" &&
|
||||
expect="$(ls "$GIT_DIR"/svn/refs/remotes/trunk/.rev_map.*)" &&
|
||||
test -n "$expect" &&
|
||||
rev_db="$(echo $expect | sed -e "s,_map,_db,")" &&
|
||||
convert_to_rev_db "$expect" "$rev_db" &&
|
||||
rm -f "$expect" &&
|
||||
test -f "$rev_db" &&
|
||||
git svn fetch -i trunk &&
|
||||
test -z "$(ls "$GIT_DIR"/svn/trunk/.rev_db.* 2>/dev/null)" &&
|
||||
test ! -e "$GIT_DIR"/svn/trunk/.rev_db &&
|
||||
test -z "$(ls "$GIT_DIR"/svn/refs/remotes/trunk/.rev_db.* 2>/dev/null)" &&
|
||||
test ! -e "$GIT_DIR"/svn/refs/remotes/trunk/.rev_db &&
|
||||
test -f "$expect"
|
||||
'
|
||||
|
||||
|
|
|
@ -28,26 +28,26 @@ test_expect_success 'Setup repo' 'git svn init "$svnrepo"'
|
|||
test_expect_success 'Fetch repo' 'git svn fetch'
|
||||
|
||||
test_expect_success 'make backup copy of unhandled.log' '
|
||||
cp .git/svn/git-svn/unhandled.log tmp
|
||||
cp .git/svn/refs/remotes/git-svn/unhandled.log tmp
|
||||
'
|
||||
|
||||
test_expect_success 'create leftover index' '> .git/svn/git-svn/index'
|
||||
test_expect_success 'create leftover index' '> .git/svn/refs/remotes/git-svn/index'
|
||||
|
||||
test_expect_success 'git svn gc runs' 'git svn gc'
|
||||
|
||||
test_expect_success 'git svn index removed' '! test -f .git/svn/git-svn/index'
|
||||
test_expect_success 'git svn index removed' '! test -f .git/svn/refs/remotes/git-svn/index'
|
||||
|
||||
if perl -MCompress::Zlib -e 0 2>/dev/null
|
||||
then
|
||||
test_expect_success 'git svn gc produces a valid gzip file' '
|
||||
gunzip .git/svn/git-svn/unhandled.log.gz
|
||||
gunzip .git/svn/refs/remotes/git-svn/unhandled.log.gz
|
||||
'
|
||||
else
|
||||
say "Perl Compress::Zlib unavailable, skipping gunzip test"
|
||||
fi
|
||||
|
||||
test_expect_success 'git svn gc does not change unhandled.log files' '
|
||||
test_cmp .git/svn/git-svn/unhandled.log tmp/unhandled.log
|
||||
test_cmp .git/svn/refs/remotes/git-svn/unhandled.log tmp/unhandled.log
|
||||
'
|
||||
|
||||
test_done
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
#!/bin/sh
|
||||
#
|
||||
# Copyright (c) 2009 Eric Wong
|
||||
|
||||
test_description='git svn old rev_map preservd'
|
||||
. ./lib-git-svn.sh
|
||||
|
||||
test_expect_success 'setup test repository with old layout' '
|
||||
mkdir i &&
|
||||
(cd i && > a) &&
|
||||
svn_cmd import -m- i "$svnrepo" &&
|
||||
git svn init "$svnrepo" &&
|
||||
git svn fetch &&
|
||||
test -d .git/svn/refs/remotes/git-svn/ &&
|
||||
! test -e .git/svn/git-svn/ &&
|
||||
mv .git/svn/refs/remotes/git-svn .git/svn/ &&
|
||||
rm -r .git/svn/refs
|
||||
'
|
||||
|
||||
test_expect_success 'old layout continues to work' '
|
||||
svn_cmd import -m- i "$svnrepo/b" &&
|
||||
git svn rebase &&
|
||||
echo a >> b/a &&
|
||||
git add b/a &&
|
||||
git commit -m- -a &&
|
||||
git svn dcommit &&
|
||||
! test -d .git/svn/refs/ &&
|
||||
test -e .git/svn/git-svn/
|
||||
'
|
||||
|
||||
test_done
|
Загрузка…
Ссылка в новой задаче