All of lore.kernel.org
 help / color / mirror / Atom feed
From: Marcus Griep <marcus@griep.us>
To: Git Mailing List <git@vger.kernel.org>
Cc: Eric Wong <normalperson@yhbt.net>
Subject: [PATCH 2/2] git-svn: Allow deep branch names by supporting multi-globs
Date: Wed, 06 Aug 2008 15:58:20 -0400	[thread overview]
Message-ID: <489A025C.50507@griep.us> (raw)

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
את.ψο´

             reply	other threads:[~2008-08-06 19:59 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-08-06 19:58 Marcus Griep [this message]
2008-08-07  9:00 ` [PATCH 2/2] git-svn: Allow deep branch names by supporting multi-globs 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

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=489A025C.50507@griep.us \
    --to=marcus@griep.us \
    --cc=git@vger.kernel.org \
    --cc=normalperson@yhbt.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.