Browse Source

git-svn: prepare multi-init for wildcard support

Update the tests since we no longer write so many things to the
config.

Signed-off-by: Eric Wong <normalperson@yhbt.net>
maint
Eric Wong 18 years ago
parent
commit
4bb9ed0466
  1. 124
      git-svn.perl
  2. 20
      t/t9107-git-svn-migrate.sh

124
git-svn.perl

@ -367,9 +367,10 @@ sub cmd_multi_init { @@ -367,9 +367,10 @@ sub cmd_multi_init {
sub cmd_multi_fetch {
my $remotes = Git::SVN::read_all_remotes();
foreach my $repo_id (sort keys %$remotes) {
my $url = $remotes->{$repo_id}->{url} or next;
my $fetch = $remotes->{$repo_id}->{fetch} or next;
Git::SVN::fetch_all($repo_id, $url, $fetch);
if ($remotes->{$repo_id}->{url} &&
$remotes->{$repo_id}->{fetch}) {
Git::SVN::fetch_all($repo_id, $remotes);
}
}
}

@ -479,9 +480,12 @@ sub complete_url_ls_init { @@ -479,9 +480,12 @@ sub complete_url_ls_init {
# don't try to init already existing refs
unless ($gs) {
print "init $url/$path => $ref\n";
$gs = Git::SVN->init($url, $path, undef, $ref);
$gs = Git::SVN->init($url, $path, undef, $ref, 1);
}
if ($gs) {
$remote_id = $gs->{repo_id};
last;
}
$remote_id ||= $gs->{repo_id} if $gs;
}
if (defined $remote_id) {
$remote_path = "$ra->{svn_path}/$repo_path/*";
@ -489,7 +493,7 @@ sub complete_url_ls_init { @@ -489,7 +493,7 @@ sub complete_url_ls_init {
$remote_path =~ s#^/##g;
my ($n) = ($switch =~ /^--(\w+)/);
command_noisy('config', "svn-remote.$remote_id.$n",
$remote_path);
"$remote_path:refs/remotes/$pfx*");
}
}

@ -660,9 +664,48 @@ BEGIN { @@ -660,9 +664,48 @@ BEGIN {
my %LOCKFILES;
END { unlink keys %LOCKFILES if %LOCKFILES }

sub resolve_local_globs {
my ($url, $fetch, $glob_spec) = @_;
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}$#;
my $p = $1;
my $pathname = $path->full_path($p);
my $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";
}
my $u = (::cmt_metadata("refs/remotes/$refname"))[0];
$u =~ s!^\Q$url\E/?!! or die
"refs/remotes/$refname: '$url' not found in '$u'\n";
if ($pathname ne $u) {
warn "W: Refspec glob conflict ",
"(ref: refs/remotes/$refname):\n",
"expected path: $pathname\n",
" real path: $u\n",
"Continuing ahead with $u\n";
next;
}
} else {
warn "Globbed ($path->{glob}:$ref->{glob}): ",
"$pathname == $refname\n";
$fetch->{$pathname} = $refname;
}
}
}

sub fetch_all {
my ($repo_id, $url, $fetch) = @_;
my ($repo_id, $remotes) = @_;
my $fetch = $remotes->{$repo_id}->{fetch};
my $url = $remotes->{$repo_id}->{url};
my @gs;
resolve_local_globs($url, $fetch, $remotes->{$repo_id}->{branches});
resolve_local_globs($url, $fetch, $remotes->{$repo_id}->{tags});
my $ra = Git::SVN::Ra->new($url);
my $head = $ra->get_latest_revnum;
my $base = $head;
@ -685,6 +728,16 @@ sub read_all_remotes { @@ -685,6 +728,16 @@ sub read_all_remotes {
$r->{$1}->{fetch}->{$2} = $3;
} elsif (m!^(.+)\.url=\s*(.*)\s*$!) {
$r->{$1}->{url} = $2;
} elsif (m!^(.+)\.(branches|tags)=
(.*):refs/remotes/(.+)\s*$/!x) {
my ($p, $g) = ($3, $4);
my $rs = $r->{$1}->{$2} = {
path => Git::SVN::GlobSpec->new($p),
ref => Git::SVN::GlobSpec->new($g) };
if (length($rs->{ref}->{right}) != 0) {
die "The '*' glob character must be the last ",
"character of '$g'\n";
}
}
}
$r;
@ -3072,10 +3125,67 @@ sub DESTROY { @@ -3072,10 +3125,67 @@ sub DESTROY {
command_close_pipe($self->{gui}, $self->{ctx});
}

package Git::SVN::GlobSpec;
use strict;
use warnings;

sub new {
my ($class, $glob) = @_;
warn "glob: $glob\n";
my $re = $glob;
$re =~ s!/+$!!g; # no need for trailing slashes
my $nr = ($re =~ s!^(.*/?)\*(/?.*)$!\(\[^/\]+\)!g);
my ($left, $right) = ($1, $2);
if ($nr > 1) {
warn "Only one '*' wildcard expansion ",
"is supported (got $nr): '$glob'\n";
} elsif ($nr == 0) {
warn "One '*' is needed for glob: '$glob'\n";
}
$re = quotemeta($left) . $re . quotemeta($right);
$left =~ s!/+$!!g;
$right =~ s!^/+!!g;
bless { left => $left, right => $right,
regex => qr/$re/, glob => $glob }, $class;
}

sub full_path {
my ($self, $path) = @_;
return (length $self->{left} ? "$self->{left}/" : '') .
$path . (length $self->{right} ? "/$self->{right}" : '');
}

__END__

Data structures:


$remotes = { # returned by read_all_remotes()
'svn' => {
# svn-remote.svn.url=https://svn.musicpd.org
url => 'https://svn.musicpd.org',
# svn-remote.svn.fetch=mpd/trunk:trunk
fetch => {
'mpd/trunk' => 'trunk',
},
# svn-remote.svn.tags=mpd/tags/*:tags/*
tags => {
path => {
left => 'mpd/tags',
right => '',
regex => qr!mpd/tags/([^/]+)$!,
glob => 'tags/*',
},
ref => {
left => 'tags',
right => '',
regex => qr!tags/([^/]+)$!,
glob => 'tags/*',
},
}
}
};

$log_entry hashref as returned by libsvn_log_entry()
{
log => 'whitespace-formatted log entry

20
t/t9107-git-svn-migrate.sh

@ -6,7 +6,7 @@ test_description='git-svn metadata migrations from previous versions' @@ -6,7 +6,7 @@ test_description='git-svn metadata migrations from previous versions'
test_expect_success 'setup old-looking metadata' "
cp $GIT_DIR/config $GIT_DIR/config-old-git-svn &&
mkdir import &&
cd import
cd import &&
for i in trunk branches/a branches/b \
tags/0.1 tags/0.2 tags/0.3; do
mkdir -p \$i && \
@ -43,11 +43,19 @@ test_expect_success 'initialize a multi-repository repo' " @@ -43,11 +43,19 @@ test_expect_success 'initialize a multi-repository repo' "
git-svn multi-init $svnrepo -T trunk -t tags -b branches &&
git-repo-config --get-all svn-remote.svn.fetch > fetch.out &&
grep '^trunk:refs/remotes/trunk$' fetch.out &&
grep '^branches/a:refs/remotes/a$' fetch.out &&
grep '^branches/b:refs/remotes/b$' fetch.out &&
grep '^tags/0\.1:refs/remotes/tags/0\.1$' fetch.out &&
grep '^tags/0\.2:refs/remotes/tags/0\.2$' fetch.out &&
grep '^tags/0\.3:refs/remotes/tags/0\.3$' fetch.out
test -n \"\`git-config --get svn-remote.svn.branches \
'^branches/\*:refs/remotes/\*$'\`\" &&
test -n \"\`git-config --get svn-remote.svn.tags \
'^tags/\*:refs/remotes/tags/\*$'\`\" &&
git config --unset svn-remote.svn.branches \
'^branches/\*:refs/remotes/\*$' &&
git config --unset svn-remote.svn.tags \
'^tags/\*:refs/remotes/tags/\*$' &&
git-config --add svn-remote.svn.fetch 'branches/a:refs/remotes/a' &&
git-config --add svn-remote.svn.fetch 'branches/b:refs/remotes/b' &&
for i in tags/0.1 tags/0.2 tags/0.3; do
git-config --add svn-remote.svn.fetch \
\$i:refs/remotes/\$i || exit 1; done
"

# refs should all be different, but the trees should all be the same:

Loading…
Cancel
Save