git-svn: Add per-svn-remote ignore-paths config
authorBen Jackson <ben@ben.com>
Sat, 11 Apr 2009 17:46:17 +0000 (10:46 -0700)
committerEric Wong <normalperson@yhbt.net>
Sun, 12 Apr 2009 00:55:37 +0000 (17:55 -0700)
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 <ben@ben.com>
Acked-by: Eric Wong <normalperson@yhbt.net>
Documentation/git-svn.txt
git-svn.perl
t/t9134-git-svn-ignore-paths.sh
index 85b2c8da5d427d1823efc3ba0f0e10a093975267..aad5e65c7022e9c3d0f33a2f51276bf4d5b47fa2 100644 (file)
@@ -107,17 +107,25 @@ repository, either don't use this option or you should both use it in
 the same local timezone.
 
 --ignore-paths=<regex>;;
-       This allows one to specify Perl regular expression that will
+       This allows one to specify 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.<name>.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
index 50a398b3e75d75c0f917290bb56c699ca866a9e5..279847921ba4c2333af299535d41cb4b2d3bc750 100755 (executable)
@@ -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 @@ sub add_directory {
 
 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});
index c4b5b8bcf7949f8f60d5d80d6cd53e892b8743f2..b9a15978ebd3126bbeeafe8447f49978d0c2f716 100755 (executable)
@@ -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 &&