From 01bdab84e31763a98206c31cf99b9dc3cb221356 Mon Sep 17 00:00:00 2001 From: Benoit Sigoure Date: Tue, 16 Oct 2007 16:36:48 +0200 Subject: [PATCH] git-svn: add a generic tree traversal to fetch SVN properties * git-svn.perl (&traverse_ignore): Remove. (&prop_walk): New. (&cmd_show_ignore): Use prop_walk. [ew: This will ease the implementation of the `create-ignore', `propget', and `proplist' commands] Signed-off-by: Benoit Sigoure Acked-by: Eric Wong Signed-off-by: Shawn O. Pearce --- git-svn.perl | 65 ++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 45 insertions(+), 20 deletions(-) diff --git a/git-svn.perl b/git-svn.perl index 1130a0949..e217cdf27 100755 --- a/git-svn.perl +++ b/git-svn.perl @@ -488,7 +488,15 @@ sub cmd_show_ignore { my ($url, $rev, $uuid, $gs) = working_head_info('HEAD'); $gs ||= Git::SVN->new; my $r = (defined $_revision ? $_revision : $gs->ra->get_latest_revnum); - $gs->traverse_ignore(\*STDOUT, $gs->{path}, $r); + $gs->prop_walk($gs->{path}, $r, sub { + my ($gs, $path, $props) = @_; + print STDOUT "\n# $path\n"; + my $s = $props->{'svn:ignore'} or return; + $s =~ s/[\r\n]+/\n/g; + chomp $s; + $s =~ s#^#$path#gm; + print STDOUT "$s\n"; + }); } sub cmd_multi_init { @@ -1480,28 +1488,45 @@ sub rel_path { $url; } -sub traverse_ignore { - my ($self, $fh, $path, $r) = @_; - $path =~ s#^/+##g; - my $ra = $self->ra; - my ($dirent, undef, $props) = $ra->get_dir($path, $r); +# prop_walk(PATH, REV, SUB) +# ------------------------- +# Recursively traverse PATH at revision REV and invoke SUB for each +# directory that contains a SVN property. SUB will be invoked as +# follows: &SUB(gs, path, props); where `gs' is this instance of +# Git::SVN, `path' the path to the directory where the properties +# `props' were found. The `path' will be relative to point of checkout, +# that is, if url://repo/trunk is the current Git branch, and that +# directory contains a sub-directory `d', SUB will be invoked with `/d/' +# as `path' (note the trailing `/'). +sub prop_walk { + my ($self, $path, $rev, $sub) = @_; + + my ($dirent, undef, $props) = $self->ra->get_dir($path, $rev); + $path =~ s#^/*#/#g; my $p = $path; - $p =~ s#^\Q$self->{path}\E(/|$)##; - print $fh length $p ? "\n# $p\n" : "\n# /\n"; - if (my $s = $props->{'svn:ignore'}) { - $s =~ s/[\r\n]+/\n/g; - chomp $s; - if (length $p == 0) { - $s =~ s#\n#\n/$p#g; - print $fh "/$s\n"; - } else { - $s =~ s#\n#\n/$p/#g; - print $fh "/$p/$s\n"; - } - } + # Strip the irrelevant part of the path. + $p =~ s#^/+\Q$self->{path}\E(/|$)#/#; + # Ensure the path is terminated by a `/'. + $p =~ s#/*$#/#; + + # The properties contain all the internal SVN stuff nobody + # (usually) cares about. + my $interesting_props = 0; + foreach (keys %{$props}) { + # If it doesn't start with `svn:', it must be a + # user-defined property. + ++$interesting_props and next if $_ !~ /^svn:/; + # FIXME: Fragile, if SVN adds new public properties, + # this needs to be updated. + ++$interesting_props if /^svn:(?:ignore|keywords|executable + |eol-style|mime-type + |externals|needs-lock)$/x; + } + &$sub($self, $p, $props) if $interesting_props; + foreach (sort keys %$dirent) { next if $dirent->{$_}->{kind} != $SVN::Node::dir; - $self->traverse_ignore($fh, "$path/$_", $r); + $self->prop_walk($path . '/' . $_, $rev, $sub); } } -- 2.30.2