Merge git://git.bogomips.org/git-svn

* git://git.bogomips.org/git-svn:
  git-svn: Add test for --ignore-paths parameter
  git-svn: documented --ignore-paths
  git-svn: add --ignore-paths option for fetching
  git-svn: fix memory leak when checking for empty symlinks
This commit is contained in:
Junio C Hamano 2009-01-25 22:27:52 -08:00
commit afc7274704
3 changed files with 135 additions and 12 deletions

View file

@ -103,6 +103,19 @@ repository to be able to interoperate with someone else's local Git
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
cause skipping of all matching paths from checkout from SVN.
Examples:
--ignore-paths="^doc" - skip "doc*" directory for every fetch.
--ignore-paths="^[^/]+/(?:branches|tags)" - skip "branches"
and "tags" of first level directories.
Regular expression is not persistent, you should specify
it every time when fetching.
'clone'::
Runs 'init' and 'fetch'. It will automatically create a
directory based on the basename of the URL passed to it;

View file

@ -70,7 +70,8 @@ BEGIN
$Git::SVN::_follow_parent = 1;
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 );
'no-auth-cache' => \$Git::SVN::Prompt::_no_auth_cache,
'ignore-paths=s' => \$SVN::Git::Fetcher::_ignore_regex );
my %fc_opts = ( 'follow-parent|follow!' => \$Git::SVN::_follow_parent,
'authors-file|A=s' => \$_authors,
'repack:i' => \$Git::SVN::_repack,
@ -3245,6 +3246,7 @@ package SVN::Git::Fetcher;
use Carp qw/croak/;
use File::Temp qw/tempfile/;
use IO::File qw//;
use vars qw/$_ignore_regex/;
# file baton members: path, mode_a, mode_b, pool, fh, blob, base
sub new {
@ -3297,6 +3299,15 @@ sub in_dot_git {
$_[0] =~ m{(?:^|/)\.git(?:/|$)};
}
# return value: 0 -- don't ignore, 1 -- ignore
sub is_path_ignored {
my ($path) = @_;
return 1 if in_dot_git($path);
return 0 unless defined($_ignore_regex);
return 1 if $path =~ m!$_ignore_regex!o;
return 0;
}
sub set_path_strip {
my ($self, $path) = @_;
$self->{path_strip} = qr/^\Q$path\E(\/|$)/ if length $path;
@ -3322,7 +3333,7 @@ sub git_path {
sub delete_entry {
my ($self, $path, $rev, $pb) = @_;
return undef if in_dot_git($path);
return undef if is_path_ignored($path);
my $gpath = $self->git_path($path);
return undef if ($gpath eq '');
@ -3352,7 +3363,7 @@ sub open_file {
my ($self, $path, $pb, $rev) = @_;
my ($mode, $blob);
goto out if in_dot_git($path);
goto out if is_path_ignored($path);
my $gpath = $self->git_path($path);
($mode, $blob) = (command('ls-tree', $self->{c}, '--', $gpath)
@ -3372,7 +3383,7 @@ sub add_file {
my ($self, $path, $pb, $cp_path, $cp_rev) = @_;
my $mode;
if (!in_dot_git($path)) {
if (!is_path_ignored($path)) {
my ($dir, $file) = ($path =~ m#^(.*?)/?([^/]+)$#);
delete $self->{empty}->{$dir};
$mode = '100644';
@ -3383,7 +3394,7 @@ sub add_file {
sub add_directory {
my ($self, $path, $cp_path, $cp_rev) = @_;
goto out if in_dot_git($path);
goto out if is_path_ignored($path);
my $gpath = $self->git_path($path);
if ($gpath eq '') {
my ($ls, $ctx) = command_output_pipe(qw/ls-tree
@ -3407,7 +3418,7 @@ sub add_directory {
sub change_dir_prop {
my ($self, $db, $prop, $value) = @_;
return undef if in_dot_git($db->{path});
return undef if is_path_ignored($db->{path});
$self->{dir_prop}->{$db->{path}} ||= {};
$self->{dir_prop}->{$db->{path}}->{$prop} = $value;
undef;
@ -3415,7 +3426,7 @@ sub change_dir_prop {
sub absent_directory {
my ($self, $path, $pb) = @_;
return undef if in_dot_git($pb->{path});
return undef if is_path_ignored($path);
$self->{absent_dir}->{$pb->{path}} ||= [];
push @{$self->{absent_dir}->{$pb->{path}}}, $path;
undef;
@ -3423,7 +3434,7 @@ sub absent_directory {
sub absent_file {
my ($self, $path, $pb) = @_;
return undef if in_dot_git($pb->{path});
return undef if is_path_ignored($path);
$self->{absent_file}->{$pb->{path}} ||= [];
push @{$self->{absent_file}->{$pb->{path}}}, $path;
undef;
@ -3431,7 +3442,7 @@ sub absent_file {
sub change_file_prop {
my ($self, $fb, $prop, $value) = @_;
return undef if in_dot_git($fb->{path});
return undef if is_path_ignored($fb->{path});
if ($prop eq 'svn:executable') {
if ($fb->{mode_b} != 120000) {
$fb->{mode_b} = defined $value ? 100755 : 100644;
@ -3447,7 +3458,7 @@ sub change_file_prop {
sub apply_textdelta {
my ($self, $fb, $exp) = @_;
return undef if (in_dot_git($fb->{path}));
return undef if 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
@ -3494,7 +3505,7 @@ sub apply_textdelta {
sub close_file {
my ($self, $fb, $exp) = @_;
return undef if (in_dot_git($fb->{path}));
return undef if is_path_ignored($fb->{path});
my $hash;
my $path = $self->git_path($fb->{path});
@ -4021,7 +4032,8 @@ package Git::SVN::Ra;
BEGIN {
# enforce temporary pool usage for some simple functions
no strict 'refs';
for my $f (qw/rev_proplist get_latest_revnum get_uuid get_repos_root/) {
for my $f (qw/rev_proplist get_latest_revnum get_uuid get_repos_root
get_file/) {
my $SUPER = "SUPER::$f";
*$f = sub {
my $self = shift;

98
t/t9134-git-svn-ignore-paths.sh Executable file
View file

@ -0,0 +1,98 @@
#!/bin/sh
#
# Copyright (c) 2009 Vitaly Shukela
# Copyright (c) 2009 Eric Wong
#
test_description='git svn property tests'
. ./lib-git-svn.sh
test_expect_success 'setup test repository' '
svn co "$svnrepo" s &&
(
cd s &&
mkdir qqq www &&
echo test_qqq > qqq/test_qqq.txt &&
echo test_www > www/test_www.txt &&
svn add qqq &&
svn add www &&
svn commit -m "create some files" &&
svn up &&
echo hi >> www/test_www.txt &&
svn commit -m "modify www/test_www.txt" &&
svn up
)
'
test_expect_success 'clone an SVN repository with ignored www directory' '
git svn clone --ignore-paths="^www" "$svnrepo" g &&
echo test_qqq > expect &&
for i in g/*/*.txt; do cat $i >> expect2; done &&
test_cmp expect expect2
'
test_expect_success 'SVN-side change outside of www' '
(
cd s &&
echo b >> qqq/test_qqq.txt &&
svn commit -m "SVN-side change outside of www" &&
svn up &&
svn log -v | fgrep "SVN-side change outside of www"
)
'
test_expect_success 'update git svn-cloned repo' '
(
cd g &&
git svn rebase --ignore-paths="^www" &&
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 commit -m "SVN-side change inside of www/test_www.txt" &&
svn up &&
svn log -v | fgrep "SVN-side change inside of www/test_www.txt"
)
'
test_expect_success 'update git svn-cloned repo' '
(
cd g &&
git svn rebase --ignore-paths="^www" &&
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 ignored www' '
(
cd s &&
echo cvf >> www/test_www.txt
echo ygg >> qqq/test_qqq.txt
svn commit -m "SVN-side change in and out of ignored www" &&
svn up &&
svn log -v | fgrep "SVN-side change in and out of ignored www"
)
'
test_expect_success 'update git svn-cloned repo again' '
(
cd g &&
git svn rebase --ignore-paths="^www" &&
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