From e234ac9d47b6618f7b7338f95f34d0b70782e4cb Mon Sep 17 00:00:00 2001 From: Michael Contreras Date: Sat, 30 Mar 2013 18:06:42 -0400 Subject: git-svn: avoid self-referencing mergeinfo When svn.pushmergeinfo is set, the target branch is included in the mergeinfo if it was previously merged into one of the source branches. SVN does not do this. Remove merge target branch path from resulting mergeinfo when svn.pushmergeinfo is set to better match the behavior of SVN. Update the svn-mergeinfo-push test. [ew: 80 columns] Signed-off-by: Michael Contreras Reported-by: Avishay Lavie Acked-by: Eric Wong --- git-svn.perl | 11 ++++++++--- t/t9161-git-svn-mergeinfo-push.sh | 1 - 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/git-svn.perl b/git-svn.perl index 6c7bd95032..705f5ab4c8 100755 --- a/git-svn.perl +++ b/git-svn.perl @@ -669,12 +669,14 @@ sub merge_revs_into_hash { } sub merge_merge_info { - my ($mergeinfo_one, $mergeinfo_two) = @_; + my ($mergeinfo_one, $mergeinfo_two, $ignore_branch) = @_; my %result_hash = (); merge_revs_into_hash(\%result_hash, $mergeinfo_one); merge_revs_into_hash(\%result_hash, $mergeinfo_two); + delete $result_hash{$ignore_branch} if $ignore_branch; + my $result = ''; # Sort below is for consistency's sake for my $branchname (sort keys(%result_hash)) { @@ -695,6 +697,7 @@ sub populate_merge_info { my $all_parents_ok = 1; my $aggregate_mergeinfo = ''; my $rooturl = $gs->repos_root; + my ($target_branch) = $gs->full_pushurl =~ /^\Q$rooturl\E(.*)/; if (defined($rewritten_parent)) { # Replace first parent with newly-rewritten version @@ -726,7 +729,8 @@ sub populate_merge_info { # Merge previous mergeinfo values $aggregate_mergeinfo = merge_merge_info($aggregate_mergeinfo, - $par_mergeinfo, 0); + $par_mergeinfo, + $target_branch); next if $parent eq $parents[0]; # Skip first parent # Add new changes being placed in tree by merge @@ -769,7 +773,8 @@ sub populate_merge_info { my $newmergeinfo = "$branchpath:" . join(',', @revsin); $aggregate_mergeinfo = merge_merge_info($aggregate_mergeinfo, - $newmergeinfo, 1); + $newmergeinfo, + $target_branch); } if ($all_parents_ok and $aggregate_mergeinfo) { return $aggregate_mergeinfo; diff --git a/t/t9161-git-svn-mergeinfo-push.sh b/t/t9161-git-svn-mergeinfo-push.sh index 6ef0c0bde3..1eab7015c7 100755 --- a/t/t9161-git-svn-mergeinfo-push.sh +++ b/t/t9161-git-svn-mergeinfo-push.sh @@ -88,7 +88,6 @@ test_expect_success 'check reintegration mergeinfo' ' test "$mergeinfo" = "/branches/svnb1:2-4,7-9,13-18 /branches/svnb2:3,8,16-17 /branches/svnb3:4,9 -/branches/svnb4:5-6,10-12 /branches/svnb5:6,11" ' -- cgit v1.2.3 From d301f18160a3b0c3a5f647b9786aefd720d57faf Mon Sep 17 00:00:00 2001 From: Jonathan Nieder Date: Sun, 5 May 2013 00:50:33 -0700 Subject: Git::SVN::*: add missing "NAME" section to perldoc lexgrog(1) relies on the NAME section to find a manpage's subject's name and description for easy access later using "man -k". Add the section it expects. Noticed using lintian. Signed-off-by: Jonathan Nieder Signed-off-by: Eric Wong --- perl/Git/SVN/Editor.pm | 2 ++ perl/Git/SVN/Fetcher.pm | 2 ++ perl/Git/SVN/Prompt.pm | 2 ++ perl/Git/SVN/Ra.pm | 2 ++ 4 files changed, 8 insertions(+) diff --git a/perl/Git/SVN/Editor.pm b/perl/Git/SVN/Editor.pm index fa0d3c6cdd..b3bcd476da 100644 --- a/perl/Git/SVN/Editor.pm +++ b/perl/Git/SVN/Editor.pm @@ -499,6 +499,8 @@ sub apply_diff { 1; __END__ +=head1 NAME + Git::SVN::Editor - commit driver for "git svn set-tree" and dcommit =head1 SYNOPSIS diff --git a/perl/Git/SVN/Fetcher.pm b/perl/Git/SVN/Fetcher.pm index 046a7a2f31..72150af687 100644 --- a/perl/Git/SVN/Fetcher.pm +++ b/perl/Git/SVN/Fetcher.pm @@ -512,6 +512,8 @@ sub stash_placeholder_list { 1; __END__ +=head1 NAME + Git::SVN::Fetcher - tree delta consumer for "git svn fetch" =head1 SYNOPSIS diff --git a/perl/Git/SVN/Prompt.pm b/perl/Git/SVN/Prompt.pm index 74daa7a597..e940b08505 100644 --- a/perl/Git/SVN/Prompt.pm +++ b/perl/Git/SVN/Prompt.pm @@ -125,6 +125,8 @@ sub _read_password { 1; __END__ +=head1 NAME + Git::SVN::Prompt - authentication callbacks for git-svn =head1 SYNOPSIS diff --git a/perl/Git/SVN/Ra.pm b/perl/Git/SVN/Ra.pm index 6a212eb7a8..75ecc425b6 100644 --- a/perl/Git/SVN/Ra.pm +++ b/perl/Git/SVN/Ra.pm @@ -627,6 +627,8 @@ sub skip_unknown_revs { 1; __END__ +=head1 NAME + Git::SVN::Ra - Subversion remote access functions for git-svn =head1 SYNOPSIS -- cgit v1.2.3 From a7b102302ad9495fb4eb5088ffcb09c44a406c06 Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Sat, 4 May 2013 00:10:18 +0100 Subject: 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 Signed-off-by: Eric Wong --- Documentation/git-svn.txt | 12 +++ contrib/completion/git-completion.bash | 2 +- git-svn.perl | 4 + perl/Git/SVN/Fetcher.pm | 16 +++- t/t9147-git-svn-include-paths.sh | 149 +++++++++++++++++++++++++++++++++ 5 files changed, 180 insertions(+), 3 deletions(-) create mode 100755 t/t9147-git-svn-include-paths.sh diff --git a/Documentation/git-svn.txt b/Documentation/git-svn.txt index 7706d41c87..58b6d540ca 100644 --- a/Documentation/git-svn.txt +++ b/Documentation/git-svn.txt @@ -85,6 +85,10 @@ COMMANDS When passed to 'init' or 'clone' this regular expression will be preserved as a config key. See 'fetch' for a description of '--ignore-paths'. +--include-paths=;; + When passed to 'init' or 'clone' this regular expression will + be preserved as a config key. See 'fetch' for a description + of '--include-paths'. --no-minimize-url;; When tracking multiple directories (using --stdlayout, --branches, or --tags options), git svn will attempt to connect @@ -146,6 +150,14 @@ Skip "branches" and "tags" of first level directories;; ------------------------------------------------------------------------ -- +--include-paths=;; + This allows one to specify a Perl regular expression that will + cause the inclusion of only matching paths from checkout from SVN. + The '--include-paths' option should match for every 'fetch' + (including automatic fetches due to 'clone', 'dcommit', + 'rebase', etc) on a given repository. '--ignore-paths' takes + precedence over '--include-paths'. + --log-window-size=;; Fetch log entries per request when scanning Subversion history. The default is 100. For very large Subversion repositories, larger diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash index b97162f381..a98c2fd2de 100644 --- a/contrib/completion/git-completion.bash +++ b/contrib/completion/git-completion.bash @@ -2451,7 +2451,7 @@ _git_svn () --no-metadata --use-svm-props --use-svnsync-props --log-window-size= --no-checkout --quiet --repack-flags --use-log-author --localtime - --ignore-paths= $remote_opts + --ignore-paths= --include-paths= $remote_opts " local init_opts=" --template= --shared= --trunk= --tags= diff --git a/git-svn.perl b/git-svn.perl index 705f5ab4c8..ccabe065f3 100755 --- a/git-svn.perl +++ b/git-svn.perl @@ -126,6 +126,7 @@ my %remote_opts = ( 'username=s' => \$Git::SVN::Prompt::_username, 'config-dir=s' => \$Git::SVN::Ra::config_dir, 'no-auth-cache' => \$Git::SVN::Prompt::_no_auth_cache, 'ignore-paths=s' => \$Git::SVN::Fetcher::_ignore_regex, + 'include-paths=s' => \$Git::SVN::Fetcher::_include_regex, 'ignore-refs=s' => \$Git::SVN::Ra::_ignore_refs_regex ); my %fc_opts = ( 'follow-parent|follow!' => \$Git::SVN::_follow_parent, 'authors-file|A=s' => \$_authors, @@ -470,6 +471,9 @@ sub do_git_init_db { my $ignore_paths_regex = \$Git::SVN::Fetcher::_ignore_regex; command_noisy('config', "$pfx.ignore-paths", $$ignore_paths_regex) if defined $$ignore_paths_regex; + my $include_paths_regex = \$Git::SVN::Fetcher::_include_regex; + command_noisy('config', "$pfx.include-paths", $$include_paths_regex) + if defined $$include_paths_regex; my $ignore_refs_regex = \$Git::SVN::Ra::_ignore_refs_regex; command_noisy('config', "$pfx.ignore-refs", $$ignore_refs_regex) if defined $$ignore_refs_regex; diff --git a/perl/Git/SVN/Fetcher.pm b/perl/Git/SVN/Fetcher.pm index 72150af687..bd174189b9 100644 --- a/perl/Git/SVN/Fetcher.pm +++ b/perl/Git/SVN/Fetcher.pm @@ -1,6 +1,7 @@ package Git::SVN::Fetcher; -use vars qw/@ISA $_ignore_regex $_preserve_empty_dirs $_placeholder_filename - @deleted_gpath %added_placeholder $repo_id/; +use vars qw/@ISA $_ignore_regex $_include_regex $_preserve_empty_dirs + $_placeholder_filename @deleted_gpath %added_placeholder + $repo_id/; use strict; use warnings; use SVN::Delta; @@ -33,6 +34,10 @@ sub new { my $v = eval { command_oneline('config', '--get', $k) }; $self->{ignore_regex} = $v; + $k = "svn-remote.$repo_id.include-paths"; + $v = eval { command_oneline('config', '--get', $k) }; + $self->{include_regex} = $v; + $k = "svn-remote.$repo_id.preserve-empty-dirs"; $v = eval { command_oneline('config', '--get', '--bool', $k) }; if ($v && $v eq 'true') { @@ -117,11 +122,18 @@ sub in_dot_git { } # return value: 0 -- don't ignore, 1 -- ignore +# This will also check whether the path is explicitly included sub is_path_ignored { my ($self, $path) = @_; return 1 if in_dot_git($path); return 1 if defined($self->{ignore_regex}) && $path =~ m!$self->{ignore_regex}!; + return 0 if defined($self->{include_regex}) && + $path =~ m!$self->{include_regex}!; + return 0 if defined($_include_regex) && + $path =~ m!$_include_regex!; + return 1 if defined($self->{include_regex}); + return 1 if defined($_include_regex); return 0 unless defined($_ignore_regex); return 1 if $path =~ m!$_ignore_regex!o; return 0; diff --git a/t/t9147-git-svn-include-paths.sh b/t/t9147-git-svn-include-paths.sh new file mode 100755 index 0000000000..a90ff58629 --- /dev/null +++ b/t/t9147-git-svn-include-paths.sh @@ -0,0 +1,149 @@ +#!/bin/sh +# +# Copyright (c) 2013 Paul Walmsley - based on t9134 by Vitaly Shukela +# + +test_description='git svn property tests' +. ./lib-git-svn.sh + +test_expect_success 'setup test repository' ' + svn_cmd co "$svnrepo" s && + ( + cd s && + mkdir qqq www xxx && + echo test_qqq > qqq/test_qqq.txt && + echo test_www > www/test_www.txt && + echo test_xxx > xxx/test_xxx.txt && + svn_cmd add qqq && + svn_cmd add www && + svn_cmd add xxx && + svn_cmd commit -m "create some files" && + svn_cmd up && + echo hi >> www/test_www.txt && + svn_cmd commit -m "modify www/test_www.txt" && + svn_cmd up + ) +' + +test_expect_success 'clone an SVN repository with filter to include qqq directory' ' + git svn clone --include-paths="qqq" "$svnrepo" g && + echo test_qqq > expect && + for i in g/*/*.txt; do cat $i >> expect2; done && + test_cmp expect expect2 +' + + +test_expect_success 'init+fetch an SVN repository with included qqq directory' ' + git svn init "$svnrepo" c && + ( cd c && git svn fetch --include-paths="qqq" ) && + rm expect2 && + echo test_qqq > expect && + for i in c/*/*.txt; do cat $i >> expect2; done && + test_cmp expect expect2 +' + +test_expect_success 'verify include-paths config saved by clone' ' + ( + cd g && + git config --get svn-remote.svn.include-paths | fgrep "qqq" + ) +' + +test_expect_success 'SVN-side change outside of www' ' + ( + cd s && + echo b >> qqq/test_qqq.txt && + svn_cmd commit -m "SVN-side change outside of www" && + svn_cmd up && + svn_cmd log -v | fgrep "SVN-side change outside of www" + ) +' + +test_expect_success 'update git svn-cloned repo (config include)' ' + ( + 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 include)' ' + ( + cd c && + git svn rebase --include-paths="qqq" && + 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 'SVN-side change inside of ignored www' ' + ( + cd s && + echo zaq >> www/test_www.txt + svn_cmd commit -m "SVN-side change inside of www/test_www.txt" && + svn_cmd up && + svn_cmd log -v | fgrep "SVN-side change inside of www/test_www.txt" + ) +' + +test_expect_success 'update git svn-cloned repo (config include)' ' + ( + 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 include)' ' + ( + cd c && + git svn rebase --include-paths="qqq" && + 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 'SVN-side change in and out of included qqq' ' + ( + cd s && + echo cvf >> www/test_www.txt + echo ygg >> qqq/test_qqq.txt + svn_cmd commit -m "SVN-side change in and out of ignored www" && + svn_cmd up && + svn_cmd log -v | fgrep "SVN-side change in and out of ignored www" + ) +' + +test_expect_success 'update git svn-cloned repo again (config include)' ' + ( + 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 include)' ' + ( + cd c && + git svn rebase --include-paths="qqq" && + printf "test_qqq\nb\nygg\n" > expect && + for i in */*.txt; do cat $i >> expect2; done && + test_cmp expect2 expect && + rm expect expect2 + ) +' + +test_done -- cgit v1.2.3