Skip to content

Commit a7b1023

Browse files
Paul WalmsleyEric Wong
authored andcommitted
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 <[email protected]> Signed-off-by: Eric Wong <[email protected]>
1 parent d301f18 commit a7b1023

File tree

5 files changed

+180
-3
lines changed

5 files changed

+180
-3
lines changed

Documentation/git-svn.txt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,10 @@ COMMANDS
8585
When passed to 'init' or 'clone' this regular expression will
8686
be preserved as a config key. See 'fetch' for a description
8787
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'.
8892
--no-minimize-url;;
8993
When tracking multiple directories (using --stdlayout,
9094
--branches, or --tags options), git svn will attempt to connect
@@ -146,6 +150,14 @@ Skip "branches" and "tags" of first level directories;;
146150
------------------------------------------------------------------------
147151
--
148152

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+
149161
--log-window-size=<n>;;
150162
Fetch <n> log entries per request when scanning Subversion history.
151163
The default is 100. For very large Subversion repositories, larger

contrib/completion/git-completion.bash

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2451,7 +2451,7 @@ _git_svn ()
24512451
--no-metadata --use-svm-props --use-svnsync-props
24522452
--log-window-size= --no-checkout --quiet
24532453
--repack-flags --use-log-author --localtime
2454-
--ignore-paths= $remote_opts
2454+
--ignore-paths= --include-paths= $remote_opts
24552455
"
24562456
local init_opts="
24572457
--template= --shared= --trunk= --tags=

git-svn.perl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ sub _req_svn {
126126
'config-dir=s' => \$Git::SVN::Ra::config_dir,
127127
'no-auth-cache' => \$Git::SVN::Prompt::_no_auth_cache,
128128
'ignore-paths=s' => \$Git::SVN::Fetcher::_ignore_regex,
129+
'include-paths=s' => \$Git::SVN::Fetcher::_include_regex,
129130
'ignore-refs=s' => \$Git::SVN::Ra::_ignore_refs_regex );
130131
my %fc_opts = ( 'follow-parent|follow!' => \$Git::SVN::_follow_parent,
131132
'authors-file|A=s' => \$_authors,
@@ -470,6 +471,9 @@ sub do_git_init_db {
470471
my $ignore_paths_regex = \$Git::SVN::Fetcher::_ignore_regex;
471472
command_noisy('config', "$pfx.ignore-paths", $$ignore_paths_regex)
472473
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;
473477
my $ignore_refs_regex = \$Git::SVN::Ra::_ignore_refs_regex;
474478
command_noisy('config', "$pfx.ignore-refs", $$ignore_refs_regex)
475479
if defined $$ignore_refs_regex;

perl/Git/SVN/Fetcher.pm

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
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/;
45
use strict;
56
use warnings;
67
use SVN::Delta;
@@ -33,6 +34,10 @@ sub new {
3334
my $v = eval { command_oneline('config', '--get', $k) };
3435
$self->{ignore_regex} = $v;
3536

37+
$k = "svn-remote.$repo_id.include-paths";
38+
$v = eval { command_oneline('config', '--get', $k) };
39+
$self->{include_regex} = $v;
40+
3641
$k = "svn-remote.$repo_id.preserve-empty-dirs";
3742
$v = eval { command_oneline('config', '--get', '--bool', $k) };
3843
if ($v && $v eq 'true') {
@@ -117,11 +122,18 @@ sub in_dot_git {
117122
}
118123

119124
# return value: 0 -- don't ignore, 1 -- ignore
125+
# This will also check whether the path is explicitly included
120126
sub is_path_ignored {
121127
my ($self, $path) = @_;
122128
return 1 if in_dot_git($path);
123129
return 1 if defined($self->{ignore_regex}) &&
124130
$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);
125137
return 0 unless defined($_ignore_regex);
126138
return 1 if $path =~ m!$_ignore_regex!o;
127139
return 0;

t/t9147-git-svn-include-paths.sh

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

0 commit comments

Comments
 (0)