Git development
 help / color / mirror / Atom feed
* Re: [PATCH 01/14] Change git_connect() to return a struct child_process instead of a pid_t.
From: Johannes Schindelin @ 2007-10-14  0:57 UTC (permalink / raw)
  To: Johannes Sixt; +Cc: gitster, git
In-Reply-To: <1192305984-22594-2-git-send-email-johannes.sixt@telecom.at>

Hi,

On Sat, 13 Oct 2007, Johannes Sixt wrote:

> -int finish_connect(pid_t pid)
> +int finish_connect(struct child_process *conn)
>  {
> -	if (pid == 0)
> +	if (conn == NULL)
>  		return 0;
>  
> -	while (waitpid(pid, NULL, 0) < 0) {
> +	while (waitpid(conn->pid, NULL, 0) < 0) {
>  		if (errno != EINTR)
>  			return -1;

Just for completeness' sake: could you do a free(conn); before return -1;?

Thanks,
Dscho

^ permalink raw reply

* Re: Git User's Survey 2007 unfinished summary continued
From: Linus Torvalds @ 2007-10-14  1:13 UTC (permalink / raw)
  To: Johannes Schindelin; +Cc: J. Bruce Fields, Jakub Narebski, git
In-Reply-To: <Pine.LNX.4.64.0710140135020.25221@racer.site>



On Sun, 14 Oct 2007, Johannes Schindelin wrote:
>
> My main point is -- and always was -- that I'd like people to realise how 
> much it depends on _them_ if (and when) their wishes come true.

Dscho, that's just not fair.

The fact is, stating what you wish for *is* taking an action. Starting to 
complain about people stating their wishes (which you have done several 
times) is simply unreasonable.

You don't have to *do* what they wish for, but I really wish you stopped 
complaining about people bringing up their hopes for improvement.

Complain about it when somebody asks for something *stupid*. Explain why 
it would be wrong to do something like that. But don't complain about 
people having wish-lists, even if those people may not work on them.

Not everybody is a "doer". It's important to get input from people who are 
just plain users, or hope to be.

		Linus

^ permalink raw reply

* Re: Git User's Survey 2007 unfinished summary continued
From: Shawn O. Pearce @ 2007-10-14  1:44 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: Johannes Schindelin, J. Bruce Fields, Jakub Narebski, git
In-Reply-To: <alpine.LFD.0.999.0710131810550.6887@woody.linux-foundation.org>

Linus Torvalds <torvalds@linux-foundation.org> wrote:
> On Sun, 14 Oct 2007, Johannes Schindelin wrote:
> >
> > My main point is -- and always was -- that I'd like people to realise how 
> > much it depends on _them_ if (and when) their wishes come true.
> 
> Dscho, that's just not fair.
...
> Complain about it when somebody asks for something *stupid*. Explain why 
> it would be wrong to do something like that. But don't complain about 
> people having wish-lists, even if those people may not work on them.
> 
> Not everybody is a "doer". It's important to get input from people who are 
> just plain users, or hope to be.

I agree with both of you.  My understanding of Dscho's original
comment was that people weren't saying *what* specifically their
wish-list was, which means we have no hope as a community of meeting
their requests.

Carl and Andy both had submitted a long list of very specific issues
that they had with Git.  The result of those lists being posted was
a number of people contributed improvements that lead us to 1.5.
Nobody can argue with that.

But just saying "MY GOD FIX THE UI" is not a wishlist item (yes,
that was a real survey answer).  It provides the community no
chance to understand what parts of the UI we need to work on, and
what parts the end-user is OK with or just hasn't even tried to use.

-- 
Shawn.

^ permalink raw reply

* Re: Git User's Survey 2007 unfinished summary continued
From: Johannes Schindelin @ 2007-10-14  2:06 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: J. Bruce Fields, Jakub Narebski, git
In-Reply-To: <alpine.LFD.0.999.0710131810550.6887@woody.linux-foundation.org>

Hi,

On Sat, 13 Oct 2007, Linus Torvalds wrote:

> On Sun, 14 Oct 2007, Johannes Schindelin wrote:
> >
> > My main point is -- and always was -- that I'd like people to realise 
> > how much it depends on _them_ if (and when) their wishes come true.
> 
> Dscho, that's just not fair.
> 
> The fact is, stating what you wish for *is* taking an action. Starting 
> to complain about people stating their wishes (which you have done 
> several times) is simply unreasonable.

Well, maybe I overreacted.

> You don't have to *do* what they wish for, but I really wish you stopped 
> complaining about people bringing up their hopes for improvement.

Fair enough, I'll shut up about these issues.

At least as long as I can hold my breath ;-)

> Complain about it when somebody asks for something *stupid*. Explain why 
> it would be wrong to do something like that. But don't complain about 
> people having wish-lists, even if those people may not work on them.
> 
> Not everybody is a "doer". It's important to get input from people who are 
> just plain users, or hope to be.

A pity, but you're probably right.

Ciao,
Dscho

^ permalink raw reply

* Re: [PATCH 0/14] fork/exec removal series
From: Shawn O. Pearce @ 2007-10-14  2:11 UTC (permalink / raw)
  To: Johannes Sixt; +Cc: gitster, git
In-Reply-To: <1192305984-22594-1-git-send-email-johannes.sixt@telecom.at>

Johannes Sixt <johannes.sixt@telecom.at> wrote:
> here is a series of patches that removes a number fork/exec pairs.
...
> The series consists of 2 parts:
> 
> - The first half replaces a number of fork/exec pairs by start_command/
>   finish_command or run_command.
> 
> - The second half introduces a new framework that runs a function
>   asynchronously. New functions start_async and finish_async are implemented
>   similarly to start_command and run_command. They are used to replace
>   occurrences of fork() that does not exec() in the child. Such code
>   could in principle be run in a thread, and on MinGW port we will go this
>   route, but on Posix we stay with fork().

This series looks pretty good to me.  I like seeing huge blocks
go away only to be replaced with the simple API offered by
run-command.h.  Makes the result much easier to follow.

The async interface is also quite simple.  Unfortunately there
is some risk with the canonical fork() implementation in that the
async routine might attempt to alter global data that the parent
is also using, and folks on a good UNIX that is using the fork()
implementation will not even notice as they are in totally separated
address spaces.  But you'll see it in MSYS Git.

Since builtin-pack-objects now accepts (limited) pthread support,
perhaps this should be implemented in terms of pthread support
when pthreads are available?  Most Linux/BSD/Mac OS X systems do
have pthreads these days and that's the majority of git users and
developers.  This would make it more likely that bugs in this sort
of code would be detected early.  Just a thought.
 
>  13 files changed, 334 insertions(+), 369 deletions(-)

Hard to argue with that final state.  You killed 35 lines and
also made Git easier to port to "that OS unfortunately named after
transparent glass thingies".

-- 
Shawn.

^ permalink raw reply

* Re: [PATCH 0/14] fork/exec removal series
From: Johannes Schindelin @ 2007-10-14  2:50 UTC (permalink / raw)
  To: Shawn O. Pearce; +Cc: Johannes Sixt, gitster, git
In-Reply-To: <20071014021149.GO27899@spearce.org>

Hi,

On Sat, 13 Oct 2007, Shawn O. Pearce wrote:

> Since builtin-pack-objects now accepts (limited) pthread support, 
> perhaps this should be implemented in terms of pthread support when 
> pthreads are available?

Falling back to fork() when no pthreads are available?  Yes, that makes 
sense.

It might also (marginally) speed up operations, since the switches between 
threads are cheaper than those between processes, right?

Ciao,
Dscho

^ permalink raw reply

* Re: [PATCH 0/14] fork/exec removal series
From: Shawn O. Pearce @ 2007-10-14  2:58 UTC (permalink / raw)
  To: Johannes Schindelin; +Cc: Johannes Sixt, gitster, git
In-Reply-To: <Pine.LNX.4.64.0710140348550.25221@racer.site>

Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:
> On Sat, 13 Oct 2007, Shawn O. Pearce wrote:
> 
> > Since builtin-pack-objects now accepts (limited) pthread support, 
> > perhaps this should be implemented in terms of pthread support when 
> > pthreads are available?
> 
> Falling back to fork() when no pthreads are available?  Yes, that makes 
> sense.
> 
> It might also (marginally) speed up operations, since the switches between 
> threads are cheaper than those between processes, right?

Usually.  If we have a large virtual address space (say due to
opening a bunch of packfiles and reading commits out of them into
struct commit* thingies) and the OS does a giant copy of the page
tables during fork() then the pthread creation should be a heck of
a lot cheaper.

But we most definately *must* continue to support fork() for the
async functions.  Its the most common interface available on one
of our biggest platforms (UNIX).

-- 
Shawn.

^ permalink raw reply

* Re: [PATCH 14/14] Use the asyncronous function infrastructure to run the content filter.
From: Johannes Schindelin @ 2007-10-14  3:07 UTC (permalink / raw)
  To: Johannes Sixt; +Cc: gitster, git
In-Reply-To: <1192305984-22594-15-git-send-email-johannes.sixt@telecom.at>

Hi,

On Sat, 13 Oct 2007, Johannes Sixt wrote:

>  	status = finish_command(&child_process);
>  	if (status)
> -		error("external filter %s failed %d", cmd, -status);
> +		error("external filter %s failed", params->cmd);

Did you mean to remove the status from the output (it should probably read 
"(exit status %d)" instead of just "%d", but an exit status can help 
identify problems, right?


> -	child_process.pid = fork();
> -	if (child_process.pid < 0) {
> -		error("cannot fork to run external filter %s", cmd);
> -		close(pipe_feed[0]);
> -		close(pipe_feed[1]);
> -		return NULL;
> -	}
> -	if (!child_process.pid) {
> -		close(pipe_feed[0]);
> -		exit(filter_buffer(pipe_feed[1], src, *sizep, cmd));
> -	}
> -	close(pipe_feed[1]);
> +	if (start_async(&async))
> +		return 0;	/* error was already reported */

Please write "return NULL;"

Thanks,
Dscho

^ permalink raw reply

* Re: Git User's Survey 2007 unfinished summary continued
From: Linus Torvalds @ 2007-10-14  3:15 UTC (permalink / raw)
  To: Shawn O. Pearce; +Cc: Johannes Schindelin, J. Bruce Fields, Jakub Narebski, git
In-Reply-To: <20071014014445.GN27899@spearce.org>



On Sat, 13 Oct 2007, Shawn O. Pearce wrote:
> 
> But just saying "MY GOD FIX THE UI" is not a wishlist item (yes,
> that was a real survey answer).  It provides the community no
> chance to understand what parts of the UI we need to work on, and
> what parts the end-user is OK with or just hasn't even tried to use.

Heh. I do agree that some people just ask for unreasonable or stupid 
things (or maybe they are just really bad at explaining them, and may have 
something non-stupid in mind but just cannot articulate it).

And I also agree that there are tons of people who are just lazy and don't 
even bother to try to explain themselves.

And I'll flame people myself. I can't even say that's a rare event. So I 
shouldn't throw _too_ many stones, or one of them might bounce back. 

But at the same time, just accepting that there are people who will 
potentially never really be productive members of society (whether 
"society" is git or something bigger), is probably a good idea. They 
aren't worth complaining about: they don't generally tend to take anything 
away from the community unless the community itself reacts negatively to 
them.

			Linus

^ permalink raw reply

* Re: Git User's Survey 2007 unfinished summary continued
From: david @ 2007-10-14  3:43 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Shawn O. Pearce, Johannes Schindelin, J. Bruce Fields,
	Jakub Narebski, git
In-Reply-To: <alpine.LFD.0.999.0710132011270.6887@woody.linux-foundation.org>

On Sat, 13 Oct 2007, Linus Torvalds wrote:

> But at the same time, just accepting that there are people who will
> potentially never really be productive members of society (whether
> "society" is git or something bigger), is probably a good idea. They
> aren't worth complaining about: they don't generally tend to take anything
> away from the community unless the community itself reacts negatively to
> them.

I'll also point out that being a 'productive member of society' may have a 
wider definition then you may think initially.

is a sysadmin who never contribures a line of code, but switches hundreds 
of servers to linux and assists friends in migrating to Linux a productive 
member? he doesn't contribute any code, so some people would say no, but 
in spreading the use he is increasing the number of potential contributers 
so others would say yes.

keep this in mind before you assume that someone isn't worth anything.

David Lang

^ permalink raw reply

* Re: Git User's Survey 2007 unfinished summary continued
From: Linus Torvalds @ 2007-10-14  3:55 UTC (permalink / raw)
  To: david
  Cc: Shawn O. Pearce, Johannes Schindelin, J. Bruce Fields,
	Jakub Narebski, git
In-Reply-To: <Pine.LNX.4.64.0710132037290.30704@asgard.lang.hm>



On Sat, 13 Oct 2007, david@lang.hm wrote:
>
> I'll also point out that being a 'productive member of society' may have a
> wider definition then you may think initially.

I actually meant it in the absolutely most narrow possible meaning: you 
take the least productive person imaginable, who is certainly not going to 
do anything at all, and in the end, who cares? It's not like nonproductive 
people really hurt.

Some people in the open source / free software world get really upset 
about "freeloaders". I think that's silly. First off, I agree with you 
that a lot of people don't even end up being freeloaders - even if you 
never code a single line of code, there are ton of ways to be usefully 
involved (and some of them will be entirely invisible to any developer - 
helping random people outside the development lists, for example).

But more importantly, even somebody who really isn't productive at all 
generally can't be messing things up either - so it's a nonissue. Unless 
it results in tons of flaming ...

		Linus

^ permalink raw reply

* Re: [PATCH] Add a simple option parser.
From: Pierre Habouzit @ 2007-10-14  7:02 UTC (permalink / raw)
  To: Alex Riesen; +Cc: git, Junio C Hamano
In-Reply-To: <20071013221450.GC2875@steel.home>

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

On Sat, Oct 13, 2007 at 10:14:50PM +0000, Alex Riesen wrote:
> Pierre Habouzit, Sat, Oct 13, 2007 22:54:04 +0200:
> > On Sat, Oct 13, 2007 at 07:16:55PM +0000, Alex Riesen wrote:
> > > Pierre Habouzit, Sat, Oct 13, 2007 15:29:03 +0200:
> > > BTW, if you just printed the usage message out (it is about usage of a
> > > program, isn't it?) and called exit() everyone would be just as happy.
> > > And you wouldn't have to include strbuf (it is the only use of it),
> > > less code, too. It'd make simplier to stea^Wcopy your implementation,
> > > which I like :)
> > 
> >   the reason is that usage() is a wrapper around a callback, and I
> > suppose it's used by some GUI's or anything like that.
> 
> It is not. Not yet. What could they use a usage text for?
> Besides, you could just export the callback (call_usage_callback or
> something) from usage.c and call it.

  Okay makes sense.

> >   FWIW you can rework the .c like this:
> 
> on top of yours:

  Added (reworked a bit for the current state of parse_options), and pushed.

-- 
·O·  Pierre Habouzit
··O                                                madcoder@debian.org
OOO                                                http://www.madism.org

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply

* Re: [PATCH 0/14] fork/exec removal series
From: Pierre Habouzit @ 2007-10-14  7:12 UTC (permalink / raw)
  To: Shawn O. Pearce; +Cc: Johannes Schindelin, Johannes Sixt, gitster, git
In-Reply-To: <20071014025857.GQ27899@spearce.org>

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

On Sun, Oct 14, 2007 at 02:58:57AM +0000, Shawn O. Pearce wrote:
> Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:
> > On Sat, 13 Oct 2007, Shawn O. Pearce wrote:
> > 
> > > Since builtin-pack-objects now accepts (limited) pthread support, 
> > > perhaps this should be implemented in terms of pthread support when 
> > > pthreads are available?
> > 
> > Falling back to fork() when no pthreads are available?  Yes, that makes 
> > sense.
> > 
> > It might also (marginally) speed up operations, since the switches between 
> > threads are cheaper than those between processes, right?
> 
> Usually.  If we have a large virtual address space (say due to
> opening a bunch of packfiles and reading commits out of them into
> struct commit* thingies) and the OS does a giant copy of the page
> tables during fork() then the pthread creation should be a heck of
> a lot cheaper.
> 
> But we most definately *must* continue to support fork() for the
> async functions.  Its the most common interface available on one
> of our biggest platforms (UNIX).

  Yeah that, and the fact that many of the git modules aren't
thread-safe (some modules have static buffers strbuf's or caching
variables) and should be used with care.

  The trivial way is to add a __thread keyword to make them TLS
variables, though, it's not really a step in the direction of
portability, and last time I looked at it, mingw didn't had TLS support,
not sure if msys has. Though, if Msys has, it's worth using, and we
could require that targets using the fancy pthread thingy should also
have some fancy TLS, or use fork().

  Portability for such issues, would be to use pthread_key_* and
pthread_{get,set}specific, and those are a hell of a sucky API.

-- 
·O·  Pierre Habouzit
··O                                                madcoder@debian.org
OOO                                                http://www.madism.org

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply

* Re: [PATCH 0/14] fork/exec removal series
From: Pierre Habouzit @ 2007-10-14  7:17 UTC (permalink / raw)
  To: Shawn O. Pearce, Johannes Schindelin, Johannes Sixt, gitster, git
In-Reply-To: <20071014071239.GB1198@artemis.corp>

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

On dim, oct 14, 2007 at 07:12:39 +0000, Pierre Habouzit wrote:
>   The trivial way is to add a __thread keyword to make them TLS
> variables, though, it's not really a step in the direction of
> portability, and last time I looked at it, mingw didn't had TLS support,
> not sure if msys has. Though, if Msys has, it's worth using, and we

  Okay forget it, mingw and msys are one and the same *g*.
  So well, maybe threading isn't such a so great idea :/

-- 
·O·  Pierre Habouzit
··O                                                madcoder@debian.org
OOO                                                http://www.madism.org

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply

* Re: [PATCH 0/14] fork/exec removal series
From: Pierre Habouzit @ 2007-10-14  7:28 UTC (permalink / raw)
  To: Shawn O. Pearce, Johannes Schindelin, Johannes Sixt, gitster, git
In-Reply-To: <20071014071751.GC1198@artemis.corp>

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

On dim, oct 14, 2007 at 07:17:51 +0000, Pierre Habouzit wrote:
> On dim, oct 14, 2007 at 07:12:39 +0000, Pierre Habouzit wrote:
> >   The trivial way is to add a __thread keyword to make them TLS
> > variables, though, it's not really a step in the direction of
> > portability, and last time I looked at it, mingw didn't had TLS support,
> > not sure if msys has. Though, if Msys has, it's worth using, and we
> 
>   Okay forget it, mingw and msys are one and the same *g*.
>   So well, maybe threading isn't such a so great idea :/

  And again last time I checked it was still a mingw 3.x in debian, now
that it's 4.2.1 it seems to support __thread (but not
__declspec(thread)) and their changelog seems to confirm that fact [0].

  So the question holds again, do we require pthread-using targets to
support TLS ? It feels sane and right to me, but …


  [0] http://sourceforge.net/project/shownotes.php?release_id=532062
      [...]
      * The  __thread keyword is honoured.
      [...]

-- 
·O·  Pierre Habouzit
··O                                                madcoder@debian.org
OOO                                                http://www.madism.org

[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]

^ permalink raw reply

* [PATCH] Add color to git-add--interactive diffs
From: Tom Tobin @ 2007-10-14  8:23 UTC (permalink / raw)
  To: Git Mailing List

Seeing the recent discussion and code regarding adding color to
git-add--interactive, I thought I'd throw in my recent attempt at
colorizing the diffs.  (This doesn't handle anything else, such as the
prompts.)

After banging my head against parsing colorized output of git-add-files,
I gave up and implemented internal colorization keying off of the
color.diff configuration.

Hopefully this can be of some use towards fully colorizing
git-add--interactive; I'll admit up front that Perl isn't my primary
language, so I apologize in advance for whatever stupidities I've
introduced.  ;)

Signed-off-by: Tom Tobin <korpios@korpios.com>
---
 git-add--interactive.perl |  111
++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 109 insertions(+), 2 deletions(-)

diff --git a/git-add--interactive.perl b/git-add--interactive.perl
index be68814..eeb38e6 100755
--- a/git-add--interactive.perl
+++ b/git-add--interactive.perl
@@ -1,5 +1,6 @@
 #!/usr/bin/perl -w
 
+use List::Util qw(first);
 use strict;
 
 sub run_cmd_pipe {
@@ -22,6 +23,112 @@ if (!defined $GIT_DIR) {
 }
 chomp($GIT_DIR);
 
+my ($use_color) = 0;
+my (%term_color_codes) = (
+	"normal", "", "black", "0", "red", "1",
+	"green", "2", "yellow", "3", "blue", "4",
+	"magenta", "5", "cyan", "6", "white", "7"
+);
+my (%term_attr_codes) = (
+	"bold", "1", "dim", "2", "ul", "4", "blink", "5", "reverse", "7"
+);
+my %colorconfig = (
+	'color.diff' => 'never',
+	'color.diff.plain' => '',
+	'color.diff.meta' => 'bold',
+	'color.diff.frag' => 'cyan',
+	'color.diff.old' => 'red',
+	'color.diff.new' => 'green',
+	'color.diff.commit' => 'yellow',
+	'color.diff.whitespace' => 'normal red'
+	);
+for (split("\n", `git-config --get-regexp '^color\.diff'`)) {
+	my ($var, $val) = $_ =~ /^([^\s]+)\s(.*)$/;
+	$colorconfig{$var} = $val;
+}
+if (first { $_ eq $colorconfig{'color.diff'} } ("true", "always",
"auto")) {
+	$use_color = 1;
+}
+
+sub parse_color {
+	my ($fg, $bg, $attr, $lookup);
+	my ($fg_code, $bg_code, $attr_code, $output_code) = ("", "", "", "");
+	my (@color) = @_;
+	my (@colorvals) = defined($color[0]) ? split(" ", $color[0]) : ();
+
+	for (@colorvals) {
+		$lookup = $term_color_codes{$_};
+		if (defined($lookup)) {
+			if (!defined($fg)) {
+				$fg = 1;
+				$fg_code = "3$lookup";
+			} elsif (!defined($bg)) {
+				$bg = 1;
+				$bg_code = "4$lookup";
+			} else {
+				die("Color slots only take up to two colors!");
+			}
+			next;
+		}
+		$lookup = $term_attr_codes{$_};
+		if (defined($lookup)) {
+			if (!defined($attr)) {
+				$attr = 1;
+				$attr_code = $lookup;
+			} else {
+				die("Color slots only take a single attribute!");
+			}
+		} else {
+			die("Unrecognized value for color slot!");
+		}
+	}
+	for ($fg_code, $bg_code, $attr_code) {
+		if ($_ eq "") {
+			next;
+		}
+		if ($output_code ne "") {
+			$output_code = $output_code . ";";
+		}
+		$output_code = $output_code . $_;
+	}
+	if (length($output_code)) {
+		return "\e[${output_code}m";
+	} else {
+		return "";
+	}
+}
+
+sub colorize_head_line {
+	my $line = shift @_;
+	if ($use_color) {
+		# git doesn't colorize these by default, soooo
+		# if ($line =~ /^\+/) {
+		#	 return parse_color($colorconfig{'color.diff.new'}) . "$line\e[m";
+		# }
+		# if ($line =~ /^-/) {
+		#	 return parse_color($colorconfig{'color.diff.old'}) . "$line\e[m";
+		# }
+		return parse_color($colorconfig{'color.diff.meta'}) . "$line\e[m";
+	}
+	return $line;
+}
+
+sub colorize_hunk_line {
+	my $line = shift @_;
+	if ($use_color) {
+		if ($line =~ /^\+/) {
+			return parse_color($colorconfig{'color.diff.new'}) . "$line\e[m";
+		}
+		if ($line =~ /^-/) {
+			return parse_color($colorconfig{'color.diff.old'}) . "$line\e[m";
+		}
+		if ($line =~ /^@@ /) {
+			return parse_color($colorconfig{'color.diff.frag'}) . "$line\e[m";
+		}
+	}
+	return $line;
+}
+
 sub refresh {
 	my $fh;
 	open $fh, 'git update-index --refresh |'
@@ -573,7 +680,7 @@ sub patch_update_cmd {
 	my $path = $it->{VALUE};
 	my ($head, @hunk) = parse_diff($path);
 	for (@{$head->{TEXT}}) {
-		print;
+		print colorize_head_line($_);
 	}
 	$num = scalar @hunk;
 	$ix = 0;
@@ -617,7 +724,7 @@ sub patch_update_cmd {
 			$other .= '/s';
 		}
 		for (@{$hunk[$ix]{TEXT}}) {
-			print;
+			print colorize_hunk_line($_);
 		}
 		print "Stage this hunk [y/n/a/d$other/?]? ";
 		my $line = <STDIN>;
-- 
1.5.3.4

^ permalink raw reply related

* Re: [PATCH] Add color to git-add--interactive diffs
From: Tom Tobin @ 2007-10-14  8:38 UTC (permalink / raw)
  To: Git Mailing List
In-Reply-To: <1192350236.7226.6.camel@athena>

On Sun, 2007-10-14 at 03:24 -0500, Tom Tobin wrote:
> Seeing the recent discussion and code regarding adding color to
> git-add--interactive, I thought I'd throw in my recent attempt at
> colorizing the diffs.  (This doesn't handle anything else, such as the
> prompts.)

Crap, my apologies; Evolution inserted a spurious line break in there.

I'll repost the patch.

^ permalink raw reply

* [PATCH] Add color to git-add--interactive diffs (Take 2: now without spurious line break!)
From: Tom Tobin @ 2007-10-14  8:44 UTC (permalink / raw)
  To: Git Mailing List

(This is repost; my damned mail client wrapped a line in the patch last
time, and now I've got that under control.  My apologies!)  :(

Seeing the recent discussion and code regarding adding color to
git-add--interactive, I thought I'd throw in my recent attempt at
colorizing the diffs.  (This doesn't handle anything else, such as the
prompts.)

After banging my head against parsing colorized output of git-add-files,
I gave up and implemented internal colorization keying off of the
color.diff configuration.

Hopefully this can be of some use towards fully colorizing
git-add--interactive; I'll admit up front that Perl isn't my primary
language, so I apologize in advance for whatever stupidities I've
introduced.  ;) 

Signed-off-by: Tom Tobin <korpios@korpios.com>
---
 git-add--interactive.perl |  111 ++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 109 insertions(+), 2 deletions(-)

diff --git a/git-add--interactive.perl b/git-add--interactive.perl
index be68814..eeb38e6 100755
--- a/git-add--interactive.perl
+++ b/git-add--interactive.perl
@@ -1,5 +1,6 @@
 #!/usr/bin/perl -w
 
+use List::Util qw(first);
 use strict;
 
 sub run_cmd_pipe {
@@ -22,6 +23,112 @@ if (!defined $GIT_DIR) {
 }
 chomp($GIT_DIR);
 
+my ($use_color) = 0;
+my (%term_color_codes) = (
+	"normal", "", "black", "0", "red", "1",
+	"green", "2", "yellow", "3", "blue", "4",
+	"magenta", "5", "cyan", "6", "white", "7"
+);
+my (%term_attr_codes) = (
+	"bold", "1", "dim", "2", "ul", "4", "blink", "5", "reverse", "7"
+);
+my %colorconfig = (
+	'color.diff' => 'never',
+	'color.diff.plain' => '',
+	'color.diff.meta' => 'bold',
+	'color.diff.frag' => 'cyan',
+	'color.diff.old' => 'red',
+	'color.diff.new' => 'green',
+	'color.diff.commit' => 'yellow',
+	'color.diff.whitespace' => 'normal red'
+	);
+for (split("\n", `git-config --get-regexp '^color\.diff'`)) {
+	my ($var, $val) = $_ =~ /^([^\s]+)\s(.*)$/;
+	$colorconfig{$var} = $val;
+}
+if (first { $_ eq $colorconfig{'color.diff'} } ("true", "always", "auto")) {
+	$use_color = 1;
+}
+
+sub parse_color {
+	my ($fg, $bg, $attr, $lookup);
+	my ($fg_code, $bg_code, $attr_code, $output_code) = ("", "", "", "");
+	my (@color) = @_;
+	my (@colorvals) = defined($color[0]) ? split(" ", $color[0]) : ();
+
+	for (@colorvals) {
+		$lookup = $term_color_codes{$_};
+		if (defined($lookup)) {
+			if (!defined($fg)) {
+				$fg = 1;
+				$fg_code = "3$lookup";
+			} elsif (!defined($bg)) {
+				$bg = 1;
+				$bg_code = "4$lookup";
+			} else {
+				die("Color slots only take up to two colors!");
+			}
+			next;
+		}
+		$lookup = $term_attr_codes{$_};
+		if (defined($lookup)) {
+			if (!defined($attr)) {
+				$attr = 1;
+				$attr_code = $lookup;
+			} else {
+				die("Color slots only take a single attribute!");
+			}
+		} else {
+			die("Unrecognized value for color slot!");
+		}
+	}
+	for ($fg_code, $bg_code, $attr_code) {
+		if ($_ eq "") {
+			next;
+		}
+		if ($output_code ne "") {
+			$output_code = $output_code . ";";
+		}
+		$output_code = $output_code . $_;
+	}
+	if (length($output_code)) {
+		return "\e[${output_code}m";
+	} else {
+		return "";
+	}
+}
+
+sub colorize_head_line {
+	my $line = shift @_;
+	if ($use_color) {
+		# git doesn't colorize these by default, soooo
+		# if ($line =~ /^\+/) {
+		#	 return parse_color($colorconfig{'color.diff.new'}) . "$line\e[m";
+		# }
+		# if ($line =~ /^-/) {
+		#	 return parse_color($colorconfig{'color.diff.old'}) . "$line\e[m";
+		# }
+		return parse_color($colorconfig{'color.diff.meta'}) . "$line\e[m";
+	}
+	return $line;
+}
+
+sub colorize_hunk_line {
+	my $line = shift @_;
+	if ($use_color) {
+		if ($line =~ /^\+/) {
+			return parse_color($colorconfig{'color.diff.new'}) . "$line\e[m";
+		}
+		if ($line =~ /^-/) {
+			return parse_color($colorconfig{'color.diff.old'}) . "$line\e[m";
+		}
+		if ($line =~ /^@@ /) {
+			return parse_color($colorconfig{'color.diff.frag'}) . "$line\e[m";
+		}
+	}
+	return $line;
+}
+
 sub refresh {
 	my $fh;
 	open $fh, 'git update-index --refresh |'
@@ -573,7 +680,7 @@ sub patch_update_cmd {
 	my $path = $it->{VALUE};
 	my ($head, @hunk) = parse_diff($path);
 	for (@{$head->{TEXT}}) {
-		print;
+		print colorize_head_line($_);
 	}
 	$num = scalar @hunk;
 	$ix = 0;
@@ -617,7 +724,7 @@ sub patch_update_cmd {
 			$other .= '/s';
 		}
 		for (@{$hunk[$ix]{TEXT}}) {
-			print;
+			print colorize_hunk_line($_);
 		}
 		print "Stage this hunk [y/n/a/d$other/?]? ";
 		my $line = <STDIN>;
-- 
1.5.3.4

^ permalink raw reply related

* Re: Git User's Survey 2007 unfinished summary continued
From: Andreas Ericsson @ 2007-10-14  8:45 UTC (permalink / raw)
  To: Johannes Schindelin; +Cc: Linus Torvalds, J. Bruce Fields, Jakub Narebski, git
In-Reply-To: <Pine.LNX.4.64.0710140304430.25221@racer.site>

Johannes Schindelin wrote:
> Hi,
> 
> On Sat, 13 Oct 2007, Linus Torvalds wrote:
> 
>>
>> Not everybody is a "doer". It's important to get input from people who are 
>> just plain users, or hope to be.
> 
> A pity, but you're probably right.
> 

It's not a pity, and he's most definitely right. Users tend to think in terms
of "I'd like to get this task done" while coders tend to think in terms of
"this would be cool/possible to implement". The reason git actually *works* so
great is, I'm sure, the fact that it was originally designed around a very specific
need by someone thinking like a *user*. The fact that it happened to be a pretty
competent programmer just meant he could express his wishes as algorithms in a
programming language and make it happen.

I'm 100% sure that if Linus had been so interested in SCM's that he'd abandoned
the Linux kernel to be full-time maintainer for git instead, it would have had
all sorts of oddities in it that nobody uses, just because they're possible to
do.

I also think Linus made a very wise decision in picking Junio to maintain it. So
far, I haven't seen him accept a single feature-patch into git that wasn't
explained to solve a specific problem.

-- 
Andreas Ericsson                   andreas.ericsson@op5.se
OP5 AB                             www.op5.se
Tel: +46 8-230225                  Fax: +46 8-230231

^ permalink raw reply

* change push's refspec behavior to match rev-parse
From: Steffen Prohaska @ 2007-10-14  8:54 UTC (permalink / raw)
  To: git

This patch series addresses recent complaints about the behavior of push/send-pack
when expanding short refspecs. The overall idea is to change push's handling of
refspecs to match the behavior of rev-parse.


The old way of matching short refspecs in push is often unexpected as
discussed in [1]. Now "git push <ref>" resolves ref the same way as rev-parse.

[1] http://marc.info/?l=git&m=119224567631084&w=2


A related question is how to push only the current branch [2]. Now
"git push HEAD" is supported to push the current head if a matching remote
ref exists.

[2] http://marc.info/?l=git&m=119089831513994&w=2

A summary of the patch series follows below.

    Steffen

 builtin-rev-parse.c   |   27 ++++++++++++-------
 cache.h               |    2 +
 remote.c              |   23 ++++++++++------
 sha1_name.c           |   51 ++++++++++++++++++++++++++++--------
 t/t5516-fetch-push.sh |   68 ++++++++++++++++++++++++++++++++++++++++++++++--
 5 files changed, 138 insertions(+), 33 deletions(-)

 [PATCH 1/6] push, send-pack: fix test if remote branch exists for colon-less refspec

	This is a bug fix that should go to maint. All following patches modifying
        the push test script require this.

 [PATCH 2/6] add get_sha1_with_real_ref() returning full name of ref on demand

	Is required by 3/6 and 4/6

 [PATCH 3/6] rev-parse: teach "git rev-parse --symbolic" to print the full ref name

	A bit off-topic. It demonstrates the use of get_sha1_with_real_ref.

 [PATCH 4/6] push, send-pack: support pushing HEAD to real ref name

	Requires 1/6.

 [PATCH 5/6] add ref_cmp_full_short() comparing full ref name with a short name
 [PATCH 6/6] push, send-pack: use same rules as git-rev-parse to resolve refspecs

	Requires 1/6.

	Note, an updated documentation is not yet included. I like to first wait for
	comments.

^ permalink raw reply

* [PATCH 2/6] add get_sha1_with_real_ref() returning full name of ref on demand
From: Steffen Prohaska @ 2007-10-14  8:54 UTC (permalink / raw)
  To: git; +Cc: Steffen Prohaska
In-Reply-To: <1192352085653-git-send-email-prohaska@zib.de>

Deep inside get_sha1() the name of the requested ref is matched
according to the rules documented in git-rev-parse. This patch
introduces a function that returns the full name of the matched
ref to the outside.

For example 'master' is typically returned as 'refs/heads/master'.

The new function can be used by "git rev-parse" to print the full
name of the matched ref and can be used by "git send-pack" to expand
a local ref to its full name.

Signed-off-by: Steffen Prohaska <prohaska@zib.de>
---
 cache.h     |    1 +
 sha1_name.c |   38 +++++++++++++++++++++++++++-----------
 2 files changed, 28 insertions(+), 11 deletions(-)

diff --git a/cache.h b/cache.h
index e0abcd6..f98d57a 100644
--- a/cache.h
+++ b/cache.h
@@ -401,6 +401,7 @@ static inline unsigned int hexval(unsigned char c)
 
 extern int get_sha1(const char *str, unsigned char *sha1);
 extern int get_sha1_with_mode(const char *str, unsigned char *sha1, unsigned *mode);
+extern int get_sha1_with_real_ref(const char *str, unsigned char *sha1, char **real_ref);
 extern int get_sha1_hex(const char *hex, unsigned char *sha1);
 extern char *sha1_to_hex(const unsigned char *sha1);	/* static buffer result! */
 extern int read_ref(const char *filename, unsigned char *sha1);
diff --git a/sha1_name.c b/sha1_name.c
index 2d727d5..b820909 100644
--- a/sha1_name.c
+++ b/sha1_name.c
@@ -306,7 +306,7 @@ int dwim_log(const char *str, int len, unsigned char *sha1, char **log)
 	return logs_found;
 }
 
-static int get_sha1_basic(const char *str, int len, unsigned char *sha1)
+static int get_sha1_basic(const char *str, int len, unsigned char *sha1, char **real_ref_out)
 {
 	static const char *warning = "warning: refname '%.*s' is ambiguous.\n";
 	char *real_ref = NULL;
@@ -378,17 +378,21 @@ static int get_sha1_basic(const char *str, int len, unsigned char *sha1)
 		}
 	}
 
-	free(real_ref);
+	if (real_ref_out) {
+		*real_ref_out = real_ref;
+	} else {
+		free(real_ref);
+	}
 	return 0;
 }
 
-static int get_sha1_1(const char *name, int len, unsigned char *sha1);
+static int get_sha1_1(const char *name, int len, unsigned char *sha1, char **real_ref);
 
 static int get_parent(const char *name, int len,
 		      unsigned char *result, int idx)
 {
 	unsigned char sha1[20];
-	int ret = get_sha1_1(name, len, sha1);
+	int ret = get_sha1_1(name, len, sha1, /*real_ref=*/ 0);
 	struct commit *commit;
 	struct commit_list *p;
 
@@ -418,7 +422,7 @@ static int get_nth_ancestor(const char *name, int len,
 			    unsigned char *result, int generation)
 {
 	unsigned char sha1[20];
-	int ret = get_sha1_1(name, len, sha1);
+	int ret = get_sha1_1(name, len, sha1, /*real_ref=*/ 0);
 	if (ret)
 		return ret;
 
@@ -471,7 +475,7 @@ static int peel_onion(const char *name, int len, unsigned char *sha1)
 	else
 		return -1;
 
-	if (get_sha1_1(name, sp - name - 2, outer))
+	if (get_sha1_1(name, sp - name - 2, outer, /*real_ref=*/ 0))
 		return -1;
 
 	o = parse_object(outer);
@@ -531,7 +535,7 @@ static int get_describe_name(const char *name, int len, unsigned char *sha1)
 	return -1;
 }
 
-static int get_sha1_1(const char *name, int len, unsigned char *sha1)
+static int get_sha1_1(const char *name, int len, unsigned char *sha1, char **real_ref)
 {
 	int ret, has_suffix;
 	const char *cp;
@@ -569,7 +573,7 @@ static int get_sha1_1(const char *name, int len, unsigned char *sha1)
 	if (!ret)
 		return 0;
 
-	ret = get_sha1_basic(name, len, sha1);
+	ret = get_sha1_basic(name, len, sha1, real_ref);
 	if (!ret)
 		return 0;
 
@@ -651,14 +655,14 @@ int get_sha1(const char *name, unsigned char *sha1)
 	return get_sha1_with_mode(name, sha1, &unused);
 }
 
-int get_sha1_with_mode(const char *name, unsigned char *sha1, unsigned *mode)
+int get_sha1_with_mode_real_ref(const char *name, unsigned char *sha1, unsigned *mode, char** real_ref)
 {
 	int ret, bracket_depth;
 	int namelen = strlen(name);
 	const char *cp;
 
 	*mode = S_IFINVALID;
-	ret = get_sha1_1(name, namelen, sha1);
+	ret = get_sha1_1(name, namelen, sha1, real_ref);
 	if (!ret)
 		return ret;
 	/* sha1:path --> object name of path in ent sha1
@@ -709,9 +713,21 @@ int get_sha1_with_mode(const char *name, unsigned char *sha1, unsigned *mode)
 	}
 	if (*cp == ':') {
 		unsigned char tree_sha1[20];
-		if (!get_sha1_1(name, cp-name, tree_sha1))
+		if (!get_sha1_1(name, cp-name, tree_sha1, real_ref))
 			return get_tree_entry(tree_sha1, cp+1, sha1,
 					      mode);
 	}
 	return ret;
 }
+
+int get_sha1_with_mode(const char *name, unsigned char *sha1, unsigned *mode)
+{
+	return get_sha1_with_mode_real_ref(name, sha1, mode, 0);
+}
+
+int get_sha1_with_real_ref(const char *name, unsigned char *sha1, char **real_ref)
+{
+	unsigned unused;
+	return get_sha1_with_mode_real_ref(name, sha1, &unused, real_ref);
+}
+
-- 
1.5.3.4.224.gc6b84

^ permalink raw reply related

* [PATCH 1/6] push, send-pack: fix test if remote branch exists for colon-less refspec
From: Steffen Prohaska @ 2007-10-14  8:54 UTC (permalink / raw)
  To: git; +Cc: Steffen Prohaska
In-Reply-To: <11923520851713-git-send-email-prohaska@zib.de>

A push must fail if the remote ref does not yet exist and the refspec
does not start with refs/. Remote refs must explicitly be created with
their full name.

This commit adds some tests and fixes the existence check in send-pack.

Signed-off-by: Steffen Prohaska <prohaska@zib.de>
---
 remote.c              |    4 ++--
 t/t5516-fetch-push.sh |   34 ++++++++++++++++++++++++++++++++--
 2 files changed, 34 insertions(+), 4 deletions(-)

diff --git a/remote.c b/remote.c
index bb774d0..36071b2 100644
--- a/remote.c
+++ b/remote.c
@@ -511,12 +511,12 @@ static int match_explicit(struct ref *src, struct ref *dst,
 	case 1:
 		break;
 	case 0:
-		if (!memcmp(dst_value, "refs/", 5))
+		if (!memcmp(rs->dst ? rs->dst : rs->src , "refs/", 5))
 			matched_dst = make_linked_ref(dst_value, dst_tail);
 		else
 			error("dst refspec %s does not match any "
 			      "existing ref on the remote and does "
-			      "not start with refs/.", dst_value);
+			      "not start with refs/.", rs->dst ? rs->dst : rs->src);
 		break;
 	default:
 		matched_dst = NULL;
diff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh
index ca46aaf..8629cf2 100755
--- a/t/t5516-fetch-push.sh
+++ b/t/t5516-fetch-push.sh
@@ -126,6 +126,36 @@ test_expect_success 'push with wildcard' '
 	)
 '
 
+test_expect_success 'push nonexisting (1)' '
+
+	mk_test &&
+	if git push testrepo master
+	then
+		echo "Oops, should have failed"
+		false
+	fi
+
+'
+
+test_expect_success 'push nonexisting (2)' '
+
+	mk_test &&
+	if git push testrepo heads/master
+	then
+		echo "Oops, should have failed"
+		false
+	fi
+
+'
+
+test_expect_success 'push nonexisting (3)' '
+
+	mk_test &&
+	git push testrepo refs/heads/master &&
+	check_push_result $the_commit heads/master
+
+'
+
 test_expect_success 'push with matching heads' '
 
 	mk_test heads/master &&
@@ -225,7 +255,7 @@ test_expect_success 'push with colon-less refspec (3)' '
 		git tag -d frotz
 	fi &&
 	git branch -f frotz master &&
-	git push testrepo frotz &&
+	git push testrepo refs/heads/frotz &&
 	check_push_result $the_commit heads/frotz &&
 	test 1 = $( cd testrepo && git show-ref | wc -l )
 '
@@ -238,7 +268,7 @@ test_expect_success 'push with colon-less refspec (4)' '
 		git branch -D frotz
 	fi &&
 	git tag -f frotz &&
-	git push testrepo frotz &&
+	git push testrepo refs/tags/frotz &&
 	check_push_result $the_commit tags/frotz &&
 	test 1 = $( cd testrepo && git show-ref | wc -l )
 
-- 
1.5.3.4.224.gc6b84

^ permalink raw reply related

* [PATCH 3/6] rev-parse: teach "git rev-parse --symbolic" to print the full ref name
From: Steffen Prohaska @ 2007-10-14  8:54 UTC (permalink / raw)
  To: git; +Cc: Steffen Prohaska
In-Reply-To: <11923520852991-git-send-email-prohaska@zib.de>

"git rev-parse --symbolic" used to return the ref name as it was
specified on the command line. This is changed to returning the
full matched ref name, i.e. "git rev-parse --symbolic master"
now typically returns "refs/heads/master".

Note, this changes output of an established command. It might
break existing setups. I checked that it does not break scripts
in git.git.

Signed-off-by: Steffen Prohaska <prohaska@zib.de>
---
 builtin-rev-parse.c |   27 +++++++++++++++++----------
 1 files changed, 17 insertions(+), 10 deletions(-)

diff --git a/builtin-rev-parse.c b/builtin-rev-parse.c
index 8d78b69..e64abeb 100644
--- a/builtin-rev-parse.c
+++ b/builtin-rev-parse.c
@@ -93,7 +93,7 @@ static void show(const char *arg)
 }
 
 /* Output a revision, only if filter allows it */
-static void show_rev(int type, const unsigned char *sha1, const char *name)
+static void show_rev(int type, const unsigned char *sha1, const char *name, const char* real_name)
 {
 	if (!(filter & DO_REVS))
 		return;
@@ -102,7 +102,9 @@ static void show_rev(int type, const unsigned char *sha1, const char *name)
 
 	if (type != show_type)
 		putchar('^');
-	if (symbolic && name)
+	if (symbolic && real_name)
+		show(real_name);
+	else if (symbolic && name)
 		show(name);
 	else if (abbrev)
 		show(find_unique_abbrev(sha1, abbrev));
@@ -131,7 +133,7 @@ static void show_default(void)
 
 		def = NULL;
 		if (!get_sha1(s, sha1)) {
-			show_rev(NORMAL, sha1, s);
+			show_rev(NORMAL, sha1, s, 0);
 			return;
 		}
 	}
@@ -139,7 +141,7 @@ static void show_default(void)
 
 static int show_reference(const char *refname, const unsigned char *sha1, int flag, void *cb_data)
 {
-	show_rev(NORMAL, sha1, refname);
+	show_rev(NORMAL, sha1, refname, 0);
 	return 0;
 }
 
@@ -187,8 +189,8 @@ static int try_difference(const char *arg)
 	if (dotdot == arg)
 		this = "HEAD";
 	if (!get_sha1(this, sha1) && !get_sha1(next, end)) {
-		show_rev(NORMAL, end, next);
-		show_rev(symmetric ? NORMAL : REVERSED, sha1, this);
+		show_rev(NORMAL, end, next, 0);
+		show_rev(symmetric ? NORMAL : REVERSED, sha1, this, 0);
 		if (symmetric) {
 			struct commit_list *exclude;
 			struct commit *a, *b;
@@ -198,7 +200,7 @@ static int try_difference(const char *arg)
 			while (exclude) {
 				struct commit_list *n = exclude->next;
 				show_rev(REVERSED,
-					 exclude->item->object.sha1,NULL);
+					 exclude->item->object.sha1, NULL, 0);
 				free(exclude);
 				exclude = n;
 			}
@@ -213,6 +215,7 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
 {
 	int i, as_is = 0, verify = 0;
 	unsigned char sha1[20];
+	char* real_name = 0;
 
 	git_config(git_default_config);
 
@@ -393,12 +396,16 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
 		/* Not a flag argument */
 		if (try_difference(arg))
 			continue;
-		if (!get_sha1(arg, sha1)) {
-			show_rev(NORMAL, sha1, arg);
+		if (!get_sha1_with_real_ref(arg, sha1, &real_name)) {
+			show_rev(NORMAL, sha1, arg, real_name);
+			if(real_name) {
+				free(real_name);
+				real_name = 0;
+			}
 			continue;
 		}
 		if (*arg == '^' && !get_sha1(arg+1, sha1)) {
-			show_rev(REVERSED, sha1, arg+1);
+			show_rev(REVERSED, sha1, arg+1, 0);
 			continue;
 		}
 		as_is = 1;
-- 
1.5.3.4.224.gc6b84

^ permalink raw reply related

* [PATCH 4/6] push, send-pack: support pushing HEAD to real ref name
From: Steffen Prohaska @ 2007-10-14  8:54 UTC (permalink / raw)
  To: git; +Cc: Steffen Prohaska
In-Reply-To: <11923520853189-git-send-email-prohaska@zib.de>

This teaches "push <remote> HEAD" to resolve HEAD on the local
side to its real ref name, e.g. refs/heads/master, and then
use the real ref name on the remote side to search a matching
remote ref.

Signed-off-by: Steffen Prohaska <prohaska@zib.de>
---
 remote.c              |   18 +++++++++++++-----
 t/t5516-fetch-push.sh |   22 ++++++++++++++++++++++
 2 files changed, 35 insertions(+), 5 deletions(-)

diff --git a/remote.c b/remote.c
index 36071b2..58bc019 100644
--- a/remote.c
+++ b/remote.c
@@ -439,6 +439,8 @@ static struct ref *try_explicit_object_name(const char *name)
 	unsigned char sha1[20];
 	struct ref *ref;
 	int len;
+	char *real_name = 0;
+	const char *best_name;
 
 	if (!*name) {
 		ref = alloc_ref(20);
@@ -446,12 +448,17 @@ static struct ref *try_explicit_object_name(const char *name)
 		hashclr(ref->new_sha1);
 		return ref;
 	}
-	if (get_sha1(name, sha1))
+	if (get_sha1_with_real_ref(name, sha1, &real_name))
 		return NULL;
-	len = strlen(name) + 1;
+	best_name = real_name ? real_name : name;
+	len = strlen(best_name) + 1;
 	ref = alloc_ref(len);
-	memcpy(ref->name, name, len);
+	memcpy(ref->name, best_name, len);
 	hashcpy(ref->new_sha1, sha1);
+
+	if (real_name) {
+		free(real_name);
+	}
 	return ref;
 }
 
@@ -475,6 +482,7 @@ static int match_explicit(struct ref *src, struct ref *dst,
 	struct ref *matched_src, *matched_dst;
 
 	const char *dst_value = rs->dst;
+	const char * const orig_dst_value = rs->dst ? rs->dst : rs->src;
 
 	if (rs->pattern)
 		return errs;
@@ -511,12 +519,12 @@ static int match_explicit(struct ref *src, struct ref *dst,
 	case 1:
 		break;
 	case 0:
-		if (!memcmp(rs->dst ? rs->dst : rs->src , "refs/", 5))
+		if (!memcmp(orig_dst_value , "refs/", 5))
 			matched_dst = make_linked_ref(dst_value, dst_tail);
 		else
 			error("dst refspec %s does not match any "
 			      "existing ref on the remote and does "
-			      "not start with refs/.", rs->dst ? rs->dst : rs->src);
+			      "not start with refs/.", orig_dst_value);
 		break;
 	default:
 		matched_dst = NULL;
diff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh
index 8629cf2..97a032e 100755
--- a/t/t5516-fetch-push.sh
+++ b/t/t5516-fetch-push.sh
@@ -274,4 +274,26 @@ test_expect_success 'push with colon-less refspec (4)' '
 
 '
 
+test_expect_success 'push with HEAD' '
+
+	mk_test heads/master &&
+	git push testrepo HEAD &&
+	check_push_result $the_commit heads/master
+
+'
+
+test_expect_success 'push with HEAD not existing at remote' '
+
+	mk_test heads/master &&
+	git checkout -b local master &&
+	if git push testrepo HEAD
+	then
+		echo "Oops, should have failed"
+		false
+	else
+		check_push_result $the_first_commit heads/master
+	fi
+
+'
+
 test_done
-- 
1.5.3.4.224.gc6b84

^ permalink raw reply related

* [PATCH 6/6] push, send-pack: use same rules as git-rev-parse to resolve refspecs
From: Steffen Prohaska @ 2007-10-14  8:54 UTC (permalink / raw)
  To: git; +Cc: Steffen Prohaska
In-Reply-To: <11923520853014-git-send-email-prohaska@zib.de>

This commit changes the rules for resolving refspecs to match the
rules for resolving refs in rev-parse. git-rev-parse uses clear rules
to resolve a short ref to its full name, which are well documented.
The rules for resolving refspecs documented in git-send-pack were
less strict and harder to understand. This commit replaces them by
the rules of git-rev-parse.

The unified rules are easier to understand and better resolve ambiguous
cases. You can now push from a repository containing several branches
ending on the same short name.

Note, this breaks existing setups. For example "master" will no longer
resolve to "origin/master".

TODO: this patch does not yet include a modified documentation of
git-send-pack. I prefer to wait for some comments first.

Signed-off-by: Steffen Prohaska <prohaska@zib.de>
---
 remote.c              |    5 +----
 t/t5516-fetch-push.sh |   12 +++++++++++-
 2 files changed, 12 insertions(+), 5 deletions(-)

diff --git a/remote.c b/remote.c
index 58bc019..09cb611 100644
--- a/remote.c
+++ b/remote.c
@@ -383,10 +383,7 @@ static int count_refspec_match(const char *pattern,
 		char *name = refs->name;
 		int namelen = strlen(name);
 
-		if (namelen < patlen ||
-		    memcmp(name + namelen - patlen, pattern, patlen))
-			continue;
-		if (namelen != patlen && name[namelen - patlen - 1] != '/')
+		if (ref_cmp_full_short(name, pattern))
 			continue;
 
 		/* A match is "weak" if it is with refs outside
diff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh
index 97a032e..2664060 100755
--- a/t/t5516-fetch-push.sh
+++ b/t/t5516-fetch-push.sh
@@ -175,11 +175,21 @@ test_expect_success 'push with no ambiguity (1)' '
 test_expect_success 'push with no ambiguity (2)' '
 
 	mk_test remotes/origin/master &&
-	git push testrepo master:master &&
+	git push testrepo master:origin/master &&
 	check_push_result $the_commit remotes/origin/master
 
 '
 
+test_expect_success 'push with colon-less refspec, no ambiguity' '
+
+	mk_test heads/master heads/t/master &&
+	git branch -f t/master master &&
+	git push testrepo master &&
+	check_push_result $the_commit heads/master &&
+	check_push_result $the_first_commit heads/t/master
+
+'
+
 test_expect_success 'push with weak ambiguity (1)' '
 
 	mk_test heads/master remotes/origin/master &&
-- 
1.5.3.4.224.gc6b84

^ 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