{"thread":{"id":"33528","subject":"[PATCH] git-svn: added an --include-path flag","startedAt":"2013-04-17T21:42:32Z","lastAt":"2013-04-17T21:42:32Z","messageCount":1,"participants":["Paul Walmsley"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"214644","messageId":"516F1748.50308@gmail.com","threadId":"33528","inReplyTo":null,"subject":"[PATCH] git-svn: added an --include-path flag","fromName":"Paul Walmsley","fromEmail":"pjwhams@gmail.com","sentAt":"2013-04-17T21:42:32Z","receivedAt":"2013-04-17T21:42:32Z","isPatch":true,"sender":{"key":"pjwhams@gmail.com","avatar":null},"body":"The SVN::Fetcher module is now able to filter for inclusion as well\nas exclusion (as used by --ignore-path). Also added tests, documentation\nchanges and git completion script.\n\nIf you have an SVN repository with many top level directories and you\nonly want a git-svn clone of some of them then using --ignore-path is\ndifficult as it requires a very long regexp. In this case it's much\neasier to filter for inclusion.\n\nSigned-off-by: Paul Walmsley <pjwhams@gmail.com>\n---\n Documentation/git-svn.txt              |   12 +++\n contrib/completion/git-completion.bash |    2 +-\n git-svn.perl                           |    4 +\n perl/Git/SVN/Fetcher.pm                |   13 ++-\n t/t9147-git-svn-include-paths.sh       |  150 ++++++++++++++++++++++++++++++++\n 5 files changed, 179 insertions(+), 2 deletions(-)\n create mode 100755 t/t9147-git-svn-include-paths.sh\n\n\n--------------1.7.10.4\nContent-Type: text/x-patch; name=\"0001-git-svn-added-an-include-path-flag.patch\"\nContent-Transfer-Encoding: 8bit\nContent-Disposition: attachment; filename=\"0001-git-svn-added-an-include-path-flag.patch\"\n\ndiff --git a/Documentation/git-svn.txt b/Documentation/git-svn.txt\nindex 69decb1..df1f40c 100644\n--- a/Documentation/git-svn.txt\n+++ b/Documentation/git-svn.txt\n@@ -85,6 +85,10 @@ COMMANDS\n \tWhen passed to 'init' or 'clone' this regular expression will\n \tbe preserved as a config key.  See 'fetch' for a description\n \tof '--ignore-paths'.\n+--include-paths=<regex>;;\n+\tWhen passed to 'init' or 'clone' this regular expression will\n+\tbe preserved as a config key.  See 'fetch' for a description\n+\tof '--include-paths'.\n --no-minimize-url;;\n \tWhen tracking multiple directories (using --stdlayout,\n \t--branches, or --tags options), git svn will attempt to connect\n@@ -146,6 +150,14 @@ Skip \"branches\" and \"tags\" of first level directories;;\n ------------------------------------------------------------------------\n --\n \n+--include-paths=<regex>;;\n+\tThis allows one to specify a Perl regular expression that will\n+\tcause the inclusion of only matching paths from checkout from SVN.\n+\tThe '--include-paths' option should match for every 'fetch'\n+\t(including automatic fetches due to 'clone', 'dcommit',\n+\t'rebase', etc) on a given repository. '--ignore-paths' takes \n+\tprecedence over '--include-paths'.\n+\n --log-window-size=<n>;;\n     Fetch <n> log entries per request when scanning Subversion history.\n     The default is 100. For very large Subversion repositories, larger\ndiff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash\nindex 39c7ff8..8b75d01 100644\n--- a/contrib/completion/git-completion.bash\n+++ b/contrib/completion/git-completion.bash\n@@ -2222,7 +2222,7 @@ _git_svn ()\n \t\t\t--no-metadata --use-svm-props --use-svnsync-props\n \t\t\t--log-window-size= --no-checkout --quiet\n \t\t\t--repack-flags --use-log-author --localtime\n-\t\t\t--ignore-paths= $remote_opts\n+\t\t\t--ignore-paths= --include-paths= $remote_opts\n \t\t\t\"\n \t\tlocal init_opts=\"\n \t\t\t--template= --shared= --trunk= --tags=\ndiff --git a/git-svn.perl b/git-svn.perl\nindex bd5266c..6d713e1 100755\n--- a/git-svn.perl\n+++ b/git-svn.perl\n@@ -127,6 +127,7 @@ my %remote_opts = ( 'username=s' => \\$Git::SVN::Prompt::_username,\n                     'config-dir=s' => \\$Git::SVN::Ra::config_dir,\n                     'no-auth-cache' => \\$Git::SVN::Prompt::_no_auth_cache,\n                     'ignore-paths=s' => \\$Git::SVN::Fetcher::_ignore_regex,\n+                    'include-paths=s' => \\$Git::SVN::Fetcher::_include_regex,\n                     'ignore-refs=s' => \\$Git::SVN::Ra::_ignore_refs_regex );\n my %fc_opts = ( 'follow-parent|follow!' => \\$Git::SVN::_follow_parent,\n \t\t'authors-file|A=s' => \\$_authors,\n@@ -477,6 +478,9 @@ sub do_git_init_db {\n \tmy $ignore_paths_regex = \\$Git::SVN::Fetcher::_ignore_regex;\n \tcommand_noisy('config', \"$pfx.ignore-paths\", $$ignore_paths_regex)\n \t\tif defined $$ignore_paths_regex;\n+\tmy $include_paths_regex = \\$Git::SVN::Fetcher::_include_regex;\n+\tcommand_noisy('config', \"$pfx.include-paths\", $$include_paths_regex)\n+\t\tif defined $$include_paths_regex;\n \tmy $ignore_refs_regex = \\$Git::SVN::Ra::_ignore_refs_regex;\n \tcommand_noisy('config', \"$pfx.ignore-refs\", $$ignore_refs_regex)\n \t\tif defined $$ignore_refs_regex;\ndiff --git a/perl/Git/SVN/Fetcher.pm b/perl/Git/SVN/Fetcher.pm\nindex 046a7a2..27824e7 100644\n--- a/perl/Git/SVN/Fetcher.pm\n+++ b/perl/Git/SVN/Fetcher.pm\n@@ -1,5 +1,5 @@\n package Git::SVN::Fetcher;\n-use vars qw/@ISA $_ignore_regex $_preserve_empty_dirs $_placeholder_filename\n+use vars qw/@ISA $_ignore_regex $_include_regex $_preserve_empty_dirs $_placeholder_filename\n             @deleted_gpath %added_placeholder $repo_id/;\n use strict;\n use warnings;\n@@ -33,6 +33,10 @@ sub new {\n \tmy $v = eval { command_oneline('config', '--get', $k) };\n \t$self->{ignore_regex} = $v;\n \n+\t$k = \"svn-remote.$repo_id.include-paths\";\n+\t$v = eval { command_oneline('config', '--get', $k) };\n+\t$self->{include_regex} = $v;\n+\n \t$k = \"svn-remote.$repo_id.preserve-empty-dirs\";\n \t$v = eval { command_oneline('config', '--get', '--bool', $k) };\n \tif ($v && $v eq 'true') {\n@@ -117,11 +121,18 @@ sub in_dot_git {\n }\n \n # return value: 0 -- don't ignore, 1 -- ignore\n+# This will also check whether the path is explicitly included\n sub is_path_ignored {\n \tmy ($self, $path) = @_;\n \treturn 1 if in_dot_git($path);\n \treturn 1 if defined($self->{ignore_regex}) &&\n \t            $path =~ m!$self->{ignore_regex}!;\n+\treturn 0 if defined($self->{include_regex}) &&\n+\t            $path =~ m!$self->{include_regex}!;\n+\treturn 0 if defined($_include_regex) &&\n+\t            $path =~ m!$_include_regex!;\n+\treturn 1 if defined($self->{include_regex});\n+\treturn 1 if defined($_include_regex);\n \treturn 0 unless defined($_ignore_regex);\n \treturn 1 if $path =~ m!$_ignore_regex!o;\n \treturn 0;\ndiff --git a/t/t9147-git-svn-include-paths.sh b/t/t9147-git-svn-include-paths.sh\nnew file mode 100755\nindex 0000000..e2e9812\n--- /dev/null\n+++ b/t/t9147-git-svn-include-paths.sh\n@@ -0,0 +1,150 @@\n+#!/bin/sh\n+#\n+# Copyright (c) 2009 Vitaly Shukela\n+# Copyright (c) 2009 Eric Wong\n+#\n+\n+test_description='git svn property tests'\n+. ./lib-git-svn.sh\n+\n+test_expect_success 'setup test repository' '\n+\tsvn_cmd co \"$svnrepo\" s &&\n+\t(\n+\t\tcd s &&\n+\t\tmkdir qqq www xxx &&\n+\t\techo test_qqq > qqq/test_qqq.txt &&\n+\t\techo test_www > www/test_www.txt &&\n+\t\techo test_xxx > xxx/test_xxx.txt &&\n+\t\tsvn_cmd add qqq &&\n+\t\tsvn_cmd add www &&\n+\t\tsvn_cmd add xxx &&\n+\t\tsvn_cmd commit -m \"create some files\" &&\n+\t\tsvn_cmd up &&\n+\t\techo hi >> www/test_www.txt &&\n+\t\tsvn_cmd commit -m \"modify www/test_www.txt\" &&\n+\t\tsvn_cmd up\n+\t)\n+'\n+\n+test_expect_success 'clone an SVN repository with filter to include qqq directory' '\n+\tgit svn clone --include-paths=\"qqq\" \"$svnrepo\" g &&\n+\techo test_qqq > expect &&\n+\tfor i in g/*/*.txt; do cat $i >> expect2; done &&\n+\ttest_cmp expect expect2\n+'\n+\n+\n+test_expect_success 'init+fetch an SVN repository with included qqq directory' '\n+\tgit svn init \"$svnrepo\" c &&\n+ \t( cd c && git svn fetch --include-paths=\"qqq\" ) &&\n+ \trm expect2 &&\n+ \techo test_qqq > expect &&\n+ \tfor i in c/*/*.txt; do cat $i >> expect2; done &&\n+ \ttest_cmp expect expect2\n+'\n+\n+test_expect_success 'verify include-paths config saved by clone' '\n+\t(\n+\t    cd g &&\n+\t    git config --get svn-remote.svn.include-paths | fgrep \"qqq\"\n+\t)\n+'\n+\n+test_expect_success 'SVN-side change outside of www' '\n+\t(\n+\t\tcd s &&\n+\t\techo b >> qqq/test_qqq.txt &&\n+\t\tsvn_cmd commit -m \"SVN-side change outside of www\" &&\n+\t\tsvn_cmd up &&\n+\t\tsvn_cmd log -v | fgrep \"SVN-side change outside of www\"\n+\t)\n+'\n+\n+test_expect_success 'update git svn-cloned repo (config include)' '\n+\t(\n+\t\tcd g &&\n+\t\tgit svn rebase &&\n+\t\tprintf \"test_qqq\\nb\\n\" > expect &&\n+\t\tfor i in */*.txt; do cat $i >> expect2; done &&\n+\t\ttest_cmp expect2 expect &&\n+\t\trm expect expect2\n+\t)\n+'\n+\n+test_expect_success 'update git svn-cloned repo (option include)' '\n+\t(\n+\t\tcd c &&\n+\t\tgit svn rebase --include-paths=\"qqq\" &&\n+\t\tprintf \"test_qqq\\nb\\n\" > expect &&\n+\t\tfor i in */*.txt; do cat $i >> expect2; done &&\n+\t\ttest_cmp expect2 expect &&\n+\t\trm expect expect2\n+\t)\n+'\n+\n+test_expect_success 'SVN-side change inside of ignored www' '\n+\t(\n+\t\tcd s &&\n+\t\techo zaq >> www/test_www.txt\n+\t\tsvn_cmd commit -m \"SVN-side change inside of www/test_www.txt\" &&\n+\t\tsvn_cmd up &&\n+\t\tsvn_cmd log -v | fgrep \"SVN-side change inside of www/test_www.txt\"\n+\t)\n+'\n+\n+test_expect_success 'update git svn-cloned repo (config include)' '\n+\t(\n+\t\tcd g &&\n+\t\tgit svn rebase &&\n+\t\tprintf \"test_qqq\\nb\\n\" > expect &&\n+\t\tfor i in */*.txt; do cat $i >> expect2; done &&\n+\t\ttest_cmp expect2 expect &&\n+\t\trm expect expect2\n+\t)\n+'\n+\n+test_expect_success 'update git svn-cloned repo (option include)' '\n+\t(\n+\t\tcd c &&\n+\t\tgit svn rebase --include-paths=\"qqq\" &&\n+\t\tprintf \"test_qqq\\nb\\n\" > expect &&\n+\t\tfor i in */*.txt; do cat $i >> expect2; done &&\n+\t\ttest_cmp expect2 expect &&\n+\t\trm expect expect2\n+\t)\n+'\n+\n+test_expect_success 'SVN-side change in and out of included qqq' '\n+\t(\n+\t\tcd s &&\n+\t\techo cvf >> www/test_www.txt\n+\t\techo ygg >> qqq/test_qqq.txt\n+\t\tsvn_cmd commit -m \"SVN-side change in and out of ignored www\" &&\n+\t\tsvn_cmd up &&\n+\t\tsvn_cmd log -v | fgrep \"SVN-side change in and out of ignored www\"\n+\t)\n+'\n+\n+test_expect_success 'update git svn-cloned repo again (config include)' '\n+\t(\n+\t\tcd g &&\n+\t\tgit svn rebase &&\n+\t\tprintf \"test_qqq\\nb\\nygg\\n\" > expect &&\n+\t\tfor i in */*.txt; do cat $i >> expect2; done &&\n+\t\ttest_cmp expect2 expect &&\n+\t\trm expect expect2\n+\t)\n+'\n+\n+test_expect_success 'update git svn-cloned repo again (option include)' '\n+\t(\n+\t\tcd c &&\n+\t\tgit svn rebase --include-paths=\"qqq\" &&\n+\t\tprintf \"test_qqq\\nb\\nygg\\n\" > expect &&\n+\t\tfor i in */*.txt; do cat $i >> expect2; done &&\n+\t\ttest_cmp expect2 expect &&\n+\t\trm expect expect2\n+\t)\n+'\n+\n+test_done\n\n--------------1.7.10.4--\n\n\n \n"}]}