Git development
 help / color / mirror / Atom feed
* 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

* [PATCH 2/5] git-fetch: Always fetch tags if the object they reference exists
From: Shawn O. Pearce @ 2007-11-11  7:29 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git

Previously git-fetch.sh used `git cat-file -t` to determine if an
object referenced by a tag exists, and if so fetch that tag locally.
This was subtly broken during the port to C based builtin-fetch as
lookup_object() only works to locate an object if it was previously
accessed by the transport.  Not all transports will access all
objects in this way, so tags were not always being fetched.

The rsync transport never loads objects into the internal object
table so automated tag following didn't work if rsync was used.
Automated tag following also didn't work on the native transport
if the new tag was behind the common point(s) negotiated between
the two ends of the connection as the tag's referrant would not
be loaded into the internal object table.  Further the automated
tag following was broken with the HTTP commit walker if the new
tag's referrant was behind an existing ref, as the walker would
stop before loading the tag's referrant into the object table.

Switching to has_sha1_file() restores the original behavior from
the shell script by checking if the object exists in the ODB,
without relying on the state left behind by a transport.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
---
 builtin-fetch.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/builtin-fetch.c b/builtin-fetch.c
index 847db73..a935b5a 100644
--- a/builtin-fetch.c
+++ b/builtin-fetch.c
@@ -389,7 +389,7 @@ static struct ref *find_non_local_tags(struct transport *transport,
 
 		if (!path_list_has_path(&existing_refs, ref_name) &&
 		    !path_list_has_path(&new_refs, ref_name) &&
-		    lookup_object(ref->old_sha1)) {
+		    has_sha1_file(ref->old_sha1)) {
 			path_list_insert(ref_name, &new_refs);
 
 			rm = alloc_ref(strlen(ref_name) + 1);
-- 
1.5.3.5.1661.gcbf0

^ permalink raw reply related

* [PATCH 3/5] run-command: Support sending stderr to /dev/null
From: Shawn O. Pearce @ 2007-11-11  7:29 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git

Some callers may wish to redirect stderr to /dev/null in some
contexts, such as if they are executing a command only to get
the exit status and don't want users to see whatever output it
may produce as a side-effect of computing that exit status.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
---
 run-command.c |    6 ++++--
 run-command.h |    1 +
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/run-command.c b/run-command.c
index d99a6c4..476d00c 100644
--- a/run-command.c
+++ b/run-command.c
@@ -41,7 +41,7 @@ int start_command(struct child_process *cmd)
 		cmd->close_out = 1;
 	}
 
-	need_err = cmd->err < 0;
+	need_err = !cmd->no_stderr && cmd->err < 0;
 	if (need_err) {
 		if (pipe(fderr) < 0) {
 			if (need_in)
@@ -87,7 +87,9 @@ int start_command(struct child_process *cmd)
 			close(cmd->out);
 		}
 
-		if (need_err) {
+		if (cmd->no_stderr)
+			dup_devnull(2);
+		else if (need_err) {
 			dup2(fderr[1], 2);
 			close_pair(fderr);
 		}
diff --git a/run-command.h b/run-command.h
index 94e1e9d..1fc781d 100644
--- a/run-command.h
+++ b/run-command.h
@@ -23,6 +23,7 @@ struct child_process {
 	unsigned close_out:1;
 	unsigned no_stdin:1;
 	unsigned no_stdout:1;
+	unsigned no_stderr:1;
 	unsigned git_cmd:1; /* if this is to be git sub-command */
 	unsigned stdout_to_stderr:1;
 };
-- 
1.5.3.5.1661.gcbf0

^ permalink raw reply related

* [PATCH 4/5] rev-list: Introduce --quiet to avoid /dev/null redirects
From: Shawn O. Pearce @ 2007-11-11  7:29 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git

Some uses of git-rev-list are to run it with --objects to see if
a range of objects between two or more commits is fully connected
or not.  In such a case the caller doesn't care about the actual
object names or hash hints so formatting this data only for it to
be dumped to /dev/null by a redirect is a waste of CPU time.  If
all the caller needs is the exit status then --quiet can be used
to bypass the commit and object formatting.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
---
 Documentation/git-rev-list.txt |    9 +++++++++
 builtin-rev-list.c             |   26 ++++++++++++++++++++++----
 2 files changed, 31 insertions(+), 4 deletions(-)

diff --git a/Documentation/git-rev-list.txt b/Documentation/git-rev-list.txt
index 4852804..989fbf3 100644
--- a/Documentation/git-rev-list.txt
+++ b/Documentation/git-rev-list.txt
@@ -20,6 +20,7 @@ SYNOPSIS
 	     [ \--not ]
 	     [ \--all ]
 	     [ \--stdin ]
+	     [ \--quiet ]
 	     [ \--topo-order ]
 	     [ \--parents ]
 	     [ \--timestamp ]
@@ -270,6 +271,14 @@ limiting may be applied.
 	In addition to the '<commit>' listed on the command
 	line, read them from the standard input.
 
+--quiet::
+
+	Don't print anything to standard output.  This form of
+	git-rev-list is primarly meant to allow the caller to
+	test the exit status to see if a range of objects is fully
+	connected (or not).  It is faster than redirecting stdout
+	to /dev/null as the output does not have to be formatted.
+
 --cherry-pick::
 
 	Omit any commit that introduces the same change as
diff --git a/builtin-rev-list.c b/builtin-rev-list.c
index 2dec887..d67724c 100644
--- a/builtin-rev-list.c
+++ b/builtin-rev-list.c
@@ -26,6 +26,7 @@ static const char rev_list_usage[] =
 "    --remove-empty\n"
 "    --all\n"
 "    --stdin\n"
+"    --quiet\n"
 "  ordering output:\n"
 "    --topo-order\n"
 "    --date-order\n"
@@ -50,6 +51,7 @@ static int show_timestamp;
 static int hdr_termination;
 static const char *header_prefix;
 
+static void finish_commit(struct commit *commit);
 static void show_commit(struct commit *commit)
 {
 	if (show_timestamp)
@@ -93,6 +95,11 @@ static void show_commit(struct commit *commit)
 		strbuf_release(&buf);
 	}
 	maybe_flush_or_die(stdout, "stdout");
+	finish_commit(commit);
+}
+
+static void finish_commit(struct commit *commit)
+{
 	if (commit->parents) {
 		free_commit_list(commit->parents);
 		commit->parents = NULL;
@@ -101,6 +108,12 @@ static void show_commit(struct commit *commit)
 	commit->buffer = NULL;
 }
 
+static void finish_object(struct object_array_entry *p)
+{
+	if (p->item->type == OBJ_BLOB && !has_sha1_file(p->item->sha1))
+		die("missing blob object '%s'", sha1_to_hex(p->item->sha1));
+}
+
 static void show_object(struct object_array_entry *p)
 {
 	/* An object with name "foo\n0000000..." can be used to
@@ -108,9 +121,7 @@ static void show_object(struct object_array_entry *p)
 	 */
 	const char *ep = strchr(p->name, '\n');
 
-	if (p->item->type == OBJ_BLOB && !has_sha1_file(p->item->sha1))
-		die("missing blob object '%s'", sha1_to_hex(p->item->sha1));
-
+	finish_object(p);
 	if (ep) {
 		printf("%s %.*s\n", sha1_to_hex(p->item->sha1),
 		       (int) (ep - p->name),
@@ -527,6 +538,7 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
 	int read_from_stdin = 0;
 	int bisect_show_vars = 0;
 	int bisect_find_all = 0;
+	int quiet = 0;
 
 	git_config(git_default_config);
 	init_revisions(&revs, prefix);
@@ -565,6 +577,10 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
 			read_revisions_from_stdin(&revs);
 			continue;
 		}
+		if (!strcmp(arg, "--quiet")) {
+			quiet = 1;
+			continue;
+		}
 		usage(rev_list_usage);
 
 	}
@@ -640,7 +656,9 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)
 		}
 	}
 
-	traverse_commit_list(&revs, show_commit, show_object);
+	traverse_commit_list(&revs,
+		quiet ? finish_commit : show_commit,
+		quiet ? finish_object : show_object);
 
 	return 0;
 }
-- 
1.5.3.5.1661.gcbf0

^ permalink raw reply related

* [PATCH 5/5] git-fetch: avoid local fetching from alternate (again)
From: Shawn O. Pearce @ 2007-11-11  7:29 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git

Back in e3c6f240fd9c5bdeb33f2d47adc859f37935e2df Junio taught
git-fetch to avoid copying objects when we are fetching from
a repository that is already registered as an alternate object
database.  In such a case there is no reason to copy any objects
as we can already obtain them through the alternate.

However we need to ensure the objects are all reachable, so we
run `git rev-list --objects $theirs --not --all` to verify this.
If any object is missing or unreadable then we need to fetch/copy
the objects from the remote.  When a missing object is detected
the git-rev-list process will exit with a non-zero exit status,
making this condition quite easy to detect.

Although git-fetch is currently a builtin (and so is rev-list)
we cannot invoke the traverse_objects() API at this point in the
transport code.  The object walker within traverse_objects() calls
die() as soon as it finds an object it cannot read.  If that happens
we want to resume the fetch process by calling do_fetch_pack().
To get around this we spawn git-rev-list into a background process
to prevent a die() from killing the foreground fetch process,
thus allowing the fetch process to resume into do_fetch_pack()
if copying is necessary.

We aren't interested in the output of rev-list (a list of SHA-1
object names that are reachable) or its errors (a "spurious" error
about an object not being found as we need to copy it) so we redirect
both stdout and stderr to /dev/null.

We run this git-rev-list based check before any fetch as we may
already have the necessary objects local from a prior fetch.  If we
don't then its very likely the first $theirs object listed on the
command line won't exist locally and git-rev-list will die very
quickly, allowing us to start the network transfer.  This test even
on remote URLs may save bandwidth if someone runs `git pull origin`,
sees a merge conflict, resets out, then redoes the same pull just
a short time later.  If the remote hasn't changed between the two
pulls and the local repository hasn't had git-gc run in it then
there is probably no need to perform network transfer as all of
the objects are local.

Documentation for the new quickfetch function was suggested and
written by Junio, based on his original comment in git-fetch.sh.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
---
 builtin-fetch.c       |   69 +++++++++++++++++++++++++++++++++++++++++++++++-
 t/t5502-quickfetch.sh |   33 +++++++++++++++++++++++
 2 files changed, 100 insertions(+), 2 deletions(-)

diff --git a/builtin-fetch.c b/builtin-fetch.c
index a935b5a..31e138e 100644
--- a/builtin-fetch.c
+++ b/builtin-fetch.c
@@ -8,10 +8,12 @@
 #include "path-list.h"
 #include "remote.h"
 #include "transport.h"
+#include "run-command.h"
 
 static const char fetch_usage[] = "git-fetch [-a | --append] [--upload-pack <upload-pack>] [-f | --force] [--no-tags] [-t | --tags] [-k | --keep] [-u | --update-head-ok] [--depth <depth>] [-v | --verbose] [<repository> <refspec>...]";
 
 static int append, force, tags, no_tags, update_head_ok, verbose, quiet;
+static const char *depth;
 static char *default_rla = NULL;
 static struct transport *transport;
 
@@ -335,9 +337,72 @@ static void store_updated_refs(const char *url, struct ref *ref_map)
 	fclose(fp);
 }
 
+/*
+ * We would want to bypass the object transfer altogether if
+ * everything we are going to fetch already exists and connected
+ * locally.
+ *
+ * The refs we are going to fetch are in to_fetch (nr_heads in
+ * total).  If running
+ *
+ *  $ git-rev-list --objects to_fetch[0] to_fetch[1] ... --not --all
+ *
+ * does not error out, that means everything reachable from the
+ * refs we are going to fetch exists and is connected to some of
+ * our existing refs.
+ */
+static int quickfetch(struct ref *ref_map)
+{
+	struct child_process revlist;
+	struct ref *ref;
+	char **argv;
+	int i, err;
+
+	/*
+	 * If we are deepening a shallow clone we already have these
+	 * objects reachable.  Running rev-list here will return with
+	 * a good (0) exit status and we'll bypass the fetch that we
+	 * really need to perform.  Claiming failure now will ensure
+	 * we perform the network exchange to deepen our history.
+	 */
+	if (depth)
+		return -1;
+
+	for (i = 0, ref = ref_map; ref; ref = ref->next)
+		i++;
+	if (!i)
+		return 0;
+
+	argv = xmalloc(sizeof(*argv) * (i + 6));
+	i = 0;
+	argv[i++] = xstrdup("rev-list");
+	argv[i++] = xstrdup("--quiet");
+	argv[i++] = xstrdup("--objects");
+	for (ref = ref_map; ref; ref = ref->next)
+		argv[i++] = xstrdup(sha1_to_hex(ref->old_sha1));
+	argv[i++] = xstrdup("--not");
+	argv[i++] = xstrdup("--all");
+	argv[i++] = NULL;
+
+	memset(&revlist, 0, sizeof(revlist));
+	revlist.argv = (const char**)argv;
+	revlist.git_cmd = 1;
+	revlist.no_stdin = 1;
+	revlist.no_stdout = 1;
+	revlist.no_stderr = 1;
+	err = run_command(&revlist);
+
+	for (i = 0; argv[i]; i++)
+		free(argv[i]);
+	free(argv);
+	return err;
+}
+
 static int fetch_refs(struct transport *transport, struct ref *ref_map)
 {
-	int ret = transport_fetch_refs(transport, ref_map);
+	int ret = quickfetch(ref_map);
+	if (ret)
+		ret = transport_fetch_refs(transport, ref_map);
 	if (!ret)
 		store_updated_refs(transport->url, ref_map);
 	transport_unlock_pack(transport);
@@ -473,7 +538,7 @@ int cmd_fetch(int argc, const char **argv, const char *prefix)
 	static const char **refs = NULL;
 	int ref_nr = 0;
 	int cmd_len = 0;
-	const char *depth = NULL, *upload_pack = NULL;
+	const char *upload_pack = NULL;
 	int keep = 0;
 
 	for (i = 1; i < argc; i++) {
diff --git a/t/t5502-quickfetch.sh b/t/t5502-quickfetch.sh
index b4760f2..16eadd6 100755
--- a/t/t5502-quickfetch.sh
+++ b/t/t5502-quickfetch.sh
@@ -86,4 +86,37 @@ test_expect_success 'quickfetch should not leave a corrupted repository' '
 
 '
 
+test_expect_success 'quickfetch should not copy from alternate' '
+
+	(
+		mkdir quickclone &&
+		cd quickclone &&
+		git init-db &&
+		(cd ../.git/objects && pwd) >.git/objects/info/alternates &&
+		git remote add origin .. &&
+		git fetch -k -k
+	) &&
+	obj_cnt=$( (
+		cd quickclone &&
+		git count-objects | sed -e "s/ *objects,.*//"
+	) ) &&
+	pck_cnt=$( (
+		cd quickclone &&
+		git count-objects -v | sed -n -e "/packs:/{
+				s/packs://
+				p
+				q
+			}"
+	) ) &&
+	origin_master=$( (
+		cd quickclone &&
+		git rev-parse origin/master
+	) ) &&
+	echo "loose objects: $obj_cnt, packfiles: $pck_cnt" &&
+	test $obj_cnt -eq 0 &&
+	test $pck_cnt -eq 0 &&
+	test z$origin_master = z$(git rev-parse master)
+
+'
+
 test_done
-- 
1.5.3.5.1661.gcbf0

^ permalink raw reply related

* [PATCH 0/3] Adding colors to git-add--interactive
From: Dan Zwell @ 2007-11-11  2:21 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>

[Note: I'm resending this because it looks like this e-mail didn't go
out properly. Sorry for duplicates.]

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 0/3] Adding colors to git-add--interactive
From: Jeff King @ 2007-11-11  7:54 UTC (permalink / raw)
  To: Dan Zwell
  Cc: Junio C Hamano, Shawn O. Pearce, Wincent Colaiuta,
	Git Mailing List, Jonathan del Strother, Johannes Schindelin,
	Frank Lichtenheld
In-Reply-To: <20071110180109.34febc3f@paradox.zwell.net>

On Sat, Nov 10, 2007 at 06:01:09PM -0600, Dan Zwell wrote:

> A bit of a recap--this feature was requested by a user a few weeks

Thanks for the recap; there have been enough iterations of this series
that at least I forgot what was going on. The patches look reasonable,
but I have a few comments (hopefully you have enough "umph" for one more
iteration). I'll just inline them here.

[patch 1/3]:
> +my ($use_color, $prompt_color, $header_color, $help_color, $normal_color);
> +my $color_config = qx(git config --get color.interactive);

Why call git config here manually, but Git::config later (I think the
answer is "because we don't call Git::config until a later patch", but it
is probably best to remain consistent).

> +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;
> +}

This also seems like a candidate for lib-ification in Git.pm, alongside
color_to_ansi_code.

> -			print "$opts->{HEADER}\n";
> +			print colored $header_color, "$opts->{HEADER}\n";

I don't know if we have a style policy on calling

  user_defined_function $foo, $bar;

rather than

  user_defined_function($foo, $bar);

In fact, I don't know that we have much perl style policy at all. But I
tend to shy away from the former because then the syntax requires that
"colored" is always defined before the calling spot.

[patch 2/3]:
> +		# 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");

It is much more common (and proper OO, in the face of inheritance) to
use

   $repo->config("color.interactive.prompt")

> +=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");

Yay, documentation!  It would also be nice to have a test script that
runs this through a few more complex git color specs.

> +	my %attrib_mappings = (
> +		"bold"    => "bold",
> +		"ul"      => "underline",
> +		"blink"   => "blink",
> +		# not supported:
> +		#"dim"     => "",

Why not? I don't especially care about "dim" support, but if there is a
good reason, then you should note it.

> +	foreach $word (split /\s+/, $git_string) {
> +		if ($word =~ /normal/) {
> +			$fg_done = "true";
> +		}

Why a regex instead of 'eq'? Also, should this be case insensitive?

> +		elsif ($word =~ /black|red|green|yellow/ ||
> +			   $word =~ /blue|magenta|cyan|white/) {

It looks like you are doing two regexes here just to meet whitespace
guidelines. Look into the '/x' modifier to make your regex prettier (but
again, consider 'eq').

> +	return Term::ANSIColor::color(join(" ", @ansi_words)||"reset");

Style: whitespace around ||

[patch 3/3]:
> +			# Not implemented:
> +			#$whitespace_color = Git::color_to_ansi_code(
> +				#Git::config($repo, "color.diff.whitespace") || "normal red");

Personally I would have just excluded the parsing, since it isn't
implemented, but I don't think it matters.

> +sub colored_diff_hunk {

Perhaps this should also go in Git.pm? Though right now I don't know
which other perl scripts would actually want to colorize a diff, so I
don't think it matters.

> -	system(qw(git diff-index -p --cached HEAD --),
> -	       map { $_->{VALUE} } @them);
> +	system(qw(git diff -p --cached HEAD --), map { $_->{VALUE} } @them);

Now this was a surprise after reading the commit message.

-Peff

^ permalink raw reply

* Dose git-fetch need --reference option like git-clone?
From: Yin Ping @ 2007-11-11  8:09 UTC (permalink / raw)
  To: git

I want to track remote repsotory (say remoteA) on my local repository
(say localB), so i do the following in directory localB
$ git remote add remoteA git://remoteAUrl
$ git fetch remoteA
This will fetch all objects from git://remoteAUrl if localB and
remoteA don't have common objects.

If I already have a cloned remoteA on local machine (say
/path/to/remoteACloned), I want to do following to reduce the net
traffic as git-clone:
git fetch --reference /path/to/remoteACloned remotedA

Is this reasonable? Or is there already a resolution for this case?

-- 
Ping Yin

^ 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