git-svn: added an --include-path flag
The SVN::Fetcher module is now able to filter for inclusion as well as exclusion (as used by --ignore-path). Also added tests, documentation changes and git completion script. If you have an SVN repository with many top level directories and you only want a git-svn clone of some of them then using --ignore-path is difficult as it requires a very long regexp. In this case it's much easier to filter for inclusion. [ew: remove trailing whitespace] Signed-off-by: Paul Walmsley <pjwhams@gmail.com> Signed-off-by: Eric Wong <normalperson@yhbt.net>
Paul Walmsley committed
May 4, 2013 at 00:10 UTC
a7b102302ad9495fb4eb5088ffcb09c44a406c06
5 files changed
+180
-3
Documentation/git-svn.txt
+12
@@ -85,6 +85,10 @@ COMMANDS
85
When passed to 'init' or 'clone' this regular expression will
86
be preserved as a config key. See 'fetch' for a description
87
of '--ignore-paths'.
88
+--include-paths=<regex>;;
89
+ When passed to 'init' or 'clone' this regular expression will
90
+ be preserved as a config key. See 'fetch' for a description
91
+ of '--include-paths'.
92
--no-minimize-url;;
93
When tracking multiple directories (using --stdlayout,
94
--branches, or --tags options), git svn will attempt to connect
@@ -146,6 +150,14 @@ Skip "branches" and "tags" of first level directories;;
150
------------------------------------------------------------------------
151
--
152
153
+--include-paths=<regex>;;
154
+ This allows one to specify a Perl regular expression that will
155
+ cause the inclusion of only matching paths from checkout from SVN.
156
+ The '--include-paths' option should match for every 'fetch'
157
+ (including automatic fetches due to 'clone', 'dcommit',
158
+ 'rebase', etc) on a given repository. '--ignore-paths' takes
159
+ precedence over '--include-paths'.
160
+
161
--log-window-size=<n>;;
162
Fetch <n> log entries per request when scanning Subversion history.
163
The default is 100. For very large Subversion repositories, larger
contrib/completion/git-completion.bash
+1
-1
@@ -2451,7 +2451,7 @@ _git_svn ()
2451
--no-metadata --use-svm-props --use-svnsync-props
2452
--log-window-size= --no-checkout --quiet
2453
--repack-flags --use-log-author --localtime
2454
- --ignore-paths= $remote_opts
2454
+ --ignore-paths= --include-paths= $remote_opts
2455
"
2456
local init_opts="
2457
--template= --shared= --trunk= --tags=
git-svn.perl
+4
@@ -126,6 +126,7 @@ my %remote_opts = ( 'username=s' => \$Git::SVN::Prompt::_username,
126
'config-dir=s' => \$Git::SVN::Ra::config_dir,
127
'no-auth-cache' => \$Git::SVN::Prompt::_no_auth_cache,
128
'ignore-paths=s' => \$Git::SVN::Fetcher::_ignore_regex,
129
+ 'include-paths=s' => \$Git::SVN::Fetcher::_include_regex,
130
'ignore-refs=s' => \$Git::SVN::Ra::_ignore_refs_regex );
131
my %fc_opts = ( 'follow-parent|follow!' => \$Git::SVN::_follow_parent,
132
'authors-file|A=s' => \$_authors,
@@ -470,6 +471,9 @@ sub do_git_init_db {
471
my $ignore_paths_regex = \$Git::SVN::Fetcher::_ignore_regex;
472
command_noisy('config', "$pfx.ignore-paths", $$ignore_paths_regex)
473
if defined $$ignore_paths_regex;
474
+ my $include_paths_regex = \$Git::SVN::Fetcher::_include_regex;
475
+ command_noisy('config', "$pfx.include-paths", $$include_paths_regex)
476
+ if defined $$include_paths_regex;
477
my $ignore_refs_regex = \$Git::SVN::Ra::_ignore_refs_regex;
478
command_noisy('config', "$pfx.ignore-refs", $$ignore_refs_regex)
479
if defined $$ignore_refs_regex;
perl/Git/SVN/Fetcher.pm
+14
-2
@@ -1,6 +1,7 @@
1
package Git::SVN::Fetcher;
2
-use vars qw/@ISA $_ignore_regex $_preserve_empty_dirs $_placeholder_filename
3
- @deleted_gpath %added_placeholder $repo_id/;
2
+use vars qw/@ISA $_ignore_regex $_include_regex $_preserve_empty_dirs
3
+ $_placeholder_filename @deleted_gpath %added_placeholder
4
+ $repo_id/;
5
use strict;
6
use warnings;
7
use SVN::Delta;
@@ -33,6 +34,10 @@ sub new {
34
my $v = eval { command_oneline('config', '--get', $k) };
35
$self->{ignore_regex} = $v;
36
37
+ $k = "svn-remote.$repo_id.include-paths";
38
+ $v = eval { command_oneline('config', '--get', $k) };
39
+ $self->{include_regex} = $v;
40
+
41
$k = "svn-remote.$repo_id.preserve-empty-dirs";
42
$v = eval { command_oneline('config', '--get', '--bool', $k) };
43
if ($v && $v eq 'true') {
@@ -117,11 +122,18 @@ sub in_dot_git {
122
}
123
124
# return value: 0 -- don't ignore, 1 -- ignore
125
+# This will also check whether the path is explicitly included
126
sub is_path_ignored {
127
my ($self, $path) = @_;
128
return 1 if in_dot_git($path);
129
return 1 if defined($self->{ignore_regex}) &&
130
$path =~ m!$self->{ignore_regex}!;
131
+ return 0 if defined($self->{include_regex}) &&
132
+ $path =~ m!$self->{include_regex}!;
133
+ return 0 if defined($_include_regex) &&
134
+ $path =~ m!$_include_regex!;
135
+ return 1 if defined($self->{include_regex});
136
+ return 1 if defined($_include_regex);
137
return 0 unless defined($_ignore_regex);
138
return 1 if $path =~ m!$_ignore_regex!o;
139
return 0;
t/t9147-git-svn-include-paths.sh
new
+149
@@ -0,0 +1,149 @@
1
+#!/bin/sh
2
+#
3
+# Copyright (c) 2013 Paul Walmsley - based on t9134 by Vitaly Shukela
4
+#
5
+
6
+test_description='git svn property tests'
7
+. ./lib-git-svn.sh
8
+
9
+test_expect_success 'setup test repository' '
10
+ svn_cmd co "$svnrepo" s &&
11
+ (
12
+ cd s &&
13
+ mkdir qqq www xxx &&
14
+ echo test_qqq > qqq/test_qqq.txt &&
15
+ echo test_www > www/test_www.txt &&
16
+ echo test_xxx > xxx/test_xxx.txt &&
17
+ svn_cmd add qqq &&
18
+ svn_cmd add www &&
19
+ svn_cmd add xxx &&
20
+ svn_cmd commit -m "create some files" &&
21
+ svn_cmd up &&
22
+ echo hi >> www/test_www.txt &&
23
+ svn_cmd commit -m "modify www/test_www.txt" &&
24
+ svn_cmd up
25
+ )
26
+'
27
+
28
+test_expect_success 'clone an SVN repository with filter to include qqq directory' '
29
+ git svn clone --include-paths="qqq" "$svnrepo" g &&
30
+ echo test_qqq > expect &&
31
+ for i in g/*/*.txt; do cat $i >> expect2; done &&
32
+ test_cmp expect expect2
33
+'
34
+
35
+
36
+test_expect_success 'init+fetch an SVN repository with included qqq directory' '
37
+ git svn init "$svnrepo" c &&
38
+ ( cd c && git svn fetch --include-paths="qqq" ) &&
39
+ rm expect2 &&
40
+ echo test_qqq > expect &&
41
+ for i in c/*/*.txt; do cat $i >> expect2; done &&
42
+ test_cmp expect expect2
43
+'
44
+
45
+test_expect_success 'verify include-paths config saved by clone' '
46
+ (
47
+ cd g &&
48
+ git config --get svn-remote.svn.include-paths | fgrep "qqq"
49
+ )
50
+'
51
+
52
+test_expect_success 'SVN-side change outside of www' '
53
+ (
54
+ cd s &&
55
+ echo b >> qqq/test_qqq.txt &&
56
+ svn_cmd commit -m "SVN-side change outside of www" &&
57
+ svn_cmd up &&
58
+ svn_cmd log -v | fgrep "SVN-side change outside of www"
59
+ )
60
+'
61
+
62
+test_expect_success 'update git svn-cloned repo (config include)' '
63
+ (
64
+ cd g &&
65
+ git svn rebase &&
66
+ printf "test_qqq\nb\n" > expect &&
67
+ for i in */*.txt; do cat $i >> expect2; done &&
68
+ test_cmp expect2 expect &&
69
+ rm expect expect2
70
+ )
71
+'
72
+
73
+test_expect_success 'update git svn-cloned repo (option include)' '
74
+ (
75
+ cd c &&
76
+ git svn rebase --include-paths="qqq" &&
77
+ printf "test_qqq\nb\n" > expect &&
78
+ for i in */*.txt; do cat $i >> expect2; done &&
79
+ test_cmp expect2 expect &&
80
+ rm expect expect2
81
+ )
82
+'
83
+
84
+test_expect_success 'SVN-side change inside of ignored www' '
85
+ (
86
+ cd s &&
87
+ echo zaq >> www/test_www.txt
88
+ svn_cmd commit -m "SVN-side change inside of www/test_www.txt" &&
89
+ svn_cmd up &&
90
+ svn_cmd log -v | fgrep "SVN-side change inside of www/test_www.txt"
91
+ )
92
+'
93
+
94
+test_expect_success 'update git svn-cloned repo (config include)' '
95
+ (
96
+ cd g &&
97
+ git svn rebase &&
98
+ printf "test_qqq\nb\n" > expect &&
99
+ for i in */*.txt; do cat $i >> expect2; done &&
100
+ test_cmp expect2 expect &&
101
+ rm expect expect2
102
+ )
103
+'
104
+
105
+test_expect_success 'update git svn-cloned repo (option include)' '
106
+ (
107
+ cd c &&
108
+ git svn rebase --include-paths="qqq" &&
109
+ printf "test_qqq\nb\n" > expect &&
110
+ for i in */*.txt; do cat $i >> expect2; done &&
111
+ test_cmp expect2 expect &&
112
+ rm expect expect2
113
+ )
114
+'
115
+
116
+test_expect_success 'SVN-side change in and out of included qqq' '
117
+ (
118
+ cd s &&
119
+ echo cvf >> www/test_www.txt
120
+ echo ygg >> qqq/test_qqq.txt
121
+ svn_cmd commit -m "SVN-side change in and out of ignored www" &&
122
+ svn_cmd up &&
123
+ svn_cmd log -v | fgrep "SVN-side change in and out of ignored www"
124
+ )
125
+'
126
+
127
+test_expect_success 'update git svn-cloned repo again (config include)' '
128
+ (
129
+ cd g &&
130
+ git svn rebase &&
131
+ printf "test_qqq\nb\nygg\n" > expect &&
132
+ for i in */*.txt; do cat $i >> expect2; done &&
133
+ test_cmp expect2 expect &&
134
+ rm expect expect2
135
+ )
136
+'
137
+
138
+test_expect_success 'update git svn-cloned repo again (option include)' '
139
+ (
140
+ cd c &&
141
+ git svn rebase --include-paths="qqq" &&
142
+ printf "test_qqq\nb\nygg\n" > expect &&
143
+ for i in */*.txt; do cat $i >> expect2; done &&
144
+ test_cmp expect2 expect &&
145
+ rm expect expect2
146
+ )
147
+'
148
+
149
+test_done