diff options
author | Eric Wong <normalperson@yhbt.net> | 2007-02-03 13:29:17 -0800 |
---|---|---|
committer | Eric Wong <normalperson@yhbt.net> | 2007-02-23 00:57:11 -0800 |
commit | 4bb9ed0466e9ca6b72b3d9c454a743aea862b1f4 (patch) | |
tree | 11bd52283e4152c1035484eb6aa85bfbc6f4dc90 /git-svn.perl | |
parent | 9fa00b655cfd67bf344668a0d913f90ec9a8141d (diff) | |
download | git-4bb9ed0466e9ca6b72b3d9c454a743aea862b1f4.tar.gz |
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>
Diffstat (limited to 'git-svn.perl')
-rwxr-xr-x | git-svn.perl | 124 |
1 files changed, 117 insertions, 7 deletions
diff --git a/git-svn.perl b/git-svn.perl index 66b4c20fd9..6874eabffa 100755 --- a/git-svn.perl +++ b/git-svn.perl @@ -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 { # 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 { $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 { 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 { $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 { 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 |