git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 2/2] git-svn: Allow deep branch names by supporting multi-globs
@ 2008-08-06 19:58 Marcus Griep
  2008-08-07  9:00 ` Eric Wong
  0 siblings, 1 reply; 14+ messages in thread
From: Marcus Griep @ 2008-08-06 19:58 UTC (permalink / raw)
  To: Git Mailing List; +Cc: Eric Wong

From 3b95061c8d19b2285cdbf94001f3b718c8264c32 Mon Sep 17 00:00:00 2001
From: Marcus Griep <marcus@griep.us>
Date: Tue, 5 Aug 2008 15:13:20 -0400
Subject: [PATCH 2/2] git-svn: Allow deep branch names by supporting multi-globs

Some repositories use a deep branching strategy, such as:
branches/1.0/1.0.rc1
branches/1.0/1.0.rc2
branches/1.0/1.0.rtm
branches/1.0/1.0.gold

Only allowing a single glob stiffles this.

This change allows for a single glob 'set' to accept this deep branching
strategy.

The ref glob depth must match the branch glob depth.  When using the -b or -t
options for init or clone, this is automatically done.

For example, using the above branches:
  svn-remote.svn.branches = branches/*/*:refs/remote/*/*
gives the following branch names:
  1.0/1.0.rc1
  1.0/1.0.rc2
  1.0/1.0.rtm
  1.0/1.0.gold

Signed-off-by: Marcus Griep <marcus@griep.us>
---
 git-svn.perl                               |   53 +++++++---
 t/t9108-git-svn-glob.sh                    |    9 +-
 t/t9108-git-svn-multi-glob.sh              |  155 ++++++++++++++++++++++++++++
 t/t9125-git-svn-multi-glob-branch-names.sh |   40 +++++++
 4 files changed, 238 insertions(+), 19 deletions(-)
 create mode 100755 t/t9108-git-svn-multi-glob.sh
 create mode 100755 t/t9125-git-svn-multi-glob-branch-names.sh

diff --git a/git-svn.perl b/git-svn.perl
index 95d11c2..dc80c56 100755
--- a/git-svn.perl
+++ b/git-svn.perl
@@ -981,7 +981,7 @@ sub complete_url_ls_init {
                die "--prefix='$pfx' must have a trailing slash '/'\n";
        }
        command_noisy('config', "svn-remote.$gs->{repo_id}.$n",
-                               "$remote_path:refs/remotes/$pfx*");
+                               "$remote_path:refs/remotes/$pfx*" . ('/*' x (($remote_path =~ tr/*/*/)-1)));
 }

 sub verify_ref {
@@ -4113,16 +4113,35 @@ sub gs_fetch_loop_common {
        Git::SVN::gc();
 }

+sub get_dir_globbed {
+       my ($self, $left, $depth, $r) = @_;
+
+       my @x = eval { $self->get_dir($left, $r) };
+       return unless scalar @x == 3;
+       my $dirents = $x[0];
+       my @finalents;
+       foreach my $de (keys %$dirents) {
+               next if $dirents->{$de}->{kind} != $SVN::Node::dir;
+               if ($depth > 1) {
+                       foreach my $dir ($self->get_dir_globbed($left.'/'.$de, $depth - 1, $r)) {
+                               push @finalents, "$de/$dir";
+                       }
+               } else {
+                       push @finalents, $de;
+               }
+       }
+       @finalents;
+}
+
 sub match_globs {
        my ($self, $exists, $paths, $globs, $r) = @_;

        sub get_dir_check {
                my ($self, $exists, $g, $r) = @_;
-               my @x = eval { $self->get_dir($g->{path}->{left}, $r) };
-               return unless scalar @x == 3;
-               my $dirents = $x[0];
-               foreach my $de (keys %$dirents) {
-                       next if $dirents->{$de}->{kind} != $SVN::Node::dir;
+
+               my @dirs = $self->get_dir_globbed($g->{path}->{left}, $g->{path}->{depth}, $r);
+
+               foreach my $de (@dirs) {
                        my $p = $g->{path}->full_path($de);
                        next if $exists->{$p};
                        next if (length $g->{path}->{right} &&
@@ -4904,16 +4923,20 @@ sub new {
        my ($class, $glob) = @_;
        my $re = $glob;
        $re =~ s!/+$!!g; # no need for trailing slashes
-       my $nr = $re =~ tr/*/*/;
-       if ($nr > 1) {
-               die "Only one '*' wildcard expansion ",
-                   "is supported (got $nr): '$glob'\n";
-       } elsif ($nr == 0) {
+       $re =~ m!^([^*]*)(\*(?:/\*)*)([^*]*)$!;
+       my $temp = $re;
+       my ($left, $right) = ($1, $3);
+       $re = $2;
+       my $depth = $re =~ tr/*/*/;
+       if ($depth != $temp =~ tr/*/*/) {
+               die "Only one set of wildcard directories (e.g. '*' or '*/*/*') is supported: '$glob'\n";
+       }
+       if ($depth == 0) {
                die "One '*' is needed for glob: '$glob'\n";
        }
-       $re =~ s!^(.*)\*(.*)$!\(\[^/\]+\)!g;
-       my ($left, $right) = ($1, $2);
-       $re = quotemeta($left) . $re . quotemeta($right);
+       $re =~ s!\*!\[^/\]*!g;
+#      $re =~ s!\?!\[^/\]!g;
+       $re = quotemeta($left) . "($re)" . quotemeta($right);
        if (length $left && !($left =~ s!/+$!!g)) {
                die "Missing trailing '/' on left side of: '$glob' ($left)\n";
        }
@@ -4922,7 +4945,7 @@ sub new {
        }
        my $left_re = qr/^\/\Q$left\E(\/|$)/;
        bless { left => $left, right => $right, left_regex => $left_re,
-               regex => qr/$re/, glob => $glob }, $class;
+               regex => qr/$re/, glob => $glob, depth => $depth }, $class;
 }

 sub full_path {
diff --git a/t/t9108-git-svn-glob.sh b/t/t9108-git-svn-glob.sh
index ef6d88e..46958e5 100755
--- a/t/t9108-git-svn-glob.sh
+++ b/t/t9108-git-svn-glob.sh
@@ -52,7 +52,8 @@ test_expect_success 'test refspec globbing' '
        test "`git rev-parse refs/remotes/tags/end~1`" = \
                "`git rev-parse refs/remotes/branches/start`" &&
        test "`git rev-parse refs/remotes/branches/start~2`" = \
-               "`git rev-parse refs/remotes/trunk`"
+               "`git rev-parse refs/remotes/trunk`" &&
+       test_must_fail git rev-parse refs/remotes/tags/end@3
        '

 echo try to try > expect.two
@@ -83,14 +84,14 @@ test_expect_success 'test left-hand-side only globbing' '
        cmp expect.two output.two
        '

-echo "Only one '*' wildcard expansion is supported (got 2): 'branches/*/*'" > expect.three
+echo "Only one set of wildcard directories (e.g. '*' or '*/*/*') is supported: 'branches/*/t/*'" > expect.three
 echo "" >> expect.three

-test_expect_success 'test disallow multi-globs' '
+test_expect_success 'test disallow multiple globs' '
        git config --add svn-remote.three.url "$svnrepo" &&
        git config --add svn-remote.three.fetch trunk:refs/remotes/three/trunk &&
        git config --add svn-remote.three.branches \
-                        "branches/*/*:refs/remotes/three/branches/*" &&
+                        "branches/*/t/*:refs/remotes/three/branches/*" &&
        git config --add svn-remote.three.tags \
                         "tags/*/*:refs/remotes/three/tags/*" &&
        cd tmp &&
diff --git a/t/t9108-git-svn-multi-glob.sh b/t/t9108-git-svn-multi-glob.sh
new file mode 100755
index 0000000..1d80cb1
--- /dev/null
+++ b/t/t9108-git-svn-multi-glob.sh
@@ -0,0 +1,155 @@
+#!/bin/sh
+# Copyright (c) 2007 Eric Wong
+test_description='git-svn globbing refspecs'
+. ./lib-git-svn.sh
+
+cat > expect.end <<EOF
+the end
+hi
+start a new branch
+initial
+EOF
+
+test_expect_success 'test refspec globbing' '
+       mkdir -p trunk/src/a trunk/src/b trunk/doc &&
+       echo "hello world" > trunk/src/a/readme &&
+       echo "goodbye world" > trunk/src/b/readme &&
+       svn import -m "initial" trunk "$svnrepo"/trunk &&
+       svn co "$svnrepo" tmp &&
+       cd tmp &&
+               mkdir branches branches/v1 tags &&
+               svn add branches tags &&
+               svn cp trunk branches/v1/start &&
+               svn commit -m "start a new branch" &&
+               svn up &&
+               echo "hi" >> branches/v1/start/src/b/readme &&
+               poke branches/v1/start/src/b/readme &&
+               echo "hey" >> branches/v1/start/src/a/readme &&
+               poke branches/v1/start/src/a/readme &&
+               svn commit -m "hi" &&
+               svn up &&
+               svn cp branches/v1/start tags/end &&
+               echo "bye" >> tags/end/src/b/readme &&
+               poke tags/end/src/b/readme &&
+               echo "aye" >> tags/end/src/a/readme &&
+               poke tags/end/src/a/readme &&
+               svn commit -m "the end" &&
+               echo "byebye" >> tags/end/src/b/readme &&
+               poke tags/end/src/b/readme &&
+               svn commit -m "nothing to see here"
+               cd .. &&
+       git config --add svn-remote.svn.url "$svnrepo" &&
+       git config --add svn-remote.svn.fetch \
+                        "trunk/src/a:refs/remotes/trunk" &&
+       git config --add svn-remote.svn.branches \
+                        "branches/*/*/src/a:refs/remotes/branches/*/*" &&
+       git config --add svn-remote.svn.tags\
+                        "tags/*/src/a:refs/remotes/tags/*" &&
+       git-svn multi-fetch &&
+       git log --pretty=oneline refs/remotes/tags/end | \
+           sed -e "s/^.\{41\}//" > output.end &&
+       cmp expect.end output.end &&
+       test "`git rev-parse refs/remotes/tags/end~1`" = \
+               "`git rev-parse refs/remotes/branches/v1/start`" &&
+       test "`git rev-parse refs/remotes/branches/v1/start~2`" = \
+               "`git rev-parse refs/remotes/trunk`" &&
+       test_must_fail git rev-parse refs/remotes/tags/end@3
+       '
+
+echo try to try > expect.two
+echo nothing to see here >> expect.two
+cat expect.end >> expect.two
+
+test_expect_success 'test left-hand-side only globbing' '
+       git config --add svn-remote.two.url "$svnrepo" &&
+       git config --add svn-remote.two.fetch trunk:refs/remotes/two/trunk &&
+       git config --add svn-remote.two.branches \
+                        "branches/*/*:refs/remotes/two/branches/*/*" &&
+       git config --add svn-remote.two.tags \
+                        "tags/*:refs/remotes/two/tags/*" &&
+       cd tmp &&
+               echo "try try" >> tags/end/src/b/readme &&
+               poke tags/end/src/b/readme &&
+               svn commit -m "try to try"
+               cd .. &&
+       git-svn fetch two &&
+       test `git rev-list refs/remotes/two/tags/end | wc -l` -eq 6 &&
+       test `git rev-list refs/remotes/two/branches/v1/start | wc -l` -eq 3 &&
+       test `git rev-parse refs/remotes/two/branches/v1/start~2` = \
+            `git rev-parse refs/remotes/two/trunk` &&
+       test `git rev-parse refs/remotes/two/tags/end~3` = \
+            `git rev-parse refs/remotes/two/branches/v1/start` &&
+       git log --pretty=oneline refs/remotes/two/tags/end | \
+           sed -e "s/^.\{41\}//" > output.two &&
+       cmp expect.two output.two
+       '
+cat > expect.four <<EOF
+adios
+adding more
+Changed 2 in v2/start
+Another versioned branch
+initial
+EOF
+
+test_expect_success 'test another branch' '
+       (
+               cd tmp &&
+               mkdir branches/v2 &&
+               svn add branches/v2 &&
+               svn cp trunk branches/v2/start &&
+               svn commit -m "Another versioned branch" &&
+               svn up &&
+               echo "hello" >> branches/v2/start/src/b/readme &&
+               poke branches/v2/start/src/b/readme &&
+               echo "howdy" >> branches/v2/start/src/a/readme &&
+               poke branches/v2/start/src/a/readme &&
+               svn commit -m "Changed 2 in v2/start" &&
+               svn up &&
+               svn cp branches/v2/start tags/next &&
+               echo "bye" >> tags/next/src/b/readme &&
+               poke tags/next/src/b/readme &&
+               echo "aye" >> tags/next/src/a/readme &&
+               poke tags/next/src/a/readme &&
+               svn commit -m "adding more" &&
+               echo "byebye" >> tags/next/src/b/readme &&
+               poke tags/next/src/b/readme &&
+               svn commit -m "adios"
+       ) &&
+       git config --add svn-remote.four.url "$svnrepo" &&
+       git config --add svn-remote.four.fetch trunk:refs/remotes/four/trunk &&
+       git config --add svn-remote.four.branches \
+                        "branches/*/*:refs/remotes/four/branches/*/*" &&
+       git config --add svn-remote.four.tags \
+                        "tags/*:refs/remotes/four/tags/*" &&
+       git-svn fetch four &&
+       test `git rev-list refs/remotes/four/tags/next | wc -l` -eq 5 &&
+       test `git rev-list refs/remotes/four/branches/v2/start | wc -l` -eq 3 &&
+       test `git rev-parse refs/remotes/four/branches/v2/start~2` = \
+            `git rev-parse refs/remotes/four/trunk` &&
+       test `git rev-parse refs/remotes/four/tags/next~2` = \
+            `git rev-parse refs/remotes/four/branches/v2/start` &&
+       git log --pretty=oneline refs/remotes/four/tags/next | \
+           sed -e "s/^.\{41\}//" > output.four &&
+       cmp expect.four output.four
+       '
+
+echo "Only one set of wildcard directories (e.g. '*' or '*/*/*') is supported: 'branches/*/t/*'" > expect.three
+echo "" >> expect.three
+
+test_expect_success 'test disallow multiple globs' '
+       git config --add svn-remote.three.url "$svnrepo" &&
+       git config --add svn-remote.three.fetch trunk:refs/remotes/three/trunk &&
+       git config --add svn-remote.three.branches \
+                        "branches/*/t/*:refs/remotes/three/branches/*/*" &&
+       git config --add svn-remote.three.tags \
+                        "tags/*:refs/remotes/three/tags/*" &&
+       cd tmp &&
+               echo "try try" >> tags/end/src/b/readme &&
+               poke tags/end/src/b/readme &&
+               svn commit -m "try to try"
+               cd .. &&
+       test_must_fail git-svn fetch three &> stderr.three &&
+       cmp expect.three stderr.three
+       '
+
+test_done
diff --git a/t/t9125-git-svn-multi-glob-branch-names.sh b/t/t9125-git-svn-multi-glob-branch-names.sh
new file mode 100755
index 0000000..f7c7836
--- /dev/null
+++ b/t/t9125-git-svn-multi-glob-branch-names.sh
@@ -0,0 +1,40 @@
+#!/bin/sh
+#
+# Copyright (c) 2007 Eric Wong
+#
+
+test_description='git-svn multi-glob branch names'
+. ./lib-git-svn.sh
+
+test_expect_success 'setup svnrepo' '
+       mkdir project project/trunk project/branches project/branches/v14.1 project/tags &&
+       echo foo > project/trunk/foo &&
+       svn import -m "$test_description" project "$svnrepo/project" &&
+       rm -rf project &&
+       svn cp -m "fun" "$svnrepo/project/trunk" \
+                       "$svnrepo/project/branches/v14.1/beta" &&
+       svn cp -m "more fun!" "$svnrepo/project/branches/v14.1/beta" \
+                             "$svnrepo/project/branches/v14.1/gold" &&
+       start_httpd
+       '
+
+test_expect_success 'test clone with multi-glob in branch names' '
+       git svn clone -T trunk -b branches/*/* -t tags "$svnrepo/project" project &&
+       cd project &&
+               git rev-parse "refs/remotes/v14.1/beta" &&
+               git rev-parse "refs/remotes/v14.1/gold" &&
+       cd ..
+       '
+
+test_expect_success 'test dcommit to multi-globbed branch' "
+       cd project &&
+       git reset --hard 'refs/remotes/v14.1/gold' &&
+       echo hello >> foo &&
+       git commit -m 'hello' -- foo &&
+       git svn dcommit &&
+       cd ..
+       "
+
+stop_httpd
+
+test_done
--
1.5.4.3

-- 
Marcus Griep
GPG Key ID: 0x5E968152
——
http://www.boohaunt.net
את.ψο´

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [PATCH 2/2] git-svn: Allow deep branch names by supporting multi-globs
  2008-08-06 19:58 [PATCH 2/2] git-svn: Allow deep branch names by supporting multi-globs Marcus Griep
@ 2008-08-07  9:00 ` Eric Wong
  2008-08-07 15:34   ` [PATCH v2 0/2] git-svn multi-glob fix and extension Marcus Griep
  0 siblings, 1 reply; 14+ messages in thread
From: Eric Wong @ 2008-08-07  9:00 UTC (permalink / raw)
  To: Marcus Griep; +Cc: Git Mailing List

Marcus Griep <marcus@griep.us> wrote:
> Some repositories use a deep branching strategy, such as:
> branches/1.0/1.0.rc1
> branches/1.0/1.0.rc2
> branches/1.0/1.0.rtm
> branches/1.0/1.0.gold
> 
> Only allowing a single glob stiffles this.
> 
> This change allows for a single glob 'set' to accept this deep branching
> strategy.
> 
> The ref glob depth must match the branch glob depth.  When using the -b or -t
> options for init or clone, this is automatically done.
> 
> For example, using the above branches:
>   svn-remote.svn.branches = branches/*/*:refs/remote/*/*
> gives the following branch names:
>   1.0/1.0.rc1
>   1.0/1.0.rc2
>   1.0/1.0.rtm
>   1.0/1.0.gold

Hi Marcus,

This looks awesome.  Some folks have been wanting to do this for a
long time but I was always too lazy to touch this code.

Unfortunately, I'm having trouble applying your patches due to
whitespace conversion issues with your MUA.  I suggest taking a look at
Documentation/SubmittingPatches on how to submit easily applyable
patches to the mailing list.

I usually use git-send-email myself, but sometimes mutt, too.

Also, there are some long lines that need to be wrapped at
80 characters or less to conform to the existing coding
conventions.

I look forward to applying and testing your patches,

Thank you!

-- 
Eric Wong

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH v2 0/2] git-svn multi-glob fix and extension
  2008-08-07  9:00 ` Eric Wong
@ 2008-08-07 15:34   ` Marcus Griep
  2008-08-07 15:34     ` [PATCH v2 1/2] Fix multi-glob assertion in git-svn Marcus Griep
  2008-08-08  8:40     ` [PATCH v2 0/2] git-svn multi-glob fix and extension Eric Wong
  0 siblings, 2 replies; 14+ messages in thread
From: Marcus Griep @ 2008-08-07 15:34 UTC (permalink / raw)
  To: Git Mailing List; +Cc: Eric Wong, Junio C Hamano


This patch series fixes and extends globs for branches and tags.

The first patch fixes the assertion that protects git-svn from allowing
multi-globs in branch names, whereas the second removes that restriction
altogether, allowing up to one multi-glob set in defining a branch hierarchy.

Also, patches are now under 80 chars wide except for a couple of echos in the
test cases.

Marcus Griep (2):
      Fix multi-glob assertion in git-svn
      git-svn: Allow deep branch names by supporting multi-globs

 git-svn.perl                               |   63 +++++++++---
 t/t9108-git-svn-glob.sh                    |   22 ++++-
 t/t9108-git-svn-multi-glob.sh              |  155 ++++++++++++++++++++++++++++
 t/t9125-git-svn-multi-glob-branch-names.sh |   41 ++++++++
 4 files changed, 264 insertions(+), 17 deletions(-)

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH v2 1/2] Fix multi-glob assertion in git-svn
  2008-08-07 15:34   ` [PATCH v2 0/2] git-svn multi-glob fix and extension Marcus Griep
@ 2008-08-07 15:34     ` Marcus Griep
  2008-08-07 15:34       ` [PATCH v2 2/2] git-svn: Allow deep branch names by supporting multi-globs Marcus Griep
  2008-08-08  8:40     ` [PATCH v2 0/2] git-svn multi-glob fix and extension Eric Wong
  1 sibling, 1 reply; 14+ messages in thread
From: Marcus Griep @ 2008-08-07 15:34 UTC (permalink / raw)
  To: Git Mailing List; +Cc: Eric Wong, Junio C Hamano, Marcus Griep

Fixes bad regex match check for multiple globs (would always return
one glob regardless of actual number).

Signed-off-by: Marcus Griep <marcus@griep.us>
---
 git-svn.perl            |    5 +++--
 t/t9108-git-svn-glob.sh |   19 +++++++++++++++++++
 2 files changed, 22 insertions(+), 2 deletions(-)

diff --git a/git-svn.perl b/git-svn.perl
index df0ed90..5974a06 100755
--- a/git-svn.perl
+++ b/git-svn.perl
@@ -4912,14 +4912,15 @@ sub new {
 	my ($class, $glob) = @_;
 	my $re = $glob;
 	$re =~ s!/+$!!g; # no need for trailing slashes
-	my $nr = ($re =~ s!^(.*)\*(.*)$!\(\[^/\]+\)!g);
-	my ($left, $right) = ($1, $2);
+	my $nr = $re =~ tr/*/*/;
 	if ($nr > 1) {
 		die "Only one '*' wildcard expansion ",
 		    "is supported (got $nr): '$glob'\n";
 	} elsif ($nr == 0) {
 		die "One '*' is needed for glob: '$glob'\n";
 	}
+	$re =~ s!^(.*)\*(.*)$!\(\[^/\]+\)!g;
+	my ($left, $right) = ($1, $2);
 	$re = quotemeta($left) . $re . quotemeta($right);
 	if (length $left && !($left =~ s!/+$!!g)) {
 		die "Missing trailing '/' on left side of: '$glob' ($left)\n";
diff --git a/t/t9108-git-svn-glob.sh b/t/t9108-git-svn-glob.sh
index f6f71d0..ef6d88e 100755
--- a/t/t9108-git-svn-glob.sh
+++ b/t/t9108-git-svn-glob.sh
@@ -83,4 +83,23 @@ test_expect_success 'test left-hand-side only globbing' '
 	cmp expect.two output.two
 	'
 
+echo "Only one '*' wildcard expansion is supported (got 2): 'branches/*/*'" > expect.three
+echo "" >> expect.three
+
+test_expect_success 'test disallow multi-globs' '
+	git config --add svn-remote.three.url "$svnrepo" &&
+	git config --add svn-remote.three.fetch trunk:refs/remotes/three/trunk &&
+	git config --add svn-remote.three.branches \
+	                 "branches/*/*:refs/remotes/three/branches/*" &&
+	git config --add svn-remote.three.tags \
+	                 "tags/*/*:refs/remotes/three/tags/*" &&
+	cd tmp &&
+		echo "try try" >> tags/end/src/b/readme &&
+		poke tags/end/src/b/readme &&
+		svn commit -m "try to try"
+		cd .. &&
+	test_must_fail git-svn fetch three &> stderr.three &&
+	cmp expect.three stderr.three
+	'
+
 test_done
-- 
1.6.0.rc2.4.g39f8

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH v2 2/2] git-svn: Allow deep branch names by supporting multi-globs
  2008-08-07 15:34     ` [PATCH v2 1/2] Fix multi-glob assertion in git-svn Marcus Griep
@ 2008-08-07 15:34       ` Marcus Griep
  0 siblings, 0 replies; 14+ messages in thread
From: Marcus Griep @ 2008-08-07 15:34 UTC (permalink / raw)
  To: Git Mailing List; +Cc: Eric Wong, Junio C Hamano, Marcus Griep

Some repositories use a deep branching strategy, such as:
branches/1.0/1.0.rc1
branches/1.0/1.0.rc2
branches/1.0/1.0.rtm
branches/1.0/1.0.gold

Only allowing a single glob stiffles this.

This change allows for a single glob 'set' to accept this deep branching
strategy.

The ref glob depth must match the branch glob depth.  When using the -b or -t
options for init or clone, this is automatically done.

For example, using the above branches:
  svn-remote.svn.branches = branches/*/*:refs/remote/*/*
gives the following branch names:
  1.0/1.0.rc1
  1.0/1.0.rc2
  1.0/1.0.rtm
  1.0/1.0.gold

Signed-off-by: Marcus Griep <marcus@griep.us>
---
 git-svn.perl                               |   64 +++++++++---
 t/t9108-git-svn-glob.sh                    |    9 +-
 t/t9108-git-svn-multi-glob.sh              |  155 ++++++++++++++++++++++++++++
 t/t9125-git-svn-multi-glob-branch-names.sh |   41 ++++++++
 4 files changed, 248 insertions(+), 21 deletions(-)
 create mode 100755 t/t9108-git-svn-multi-glob.sh
 create mode 100755 t/t9125-git-svn-multi-glob-branch-names.sh

diff --git a/git-svn.perl b/git-svn.perl
index 5974a06..fe78461 100755
--- a/git-svn.perl
+++ b/git-svn.perl
@@ -169,7 +169,8 @@ my %cmd = (
 			  'color' => \$Git::SVN::Log::color,
 			  'pager=s' => \$Git::SVN::Log::pager
 			} ],
-	'find-rev' => [ \&cmd_find_rev, "Translate between SVN revision numbers and tree-ish",
+	'find-rev' => [ \&cmd_find_rev, 
+				   "Translate between SVN revision numbers and tree-ish",
 			{} ],
 	'rebase' => [ \&cmd_rebase, "Fetch and rebase your working directory",
 			{ 'merge|m|M' => \$_merge,
@@ -229,7 +230,9 @@ unless ($cmd && $cmd =~ /(?:clone|init|multi-init)$/) {
 my %opts = %{$cmd{$cmd}->[2]} if (defined $cmd);
 
 read_repo_config(\%opts);
-Getopt::Long::Configure('pass_through') if ($cmd && ($cmd eq 'log' || $cmd eq 'blame'));
+if ($cmd && ($cmd eq 'log' || $cmd eq 'blame')) {
+	Getopt::Long::Configure('pass_through');
+}
 my $rv = GetOptions(%opts, 'help|H|h' => \$_help, 'version|V' => \$_version,
                     'minimize-connections' => \$Git::SVN::Migration::_minimize,
                     'id|i=s' => \$Git::SVN::default_ref_id,
@@ -985,7 +988,7 @@ sub complete_url_ls_init {
 		die "--prefix='$pfx' must have a trailing slash '/'\n";
 	}
 	command_noisy('config', "svn-remote.$gs->{repo_id}.$n",
-				"$remote_path:refs/remotes/$pfx*");
+				"$remote_path:refs/remotes/$pfx*" . ('/*' x (($remote_path =~ tr/*/*/)-1)));
 }
 
 sub verify_ref {
@@ -4121,16 +4124,38 @@ sub gs_fetch_loop_common {
 	Git::SVN::gc();
 }
 
+sub get_dir_globbed {
+	my ($self, $left, $depth, $r) = @_;
+
+	my @x = eval { $self->get_dir($left, $r) };
+	return unless scalar @x == 3;
+	my $dirents = $x[0];
+	my @finalents;
+	foreach my $de (keys %$dirents) {
+		next if $dirents->{$de}->{kind} != $SVN::Node::dir;
+		if ($depth > 1) {
+			foreach my $dir ($self->get_dir_globbed($left.'/'.$de, $depth - 1, $r)) {
+				push @finalents, "$de/$dir";
+			}
+		} else {
+			push @finalents, $de;
+		}
+	}
+	@finalents;
+}
+
 sub match_globs {
 	my ($self, $exists, $paths, $globs, $r) = @_;
 
 	sub get_dir_check {
 		my ($self, $exists, $g, $r) = @_;
-		my @x = eval { $self->get_dir($g->{path}->{left}, $r) };
-		return unless scalar @x == 3;
-		my $dirents = $x[0];
-		foreach my $de (keys %$dirents) {
-			next if $dirents->{$de}->{kind} != $SVN::Node::dir;
+
+		my @dirs = $self->get_dir_globbed(
+							$g->{path}->{left}, 
+							$g->{path}->{depth}, 
+							$r);
+
+		foreach my $de (@dirs) {
 			my $p = $g->{path}->full_path($de);
 			next if $exists->{$p};
 			next if (length $g->{path}->{right} &&
@@ -4912,16 +4937,21 @@ sub new {
 	my ($class, $glob) = @_;
 	my $re = $glob;
 	$re =~ s!/+$!!g; # no need for trailing slashes
-	my $nr = $re =~ tr/*/*/;
-	if ($nr > 1) {
-		die "Only one '*' wildcard expansion ",
-		    "is supported (got $nr): '$glob'\n";
-	} elsif ($nr == 0) {
+	$re =~ m!^([^*]*)(\*(?:/\*)*)([^*]*)$!;
+	my $temp = $re;
+	my ($left, $right) = ($1, $3);
+	$re = $2;
+	my $depth = $re =~ tr/*/*/;
+	if ($depth != $temp =~ tr/*/*/) {
+		die "Only one set of wildcard directories " .
+			"(e.g. '*' or '*/*/*') is supported: '$glob'\n";
+	}
+	if ($depth == 0) {
 		die "One '*' is needed for glob: '$glob'\n";
 	}
-	$re =~ s!^(.*)\*(.*)$!\(\[^/\]+\)!g;
-	my ($left, $right) = ($1, $2);
-	$re = quotemeta($left) . $re . quotemeta($right);
+	$re =~ s!\*!\[^/\]*!g;
+#	$re =~ s!\?!\[^/\]!g;
+	$re = quotemeta($left) . "($re)" . quotemeta($right);
 	if (length $left && !($left =~ s!/+$!!g)) {
 		die "Missing trailing '/' on left side of: '$glob' ($left)\n";
 	}
@@ -4930,7 +4960,7 @@ sub new {
 	}
 	my $left_re = qr/^\/\Q$left\E(\/|$)/;
 	bless { left => $left, right => $right, left_regex => $left_re,
-	        regex => qr/$re/, glob => $glob }, $class;
+	        regex => qr/$re/, glob => $glob, depth => $depth }, $class;
 }
 
 sub full_path {
diff --git a/t/t9108-git-svn-glob.sh b/t/t9108-git-svn-glob.sh
index ef6d88e..46958e5 100755
--- a/t/t9108-git-svn-glob.sh
+++ b/t/t9108-git-svn-glob.sh
@@ -52,7 +52,8 @@ test_expect_success 'test refspec globbing' '
 	test "`git rev-parse refs/remotes/tags/end~1`" = \
 		"`git rev-parse refs/remotes/branches/start`" &&
 	test "`git rev-parse refs/remotes/branches/start~2`" = \
-		"`git rev-parse refs/remotes/trunk`"
+		"`git rev-parse refs/remotes/trunk`" &&
+	test_must_fail git rev-parse refs/remotes/tags/end@3
 	'
 
 echo try to try > expect.two
@@ -83,14 +84,14 @@ test_expect_success 'test left-hand-side only globbing' '
 	cmp expect.two output.two
 	'
 
-echo "Only one '*' wildcard expansion is supported (got 2): 'branches/*/*'" > expect.three
+echo "Only one set of wildcard directories (e.g. '*' or '*/*/*') is supported: 'branches/*/t/*'" > expect.three
 echo "" >> expect.three
 
-test_expect_success 'test disallow multi-globs' '
+test_expect_success 'test disallow multiple globs' '
 	git config --add svn-remote.three.url "$svnrepo" &&
 	git config --add svn-remote.three.fetch trunk:refs/remotes/three/trunk &&
 	git config --add svn-remote.three.branches \
-	                 "branches/*/*:refs/remotes/three/branches/*" &&
+	                 "branches/*/t/*:refs/remotes/three/branches/*" &&
 	git config --add svn-remote.three.tags \
 	                 "tags/*/*:refs/remotes/three/tags/*" &&
 	cd tmp &&
diff --git a/t/t9108-git-svn-multi-glob.sh b/t/t9108-git-svn-multi-glob.sh
new file mode 100755
index 0000000..1d80cb1
--- /dev/null
+++ b/t/t9108-git-svn-multi-glob.sh
@@ -0,0 +1,155 @@
+#!/bin/sh
+# Copyright (c) 2007 Eric Wong
+test_description='git-svn globbing refspecs'
+. ./lib-git-svn.sh
+
+cat > expect.end <<EOF
+the end
+hi
+start a new branch
+initial
+EOF
+
+test_expect_success 'test refspec globbing' '
+	mkdir -p trunk/src/a trunk/src/b trunk/doc &&
+	echo "hello world" > trunk/src/a/readme &&
+	echo "goodbye world" > trunk/src/b/readme &&
+	svn import -m "initial" trunk "$svnrepo"/trunk &&
+	svn co "$svnrepo" tmp &&
+	cd tmp &&
+		mkdir branches branches/v1 tags &&
+		svn add branches tags &&
+		svn cp trunk branches/v1/start &&
+		svn commit -m "start a new branch" &&
+		svn up &&
+		echo "hi" >> branches/v1/start/src/b/readme &&
+		poke branches/v1/start/src/b/readme &&
+		echo "hey" >> branches/v1/start/src/a/readme &&
+		poke branches/v1/start/src/a/readme &&
+		svn commit -m "hi" &&
+		svn up &&
+		svn cp branches/v1/start tags/end &&
+		echo "bye" >> tags/end/src/b/readme &&
+		poke tags/end/src/b/readme &&
+		echo "aye" >> tags/end/src/a/readme &&
+		poke tags/end/src/a/readme &&
+		svn commit -m "the end" &&
+		echo "byebye" >> tags/end/src/b/readme &&
+		poke tags/end/src/b/readme &&
+		svn commit -m "nothing to see here"
+		cd .. &&
+	git config --add svn-remote.svn.url "$svnrepo" &&
+	git config --add svn-remote.svn.fetch \
+	                 "trunk/src/a:refs/remotes/trunk" &&
+	git config --add svn-remote.svn.branches \
+	                 "branches/*/*/src/a:refs/remotes/branches/*/*" &&
+	git config --add svn-remote.svn.tags\
+	                 "tags/*/src/a:refs/remotes/tags/*" &&
+	git-svn multi-fetch &&
+	git log --pretty=oneline refs/remotes/tags/end | \
+	    sed -e "s/^.\{41\}//" > output.end &&
+	cmp expect.end output.end &&
+	test "`git rev-parse refs/remotes/tags/end~1`" = \
+		"`git rev-parse refs/remotes/branches/v1/start`" &&
+	test "`git rev-parse refs/remotes/branches/v1/start~2`" = \
+		"`git rev-parse refs/remotes/trunk`" &&
+	test_must_fail git rev-parse refs/remotes/tags/end@3
+	'
+
+echo try to try > expect.two
+echo nothing to see here >> expect.two
+cat expect.end >> expect.two
+
+test_expect_success 'test left-hand-side only globbing' '
+	git config --add svn-remote.two.url "$svnrepo" &&
+	git config --add svn-remote.two.fetch trunk:refs/remotes/two/trunk &&
+	git config --add svn-remote.two.branches \
+	                 "branches/*/*:refs/remotes/two/branches/*/*" &&
+	git config --add svn-remote.two.tags \
+	                 "tags/*:refs/remotes/two/tags/*" &&
+	cd tmp &&
+		echo "try try" >> tags/end/src/b/readme &&
+		poke tags/end/src/b/readme &&
+		svn commit -m "try to try"
+		cd .. &&
+	git-svn fetch two &&
+	test `git rev-list refs/remotes/two/tags/end | wc -l` -eq 6 &&
+	test `git rev-list refs/remotes/two/branches/v1/start | wc -l` -eq 3 &&
+	test `git rev-parse refs/remotes/two/branches/v1/start~2` = \
+	     `git rev-parse refs/remotes/two/trunk` &&
+	test `git rev-parse refs/remotes/two/tags/end~3` = \
+	     `git rev-parse refs/remotes/two/branches/v1/start` &&
+	git log --pretty=oneline refs/remotes/two/tags/end | \
+	    sed -e "s/^.\{41\}//" > output.two &&
+	cmp expect.two output.two
+	'
+cat > expect.four <<EOF
+adios
+adding more
+Changed 2 in v2/start
+Another versioned branch
+initial
+EOF
+
+test_expect_success 'test another branch' '
+	(
+		cd tmp &&
+		mkdir branches/v2 &&
+		svn add branches/v2 &&
+		svn cp trunk branches/v2/start &&
+		svn commit -m "Another versioned branch" &&
+		svn up &&
+		echo "hello" >> branches/v2/start/src/b/readme &&
+		poke branches/v2/start/src/b/readme &&
+		echo "howdy" >> branches/v2/start/src/a/readme &&
+		poke branches/v2/start/src/a/readme &&
+		svn commit -m "Changed 2 in v2/start" &&
+		svn up &&
+		svn cp branches/v2/start tags/next &&
+		echo "bye" >> tags/next/src/b/readme &&
+		poke tags/next/src/b/readme &&
+		echo "aye" >> tags/next/src/a/readme &&
+		poke tags/next/src/a/readme &&
+		svn commit -m "adding more" &&
+		echo "byebye" >> tags/next/src/b/readme &&
+		poke tags/next/src/b/readme &&
+		svn commit -m "adios"
+	) &&
+	git config --add svn-remote.four.url "$svnrepo" &&
+	git config --add svn-remote.four.fetch trunk:refs/remotes/four/trunk &&
+	git config --add svn-remote.four.branches \
+	                 "branches/*/*:refs/remotes/four/branches/*/*" &&
+	git config --add svn-remote.four.tags \
+	                 "tags/*:refs/remotes/four/tags/*" &&
+	git-svn fetch four &&
+	test `git rev-list refs/remotes/four/tags/next | wc -l` -eq 5 &&
+	test `git rev-list refs/remotes/four/branches/v2/start | wc -l` -eq 3 &&
+	test `git rev-parse refs/remotes/four/branches/v2/start~2` = \
+	     `git rev-parse refs/remotes/four/trunk` &&
+	test `git rev-parse refs/remotes/four/tags/next~2` = \
+	     `git rev-parse refs/remotes/four/branches/v2/start` &&
+	git log --pretty=oneline refs/remotes/four/tags/next | \
+	    sed -e "s/^.\{41\}//" > output.four &&
+	cmp expect.four output.four
+	'
+
+echo "Only one set of wildcard directories (e.g. '*' or '*/*/*') is supported: 'branches/*/t/*'" > expect.three
+echo "" >> expect.three
+
+test_expect_success 'test disallow multiple globs' '
+	git config --add svn-remote.three.url "$svnrepo" &&
+	git config --add svn-remote.three.fetch trunk:refs/remotes/three/trunk &&
+	git config --add svn-remote.three.branches \
+	                 "branches/*/t/*:refs/remotes/three/branches/*/*" &&
+	git config --add svn-remote.three.tags \
+	                 "tags/*:refs/remotes/three/tags/*" &&
+	cd tmp &&
+		echo "try try" >> tags/end/src/b/readme &&
+		poke tags/end/src/b/readme &&
+		svn commit -m "try to try"
+		cd .. &&
+	test_must_fail git-svn fetch three &> stderr.three &&
+	cmp expect.three stderr.three
+	'
+
+test_done
diff --git a/t/t9125-git-svn-multi-glob-branch-names.sh b/t/t9125-git-svn-multi-glob-branch-names.sh
new file mode 100755
index 0000000..5560db0
--- /dev/null
+++ b/t/t9125-git-svn-multi-glob-branch-names.sh
@@ -0,0 +1,41 @@
+#!/bin/sh
+#
+# Copyright (c) 2007 Eric Wong
+#
+
+test_description='git-svn multi-glob branch names'
+. ./lib-git-svn.sh
+
+test_expect_success 'setup svnrepo' '
+	mkdir project project/trunk project/branches \
+			project/branches/v14.1 project/tags &&
+	echo foo > project/trunk/foo &&
+	svn import -m "$test_description" project "$svnrepo/project" &&
+	rm -rf project &&
+	svn cp -m "fun" "$svnrepo/project/trunk" \
+	                "$svnrepo/project/branches/v14.1/beta" &&
+	svn cp -m "more fun!" "$svnrepo/project/branches/v14.1/beta" \
+	                      "$svnrepo/project/branches/v14.1/gold" &&
+	start_httpd
+	'
+
+test_expect_success 'test clone with multi-glob in branch names' '
+	git svn clone -T trunk -b branches/*/* -t tags "$svnrepo/project" project &&
+	cd project &&
+		git rev-parse "refs/remotes/v14.1/beta" &&
+		git rev-parse "refs/remotes/v14.1/gold" &&
+	cd ..
+	'
+
+test_expect_success 'test dcommit to multi-globbed branch' "
+	cd project &&
+	git reset --hard 'refs/remotes/v14.1/gold' &&
+	echo hello >> foo &&
+	git commit -m 'hello' -- foo &&
+	git svn dcommit &&
+	cd ..
+	"
+
+stop_httpd
+
+test_done
-- 
1.6.0.rc2.4.g39f8

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [PATCH v2 0/2] git-svn multi-glob fix and extension
  2008-08-07 15:34   ` [PATCH v2 0/2] git-svn multi-glob fix and extension Marcus Griep
  2008-08-07 15:34     ` [PATCH v2 1/2] Fix multi-glob assertion in git-svn Marcus Griep
@ 2008-08-08  8:40     ` Eric Wong
  2008-08-08  8:41       ` [PATCH 1/3] Fix multi-glob assertion in git-svn Eric Wong
                         ` (4 more replies)
  1 sibling, 5 replies; 14+ messages in thread
From: Eric Wong @ 2008-08-08  8:40 UTC (permalink / raw)
  To: Marcus Griep; +Cc: Git Mailing List, Junio C Hamano

Marcus Griep <marcus@griep.us> wrote:
> 
> This patch series fixes and extends globs for branches and tags.
> 
> The first patch fixes the assertion that protects git-svn from allowing
> multi-globs in branch names, whereas the second removes that restriction
> altogether, allowing up to one multi-glob set in defining a branch hierarchy.
> 
> Also, patches are now under 80 chars wide except for a couple of echos in the
> test cases.

Thanks.  At least I can apply the patches now :)
I've made couple of fixups which will be replies to this message.

Eric Wong (1):
      git-svn: wrap long lines in a few places

Marcus Griep (2):
      Fix multi-glob assertion in git-svn
      git-svn: Allow deep branch names by supporting multi-globs

---
 git-svn.perl                               |   67 +++++++++---
 t/t9108-git-svn-glob.sh                    |   24 ++++-
 t/t9108-git-svn-multi-glob.sh              |  157 ++++++++++++++++++++++++++++
 t/t9125-git-svn-multi-glob-branch-names.sh |   37 +++++++
 4 files changed, 267 insertions(+), 18 deletions(-)

-- 
Eric Wong

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 1/3] Fix multi-glob assertion in git-svn
  2008-08-08  8:40     ` [PATCH v2 0/2] git-svn multi-glob fix and extension Eric Wong
@ 2008-08-08  8:41       ` Eric Wong
  2008-08-08  9:41         ` Junio C Hamano
  2008-08-08  8:41       ` [PATCH 2/3] git-svn: Allow deep branch names by supporting multi-globs Eric Wong
                         ` (3 subsequent siblings)
  4 siblings, 1 reply; 14+ messages in thread
From: Eric Wong @ 2008-08-08  8:41 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, Marcus Griep

From: Marcus Griep <marcus@griep.us>

Fixes bad regex match check for multiple globs (would always return
one glob regardless of actual number).

[ew: fixed a bashism in the test and some minor line-wrapping]

Signed-off-by: Marcus Griep <marcus@griep.us>
Acked-by: Eric Wong <normalperson@yhbt.net>
---
 git-svn.perl            |    5 +++--
 t/t9108-git-svn-glob.sh |   21 +++++++++++++++++++++
 2 files changed, 24 insertions(+), 2 deletions(-)

diff --git a/git-svn.perl b/git-svn.perl
index 06a82c8..503a7c9 100755
--- a/git-svn.perl
+++ b/git-svn.perl
@@ -4915,14 +4915,15 @@ sub new {
 	my ($class, $glob) = @_;
 	my $re = $glob;
 	$re =~ s!/+$!!g; # no need for trailing slashes
-	my $nr = ($re =~ s!^(.*)\*(.*)$!\(\[^/\]+\)!g);
-	my ($left, $right) = ($1, $2);
+	my $nr = $re =~ tr/*/*/;
 	if ($nr > 1) {
 		die "Only one '*' wildcard expansion ",
 		    "is supported (got $nr): '$glob'\n";
 	} elsif ($nr == 0) {
 		die "One '*' is needed for glob: '$glob'\n";
 	}
+	$re =~ s!^(.*)\*(.*)$!\(\[^/\]+\)!g;
+	my ($left, $right) = ($1, $2);
 	$re = quotemeta($left) . $re . quotemeta($right);
 	if (length $left && !($left =~ s!/+$!!g)) {
 		die "Missing trailing '/' on left side of: '$glob' ($left)\n";
diff --git a/t/t9108-git-svn-glob.sh b/t/t9108-git-svn-glob.sh
index f6f71d0..a6f88bd 100755
--- a/t/t9108-git-svn-glob.sh
+++ b/t/t9108-git-svn-glob.sh
@@ -83,4 +83,25 @@ test_expect_success 'test left-hand-side only globbing' '
 	cmp expect.two output.two
 	'
 
+echo "Only one '*' wildcard expansion is supported (got 2): 'branches/*/*'" \
+     > expect.three
+echo "" >> expect.three
+
+test_expect_success 'test disallow multi-globs' '
+	git config --add svn-remote.three.url "$svnrepo" &&
+	git config --add svn-remote.three.fetch \
+	                 trunk:refs/remotes/three/trunk &&
+	git config --add svn-remote.three.branches \
+	                 "branches/*/*:refs/remotes/three/branches/*" &&
+	git config --add svn-remote.three.tags \
+	                 "tags/*/*:refs/remotes/three/tags/*" &&
+	cd tmp &&
+		echo "try try" >> tags/end/src/b/readme &&
+		poke tags/end/src/b/readme &&
+		svn commit -m "try to try"
+		cd .. &&
+	test_must_fail git-svn fetch three 2> stderr.three &&
+	cmp expect.three stderr.three
+	'
+
 test_done
-- 
1.6.0.rc2.4.g0643f

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 2/3] git-svn: Allow deep branch names by supporting multi-globs
  2008-08-08  8:40     ` [PATCH v2 0/2] git-svn multi-glob fix and extension Eric Wong
  2008-08-08  8:41       ` [PATCH 1/3] Fix multi-glob assertion in git-svn Eric Wong
@ 2008-08-08  8:41       ` Eric Wong
  2008-08-08  8:41       ` [PATCH 3/3] git-svn: wrap long lines in a few places Eric Wong
                         ` (2 subsequent siblings)
  4 siblings, 0 replies; 14+ messages in thread
From: Eric Wong @ 2008-08-08  8:41 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, Marcus Griep

From: Marcus Griep <marcus@griep.us>

Some repositories use a deep branching strategy, such as:
branches/1.0/1.0.rc1
branches/1.0/1.0.rc2
branches/1.0/1.0.rtm
branches/1.0/1.0.gold

Only allowing a single glob stiffles this.

This change allows for a single glob 'set' to accept this deep
branching strategy.

The ref glob depth must match the branch glob depth.  When using
the -b or -t options for init or clone, this is automatically
done.

For example, using the above branches:
  svn-remote.svn.branches = branches/*/*:refs/remote/*/*
gives the following branch names:
  1.0/1.0.rc1
  1.0/1.0.rc2
  1.0/1.0.rtm
  1.0/1.0.gold

[ew:
  * removed unrelated line-wrapping changes
  * fixed line-wrapping in a few more places
  * removed trailing whitespace
  * fixed bashism in test
  * removed unnecessary httpd startup in test
  * changed copyright on tests to 2008 Marcus Griep
  * added executable permissions to new tests
]

Signed-off-by: Marcus Griep <marcus@griep.us>
Acked-by: Eric Wong <normalperson@yhbt.net>
---
 git-svn.perl                               |   61 ++++++++---
 t/t9108-git-svn-glob.sh                    |    9 +-
 t/t9108-git-svn-multi-glob.sh              |  157 ++++++++++++++++++++++++++++
 t/t9125-git-svn-multi-glob-branch-names.sh |   37 +++++++
 4 files changed, 244 insertions(+), 20 deletions(-)
 create mode 100755 t/t9108-git-svn-multi-glob.sh
 create mode 100755 t/t9125-git-svn-multi-glob-branch-names.sh

diff --git a/git-svn.perl b/git-svn.perl
index 503a7c9..47ad378 100755
--- a/git-svn.perl
+++ b/git-svn.perl
@@ -987,8 +987,10 @@ sub complete_url_ls_init {
 	if (length $pfx && $pfx !~ m#/$#) {
 		die "--prefix='$pfx' must have a trailing slash '/'\n";
 	}
-	command_noisy('config', "svn-remote.$gs->{repo_id}.$n",
-				"$remote_path:refs/remotes/$pfx*");
+	command_noisy('config',
+	              "svn-remote.$gs->{repo_id}.$n",
+	              "$remote_path:refs/remotes/$pfx*" .
+	                ('/*' x (($remote_path =~ tr/*/*/) - 1)) );
 }
 
 sub verify_ref {
@@ -4124,16 +4126,38 @@ sub gs_fetch_loop_common {
 	Git::SVN::gc();
 }
 
+sub get_dir_globbed {
+	my ($self, $left, $depth, $r) = @_;
+
+	my @x = eval { $self->get_dir($left, $r) };
+	return unless scalar @x == 3;
+	my $dirents = $x[0];
+	my @finalents;
+	foreach my $de (keys %$dirents) {
+		next if $dirents->{$de}->{kind} != $SVN::Node::dir;
+		if ($depth > 1) {
+			my @args = ("$left/$de", $depth - 1, $r);
+			foreach my $dir ($self->get_dir_globbed(@args)) {
+				push @finalents, "$de/$dir";
+			}
+		} else {
+			push @finalents, $de;
+		}
+	}
+	@finalents;
+}
+
 sub match_globs {
 	my ($self, $exists, $paths, $globs, $r) = @_;
 
 	sub get_dir_check {
 		my ($self, $exists, $g, $r) = @_;
-		my @x = eval { $self->get_dir($g->{path}->{left}, $r) };
-		return unless scalar @x == 3;
-		my $dirents = $x[0];
-		foreach my $de (keys %$dirents) {
-			next if $dirents->{$de}->{kind} != $SVN::Node::dir;
+
+		my @dirs = $self->get_dir_globbed($g->{path}->{left},
+		                                  $g->{path}->{depth},
+		                                  $r);
+
+		foreach my $de (@dirs) {
 			my $p = $g->{path}->full_path($de);
 			next if $exists->{$p};
 			next if (length $g->{path}->{right} &&
@@ -4915,16 +4939,21 @@ sub new {
 	my ($class, $glob) = @_;
 	my $re = $glob;
 	$re =~ s!/+$!!g; # no need for trailing slashes
-	my $nr = $re =~ tr/*/*/;
-	if ($nr > 1) {
-		die "Only one '*' wildcard expansion ",
-		    "is supported (got $nr): '$glob'\n";
-	} elsif ($nr == 0) {
+	$re =~ m!^([^*]*)(\*(?:/\*)*)([^*]*)$!;
+	my $temp = $re;
+	my ($left, $right) = ($1, $3);
+	$re = $2;
+	my $depth = $re =~ tr/*/*/;
+	if ($depth != $temp =~ tr/*/*/) {
+		die "Only one set of wildcard directories " .
+			"(e.g. '*' or '*/*/*') is supported: '$glob'\n";
+	}
+	if ($depth == 0) {
 		die "One '*' is needed for glob: '$glob'\n";
 	}
-	$re =~ s!^(.*)\*(.*)$!\(\[^/\]+\)!g;
-	my ($left, $right) = ($1, $2);
-	$re = quotemeta($left) . $re . quotemeta($right);
+	$re =~ s!\*!\[^/\]*!g;
+#	$re =~ s!\?!\[^/\]!g;
+	$re = quotemeta($left) . "($re)" . quotemeta($right);
 	if (length $left && !($left =~ s!/+$!!g)) {
 		die "Missing trailing '/' on left side of: '$glob' ($left)\n";
 	}
@@ -4933,7 +4962,7 @@ sub new {
 	}
 	my $left_re = qr/^\/\Q$left\E(\/|$)/;
 	bless { left => $left, right => $right, left_regex => $left_re,
-	        regex => qr/$re/, glob => $glob }, $class;
+	        regex => qr/$re/, glob => $glob, depth => $depth }, $class;
 }
 
 sub full_path {
diff --git a/t/t9108-git-svn-glob.sh b/t/t9108-git-svn-glob.sh
index a6f88bd..bb9df56 100755
--- a/t/t9108-git-svn-glob.sh
+++ b/t/t9108-git-svn-glob.sh
@@ -52,7 +52,8 @@ test_expect_success 'test refspec globbing' '
 	test "`git rev-parse refs/remotes/tags/end~1`" = \
 		"`git rev-parse refs/remotes/branches/start`" &&
 	test "`git rev-parse refs/remotes/branches/start~2`" = \
-		"`git rev-parse refs/remotes/trunk`"
+		"`git rev-parse refs/remotes/trunk`" &&
+	test_must_fail git rev-parse refs/remotes/tags/end@3
 	'
 
 echo try to try > expect.two
@@ -83,8 +84,8 @@ test_expect_success 'test left-hand-side only globbing' '
 	cmp expect.two output.two
 	'
 
-echo "Only one '*' wildcard expansion is supported (got 2): 'branches/*/*'" \
-     > expect.three
+echo "Only one set of wildcard directories" \
+     "(e.g. '*' or '*/*/*') is supported: 'branches/*/t/*'" > expect.three
 echo "" >> expect.three
 
 test_expect_success 'test disallow multi-globs' '
@@ -92,7 +93,7 @@ test_expect_success 'test disallow multi-globs' '
 	git config --add svn-remote.three.fetch \
 	                 trunk:refs/remotes/three/trunk &&
 	git config --add svn-remote.three.branches \
-	                 "branches/*/*:refs/remotes/three/branches/*" &&
+	                 "branches/*/t/*:refs/remotes/three/branches/*" &&
 	git config --add svn-remote.three.tags \
 	                 "tags/*/*:refs/remotes/three/tags/*" &&
 	cd tmp &&
diff --git a/t/t9108-git-svn-multi-glob.sh b/t/t9108-git-svn-multi-glob.sh
new file mode 100755
index 0000000..9fb51d6
--- /dev/null
+++ b/t/t9108-git-svn-multi-glob.sh
@@ -0,0 +1,157 @@
+#!/bin/sh
+# Copyright (c) 2007 Eric Wong
+test_description='git-svn globbing refspecs'
+. ./lib-git-svn.sh
+
+cat > expect.end <<EOF
+the end
+hi
+start a new branch
+initial
+EOF
+
+test_expect_success 'test refspec globbing' '
+	mkdir -p trunk/src/a trunk/src/b trunk/doc &&
+	echo "hello world" > trunk/src/a/readme &&
+	echo "goodbye world" > trunk/src/b/readme &&
+	svn import -m "initial" trunk "$svnrepo"/trunk &&
+	svn co "$svnrepo" tmp &&
+	cd tmp &&
+		mkdir branches branches/v1 tags &&
+		svn add branches tags &&
+		svn cp trunk branches/v1/start &&
+		svn commit -m "start a new branch" &&
+		svn up &&
+		echo "hi" >> branches/v1/start/src/b/readme &&
+		poke branches/v1/start/src/b/readme &&
+		echo "hey" >> branches/v1/start/src/a/readme &&
+		poke branches/v1/start/src/a/readme &&
+		svn commit -m "hi" &&
+		svn up &&
+		svn cp branches/v1/start tags/end &&
+		echo "bye" >> tags/end/src/b/readme &&
+		poke tags/end/src/b/readme &&
+		echo "aye" >> tags/end/src/a/readme &&
+		poke tags/end/src/a/readme &&
+		svn commit -m "the end" &&
+		echo "byebye" >> tags/end/src/b/readme &&
+		poke tags/end/src/b/readme &&
+		svn commit -m "nothing to see here"
+		cd .. &&
+	git config --add svn-remote.svn.url "$svnrepo" &&
+	git config --add svn-remote.svn.fetch \
+	                 "trunk/src/a:refs/remotes/trunk" &&
+	git config --add svn-remote.svn.branches \
+	                 "branches/*/*/src/a:refs/remotes/branches/*/*" &&
+	git config --add svn-remote.svn.tags\
+	                 "tags/*/src/a:refs/remotes/tags/*" &&
+	git-svn multi-fetch &&
+	git log --pretty=oneline refs/remotes/tags/end | \
+	    sed -e "s/^.\{41\}//" > output.end &&
+	cmp expect.end output.end &&
+	test "`git rev-parse refs/remotes/tags/end~1`" = \
+		"`git rev-parse refs/remotes/branches/v1/start`" &&
+	test "`git rev-parse refs/remotes/branches/v1/start~2`" = \
+		"`git rev-parse refs/remotes/trunk`" &&
+	test_must_fail git rev-parse refs/remotes/tags/end@3
+	'
+
+echo try to try > expect.two
+echo nothing to see here >> expect.two
+cat expect.end >> expect.two
+
+test_expect_success 'test left-hand-side only globbing' '
+	git config --add svn-remote.two.url "$svnrepo" &&
+	git config --add svn-remote.two.fetch trunk:refs/remotes/two/trunk &&
+	git config --add svn-remote.two.branches \
+	                 "branches/*/*:refs/remotes/two/branches/*/*" &&
+	git config --add svn-remote.two.tags \
+	                 "tags/*:refs/remotes/two/tags/*" &&
+	cd tmp &&
+		echo "try try" >> tags/end/src/b/readme &&
+		poke tags/end/src/b/readme &&
+		svn commit -m "try to try"
+		cd .. &&
+	git-svn fetch two &&
+	test `git rev-list refs/remotes/two/tags/end | wc -l` -eq 6 &&
+	test `git rev-list refs/remotes/two/branches/v1/start | wc -l` -eq 3 &&
+	test `git rev-parse refs/remotes/two/branches/v1/start~2` = \
+	     `git rev-parse refs/remotes/two/trunk` &&
+	test `git rev-parse refs/remotes/two/tags/end~3` = \
+	     `git rev-parse refs/remotes/two/branches/v1/start` &&
+	git log --pretty=oneline refs/remotes/two/tags/end | \
+	    sed -e "s/^.\{41\}//" > output.two &&
+	cmp expect.two output.two
+	'
+cat > expect.four <<EOF
+adios
+adding more
+Changed 2 in v2/start
+Another versioned branch
+initial
+EOF
+
+test_expect_success 'test another branch' '
+	(
+		cd tmp &&
+		mkdir branches/v2 &&
+		svn add branches/v2 &&
+		svn cp trunk branches/v2/start &&
+		svn commit -m "Another versioned branch" &&
+		svn up &&
+		echo "hello" >> branches/v2/start/src/b/readme &&
+		poke branches/v2/start/src/b/readme &&
+		echo "howdy" >> branches/v2/start/src/a/readme &&
+		poke branches/v2/start/src/a/readme &&
+		svn commit -m "Changed 2 in v2/start" &&
+		svn up &&
+		svn cp branches/v2/start tags/next &&
+		echo "bye" >> tags/next/src/b/readme &&
+		poke tags/next/src/b/readme &&
+		echo "aye" >> tags/next/src/a/readme &&
+		poke tags/next/src/a/readme &&
+		svn commit -m "adding more" &&
+		echo "byebye" >> tags/next/src/b/readme &&
+		poke tags/next/src/b/readme &&
+		svn commit -m "adios"
+	) &&
+	git config --add svn-remote.four.url "$svnrepo" &&
+	git config --add svn-remote.four.fetch trunk:refs/remotes/four/trunk &&
+	git config --add svn-remote.four.branches \
+	                 "branches/*/*:refs/remotes/four/branches/*/*" &&
+	git config --add svn-remote.four.tags \
+	                 "tags/*:refs/remotes/four/tags/*" &&
+	git-svn fetch four &&
+	test `git rev-list refs/remotes/four/tags/next | wc -l` -eq 5 &&
+	test `git rev-list refs/remotes/four/branches/v2/start | wc -l` -eq 3 &&
+	test `git rev-parse refs/remotes/four/branches/v2/start~2` = \
+	     `git rev-parse refs/remotes/four/trunk` &&
+	test `git rev-parse refs/remotes/four/tags/next~2` = \
+	     `git rev-parse refs/remotes/four/branches/v2/start` &&
+	git log --pretty=oneline refs/remotes/four/tags/next | \
+	    sed -e "s/^.\{41\}//" > output.four &&
+	cmp expect.four output.four
+	'
+
+echo "Only one set of wildcard directories" \
+     "(e.g. '*' or '*/*/*') is supported: 'branches/*/t/*'" > expect.three
+echo "" >> expect.three
+
+test_expect_success 'test disallow multiple globs' '
+	git config --add svn-remote.three.url "$svnrepo" &&
+	git config --add svn-remote.three.fetch \
+	                 trunk:refs/remotes/three/trunk &&
+	git config --add svn-remote.three.branches \
+	                 "branches/*/t/*:refs/remotes/three/branches/*/*" &&
+	git config --add svn-remote.three.tags \
+	                 "tags/*:refs/remotes/three/tags/*" &&
+	cd tmp &&
+		echo "try try" >> tags/end/src/b/readme &&
+		poke tags/end/src/b/readme &&
+		svn commit -m "try to try"
+		cd .. &&
+	test_must_fail git-svn fetch three 2> stderr.three &&
+	cmp expect.three stderr.three
+	'
+
+test_done
diff --git a/t/t9125-git-svn-multi-glob-branch-names.sh b/t/t9125-git-svn-multi-glob-branch-names.sh
new file mode 100755
index 0000000..6b62b52
--- /dev/null
+++ b/t/t9125-git-svn-multi-glob-branch-names.sh
@@ -0,0 +1,37 @@
+#!/bin/sh
+# Copyright (c) 2008 Marcus Griep
+
+test_description='git-svn multi-glob branch names'
+. ./lib-git-svn.sh
+
+test_expect_success 'setup svnrepo' '
+	mkdir project project/trunk project/branches \
+			project/branches/v14.1 project/tags &&
+	echo foo > project/trunk/foo &&
+	svn import -m "$test_description" project "$svnrepo/project" &&
+	rm -rf project &&
+	svn cp -m "fun" "$svnrepo/project/trunk" \
+	                "$svnrepo/project/branches/v14.1/beta" &&
+	svn cp -m "more fun!" "$svnrepo/project/branches/v14.1/beta" \
+	                      "$svnrepo/project/branches/v14.1/gold"
+	'
+
+test_expect_success 'test clone with multi-glob in branch names' '
+	git svn clone -T trunk -b branches/*/* -t tags \
+	              "$svnrepo/project" project &&
+	cd project &&
+		git rev-parse "refs/remotes/v14.1/beta" &&
+		git rev-parse "refs/remotes/v14.1/gold" &&
+	cd ..
+	'
+
+test_expect_success 'test dcommit to multi-globbed branch' "
+	cd project &&
+	git reset --hard 'refs/remotes/v14.1/gold' &&
+	echo hello >> foo &&
+	git commit -m 'hello' -- foo &&
+	git svn dcommit &&
+	cd ..
+	"
+
+test_done
-- 
1.6.0.rc2.4.g0643f

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 3/3] git-svn: wrap long lines in a few places
  2008-08-08  8:40     ` [PATCH v2 0/2] git-svn multi-glob fix and extension Eric Wong
  2008-08-08  8:41       ` [PATCH 1/3] Fix multi-glob assertion in git-svn Eric Wong
  2008-08-08  8:41       ` [PATCH 2/3] git-svn: Allow deep branch names by supporting multi-globs Eric Wong
@ 2008-08-08  8:41       ` Eric Wong
  2008-08-08  8:56       ` [PATCH 1/3] Fix multi-glob assertion in git-svn Eric Wong
  2008-08-08  8:57       ` [PATCH 2/3] git-svn: Allow deep branch names by supporting multi-globs Eric Wong
  4 siblings, 0 replies; 14+ messages in thread
From: Eric Wong @ 2008-08-08  8:41 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, Marcus Griep, Eric Wong

Oops, I let a few patches slip by with long lines in them.
Extracted from an unrelated patch by: Marcus Griep <marcus@griep.us>

Signed-off-by: Eric Wong <normalperson@yhbt.net>
---
 git-svn.perl |    7 +++++--
 1 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/git-svn.perl b/git-svn.perl
index 47ad378..d7a884d 100755
--- a/git-svn.perl
+++ b/git-svn.perl
@@ -171,7 +171,8 @@ my %cmd = (
 			  'color' => \$Git::SVN::Log::color,
 			  'pager=s' => \$Git::SVN::Log::pager
 			} ],
-	'find-rev' => [ \&cmd_find_rev, "Translate between SVN revision numbers and tree-ish",
+	'find-rev' => [ \&cmd_find_rev,
+	                "Translate between SVN revision numbers and tree-ish",
 			{} ],
 	'rebase' => [ \&cmd_rebase, "Fetch and rebase your working directory",
 			{ 'merge|m|M' => \$_merge,
@@ -231,7 +232,9 @@ unless ($cmd && $cmd =~ /(?:clone|init|multi-init)$/) {
 my %opts = %{$cmd{$cmd}->[2]} if (defined $cmd);
 
 read_repo_config(\%opts);
-Getopt::Long::Configure('pass_through') if ($cmd && ($cmd eq 'log' || $cmd eq 'blame'));
+if ($cmd && ($cmd eq 'log' || $cmd eq 'blame')) {
+	Getopt::Long::Configure('pass_through');
+}
 my $rv = GetOptions(%opts, 'help|H|h' => \$_help, 'version|V' => \$_version,
                     'minimize-connections' => \$Git::SVN::Migration::_minimize,
                     'id|i=s' => \$Git::SVN::default_ref_id,
-- 
1.6.0.rc2.4.g0643f

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 1/3] Fix multi-glob assertion in git-svn
  2008-08-08  8:40     ` [PATCH v2 0/2] git-svn multi-glob fix and extension Eric Wong
                         ` (2 preceding siblings ...)
  2008-08-08  8:41       ` [PATCH 3/3] git-svn: wrap long lines in a few places Eric Wong
@ 2008-08-08  8:56       ` Eric Wong
  2008-08-08  8:57       ` [PATCH 2/3] git-svn: Allow deep branch names by supporting multi-globs Eric Wong
  4 siblings, 0 replies; 14+ messages in thread
From: Eric Wong @ 2008-08-08  8:56 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Git Mailing List, Marcus Griep

From: Marcus Griep <marcus@griep.us>
Date: Thu, 7 Aug 2008 11:34:01 -0400
Subject: [PATCH 1/3] Fix multi-glob assertion in git-svn

Fixes bad regex match check for multiple globs (would always return
one glob regardless of actual number).

[ew: fixed a bashism in the test and some minor line-wrapping]

Signed-off-by: Marcus Griep <marcus@griep.us>
Acked-by: Eric Wong <normalperson@yhbt.net>
---

 Oops, resent as I forgot to change the From: header

 git-svn.perl            |    5 +++--
 t/t9108-git-svn-glob.sh |   21 +++++++++++++++++++++
 2 files changed, 24 insertions(+), 2 deletions(-)

diff --git a/git-svn.perl b/git-svn.perl
index 06a82c8..503a7c9 100755
--- a/git-svn.perl
+++ b/git-svn.perl
@@ -4915,14 +4915,15 @@ sub new {
 	my ($class, $glob) = @_;
 	my $re = $glob;
 	$re =~ s!/+$!!g; # no need for trailing slashes
-	my $nr = ($re =~ s!^(.*)\*(.*)$!\(\[^/\]+\)!g);
-	my ($left, $right) = ($1, $2);
+	my $nr = $re =~ tr/*/*/;
 	if ($nr > 1) {
 		die "Only one '*' wildcard expansion ",
 		    "is supported (got $nr): '$glob'\n";
 	} elsif ($nr == 0) {
 		die "One '*' is needed for glob: '$glob'\n";
 	}
+	$re =~ s!^(.*)\*(.*)$!\(\[^/\]+\)!g;
+	my ($left, $right) = ($1, $2);
 	$re = quotemeta($left) . $re . quotemeta($right);
 	if (length $left && !($left =~ s!/+$!!g)) {
 		die "Missing trailing '/' on left side of: '$glob' ($left)\n";
diff --git a/t/t9108-git-svn-glob.sh b/t/t9108-git-svn-glob.sh
index f6f71d0..a6f88bd 100755
--- a/t/t9108-git-svn-glob.sh
+++ b/t/t9108-git-svn-glob.sh
@@ -83,4 +83,25 @@ test_expect_success 'test left-hand-side only globbing' '
 	cmp expect.two output.two
 	'
 
+echo "Only one '*' wildcard expansion is supported (got 2): 'branches/*/*'" \
+     > expect.three
+echo "" >> expect.three
+
+test_expect_success 'test disallow multi-globs' '
+	git config --add svn-remote.three.url "$svnrepo" &&
+	git config --add svn-remote.three.fetch \
+	                 trunk:refs/remotes/three/trunk &&
+	git config --add svn-remote.three.branches \
+	                 "branches/*/*:refs/remotes/three/branches/*" &&
+	git config --add svn-remote.three.tags \
+	                 "tags/*/*:refs/remotes/three/tags/*" &&
+	cd tmp &&
+		echo "try try" >> tags/end/src/b/readme &&
+		poke tags/end/src/b/readme &&
+		svn commit -m "try to try"
+		cd .. &&
+	test_must_fail git-svn fetch three 2> stderr.three &&
+	cmp expect.three stderr.three
+	'
+
 test_done
-- 
1.6.0.rc2.4.g0643f

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 2/3] git-svn: Allow deep branch names by supporting multi-globs
  2008-08-08  8:40     ` [PATCH v2 0/2] git-svn multi-glob fix and extension Eric Wong
                         ` (3 preceding siblings ...)
  2008-08-08  8:56       ` [PATCH 1/3] Fix multi-glob assertion in git-svn Eric Wong
@ 2008-08-08  8:57       ` Eric Wong
  4 siblings, 0 replies; 14+ messages in thread
From: Eric Wong @ 2008-08-08  8:57 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Git Mailing List, Marcus Griep

From: Marcus Griep <marcus@griep.us>
Date: Thu, 7 Aug 2008 11:34:02 -0400
Subject: [PATCH 2/3] git-svn: Allow deep branch names by supporting multi-globs

Some repositories use a deep branching strategy, such as:
branches/1.0/1.0.rc1
branches/1.0/1.0.rc2
branches/1.0/1.0.rtm
branches/1.0/1.0.gold

Only allowing a single glob stiffles this.

This change allows for a single glob 'set' to accept this deep
branching strategy.

The ref glob depth must match the branch glob depth.  When using
the -b or -t options for init or clone, this is automatically
done.

For example, using the above branches:
  svn-remote.svn.branches = branches/*/*:refs/remote/*/*
gives the following branch names:
  1.0/1.0.rc1
  1.0/1.0.rc2
  1.0/1.0.rtm
  1.0/1.0.gold

[ew:
  * removed unrelated line-wrapping changes
  * fixed line-wrapping in a few more places
  * removed trailing whitespace
  * fixed bashism in test
  * removed unnecessary httpd startup in test
  * changed copyright on tests to 2008 Marcus Griep
  * added executable permissions to new tests
]

Signed-off-by: Marcus Griep <marcus@griep.us>
Acked-by: Eric Wong <normalperson@yhbt.net>
---
 Oops, resent as I forgot to change the From: header

 git-svn.perl                               |   61 ++++++++---
 t/t9108-git-svn-glob.sh                    |    9 +-
 t/t9108-git-svn-multi-glob.sh              |  157 ++++++++++++++++++++++++++++
 t/t9125-git-svn-multi-glob-branch-names.sh |   37 +++++++
 4 files changed, 244 insertions(+), 20 deletions(-)
 create mode 100755 t/t9108-git-svn-multi-glob.sh
 create mode 100755 t/t9125-git-svn-multi-glob-branch-names.sh

diff --git a/git-svn.perl b/git-svn.perl
index 503a7c9..47ad378 100755
--- a/git-svn.perl
+++ b/git-svn.perl
@@ -987,8 +987,10 @@ sub complete_url_ls_init {
 	if (length $pfx && $pfx !~ m#/$#) {
 		die "--prefix='$pfx' must have a trailing slash '/'\n";
 	}
-	command_noisy('config', "svn-remote.$gs->{repo_id}.$n",
-				"$remote_path:refs/remotes/$pfx*");
+	command_noisy('config',
+	              "svn-remote.$gs->{repo_id}.$n",
+	              "$remote_path:refs/remotes/$pfx*" .
+	                ('/*' x (($remote_path =~ tr/*/*/) - 1)) );
 }
 
 sub verify_ref {
@@ -4124,16 +4126,38 @@ sub gs_fetch_loop_common {
 	Git::SVN::gc();
 }
 
+sub get_dir_globbed {
+	my ($self, $left, $depth, $r) = @_;
+
+	my @x = eval { $self->get_dir($left, $r) };
+	return unless scalar @x == 3;
+	my $dirents = $x[0];
+	my @finalents;
+	foreach my $de (keys %$dirents) {
+		next if $dirents->{$de}->{kind} != $SVN::Node::dir;
+		if ($depth > 1) {
+			my @args = ("$left/$de", $depth - 1, $r);
+			foreach my $dir ($self->get_dir_globbed(@args)) {
+				push @finalents, "$de/$dir";
+			}
+		} else {
+			push @finalents, $de;
+		}
+	}
+	@finalents;
+}
+
 sub match_globs {
 	my ($self, $exists, $paths, $globs, $r) = @_;
 
 	sub get_dir_check {
 		my ($self, $exists, $g, $r) = @_;
-		my @x = eval { $self->get_dir($g->{path}->{left}, $r) };
-		return unless scalar @x == 3;
-		my $dirents = $x[0];
-		foreach my $de (keys %$dirents) {
-			next if $dirents->{$de}->{kind} != $SVN::Node::dir;
+
+		my @dirs = $self->get_dir_globbed($g->{path}->{left},
+		                                  $g->{path}->{depth},
+		                                  $r);
+
+		foreach my $de (@dirs) {
 			my $p = $g->{path}->full_path($de);
 			next if $exists->{$p};
 			next if (length $g->{path}->{right} &&
@@ -4915,16 +4939,21 @@ sub new {
 	my ($class, $glob) = @_;
 	my $re = $glob;
 	$re =~ s!/+$!!g; # no need for trailing slashes
-	my $nr = $re =~ tr/*/*/;
-	if ($nr > 1) {
-		die "Only one '*' wildcard expansion ",
-		    "is supported (got $nr): '$glob'\n";
-	} elsif ($nr == 0) {
+	$re =~ m!^([^*]*)(\*(?:/\*)*)([^*]*)$!;
+	my $temp = $re;
+	my ($left, $right) = ($1, $3);
+	$re = $2;
+	my $depth = $re =~ tr/*/*/;
+	if ($depth != $temp =~ tr/*/*/) {
+		die "Only one set of wildcard directories " .
+			"(e.g. '*' or '*/*/*') is supported: '$glob'\n";
+	}
+	if ($depth == 0) {
 		die "One '*' is needed for glob: '$glob'\n";
 	}
-	$re =~ s!^(.*)\*(.*)$!\(\[^/\]+\)!g;
-	my ($left, $right) = ($1, $2);
-	$re = quotemeta($left) . $re . quotemeta($right);
+	$re =~ s!\*!\[^/\]*!g;
+#	$re =~ s!\?!\[^/\]!g;
+	$re = quotemeta($left) . "($re)" . quotemeta($right);
 	if (length $left && !($left =~ s!/+$!!g)) {
 		die "Missing trailing '/' on left side of: '$glob' ($left)\n";
 	}
@@ -4933,7 +4962,7 @@ sub new {
 	}
 	my $left_re = qr/^\/\Q$left\E(\/|$)/;
 	bless { left => $left, right => $right, left_regex => $left_re,
-	        regex => qr/$re/, glob => $glob }, $class;
+	        regex => qr/$re/, glob => $glob, depth => $depth }, $class;
 }
 
 sub full_path {
diff --git a/t/t9108-git-svn-glob.sh b/t/t9108-git-svn-glob.sh
index a6f88bd..bb9df56 100755
--- a/t/t9108-git-svn-glob.sh
+++ b/t/t9108-git-svn-glob.sh
@@ -52,7 +52,8 @@ test_expect_success 'test refspec globbing' '
 	test "`git rev-parse refs/remotes/tags/end~1`" = \
 		"`git rev-parse refs/remotes/branches/start`" &&
 	test "`git rev-parse refs/remotes/branches/start~2`" = \
-		"`git rev-parse refs/remotes/trunk`"
+		"`git rev-parse refs/remotes/trunk`" &&
+	test_must_fail git rev-parse refs/remotes/tags/end@3
 	'
 
 echo try to try > expect.two
@@ -83,8 +84,8 @@ test_expect_success 'test left-hand-side only globbing' '
 	cmp expect.two output.two
 	'
 
-echo "Only one '*' wildcard expansion is supported (got 2): 'branches/*/*'" \
-     > expect.three
+echo "Only one set of wildcard directories" \
+     "(e.g. '*' or '*/*/*') is supported: 'branches/*/t/*'" > expect.three
 echo "" >> expect.three
 
 test_expect_success 'test disallow multi-globs' '
@@ -92,7 +93,7 @@ test_expect_success 'test disallow multi-globs' '
 	git config --add svn-remote.three.fetch \
 	                 trunk:refs/remotes/three/trunk &&
 	git config --add svn-remote.three.branches \
-	                 "branches/*/*:refs/remotes/three/branches/*" &&
+	                 "branches/*/t/*:refs/remotes/three/branches/*" &&
 	git config --add svn-remote.three.tags \
 	                 "tags/*/*:refs/remotes/three/tags/*" &&
 	cd tmp &&
diff --git a/t/t9108-git-svn-multi-glob.sh b/t/t9108-git-svn-multi-glob.sh
new file mode 100755
index 0000000..9fb51d6
--- /dev/null
+++ b/t/t9108-git-svn-multi-glob.sh
@@ -0,0 +1,157 @@
+#!/bin/sh
+# Copyright (c) 2007 Eric Wong
+test_description='git-svn globbing refspecs'
+. ./lib-git-svn.sh
+
+cat > expect.end <<EOF
+the end
+hi
+start a new branch
+initial
+EOF
+
+test_expect_success 'test refspec globbing' '
+	mkdir -p trunk/src/a trunk/src/b trunk/doc &&
+	echo "hello world" > trunk/src/a/readme &&
+	echo "goodbye world" > trunk/src/b/readme &&
+	svn import -m "initial" trunk "$svnrepo"/trunk &&
+	svn co "$svnrepo" tmp &&
+	cd tmp &&
+		mkdir branches branches/v1 tags &&
+		svn add branches tags &&
+		svn cp trunk branches/v1/start &&
+		svn commit -m "start a new branch" &&
+		svn up &&
+		echo "hi" >> branches/v1/start/src/b/readme &&
+		poke branches/v1/start/src/b/readme &&
+		echo "hey" >> branches/v1/start/src/a/readme &&
+		poke branches/v1/start/src/a/readme &&
+		svn commit -m "hi" &&
+		svn up &&
+		svn cp branches/v1/start tags/end &&
+		echo "bye" >> tags/end/src/b/readme &&
+		poke tags/end/src/b/readme &&
+		echo "aye" >> tags/end/src/a/readme &&
+		poke tags/end/src/a/readme &&
+		svn commit -m "the end" &&
+		echo "byebye" >> tags/end/src/b/readme &&
+		poke tags/end/src/b/readme &&
+		svn commit -m "nothing to see here"
+		cd .. &&
+	git config --add svn-remote.svn.url "$svnrepo" &&
+	git config --add svn-remote.svn.fetch \
+	                 "trunk/src/a:refs/remotes/trunk" &&
+	git config --add svn-remote.svn.branches \
+	                 "branches/*/*/src/a:refs/remotes/branches/*/*" &&
+	git config --add svn-remote.svn.tags\
+	                 "tags/*/src/a:refs/remotes/tags/*" &&
+	git-svn multi-fetch &&
+	git log --pretty=oneline refs/remotes/tags/end | \
+	    sed -e "s/^.\{41\}//" > output.end &&
+	cmp expect.end output.end &&
+	test "`git rev-parse refs/remotes/tags/end~1`" = \
+		"`git rev-parse refs/remotes/branches/v1/start`" &&
+	test "`git rev-parse refs/remotes/branches/v1/start~2`" = \
+		"`git rev-parse refs/remotes/trunk`" &&
+	test_must_fail git rev-parse refs/remotes/tags/end@3
+	'
+
+echo try to try > expect.two
+echo nothing to see here >> expect.two
+cat expect.end >> expect.two
+
+test_expect_success 'test left-hand-side only globbing' '
+	git config --add svn-remote.two.url "$svnrepo" &&
+	git config --add svn-remote.two.fetch trunk:refs/remotes/two/trunk &&
+	git config --add svn-remote.two.branches \
+	                 "branches/*/*:refs/remotes/two/branches/*/*" &&
+	git config --add svn-remote.two.tags \
+	                 "tags/*:refs/remotes/two/tags/*" &&
+	cd tmp &&
+		echo "try try" >> tags/end/src/b/readme &&
+		poke tags/end/src/b/readme &&
+		svn commit -m "try to try"
+		cd .. &&
+	git-svn fetch two &&
+	test `git rev-list refs/remotes/two/tags/end | wc -l` -eq 6 &&
+	test `git rev-list refs/remotes/two/branches/v1/start | wc -l` -eq 3 &&
+	test `git rev-parse refs/remotes/two/branches/v1/start~2` = \
+	     `git rev-parse refs/remotes/two/trunk` &&
+	test `git rev-parse refs/remotes/two/tags/end~3` = \
+	     `git rev-parse refs/remotes/two/branches/v1/start` &&
+	git log --pretty=oneline refs/remotes/two/tags/end | \
+	    sed -e "s/^.\{41\}//" > output.two &&
+	cmp expect.two output.two
+	'
+cat > expect.four <<EOF
+adios
+adding more
+Changed 2 in v2/start
+Another versioned branch
+initial
+EOF
+
+test_expect_success 'test another branch' '
+	(
+		cd tmp &&
+		mkdir branches/v2 &&
+		svn add branches/v2 &&
+		svn cp trunk branches/v2/start &&
+		svn commit -m "Another versioned branch" &&
+		svn up &&
+		echo "hello" >> branches/v2/start/src/b/readme &&
+		poke branches/v2/start/src/b/readme &&
+		echo "howdy" >> branches/v2/start/src/a/readme &&
+		poke branches/v2/start/src/a/readme &&
+		svn commit -m "Changed 2 in v2/start" &&
+		svn up &&
+		svn cp branches/v2/start tags/next &&
+		echo "bye" >> tags/next/src/b/readme &&
+		poke tags/next/src/b/readme &&
+		echo "aye" >> tags/next/src/a/readme &&
+		poke tags/next/src/a/readme &&
+		svn commit -m "adding more" &&
+		echo "byebye" >> tags/next/src/b/readme &&
+		poke tags/next/src/b/readme &&
+		svn commit -m "adios"
+	) &&
+	git config --add svn-remote.four.url "$svnrepo" &&
+	git config --add svn-remote.four.fetch trunk:refs/remotes/four/trunk &&
+	git config --add svn-remote.four.branches \
+	                 "branches/*/*:refs/remotes/four/branches/*/*" &&
+	git config --add svn-remote.four.tags \
+	                 "tags/*:refs/remotes/four/tags/*" &&
+	git-svn fetch four &&
+	test `git rev-list refs/remotes/four/tags/next | wc -l` -eq 5 &&
+	test `git rev-list refs/remotes/four/branches/v2/start | wc -l` -eq 3 &&
+	test `git rev-parse refs/remotes/four/branches/v2/start~2` = \
+	     `git rev-parse refs/remotes/four/trunk` &&
+	test `git rev-parse refs/remotes/four/tags/next~2` = \
+	     `git rev-parse refs/remotes/four/branches/v2/start` &&
+	git log --pretty=oneline refs/remotes/four/tags/next | \
+	    sed -e "s/^.\{41\}//" > output.four &&
+	cmp expect.four output.four
+	'
+
+echo "Only one set of wildcard directories" \
+     "(e.g. '*' or '*/*/*') is supported: 'branches/*/t/*'" > expect.three
+echo "" >> expect.three
+
+test_expect_success 'test disallow multiple globs' '
+	git config --add svn-remote.three.url "$svnrepo" &&
+	git config --add svn-remote.three.fetch \
+	                 trunk:refs/remotes/three/trunk &&
+	git config --add svn-remote.three.branches \
+	                 "branches/*/t/*:refs/remotes/three/branches/*/*" &&
+	git config --add svn-remote.three.tags \
+	                 "tags/*:refs/remotes/three/tags/*" &&
+	cd tmp &&
+		echo "try try" >> tags/end/src/b/readme &&
+		poke tags/end/src/b/readme &&
+		svn commit -m "try to try"
+		cd .. &&
+	test_must_fail git-svn fetch three 2> stderr.three &&
+	cmp expect.three stderr.three
+	'
+
+test_done
diff --git a/t/t9125-git-svn-multi-glob-branch-names.sh b/t/t9125-git-svn-multi-glob-branch-names.sh
new file mode 100755
index 0000000..6b62b52
--- /dev/null
+++ b/t/t9125-git-svn-multi-glob-branch-names.sh
@@ -0,0 +1,37 @@
+#!/bin/sh
+# Copyright (c) 2008 Marcus Griep
+
+test_description='git-svn multi-glob branch names'
+. ./lib-git-svn.sh
+
+test_expect_success 'setup svnrepo' '
+	mkdir project project/trunk project/branches \
+			project/branches/v14.1 project/tags &&
+	echo foo > project/trunk/foo &&
+	svn import -m "$test_description" project "$svnrepo/project" &&
+	rm -rf project &&
+	svn cp -m "fun" "$svnrepo/project/trunk" \
+	                "$svnrepo/project/branches/v14.1/beta" &&
+	svn cp -m "more fun!" "$svnrepo/project/branches/v14.1/beta" \
+	                      "$svnrepo/project/branches/v14.1/gold"
+	'
+
+test_expect_success 'test clone with multi-glob in branch names' '
+	git svn clone -T trunk -b branches/*/* -t tags \
+	              "$svnrepo/project" project &&
+	cd project &&
+		git rev-parse "refs/remotes/v14.1/beta" &&
+		git rev-parse "refs/remotes/v14.1/gold" &&
+	cd ..
+	'
+
+test_expect_success 'test dcommit to multi-globbed branch' "
+	cd project &&
+	git reset --hard 'refs/remotes/v14.1/gold' &&
+	echo hello >> foo &&
+	git commit -m 'hello' -- foo &&
+	git svn dcommit &&
+	cd ..
+	"
+
+test_done
-- 
1.6.0.rc2.4.g0643f

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [PATCH 1/3] Fix multi-glob assertion in git-svn
  2008-08-08  8:41       ` [PATCH 1/3] Fix multi-glob assertion in git-svn Eric Wong
@ 2008-08-08  9:41         ` Junio C Hamano
  2008-08-09  7:28           ` Eric Wong
  0 siblings, 1 reply; 14+ messages in thread
From: Junio C Hamano @ 2008-08-08  9:41 UTC (permalink / raw)
  To: Eric Wong; +Cc: git, Marcus Griep

Eric Wong <normalperson@yhbt.net> writes:

> From: Marcus Griep <marcus@griep.us>
>
> Fixes bad regex match check for multiple globs (would always return
> one glob regardless of actual number).
>
> [ew: fixed a bashism in the test and some minor line-wrapping]

Thanks both.

> +test_expect_success 'test disallow multi-globs' '
> ...
> +	cd tmp &&
> +		echo "try try" >> tags/end/src/b/readme &&
> +		poke tags/end/src/b/readme &&
> +		svn commit -m "try to try"
> +		cd .. &&

Do you want to ignore exit code from 'svn commit -m' here?

In any case, I'd want to see "temporarily work in subdirectory" done in a
subshell when applicable, so that we won't have to worry about where we
are when we later add more tests, like this:

	(
        	cd tmp &&
                echo "try try" >>tags/end/src/b/readme &&
                poke tags/end/src/b/readme &&
                svn commit -m "try to try" &&
	) &&

> +	test_must_fail git-svn fetch three 2> stderr.three &&
> +	cmp expect.three stderr.three

s/cmp/test_cmp/;

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 1/3] Fix multi-glob assertion in git-svn
  2008-08-08  9:41         ` Junio C Hamano
@ 2008-08-09  7:28           ` Eric Wong
  2008-08-09  7:48             ` Junio C Hamano
  0 siblings, 1 reply; 14+ messages in thread
From: Eric Wong @ 2008-08-09  7:28 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, Marcus Griep

Junio C Hamano <gitster@pobox.com> wrote:
> Eric Wong <normalperson@yhbt.net> writes:
> 
> > From: Marcus Griep <marcus@griep.us>
> >
> > Fixes bad regex match check for multiple globs (would always return
> > one glob regardless of actual number).
> >
> > [ew: fixed a bashism in the test and some minor line-wrapping]
> 
> Thanks both.
> 
> > +test_expect_success 'test disallow multi-globs' '
> > ...
> > +	cd tmp &&
> > +		echo "try try" >> tags/end/src/b/readme &&
> > +		poke tags/end/src/b/readme &&
> > +		svn commit -m "try to try"
> > +		cd .. &&
> 
> Do you want to ignore exit code from 'svn commit -m' here?

Oops, no missed that.

> In any case, I'd want to see "temporarily work in subdirectory" done in a
> subshell when applicable, so that we won't have to worry about where we
> are when we later add more tests, like this:
> 
> 	(
>         	cd tmp &&
>                 echo "try try" >>tags/end/src/b/readme &&
>                 poke tags/end/src/b/readme &&
>                 svn commit -m "try to try" &&
> 	) &&

Yes, that's a good idea

> > +	test_must_fail git-svn fetch three 2> stderr.three &&
> > +	cmp expect.three stderr.three
> 
> s/cmp/test_cmp/;

Noted.

Shall I make those changes and resubmit or are they simple enough
for you to do?

-- 
Eric Wong

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 1/3] Fix multi-glob assertion in git-svn
  2008-08-09  7:28           ` Eric Wong
@ 2008-08-09  7:48             ` Junio C Hamano
  0 siblings, 0 replies; 14+ messages in thread
From: Junio C Hamano @ 2008-08-09  7:48 UTC (permalink / raw)
  To: Eric Wong; +Cc: git, Marcus Griep

Eric Wong <normalperson@yhbt.net> writes:

> Shall I make those changes and resubmit or are they simple enough
> for you to do?

I've already queued them with fixups.  Thanks.

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2008-08-09  7:49 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-08-06 19:58 [PATCH 2/2] git-svn: Allow deep branch names by supporting multi-globs Marcus Griep
2008-08-07  9:00 ` Eric Wong
2008-08-07 15:34   ` [PATCH v2 0/2] git-svn multi-glob fix and extension Marcus Griep
2008-08-07 15:34     ` [PATCH v2 1/2] Fix multi-glob assertion in git-svn Marcus Griep
2008-08-07 15:34       ` [PATCH v2 2/2] git-svn: Allow deep branch names by supporting multi-globs Marcus Griep
2008-08-08  8:40     ` [PATCH v2 0/2] git-svn multi-glob fix and extension Eric Wong
2008-08-08  8:41       ` [PATCH 1/3] Fix multi-glob assertion in git-svn Eric Wong
2008-08-08  9:41         ` Junio C Hamano
2008-08-09  7:28           ` Eric Wong
2008-08-09  7:48             ` Junio C Hamano
2008-08-08  8:41       ` [PATCH 2/3] git-svn: Allow deep branch names by supporting multi-globs Eric Wong
2008-08-08  8:41       ` [PATCH 3/3] git-svn: wrap long lines in a few places Eric Wong
2008-08-08  8:56       ` [PATCH 1/3] Fix multi-glob assertion in git-svn Eric Wong
2008-08-08  8:57       ` [PATCH 2/3] git-svn: Allow deep branch names by supporting multi-globs Eric Wong

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).