Git development
 help / color / mirror / Atom feed
* [PATCH 3/3] Added diff hunk coloring to git-add--interactive
From: Dan Zwell @ 2007-11-11  0:03 UTC (permalink / raw)
  To: Jeff King
  Cc: Junio C Hamano, Shawn O. Pearce, Wincent Colaiuta,
	Git Mailing List, Jonathan del Strother, Johannes Schindelin,
	Frank Lichtenheld
In-Reply-To: <20071104054305.GA13929@sigill.intra.peff.net>

Added and integrated method "color_diff_hunk", which colors
lines, and returns them in an array. Coloring bad whitespace is
not yet supported.

Signed-off-by: Dan Zwell <dzwell@zwell.net>
---
 git-add--interactive.perl |   58 ++++++++++++++++++++++++++++++++++++++------
 1 files changed, 50 insertions(+), 8 deletions(-)

diff --git a/git-add--interactive.perl b/git-add--interactive.perl
index 508531f..d92e8ed 100755
--- a/git-add--interactive.perl
+++ b/git-add--interactive.perl
@@ -3,7 +3,11 @@
 use strict;
 use Git;
 
+# Prompt colors:
 my ($use_color, $prompt_color, $header_color, $help_color, $normal_color);
+# Diff colors:
+my ($diff_use_color, $new_color, $old_color, $fraginfo_color,
+    $metainfo_color, $whitespace_color);
 my $color_config = qx(git config --get color.interactive);
 if ($color_config=~/true|always/ || -t STDOUT && $color_config=~/auto/) {
 	eval { require Term::ANSIColor; };
@@ -21,6 +25,24 @@ if ($color_config=~/true|always/ || -t STDOUT && $color_config=~/auto/) {
 		$help_color = Git::color_to_ansi_code(
 			Git::config($repo, "color.interactive.help") || "red bold");
 		$normal_color = Git::color_to_ansi_code("normal");
+
+		# Do we also set diff colors?
+		my $diff_colors = Git::config($repo, "color.diff");
+		if ($diff_colors=~/true/ ||
+			-t STDOUT && $diff_colors=~/auto/) {
+			$diff_use_color = 1;
+			$new_color = Git::color_to_ansi_code(
+				Git::config($repo, "color.diff.new") || "green");
+			$old_color = Git::color_to_ansi_code(
+				Git::config($repo, "color.diff.old") || "red");
+			$fraginfo_color = Git::color_to_ansi_code(
+				Git::config($repo, "color.diff.frag") || "cyan");
+			$metainfo_color = Git::color_to_ansi_code(
+				Git::config($repo, "color.diff.meta") || "bold");
+			# Not implemented:
+			#$whitespace_color = Git::color_to_ansi_code(
+				#Git::config($repo, "color.diff.whitespace") || "normal red");
+		}
 	}
 }
 
@@ -389,6 +411,31 @@ sub parse_diff {
 	return @hunk;
 }
 
+sub colored_diff_hunk {
+	my ($text) = @_;
+	# return the text, so that it can be passed to print()
+	my @ret;
+	for (@$text) {
+		if (!$diff_use_color) {
+			push @ret, $_;
+			next;
+		}
+
+		if (/^\+/) {
+			push @ret, colored($new_color, $_);
+		} elsif (/^\-/) {
+			push @ret, colored($old_color, $_);
+		} elsif (/^\@/) {
+			push @ret, colored($fraginfo_color, $_);
+		} elsif (/^ /) {
+			push @ret, colored($normal_color, $_);
+		} else {
+			push @ret, colored($metainfo_color, $_);
+		}
+	}
+	return @ret;
+}
+
 sub hunk_splittable {
 	my ($text) = @_;
 
@@ -611,9 +658,7 @@ sub patch_update_cmd {
 	my ($ix, $num);
 	my $path = $it->{VALUE};
 	my ($head, @hunk) = parse_diff($path);
-	for (@{$head->{TEXT}}) {
-		print;
-	}
+	print colored_diff_hunk($head->{TEXT});
 	$num = scalar @hunk;
 	$ix = 0;
 
@@ -655,9 +700,7 @@ sub patch_update_cmd {
 		if (hunk_splittable($hunk[$ix]{TEXT})) {
 			$other .= '/s';
 		}
-		for (@{$hunk[$ix]{TEXT}}) {
-			print;
-		}
+		print colored_diff_hunk($hunk[$ix]{TEXT});
 		print colored $prompt_color, "Stage this hunk [y/n/a/d$other/?]? ";
 		my $line = <STDIN>;
 		if ($line) {
@@ -795,8 +838,7 @@ sub diff_cmd {
 				     HEADER => $status_head, },
 				   @mods);
 	return if (!@them);
-	system(qw(git diff-index -p --cached HEAD --),
-	       map { $_->{VALUE} } @them);
+	system(qw(git diff -p --cached HEAD --), map { $_->{VALUE} } @them);
 }
 
 sub quit_cmd {
-- 
1.5.3.5.565.gf0b83-dirty

^ permalink raw reply related

* Re: git svn dcommit with a dirty index
From: Eric Wong @ 2007-11-11  1:42 UTC (permalink / raw)
  To: Benoit Sigoure; +Cc: git list
In-Reply-To: <DBC1E504-9007-4C89-9728-2DDBAFF2053B@lrde.epita.fr>

Benoit Sigoure <tsuna@lrde.epita.fr> wrote:
> Hello list,
> From what I understand, when using dcommit, git-svn uses rebase to  
> "sync" the history with what has just been committed.  If the index  
> is in a dirty state, this will cause trouble.  I thought about using  
> git-stash and then git stash apply --index but I'm afraid this could  
> be confusing if dcommit actually brings more revision in that the  
> ones it has just committed.  I'm not sure this is possible and even  
> if it is, it might not be troublesome since if the commits are  
> accepted in the SVN repo, they surely don't overlap with commits that  
> have been sent in the mean time.  But it's risky, so I don't know  
> what to do.  If we use the stash approach, we might want to tell the  
> user that we bailed out because of a problem that needs to be fixed  
> and that he can recover his changes with git stash apply --index.
> 
> Or we should simply check that the index isn't dirty beforehand and  
> refuse to dcommit if it is.
> 
> Any suggestion?

The latter option is much simpler.  I actually thought there was already
a check in dcommit that prevents it from committing with a dirty index,
but apparently not...

> PS OT: Eric, have you made any progress on the svn:externals<- 
> >submodules mapping?  I badly need this feature, but I don't want to  
> start to work on it if you're currently working on it (or about to  
> deal with it) to avoid unecessary effort duplication.

Oops, sorry.  I've been busy and forgetful.  I'll try to work on it
later tonight or tomorrow.

-- 
Eric Wong

^ permalink raw reply

* Re: Deprecate git-fetch-pack?
From: Ask Bjørn Hansen @ 2007-11-11  3:09 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Daniel Barkalow, git
In-Reply-To: <7v4pftip42.fsf@gitster.siamese.dyndns.org>


On Nov 10, 2007, at 4:48 PM, Junio C Hamano wrote:

> As to peek-remote, ls-remote over the native transport is a
> synonym so I do not think anybody doing the scripting would have
> problem doing s/peek-/ls-/ to their script, but again I do not
> see a heavy maintenance burden to keep the synonym, yet.

For new users the superfluous programs are a burden making it harder  
to learn how everything works.

"What does this thing do?  How is it different from that other similar  
program?  How do they interact?  Oh, this one isn't really used.  Grrh."

At least a note in the documentation that it's superseded by  
$other_program would be helpful for us newcomers.  :-)


  - ask

-- 
http://develooper.com/ - http://askask.com/

^ permalink raw reply

* [PATCH 2/3] Let git-add--interactive read colors from .gitconfig
From: Dan Zwell @ 2007-11-11  0:02 UTC (permalink / raw)
  To: Jeff King
  Cc: Junio C Hamano, Shawn O. Pearce, Wincent Colaiuta,
	Git Mailing List, Jonathan del Strother, Johannes Schindelin,
	Frank Lichtenheld
In-Reply-To: <20071104054305.GA13929@sigill.intra.peff.net>

Colors are specified in color.interactive.{prompt,header,help}.
They are specified as git color strings as described in the
documentation. The method color_to_ansi_string() in Git.pm parses
these strings and returns ANSI color codes (using
Term::ANSIColor).

Signed-off-by: Dan Zwell <dzwell@zwell.net>
---
 Documentation/config.txt  |    7 +++++
 git-add--interactive.perl |   19 ++++++++++-----
 perl/Git.pm               |   55
++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 74
insertions(+), 7 deletions(-)

diff --git a/Documentation/config.txt b/Documentation/config.txt
index 3712d6a..47c1ab2 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -388,6 +388,13 @@ color.interactive::
 	`auto`, use colors only when the output is to the
 	terminal. Defaults to false.
 
+color.interactive.<slot>::
+	Use customized color for `git add --interactive`
+	output. `<slot>` may be `prompt`, `header`, or `help`, for
+	three distinct types of normal output from interactive
+	programs.  The values of these variables may be specified as
+	in color.branch.<slot>.
+
 color.pager::
 	A boolean to enable/disable colored output when the pager is in
 	use (default is true).
diff --git a/git-add--interactive.perl b/git-add--interactive.perl
index f2b0e56..508531f 100755
--- a/git-add--interactive.perl
+++ b/git-add--interactive.perl
@@ -1,6 +1,7 @@
 #!/usr/bin/perl -w
 
 use strict;
+use Git;
 
 my ($use_color, $prompt_color, $header_color, $help_color,
$normal_color); my $color_config = qx(git config --get
color.interactive); @@ -8,12 +9,18 @@ if ($color_config=~/true|always/
|| -t STDOUT && $color_config=~/auto/) { eval { require
Term::ANSIColor; }; if (!$@) {
 		$use_color = 1;
-
-		# Sane (visible) defaults:
-		$prompt_color = Term::ANSIColor::color("blue bold");
-		$header_color = Term::ANSIColor::color("bold");
-		$help_color   = Term::ANSIColor::color("red bold");
-		$normal_color = Term::ANSIColor::color("reset");
+		# Set interactive colors:
+
+		# Grab the 3 main colors in git color string format,
with sane
+		# (visible) defaults:
+		my $repo = Git->repository();
+		$prompt_color = Git::color_to_ansi_code(
+			Git::config($repo, "color.interactive.prompt")
|| "bold blue");
+		$header_color = Git::color_to_ansi_code(
+			Git::config($repo, "color.interactive.header")
|| "bold");
+		$help_color = Git::color_to_ansi_code(
+			Git::config($repo, "color.interactive.help")
|| "red bold");
+		$normal_color = Git::color_to_ansi_code("normal");
 	}
 }
 
diff --git a/perl/Git.pm b/perl/Git.pm
index dca92c8..c9e661a 100644
--- a/perl/Git.pm
+++ b/perl/Git.pm
@@ -515,7 +515,6 @@ sub config {
 	};
 }
 
-
 =item config_bool ( VARIABLE )
 
 Retrieve the bool configuration C<VARIABLE>. The return value
@@ -550,6 +549,60 @@ sub config_bool {
 }
 
 
+=item color_to_ansi_code ( COLOR )
+
+Converts a git-style color string, like "underline blue white" to
+an ANSI color code. The code is generated by Term::ANSIColor,
+after the string is parsed into the format that is accepted by
+that module. Used as follows:
+
+	print color_to_ansi_code("underline blue white");
+	print "some text";
+	print color_to_ansi_code("normal");
+
+=cut
+
+sub color_to_ansi_code {
+	my ($git_string) = @_;
+	my @ansi_words;
+	my %attrib_mappings = (
+		"bold"    => "bold",
+		"ul"      => "underline",
+		"blink"   => "blink",
+		# not supported:
+		#"dim"     => "",
+		"reverse" => "reverse"
+	);
+	my ($fg_done, $word);
+
+	foreach $word (split /\s+/, $git_string) {
+		if ($word =~ /normal/) {
+			$fg_done = "true";
+		}
+		elsif ($word =~ /black|red|green|yellow/ ||
+			   $word =~ /blue|magenta|cyan|white/) {
+			# is a color.
+			if ($fg_done) {
+				# this is the background
+				push @ansi_words, "on_" . $word;
+			}
+			else {
+				# this is foreground
+				$fg_done = "true";
+				push @ansi_words, $word;
+			}
+		}
+		else {
+			# this is an attribute, not a color.
+			if ($attrib_mappings{$word}) {
+				push(@ansi_words,
+					 $attrib_mappings{$word});
+			}
+		}
+	}
+	return Term::ANSIColor::color(join(" ", @ansi_words)||"reset");
+}
+
 =item ident ( TYPE | IDENTSTR )
 
 =item ident_person ( TYPE | IDENTSTR | IDENTARRAY )
-- 
1.5.3.5.565.gf0b83-dirty

^ permalink raw reply related

* Re: tracking remotes with Git
From: Ivan Shmakov @ 2007-11-11  4:05 UTC (permalink / raw)
  To: git; +Cc: Ivan Shmakov
In-Reply-To: <200711092138.56277.robin.rosenberg.lists@dewire.com>

>>>>> Robin Rosenberg <robin.rosenberg.lists@dewire.com> writes:

[...]

 >> * it looks like `git-cvsimport' uses its own CVS protocol
 >> implementation which doesn't support compression; I've tried to
 >> clone a repository of a project hosted in CVS since circa 1998 and
 >> it 20 MiB or so to obtain revisions until 2000 or so; any ways to
 >> minimize traffic?

 > You can pass options to cvsps.  My guess is -P "-Z" will do it.

	Well, this helps somewhat.  But still, IIUC, cvsps(1) is used
	only to reconstruct the ``patch sets'', and to fetch the actual
	revisions, `git-cvsimport' contacts the CVS repository directly:

--cut: $ nl -ba git-cvsimport--
...
   182	package CVSconn;
   183	# Basic CVS dialog.
   184	# We're only interested in connecting and downloading, so ...
   185	
... not a word about the compression...
   482	package main;
   483	
   484	my $cvs = CVSconn->new($opt_d, $cvs_tree);
...
   911			print "Fetching $fn   v $rev\n" if $opt_v;
   912			my ($tmpname, $size) = $cvs->file($fn,$rev);
...
   930			unlink($tmpname);
...
--cut: $ nl -ba git-cvsimport--

^ permalink raw reply

* [PATCH] fix index-pack with packs >4GB containing deltas on 32-bit machines
From: Nicolas Pitre @ 2007-11-11  4:29 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git

This probably hasn't been properly tested before.  Here's a script to 
create a 8GB repo with the necessary characteristics (copy the 
test-genrandom executable from the Git build tree to /tmp first):

-----
#!/bin/bash

git init
git config core.compression 0

# create big objects with no deltas
for i in $(seq -w 1 2 63)
do
	echo $i
	/tmp/test-genrandom $i 268435456 > file_$i
	git add file_$i
	rm file_$i
	echo "file_$i -delta" >> .gitattributes
done

# create "deltifiable" objects in between big objects
for i in $(seq -w 2 2 64)
do
	echo "$i $i $i" >> grow
	cp grow file_$i
	git add file_$i
	rm file_$i
done
rm grow

# create a pack with them
git commit -q -m "commit of big objects interlaced with small deltas"
git repack -a -d
-----

Then clone this repo over the Git protocol.

Signed-off-by: Nicolas Pitre <nico@cam.org>
---
diff --git a/index-pack.c b/index-pack.c
index 469a330..9fd6982 100644
--- a/index-pack.c
+++ b/index-pack.c
@@ -256,7 +256,7 @@ static void *unpack_raw_entry(struct object_entry *obj, union delta_base *delta_
 
 static void *get_data_from_pack(struct object_entry *obj)
 {
-	unsigned long from = obj[0].idx.offset + obj[0].hdr_size;
+	off_t from = obj[0].idx.offset + obj[0].hdr_size;
 	unsigned long len = obj[1].idx.offset - from;
 	unsigned long rdy = 0;
 	unsigned char *src, *data;

^ permalink raw reply related

* Re: git packs
From: Nicolas Pitre @ 2007-11-11  4:35 UTC (permalink / raw)
  To: bob; +Cc: git
In-Reply-To: <B20E1D71-BCDB-4189-952F-3B809A342870@mac.com>

On Sat, 10 Nov 2007, bob wrote:

> I will try a few things and see if I can get a script put together
> that generates the inflate problem.  The data that I am
> using is a backup of my original repository.  So, I can
> play all that I want.  But it would be a lot easier if I
> could just generate some files using dd or something.

Please see the patch I just posted to the list.  That should fix your 
problem.  I even included a small script to create a repository 
confirming the problem and allowing to test the fix.


Nicolas

^ permalink raw reply

* Subject: [PATCH 1/3] Added basic color support to git add --interactive
From: Dan Zwell @ 2007-11-11  2:23 UTC (permalink / raw)
  To: Jeff King
  Cc: Junio C Hamano, Shawn O. Pearce, Wincent Colaiuta,
	Git Mailing List, Jonathan del Strother, Johannes Schindelin,
	Frank Lichtenheld
In-Reply-To: <20071104054305.GA13929@sigill.intra.peff.net>

Added function "colored()" that prints text with a color that
is passed in. Converted many calls to "print" to being calls to
"print colored".

The prompt, the header, and the help output are the 3 types of
colorized output, and each has its own color.

Colorization is done through Term::ANSIColor, which is included
with modern versions of perl. This is optional, and should not
need to be present if color.interactive is not turned on.

Signed-off-by: Dan Zwell <dzwell@zwell.net>
---
The last version of this e-mail was line wrapped, if it was 
successfully sent at all...
 Documentation/config.txt  |    6 ++++++
 git-add--interactive.perl |   44 ++++++++++++++++++++++++++++++++++++++------
 2 files changed, 44 insertions(+), 6 deletions(-)

diff --git a/Documentation/config.txt b/Documentation/config.txt
index 8d5d200..3712d6a 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -382,6 +382,12 @@ color.diff.<slot>::
 	whitespace).  The values of these variables may be specified as
 	in color.branch.<slot>.
 
+color.interactive::
+	When true (or `always`), always use colors in `git add
+	--interactive`.  When false (or `never`), never.  When set to
+	`auto`, use colors only when the output is to the
+	terminal. Defaults to false.
+
 color.pager::
 	A boolean to enable/disable colored output when the pager is in
 	use (default is true).
diff --git a/git-add--interactive.perl b/git-add--interactive.perl
index ac598f8..f2b0e56 100755
--- a/git-add--interactive.perl
+++ b/git-add--interactive.perl
@@ -2,6 +2,38 @@
 
 use strict;
 
+my ($use_color, $prompt_color, $header_color, $help_color, $normal_color);
+my $color_config = qx(git config --get color.interactive);
+if ($color_config=~/true|always/ || -t STDOUT && $color_config=~/auto/) {
+	eval { require Term::ANSIColor; };
+	if (!$@) {
+		$use_color = 1;
+
+		# Sane (visible) defaults:
+		$prompt_color = Term::ANSIColor::color("blue bold");
+		$header_color = Term::ANSIColor::color("bold");
+		$help_color   = Term::ANSIColor::color("red bold");
+		$normal_color = Term::ANSIColor::color("reset");
+	}
+}
+
+sub colored {
+	my $color = shift;
+	my $string = join("", @_);
+
+	if ($use_color) {
+		# Put a color code at the beginning of each line, a reset at the end
+		# color after newlines that are not at the end of the string
+		$string =~ s/(\n+)(.)/$1$color$2/g;
+		# reset before newlines
+		$string =~ s/(\n+)/$normal_color$1/g;
+		# codes at beginning and end (if necessary):
+		$string =~ s/^/$color/;
+		$string =~ s/$/$normal_color/ unless $string =~ /\n$/;
+	}
+	return $string;
+}
+
 sub run_cmd_pipe {
 	if ($^O eq 'MSWin32') {
 		my @invalid = grep {m/[":*]/} @_;
@@ -175,7 +207,7 @@ sub list_and_choose {
 			if (!$opts->{LIST_FLAT}) {
 				print "     ";
 			}
-			print "$opts->{HEADER}\n";
+			print colored $header_color, "$opts->{HEADER}\n";
 		}
 		for ($i = 0; $i < @stuff; $i++) {
 			my $chosen = $chosen[$i] ? '*' : ' ';
@@ -205,7 +237,7 @@ sub list_and_choose {
 
 		return if ($opts->{LIST_ONLY});
 
-		print $opts->{PROMPT};
+		print colored $prompt_color, $opts->{PROMPT};
 		if ($opts->{SINGLETON}) {
 			print "> ";
 		}
@@ -544,7 +576,7 @@ sub coalesce_overlapping_hunks {
 }
 
 sub help_patch_cmd {
-	print <<\EOF ;
+	print colored $help_color, <<\EOF ;
 y - stage this hunk
 n - do not stage this hunk
 a - stage this and all the remaining hunks
@@ -619,7 +651,7 @@ sub patch_update_cmd {
 		for (@{$hunk[$ix]{TEXT}}) {
 			print;
 		}
-		print "Stage this hunk [y/n/a/d$other/?]? ";
+		print colored $prompt_color, "Stage this hunk [y/n/a/d$other/?]? ";
 		my $line = <STDIN>;
 		if ($line) {
 			if ($line =~ /^y/i) {
@@ -673,7 +705,7 @@ sub patch_update_cmd {
 			elsif ($other =~ /s/ && $line =~ /^s/) {
 				my @split = split_hunk($hunk[$ix]{TEXT});
 				if (1 < @split) {
-					print "Split into ",
+					print colored $header_color, "Split into ",
 					scalar(@split), " hunks.\n";
 				}
 				splice(@hunk, $ix, 1,
@@ -766,7 +798,7 @@ sub quit_cmd {
 }
 
 sub help_cmd {
-	print <<\EOF ;
+	print colored $help_color, <<\EOF ;
 status        - show paths with changes
 update        - add working tree state to the staged set of changes
 revert        - revert staged set of changes back to the HEAD version
-- 
1.5.3.5.565.gf0b83-dirty

^ permalink raw reply related

* Subject: [PATCH 2/3] Let git-add--interactive read colors from .gitconfig
From: Dan Zwell @ 2007-11-11  2:23 UTC (permalink / raw)
  To: Jeff King
  Cc: Junio C Hamano, Shawn O. Pearce, Wincent Colaiuta,
	Git Mailing List, Jonathan del Strother, Johannes Schindelin,
	Frank Lichtenheld
In-Reply-To: <20071104054305.GA13929@sigill.intra.peff.net>

Colors are specified in color.interactive.{prompt,header,help}.
They are specified as git color strings as described in the
documentation. The method color_to_ansi_string() in Git.pm parses
these strings and returns ANSI color codes (using
Term::ANSIColor).

Signed-off-by: Dan Zwell <dzwell@zwell.net>
---
The last version of this e-mail was line wrapped, if it was 
successfully sent at all.

 Documentation/config.txt  |    7 +++++
 git-add--interactive.perl |   19 ++++++++++-----
 perl/Git.pm               |   55 ++++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 74 insertions(+), 7 deletions(-)

diff --git a/Documentation/config.txt b/Documentation/config.txt
index 3712d6a..47c1ab2 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -388,6 +388,13 @@ color.interactive::
 	`auto`, use colors only when the output is to the
 	terminal. Defaults to false.
 
+color.interactive.<slot>::
+	Use customized color for `git add --interactive`
+	output. `<slot>` may be `prompt`, `header`, or `help`, for
+	three distinct types of normal output from interactive
+	programs.  The values of these variables may be specified as
+	in color.branch.<slot>.
+
 color.pager::
 	A boolean to enable/disable colored output when the pager is in
 	use (default is true).
diff --git a/git-add--interactive.perl b/git-add--interactive.perl
index f2b0e56..508531f 100755
--- a/git-add--interactive.perl
+++ b/git-add--interactive.perl
@@ -1,6 +1,7 @@
 #!/usr/bin/perl -w
 
 use strict;
+use Git;
 
 my ($use_color, $prompt_color, $header_color, $help_color, $normal_color);
 my $color_config = qx(git config --get color.interactive);
@@ -8,12 +9,18 @@ if ($color_config=~/true|always/ || -t STDOUT && $color_config=~/auto/) {
 	eval { require Term::ANSIColor; };
 	if (!$@) {
 		$use_color = 1;
-
-		# Sane (visible) defaults:
-		$prompt_color = Term::ANSIColor::color("blue bold");
-		$header_color = Term::ANSIColor::color("bold");
-		$help_color   = Term::ANSIColor::color("red bold");
-		$normal_color = Term::ANSIColor::color("reset");
+		# Set interactive colors:
+
+		# Grab the 3 main colors in git color string format, with sane
+		# (visible) defaults:
+		my $repo = Git->repository();
+		$prompt_color = Git::color_to_ansi_code(
+			Git::config($repo, "color.interactive.prompt") || "bold blue");
+		$header_color = Git::color_to_ansi_code(
+			Git::config($repo, "color.interactive.header") || "bold");
+		$help_color = Git::color_to_ansi_code(
+			Git::config($repo, "color.interactive.help") || "red bold");
+		$normal_color = Git::color_to_ansi_code("normal");
 	}
 }
 
diff --git a/perl/Git.pm b/perl/Git.pm
index dca92c8..c9e661a 100644
--- a/perl/Git.pm
+++ b/perl/Git.pm
@@ -515,7 +515,6 @@ sub config {
 	};
 }
 
-
 =item config_bool ( VARIABLE )
 
 Retrieve the bool configuration C<VARIABLE>. The return value
@@ -550,6 +549,60 @@ sub config_bool {
 }
 
 
+=item color_to_ansi_code ( COLOR )
+
+Converts a git-style color string, like "underline blue white" to
+an ANSI color code. The code is generated by Term::ANSIColor,
+after the string is parsed into the format that is accepted by
+that module. Used as follows:
+
+	print color_to_ansi_code("underline blue white");
+	print "some text";
+	print color_to_ansi_code("normal");
+
+=cut
+
+sub color_to_ansi_code {
+	my ($git_string) = @_;
+	my @ansi_words;
+	my %attrib_mappings = (
+		"bold"    => "bold",
+		"ul"      => "underline",
+		"blink"   => "blink",
+		# not supported:
+		#"dim"     => "",
+		"reverse" => "reverse"
+	);
+	my ($fg_done, $word);
+
+	foreach $word (split /\s+/, $git_string) {
+		if ($word =~ /normal/) {
+			$fg_done = "true";
+		}
+		elsif ($word =~ /black|red|green|yellow/ ||
+			   $word =~ /blue|magenta|cyan|white/) {
+			# is a color.
+			if ($fg_done) {
+				# this is the background
+				push @ansi_words, "on_" . $word;
+			}
+			else {
+				# this is foreground
+				$fg_done = "true";
+				push @ansi_words, $word;
+			}
+		}
+		else {
+			# this is an attribute, not a color.
+			if ($attrib_mappings{$word}) {
+				push(@ansi_words,
+					 $attrib_mappings{$word});
+			}
+		}
+	}
+	return Term::ANSIColor::color(join(" ", @ansi_words)||"reset");
+}
+
 =item ident ( TYPE | IDENTSTR )
 
 =item ident_person ( TYPE | IDENTSTR | IDENTARRAY )
-- 
1.5.3.5.565.gf0b83-dirty

^ permalink raw reply related

* Re: gitk/git-gui misfeature: saving the geometry can the window out of reach
From: Shawn O. Pearce @ 2007-11-11  5:11 UTC (permalink / raw)
  To: Benoit Sigoure; +Cc: Git Mailing List
In-Reply-To: <63F7323C-D90A-4F5E-AE3C-8937455972FD@lrde.epita.fr>

Benoit Sigoure <tsuna@lrde.epita.fr> wrote:
> gitk (and I think git-gui too) save their "geometry" (which includes  
> X/Y position) in ~/.gitk.  So far so good.  The problem is that I  
> often use 2 screens at work (one is the screen of my laptop, the  
> other one is above) and I happen to put my gitk/git-gui windows on  
> the 2nd screen.  When I go back home, I don't have a second screen  
> and gitk/git-gui open their windows out of reach.  This could well be  
> an ugly wart in Apple's port of Tcl/Tk (I have a MacBook with OSX  
> 10.4.10) or a more general problem (didn't try with other OSes).
> 
> git-gui version 0.8.4
> git version 1.5.3.5.654.gdd5ec (tonight's master's HEAD)
> Tcl/Tk version 8.4.7 (Apple's)
> (gitk doesn't support --version!)
> 
> For those struggling with the same problem, here is a quick workaround:
>   gnused -i /geometry/d ~/.gitk

Actually git-gui saves the geometry to .git/config so I'm not sure
why the sed line above would correct git-gui's display issues.  But I
have also noticed this problem on my Mac OS X laptop when running
again after leaving either git-gui or gitk on the external display.

I once started working on a fix for git-gui but put it aside as I
didn't have an external monitor handy.  I haven't hooked one up to
my laptop in months so it would be a bit of work for me to test
and debug.

-- 
Shawn.

^ permalink raw reply

* Re: [PATCH 01/11] Fix memory leak in traverse_commit_list
From: Shawn O. Pearce @ 2007-11-11  5:17 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <7vmytnqbu2.fsf@gitster.siamese.dyndns.org>

Junio C Hamano <gitster@pobox.com> wrote:
> "Shawn O. Pearce" <spearce@spearce.org> writes:
> 
> > diff --git a/list-objects.c b/list-objects.c
> > index e5c88c2..713bef9 100644
> > --- a/list-objects.c
> > +++ b/list-objects.c
> > @@ -170,4 +170,11 @@ void traverse_commit_list(struct rev_info *revs,
> >  	}
> >  	for (i = 0; i < objects.nr; i++)
> >  		show_object(&objects.objects[i]);
> > +	free(objects.objects);
> > +	if (revs->pending.nr) {
> > +		revs->pending.nr = 0;
> > +		revs->pending.alloc = 0;
> > +		revs->pending.objects = NULL;
> > +		free(revs->pending.objects);
> > +	}
> >  }
> 
> It is locally verifiable that objects.objects are no longer
> needed after this point, but it made me a bit nervous about
> freeing of revs->pending.objects.
> 
> I think the existing callers are all Ok, but somebody else
> should double check.

There are 5 calllers:

* builtin-fetch.c:

   This one I added with my series.  It doesn't care about the
   pending object list.

* builtin-pack-objects.c:

   This doesn't care about the pending list after the call to
   traverse_commit_list.

* builtin-rev-list.c (2):

   Two calls; the first one is for the bisect case where we print
   bisect stats and then return 0 and the second is the end of
   the program for the non-bisect case.  Neither cares about the
   pending list.

* upload-pack.c:

   This is called in the async thread spawned by upload-pack to
   feed pack-objects.  The last thing the async thread does is run
   traverse_commit_list, at which point it exits.  I actually have
   to wonder why we didn't just teach this trick to pack-objects
   so we could avoid the async complexity here in upload-pack.

So yea, the cleanup here is safe, assuming I didn't make the
extremely obvious leak of setting to NULL then calling free()
(as Dscho pointed out).

-- 
Shawn.

^ permalink raw reply

* Re: [PATCH 06/11] git-fetch: Release objects used by a prior transport
From: Shawn O. Pearce @ 2007-11-11  5:29 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <7vve8bqcke.fsf@gitster.siamese.dyndns.org>

Junio C Hamano <gitster@pobox.com> wrote:
> "Shawn O. Pearce" <spearce@spearce.org> writes:
> > diff --git a/builtin-fetch.c b/builtin-fetch.c
> > index 847db73..18f123e 100644
> > --- a/builtin-fetch.c
> > +++ b/builtin-fetch.c
> > @@ -337,7 +337,10 @@ static void store_updated_refs(const char *url, struct ref *ref_map)
> >  
> >  static int fetch_refs(struct transport *transport, struct ref *ref_map)
> >  {
> > -	int ret = transport_fetch_refs(transport, ref_map);
> > +	int ret;
> > +
> > +	free_all_objects();
> > +	ret = transport_fetch_refs(transport, ref_map);
> >  	if (!ret)
> >  		store_updated_refs(transport->url, ref_map);
> >  	transport_unlock_pack(transport);
> 
> This sounds a very heavy-handed approach.
> 
> Is it the callers responsibility to know what function does call
> free_all_objects() and makes sure there is no pointer to objects
> obtained before the call that is used after the call returns?

Yea, I guess it is.  That's part of the reason why this usage was
put here in a static function of builtin-fetch.  Its high enough
up in the call stack that nobody above it cares.  Where we would
run into trouble would be if a transport decided to hang onto any
pointers in its data structure between calls to the transport.

Lets just say we don't free the objects; the flags are still all
messed up from any prior user.  Its tricky to reuse the objects
because we don't know what state an object is left in by someone
that ran before us (e.g. an internal call to fetch-pack!).  Its
also tricky when they free the parent list but leave parsed=1;
we can't rebuild the parent pointers!

-- 
Shawn.

^ permalink raw reply

* Re: [PATCH] status&commit: Teach them to show commits of modified submodules.
From: Yin Ping @ 2007-11-11  5:30 UTC (permalink / raw)
  To: skimo; +Cc: git
In-Reply-To: <20071110195509.GI2261MdfPADPa@greensroom.kotnet.org>

On Nov 11, 2007 3:55 AM, Sven Verdoolaege <skimo@kotnet.org> wrote:
> On Sun, Nov 11, 2007 at 03:27:43AM +0800, Ping Yin wrote:
> > This commit teaches git status/commit to also show commits of user-cared
>
> Does it?  It looks like you only changed git-commit.
> Shouldn't this be put in wt_status_print, if anywhere?
>
git-commit and git-status correspond to the same script git-commit.sh
> Also, you have some typos:
>
> > +     test -n "$modules" && echo -e "#\n# submodule modifiled: "$modules"\n#"
> [..]
> > +                             echo "  Warn: $name dosn't contains commit $headone"
>
> skimo
>
Oops, i'll fix it



-- 
Ping Yin

^ permalink raw reply

* [PATCH 0/3] Adding colors to git-add--interactive
From: Dan Zwell @ 2007-11-11  0:01 UTC (permalink / raw)
  To: Jeff King
  Cc: Junio C Hamano, Shawn O. Pearce, Wincent Colaiuta,
	Git Mailing List, Jonathan del Strother, Johannes Schindelin,
	Frank Lichtenheld
In-Reply-To: <20071104054305.GA13929@sigill.intra.peff.net>

A bit of a recap--this feature was requested by a user a few weeks
ago, and I wrote a short patch that implemented partial coloring. The
main criticisms of this patch were:
- The name of the configuration key to turn on interactive coloring
was not well chosen.
- The color attribute synonyms "clear" and "reset" were used
interchangeably, though "reset" is what the rest of git uses.
- The colors were not user-settable.

When the above were fixed, the new patch garnered the following
criticism:
- The color names accepted in .gitconfig were perl color names (to be
fed to Term::ANSIColor), and this was not consistent with the rest
of git. For example, "red blue ul" would have to be written, "red
on_blue underline".

Fixing this (the colors could not be converted by a regex, but had to
be parsed) was very libraryish, and also a little confusing. I was
given a suggestion or two about how to make it more readable. This
parsing also needed to be added to Git.pm instead of
git-add--interactive.perl.

In the next iteration, all of the above were fixed, but as Jeff King
pointed out, I was printing $color before the beginning of a string,
and printing $clear at the end, which allowed ${COLOR}text\n${RESET},
which looks bad on some terminals.

Last iteration, it was pointed out that print_colored must take a
file handle to pave the way for pager support, and Junio Hamano and Jeff
King both gave suggestions as to how, and Junio sent me few changes
that allow printing colored diffs in addition to prompts. I ended up
making changes so that the two color functions can be used with perl's
print():
print colored($color, "some text")
print color_diff_hunk($hunk)

This way, file handles can be added directly to the print calls, when
support for $PAGER is added.

Let me know if other things need correction.

Dan

^ permalink raw reply

* Re: [PATCH 07/11] git-fetch: Limit automated tag following to only fetched objects
From: Shawn O. Pearce @ 2007-11-11  5:49 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <7v7ikrrr77.fsf@gitster.siamese.dyndns.org>

Junio C Hamano <gitster@pobox.com> wrote:
> "Shawn O. Pearce" <spearce@spearce.org> writes:
> 
> > We now redefine the rule to be: "tags are fetched if they refer
> > to an object that was just transferred; that is an object that is
> > new to your repository".  This rule is quite simple to understand,
> > you only get a tag if you just got the object it refers to.
> 
> In other words, if I do this:
> 
> 	git fetch git-gui master
> 
> (which should not follow any tags) when your master is a bit
> ahead of a new tag in git-gui I do not have, and then
> immediately afterwards if I do:
> 
> 	git fetch git-gui
> 
> I will not get the new tag followed?
> 
> If that is what the patch does, it feels like a regression.

Yeah, that's what it does, and everyone has stated its a regression
so its not the right change to make here.
 
> The intended behaviour was "when tag following is enabled, they
> are followed if they refer to an object that is reachable from
> your existing refs".
> 
> But this is quite expensive to compute.  If a tag points at a
> blob that is contained inside a commit that is reachable from a
> ref, we would need to grep "git rev-list --objects -all" output
> to find it out.  I do not offhand recall what the scripted
> version did, but I would not be surprised if as an approximation
> we did the auto-following by "does the pointee exist" check.

We just did `git cat-file -t`.  If it passed then we followed
the tag.  Which means we could just do a has_sha1_file() test and
call it a day.  If the object is already reachable from our current
refs we'll only download the tag; if it isn't really reachable but
is dangling in the ODB we'll download possibly a lot of objects.

I was trying to make tag auto-following only work if the tag's
target was already completely available and we'd only need to
download the tag object itself.
 
> What "random behaviour" are you trying to fix? 

Apparently I'm introducing even more random behavior.  It may have
just been a bug in the past.  Or a tag whose referred object wasn't
reachable from a ref but I thought it should have been.  Obviously
my patch series resolves neither.

-- 
Shawn.

^ permalink raw reply

* [PATCH 1/3] Added basic color support to git add --interactive
From: Dan Zwell @ 2007-11-11  0:01 UTC (permalink / raw)
  To: Jeff King
  Cc: Junio C Hamano, Shawn O. Pearce, Wincent Colaiuta,
	Git Mailing List, Jonathan del Strother, Johannes Schindelin,
	Frank Lichtenheld
In-Reply-To: <20071104054305.GA13929@sigill.intra.peff.net>

Added function "colored()" that prints text with a color that
is passed in. Converted many calls to "print" to being calls to
"print colored".

The prompt, the header, and the help output are the 3 types of
colorized output, and each has its own color.

Colorization is done through Term::ANSIColor, which is included
with modern versions of perl. This is optional, and should not
need to be present if color.interactive is not turned on.

Signed-off-by: Dan Zwell <dzwell@zwell.net>
---
 Documentation/config.txt  |    6 ++++++
 git-add--interactive.perl |   44
++++++++++++++++++++++++++++++++++++++------ 2 files changed, 44
insertions(+), 6 deletions(-)

diff --git a/Documentation/config.txt b/Documentation/config.txt
index 8d5d200..3712d6a 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -382,6 +382,12 @@ color.diff.<slot>::
 	whitespace).  The values of these variables may be specified as
 	in color.branch.<slot>.
 
+color.interactive::
+	When true (or `always`), always use colors in `git add
+	--interactive`.  When false (or `never`), never.  When set to
+	`auto`, use colors only when the output is to the
+	terminal. Defaults to false.
+
 color.pager::
 	A boolean to enable/disable colored output when the pager is in
 	use (default is true).
diff --git a/git-add--interactive.perl b/git-add--interactive.perl
index ac598f8..f2b0e56 100755
--- a/git-add--interactive.perl
+++ b/git-add--interactive.perl
@@ -2,6 +2,38 @@
 
 use strict;
 
+my ($use_color, $prompt_color, $header_color, $help_color,
$normal_color); +my $color_config = qx(git config --get
color.interactive); +if ($color_config=~/true|always/ || -t STDOUT &&
$color_config=~/auto/) {
+	eval { require Term::ANSIColor; };
+	if (!$@) {
+		$use_color = 1;
+
+		# Sane (visible) defaults:
+		$prompt_color = Term::ANSIColor::color("blue bold");
+		$header_color = Term::ANSIColor::color("bold");
+		$help_color   = Term::ANSIColor::color("red bold");
+		$normal_color = Term::ANSIColor::color("reset");
+	}
+}
+
+sub colored {
+	my $color = shift;
+	my $string = join("", @_);
+
+	if ($use_color) {
+		# Put a color code at the beginning of each line, a
reset at the end
+		# color after newlines that are not at the end of the
string
+		$string =~ s/(\n+)(.)/$1$color$2/g;
+		# reset before newlines
+		$string =~ s/(\n+)/$normal_color$1/g;
+		# codes at beginning and end (if necessary):
+		$string =~ s/^/$color/;
+		$string =~ s/$/$normal_color/ unless $string =~ /\n$/;
+	}
+	return $string;
+}
+
 sub run_cmd_pipe {
 	if ($^O eq 'MSWin32') {
 		my @invalid = grep {m/[":*]/} @_;
@@ -175,7 +207,7 @@ sub list_and_choose {
 			if (!$opts->{LIST_FLAT}) {
 				print "     ";
 			}
-			print "$opts->{HEADER}\n";
+			print colored $header_color,
"$opts->{HEADER}\n"; }
 		for ($i = 0; $i < @stuff; $i++) {
 			my $chosen = $chosen[$i] ? '*' : ' ';
@@ -205,7 +237,7 @@ sub list_and_choose {
 
 		return if ($opts->{LIST_ONLY});
 
-		print $opts->{PROMPT};
+		print colored $prompt_color, $opts->{PROMPT};
 		if ($opts->{SINGLETON}) {
 			print "> ";
 		}
@@ -544,7 +576,7 @@ sub coalesce_overlapping_hunks {
 }
 
 sub help_patch_cmd {
-	print <<\EOF ;
+	print colored $help_color, <<\EOF ;
 y - stage this hunk
 n - do not stage this hunk
 a - stage this and all the remaining hunks
@@ -619,7 +651,7 @@ sub patch_update_cmd {
 		for (@{$hunk[$ix]{TEXT}}) {
 			print;
 		}
-		print "Stage this hunk [y/n/a/d$other/?]? ";
+		print colored $prompt_color, "Stage this hunk
[y/n/a/d$other/?]? "; my $line = <STDIN>;
 		if ($line) {
 			if ($line =~ /^y/i) {
@@ -673,7 +705,7 @@ sub patch_update_cmd {
 			elsif ($other =~ /s/ && $line =~ /^s/) {
 				my @split =
split_hunk($hunk[$ix]{TEXT}); if (1 < @split) {
-					print "Split into ",
+					print colored $header_color,
"Split into ", scalar(@split), " hunks.\n";
 				}
 				splice(@hunk, $ix, 1,
@@ -766,7 +798,7 @@ sub quit_cmd {
 }
 
 sub help_cmd {
-	print <<\EOF ;
+	print colored $help_color, <<\EOF ;
 status        - show paths with changes
 update        - add working tree state to the staged set of changes
 revert        - revert staged set of changes back to the HEAD version
-- 
1.5.3.5.565.gf0b83-dirty

^ permalink raw reply related

* Re: git-gui messes up the diff view on non ASCII characters
From: Shawn O. Pearce @ 2007-11-11  5:59 UTC (permalink / raw)
  To: Michele Ballabio; +Cc: git, Peter Baumann
In-Reply-To: <200711092230.37905.barra_cuda@katamail.com>

Michele Ballabio <barra_cuda@katamail.com> wrote:
> On Friday 09 November 2007, Peter Baumann wrote:
> > I'm managing some UTF-8 encoded LaTeX files in git, which include some
> > non ASCII characters like the german ä,ö and ü. If I view the diff with
> > git-diff on an UTF8 enabled terminal, all looks nice. So does the diff
> > view in gitk after I commited my changes. Only git-gui shows some
> > "strange" characters, so I assume it is an encoding problem.
> > 
> > I have to admit that I'm totally unaware how this should work, but at
> > least I think my configuration is correct here, because otherwise git-diff
> > or gitk would show the same behaviour. Is there anything which could be
> > done to make git-gui happy, too?
> 
> It's a known issue, and already on Shawn's ToDo list. I have to add that
> viewing untracked UTF8 files in git-gui works just fine. Weird.

Cute.  That's because in the untracked case we open the file and
let the platform's chosen encoding be used to convert it into the
text viewer.  In the tracked diff case we force the encoding to
be in binary.

Now gitk works because it assumes the diff is in the same character
encoding as the commit message itself.  Since commit messages are
typically in UTF-8 (as that is the Git default encoding) then a
UTF-8 encoded file shows correctly in gitk.

What's the right behavior here?  Just assume the platform encoding
is correct for the file we are showing and show it?  Assume the
commit encoding configured in i18n.commitencoding is the correct
one for the file content?  Something else?

-- 
Shawn.

^ permalink raw reply

* [PATCH 0/3] git-svn log fixes
From: David D Kilzer @ 2007-11-11  6:10 UTC (permalink / raw)
  To: git; +Cc: gitster, David D Kilzer

This patch series contains varies fixes for the "git-svn log" command:

[PATCH 1/3] git-svn log: fix ascending revision ranges
[PATCH 2/3] git-svn log: include commit log for the smallest revision in a range
[PATCH 3/3] git-svn log: handle unreachable revisions like "svn log"

I am looking for feedback since this is my first significant patch series
for git.  (I posted a couple of documentation fixes and Makefile tweaks
previously.)

Thanks!

Dave
--
 git-svn.perl           |   60 ++++++++++++++++++++++++------------
 t/t9116-git-svn-log.sh |   80 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 120 insertions(+), 20 deletions(-)
--

^ permalink raw reply

* [PATCH 2/3] git-svn log: include commit log for the smallest revision in a range
From: David D Kilzer @ 2007-11-11  6:10 UTC (permalink / raw)
  To: git; +Cc: gitster, David D Kilzer
In-Reply-To: <1194761435-7286-2-git-send-email-ddkilzer@kilzer.net>

The "svn log -rM:N" command shows commit logs inclusive in the range [M,N].
Previously "git-svn log" always excluded the commit log for the smallest
revision in a range, whether the range was ascending or descending.  With
this patch, the smallest revision in a range is always shown.

Updated tests for ascending and descending revision ranges.

Signed-off-by: David D Kilzer <ddkilzer@kilzer.net>
---
 git-svn.perl           |    6 +++---
 t/t9116-git-svn-log.sh |    8 ++++----
 2 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/git-svn.perl b/git-svn.perl
index 3c5a87d..39585d8 100755
--- a/git-svn.perl
+++ b/git-svn.perl
@@ -3592,9 +3592,9 @@ sub git_svn_log_cmd {
 		$c_min = $gs->rev_db_get($r_min);
 		if (defined $c_min && defined $c_max) {
 			if ($r_max > $r_min) {
-				push @cmd, "$c_min..$c_max";
+				push @cmd, "--boundary", "$c_min..$c_max";
 			} else {
-				push @cmd, "$c_max..$c_min";
+				push @cmd, "--boundary", "$c_max..$c_min";
 			}
 		} elsif ($r_max > $r_min) {
 			push @cmd, $c_max;
@@ -3773,7 +3773,7 @@ sub cmd_show_log {
 	my (@k, $c, $d, $stat);
 	my $esc_color = qr/(?:\033\[(?:(?:\d+;)*\d*)?m)*/;
 	while (<$log>) {
-		if (/^${esc_color}commit ($::sha1_short)/o) {
+		if (/^${esc_color}commit -?($::sha1_short)/o) {
 			my $cmt = $1;
 			if ($c && cmt_showable($c) && $c->{r} != $r_last) {
 				$r_last = $c->{r};
diff --git a/t/t9116-git-svn-log.sh b/t/t9116-git-svn-log.sh
index 618d7e9..5000892 100755
--- a/t/t9116-git-svn-log.sh
+++ b/t/t9116-git-svn-log.sh
@@ -45,18 +45,18 @@ test_expect_success 'run log against a from trunk' "
 	git svn log -r3 a | grep ^r3
 	"
 
-printf 'r2 \nr4 \n' > expected-range-r2-r4
+printf 'r1 \nr2 \nr4 \n' > expected-range-r1-r2-r4
 
 test_expect_success 'test ascending revision range' "
 	git reset --hard trunk &&
-	git svn log -r 1:4 | grep '^r[0-9]' | cut -d'|' -f1 | diff -u expected-range-r2-r4 -
+	git svn log -r 1:4 | grep '^r[0-9]' | cut -d'|' -f1 | diff -u expected-range-r1-r2-r4 -
 	"
 
-printf 'r4 \nr2 \n' > expected-range-r4-r2
+printf 'r4 \nr2 \nr1 \n' > expected-range-r4-r2-r1
 
 test_expect_success 'test descending revision range' "
 	git reset --hard trunk &&
-	git svn log -r 4:1 | grep '^r[0-9]' | cut -d'|' -f1 | diff -u expected-range-r4-r2 -
+	git svn log -r 4:1 | grep '^r[0-9]' | cut -d'|' -f1 | diff -u expected-range-r4-r2-r1 -
 	"
 
 test_done
-- 
1.5.3.4

^ permalink raw reply related

* [PATCH 3/3] git-svn log: handle unreachable revisions like "svn log"
From: David D Kilzer @ 2007-11-11  6:10 UTC (permalink / raw)
  To: git; +Cc: gitster, David D Kilzer
In-Reply-To: <1194761435-7286-3-git-send-email-ddkilzer@kilzer.net>

When unreachable revisions are given to "svn log", it displays all commit
logs in the given range that exist in the current tree.  (If no commit
logs are found in the current tree, it simply prints a single commit log
separator.)  This patch makes "git-svn log" behave the same way.

Ten tests added to t/t9116-git-svn-log.sh.

Signed-off-by: David D Kilzer <ddkilzer@kilzer.net>
---
 git-svn.perl           |   58 ++++++++++++++++++++++++++++--------------
 t/t9116-git-svn-log.sh |   66 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 105 insertions(+), 19 deletions(-)

diff --git a/git-svn.perl b/git-svn.perl
index 39585d8..c584715 100755
--- a/git-svn.perl
+++ b/git-svn.perl
@@ -2257,9 +2257,10 @@ sub rev_db_get {
 }
 
 sub find_rev_before {
-	my ($self, $rev, $eq_ok) = @_;
+	my ($self, $rev, $eq_ok, $min_rev) = @_;
 	--$rev unless $eq_ok;
-	while ($rev > 0) {
+	$min_rev ||= 1;
+	while ($rev >= $min_rev) {
 		if (my $c = $self->rev_db_get($rev)) {
 			return ($rev, $c);
 		}
@@ -2268,6 +2269,19 @@ sub find_rev_before {
 	return (undef, undef);
 }
 
+sub find_rev_after {
+	my ($self, $rev, $eq_ok, $max_rev) = @_;
+	++$rev unless $eq_ok;
+	$max_rev ||= $self->rev_db_max();
+	while ($rev <= $max_rev) {
+		if (my $c = $self->rev_db_get($rev)) {
+			return ($rev, $c);
+		}
+		++$rev;
+	}
+	return (undef, undef);
+}
+
 sub _new {
 	my ($class, $repo_id, $ref_id, $path) = @_;
 	unless (defined $repo_id && length $repo_id) {
@@ -3587,19 +3601,19 @@ sub git_svn_log_cmd {
 			push @cmd, $c;
 		}
 	} elsif (defined $r_max) {
-		my ($c_min, $c_max);
-		$c_max = $gs->rev_db_get($r_max);
-		$c_min = $gs->rev_db_get($r_min);
-		if (defined $c_min && defined $c_max) {
-			if ($r_max > $r_min) {
-				push @cmd, "--boundary", "$c_min..$c_max";
-			} else {
-				push @cmd, "--boundary", "$c_max..$c_min";
-			}
-		} elsif ($r_max > $r_min) {
-			push @cmd, $c_max;
+		if ($r_max < $r_min) {
+			($r_min, $r_max) = ($r_max, $r_min);
+		}
+		my (undef, $c_max) = $gs->find_rev_before($r_max, 1, $r_min);
+		my (undef, $c_min) = $gs->find_rev_after($r_min, 1, $r_max);
+		# If there are no commits in the range, both $c_max and $c_min
+		# will be undefined.  If there is at least 1 commit in the
+		# range, both will be defined.
+		return () if !defined $c_min;
+		if ($c_min eq $c_max) {
+			push @cmd, '--max-count=1', $c_min;
 		} else {
-			push @cmd, $c_min;
+			push @cmd, '--boundary', "$c_min..$c_max";
 		}
 	}
 	return (@cmd, @files);
@@ -3705,9 +3719,13 @@ sub show_commit_changed_paths {
 	print "Changed paths:\n", @{$c->{changed}};
 }
 
+sub commit_log_separator {
+    return ('-' x 72) . "\n";
+}
+
 sub show_commit_normal {
 	my ($c) = @_;
-	print '-' x72, "\nr$c->{r} | ";
+	print commit_log_separator(), "r$c->{r} | ";
 	print "$c->{c} | " if $show_commit;
 	print "$c->{a} | ", strftime("%Y-%m-%d %H:%M:%S %z (%a, %d %b %Y)",
 				 localtime($c->{t_utc})), ' | ';
@@ -3768,6 +3786,10 @@ sub cmd_show_log {
 
 	config_pager();
 	@args = git_svn_log_cmd($r_min, $r_max, @args);
+	if (!@args) {
+		print commit_log_separator() unless $incremental || $oneline;
+		return;
+	}
 	my $log = command_output_pipe(@args);
 	run_pager();
 	my (@k, $c, $d, $stat);
@@ -3816,14 +3838,12 @@ sub cmd_show_log {
 		process_commit($c, $r_min, $r_max, \@k);
 	}
 	if (@k) {
-		my $swap = $r_max;
-		$r_max = $r_min;
-		$r_min = $swap;
+		($r_min, $r_max) = ($r_max, $r_min);
 		process_commit($_, $r_min, $r_max) foreach reverse @k;
 	}
 out:
 	close $log;
-	print '-' x72,"\n" unless $incremental || $oneline;
+	print commit_log_separator() unless $incremental || $oneline;
 }
 
 package Git::SVN::Migration;
diff --git a/t/t9116-git-svn-log.sh b/t/t9116-git-svn-log.sh
index 5000892..56dd8fe 100755
--- a/t/t9116-git-svn-log.sh
+++ b/t/t9116-git-svn-log.sh
@@ -30,6 +30,12 @@ test_expect_success 'setup repository and import' "
 	git reset --hard trunk &&
 	echo aye >> README &&
 	git commit -a -m aye &&
+	git svn dcommit &&
+	git reset --hard b &&
+	echo spy >> README &&
+	git commit -a -m spy &&
+	echo try >> README &&
+	git commit -a -m try &&
 	git svn dcommit
 	"
 
@@ -59,4 +65,64 @@ test_expect_success 'test descending revision range' "
 	git svn log -r 4:1 | grep '^r[0-9]' | cut -d'|' -f1 | diff -u expected-range-r4-r2-r1 -
 	"
 
+printf 'r1 \nr2 \n' > expected-range-r1-r2
+
+test_expect_success 'test ascending revision range with unreachable revision' "
+	git reset --hard trunk &&
+	git svn log -r 1:3 | grep '^r[0-9]' | cut -d'|' -f1 | diff -u expected-range-r1-r2 -
+	"
+
+printf 'r2 \nr1 \n' > expected-range-r2-r1
+
+test_expect_success 'test descending revision range with unreachable revision' "
+	git reset --hard trunk &&
+	git svn log -r 3:1 | grep '^r[0-9]' | cut -d'|' -f1 | diff -u expected-range-r2-r1 -
+	"
+
+printf 'r2 \n' > expected-range-r2
+
+test_expect_success 'test ascending revision range with unreachable upper boundary revision and 1 commit' "
+	git reset --hard trunk &&
+	git svn log -r 2:3 | grep '^r[0-9]' | cut -d'|' -f1 | diff -u expected-range-r2 -
+	"
+
+test_expect_success 'test descending revision range with unreachable upper boundary revision and 1 commit' "
+	git reset --hard trunk &&
+	git svn log -r 3:2 | grep '^r[0-9]' | cut -d'|' -f1 | diff -u expected-range-r2 -
+	"
+
+printf 'r4 \n' > expected-range-r4
+
+test_expect_success 'test ascending revision range with unreachable lower boundary revision and 1 commit' "
+	git reset --hard trunk &&
+	git svn log -r 3:4 | grep '^r[0-9]' | cut -d'|' -f1 | diff -u expected-range-r4 -
+	"
+
+test_expect_success 'test descending revision range with unreachable lower boundary revision and 1 commit' "
+	git reset --hard trunk &&
+	git svn log -r 4:3 | grep '^r[0-9]' | cut -d'|' -f1 | diff -u expected-range-r4 -
+	"
+
+echo ------------------------------------------------------------------------ > expected-separator
+
+test_expect_success 'test ascending revision range with unreachable boundary revisions and no commits' "
+	git reset --hard trunk &&
+	git svn log -r 5:6 | diff -u expected-separator -
+	"
+
+test_expect_success 'test descending revision range with unreachable boundary revisions and no commits' "
+	git reset --hard trunk &&
+	git svn log -r 6:5 | diff -u expected-separator -
+	"
+
+test_expect_success 'test ascending revision range with unreachable boundary revisions and 1 commit' "
+	git reset --hard trunk &&
+	git svn log -r 3:5 | grep '^r[0-9]' | cut -d'|' -f1 | diff -u expected-range-r4 -
+	"
+
+test_expect_success 'test descending revision range with unreachable boundary revisions and 1 commit' "
+	git reset --hard trunk &&
+	git svn log -r 5:3 | grep '^r[0-9]' | cut -d'|' -f1 | diff -u expected-range-r4 -
+	"
+
 test_done
-- 
1.5.3.4

^ permalink raw reply related

* [PATCH 1/3] git-svn log: fix ascending revision ranges
From: David D Kilzer @ 2007-11-11  6:10 UTC (permalink / raw)
  To: git; +Cc: gitster, David D Kilzer
In-Reply-To: <1194761435-7286-1-git-send-email-ddkilzer@kilzer.net>

Fixed typo in Git::SVN::Log::git_svn_log_cmd().  Previously a command like
"git-svn log -r1:4" would only show a commit log separator.

Added tests for ascending and descending revision ranges.

Signed-off-by: David D Kilzer <ddkilzer@kilzer.net>
---
 git-svn.perl           |    2 +-
 t/t9116-git-svn-log.sh |   14 ++++++++++++++
 2 files changed, 15 insertions(+), 1 deletions(-)

diff --git a/git-svn.perl b/git-svn.perl
index ec25ea4..3c5a87d 100755
--- a/git-svn.perl
+++ b/git-svn.perl
@@ -3591,7 +3591,7 @@ sub git_svn_log_cmd {
 		$c_max = $gs->rev_db_get($r_max);
 		$c_min = $gs->rev_db_get($r_min);
 		if (defined $c_min && defined $c_max) {
-			if ($r_max > $r_max) {
+			if ($r_max > $r_min) {
 				push @cmd, "$c_min..$c_max";
 			} else {
 				push @cmd, "$c_max..$c_min";
diff --git a/t/t9116-git-svn-log.sh b/t/t9116-git-svn-log.sh
index 0d4e6b3..618d7e9 100755
--- a/t/t9116-git-svn-log.sh
+++ b/t/t9116-git-svn-log.sh
@@ -45,4 +45,18 @@ test_expect_success 'run log against a from trunk' "
 	git svn log -r3 a | grep ^r3
 	"
 
+printf 'r2 \nr4 \n' > expected-range-r2-r4
+
+test_expect_success 'test ascending revision range' "
+	git reset --hard trunk &&
+	git svn log -r 1:4 | grep '^r[0-9]' | cut -d'|' -f1 | diff -u expected-range-r2-r4 -
+	"
+
+printf 'r4 \nr2 \n' > expected-range-r4-r2
+
+test_expect_success 'test descending revision range' "
+	git reset --hard trunk &&
+	git svn log -r 4:1 | grep '^r[0-9]' | cut -d'|' -f1 | diff -u expected-range-r4-r2 -
+	"
+
 test_done
-- 
1.5.3.4

^ permalink raw reply related

* Re: [PATCH] status&commit: Teach them to show commits of modified submodules.
From: Yin Ping @ 2007-11-11  6:18 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <7vabpliz13.fsf@gitster.siamese.dyndns.org>

On Nov 11, 2007 5:14 AM, Junio C Hamano <gitster@pobox.com> wrote:
>  * I think everbody preferes to have "On branch master" at the
>    very beginning

Reasonable.

>
>  * As I understand it, in the real life use,
>    the superproject can stay behind from the tip of subproject
>    and rebind it to a different commit only when there are
>    significant changes of the subproject that need to be there
>    to allow the other parts of the superproject (either
>    superproject itself or another submodule) to use the features
>    and/or fixes the submodule updates provides.

I think it's this kind of case in most open-source project. However,
in a company environment, superprojects may be not so super. A
superproject may bind very tightly with submodules (such as the html
template files which change very frequently) and the developer of a superproject
and its submodules may be the same guy(s). In these cases, a long list
of commits
for submodules are expected be reviewed when commiting the superproject.
>
>    And I think it is more important to give the birds-eye view
>    of the supermodule itself first, when you are helping to
>    prepare a commit message for the supermodule.
>    and then continue "Notable changes in submodule A are ...".
>    And the new part you are adding would help the user to write
>    the latter description.
I agree.
>
> I also find "<<< lines then >>> other lines" format very hard to
> read.  Maybe formatting it like this would make it a bit more
> readable and more space efficient?
>
>         # * sm1 354cd45...3f751e5:
>         #   - one line message for C
>         #   - one line message for B
>         #   + one line message for D
>         #   + one line message for E
>         # * sm2 5c8bfb5...ac46d84:
>         #   - msg
>
I have struggled between these two kinds of presentation and finally
choose the '<<<' one.
IMHO, '-/+' one each line will distract and less space/size efficient
(100 '+/-' for 100 lines of messages).

However, it's not a big matter. I'll change the presentation if
everyone prefers the
patch-like one.

> Note that if you swap the order and move this at the tail
> (perhaps before "Untracked files:" section, if you do not have a
> decent .gitignore set up), you can also lose the "submodules
> modified: sm1 sm2" line and the blank line before it, which
> would make the output even shorter without losing any useful
> information.
>
So following is ok?
        # On branch master
        # Changes to be committed:
        #   (use "git reset HEAD <file>..." to unstage)
        #
        #       modified:   sm1
        #       modified:   sm2
        #       modified:   sm3
        #
        # Changed but not updated:
        #   (use "git add/rm <file>..." to update what will be committed)
        #
        #       modified:   file1
        #
        # Submodules modifiled: sm1 sm2 sm3
        #
        # * sm1 354cd45...3f751e5:
        #   - one line message for C
        #   - one line message for B
        #   + one line message for D
        #   + one line message for E
        # * sm2 354cd46...3f751e7:
        #   - one line message
        # * sm3 354cd47...3f751e8:
        #   Warn: sm1 doesn't contains commit 354cd45
        #
        # Untracked files:
        #   (use "git add <file>..." to include in what will be committed)
        #
        #       file2
        #



-- 
Ping Yin

^ permalink raw reply

* Re: [PATCH] status&commit: Teach them to show commits of modified submodules.
From: Yin Ping @ 2007-11-11  6:24 UTC (permalink / raw)
  To: Lars Hjemli; +Cc: git
In-Reply-To: <8c5c35580711101607l7c45d6f5ge0f40ac6e447031a@mail.gmail.com>

On Nov 11, 2007 8:07 AM, Lars Hjemli <hjemli@gmail.com> wrote:
> On Nov 10, 2007 8:27 PM, Ping Yin <pkufranky@gmail.com> wrote:
> > This commit teaches git status/commit to also show commits of user-cared
> > modified submodules since HEAD (or HEAD^ if --amend option is on).
>
> Some nitpicks:
> -we'll need a config option to enable/disable this output in git-status
agree. default off?
> -the feature should probably be implemented in git-submodule.sh
>
I'll want to see the commits of submodules when editing commit msg. So
i implemented
this in git-commit.sh. May be a configuration/option can added to turn
this on or off.

> --
> larsh
>



-- 
Ping Yin

^ permalink raw reply

* [PATCH 0/5] Return of 'quickfetch' version 3
From: Shawn O. Pearce @ 2007-11-11  7:29 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git

OK, attempt #3.  Much shorter series as I've taken out the (messy)
object memory management change.  Its now unrelated to this series
and may return in the near future.

 1) Fix memory leak in traverse_commit_list

The memory leak we talked about in traverse_commit_list.  Its still
valid for pack-objects but is unnecessary for fetch.

 2) git-fetch: Always fetch tags if the object they reference exists

I think I figured out why I said "random behavior" earlier.
Please see the commit message for an updated description.

 3) run-command: Support sending stderr to /dev/null
 4) rev-list: Introduce --quiet to avoid /dev/null redirects
 5) git-fetch: avoid local fetching from alternate (again)

Pretty much the original quickfetch series, but updated with list
comments and moved to builtin-fetch where it works for all types
of transports and not just the native git one.

-- 
Shawn.

^ permalink raw reply

* [PATCH 1/5] Fix memory leak in traverse_commit_list
From: Shawn O. Pearce @ 2007-11-11  7:29 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git

If we were listing objects too then the objects were buffered in an
array only reachable from a stack allocated structure.  When this
function returns that array would be leaked as nobody would have
a reference to it anymore.

Historically this hasn't been a problem as the primary user of
traverse_commit_list() (the noble git-rev-list) would terminate
as soon as the function was finished, thus allowing the operating
system to cleanup memory.  However we have been leaking this data
in git-pack-objects ever since that program learned how to run the
revision listing internally, rather than relying on reading object
names from git-rev-list.

To better facilitate reuse of traverse_commit_list during other
builtin tools we shouldn't leak temporary memory like this and
instead we need to clean up properly after ourselves.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
---
 list-objects.c |    7 +++++++
 1 files changed, 7 insertions(+), 0 deletions(-)

diff --git a/list-objects.c b/list-objects.c
index e5c88c2..4ef58e7 100644
--- a/list-objects.c
+++ b/list-objects.c
@@ -170,4 +170,11 @@ void traverse_commit_list(struct rev_info *revs,
 	}
 	for (i = 0; i < objects.nr; i++)
 		show_object(&objects.objects[i]);
+	free(objects.objects);
+	if (revs->pending.nr) {
+		free(revs->pending.objects);
+		revs->pending.nr = 0;
+		revs->pending.alloc = 0;
+		revs->pending.objects = NULL;
+	}
 }
-- 
1.5.3.5.1661.gcbf0

^ permalink raw reply related


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