From 0d8bee71af1cda3d13d896c210773216dcf87b7c Mon Sep 17 00:00:00 2001 From: Ben Jackson Date: Sat, 11 Apr 2009 10:46:17 -0700 Subject: [PATCH] git-svn: Add per-svn-remote ignore-paths config The --ignore-paths option to fetch is very useful for working on a subset of a SVN repository. For proper operation, every command that causes a fetch (explicit or implied) must include a matching --ignore-paths option. This patch adds a persistent svn-remote.$repo_id.ignore-paths config by promoting Fetcher::is_path_ignored to a member function and initializing $self->{ignore_regex} in Fetcher::new. Command line --ignore-paths is still recognized and acts in addition to the config value. Signed-off-by: Ben Jackson Acked-by: Eric Wong --- Documentation/git-svn.txt | 22 ++++++++----- git-svn.perl | 26 +++++++++------- t/t9134-git-svn-ignore-paths.sh | 55 +++++++++++++++++++++++++++++++-- 3 files changed, 82 insertions(+), 21 deletions(-) diff --git a/Documentation/git-svn.txt b/Documentation/git-svn.txt index 85b2c8da5..aad5e65c7 100644 --- a/Documentation/git-svn.txt +++ b/Documentation/git-svn.txt @@ -107,17 +107,25 @@ repository, either don't use this option or you should both use it in the same local timezone. --ignore-paths=;; - This allows one to specify Perl regular expression that will + This allows one to specify a Perl regular expression that will cause skipping of all matching paths from checkout from SVN. - Examples: + The '--ignore-paths' option should match for every 'fetch' + (including automatic fetches due to 'clone', 'dcommit', + 'rebase', etc) on a given repository. - --ignore-paths="^doc" - skip "doc*" directory for every fetch. +config key: svn-remote..ignore-paths - --ignore-paths="^[^/]+/(?:branches|tags)" - skip "branches" - and "tags" of first level directories. + If the ignore-paths config key is set and the command + line option is also given, both regular expressions + will be used. - Regular expression is not persistent, you should specify - it every time when fetching. +Examples: + + --ignore-paths="^doc" - skip "doc*" directory for every + fetch. + + --ignore-paths="^[^/]+/(?:branches|tags)" - skip + "branches" and "tags" of first level directories. 'clone':: Runs 'init' and 'fetch'. It will automatically create a diff --git a/git-svn.perl b/git-svn.perl index 50a398b3e..279847921 100755 --- a/git-svn.perl +++ b/git-svn.perl @@ -3331,6 +3331,8 @@ sub new { $self->{empty_symlinks} = _mark_empty_symlinks($git_svn, $switch_path); } + $self->{ignore_regex} = eval { command_oneline('config', '--get', + "svn-remote.$git_svn->{repo_id}.ignore-paths") }; $self->{empty} = {}; $self->{dir_prop} = {}; $self->{file_prop} = {}; @@ -3395,8 +3397,10 @@ sub in_dot_git { # return value: 0 -- don't ignore, 1 -- ignore sub is_path_ignored { - my ($path) = @_; + my ($self, $path) = @_; return 1 if in_dot_git($path); + return 1 if defined($self->{ignore_regex}) && + $path =~ m!$self->{ignore_regex}!; return 0 unless defined($_ignore_regex); return 1 if $path =~ m!$_ignore_regex!o; return 0; @@ -3427,7 +3431,7 @@ sub git_path { sub delete_entry { my ($self, $path, $rev, $pb) = @_; - return undef if is_path_ignored($path); + return undef if $self->is_path_ignored($path); my $gpath = $self->git_path($path); return undef if ($gpath eq ''); @@ -3460,7 +3464,7 @@ sub open_file { my ($self, $path, $pb, $rev) = @_; my ($mode, $blob); - goto out if is_path_ignored($path); + goto out if $self->is_path_ignored($path); my $gpath = $self->git_path($path); ($mode, $blob) = (command('ls-tree', '-z', $self->{c}, "./$gpath") @@ -3480,7 +3484,7 @@ sub add_file { my ($self, $path, $pb, $cp_path, $cp_rev) = @_; my $mode; - if (!is_path_ignored($path)) { + if (!$self->is_path_ignored($path)) { my ($dir, $file) = ($path =~ m#^(.*?)/?([^/]+)$#); delete $self->{empty}->{$dir}; $mode = '100644'; @@ -3491,7 +3495,7 @@ sub add_file { sub add_directory { my ($self, $path, $cp_path, $cp_rev) = @_; - goto out if is_path_ignored($path); + goto out if $self->is_path_ignored($path); my $gpath = $self->git_path($path); if ($gpath eq '') { my ($ls, $ctx) = command_output_pipe(qw/ls-tree @@ -3515,7 +3519,7 @@ out: sub change_dir_prop { my ($self, $db, $prop, $value) = @_; - return undef if is_path_ignored($db->{path}); + return undef if $self->is_path_ignored($db->{path}); $self->{dir_prop}->{$db->{path}} ||= {}; $self->{dir_prop}->{$db->{path}}->{$prop} = $value; undef; @@ -3523,7 +3527,7 @@ sub change_dir_prop { sub absent_directory { my ($self, $path, $pb) = @_; - return undef if is_path_ignored($path); + return undef if $self->is_path_ignored($path); $self->{absent_dir}->{$pb->{path}} ||= []; push @{$self->{absent_dir}->{$pb->{path}}}, $path; undef; @@ -3531,7 +3535,7 @@ sub absent_directory { sub absent_file { my ($self, $path, $pb) = @_; - return undef if is_path_ignored($path); + return undef if $self->is_path_ignored($path); $self->{absent_file}->{$pb->{path}} ||= []; push @{$self->{absent_file}->{$pb->{path}}}, $path; undef; @@ -3539,7 +3543,7 @@ sub absent_file { sub change_file_prop { my ($self, $fb, $prop, $value) = @_; - return undef if is_path_ignored($fb->{path}); + return undef if $self->is_path_ignored($fb->{path}); if ($prop eq 'svn:executable') { if ($fb->{mode_b} != 120000) { $fb->{mode_b} = defined $value ? 100755 : 100644; @@ -3555,7 +3559,7 @@ sub change_file_prop { sub apply_textdelta { my ($self, $fb, $exp) = @_; - return undef if is_path_ignored($fb->{path}); + return undef if $self->is_path_ignored($fb->{path}); my $fh = $::_repository->temp_acquire('svn_delta'); # $fh gets auto-closed() by SVN::TxDelta::apply(), # (but $base does not,) so dup() it for reading in close_file @@ -3602,7 +3606,7 @@ sub apply_textdelta { sub close_file { my ($self, $fb, $exp) = @_; - return undef if is_path_ignored($fb->{path}); + return undef if $self->is_path_ignored($fb->{path}); my $hash; my $path = $self->git_path($fb->{path}); diff --git a/t/t9134-git-svn-ignore-paths.sh b/t/t9134-git-svn-ignore-paths.sh index c4b5b8bcf..b9a15978e 100755 --- a/t/t9134-git-svn-ignore-paths.sh +++ b/t/t9134-git-svn-ignore-paths.sh @@ -31,6 +31,22 @@ test_expect_success 'clone an SVN repository with ignored www directory' ' test_cmp expect expect2 ' +test_expect_success 'init+fetch an SVN repository with ignored www directory' ' + git svn init "$svnrepo" c && + ( cd c && git svn fetch --ignore-paths="^www" ) && + rm expect2 && + echo test_qqq > expect && + for i in c/*/*.txt; do cat $i >> expect2; done && + test_cmp expect expect2 +' + +test_expect_success 'set persistent ignore-paths config' ' + ( + cd g && + git config svn-remote.svn.ignore-paths "^www" + ) +' + test_expect_success 'SVN-side change outside of www' ' ( cd s && @@ -41,9 +57,20 @@ test_expect_success 'SVN-side change outside of www' ' ) ' -test_expect_success 'update git svn-cloned repo' ' +test_expect_success 'update git svn-cloned repo (config ignore)' ' ( cd g && + git svn rebase && + printf "test_qqq\nb\n" > expect && + for i in */*.txt; do cat $i >> expect2; done && + test_cmp expect2 expect && + rm expect expect2 + ) +' + +test_expect_success 'update git svn-cloned repo (option ignore)' ' + ( + cd c && git svn rebase --ignore-paths="^www" && printf "test_qqq\nb\n" > expect && for i in */*.txt; do cat $i >> expect2; done && @@ -62,9 +89,20 @@ test_expect_success 'SVN-side change inside of ignored www' ' ) ' -test_expect_success 'update git svn-cloned repo' ' +test_expect_success 'update git svn-cloned repo (config ignore)' ' ( cd g && + git svn rebase && + printf "test_qqq\nb\n" > expect && + for i in */*.txt; do cat $i >> expect2; done && + test_cmp expect2 expect && + rm expect expect2 + ) +' + +test_expect_success 'update git svn-cloned repo (option ignore)' ' + ( + cd c && git svn rebase --ignore-paths="^www" && printf "test_qqq\nb\n" > expect && for i in */*.txt; do cat $i >> expect2; done && @@ -84,9 +122,20 @@ test_expect_success 'SVN-side change in and out of ignored www' ' ) ' -test_expect_success 'update git svn-cloned repo again' ' +test_expect_success 'update git svn-cloned repo again (config ignore)' ' ( cd g && + git svn rebase && + printf "test_qqq\nb\nygg\n" > expect && + for i in */*.txt; do cat $i >> expect2; done && + test_cmp expect2 expect && + rm expect expect2 + ) +' + +test_expect_success 'update git svn-cloned repo again (option ignore)' ' + ( + cd c && git svn rebase --ignore-paths="^www" && printf "test_qqq\nb\nygg\n" > expect && for i in */*.txt; do cat $i >> expect2; done && -- 2.30.2