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