diff options
Diffstat (limited to 'git-svn.perl')
-rwxr-xr-x | git-svn.perl | 98 |
1 files changed, 91 insertions, 7 deletions
diff --git a/git-svn.perl b/git-svn.perl index a366c891dc..cf6dbbc427 100755 --- a/git-svn.perl +++ b/git-svn.perl @@ -261,7 +261,7 @@ sub usage { my $fd = $exit ? \*STDERR : \*STDOUT; print $fd <<""; git-svn - bidirectional operations between a single Subversion tree and git -Usage: $0 <command> [options] [arguments]\n +Usage: git svn <command> [options] [arguments]\n print $fd "Available commands:\n" unless $cmd; @@ -537,13 +537,13 @@ sub cmd_find_rev { my $head = shift; $head ||= 'HEAD'; my @refs; - my (undef, undef, undef, $gs) = working_head_info($head, \@refs); + my (undef, undef, $uuid, $gs) = working_head_info($head, \@refs); unless ($gs) { die "Unable to determine upstream SVN information from ", "$head history\n"; } my $desired_revision = substr($revision_or_hash, 1); - $result = $gs->rev_map_get($desired_revision); + $result = $gs->rev_map_get($desired_revision, $uuid); } else { my (undef, $rev, undef) = cmt_metadata($revision_or_hash); $result = $rev; @@ -1162,7 +1162,7 @@ sub working_head_info { if (defined $url && defined $rev) { next if $max{$url} and $max{$url} < $rev; if (my $gs = Git::SVN->find_by_url($url)) { - my $c = $gs->rev_map_get($rev); + my $c = $gs->rev_map_get($rev, $uuid); if ($c && $c eq $hash) { close $fh; # break the pipe return ($url, $rev, $uuid, $gs); @@ -1226,7 +1226,7 @@ sub linearize_history { sub find_file_type_and_diff_status { my ($path) = @_; - return ('dir', '') if $path eq '.'; + return ('dir', '') if $path eq ''; my $diff_output = command_oneline(qw(diff --cached --name-status --), $path) || ""; @@ -1416,11 +1416,17 @@ sub fetch_all { sub read_all_remotes { my $r = {}; + my $use_svm_props = eval { command_oneline(qw/config --bool + svn.useSvmProps/) }; + $use_svm_props = $use_svm_props eq 'true' if $use_svm_props; foreach (grep { s/^svn-remote\.// } command(qw/config -l/)) { if (m!^(.+)\.fetch=\s*(.*)\s*:\s*refs/remotes/(.+)\s*$!) { my ($remote, $local_ref, $remote_ref) = ($1, $2, $3); $local_ref =~ s{^/}{}; $r->{$remote}->{fetch}->{$local_ref} = $remote_ref; + $r->{$remote}->{svm} = {} if $use_svm_props; + } elsif (m!^(.+)\.usesvmprops=\s*(.*)\s*$!) { + $r->{$1}->{svm} = {}; } elsif (m!^(.+)\.url=\s*(.*)\s*$!) { $r->{$1}->{url} = $2; } elsif (m!^(.+)\.(branches|tags)= @@ -1437,6 +1443,23 @@ sub read_all_remotes { } } } + + map { + if (defined $r->{$_}->{svm}) { + my $svm; + eval { + my $section = "svn-remote.$_"; + $svm = { + source => tmp_config('--get', + "$section.svm-source"), + replace => tmp_config('--get', + "$section.svm-replace"), + } + }; + $r->{$_}->{svm} = $svm; + } + } keys %$r; + $r; } @@ -1563,13 +1586,21 @@ sub find_by_url { # repos_root and, path are optional } my $p = $path; my $rwr = rewrite_root({repo_id => $repo_id}); + my $svm = $remotes->{$repo_id}->{svm} + if defined $remotes->{$repo_id}->{svm}; unless (defined $p) { $p = $full_url; my $z = $u; + my $prefix = ''; if ($rwr) { $z = $rwr; + } elsif (defined $svm) { + $z = $svm->{source}; + $prefix = $svm->{replace}; + $prefix =~ s#^\Q$u\E(?:/|$)##; + $prefix =~ s#/$##; } - $p =~ s#^\Q$z\E(?:/|$)## or next; + $p =~ s#^\Q$z\E(?:/|$)#$prefix# or next; } foreach my $f (keys %$fetch) { next if $f ne $p; @@ -3309,6 +3340,7 @@ sub new { $self->{rm} = { }; $self->{path_prefix} = length $self->{svn_path} ? "$self->{svn_path}/" : ''; + $self->{config} = $opts->{config}; return $self; } @@ -3497,6 +3529,57 @@ sub ensure_path { return $bat->{$c}; } +# Subroutine to convert a globbing pattern to a regular expression. +# From perl cookbook. +sub glob2pat { + my $globstr = shift; + my %patmap = ('*' => '.*', '?' => '.', '[' => '[', ']' => ']'); + $globstr =~ s{(.)} { $patmap{$1} || "\Q$1" }ge; + return '^' . $globstr . '$'; +} + +sub check_autoprop { + my ($self, $pattern, $properties, $file, $fbat) = @_; + # Convert the globbing pattern to a regular expression. + my $regex = glob2pat($pattern); + # Check if the pattern matches the file name. + if($file =~ m/($regex)/) { + # Parse the list of properties to set. + my @props = split(/;/, $properties); + foreach my $prop (@props) { + # Parse 'name=value' syntax and set the property. + if ($prop =~ /([^=]+)=(.*)/) { + my ($n,$v) = ($1,$2); + for ($n, $v) { + s/^\s+//; s/\s+$//; + } + $self->change_file_prop($fbat, $n, $v); + } + } + } +} + +sub apply_autoprops { + my ($self, $file, $fbat) = @_; + my $conf_t = ${$self->{config}}{'config'}; + no warnings 'once'; + # Check [miscellany]/enable-auto-props in svn configuration. + if (SVN::_Core::svn_config_get_bool( + $conf_t, + $SVN::_Core::SVN_CONFIG_SECTION_MISCELLANY, + $SVN::_Core::SVN_CONFIG_OPTION_ENABLE_AUTO_PROPS, + 0)) { + # Auto-props are enabled. Enumerate them to look for matches. + my $callback = sub { + $self->check_autoprop($_[0], $_[1], $file, $fbat); + }; + SVN::_Core::svn_config_enumerate( + $conf_t, + $SVN::_Core::SVN_CONFIG_SECTION_AUTO_PROPS, + $callback); + } +} + sub A { my ($self, $m) = @_; my ($dir, $file) = split_path($m->{file_b}); @@ -3504,6 +3587,7 @@ sub A { my $fbat = $self->add_file($self->repo_path($m->{file_b}), $pbat, undef, -1); print "\tA\t$m->{file_b}\n" unless $::_q; + $self->apply_autoprops($file, $fbat); $self->chg_file($fbat, $m); $self->close_file($fbat,undef,$self->{pool}); } @@ -4619,7 +4703,7 @@ sub migrate_from_v1 { mkpath([$svn_dir]); print STDERR "Data from a previous version of git-svn exists, but\n\t", "$svn_dir\n\t(required for this version ", - "($::VERSION) of git-svn) does not. exist\n"; + "($::VERSION) of git-svn) does not exist.\n"; my ($fh, $ctx) = command_output_pipe(qw/rev-parse --symbolic --all/); while (<$fh>) { my $x = $_; |