Git development
 help / color / mirror / Atom feed
* Re: Switching from CVS to GIT
From: Eli Zaretskii @ 2007-10-16 15:12 UTC (permalink / raw)
  To: Johannes Schindelin
  Cc: prohaska, git, robin.rosenberg.lists, barkalow, raa.lkml, tsuna,
	ae
In-Reply-To: <Pine.LNX.4.64.0710161512450.25221@racer.site>

> Date: Tue, 16 Oct 2007 15:14:19 +0100 (BST)
> From: Johannes Schindelin <Johannes.Schindelin@gmx.de>
> cc: Git Mailing List <git@vger.kernel.org>, 
>     Robin Rosenberg <robin.rosenberg.lists@dewire.com>, 
>     Eli Zaretskii <eliz@gnu.org>, Daniel Barkalow <barkalow@iabervon.org>, 
>     Alex Riesen <raa.lkml@gmail.com>, tsuna@lrde.epita.fr, 
>     Andreas Ericsson <ae@op5.se>
> 
> So I think this will always be something Windows users would wish to 
> impose onto others, while Linux users would always refuse.

Here is one Windows user that will never try to impose that ;-)

However, it's possible that an option could be supported to do that
when the user particularly wants that in her database.  Just a
thought...

^ permalink raw reply

* Re: [PATCHv2 1/5] Add a generic tree traversal to fetch SVN properties.
From: Benoit SIGOURE @ 2007-10-16 15:10 UTC (permalink / raw)
  To: Johannes Sixt; +Cc: git list
In-Reply-To: <4714D068.8090606@viscovery.net>

[-- Attachment #1: Type: text/plain, Size: 1149 bytes --]

On Oct 16, 2007, at 4:53 PM, Johannes Sixt wrote:

> Benoit Sigoure schrieb:
>> 	* git-svn.perl (&traverse_ignore): Remove.
>> 	(&prop_walk): New.
>> 	(&cmd_show_ignore): Use prop_walk.
>
> This may be your favorite style of commit messaged, but I think the  
> concensus for git is a different style of commit message: We would  
> like to see *why* this change is good. But you only note *what* was  
> changed, something that can be seen by looking at the patch anyway.
>
> The commit message should be helpful when the commit is looked at  
> in isolation, like when you are doing some code archeology half a  
> year later and e.g. git-blame/git-bisect points you to this commit.
>
> Also a notice such as
>
>  "With this we will be able to lift properties like svn:ignore into
>   .gitignore in a follow-up change."
>
> tells that this was actually part of a series and you don't have to  
> remember that half a year ago there were 4 more patches submitted  
> in the same second with this one.

Indeed, sorry, I'll write more explanatory commit messages next time :)

-- 
Benoit Sigoure aka Tsuna
EPITA Research and Development Laboratory



[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 186 bytes --]

^ permalink raw reply

* Re: Switching from CVS to GIT
From: Eli Zaretskii @ 2007-10-16 15:02 UTC (permalink / raw)
  To: Johannes Schindelin; +Cc: barkalow, raa.lkml, ae, tsuna, git
In-Reply-To: <Pine.LNX.4.64.0710161422110.25221@racer.site>

> Date: Tue, 16 Oct 2007 14:24:34 +0100 (BST)
> From: Johannes Schindelin <Johannes.Schindelin@gmx.de>
> cc: barkalow@iabervon.org, raa.lkml@gmail.com, ae@op5.se, tsuna@lrde.epita.fr, 
>     git@vger.kernel.org
> 
> Funny.  Last time I checked the toolbar went away, as well as the desktop, 
> when I killed explorer.exe.

That's a ``feature'': Explorer is the parent of all the desktop
display.  Kinda like the login shell on Unix: if you kill it, there
goes your whole session.  Except that on Windows, the OS pays
attention and restarts Explorer right away to get you back in
business.  (In first versions of Windows, there was no restarting of
Explorer, so if you killed it, you needed to reboot :-()

^ permalink raw reply

* Re: [PATCHv2 1/5] Add a generic tree traversal to fetch SVN properties.
From: Johannes Sixt @ 2007-10-16 14:53 UTC (permalink / raw)
  To: Benoit Sigoure; +Cc: git, normalperson
In-Reply-To: <1192545412-10929-1-git-send-email-tsuna@lrde.epita.fr>

Benoit Sigoure schrieb:
> 	* git-svn.perl (&traverse_ignore): Remove.
> 	(&prop_walk): New.
> 	(&cmd_show_ignore): Use prop_walk.

This may be your favorite style of commit messaged, but I think the 
concensus for git is a different style of commit message: We would like to 
see *why* this change is good. But you only note *what* was changed, 
something that can be seen by looking at the patch anyway.

The commit message should be helpful when the commit is looked at in 
isolation, like when you are doing some code archeology half a year later 
and e.g. git-blame/git-bisect points you to this commit.

Also a notice such as

  "With this we will be able to lift properties like svn:ignore into
   .gitignore in a follow-up change."

tells that this was actually part of a series and you don't have to remember 
that half a year ago there were 4 more patches submitted in the same second 
with this one.

-- Hannes

^ permalink raw reply

* Re: should git command and git-command be equivalent?
From: Matthieu Moy @ 2007-10-16 14:46 UTC (permalink / raw)
  To: David Symonds; +Cc: franky, git
In-Reply-To: <ee77f5c20710160528k520704d7pd3cf99dea1f83a77@mail.gmail.com>

"David Symonds" <dsymonds@gmail.com> writes:

> If you use the contrib/completion/git-completion.bash script, you can
> type "git st<TAB>", and it'll complete it for you. Well, it did, until
> git-stash came along and ruined it...
>
> At any rate, the bash completion also completes things like branch
> names, which can be immensely helpful.

I don't use bash, but the zsh completion for git is also excellent.

But "git st" is still one less key to type than "git st<tab>" ;-).

-- 
Matthieu

^ permalink raw reply

* [PATCHv2 5/5] Simplify the handling of fatal errors.
From: Benoit Sigoure @ 2007-10-16 14:36 UTC (permalink / raw)
  To: git; +Cc: normalperson, Benoit Sigoure
In-Reply-To: <1192545412-10929-4-git-send-email-tsuna@lrde.epita.fr>

	* git-svn.perl (&fatal): Append the newline at the end of the error
	message.
	Adjust all callers.

Signed-off-by: Benoit Sigoure <tsuna@lrde.epita.fr>
---
 git-svn.perl |   42 +++++++++++++++++++++---------------------
 1 files changed, 21 insertions(+), 21 deletions(-)

diff --git a/git-svn.perl b/git-svn.perl
index 8efe949..656493a 100755
--- a/git-svn.perl
+++ b/git-svn.perl
@@ -21,12 +21,12 @@ $Git::SVN::Log::TZ = $ENV{TZ};
 $ENV{TZ} = 'UTC';
 $| = 1; # unbuffer STDOUT
 
-sub fatal (@) { print STDERR @_; exit 1 }
+sub fatal (@) { print STDERR "@_\n"; exit 1 }
 require SVN::Core; # use()-ing this causes segfaults for me... *shrug*
 require SVN::Ra;
 require SVN::Delta;
 if ($SVN::Core::VERSION lt '1.1.0') {
-	fatal "Need SVN::Core 1.1.0 or better (got $SVN::Core::VERSION)\n";
+	fatal "Need SVN::Core 1.1.0 or better (got $SVN::Core::VERSION)";
 }
 push @Git::SVN::Ra::ISA, 'SVN::Ra';
 push @SVN::Git::Editor::ISA, 'SVN::Delta::Editor';
@@ -369,7 +369,7 @@ sub cmd_set_tree {
 		} elsif (scalar @tmp > 1) {
 			push @revs, reverse(command('rev-list',@tmp));
 		} else {
-			fatal "Failed to rev-parse $c\n";
+			fatal "Failed to rev-parse $c";
 		}
 	}
 	my $gs = Git::SVN->new;
@@ -379,7 +379,7 @@ sub cmd_set_tree {
 		fatal "There are new revisions that were fetched ",
 		      "and need to be merged (or acknowledged) ",
 		      "before committing.\nlast rev: $r_last\n",
-		      " current: $gs->{last_rev}\n";
+		      " current: $gs->{last_rev}";
 	}
 	$gs->set_tree($_) foreach @revs;
 	print "Done committing ",scalar @revs," revisions to SVN\n";
@@ -408,7 +408,7 @@ sub cmd_dcommit {
 			(undef, $last_rev, undef) = cmt_metadata("$d~1");
 			unless (defined $last_rev) {
 				fatal "Unable to extract revision information ",
-				      "from commit $d~1\n";
+				      "from commit $d~1";
 			}
 		}
 		if ($_dry_run) {
@@ -521,7 +521,7 @@ sub cmd_create_ignore {
 		my $ignore = '.' . $path . '.gitignore';
 		my $s = $props->{'svn:ignore'} or return;
 		open(GITIGNORE, '>', $ignore)
-		  or fatal("Failed to open `$ignore' for writing: $!\n");
+		  or fatal("Failed to open `$ignore' for writing: $!");
 		$s =~ s/[\r\n]+/\n/g;
 		chomp $s;
 		# Prefix all patterns so that the ignore doesn't apply
@@ -529,7 +529,7 @@ sub cmd_create_ignore {
 		$s =~ s#^#/#gm;
 		print GITIGNORE "$s\n";
 		close(GITIGNORE)
-		  or fatal("Failed to close `$ignore': $!\n");
+		  or fatal("Failed to close `$ignore': $!");
 		command_noisy('add', $ignore);
 	});
 }
@@ -545,7 +545,7 @@ sub get_svnprops {
 	# prefix THE PATH by the sub-directory from which the user
 	# invoked us.
 	$path = $cmd_dir_prefix . $path;
-	fatal("No such file or directory: $path\n") unless -e $path;
+	fatal("No such file or directory: $path") unless -e $path;
 	my $is_dir = -d $path ? 1 : 0;
 	$path = $gs->{path} . '/' . $path;
 
@@ -578,7 +578,7 @@ sub cmd_propget {
 	usage(1) if not defined $prop;
 	my $props = get_svnprops($path);
 	if (not defined $props->{$prop}) {
-		fatal("`$path' does not have a `$prop' SVN property.\n");
+		fatal("`$path' does not have a `$prop' SVN property.");
 	}
 	print $props->{$prop} . "\n";
 }
@@ -642,7 +642,7 @@ sub cmd_multi_fetch {
 sub cmd_commit_diff {
 	my ($ta, $tb, $url) = @_;
 	my $usage = "Usage: $0 commit-diff -r<revision> ".
-	            "<tree-ish> <tree-ish> [<URL>]\n";
+	            "<tree-ish> <tree-ish> [<URL>]";
 	fatal($usage) if (!defined $ta || !defined $tb);
 	my $svn_path;
 	if (!defined $url) {
@@ -660,7 +660,7 @@ sub cmd_commit_diff {
 	if (defined $_message && defined $_file) {
 		fatal("Both --message/-m and --file/-F specified ",
 		      "for the commit message.\n",
-		      "I have no idea what you mean\n");
+		      "I have no idea what you mean");
 	}
 	if (defined $_file) {
 		$_message = file_to_s($_file);
@@ -723,7 +723,7 @@ sub complete_svn_url {
 	if ($path !~ m#^[a-z\+]+://#) {
 		if (!defined $url || $url !~ m#^[a-z\+]+://#) {
 			fatal("E: '$path' is not a complete URL ",
-			      "and a separate URL is not specified\n");
+			      "and a separate URL is not specified");
 		}
 		return ($url, $path);
 	}
@@ -744,7 +744,7 @@ sub complete_url_ls_init {
 		$repo_path =~ s#^/+##;
 		unless ($ra) {
 			fatal("E: '$repo_path' is not a complete URL ",
-			      "and a separate URL is not specified\n");
+			      "and a separate URL is not specified");
 		}
 	}
 	my $url = $ra->{url};
@@ -1750,7 +1750,7 @@ sub assert_index_clean {
 		$x = command_oneline('write-tree');
 		if ($y ne $x) {
 			::fatal "trees ($treeish) $y != $x\n",
-			        "Something is seriously wrong...\n";
+			        "Something is seriously wrong...";
 		}
 	});
 }
@@ -2176,7 +2176,7 @@ sub set_tree {
 	my ($self, $tree) = (shift, shift);
 	my $log_entry = ::get_commit_entry($tree);
 	unless ($self->{last_rev}) {
-		fatal("Must have an existing revision to commit\n");
+		fatal("Must have an existing revision to commit");
 	}
 	my %ed_opts = ( r => $self->{last_rev},
 	                log => $log_entry->{log},
@@ -3126,7 +3126,7 @@ sub apply_diff {
 		if (defined $o{$f}) {
 			$self->$f($m);
 		} else {
-			fatal("Invalid change type: $f\n");
+			fatal("Invalid change type: $f");
 		}
 	}
 	$self->rmdirs if $_rmdir;
@@ -3734,15 +3734,15 @@ sub config_pager {
 sub run_pager {
 	return unless -t *STDOUT && defined $pager;
 	pipe my $rfd, my $wfd or return;
-	defined(my $pid = fork) or ::fatal "Can't fork: $!\n";
+	defined(my $pid = fork) or ::fatal "Can't fork: $!";
 	if (!$pid) {
 		open STDOUT, '>&', $wfd or
-		                     ::fatal "Can't redirect to stdout: $!\n";
+		                     ::fatal "Can't redirect to stdout: $!";
 		return;
 	}
-	open STDIN, '<&', $rfd or ::fatal "Can't redirect stdin: $!\n";
+	open STDIN, '<&', $rfd or ::fatal "Can't redirect stdin: $!";
 	$ENV{LESS} ||= 'FRSX';
-	exec $pager or ::fatal "Can't run pager: $! ($pager)\n";
+	exec $pager or ::fatal "Can't run pager: $! ($pager)";
 }
 
 sub tz_to_s_offset {
@@ -3878,7 +3878,7 @@ sub cmd_show_log {
 			$r_min = $r_max = $::_revision;
 		} else {
 			::fatal "-r$::_revision is not supported, use ",
-				"standard \'git log\' arguments instead\n";
+				"standard 'git log' arguments instead";
 		}
 	}
 
-- 
1.5.3.4.214.g6f43

^ permalink raw reply related

* [PATCHv2 4/5] Add git svn proplist.
From: Benoit Sigoure @ 2007-10-16 14:36 UTC (permalink / raw)
  To: git; +Cc: normalperson, Benoit Sigoure
In-Reply-To: <1192545412-10929-3-git-send-email-tsuna@lrde.epita.fr>

	* git-svn.perl (%cmd): Add the command `proplist'.
	(&cmd_proplist): New.
	* t/t9101-git-svn-props.sh: Test git svn proplist.

Signed-off-by: Benoit Sigoure <tsuna@lrde.epita.fr>
---
 git-svn.perl             |   18 +++++++++++++++++-
 t/t9101-git-svn-props.sh |   21 +++++++++++++++++++++
 2 files changed, 38 insertions(+), 1 deletions(-)

diff --git a/git-svn.perl b/git-svn.perl
index 40be2c4..8efe949 100755
--- a/git-svn.perl
+++ b/git-svn.perl
@@ -132,6 +132,9 @@ my %cmd = (
         'propget' => [ \&cmd_propget,
 		       'Print the value of a property on a file or directory',
 		       { 'revision|r=i' => \$_revision } ],
+        'proplist' => [ \&cmd_proplist,
+		       'List all properties of a file or directory',
+		       { 'revision|r=i' => \$_revision } ],
 	'show-ignore' => [ \&cmd_show_ignore, "Show svn:ignore listings",
 			{ 'revision|r=i' => \$_revision
 			} ],
@@ -533,7 +536,7 @@ sub cmd_create_ignore {
 
 # get_svnprops(PATH)
 # ------------------
-# Helper for cmd_propget below.
+# Helper for cmd_propget and cmd_proplist below.
 sub get_svnprops {
 	my $path = shift;
 	my ($url, $rev, $uuid, $gs) = working_head_info('HEAD');
@@ -580,6 +583,19 @@ sub cmd_propget {
 	print $props->{$prop} . "\n";
 }
 
+# cmd_proplist (PATH)
+# -------------------
+# Print the list of SVN properties for PATH.
+sub cmd_proplist {
+	my $path = shift;
+	$path = '.' if not defined $path;
+	my $props = get_svnprops($path);
+	print "Properties on '$path':\n";
+	foreach (sort keys %{$props}) {
+		print "  $_\n";
+	}
+}
+
 sub cmd_multi_init {
 	my $url = shift;
 	unless (defined $_trunk || defined $_branches || defined $_tags) {
diff --git a/t/t9101-git-svn-props.sh b/t/t9101-git-svn-props.sh
index 61c8799..3c83127 100755
--- a/t/t9101-git-svn-props.sh
+++ b/t/t9101-git-svn-props.sh
@@ -193,4 +193,25 @@ test_expect_success 'test propget' "
 	git-svn propget svn:ignore .././deeply/nested | cmp - ../prop.expect
 	"
 
+cat >prop.expect <<\EOF
+Properties on '.':
+  svn:entry:committed-date
+  svn:entry:committed-rev
+  svn:entry:last-author
+  svn:entry:uuid
+  svn:ignore
+EOF
+cat >prop2.expect <<\EOF
+Properties on 'nested/directory/.keep':
+  svn:entry:committed-date
+  svn:entry:committed-rev
+  svn:entry:last-author
+  svn:entry:uuid
+EOF
+
+test_expect_success 'test proplist' "
+	git-svn proplist . | cmp - prop.expect &&
+	git-svn proplist nested/directory/.keep | cmp - prop2.expect
+	"
+
 test_done
-- 
1.5.3.4.214.g6f43

^ permalink raw reply related

* [PATCHv2 1/5] Add a generic tree traversal to fetch SVN properties.
From: Benoit Sigoure @ 2007-10-16 14:36 UTC (permalink / raw)
  To: git; +Cc: normalperson, Benoit Sigoure

	* git-svn.perl (&traverse_ignore): Remove.
	(&prop_walk): New.
	(&cmd_show_ignore): Use prop_walk.

Signed-off-by: Benoit Sigoure <tsuna@lrde.epita.fr>
---
 git-svn.perl |   65 ++++++++++++++++++++++++++++++++++++++++-----------------
 1 files changed, 45 insertions(+), 20 deletions(-)

diff --git a/git-svn.perl b/git-svn.perl
index 777e436..95393b6 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);
 	}
 }
 
-- 
1.5.3.4.214.g6f43

^ permalink raw reply related

* [PATCHv2 3/5] Add git svn propget.
From: Benoit Sigoure @ 2007-10-16 14:36 UTC (permalink / raw)
  To: git; +Cc: normalperson, Benoit Sigoure
In-Reply-To: <1192545412-10929-2-git-send-email-tsuna@lrde.epita.fr>

	* git-svn.perl (%cmd): Add the new command `propget'.
	($cmd_dir_prefix): New global.
	(&get_svnprops): New helper.
	(&cmd_propget): New.  Use &get_svnprops.
	* t/t9101-git-svn-props.sh: Add a test case for propget.

Signed-off-by: Benoit Sigoure <tsuna@lrde.epita.fr>
---
 git-svn.perl             |   54 ++++++++++++++++++++++++++++++++++++++++++++++
 t/t9101-git-svn-props.sh |   23 +++++++++++++++++++
 2 files changed, 77 insertions(+), 0 deletions(-)

diff --git a/git-svn.perl b/git-svn.perl
index 4d643d7..40be2c4 100755
--- a/git-svn.perl
+++ b/git-svn.perl
@@ -9,6 +9,8 @@ use vars qw/	$AUTHOR $VERSION
 $AUTHOR = 'Eric Wong <normalperson@yhbt.net>';
 $VERSION = '@@GIT_VERSION@@';
 
+# From which subdir have we been invoked?
+my $cmd_dir_prefix = command_oneline(qw/rev-parse --show-prefix/) || '';
 my $git_dir_user_set = 1 if defined $ENV{GIT_DIR};
 $ENV{GIT_DIR} ||= '.git';
 $Git::SVN::default_repo_id = 'svn';
@@ -127,6 +129,9 @@ my %cmd = (
 			     'Create a .gitignore per svn:ignore',
 			     { 'revision|r=i' => \$_revision
 			     } ],
+        'propget' => [ \&cmd_propget,
+		       'Print the value of a property on a file or directory',
+		       { 'revision|r=i' => \$_revision } ],
 	'show-ignore' => [ \&cmd_show_ignore, "Show svn:ignore listings",
 			{ 'revision|r=i' => \$_revision
 			} ],
@@ -526,6 +531,55 @@ sub cmd_create_ignore {
 	});
 }
 
+# get_svnprops(PATH)
+# ------------------
+# Helper for cmd_propget below.
+sub get_svnprops {
+	my $path = shift;
+	my ($url, $rev, $uuid, $gs) = working_head_info('HEAD');
+	$gs ||= Git::SVN->new;
+
+	# prefix THE PATH by the sub-directory from which the user
+	# invoked us.
+	$path = $cmd_dir_prefix . $path;
+	fatal("No such file or directory: $path\n") unless -e $path;
+	my $is_dir = -d $path ? 1 : 0;
+	$path = $gs->{path} . '/' . $path;
+
+	# canonicalize the path (otherwise libsvn will abort or fail to
+	# find the file)
+	# File::Spec->canonpath doesn't collapse x/../y into y (for a
+	# good reason), so let's do this manually.
+	$path =~ s#/+#/#g;
+	$path =~ s#/\.(?:/|$)#/#g;
+	$path =~ s#/[^/]+/\.\.##g;
+	$path =~ s#/$##g;
+
+	my $r = (defined $_revision ? $_revision : $gs->ra->get_latest_revnum);
+	my $props;
+	if ($is_dir) {
+		(undef, undef, $props) = $gs->ra->get_dir($path, $r);
+	}
+	else {
+		(undef, $props) = $gs->ra->get_file($path, $r, undef);
+	}
+	return $props;
+}
+
+# cmd_propget (PROP, PATH)
+# ------------------------
+# Print the SVN property PROP for PATH.
+sub cmd_propget {
+	my ($prop, $path) = @_;
+	$path = '.' if not defined $path;
+	usage(1) if not defined $prop;
+	my $props = get_svnprops($path);
+	if (not defined $props->{$prop}) {
+		fatal("`$path' does not have a `$prop' SVN property.\n");
+	}
+	print $props->{$prop} . "\n";
+}
+
 sub cmd_multi_init {
 	my $url = shift;
 	unless (defined $_trunk || defined $_branches || defined $_tags) {
diff --git a/t/t9101-git-svn-props.sh b/t/t9101-git-svn-props.sh
index 796d80e..61c8799 100755
--- a/t/t9101-git-svn-props.sh
+++ b/t/t9101-git-svn-props.sh
@@ -170,4 +170,27 @@ test_expect_success 'test create-ignore' "
 	git ls-files -s | grep gitignore | cmp - create-ignore-index.expect
 	"
 
+cat >prop.expect <<\EOF
+no-such-file*
+
+EOF
+cat >prop2.expect <<\EOF
+8
+EOF
+
+# This test can be improved: since all the svn:ignore contain the same
+# pattern, it can pass even though the propget did not execute on the
+# right directory.
+test_expect_success 'test propget' "
+	git-svn propget svn:ignore . | cmp - prop.expect &&
+	cd deeply &&
+	git-svn propget svn:ignore . | cmp - ../prop.expect &&
+	git-svn propget svn:entry:committed-rev nested/directory/.keep \
+	  | cmp - ../prop2.expect &&
+	git-svn propget svn:ignore .. | cmp - ../prop.expect &&
+	git-svn propget svn:ignore nested/ | cmp - ../prop.expect &&
+	git-svn propget svn:ignore ./nested | cmp - ../prop.expect &&
+	git-svn propget svn:ignore .././deeply/nested | cmp - ../prop.expect
+	"
+
 test_done
-- 
1.5.3.4.214.g6f43

^ permalink raw reply related

* [PATCH 0/5] Add easy access to SVN properties in git-svn.
From: Benoit Sigoure @ 2007-10-15 15:34 UTC (permalink / raw)
  To: git; +Cc: normalperson


Hello,
this is a fairly simple patch series that adds easy access to SVN properties
from within git-svn.

The first patch simply factors some code that was used for
git-svn show-ignore in order to easily implement git-svn create-ignore (2nd
patch).  The 3rd and 4th patch implement git-svn propget / proplist to easily
access SVN properties.  The last patch does some cleanup because I found it
more convenient to not have to remember to add a `\n' at the end of each
error message.

 git-svn.perl             |  201 +++++++++++++++++++++++++++++++++++++---------
 t/t9101-git-svn-props.sh |   72 ++++++++++++++++-
 2 files changed, 233 insertions(+), 40 deletions(-)

^ permalink raw reply

* [PATCHv2 2/5] Implement git svn create-ignore.
From: Benoit Sigoure @ 2007-10-16 14:36 UTC (permalink / raw)
  To: git; +Cc: normalperson, Benoit Sigoure
In-Reply-To: <1192545412-10929-1-git-send-email-tsuna@lrde.epita.fr>

	* git-svn.perl (%cmd): Add the new command `create-ignore'.
	(&cmd_create_ignore): New.
	* t/t9101-git-svn-props.sh: Adjust the test-case for show-ignore and
	add a test case for create-ignore.

Signed-off-by: Benoit Sigoure <tsuna@lrde.epita.fr>
---
 git-svn.perl             |   27 +++++++++++++++++++++++++++
 t/t9101-git-svn-props.sh |   28 +++++++++++++++++++++++++---
 2 files changed, 52 insertions(+), 3 deletions(-)

diff --git a/git-svn.perl b/git-svn.perl
index 95393b6..4d643d7 100755
--- a/git-svn.perl
+++ b/git-svn.perl
@@ -123,6 +123,10 @@ my %cmd = (
 	'set-tree' => [ \&cmd_set_tree,
 	                "Set an SVN repository to a git tree-ish",
 			{ 'stdin|' => \$_stdin, %cmt_opts, %fc_opts, } ],
+	'create-ignore' => [ \&cmd_create_ignore,
+			     'Create a .gitignore per svn:ignore',
+			     { 'revision|r=i' => \$_revision
+			     } ],
 	'show-ignore' => [ \&cmd_show_ignore, "Show svn:ignore listings",
 			{ 'revision|r=i' => \$_revision
 			} ],
@@ -499,6 +503,29 @@ sub cmd_show_ignore {
 	});
 }
 
+sub cmd_create_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->prop_walk($gs->{path}, $r, sub {
+		my ($gs, $path, $props) = @_;
+		# $path is of the form /path/to/dir/
+		my $ignore = '.' . $path . '.gitignore';
+		my $s = $props->{'svn:ignore'} or return;
+		open(GITIGNORE, '>', $ignore)
+		  or fatal("Failed to open `$ignore' for writing: $!\n");
+		$s =~ s/[\r\n]+/\n/g;
+		chomp $s;
+		# Prefix all patterns so that the ignore doesn't apply
+		# to sub-directories.
+		$s =~ s#^#/#gm;
+		print GITIGNORE "$s\n";
+		close(GITIGNORE)
+		  or fatal("Failed to close `$ignore': $!\n");
+		command_noisy('add', $ignore);
+	});
+}
+
 sub cmd_multi_init {
 	my $url = shift;
 	unless (defined $_trunk || defined $_branches || defined $_tags) {
diff --git a/t/t9101-git-svn-props.sh b/t/t9101-git-svn-props.sh
index 5aac644..796d80e 100755
--- a/t/t9101-git-svn-props.sh
+++ b/t/t9101-git-svn-props.sh
@@ -126,19 +126,20 @@ cat > show-ignore.expect <<\EOF
 # /
 /no-such-file*
 
-# deeply
+# /deeply/
 /deeply/no-such-file*
 
-# deeply/nested
+# /deeply/nested/
 /deeply/nested/no-such-file*
 
-# deeply/nested/directory
+# /deeply/nested/directory/
 /deeply/nested/directory/no-such-file*
 EOF
 
 test_expect_success 'test show-ignore' "
 	cd test_wc &&
 	mkdir -p deeply/nested/directory &&
+	touch deeply/nested/directory/.keep &&
 	svn add deeply &&
 	svn up &&
 	svn propset -R svn:ignore 'no-such-file*' .
@@ -148,4 +149,25 @@ test_expect_success 'test show-ignore' "
 	cmp show-ignore.expect show-ignore.got
 	"
 
+cat >create-ignore.expect <<\EOF
+/no-such-file*
+EOF
+
+cat >create-ignore-index.expect <<\EOF
+100644 8c52e5dfcd0a8b6b6bcfe6b41b89bcbf493718a5 0	.gitignore
+100644 8c52e5dfcd0a8b6b6bcfe6b41b89bcbf493718a5 0	deeply/.gitignore
+100644 8c52e5dfcd0a8b6b6bcfe6b41b89bcbf493718a5 0	deeply/nested/.gitignore
+100644 8c52e5dfcd0a8b6b6bcfe6b41b89bcbf493718a5 0	deeply/nested/directory/.gitignore
+EOF
+
+test_expect_success 'test create-ignore' "
+	git-svn fetch && git pull . remotes/git-svn &&
+	git-svn create-ignore &&
+	cmp ./.gitignore create-ignore.expect &&
+	cmp ./deeply/.gitignore create-ignore.expect &&
+	cmp ./deeply/nested/.gitignore create-ignore.expect &&
+	cmp ./deeply/nested/directory/.gitignore create-ignore.expect &&
+	git ls-files -s | grep gitignore | cmp - create-ignore-index.expect
+	"
+
 test_done
-- 
1.5.3.4.214.g6f43

^ permalink raw reply related

* [PATCH 3/5] Add git svn propget.
From: Benoit Sigoure @ 2007-10-15 15:35 UTC (permalink / raw)
  To: git; +Cc: normalperson, Benoit Sigoure
In-Reply-To: <1192462506-3783-2-git-send-email-tsuna@lrde.epita.fr>

	* git-svn.perl (%cmd): Add the new command `propget'.
	($cmd_dir_prefix): New global.
	(&get_svnprops): New helper.
	(&cmd_propget): New.  Use &get_svnprops.
	* t/t9101-git-svn-props.sh: Add a test case for propget.

Signed-off-by: Benoit Sigoure <tsuna@lrde.epita.fr>
---
 git-svn.perl             |   57 ++++++++++++++++++++++++++++++++++++++++++++++
 t/t9101-git-svn-props.sh |   23 ++++++++++++++++++
 2 files changed, 80 insertions(+), 0 deletions(-)

diff --git a/git-svn.perl b/git-svn.perl
index 94091ea..e58ff38 100755
--- a/git-svn.perl
+++ b/git-svn.perl
@@ -9,6 +9,8 @@ use vars qw/	$AUTHOR $VERSION
 $AUTHOR = 'Eric Wong <normalperson@yhbt.net>';
 $VERSION = '@@GIT_VERSION@@';
 
+# From which subdir have we been invoked?
+my $cmd_dir_prefix = command_oneline(qw/rev-parse --show-prefix/) || '';
 my $git_dir_user_set = 1 if defined $ENV{GIT_DIR};
 $ENV{GIT_DIR} ||= '.git';
 $Git::SVN::default_repo_id = 'svn';
@@ -127,6 +129,9 @@ my %cmd = (
 			     'Create a .gitignore per svn:ignore',
 			     { 'revision|r=i' => \$_revision
 			     } ],
+        'propget' => [ \&cmd_propget,
+		       'Print the value of a property on a file or directory',
+		       { 'revision|r=i' => \$_revision } ],
 	'show-ignore' => [ \&cmd_show_ignore, "Show svn:ignore listings",
 			{ 'revision|r=i' => \$_revision
 			} ],
@@ -526,6 +531,58 @@ sub cmd_create_ignore {
 	});
 }
 
+# get_svnprops(PATH)
+# ------------------
+# Helper for cmd_propget below.
+sub get_svnprops {
+	my $path = shift;
+	my ($url, $rev, $uuid, $gs) = working_head_info('HEAD');
+	$gs ||= Git::SVN->new;
+
+	# prefix THE PATH by the sub-directory from which the user
+	# invoked us.
+	$path = $cmd_dir_prefix . $path;
+	fatal("No such file or directory: $path\n") unless -e $path;
+	my $is_dir = -d $path ? 1 : 0;
+	$path = $gs->{path} . '/' . $path;
+
+	# canonicalize the path (otherwise libsvn will abort or fail to
+	# find the file)
+	# File::Spec->canonpath doesn't collapse x/../y into y (for a
+	# good reason), so let's do this manually.
+	$path =~ s#/+#/#g;
+	$path =~ s#/\.(?:/|$)#/#g;
+	$path =~ s#/[^/]+/\.\.##g;
+	$path =~ s#/$##g;
+
+	my $r = (defined $_revision ? $_revision : $gs->ra->get_latest_revnum);
+	my $props;
+	if ($is_dir)
+	{
+		(undef, undef, $props) = $gs->ra->get_dir($path, $r);
+	}
+	else
+	{
+		(undef, $props) = $gs->ra->get_file($path, $r, undef);
+	}
+	return $props;
+}
+
+# cmd_propget (PROP, PATH)
+# ------------------------
+# Print the SVN property PROP for PATH.
+sub cmd_propget {
+	my ($prop, $path) = @_;
+	$path = '.' if not defined $path;
+	usage(1) if not defined $prop;
+	my $props = get_svnprops($path);
+	if (not defined $props->{$prop})
+	{
+		fatal("`$path' does not have a `$prop' SVN property.\n");
+	}
+	print $props->{$prop} . "\n";
+}
+
 sub cmd_multi_init {
 	my $url = shift;
 	unless (defined $_trunk || defined $_branches || defined $_tags) {
diff --git a/t/t9101-git-svn-props.sh b/t/t9101-git-svn-props.sh
index 796d80e..61c8799 100755
--- a/t/t9101-git-svn-props.sh
+++ b/t/t9101-git-svn-props.sh
@@ -170,4 +170,27 @@ test_expect_success 'test create-ignore' "
 	git ls-files -s | grep gitignore | cmp - create-ignore-index.expect
 	"
 
+cat >prop.expect <<\EOF
+no-such-file*
+
+EOF
+cat >prop2.expect <<\EOF
+8
+EOF
+
+# This test can be improved: since all the svn:ignore contain the same
+# pattern, it can pass even though the propget did not execute on the
+# right directory.
+test_expect_success 'test propget' "
+	git-svn propget svn:ignore . | cmp - prop.expect &&
+	cd deeply &&
+	git-svn propget svn:ignore . | cmp - ../prop.expect &&
+	git-svn propget svn:entry:committed-rev nested/directory/.keep \
+	  | cmp - ../prop2.expect &&
+	git-svn propget svn:ignore .. | cmp - ../prop.expect &&
+	git-svn propget svn:ignore nested/ | cmp - ../prop.expect &&
+	git-svn propget svn:ignore ./nested | cmp - ../prop.expect &&
+	git-svn propget svn:ignore .././deeply/nested | cmp - ../prop.expect
+	"
+
 test_done
-- 
1.5.3.4.214.g6f43

^ permalink raw reply related

* [PATCH 4/5] Add git svn proplist.
From: Benoit Sigoure @ 2007-10-15 15:35 UTC (permalink / raw)
  To: git; +Cc: normalperson, Benoit Sigoure
In-Reply-To: <1192462506-3783-3-git-send-email-tsuna@lrde.epita.fr>

	* git-svn.perl (%cmd): Add the command `proplist'.
	(&cmd_proplist): New.
	* t/t9101-git-svn-props.sh: Test git svn proplist.

Signed-off-by: Benoit Sigoure <tsuna@lrde.epita.fr>
---
 git-svn.perl             |   17 +++++++++++++++++
 t/t9101-git-svn-props.sh |   21 +++++++++++++++++++++
 2 files changed, 38 insertions(+), 0 deletions(-)

diff --git a/git-svn.perl b/git-svn.perl
index e58ff38..466fdd3 100755
--- a/git-svn.perl
+++ b/git-svn.perl
@@ -132,6 +132,9 @@ my %cmd = (
         'propget' => [ \&cmd_propget,
 		       'Print the value of a property on a file or directory',
 		       { 'revision|r=i' => \$_revision } ],
+        'proplist' => [ \&cmd_proplist,
+		       'List all properties of a file or directory',
+		       { 'revision|r=i' => \$_revision } ],
 	'show-ignore' => [ \&cmd_show_ignore, "Show svn:ignore listings",
 			{ 'revision|r=i' => \$_revision
 			} ],
@@ -583,6 +586,20 @@ sub cmd_propget {
 	print $props->{$prop} . "\n";
 }
 
+# cmd_proplist (PATH)
+# -------------------
+# Print the list of SVN properties for PATH.
+sub cmd_proplist {
+	my $path = shift;
+	$path = '.' if not defined $path;
+	my $props = get_svnprops($path);
+	print "Properties on '$path':\n";
+	foreach (sort keys %{$props})
+	{
+		print "  $_\n";
+	}
+}
+
 sub cmd_multi_init {
 	my $url = shift;
 	unless (defined $_trunk || defined $_branches || defined $_tags) {
diff --git a/t/t9101-git-svn-props.sh b/t/t9101-git-svn-props.sh
index 61c8799..3c83127 100755
--- a/t/t9101-git-svn-props.sh
+++ b/t/t9101-git-svn-props.sh
@@ -193,4 +193,25 @@ test_expect_success 'test propget' "
 	git-svn propget svn:ignore .././deeply/nested | cmp - ../prop.expect
 	"
 
+cat >prop.expect <<\EOF
+Properties on '.':
+  svn:entry:committed-date
+  svn:entry:committed-rev
+  svn:entry:last-author
+  svn:entry:uuid
+  svn:ignore
+EOF
+cat >prop2.expect <<\EOF
+Properties on 'nested/directory/.keep':
+  svn:entry:committed-date
+  svn:entry:committed-rev
+  svn:entry:last-author
+  svn:entry:uuid
+EOF
+
+test_expect_success 'test proplist' "
+	git-svn proplist . | cmp - prop.expect &&
+	git-svn proplist nested/directory/.keep | cmp - prop2.expect
+	"
+
 test_done
-- 
1.5.3.4.214.g6f43

^ permalink raw reply related

* [PATCH 5/5] Simplify the handling of fatal errors.
From: Benoit Sigoure @ 2007-10-15 15:35 UTC (permalink / raw)
  To: git; +Cc: normalperson, Benoit Sigoure
In-Reply-To: <1192462506-3783-4-git-send-email-tsuna@lrde.epita.fr>

	* git-svn.perl (&fatal): Append the newline at the end of the error
	message.
	Adjust all callers.

Signed-off-by: Benoit Sigoure <tsuna@lrde.epita.fr>
---
 git-svn.perl |   42 +++++++++++++++++++++---------------------
 1 files changed, 21 insertions(+), 21 deletions(-)

diff --git a/git-svn.perl b/git-svn.perl
index 466fdd3..1a6aa14 100755
--- a/git-svn.perl
+++ b/git-svn.perl
@@ -21,12 +21,12 @@ $Git::SVN::Log::TZ = $ENV{TZ};
 $ENV{TZ} = 'UTC';
 $| = 1; # unbuffer STDOUT
 
-sub fatal (@) { print STDERR @_; exit 1 }
+sub fatal (@) { print STDERR "@_\n"; exit 1 }
 require SVN::Core; # use()-ing this causes segfaults for me... *shrug*
 require SVN::Ra;
 require SVN::Delta;
 if ($SVN::Core::VERSION lt '1.1.0') {
-	fatal "Need SVN::Core 1.1.0 or better (got $SVN::Core::VERSION)\n";
+	fatal "Need SVN::Core 1.1.0 or better (got $SVN::Core::VERSION)";
 }
 push @Git::SVN::Ra::ISA, 'SVN::Ra';
 push @SVN::Git::Editor::ISA, 'SVN::Delta::Editor';
@@ -369,7 +369,7 @@ sub cmd_set_tree {
 		} elsif (scalar @tmp > 1) {
 			push @revs, reverse(command('rev-list',@tmp));
 		} else {
-			fatal "Failed to rev-parse $c\n";
+			fatal "Failed to rev-parse $c";
 		}
 	}
 	my $gs = Git::SVN->new;
@@ -379,7 +379,7 @@ sub cmd_set_tree {
 		fatal "There are new revisions that were fetched ",
 		      "and need to be merged (or acknowledged) ",
 		      "before committing.\nlast rev: $r_last\n",
-		      " current: $gs->{last_rev}\n";
+		      " current: $gs->{last_rev}";
 	}
 	$gs->set_tree($_) foreach @revs;
 	print "Done committing ",scalar @revs," revisions to SVN\n";
@@ -408,7 +408,7 @@ sub cmd_dcommit {
 			(undef, $last_rev, undef) = cmt_metadata("$d~1");
 			unless (defined $last_rev) {
 				fatal "Unable to extract revision information ",
-				      "from commit $d~1\n";
+				      "from commit $d~1";
 			}
 		}
 		if ($_dry_run) {
@@ -521,7 +521,7 @@ sub cmd_create_ignore {
 		my $ignore = '.' . $path . '.gitignore';
 		my $s = $props->{'svn:ignore'} or return;
 		open(GITIGNORE, '>', $ignore)
-		  or fatal("Failed to open `$ignore' for writing: $!\n");
+		  or fatal("Failed to open `$ignore' for writing: $!");
 		$s =~ s/[\r\n]+/\n/g;
 		chomp $s;
 		# Prefix all patterns so that the ignore doesn't apply
@@ -529,7 +529,7 @@ sub cmd_create_ignore {
 		$s =~ s#^#/#gm;
 		print GITIGNORE "$s\n";
 		close(GITIGNORE)
-		  or fatal("Failed to close `$ignore': $!\n");
+		  or fatal("Failed to close `$ignore': $!");
 		command_noisy('add', $ignore);
 	});
 }
@@ -545,7 +545,7 @@ sub get_svnprops {
 	# prefix THE PATH by the sub-directory from which the user
 	# invoked us.
 	$path = $cmd_dir_prefix . $path;
-	fatal("No such file or directory: $path\n") unless -e $path;
+	fatal("No such file or directory: $path") unless -e $path;
 	my $is_dir = -d $path ? 1 : 0;
 	$path = $gs->{path} . '/' . $path;
 
@@ -581,7 +581,7 @@ sub cmd_propget {
 	my $props = get_svnprops($path);
 	if (not defined $props->{$prop})
 	{
-		fatal("`$path' does not have a `$prop' SVN property.\n");
+		fatal("`$path' does not have a `$prop' SVN property.");
 	}
 	print $props->{$prop} . "\n";
 }
@@ -646,7 +646,7 @@ sub cmd_multi_fetch {
 sub cmd_commit_diff {
 	my ($ta, $tb, $url) = @_;
 	my $usage = "Usage: $0 commit-diff -r<revision> ".
-	            "<tree-ish> <tree-ish> [<URL>]\n";
+	            "<tree-ish> <tree-ish> [<URL>]";
 	fatal($usage) if (!defined $ta || !defined $tb);
 	my $svn_path;
 	if (!defined $url) {
@@ -664,7 +664,7 @@ sub cmd_commit_diff {
 	if (defined $_message && defined $_file) {
 		fatal("Both --message/-m and --file/-F specified ",
 		      "for the commit message.\n",
-		      "I have no idea what you mean\n");
+		      "I have no idea what you mean");
 	}
 	if (defined $_file) {
 		$_message = file_to_s($_file);
@@ -727,7 +727,7 @@ sub complete_svn_url {
 	if ($path !~ m#^[a-z\+]+://#) {
 		if (!defined $url || $url !~ m#^[a-z\+]+://#) {
 			fatal("E: '$path' is not a complete URL ",
-			      "and a separate URL is not specified\n");
+			      "and a separate URL is not specified");
 		}
 		return ($url, $path);
 	}
@@ -748,7 +748,7 @@ sub complete_url_ls_init {
 		$repo_path =~ s#^/+##;
 		unless ($ra) {
 			fatal("E: '$repo_path' is not a complete URL ",
-			      "and a separate URL is not specified\n");
+			      "and a separate URL is not specified");
 		}
 	}
 	my $url = $ra->{url};
@@ -1755,7 +1755,7 @@ sub assert_index_clean {
 		$x = command_oneline('write-tree');
 		if ($y ne $x) {
 			::fatal "trees ($treeish) $y != $x\n",
-			        "Something is seriously wrong...\n";
+			        "Something is seriously wrong...";
 		}
 	});
 }
@@ -2181,7 +2181,7 @@ sub set_tree {
 	my ($self, $tree) = (shift, shift);
 	my $log_entry = ::get_commit_entry($tree);
 	unless ($self->{last_rev}) {
-		fatal("Must have an existing revision to commit\n");
+		fatal("Must have an existing revision to commit");
 	}
 	my %ed_opts = ( r => $self->{last_rev},
 	                log => $log_entry->{log},
@@ -3131,7 +3131,7 @@ sub apply_diff {
 		if (defined $o{$f}) {
 			$self->$f($m);
 		} else {
-			fatal("Invalid change type: $f\n");
+			fatal("Invalid change type: $f");
 		}
 	}
 	$self->rmdirs if $_rmdir;
@@ -3739,15 +3739,15 @@ sub config_pager {
 sub run_pager {
 	return unless -t *STDOUT && defined $pager;
 	pipe my $rfd, my $wfd or return;
-	defined(my $pid = fork) or ::fatal "Can't fork: $!\n";
+	defined(my $pid = fork) or ::fatal "Can't fork: $!";
 	if (!$pid) {
 		open STDOUT, '>&', $wfd or
-		                     ::fatal "Can't redirect to stdout: $!\n";
+		                     ::fatal "Can't redirect to stdout: $!";
 		return;
 	}
-	open STDIN, '<&', $rfd or ::fatal "Can't redirect stdin: $!\n";
+	open STDIN, '<&', $rfd or ::fatal "Can't redirect stdin: $!";
 	$ENV{LESS} ||= 'FRSX';
-	exec $pager or ::fatal "Can't run pager: $! ($pager)\n";
+	exec $pager or ::fatal "Can't run pager: $! ($pager)";
 }
 
 sub tz_to_s_offset {
@@ -3883,7 +3883,7 @@ sub cmd_show_log {
 			$r_min = $r_max = $::_revision;
 		} else {
 			::fatal "-r$::_revision is not supported, use ",
-				"standard \'git log\' arguments instead\n";
+				"standard 'git log' arguments instead";
 		}
 	}
 
-- 
1.5.3.4.214.g6f43

^ permalink raw reply related

* [PATCH 2/5] Implement git svn create-ignore.
From: Benoit Sigoure @ 2007-10-15 15:35 UTC (permalink / raw)
  To: git; +Cc: normalperson, Benoit Sigoure
In-Reply-To: <1192462506-3783-1-git-send-email-tsuna@lrde.epita.fr>

	* git-svn.perl (%cmd): Add the new command `create-ignore'.
	(&cmd_create_ignore): New.
	* t/t9101-git-svn-props.sh: Adjust the test-case for show-ignore and
	add a test case for create-ignore.

Signed-off-by: Benoit Sigoure <tsuna@lrde.epita.fr>
---
 git-svn.perl             |   27 +++++++++++++++++++++++++++
 t/t9101-git-svn-props.sh |   28 +++++++++++++++++++++++++---
 2 files changed, 52 insertions(+), 3 deletions(-)

diff --git a/git-svn.perl b/git-svn.perl
index abc83ec..94091ea 100755
--- a/git-svn.perl
+++ b/git-svn.perl
@@ -123,6 +123,10 @@ my %cmd = (
 	'set-tree' => [ \&cmd_set_tree,
 	                "Set an SVN repository to a git tree-ish",
 			{ 'stdin|' => \$_stdin, %cmt_opts, %fc_opts, } ],
+	'create-ignore' => [ \&cmd_create_ignore,
+			     'Create a .gitignore per svn:ignore',
+			     { 'revision|r=i' => \$_revision
+			     } ],
 	'show-ignore' => [ \&cmd_show_ignore, "Show svn:ignore listings",
 			{ 'revision|r=i' => \$_revision
 			} ],
@@ -499,6 +503,29 @@ sub cmd_show_ignore {
 	});
 }
 
+sub cmd_create_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->prop_walk($gs->{path}, $r, sub {
+		my ($gs, $path, $props) = @_;
+		# $path is of the form /path/to/dir/
+		my $ignore = '.' . $path . '.gitignore';
+		my $s = $props->{'svn:ignore'} or return;
+		open(GITIGNORE, '>', $ignore)
+		  or fatal("Failed to open `$ignore' for writing: $!\n");
+		$s =~ s/[\r\n]+/\n/g;
+		chomp $s;
+		# Prefix all patterns so that the ignore doesn't apply
+		# to sub-directories.
+		$s =~ s#^#/#gm;
+		print GITIGNORE "$s\n";
+		close(GITIGNORE)
+		  or fatal("Failed to close `$ignore': $!\n");
+		command_noisy('add', $ignore);
+	});
+}
+
 sub cmd_multi_init {
 	my $url = shift;
 	unless (defined $_trunk || defined $_branches || defined $_tags) {
diff --git a/t/t9101-git-svn-props.sh b/t/t9101-git-svn-props.sh
index 5aac644..796d80e 100755
--- a/t/t9101-git-svn-props.sh
+++ b/t/t9101-git-svn-props.sh
@@ -126,19 +126,20 @@ cat > show-ignore.expect <<\EOF
 # /
 /no-such-file*
 
-# deeply
+# /deeply/
 /deeply/no-such-file*
 
-# deeply/nested
+# /deeply/nested/
 /deeply/nested/no-such-file*
 
-# deeply/nested/directory
+# /deeply/nested/directory/
 /deeply/nested/directory/no-such-file*
 EOF
 
 test_expect_success 'test show-ignore' "
 	cd test_wc &&
 	mkdir -p deeply/nested/directory &&
+	touch deeply/nested/directory/.keep &&
 	svn add deeply &&
 	svn up &&
 	svn propset -R svn:ignore 'no-such-file*' .
@@ -148,4 +149,25 @@ test_expect_success 'test show-ignore' "
 	cmp show-ignore.expect show-ignore.got
 	"
 
+cat >create-ignore.expect <<\EOF
+/no-such-file*
+EOF
+
+cat >create-ignore-index.expect <<\EOF
+100644 8c52e5dfcd0a8b6b6bcfe6b41b89bcbf493718a5 0	.gitignore
+100644 8c52e5dfcd0a8b6b6bcfe6b41b89bcbf493718a5 0	deeply/.gitignore
+100644 8c52e5dfcd0a8b6b6bcfe6b41b89bcbf493718a5 0	deeply/nested/.gitignore
+100644 8c52e5dfcd0a8b6b6bcfe6b41b89bcbf493718a5 0	deeply/nested/directory/.gitignore
+EOF
+
+test_expect_success 'test create-ignore' "
+	git-svn fetch && git pull . remotes/git-svn &&
+	git-svn create-ignore &&
+	cmp ./.gitignore create-ignore.expect &&
+	cmp ./deeply/.gitignore create-ignore.expect &&
+	cmp ./deeply/nested/.gitignore create-ignore.expect &&
+	cmp ./deeply/nested/directory/.gitignore create-ignore.expect &&
+	git ls-files -s | grep gitignore | cmp - create-ignore-index.expect
+	"
+
 test_done
-- 
1.5.3.4.214.g6f43

^ permalink raw reply related

* [PATCH 1/5] Add a generic tree traversal to fetch SVN properties.
From: Benoit Sigoure @ 2007-10-15 15:35 UTC (permalink / raw)
  To: git; +Cc: normalperson, Benoit Sigoure

	* git-svn.perl (&traverse_ignore): Remove.
	(&prop_walk): New.
	(&cmd_show_ignore): Use prop_walk.

Signed-off-by: Benoit Sigoure <tsuna@lrde.epita.fr>
---
 git-svn.perl |   66 ++++++++++++++++++++++++++++++++++++++++-----------------
 1 files changed, 46 insertions(+), 20 deletions(-)

diff --git a/git-svn.perl b/git-svn.perl
index 777e436..abc83ec 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,46 @@ 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);
 	}
 }
 
-- 
1.5.3.4.214.g6f43

^ permalink raw reply related

* Re: Switching from CVS to GIT
From: Steffen Prohaska @ 2007-10-16 14:36 UTC (permalink / raw)
  To: Johannes Schindelin
  Cc: Git Mailing List, Robin Rosenberg, Eli Zaretskii, Daniel Barkalow,
	Alex Riesen, tsuna, Andreas Ericsson
In-Reply-To: <Pine.LNX.4.64.0710161512450.25221@racer.site>


On Oct 16, 2007, at 4:14 PM, Johannes Schindelin wrote:

> On Tue, 16 Oct 2007, Steffen Prohaska wrote:
>
>> On Oct 16, 2007, at 3:21 PM, Johannes Schindelin wrote:
>>
>>> What you want would probably be all too easy with a pre-commit hook.
>>> No need to clutter the git-core with code that is usually not needed
>>> (you'd only ever activate it on Linux when other developers use
>>> Windows or MacOSX).
>>
>> Personally, I'd be very happy if git enforced the minimal consent
>> between (supported) filesystems and provided a system to guarantee  
>> that
>> I can only create tree objects that can be checked out on all
>> (supported) filesystems.
>
> This will not happen.  In the Linux kernel, there were exactly such  
> cases,
> where the filenames differed only in case.
>
> Also, some projects I checked out (notably Perl) assume that  
> Makefile is
> different from makefile.

weird Linux and Perl world, indeed.


> So I think this will always be something Windows users

and Mac users, who also need to deal with a case-preserving,
but case-insensitive filesystem.

> would wish to
> impose onto others, while Linux users would always refuse.

maybe Linux kernel developers. When I work on Linux, I'd be happy
if git saved me from creating directories containing Readme and
readme at the same time.

	Steffen

^ permalink raw reply

* Re: Switching from CVS to GIT
From: Johannes Schindelin @ 2007-10-16 14:14 UTC (permalink / raw)
  To: Steffen Prohaska
  Cc: Git Mailing List, Robin Rosenberg, Eli Zaretskii, Daniel Barkalow,
	Alex Riesen, tsuna, Andreas Ericsson
In-Reply-To: <26554F2D-B44D-4691-A696-9B6924E08599@zib.de>

Hi,

On Tue, 16 Oct 2007, Steffen Prohaska wrote:

> On Oct 16, 2007, at 3:21 PM, Johannes Schindelin wrote:
> 
> > What you want would probably be all too easy with a pre-commit hook.  
> > No need to clutter the git-core with code that is usually not needed 
> > (you'd only ever activate it on Linux when other developers use 
> > Windows or MacOSX).
> 
> Personally, I'd be very happy if git enforced the minimal consent 
> between (supported) filesystems and provided a system to guarantee that 
> I can only create tree objects that can be checked out on all 
> (supported) filesystems.

This will not happen.  In the Linux kernel, there were exactly such cases, 
where the filenames differed only in case.

Also, some projects I checked out (notably Perl) assume that Makefile is 
different from makefile.

So I think this will always be something Windows users would wish to 
impose onto others, while Linux users would always refuse.

Ciao,
Dscho

^ permalink raw reply

* Re: Switching from CVS to GIT
From: Steffen Prohaska @ 2007-10-16 13:50 UTC (permalink / raw)
  To: Johannes Schindelin
  Cc: Git Mailing List, Robin Rosenberg, Eli Zaretskii, Daniel Barkalow,
	Alex Riesen, tsuna, Andreas Ericsson
In-Reply-To: <Pine.LNX.4.64.0710161419140.25221@racer.site>


On Oct 16, 2007, at 3:21 PM, Johannes Schindelin wrote:

> Hi,
>
> On Tue, 16 Oct 2007, Steffen Prohaska wrote:
>
>> On Oct 16, 2007, at 2:33 PM, Johannes Schindelin wrote:
>>
>>>> Maybe we need a configuration similar to core.autocrlf (which  
>>>> controls
>>>> newline conversion) to control filename comparison and  
>>>> normalization?
>>>>
>>>> Most obviously for the case (in-)sensitivity on Windows, but I also
>>>> remember the unicode normalization happening on Mac's HFS  
>>>> filesystem
>>>> that caused trouble in the past.
>>>
>>> Robin Rosenberg has some preliminary code for that.  The idea is  
>>> to wrap
>>> all filesystem operations in cache.h, and do a filename  
>>> normalisation
>>> first.
>>
>> At that point we could add a safety check. Paths that differ only by
>> case, or whitespace, or ... (add general and project specific  
>> rules here)
>> should be denied. This would guarantee that tree objects can  
>> always be
>> checked out. Even if the filesystem capabilities are limited.
>
> This would be an independent change.  The method I talked about  
> only ever
> looks at one filename, never what is already there.

Oh, hmm ... obviously, ... if I think about it ;)


> What you want would probably be all too easy with a pre-commit  
> hook.  No
> need to clutter the git-core with code that is usually not needed  
> (you'd
> only ever activate it on Linux when other developers use Windows or
> MacOSX).

Personally, I'd be very happy if git enforced the minimal consent  
between
(supported) filesystems and provided a system to guarantee that I can  
only
create tree objects that can be checked out on all (supported)  
filesystems.

I'd _always_ switch on such a mechanism. I think the idea of relying on
filenames that only differ by whitespace or case is insane  
independent of
the capabilities of the filesystem used. Humans hardly see such  
differences.
There may be other characters that should be avoided purely for  
technical reasons. If git checked this, too, I'd be happy.

An update hook is only very loosely coupled to git. I'd prefer a tighter
integration. 'git add <something>' should immediately report the  
problem.
But, maybe I'll try a commit hook first.

	Steffen

^ permalink raw reply

* Re: Switching from CVS to GIT
From: Johannes Schindelin @ 2007-10-16 13:24 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: barkalow, raa.lkml, ae, tsuna, git
In-Reply-To: <E1IhmHM-0002hB-HR@fencepost.gnu.org>

Hi,

On Tue, 16 Oct 2007, Eli Zaretskii wrote:

> > Date: Tue, 16 Oct 2007 13:39:12 +0100 (BST)
> > From: Johannes Schindelin <Johannes.Schindelin@gmx.de>
> > cc: Daniel Barkalow <barkalow@iabervon.org>, raa.lkml@gmail.com, ae@op5.se, 
> >     tsuna@lrde.epita.fr, git@vger.kernel.org
> > 
> > > As I wrote in my other message, using native APIs improves 
> > > performance by at least a factor of two.
> > 
> > Somehow this does not appeal to my "portability is good" side.  You 
> > know, if we had to do such trickeries for every platform we support, 
> > we'd soon be as big as Subversion *cough*.
> 
> You have to decide whether you care about performance enough to do
> that or not.

Yes, I know that we'll have to use more special casing of Windows for 
performance reasons.  I was only lamenting that it would not need to be 
that way.  Just ignore me.

> > For me, this is the most annoying part about programming Win32.  They 
> > went out of their way to make it incompatible with everything else, 
> > and as a consequence it is a PITA to maintain crossplatform programs.
> 
> Portability is a two-way street.  A program that wasn't designed to be 
> portable will by definition be hard to port.  To me, what's annoying is 
> a program that was designed around a single-OS model of APIs.

You're obviously not talking about git here.

> > Explorer often accesses files it should not lock.  On the machine I 
> > test msysGit on, this is the most common reason for a test case to 
> > fail: it cannot delete the temporary directory, which _should_ be 
> > unused.  Indeed, a second after that, it _is_ unused.
> 
> One more reason not to launch Explorer, if you ask me ;-)  But maybe you 
> have valid reasons to do that.  All I can say is that I never saw such 
> problems, but then I don't usually run programs that rewrite files in a 
> frenzy.

Funny.  Last time I checked the toolbar went away, as well as the desktop, 
when I killed explorer.exe.

Ciao,
Dscho

^ permalink raw reply

* Re: git-svn has a _lot_ of metadata
From: Sam Vilain @ 2007-10-16 13:22 UTC (permalink / raw)
  To: Karl Hasselström; +Cc: Eric Wong, git list
In-Reply-To: <20071016102259.GB5945@diana.vm.bytemark.co.uk>

Karl Hasselström wrote:
>     This could probably be stored _much_ more efficiently. Just
>     gzipping it with the standard options shrinks it by between a
>     factor of 4 (for one of the busiest branches) and 300 (for a tag,
>     which is written just once). But I understand that we need quick
>     random access here?
>   

I understand that patches to enhance git-svn to allow it to store its
metadata via DBI (as git-cvsserver currently does) would be more than
welcome.

I made an example for an old version of git-svn, which stored the
information in a DBM.  However using a set of tables would be much less
of a hack.

http://git.catalyst.net.nz/gw?p=git.git;a=commitdiff;h=dbe3fa060

Treat that change as a reference only; it just shows what places in the
code would need to be touched to support a different storage format.  A
mergeable patch to fix this would probably need to support both methods,
detecting which is available or in use.

Sam.

^ permalink raw reply

* Re: Switching from CVS to GIT
From: Johannes Schindelin @ 2007-10-16 13:21 UTC (permalink / raw)
  To: Steffen Prohaska
  Cc: Git Mailing List, Robin Rosenberg, Eli Zaretskii, Daniel Barkalow,
	Alex Riesen, tsuna, Andreas Ericsson
In-Reply-To: <4D822762-D344-465E-B77D-90A64D61F5A9@zib.de>

Hi,

On Tue, 16 Oct 2007, Steffen Prohaska wrote:

> On Oct 16, 2007, at 2:33 PM, Johannes Schindelin wrote:
> 
> > > Maybe we need a configuration similar to core.autocrlf (which controls
> > > newline conversion) to control filename comparison and normalization?
> > > 
> > > Most obviously for the case (in-)sensitivity on Windows, but I also
> > > remember the unicode normalization happening on Mac's HFS filesystem
> > > that caused trouble in the past.
> > 
> > Robin Rosenberg has some preliminary code for that.  The idea is to wrap
> > all filesystem operations in cache.h, and do a filename normalisation
> > first.
> 
> At that point we could add a safety check. Paths that differ only by
> case, or whitespace, or ... (add general and project specific rules here)
> should be denied. This would guarantee that tree objects can always be
> checked out. Even if the filesystem capabilities are limited.

This would be an independent change.  The method I talked about only ever 
looks at one filename, never what is already there.

What you want would probably be all too easy with a pre-commit hook.  No 
need to clutter the git-core with code that is usually not needed (you'd 
only ever activate it on Linux when other developers use Windows or 
MacOSX).

Ciao,
Dscho

^ permalink raw reply

* Re: [PATCH 07/25] parse-options: make some arguments optional, add callbacks.
From: Johannes Schindelin @ 2007-10-16 13:18 UTC (permalink / raw)
  To: Pierre Habouzit; +Cc: git, Shawn O. Pearce
In-Reply-To: <20071016084510.GI6919@artemis.corp>

Hi,

On Tue, 16 Oct 2007, Pierre Habouzit wrote:

> This bit is to allow to aggregate options with arguments together when
> the argument is numeric.
> 
>     +#if 0
>     +		/* can be used to understand -A1B1 like -A1 -B1 */
>     +		if (flag & OPT_SHORT && opt->opt && isdigit(*opt->opt)) {
>     +			*(int *)opt->value = strtol(opt->opt, (char **)&opt->opt, 10);
>     +			return 0;
>     +		}
>     +#endif
> 
> I'm not a huge fan, but people may like it. Feel free to keep the
> chunk, drop it, or enable it to your liking.

FWIW I like it.  It allows me to aggregate options such as -M30 with other 
short options.

Ciao,
Dscho

^ permalink raw reply

* Re: [PATCH 09/25] Port builtin-add.c to use the new option parser.
From: Johannes Schindelin @ 2007-10-16 13:17 UTC (permalink / raw)
  To: Michael Witten; +Cc: Pierre Habouzit, git
In-Reply-To: <2209D123-A245-43C4-8DD9-A83386852556@mit.edu>

Hi,

On Tue, 16 Oct 2007, Michael Witten wrote:

> On 16 Oct 2007, at 4:39:42 AM, Pierre Habouzit wrote:
> 
> > +	OPT_BOOLEAN('u', NULL, &take_worktree_changes, "update only files
> > that git already knows about"),
> 
> "update only files in the current directory that git already knows about"

"update tracked files"

Ciao,
Dscho

^ permalink raw reply

* Re: Switching from CVS to GIT
From: Eli Zaretskii @ 2007-10-16 13:16 UTC (permalink / raw)
  To: Johannes Schindelin; +Cc: barkalow, raa.lkml, ae, tsuna, git
In-Reply-To: <Pine.LNX.4.64.0710161335260.25221@racer.site>

> Date: Tue, 16 Oct 2007 13:39:12 +0100 (BST)
> From: Johannes Schindelin <Johannes.Schindelin@gmx.de>
> cc: Daniel Barkalow <barkalow@iabervon.org>, raa.lkml@gmail.com, ae@op5.se, 
>     tsuna@lrde.epita.fr, git@vger.kernel.org
> 
> > As I wrote in my other message, using native APIs improves performance 
> > by at least a factor of two.
> 
> Somehow this does not appeal to my "portability is good" side.  You know, 
> if we had to do such trickeries for every platform we support, we'd soon 
> be as big as Subversion *cough*.

You have to decide whether you care about performance enough to do
that or not.  If you do, then introducing file I/O abstractions at
higher level than the normal ``use-library-functions'' method is not
such a hard problem, and doesn't make the binary larger because each
platform gets only its own backend.  In practice, I have found that in
most cases a few well-designed and strategically placed macros is all
you need.

> For me, this is the most annoying part about programming Win32.  They went 
> out of their way to make it incompatible with everything else, and as a 
> consequence it is a PITA to maintain crossplatform programs.

Portability is a two-way street.  A program that wasn't designed to be
portable will by definition be hard to port.  To me, what's annoying
is a program that was designed around a single-OS model of APIs.

Cross-platform programs are not that hard if you design them to be
like that from the ground up.  I'm working for a firm that does that
for a living: we develop software that compiles and runs on Windows
and Linux from the same source.

> Explorer often accesses files it should not lock.  
> On the machine I test msysGit on, this is the most common reason for a 
> test case to fail: it cannot delete the temporary directory, which 
> _should_ be unused.  Indeed, a second after that, it _is_ unused.

One more reason not to launch Explorer, if you ask me ;-)  But maybe
you have valid reasons to do that.  All I can say is that I never saw
such problems, but then I don't usually run programs that rewrite
files in a frenzy.

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox