This change allows multiple branch and tag patterns to be specified in .git/config for git-svn projects. This is useful for fetching several different parts out of the namespace of an svn repository. Additionally, a new repeatable directive called "skip" has been added to specify a specific tag or branch to ignore. Signed-off-by: Michael W. Olson <mwolson@xxxxxxx> --- I've been using this patch regularly for over a year on a very large svn repository. This patch is known to work on git 1.6.3.3 specifically. Once I get a few responses about whether or not it is useful, I'll rebase it against the git.git master branch. Some further documentation (perhaps just a relevant example or two) would also need to be added to the git-svn manpage. Here is an example ~/.git/config file which works with these changes. The example upstream svn repository has branches in tags in 2 different namespaces. Originally all tags/branches were directly under /root/mod/branches and /root/mod/tags. Later on, they created new branches and tags in subdirectories such as /root/mod/branches/myorg/bugs/BUGID. This config file forces old-style branches and tags into the "old/" namespace in git, and puts new-style branches and tags into (for example) "myorg/bugs/BUGID". The "skip" directives prevent the first level of the new namespace ("myorg", in particular) from being replicated underneath "old/" in git, which is for cosmetic purposes. [core] repositoryformatversion = 0 filemode = true bare = false logallrefupdates = true [svn-remote "svn"] url = https://svn.my.org/svn/root fetch = mod/trunk:refs/remotes/trunk branches = mod/branches/*:refs/remotes/old/* skip = branches:old/myorg tags = mod/tags/*:refs/remotes/tags/old/* skip = tags:old/myorg branches = mod/branches/myorg/bugs/*:refs/remotes/myorg/bugs/* tags = mod/tags/myorg/bugs/*:refs/remotes/tags/myorg/bugs/* branches = mod/branches/myorg/projects/*:refs/remotes/myorg/projects/* tags = mod/tags/myorg/projects/*:refs/remotes/tags/myorg/projects/* branches = mod/branches/myorg/releases/*:refs/remotes/myorg/releases/* tags = mod/tags/myorg/releases/*:refs/remotes/tags/myorg/releases/* git-svn.perl | 25 ++++++++++++++++++++----- 1 files changed, 20 insertions(+), 5 deletions(-) diff --git a/git-svn.perl b/git-svn.perl index ef1d30d..f7ec70c 100755 --- a/git-svn.perl +++ b/git-svn.perl @@ -1548,7 +1548,7 @@ sub fetch_all { # read the max revs for wildcard expansion (branches/*, tags/*) foreach my $t (qw/branches tags/) { defined $remote->{$t} or next; - push @globs, $remote->{$t}; + push @globs, @{$remote->{$t}}; my $max_rev = eval { tmp_config(qw/--int --get/, "svn-remote.$repo_id.${t}-maxRev") }; if (defined $max_rev && ($max_rev < $base)) { @@ -1592,14 +1592,17 @@ sub read_all_remotes { $r->{$1}->{svm} = {}; } elsif (m!^(.+)\.url=\s*(.*)\s*$!) { $r->{$1}->{url} = $2; + } elsif (m!^(.+)\.skip=(branches|tags):\s*(.*)\s*$!) { + push @{$r->{$1}->{skip}->{$2}}, $3; } elsif (m!^(.+)\.(branches|tags)= (.*):refs/remotes/(.+)\s*$/!x) { my ($p, $g) = ($3, $4); - my $rs = $r->{$1}->{$2} = { + my $rs = { t => $2, remote => $1, path => Git::SVN::GlobSpec->new($p), ref => Git::SVN::GlobSpec->new($g) }; + push @{$r->{$1}->{$2}}, $rs; if (length($rs->{ref}->{right}) != 0) { die "The '*' glob character must be the last ", "character of '$g'\n"; @@ -1623,6 +1626,14 @@ sub read_all_remotes { } } keys %$r; + for my $rname (keys %$r) { + map { $_->{skip} = $r->{$rname}->{skip}->{branches} } + @{$r->{$rname}->{branches}}; + map { $_->{skip} = + [ map { "tags/$_" } @{$r->{$rname}->{skip}->{tags}} ] } + @{$r->{$rname}->{tags}}; + } + $r; } @@ -1744,8 +1755,9 @@ sub find_by_url { # repos_root and, path are optional my $fetch = $remotes->{$repo_id}->{fetch} || {}; foreach (qw/branches tags/) { - resolve_local_globs($u, $fetch, - $remotes->{$repo_id}->{$_}); + for my $p (@{$remotes->{$repo_id}->{$_}}) { + resolve_local_globs($u, $fetch, $p); + } } my $p = $path; my $rwr = rewrite_root({repo_id => $repo_id}); @@ -4586,12 +4598,15 @@ sub match_globs { next unless /$g->{path}->{regex}/; my $p = $1; my $pathname = $g->{path}->full_path($p); + my $refname = $g->{ref}->full_path($p); + next if $g->{skip} && grep { $refname eq $_ } + @{$g->{skip}}; next if $exists->{$pathname}; next if ($self->check_path($pathname, $r) != $SVN::Node::dir); $exists->{$pathname} = Git::SVN->init( $self->{url}, $pathname, undef, - $g->{ref}->full_path($p), 1); + $refname, 1); } my $c = ''; foreach (split m#/#, $g->{path}->{left}) { -- 1.6.3.3 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html