git-svn: allow subset of branches/tags to be specified in glob spec
For very large projects it is useful to be able to clone a subset of the upstream SVN repo's branches. Allow for this by letting the left-side of the branches and tags glob specs contain a brace-delineated comma-separated list of names. e.g.: branches = branches/{red,green}/src:refs/remotes/branches/* Signed-off-by: Jay Soffian <jaysoffian@gmail.com> Acked-by: Eric Wong <normalperson@yhbt.net>
Jay Soffian committed
Jan 23, 2010 at 03:30 UTC
075762085c6668f11c4ea165ecec17f69245ef09
4 files changed
+320
-20
Documentation/git-svn.txt
+16
@@ -838,6 +838,22 @@ independent path component (surrounded by '/' or EOL). This
838
type of configuration is not automatically created by 'init' and
839
should be manually entered with a text-editor or using 'git config'.
840
841
+It is also possible to fetch a subset of branches or tags by using a
842
+comma-separated list of names within braces. For example:
843
+
844
+------------------------------------------------------------------------
845
+[svn-remote "huge-project"]
846
+ url = http://server.org/svn
847
+ fetch = trunk/src:refs/remotes/trunk
848
+ branches = branches/{red,green}/src:refs/remotes/branches/*
849
+ tags = tags/{1.0,2.0}/src:refs/remotes/tags/*
850
+------------------------------------------------------------------------
851
+
852
+Note that git-svn keeps track of the highest revision in which a branch
853
+or tag has appeared. If the subset of branches or tags is changed after
854
+fetching, then .git/svn/.metadata must be manually edited to remove (or
855
+reset) branches-maxRev and/or tags-maxRev as appropriate.
856
+
857
SEE ALSO
858
--------
859
linkgit:git-rebase[1]
git-svn.perl
+40
-20
@@ -1825,8 +1825,8 @@ sub read_all_remotes {
1825
my $rs = {
1826
t => $t,
1827
remote => $remote,
1828
- path => Git::SVN::GlobSpec->new($local_ref),
1829
- ref => Git::SVN::GlobSpec->new($remote_ref) };
1828
+ path => Git::SVN::GlobSpec->new($local_ref, 1),
1829
+ ref => Git::SVN::GlobSpec->new($remote_ref, 0) };
1830
if (length($rs->{ref}->{right}) != 0) {
1831
die "The '*' glob character must be the last ",
1832
"character of '$remote_ref'\n";
@@ -5233,6 +5233,7 @@ sub match_globs {
5233
next if (length $g->{path}->{right} &&
5234
($self->check_path($p, $r) !=
5235
$SVN::Node::dir));
5236
+ next unless $p =~ /$g->{path}->{regex}/;
5237
$exists->{$p} = Git::SVN->init($self->{url}, $p, undef,
5238
$g->{ref}->full_path($de), 1);
5239
}
@@ -6006,29 +6007,48 @@ use strict;
6007
use warnings;
6008
6009
sub new {
6009
- my ($class, $glob) = @_;
6010
+ my ($class, $glob, $pattern_ok) = @_;
6011
my $re = $glob;
6012
$re =~ s!/+$!!g; # no need for trailing slashes
6012
- $re =~ m!^([^*]*)(\*(?:/\*)*)(.*)$!;
6013
- my $temp = $re;
6014
- my ($left, $right) = ($1, $3);
6015
- $re = $2;
6016
- my $depth = $re =~ tr/*/*/;
6017
- if ($depth != $temp =~ tr/*/*/) {
6018
- die "Only one set of wildcard directories " .
6019
- "(e.g. '*' or '*/*/*') is supported: '$glob'\n";
6013
+ my (@left, @right, @patterns);
6014
+ my $state = "left";
6015
+ my $die_msg = "Only one set of wildcard directories " .
6016
+ "(e.g. '*' or '*/*/*') is supported: '$glob'\n";
6017
+ for my $part (split(m|/|, $glob)) {
6018
+ if ($part =~ /\*/ && $part ne "*") {
6019
+ die "Invalid pattern in '$glob': $part\n";
6020
+ } elsif ($pattern_ok && $part =~ /[{}]/ &&
6021
+ $part !~ /^\{[^{}]+\}/) {
6022
+ die "Invalid pattern in '$glob': $part\n";
6023
+ }
6024
+ if ($part eq "*") {
6025
+ die $die_msg if $state eq "right";
6026
+ $state = "pattern";
6027
+ push(@patterns, "[^/]*");
6028
+ } elsif ($pattern_ok && $part =~ /^\{(.*)\}$/) {
6029
+ die $die_msg if $state eq "right";
6030
+ $state = "pattern";
6031
+ my $p = quotemeta($1);
6032
+ $p =~ s/\\,/|/g;
6033
+ push(@patterns, "(?:$p)");
6034
+ } else {
6035
+ if ($state eq "left") {
6036
+ push(@left, $part);
6037
+ } else {
6038
+ push(@right, $part);
6039
+ $state = "right";
6040
+ }
6041
+ }
6042
}
6043
+ my $depth = @patterns;
6044
if ($depth == 0) {
6022
- die "One '*' is needed for glob: '$glob'\n";
6023
- }
6024
- $re =~ s!\*!\[^/\]*!g;
6025
- $re = quotemeta($left) . "($re)" . quotemeta($right);
6026
- if (length $left && !($left =~ s!/+$!!g)) {
6027
- die "Missing trailing '/' on left side of: '$glob' ($left)\n";
6028
- }
6029
- if (length $right && !($right =~ s!^/+!!g)) {
6030
- die "Missing leading '/' on right side of: '$glob' ($right)\n";
6045
+ die "One '*' is needed in glob: '$glob'\n";
6046
}
6047
+ my $left = join('/', @left);
6048
+ my $right = join('/', @right);
6049
+ $re = join('/', @patterns);
6050
+ $re = join('\/',
6051
+ grep(length, quotemeta($left), "($re)", quotemeta($right)));
6052
my $left_re = qr/^\/\Q$left\E(\/|$)/;
6053
bless { left => $left, right => $right, left_regex => $left_re,
6054
regex => qr/$re/, glob => $glob, depth => $depth }, $class;
t/t9154-git-svn-fancy-glob.sh
new
+42
@@ -0,0 +1,42 @@
1
+#!/bin/sh
2
+#
3
+# Copyright (c) 2010 Jay Soffian
4
+#
5
+
6
+test_description='git svn fancy glob test'
7
+
8
+. ./lib-git-svn.sh
9
+
10
+test_expect_success 'load svn repo' "
11
+ svnadmin load -q '$rawsvnrepo' < '$TEST_DIRECTORY/t9154/svn.dump' &&
12
+ git svn init --minimize-url -T trunk '$svnrepo' &&
13
+ git svn fetch
14
+ "
15
+
16
+test_expect_success 'add red branch' "
17
+ git config svn-remote.svn.branches 'branches/{red}:refs/remotes/*' &&
18
+ git svn fetch &&
19
+ git rev-parse refs/remotes/red &&
20
+ test_must_fail git rev-parse refs/remotes/green &&
21
+ test_must_fail git rev-parse refs/remotes/blue
22
+ "
23
+
24
+test_expect_success 'add green branch' "
25
+ GIT_CONFIG=.git/svn/.metadata git config --unset svn-remote.svn.branches-maxRev &&
26
+ git config svn-remote.svn.branches 'branches/{red,green}:refs/remotes/*' &&
27
+ git svn fetch &&
28
+ git rev-parse refs/remotes/red &&
29
+ git rev-parse refs/remotes/green &&
30
+ test_must_fail git rev-parse refs/remotes/blue
31
+ "
32
+
33
+test_expect_success 'add all branches' "
34
+ GIT_CONFIG=.git/svn/.metadata git config --unset svn-remote.svn.branches-maxRev &&
35
+ git config svn-remote.svn.branches 'branches/*:refs/remotes/*' &&
36
+ git svn fetch &&
37
+ git rev-parse refs/remotes/red &&
38
+ git rev-parse refs/remotes/green &&
39
+ git rev-parse refs/remotes/blue
40
+ "
41
+
42
+test_done
t/t9154/svn.dump
new
+222
@@ -0,0 +1,222 @@
1
+SVN-fs-dump-format-version: 2
2
+
3
+UUID: a18093a0-5f0b-44e0-8d88-8911ac7078db
4
+
5
+Revision-number: 0
6
+Prop-content-length: 56
7
+Content-length: 56
8
+
9
+K 8
10
+svn:date
11
+V 27
12
+2010-01-23T07:40:25.660053Z
13
+PROPS-END
14
+
15
+Revision-number: 1
16
+Prop-content-length: 104
17
+Content-length: 104
18
+
19
+K 7
20
+svn:log
21
+V 7
22
+initial
23
+K 10
24
+svn:author
25
+V 3
26
+jay
27
+K 8
28
+svn:date
29
+V 27
30
+2010-01-23T07:41:33.636365Z
31
+PROPS-END
32
+
33
+Node-path: trunk
34
+Node-kind: dir
35
+Node-action: add
36
+Prop-content-length: 10
37
+Content-length: 10
38
+
39
+PROPS-END
40
+
41
+
42
+Node-path: trunk/foo
43
+Node-kind: file
44
+Node-action: add
45
+Prop-content-length: 10
46
+Text-content-length: 4
47
+Text-content-md5: d3b07384d113edec49eaa6238ad5ff00
48
+Text-content-sha1: f1d2d2f924e986ac86fdf7b36c94bcdf32beec15
49
+Content-length: 14
50
+
51
+PROPS-END
52
+foo
53
+
54
+
55
+Revision-number: 2
56
+Prop-content-length: 110
57
+Content-length: 110
58
+
59
+K 7
60
+svn:log
61
+V 12
62
+add branches
63
+K 10
64
+svn:author
65
+V 3
66
+jay
67
+K 8
68
+svn:date
69
+V 27
70
+2010-01-23T07:42:37.290694Z
71
+PROPS-END
72
+
73
+Node-path: branches
74
+Node-kind: dir
75
+Node-action: add
76
+Prop-content-length: 10
77
+Content-length: 10
78
+
79
+PROPS-END
80
+
81
+
82
+Node-path: branches/blue
83
+Node-kind: dir
84
+Node-action: add
85
+Node-copyfrom-rev: 1
86
+Node-copyfrom-path: trunk
87
+
88
+
89
+Node-path: branches/green
90
+Node-kind: dir
91
+Node-action: add
92
+Node-copyfrom-rev: 1
93
+Node-copyfrom-path: trunk
94
+
95
+
96
+Node-path: branches/red
97
+Node-kind: dir
98
+Node-action: add
99
+Node-copyfrom-rev: 1
100
+Node-copyfrom-path: trunk
101
+
102
+
103
+Revision-number: 3
104
+Prop-content-length: 108
105
+Content-length: 108
106
+
107
+K 7
108
+svn:log
109
+V 10
110
+red change
111
+K 10
112
+svn:author
113
+V 3
114
+jay
115
+K 8
116
+svn:date
117
+V 27
118
+2010-01-23T07:43:02.208918Z
119
+PROPS-END
120
+
121
+Node-path: branches/red/foo
122
+Node-kind: file
123
+Node-action: change
124
+Text-content-length: 8
125
+Text-content-md5: 64c3c8cf7d0233ab7627623a68888bd1
126
+Text-content-sha1: 95a0492027876adfd3891ec71ee37b79ee44d640
127
+Content-length: 8
128
+
129
+foo
130
+red
131
+
132
+
133
+Revision-number: 4
134
+Prop-content-length: 110
135
+Content-length: 110
136
+
137
+K 7
138
+svn:log
139
+V 12
140
+green change
141
+K 10
142
+svn:author
143
+V 3
144
+jay
145
+K 8
146
+svn:date
147
+V 27
148
+2010-01-23T07:43:15.746586Z
149
+PROPS-END
150
+
151
+Node-path: branches/green/foo
152
+Node-kind: file
153
+Node-action: change
154
+Text-content-length: 10
155
+Text-content-md5: 0209b6450891abc033d5eaaa9d3a8023
156
+Text-content-sha1: 87fc3bef9faeec48c0cd61dfc9851db377fdccf7
157
+Content-length: 10
158
+
159
+foo
160
+green
161
+
162
+
163
+Revision-number: 5
164
+Prop-content-length: 109
165
+Content-length: 109
166
+
167
+K 7
168
+svn:log
169
+V 11
170
+blue change
171
+K 10
172
+svn:author
173
+V 3
174
+jay
175
+K 8
176
+svn:date
177
+V 27
178
+2010-01-23T07:43:29.364811Z
179
+PROPS-END
180
+
181
+Node-path: branches/blue/foo
182
+Node-kind: file
183
+Node-action: change
184
+Text-content-length: 9
185
+Text-content-md5: 9fbe4c13d0bae86386ae5209b2e6b275
186
+Text-content-sha1: cc4575083459a16f9aaef796c4a2456d64691ba0
187
+Content-length: 9
188
+
189
+foo
190
+blue
191
+
192
+
193
+Revision-number: 6
194
+Prop-content-length: 110
195
+Content-length: 110
196
+
197
+K 7
198
+svn:log
199
+V 12
200
+trunk change
201
+K 10
202
+svn:author
203
+V 3
204
+jay
205
+K 8
206
+svn:date
207
+V 27
208
+2010-01-23T07:44:01.313130Z
209
+PROPS-END
210
+
211
+Node-path: trunk/foo
212
+Node-kind: file
213
+Node-action: change
214
+Text-content-length: 10
215
+Text-content-md5: 1c4db977d7a57c3bae582aab87948516
216
+Text-content-sha1: 469c08df449e702cf2a1fe746244a9ef3f837fad
217
+Content-length: 10
218
+
219
+foo
220
+trunk
221
+
222
+