Git development
 help / color / mirror / Atom feed
* [PATCH v3.1 3/5] Introduce new pretty formats %g[sdD] for reflog information
From: Thomas Rast @ 2009-10-17 14:39 UTC (permalink / raw)
  To: Jeff King, Junio C Hamano; +Cc: Jef Driesen, Nanako Shiraishi, git
In-Reply-To: <cover.1255789678.git.trast@student.ethz.ch>

Add three new --pretty=format escapes:

  %gD  long  reflog descriptor (e.g. refs/stash@{0})
  %gd  short reflog descriptor (e.g. stash@{0})
  %gs  reflog message

This is achieved by passing down the reflog info, if any, inside the
pretty_print_context struct.

We use the newly refactored get_reflog_selector(), and give it some
extra functionality to extract a shortened ref.  The shortening is
cached inside the commit_reflogs struct; the only allocation of it
happens in read_complete_reflog(), where it is initialised to 0.  Also
add another helper get_reflog_message() for the message extraction.

Note that the --format="%h %gD: %gs" tests may not work in real
repositories, as the --pretty formatter doesn't know to leave away the
": " on the last commit in an incomplete (because git-gc removed the
old part) reflog.  This equivalence is nevertheless the main goal of
this patch.

Thanks to Jeff King for reviews, the %gd testcase and documentation.

Signed-off-by: Thomas Rast <trast@student.ethz.ch>
---

[Tacking this on the corresponding v3 patch, but the text below is
from <20091017011801.GA31443@coredump.intra.peff.net>.]

Jeff King wrote:
> I am tempted to do a note like the one below, but maybe the behavior is
> obvious enough to users that it isn't necessary.
[...]
> +NOTE: Some placeholders may depend on other options given to the
> +revision traversal engine. For example, the `%g*` reflog options will
> +insert an empty string unless we are traversing reflog entries (e.g., by
> +`git log -g`). The `%d` placeholder will use the "short" decoration
> +format if `--decorate` was not already provided on the command line.

Sure.  I figured it was obvious enough, but since you already went to
the lengths of documenting the exact behaviour of %d, I squashed it
and adjusted the acknowledgement in the commit message accordingly.


 Documentation/pretty-formats.txt |    9 +++++++++
 commit.h                         |    1 +
 log-tree.c                       |    1 +
 pretty.c                         |   17 +++++++++++++++++
 reflog-walk.c                    |   35 ++++++++++++++++++++++++++++++++---
 reflog-walk.h                    |    8 ++++++++
 t/t6006-rev-list-format.sh       |   18 ++++++++++++++++++
 7 files changed, 86 insertions(+), 3 deletions(-)

diff --git a/Documentation/pretty-formats.txt b/Documentation/pretty-formats.txt
index 2a845b1..38b9904 100644
--- a/Documentation/pretty-formats.txt
+++ b/Documentation/pretty-formats.txt
@@ -123,6 +123,9 @@ The placeholders are:
 - '%s': subject
 - '%f': sanitized subject line, suitable for a filename
 - '%b': body
+- '%gD': reflog selector, e.g., `refs/stash@\{1\}`
+- '%gd': shortened reflog selector, e.g., `stash@\{1\}`
+- '%gs': reflog subject
 - '%Cred': switch color to red
 - '%Cgreen': switch color to green
 - '%Cblue': switch color to blue
@@ -132,6 +135,12 @@ The placeholders are:
 - '%n': newline
 - '%x00': print a byte from a hex code
 
+NOTE: Some placeholders may depend on other options given to the
+revision traversal engine. For example, the `%g*` reflog options will
+insert an empty string unless we are traversing reflog entries (e.g., by
+`git log -g`). The `%d` placeholder will use the "short" decoration
+format if `--decorate` was not already provided on the command line.
+
 * 'tformat:'
 +
 The 'tformat:' format works exactly like 'format:', except that it
diff --git a/commit.h b/commit.h
index 011766d..15cb649 100644
--- a/commit.h
+++ b/commit.h
@@ -70,6 +70,7 @@ struct pretty_print_context
 	const char *after_subject;
 	enum date_mode date_mode;
 	int need_8bit_cte;
+	struct reflog_walk_info *reflog_info;
 };
 
 extern int non_ascii(int);
diff --git a/log-tree.c b/log-tree.c
index f57487f..8e782fc 100644
--- a/log-tree.c
+++ b/log-tree.c
@@ -409,6 +409,7 @@ void show_log(struct rev_info *opt)
 	ctx.date_mode = opt->date_mode;
 	ctx.abbrev = opt->diffopt.abbrev;
 	ctx.after_subject = extra_headers;
+	ctx.reflog_info = opt->reflog_info;
 	pretty_print_commit(opt->commit_format, commit, &msgbuf, &ctx);
 
 	if (opt->add_signoff)
diff --git a/pretty.c b/pretty.c
index d6d57eb..fc65fca 100644
--- a/pretty.c
+++ b/pretty.c
@@ -7,6 +7,7 @@
 #include "mailmap.h"
 #include "log-tree.h"
 #include "color.h"
+#include "reflog-walk.h"
 
 static char *user_format;
 
@@ -701,6 +702,22 @@ static size_t format_commit_item(struct strbuf *sb, const char *placeholder,
 	case 'd':
 		format_decoration(sb, commit);
 		return 1;
+	case 'g':		/* reflog info */
+		switch(placeholder[1]) {
+		case 'd':	/* reflog selector */
+		case 'D':
+			if (c->pretty_ctx->reflog_info)
+				get_reflog_selector(sb,
+						    c->pretty_ctx->reflog_info,
+						    c->pretty_ctx->date_mode,
+						    (placeholder[1] == 'd'));
+			return 2;
+		case 's':	/* reflog message */
+			if (c->pretty_ctx->reflog_info)
+				get_reflog_message(sb, c->pretty_ctx->reflog_info);
+			return 2;
+		}
+		return 0;	/* unknown %g placeholder */
 	}
 
 	/* For the rest we have to parse the commit header. */
diff --git a/reflog-walk.c b/reflog-walk.c
index 596bafe..caba4f7 100644
--- a/reflog-walk.c
+++ b/reflog-walk.c
@@ -8,6 +8,7 @@
 
 struct complete_reflogs {
 	char *ref;
+	const char *short_ref;
 	struct reflog_info {
 		unsigned char osha1[20], nsha1[20];
 		char *email;
@@ -243,15 +244,26 @@ void fake_reflog_parent(struct reflog_walk_info *info, struct commit *commit)
 
 void get_reflog_selector(struct strbuf *sb,
 			 struct reflog_walk_info *reflog_info,
-			 enum date_mode dmode)
+			 enum date_mode dmode,
+			 int shorten)
 {
 	struct commit_reflog *commit_reflog = reflog_info->last_commit_reflog;
 	struct reflog_info *info;
+	const char *printed_ref;
 
 	if (!commit_reflog)
 		return;
 
-	strbuf_addf(sb, "%s@{", commit_reflog->reflogs->ref);
+	if (shorten) {
+		if (!commit_reflog->reflogs->short_ref)
+			commit_reflog->reflogs->short_ref
+				= shorten_unambiguous_ref(commit_reflog->reflogs->ref, 0);
+		printed_ref = commit_reflog->reflogs->short_ref;
+	} else {
+		printed_ref = commit_reflog->reflogs->ref;
+	}
+
+	strbuf_addf(sb, "%s@{", printed_ref);
 	if (commit_reflog->flag || dmode) {
 		info = &commit_reflog->reflogs->items[commit_reflog->recno+1];
 		strbuf_addstr(sb, show_date(info->timestamp, info->tz, dmode));
@@ -263,6 +275,23 @@ void get_reflog_selector(struct strbuf *sb,
 	strbuf_addch(sb, '}');
 }
 
+void get_reflog_message(struct strbuf *sb,
+			struct reflog_walk_info *reflog_info)
+{
+	struct commit_reflog *commit_reflog = reflog_info->last_commit_reflog;
+	struct reflog_info *info;
+	size_t len;
+
+	if (!commit_reflog)
+		return;
+
+	info = &commit_reflog->reflogs->items[commit_reflog->recno+1];
+	len = strlen(info->message);
+	if (len > 0)
+		len--; /* strip away trailing newline */
+	strbuf_add(sb, info->message, len);
+}
+
 void show_reflog_message(struct reflog_walk_info *reflog_info, int oneline,
 	enum date_mode dmode)
 {
@@ -272,7 +301,7 @@ void show_reflog_message(struct reflog_walk_info *reflog_info, int oneline,
 		struct strbuf selector = STRBUF_INIT;
 
 		info = &commit_reflog->reflogs->items[commit_reflog->recno+1];
-		get_reflog_selector(&selector, reflog_info, dmode);
+		get_reflog_selector(&selector, reflog_info, dmode, 0);
 		if (oneline) {
 			printf("%s: %s", selector.buf, info->message);
 		}
diff --git a/reflog-walk.h b/reflog-walk.h
index 74c9096..7bd2cd4 100644
--- a/reflog-walk.h
+++ b/reflog-walk.h
@@ -3,6 +3,8 @@
 
 #include "cache.h"
 
+struct reflog_walk_info;
+
 extern void init_reflog_walk(struct reflog_walk_info** info);
 extern int add_reflog_for_walk(struct reflog_walk_info *info,
 		struct commit *commit, const char *name);
@@ -10,5 +12,11 @@ extern void fake_reflog_parent(struct reflog_walk_info *info,
 		struct commit *commit);
 extern void show_reflog_message(struct reflog_walk_info *info, int,
 		enum date_mode);
+extern void get_reflog_message(struct strbuf *sb,
+		struct reflog_walk_info *reflog_info);
+extern void get_reflog_selector(struct strbuf *sb,
+		struct reflog_walk_info *reflog_info,
+		enum date_mode dmode,
+		int shorten);
 
 #endif
diff --git a/t/t6006-rev-list-format.sh b/t/t6006-rev-list-format.sh
index 59d1f62..7f61ab0 100755
--- a/t/t6006-rev-list-format.sh
+++ b/t/t6006-rev-list-format.sh
@@ -162,4 +162,22 @@ test_expect_success 'empty email' '
 	}
 '
 
+test_expect_success '"%h %gD: %gs" is same as git-reflog' '
+	git reflog >expect &&
+	git log -g --format="%h %gD: %gs" >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success '"%h %gD: %gs" is same as git-reflog (with date)' '
+	git reflog --date=raw >expect &&
+	git log -g --format="%h %gD: %gs" --date=raw >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success '%gd shortens ref name' '
+	echo "master@{0}" >expect.gd-short &&
+	git log -g -1 --format=%gd refs/heads/master >actual.gd-short &&
+	test_cmp expect.gd-short actual.gd-short
+'
+
 test_done
-- 
1.6.5.116.g4aaa3

^ permalink raw reply related

* [PATCH v3.1 3/5] Introduce new pretty formats %g[sdD] for reflog information
From: Thomas Rast @ 2009-10-17 14:48 UTC (permalink / raw)
  To: Jeff King, Junio C Hamano; +Cc: Jef Driesen, Nanako Shiraishi, git
In-Reply-To: <8a5b3a586d437f02e2a75edd2786636b605522a7.1255701207.git.trast@student.ethz.ch>

Add three new --pretty=format escapes:

  %gD  long  reflog descriptor (e.g. refs/stash@{0})
  %gd  short reflog descriptor (e.g. stash@{0})
  %gs  reflog message

This is achieved by passing down the reflog info, if any, inside the
pretty_print_context struct.

We use the newly refactored get_reflog_selector(), and give it some
extra functionality to extract a shortened ref.  The shortening is
cached inside the commit_reflogs struct; the only allocation of it
happens in read_complete_reflog(), where it is initialised to 0.  Also
add another helper get_reflog_message() for the message extraction.

Note that the --format="%h %gD: %gs" tests may not work in real
repositories, as the --pretty formatter doesn't know to leave away the
": " on the last commit in an incomplete (because git-gc removed the
old part) reflog.  This equivalence is nevertheless the main goal of
this patch.

Thanks to Jeff King for reviews, the %gd testcase and documentation.

Signed-off-by: Thomas Rast <trast@student.ethz.ch>
---

I wrote:
> [Tacking this on the corresponding v3 patch, but the text below is
> from <20091017011801.GA31443@coredump.intra.peff.net>.]

This sadly backfired, as I forgot to snip out the in-reply-to in the
mail itself and git-send-email apparently trusted that more.  Sorry
for the confusion.

Jeff King wrote:
> I am tempted to do a note like the one below, but maybe the behavior is
> obvious enough to users that it isn't necessary.
[...]
> +NOTE: Some placeholders may depend on other options given to the
> +revision traversal engine. For example, the `%g*` reflog options will
> +insert an empty string unless we are traversing reflog entries (e.g., by
> +`git log -g`). The `%d` placeholder will use the "short" decoration
> +format if `--decorate` was not already provided on the command line.

Sure.  I figured it was obvious enough, but since you already went to
the lengths of documenting the exact behaviour of %d, I squashed it
and adjusted the acknowledgement in the commit message accordingly.

 Documentation/pretty-formats.txt |    9 +++++++++
 commit.h                         |    1 +
 log-tree.c                       |    1 +
 pretty.c                         |   17 +++++++++++++++++
 reflog-walk.c                    |   35 ++++++++++++++++++++++++++++++++---
 reflog-walk.h                    |    8 ++++++++
 t/t6006-rev-list-format.sh       |   18 ++++++++++++++++++
 7 files changed, 86 insertions(+), 3 deletions(-)

diff --git a/Documentation/pretty-formats.txt b/Documentation/pretty-formats.txt
index 2a845b1..38b9904 100644
--- a/Documentation/pretty-formats.txt
+++ b/Documentation/pretty-formats.txt
@@ -123,6 +123,9 @@ The placeholders are:
 - '%s': subject
 - '%f': sanitized subject line, suitable for a filename
 - '%b': body
+- '%gD': reflog selector, e.g., `refs/stash@\{1\}`
+- '%gd': shortened reflog selector, e.g., `stash@\{1\}`
+- '%gs': reflog subject
 - '%Cred': switch color to red
 - '%Cgreen': switch color to green
 - '%Cblue': switch color to blue
@@ -132,6 +135,12 @@ The placeholders are:
 - '%n': newline
 - '%x00': print a byte from a hex code
 
+NOTE: Some placeholders may depend on other options given to the
+revision traversal engine. For example, the `%g*` reflog options will
+insert an empty string unless we are traversing reflog entries (e.g., by
+`git log -g`). The `%d` placeholder will use the "short" decoration
+format if `--decorate` was not already provided on the command line.
+
 * 'tformat:'
 +
 The 'tformat:' format works exactly like 'format:', except that it
diff --git a/commit.h b/commit.h
index 011766d..15cb649 100644
--- a/commit.h
+++ b/commit.h
@@ -70,6 +70,7 @@ struct pretty_print_context
 	const char *after_subject;
 	enum date_mode date_mode;
 	int need_8bit_cte;
+	struct reflog_walk_info *reflog_info;
 };
 
 extern int non_ascii(int);
diff --git a/log-tree.c b/log-tree.c
index f57487f..8e782fc 100644
--- a/log-tree.c
+++ b/log-tree.c
@@ -409,6 +409,7 @@ void show_log(struct rev_info *opt)
 	ctx.date_mode = opt->date_mode;
 	ctx.abbrev = opt->diffopt.abbrev;
 	ctx.after_subject = extra_headers;
+	ctx.reflog_info = opt->reflog_info;
 	pretty_print_commit(opt->commit_format, commit, &msgbuf, &ctx);
 
 	if (opt->add_signoff)
diff --git a/pretty.c b/pretty.c
index d6d57eb..fc65fca 100644
--- a/pretty.c
+++ b/pretty.c
@@ -7,6 +7,7 @@
 #include "mailmap.h"
 #include "log-tree.h"
 #include "color.h"
+#include "reflog-walk.h"
 
 static char *user_format;
 
@@ -701,6 +702,22 @@ static size_t format_commit_item(struct strbuf *sb, const char *placeholder,
 	case 'd':
 		format_decoration(sb, commit);
 		return 1;
+	case 'g':		/* reflog info */
+		switch(placeholder[1]) {
+		case 'd':	/* reflog selector */
+		case 'D':
+			if (c->pretty_ctx->reflog_info)
+				get_reflog_selector(sb,
+						    c->pretty_ctx->reflog_info,
+						    c->pretty_ctx->date_mode,
+						    (placeholder[1] == 'd'));
+			return 2;
+		case 's':	/* reflog message */
+			if (c->pretty_ctx->reflog_info)
+				get_reflog_message(sb, c->pretty_ctx->reflog_info);
+			return 2;
+		}
+		return 0;	/* unknown %g placeholder */
 	}
 
 	/* For the rest we have to parse the commit header. */
diff --git a/reflog-walk.c b/reflog-walk.c
index 596bafe..caba4f7 100644
--- a/reflog-walk.c
+++ b/reflog-walk.c
@@ -8,6 +8,7 @@
 
 struct complete_reflogs {
 	char *ref;
+	const char *short_ref;
 	struct reflog_info {
 		unsigned char osha1[20], nsha1[20];
 		char *email;
@@ -243,15 +244,26 @@ void fake_reflog_parent(struct reflog_walk_info *info, struct commit *commit)
 
 void get_reflog_selector(struct strbuf *sb,
 			 struct reflog_walk_info *reflog_info,
-			 enum date_mode dmode)
+			 enum date_mode dmode,
+			 int shorten)
 {
 	struct commit_reflog *commit_reflog = reflog_info->last_commit_reflog;
 	struct reflog_info *info;
+	const char *printed_ref;
 
 	if (!commit_reflog)
 		return;
 
-	strbuf_addf(sb, "%s@{", commit_reflog->reflogs->ref);
+	if (shorten) {
+		if (!commit_reflog->reflogs->short_ref)
+			commit_reflog->reflogs->short_ref
+				= shorten_unambiguous_ref(commit_reflog->reflogs->ref, 0);
+		printed_ref = commit_reflog->reflogs->short_ref;
+	} else {
+		printed_ref = commit_reflog->reflogs->ref;
+	}
+
+	strbuf_addf(sb, "%s@{", printed_ref);
 	if (commit_reflog->flag || dmode) {
 		info = &commit_reflog->reflogs->items[commit_reflog->recno+1];
 		strbuf_addstr(sb, show_date(info->timestamp, info->tz, dmode));
@@ -263,6 +275,23 @@ void get_reflog_selector(struct strbuf *sb,
 	strbuf_addch(sb, '}');
 }
 
+void get_reflog_message(struct strbuf *sb,
+			struct reflog_walk_info *reflog_info)
+{
+	struct commit_reflog *commit_reflog = reflog_info->last_commit_reflog;
+	struct reflog_info *info;
+	size_t len;
+
+	if (!commit_reflog)
+		return;
+
+	info = &commit_reflog->reflogs->items[commit_reflog->recno+1];
+	len = strlen(info->message);
+	if (len > 0)
+		len--; /* strip away trailing newline */
+	strbuf_add(sb, info->message, len);
+}
+
 void show_reflog_message(struct reflog_walk_info *reflog_info, int oneline,
 	enum date_mode dmode)
 {
@@ -272,7 +301,7 @@ void show_reflog_message(struct reflog_walk_info *reflog_info, int oneline,
 		struct strbuf selector = STRBUF_INIT;
 
 		info = &commit_reflog->reflogs->items[commit_reflog->recno+1];
-		get_reflog_selector(&selector, reflog_info, dmode);
+		get_reflog_selector(&selector, reflog_info, dmode, 0);
 		if (oneline) {
 			printf("%s: %s", selector.buf, info->message);
 		}
diff --git a/reflog-walk.h b/reflog-walk.h
index 74c9096..7bd2cd4 100644
--- a/reflog-walk.h
+++ b/reflog-walk.h
@@ -3,6 +3,8 @@
 
 #include "cache.h"
 
+struct reflog_walk_info;
+
 extern void init_reflog_walk(struct reflog_walk_info** info);
 extern int add_reflog_for_walk(struct reflog_walk_info *info,
 		struct commit *commit, const char *name);
@@ -10,5 +12,11 @@ extern void fake_reflog_parent(struct reflog_walk_info *info,
 		struct commit *commit);
 extern void show_reflog_message(struct reflog_walk_info *info, int,
 		enum date_mode);
+extern void get_reflog_message(struct strbuf *sb,
+		struct reflog_walk_info *reflog_info);
+extern void get_reflog_selector(struct strbuf *sb,
+		struct reflog_walk_info *reflog_info,
+		enum date_mode dmode,
+		int shorten);
 
 #endif
diff --git a/t/t6006-rev-list-format.sh b/t/t6006-rev-list-format.sh
index 59d1f62..7f61ab0 100755
--- a/t/t6006-rev-list-format.sh
+++ b/t/t6006-rev-list-format.sh
@@ -162,4 +162,22 @@ test_expect_success 'empty email' '
 	}
 '
 
+test_expect_success '"%h %gD: %gs" is same as git-reflog' '
+	git reflog >expect &&
+	git log -g --format="%h %gD: %gs" >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success '"%h %gD: %gs" is same as git-reflog (with date)' '
+	git reflog --date=raw >expect &&
+	git log -g --format="%h %gD: %gs" --date=raw >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success '%gd shortens ref name' '
+	echo "master@{0}" >expect.gd-short &&
+	git log -g -1 --format=%gd refs/heads/master >actual.gd-short &&
+	test_cmp expect.gd-short actual.gd-short
+'
+
 test_done
-- 
1.6.5.116.g4aaa3

^ permalink raw reply related

* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was
From: Julian Phillips @ 2009-10-17 15:02 UTC (permalink / raw)
  To: Björn Steinbrink
  Cc: Daniel Barkalow, James Pickens, Jeff King, Junio C Hamano,
	Nicolas Pitre, Jay Soffian, git
In-Reply-To: <20091017075551.GA5474@atjola.homenet>

On Sat, 17 Oct 2009, Bj?rn Steinbrink wrote:

> On 2009.10.16 18:31:23 +0100, Julian Phillips wrote:
>> On Fri, 16 Oct 2009, Bj?rn Steinbrink wrote:
>>> On 2009.10.16 13:15:35 +0100, Julian Phillips wrote:
>>>> How about:
>>>>
>>>> $ git checkout origin/master
>>>> $ git fetch
>>>> Refusing to fetch, as it would update a checkedout branch
>>>> "git fetch -f" will force the update, but you will need to run "git
>>>> reset --hard HEAD" to update your checkout to match.
>>>
>>> That would redefine -f (currently means "allow non-fast-forward
>>> updates"), the flag that allows the checked out branch head to be
>>> updated is -u, --update-head-ok, and is for internal use only.
>>>
>>> And suggesting "reset --hard" seems wrong, that just kills any
>>> uncommitted changes.
>>
>> Ok, so the commands were wrong.  Not important.
>>
>> It was the approach that I was trying to suggest rather than the
>> actual commands.  The point I was trying to make was how, as a user,
>> I would be happy to git behave.
>
> Your approach explicitly included "mess up the index/worktree state",
> otherwise, "git fetch" would not have to tell the user that he has to do
> a "git reset --hard HEAD". I honestly can't believe that you would be
> happy with git messing up your work.
>
>> So, I try to run fetch, git says "ooh, now that would be dangerous -
>> you can force it happen by running "git foo", but you will then be
>> in situation X, which you can then recover from by running "git
>> bar", though you may need to run "git stash" to save any edits you
>> have made" or something similar.
>
> But why make "git fetch" with non-"obscure" refspecs dangerous to begin
> with? If we detach but keep some extra information, there's no need to
> make "git fetch" dangerous, _and_ we can still provide a command that
> just fetches the most recent version of the "checked out" remote
> tracking branch and checks that out. May it be another mode of operation
> for "git pull" or some "git up" command or whatever.

My entire argument was in the context of the mail that I orginally replied 
to, i.e. assuming that the decision to not detach had been taken.  If that 
is not the case, then everything I had said is irrelevant.

I wasn't arguing against detaching, but rather trying to say that _if_ we 
are not going to detach then I think it would better like this than that. 
I don't personally have any input on the detach or not, as I have been 
using git for too long to know if detaching is a problem for others.  I 
can tell from my bash prompt if I'm detached or on a branch - and that's 
fine for me.

-- 
Julian

  ---
Wedding is destiny, and hanging likewise.
 		-- John Heywood

^ permalink raw reply

* Re: [PATCH v3.1 3/5] Introduce new pretty formats %g[sdD] for reflog information
From: Jakub Narebski @ 2009-10-17 15:06 UTC (permalink / raw)
  To: Thomas Rast; +Cc: Jeff King, Junio C Hamano, Jef Driesen, Nanako Shiraishi, git
In-Reply-To: <e0ab6923eb4057bcbc8e97980dad5e4a37e53067.1255790816.git.trast@student.ethz.ch>

Thomas Rast <trast@student.ethz.ch> writes:

> Note that the --format="%h %gD: %gs" tests may not work in real
> repositories, as the --pretty formatter doesn't know to leave away the
> ": " on the last commit in an incomplete (because git-gc removed the
> old part) reflog.  This equivalence is nevertheless the main goal of
> this patch.

Perhaps just-introduced grouping syntax would help there?  You could
for example write

  --format="%h%[all() %gD: %gs%]"

which would expand nested group if _all_ placeholders within it have
expansion.  Perhaps %[ ... %], or %[? ... %], or %[* ... %] could be
shorter versions...

-- 
Jakub Narebski
Poland
ShadeHawk on #git

^ permalink raw reply

* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was
From: Julian Phillips @ 2009-10-17 15:15 UTC (permalink / raw)
  To: Nicolas Pitre
  Cc: Junio C Hamano, Björn Steinbrink, Daniel Barkalow,
	James Pickens, Jeff King, Jay Soffian, Git Mailing List
In-Reply-To: <alpine.LFD.2.00.0910161557500.20122@xanadu.home>

On Fri, 16 Oct 2009, Nicolas Pitre wrote:

> On Fri, 16 Oct 2009, Julian Phillips wrote:
>
>> My interest in this thread is solely that it might provide a mechanism to find
>> out which tag was checked out.  So, I'm just chucking in my $0.02 as a user.
>
> Try this:
>
> $ git checkout v1.5.5
> Note: moving to 'v1.5.5' which isn't a local branch
> If you want to create a new branch from this checkout, you may do so
> (now or later) by using -b with the checkout command again. Example:
>  git checkout -b <new_branch_name>
> HEAD is now at 1d2375d... GIT 1.5.5
>
> [look around, and then ...]
>
> $ git checkout HEAD~2
> Previous HEAD position was 1d2375d... GIT 1.5.5
> HEAD is now at f61cc48... git-svn: fix following renamed paths when tracking a single path
>
> [go out for lunch ... and forget what this was about.]
>
> $ git reflog -3
> f61cc48 HEAD@{0}: checkout: moving from 1d2375d... to HEAD~2
> 1d2375d HEAD@{1}: checkout: moving from master to v1.5.5
> c274db7 HEAD@{2}: pull : Fast forward
>
> Here I have all the information to see what I did, and from what state.
> I even know that I did a pull on the master branch before moving away
> from it.  The -3 limits the log to 3 entries.  With no limit you get it
> all in your default pager.
>
> So there is no need for another mechanism to find out what tag was
> actually checked out -- you have it all already.

What I want is a way for my build process to reliably know what branch or 
tag is currently being built.  "git symbolic-ref HEAD" will give me the 
branch name, but doesn't work for tags.  "git describe" will find _a_ tag, 
but I can't tell if it's actually the one checked out.

Using the reflog isn't something that had occured to me, but it seems a 
bit ... uncontrolled ... for a script.  I'd rather have a plumbing level 
command that just told me what I had actually checked out.  Though I may 
well look into using the reflog until such a command is available (or I 
find out there already is one).

-- 
Julian

  ---
I doubt, therefore I might be.

^ permalink raw reply

* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was
From: Julian Phillips @ 2009-10-17 15:32 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Björn Steinbrink, Daniel Barkalow, James Pickens, Jeff King,
	Nicolas Pitre, Jay Soffian, git
In-Reply-To: <7vk4yvt7kp.fsf@alter.siamese.dyndns.org>

On Fri, 16 Oct 2009, Junio C Hamano wrote:

> Julian Phillips <julian@quantumfyre.co.uk> writes:
>
>> On Fri, 16 Oct 2009, Junio C Hamano wrote:
>>
>>> Julian Phillips <julian@quantumfyre.co.uk> writes:
>>> ...
>>>> I don't care what git has to do, I'm talking about the user experience
>>>
>>> But Bj?rn is showing two commands the _user_ has to type, iow, the comment
>>> is about the user experience.
>>
>> Only Currently.  My point was that _if_ we wanted to support this sort
>> of thing, then we can make is simpler to do by providing a simple
>> command for the user.
>>
>> The point I wanted to make was that the decision on what to do should
>> be driven by the user's experience - not by the fact that it is easier
>> to implement something else.
>
> Sorry, but I do not see in what way what you said in the thread connects
> to the above three lines.  Are you talking about this one from you a few
> messages back?
>
>    How about:
>
>    $ git checkout origin/master
>    $ git fetch
>    Refusing to fetch, as it would update a checkedout branch
>    "git fetch -f" will force the update, but you will need to run "git
>    reset --hard HEAD" to update your checkout to match.
>
> I am not seeing "not the implementation ease but the user experience"
> drive in this suggestion.  If you are driving from the user experience
> point of view, I would have instead suggested:
>
>    How about:
>
>    $ git checkout origin/master
>    $ git fetch
>
>    and fetch happily updates the tracked branch, without affecting the
>    HEAD state (nor index nor the work tree, of course).

True.  I was saying that having git stop and explain things is better than 
making a mess for the user to clear up.  Having it just work would of 
course be even better.  Hoist by my own petard indead ...

>> My interest in this thread is solely that it might provide a mechanism
>> to find out which tag was checked out.
>
> Hmm, what is lacking in "git describe HEAD" for that?  I am not
> complaining that you might be asking for something that exists, but I _do_
> want to know if something that exists is not a satisfactory solution and
> if so how it can be improved.

What is lacking is the "checked out" part.  "git describe HEAD" will tell 
me _a_ tag that matches the currently checked out state.  However, it 
makes no guarantee that it was the one I checked out.  If I tag the code 
with "v1.0.0", and a colleague later tags it with "this_version_sucks", 
then when I check out and build the code for the customer the version it 
reports could well be "this_version_sucks" instead of "v1.0.0" ...

Nicolas Pitre suggested using the reflog, which does seem to include the 
information that I want, but I feel a little uneasy about accessing it via 
a script - how certain is it that the format of the message won't change? 
Is accessing the reflog the sort of thing people expect as part of the 
scripting interface?

-- 
Julian

  ---
Those who would repeat the past must control the teaching of history.

   -- Bene Gesserit Coda

^ permalink raw reply

* Re: Git gui and gitk documentation
From: Sitaram Chamarty @ 2009-10-17 16:15 UTC (permalink / raw)
  To: Michael J Gruber; +Cc: chris miles, git
In-Reply-To: <4AD870CD.1040709@drmicha.warpmail.net>

On Fri, Oct 16, 2009 at 6:40 PM, Michael J Gruber
<git@drmicha.warpmail.net> wrote:
> chris miles venit, vidit, dixit 15.10.2009 22:51:

>> I'm looking for documentation on gitk and the gui that is distributed with git.

> How about
>
> man gitk
> man git-gui

Here's my attempt to document the GUI parts of gitk (the command line options
you can get from 'man gitk' suggested above).  I haven't maintained it or
updated it in a while but what there is should still be correct.  It may even
be useful :-)

http://sitaramc.github.com/1-basic-usage/gitk.html

^ permalink raw reply

* [PATCH] describe: load refnames before calling describe()
From: René Scharfe @ 2009-10-17 16:30 UTC (permalink / raw)
  To: Git Mailing List; +Cc: Junio C Hamano, Shawn O. Pearce

Get rid of the static variable that was used to prevent loading all
the refnames multiple times by moving that code out of describe(),
simply making sure it is only run once that way.

Also change the error message that is shown in case no refnames are
found to not include a hash any more, as the error condition is not
specific to any particular revision.

Signed-off-by: Rene Scharfe <rene.scharfe@lsrfire.ath.cx>
---
 builtin-describe.c |   13 ++++---------
 1 files changed, 4 insertions(+), 9 deletions(-)

diff --git a/builtin-describe.c b/builtin-describe.c
index df67a73..2dcfd3d 100644
--- a/builtin-describe.c
+++ b/builtin-describe.c
@@ -180,7 +180,6 @@ static void describe(const char *arg, int last_one)
 	unsigned char sha1[20];
 	struct commit *cmit, *gave_up_on = NULL;
 	struct commit_list *list;
-	static int initialized = 0;
 	struct commit_name *n;
 	struct possible_tag all_matches[MAX_TAGS];
 	unsigned int match_cnt = 0, annotated_cnt = 0, cur_match;
@@ -192,14 +191,6 @@ static void describe(const char *arg, int last_one)
 	if (!cmit)
 		die("%s is not a valid '%s' object", arg, commit_type);
 
-	if (!initialized) {
-		initialized = 1;
-		for_each_ref(get_name, NULL);
-	}
-
-	if (!found_names)
-		die("cannot describe '%s'", sha1_to_hex(sha1));
-
 	n = cmit->util;
 	if (n) {
 		/*
@@ -359,6 +350,10 @@ int cmd_describe(int argc, const char **argv, const char *prefix)
 		return cmd_name_rev(i + argc, args, prefix);
 	}
 
+	for_each_ref(get_name, NULL);
+	if (!found_names)
+		die("No names found, cannot describe anything.");
+
 	if (argc == 0) {
 		describe("HEAD", 1);
 	} else {
-- 
1.6.5

^ permalink raw reply related

* Re: Introduction and Wikipedia and Git Blame
From: jamesmikedupont @ 2009-10-17 16:42 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Johannes Schindelin, git
In-Reply-To: <ee9cc730910162350p250b8afak767b0626bede34e4@mail.gmail.com>

I have done a workaround hack,
today I attempted to hack the blame code but I need to do more
research, it did not work.

But I did get a new version of the import script running and word
level blame going.

http://fmtyewtk.blogspot.com/2009/10/mediawiki-git-word-level-blaming-one.html

Next step is ready :

1. I have a single script that will pull a given article and check in
the revisions into git,
it is not perfect, but works.

http://bazaar.launchpad.net/~jamesmikedupont/+junk/wikiatransfer/revision/8
you run it like this,from inside a git repo :

perl GetRevisions.pl "Article_Name"

git blame Article_Name/Article.xml
git push origin master

The code that splits up the line is in Process File, this splits all
spaces into newlines.
that way we get a word level blame.

     if ($insidetext)
     {
  ## split all lines on the space
  s/(\ )/\\\n/g;


  print OUT  $_;
     }


The Article is here:
http://github.com/h4ck3rm1k3/KosovoWikipedia/blob/master/Wiki/2008_Kosovo_declaration_of_independence/article.xml


here are the blame results.
http://github.com/h4ck3rm1k3/KosovoWikipedia/blob/master/Wiki/2008_Kosovo_declaration_of_independence/wordblame.txt


Problem is that github does not like this amount of processor power
begin used and kills the process, you can do a local git blame.

Now we have the tool to easily create a repository from wikipedia, or
any other export enabled mediawiki.

mike


On Sat, Oct 17, 2009 at 8:50 AM, jamesmikedupont@googlemail.com
<jamesmikedupont@googlemail.com> wrote:
> Thank you very much for your input and advice,
> I have a lot of learn about this great tool.
> I am working on learning how the existing blame tool runs now.
> Will report back when I have some code.
> mike
>
> On Sat, Oct 17, 2009 at 1:25 AM, Junio C Hamano <gitster@pobox.com> wrote:
>> "jamesmikedupont@googlemail.com" <jamesmikedupont@googlemail.com> writes:
>>
>>> What do you think of my idea to create blames along a specific user
>>> defined byte positions ?
>>
>> Overly complicated and not enough time for _review_.  If you are blaming
>> one-byte (or one-char) per line, wouldn't it be enough to consider the
>> line number in the output as byte (or char) position when reconstituting
>> the original text?
>>
>

^ permalink raw reply

* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was
From: Björn Steinbrink @ 2009-10-17 17:04 UTC (permalink / raw)
  To: Julian Phillips
  Cc: Nicolas Pitre, Junio C Hamano, Daniel Barkalow, James Pickens,
	Jeff King, Jay Soffian, Git Mailing List
In-Reply-To: <alpine.LNX.2.00.0910171606180.6644@reaper.quantumfyre.co.uk>

On 2009.10.17 16:15:13 +0100, Julian Phillips wrote:
> On Fri, 16 Oct 2009, Nicolas Pitre wrote:
> 
> >On Fri, 16 Oct 2009, Julian Phillips wrote:
> >
> >>My interest in this thread is solely that it might provide a mechanism to find
> >>out which tag was checked out.  So, I'm just chucking in my $0.02 as a user.
> >
> >Try this:
> >
> >$ git checkout v1.5.5
> >Note: moving to 'v1.5.5' which isn't a local branch
> >If you want to create a new branch from this checkout, you may do so
> >(now or later) by using -b with the checkout command again. Example:
> > git checkout -b <new_branch_name>
> >HEAD is now at 1d2375d... GIT 1.5.5
> >
> >[look around, and then ...]
> >
> >$ git checkout HEAD~2
> >Previous HEAD position was 1d2375d... GIT 1.5.5
> >HEAD is now at f61cc48... git-svn: fix following renamed paths when tracking a single path
> >
> >[go out for lunch ... and forget what this was about.]
> >
> >$ git reflog -3
> >f61cc48 HEAD@{0}: checkout: moving from 1d2375d... to HEAD~2
> >1d2375d HEAD@{1}: checkout: moving from master to v1.5.5
> >c274db7 HEAD@{2}: pull : Fast forward
> >
> >Here I have all the information to see what I did, and from what state.
> >I even know that I did a pull on the master branch before moving away
> >from it.  The -3 limits the log to 3 entries.  With no limit you get it
> >all in your default pager.
> >
> >So there is no need for another mechanism to find out what tag was
> >actually checked out -- you have it all already.
> 
> What I want is a way for my build process to reliably know what
> branch or tag is currently being built.  "git symbolic-ref HEAD"
> will give me the branch name, but doesn't work for tags.  "git
> describe" will find _a_ tag, but I can't tell if it's actually the
> one checked out.

Do you have multiple (annotated) tags for the same commit? Otherwise, I
don't see why "git describe HEAD" should print the wrong one. If there's
a tag that can be resolved to the same commit that HEAD can be resolved,
then "git describe HEAD" must output that one. Otherwise, that'd be a
clear bug to me.

Björn

^ permalink raw reply

* Re: [PATCH v3 1/5] Refactor pretty_print_commit arguments into a struct
From: Junio C Hamano @ 2009-10-17 17:05 UTC (permalink / raw)
  To: Thomas Rast; +Cc: Jeff King, Jef Driesen, Nanako Shiraishi, git
In-Reply-To: <9d3d0f0a6126afc86689138adf58ac7a12c43858.1255701207.git.trast@student.ethz.ch>

Thomas Rast <trast@student.ethz.ch> writes:

> pretty_print_commit() has a bunch of rarely-used arguments, and
> introducing more of them requires yet another update of all the call
> sites.  Refactor most of them into a struct to make future extensions
> easier.
>
> The ones that stay "plain" arguments were chosen on the grounds that
> all callers put real arguments there, whereas some callers have 0/NULL
> for all arguments that were factored into the struct.
>
> We declare the struct 'const' to ensure none of the callers are bitten
> by the changed (no longer call-by-value) semantics.
>
> Signed-off-by: Thomas Rast <trast@student.ethz.ch>

Good idea, a slightly sloppy/careless execution.

The existing calls to format_commit_message() often take DATE_NORMAL to
its "enum date_mode dmode" argument, and you replaced it with a pointer to
a struct.  DATE_NORMAL happens to be "0" and the compiler does not catch
calls you forgot to convert in this patch.

^ permalink raw reply

* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD  was
From: James Pickens @ 2009-10-17 17:07 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Björn Steinbrink, Julian Phillips, Daniel Barkalow,
	Jeff King, Nicolas Pitre, Jay Soffian, git
In-Reply-To: <7vaazqcry5.fsf@alter.siamese.dyndns.org>

On Sat, Oct 17, 2009, Junio C Hamano <gitster@pobox.com> wrote:
> As I already said many times (here and elsewhere), "up" is an inferior and
> more dangerous model we would be better off not following if we can.

I agree that the "up" model is inferior, but I have to say, "up" is one of the
most common things my users ask about.  It is very common for users to have some
work in progress that they aren't ready to commit, and they want to get up to
date with the latest code from the central repository.  Most of the time, they
haven't modified any files that have also been modified upstream, so all they
need is "git pull".  But once in a while, they will have modified the same file,
and the pull will be rejected, and they don't know what to do.

These are not sophisticated users, so telling them to commit first, then pull,
and rebase later on to clean up the history (since the work they committed
wasn't finished) is no good.  They don't care to preserve their exact state and
just want to get up to date with the central repo.

If they ask me what to do, I tell them that if they're ready to commit, do so,
otherwise use 'git stash; git pull; git stash pop'.  To a typical user, this
looks like Git is inferior since it requires 3 commands to do what only takes 1
command in CVS/SVN.  One of my users didn't ask, and I later found out that he
had been doing this:

$ git pull ;# rejected due to modifications in file1
$ mv file1 file1.bak
$ git checkout HEAD file1
$ git pull ;# rejected due to modifications in file2
$ mv file2 file2.bak
$ git checkout HEAD file2
$ git pull ;# ok
<manually merge file1.bak with file1>
<manually merge file2.bak with file2>

So I think an "scm up" like command is not an unreasonable thing to want.  There
is a valid, and fairly common, use case.  There are ways to get the same result
in Git, but they're cumbersome compared to just typing "scm up".  It shouldn't
be the default, but I think a lot of users would appreciate having it.

James

^ permalink raw reply

* git submodules
From: Steven Noonan @ 2009-10-17 17:15 UTC (permalink / raw)
  To: Git Mailing List; +Cc: crawl-ref-discuss

One of the open source projects I work on (CC'd) recently moved to
git, but we're having some slight problems, and I believe that it's
the fault of git's UI in this case.

We're using git submodules for the contributing libraries. When I
commit changes to those contribs, it correctly shows in the parent
repository that those folders have different revisions than what's
currently committed. However, if someone pulls those changes, it
doesn't automatically update the contribs to match the committed
version. But doing a pull or merge _should_ update the working tree to
match the committed versions. It does with file data, so why not
update the submodules? Especially if the submodule revision matched
the committed version -before- the pull. Why are we forced into using
'git submodule update'?

- Steven

^ permalink raw reply

* Re: git submodules
From: Jakub Narebski @ 2009-10-17 17:27 UTC (permalink / raw)
  To: Steven Noonan; +Cc: Git Mailing List, crawl-ref-discuss
In-Reply-To: <f488382f0910171015j1a6d4d9fg690867154334c514@mail.gmail.com>

Steven Noonan <steven@uplinklabs.net> writes:

> We're using git submodules for the contributing libraries. When I
> commit changes to those contribs, it correctly shows in the parent
> repository that those folders have different revisions than what's
> currently committed. However, if someone pulls those changes, it
> doesn't automatically update the contribs to match the committed
> version. But doing a pull or merge _should_ update the working tree to
> match the committed versions. It does with file data, so why not
> update the submodules? Especially if the submodule revision matched
> the committed version -before- the pull. Why are we forced into using
> 'git submodule update'?

Because you might want not to use most current version of submodule,
so git-pull shouldn't update submodules by default.  And because
git-pull didn't learn --recursive option yet.

-- 
Jakub Narebski
Poland
ShadeHawk on #git

^ permalink raw reply

* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was
From: Julian Phillips @ 2009-10-17 17:35 UTC (permalink / raw)
  To: Björn Steinbrink
  Cc: Nicolas Pitre, Junio C Hamano, Daniel Barkalow, James Pickens,
	Jeff King, Jay Soffian, Git Mailing List
In-Reply-To: <20091017170421.GA10490@atjola.homenet>

On Sat, 17 Oct 2009, Bj?rn Steinbrink wrote:

> On 2009.10.17 16:15:13 +0100, Julian Phillips wrote:
>> On Fri, 16 Oct 2009, Nicolas Pitre wrote:
>>
>>> On Fri, 16 Oct 2009, Julian Phillips wrote:
>>>
>>>> My interest in this thread is solely that it might provide a mechanism to find
>>>> out which tag was checked out.  So, I'm just chucking in my $0.02 as a user.
>>>
>>> Try this:
>>>
>>> $ git checkout v1.5.5
>>> Note: moving to 'v1.5.5' which isn't a local branch
>>> If you want to create a new branch from this checkout, you may do so
>>> (now or later) by using -b with the checkout command again. Example:
>>> git checkout -b <new_branch_name>
>>> HEAD is now at 1d2375d... GIT 1.5.5
>>>
>>> [look around, and then ...]
>>>
>>> $ git checkout HEAD~2
>>> Previous HEAD position was 1d2375d... GIT 1.5.5
>>> HEAD is now at f61cc48... git-svn: fix following renamed paths when tracking a single path
>>>
>>> [go out for lunch ... and forget what this was about.]
>>>
>>> $ git reflog -3
>>> f61cc48 HEAD@{0}: checkout: moving from 1d2375d... to HEAD~2
>>> 1d2375d HEAD@{1}: checkout: moving from master to v1.5.5
>>> c274db7 HEAD@{2}: pull : Fast forward
>>>
>>> Here I have all the information to see what I did, and from what state.
>>> I even know that I did a pull on the master branch before moving away
>>> from it.  The -3 limits the log to 3 entries.  With no limit you get it
>>> all in your default pager.
>>>
>>> So there is no need for another mechanism to find out what tag was
>>> actually checked out -- you have it all already.
>>
>> What I want is a way for my build process to reliably know what
>> branch or tag is currently being built.  "git symbolic-ref HEAD"
>> will give me the branch name, but doesn't work for tags.  "git
>> describe" will find _a_ tag, but I can't tell if it's actually the
>> one checked out.
>
> Do you have multiple (annotated) tags for the same commit?

Potentially, yes.  Releasing isn't the only thing that requires keeping 
track of things.  It's even possible that the person creating the newer 
tag doesn't yet know that a release tag has been applied if the person 
who applied it hasn't yet pushed it back.

> Otherwise, I don't see why "git describe HEAD" should print the wrong 
> one. If there's a tag that can be resolved to the same commit that HEAD 
> can be resolved, then "git describe HEAD" must output that one. 
> Otherwise, that'd be a clear bug to me.

Oh, definately no bug.  git describe works exactly as expected, the 
problem is that the tag checked out isn't always the latest tag applied to 
that commit.

-- 
Julian

  ---
Jayne: Shee-nio high tech Alliance crap!"
 				--Episode #9, "Ariel"

^ permalink raw reply

* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was
From: Junio C Hamano @ 2009-10-17 17:42 UTC (permalink / raw)
  To: Björn Steinbrink
  Cc: Junio C Hamano, Christoph Bartoschek, git, Daniel Barkalow
In-Reply-To: <20091017081901.GB5474@atjola.homenet>

Björn Steinbrink <B.Steinbrink@gmx.de> writes:

> On 2009.10.17 00:43:31 -0700, Junio C Hamano wrote:
>> Christoph Bartoschek <bartoschek@gmx.de> writes:
>> > Daniel Barkalow wrote:
>> >
>> >> The upshot of the messages should be:
>> >> 
>> >>  $ git checkout origin/master
>> >>  Since you can't actually change "origin/master" yourself, you'll just
>> >>  be sightseeing unless you create a local branch to hold new local work.
>> >> 
>> >>  $ git branch
>> >>  * (not a local branch, but "origin/master")
>> >> 
>> >>  $ git commit
>> >>  You've been sightseeing "origin/master". The commit can't change that
>> >>  value, so your commit isn't held in any branch. If you want to create
>> >>  a branch to hold it, here's how.
>
> [...]
>
>> The second item in the Daniel's transcript above may be an improvement but
>> I think it is a wrong economy to record and show 'but "origin/master"'
>> (which cannot be correct forever and has to be invalidated once the user
>> starts committing or resetting) in the message.
>
> I don't think it's entirely wrong to record that information, git just
> has to know when to invalidate it, possibly requiring the user to really
> detach HEAD.

Isn't it redundant information to begin with?  See $gmane/130527

> git checkout origin/master
> git checkout origin/master~3
> git checkout HEAD^2~5
> git reset --hard HEAD~2
>
> Those commands are all about walking the ancestry of origin/master in
> some way. So it seems reasonable to assume that HEAD is still weakly
> bound to origin/master.

But as "walking" gets longer, the information will become less and less
relevant and at some point it becomes misleading.  I cannot explain why
"let's take pains to maintain and carefully invalidate an extra piece of
redundant information so that we can show information the end user
shouldn't be trained to trust to begin with because it is unreliable" is a
good idea.

^ permalink raw reply

* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was
From: Junio C Hamano @ 2009-10-17 17:43 UTC (permalink / raw)
  To: Julian Phillips
  Cc: Björn Steinbrink, Daniel Barkalow, James Pickens, Jeff King,
	Nicolas Pitre, Jay Soffian, git
In-Reply-To: <alpine.LNX.2.00.0910171617580.6644@reaper.quantumfyre.co.uk>

Julian Phillips <julian@quantumfyre.co.uk> writes:

>>> My interest in this thread is solely that it might provide a mechanism
>>> to find out which tag was checked out.
>>
>> Hmm, what is lacking in "git describe HEAD" for that?  I am not
>> complaining that you might be asking for something that exists, but I _do_
>> want to know if something that exists is not a satisfactory solution and
>> if so how it can be improved.
>
> What is lacking is the "checked out" part.  "git describe HEAD" will
> tell me _a_ tag that matches the currently checked out state.
> However, it makes no guarantee that it was the one I checked out.  If
> I tag the code with "v1.0.0", and a colleague later tags it with
> "this_version_sucks", then when I check out and build the code for the
> customer the version it reports could well be "this_version_sucks"
> instead of "v1.0.0" ...

I think I understand why you think showing what you gave to your last "git
checkout" (e.g. "checkout origin/master" or "checkout v1.0.0") and using
that as a build identification token is a good idea.  But "origin/master"
is a moving target---it depends on when you checked it out.  describe uses
tags and does not use branch heads for a good reason.

"v1.0.0" also is to a lessor degree, as you may have tagged v1.0.0 locally
and somebody else also has used the tag for a different version, but a tag
is far less likely to move due to social convention.  "describe --long"
would make sure this won't be an issue anyway, though.

^ permalink raw reply

* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was
From: Björn Steinbrink @ 2009-10-17 17:48 UTC (permalink / raw)
  To: Julian Phillips
  Cc: Nicolas Pitre, Junio C Hamano, Daniel Barkalow, James Pickens,
	Jeff King, Jay Soffian, Git Mailing List
In-Reply-To: <alpine.LNX.2.00.0910171829430.7906@reaper.quantumfyre.co.uk>

On 2009.10.17 18:35:38 +0100, Julian Phillips wrote:
> On Sat, 17 Oct 2009, Bj?rn Steinbrink wrote:
> >Do you have multiple (annotated) tags for the same commit?
> 
> Potentially, yes.  Releasing isn't the only thing that requires
> keeping track of things.  It's even possible that the person
> creating the newer tag doesn't yet know that a release tag has been
> applied if the person who applied it hasn't yet pushed it back.

OK, I'd consider that namespace pollution, as things like
"this-version-sucks" doesn't seem like it show go into public repos, but
anyway. If your release tags fix into a certain "unique" format, you
could use describe with --match, like:
git describe --match 'v[0-9]*'

> >Otherwise, I don't see why "git describe HEAD" should print the
> >wrong one. If there's a tag that can be resolved to the same
> >commit that HEAD can be resolved, then "git describe HEAD" must
> >output that one. Otherwise, that'd be a clear bug to me.
> 
> Oh, definately no bug.  git describe works exactly as expected, the
> problem is that the tag checked out isn't always the latest tag
> applied to that commit.

I misworded that one. Should be "If there's only tag that can be ...".
IOW it was meant for "only one tag per commit", which is what I assumed
to be the case.

Björn

^ permalink raw reply

* [PATCH] Add the --submodule option to the diff option family
From: Jens Lehmann @ 2009-10-17 18:46 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Johannes Schindelin, Git Mailing List

When you use the option --submodule=left-right-log you can see the submodule
summaries inlined in the diff, instead of not-quite-helpful SHA-1 pairs.

The format imitates what "git submodule summary" shows.

To do that, <path>/.git/objects/ is added to the alternate object
databases (if that directory exists).

This option was requested by Jens Lehmann at the GitTogether in Berlin.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Signed-off-by: Jens Lehmann <Jens.Lehmann@web.de>
---


In this patch i tried to address all the issues mentioned so far, please
let me know if anything is missing.


 Documentation/diff-options.txt |    7 +++
 Makefile                       |    2 +
 diff.c                         |   16 ++++++
 diff.h                         |    1 +
 submodule.c                    |  112 ++++++++++++++++++++++++++++++++++++++++
 submodule.h                    |    8 +++
 6 files changed, 146 insertions(+), 0 deletions(-)
 create mode 100644 submodule.c
 create mode 100644 submodule.h

diff --git a/Documentation/diff-options.txt b/Documentation/diff-options.txt
index 9276fae..99cb517 100644
--- a/Documentation/diff-options.txt
+++ b/Documentation/diff-options.txt
@@ -87,6 +87,13 @@ endif::git-format-patch[]
 	Show only names and status of changed files. See the description
 	of the `--diff-filter` option on what the status letters mean.

+--submodule[=<format>]::
+	Chose the output format for submodule differences. <format> can be one of
+	'short' and 'left-right-log'. 'short' is the default value for this
+	option and and shows pairs of commit names. 'left-right-log' lists the
+	commits in that commit range like the 'summary' option of
+	linkgit:git-submodule[1] does.
+
 --color::
 	Show colored diff.

diff --git a/Makefile b/Makefile
index c0eff64..2f61e17 100644
--- a/Makefile
+++ b/Makefile
@@ -453,6 +453,7 @@ LIB_H += sideband.h
 LIB_H += sigchain.h
 LIB_H += strbuf.h
 LIB_H += string-list.h
+LIB_H += submodule.h
 LIB_H += tag.h
 LIB_H += transport.h
 LIB_H += tree.h
@@ -551,6 +552,7 @@ LIB_OBJS += sideband.o
 LIB_OBJS += sigchain.o
 LIB_OBJS += strbuf.o
 LIB_OBJS += string-list.o
+LIB_OBJS += submodule.o
 LIB_OBJS += symlinks.o
 LIB_OBJS += tag.o
 LIB_OBJS += trace.o
diff --git a/diff.c b/diff.c
index c719ce2..8af1ae2 100644
--- a/diff.c
+++ b/diff.c
@@ -13,6 +13,7 @@
 #include "utf8.h"
 #include "userdiff.h"
 #include "sigchain.h"
+#include "submodule.h"

 #ifdef NO_FAST_WORKING_DIRECTORY
 #define FAST_WORKING_DIRECTORY 0
@@ -1557,6 +1558,17 @@ static void builtin_diff(const char *name_a,
 	const char *a_prefix, *b_prefix;
 	const char *textconv_one = NULL, *textconv_two = NULL;

+	if (DIFF_OPT_TST(o, SUBMODULE_LEFT_RIGHT_LOG) &&
+			(!one->mode || S_ISGITLINK(one->mode)) &&
+			(!two->mode || S_ISGITLINK(two->mode))) {
+		const char *del = diff_get_color_opt(o, DIFF_FILE_OLD);
+		const char *add = diff_get_color_opt(o, DIFF_FILE_NEW);
+		show_submodule_summary(o->file, one ? one->path : two->path,
+				one->sha1, two->sha1,
+				del, add, reset);
+		return;
+	}
+
 	if (DIFF_OPT_TST(o, ALLOW_TEXTCONV)) {
 		textconv_one = get_textconv(one);
 		textconv_two = get_textconv(two);
@@ -2771,6 +2783,10 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)
 		DIFF_OPT_CLR(options, ALLOW_TEXTCONV);
 	else if (!strcmp(arg, "--ignore-submodules"))
 		DIFF_OPT_SET(options, IGNORE_SUBMODULES);
+	else if (!prefixcmp(arg, "--submodule=")) {
+		if (!strcmp(arg + 12, "left-right-log"))
+			DIFF_OPT_SET(options, SUBMODULE_LEFT_RIGHT_LOG);
+	}

 	/* misc options */
 	else if (!strcmp(arg, "-z"))
diff --git a/diff.h b/diff.h
index a7e7ccb..8079f5b 100644
--- a/diff.h
+++ b/diff.h
@@ -67,6 +67,7 @@ typedef void (*diff_format_fn_t)(struct diff_queue_struct *q,
 #define DIFF_OPT_DIRSTAT_BY_FILE     (1 << 20)
 #define DIFF_OPT_ALLOW_TEXTCONV      (1 << 21)
 #define DIFF_OPT_DIFF_FROM_CONTENTS  (1 << 22)
+#define DIFF_OPT_SUBMODULE_LEFT_RIGHT_LOG (1 << 23)
 #define DIFF_OPT_TST(opts, flag)    ((opts)->flags & DIFF_OPT_##flag)
 #define DIFF_OPT_SET(opts, flag)    ((opts)->flags |= DIFF_OPT_##flag)
 #define DIFF_OPT_CLR(opts, flag)    ((opts)->flags &= ~DIFF_OPT_##flag)
diff --git a/submodule.c b/submodule.c
new file mode 100644
index 0000000..206386f
--- /dev/null
+++ b/submodule.c
@@ -0,0 +1,112 @@
+#include "cache.h"
+#include "submodule.h"
+#include "dir.h"
+#include "diff.h"
+#include "commit.h"
+#include "revision.h"
+
+int add_submodule_odb(const char *path)
+{
+	struct strbuf objects_directory = STRBUF_INIT;
+	struct alternate_object_database *alt_odb;
+
+	strbuf_addf(&objects_directory, "%s/.git/objects/", path);
+	if (!is_directory(objects_directory.buf))
+		return -1;
+
+	/* avoid adding it twice */
+	for (alt_odb = alt_odb_list; alt_odb; alt_odb = alt_odb->next)
+		if (alt_odb->name - alt_odb->base == objects_directory.len &&
+				!strncmp(alt_odb->base, objects_directory.buf,
+					objects_directory.len))
+			return 0;
+
+	alt_odb = xmalloc(objects_directory.len + 42 + sizeof(*alt_odb));
+	alt_odb->next = alt_odb_list;
+	strcpy(alt_odb->base, objects_directory.buf);
+	alt_odb->name = alt_odb->base + objects_directory.len;
+	alt_odb->name[2] = '/';
+	alt_odb->name[40] = '\0';
+	alt_odb->name[41] = '\0';
+	alt_odb_list = alt_odb;
+	prepare_alt_odb();
+	return 0;
+}
+
+void show_submodule_summary(FILE *f, const char *path,
+		unsigned char one[20], unsigned char two[20],
+		const char *del, const char *add, const char *reset)
+{
+	struct rev_info rev;
+	struct commit *commit, *left = left, *right;
+	struct commit_list *merge_bases, *list;
+	const char *message = NULL;
+	struct strbuf sb = STRBUF_INIT;
+	static const char *format = "  %m %s";
+	int fast_forward = 0, fast_backward = 0;
+
+	if (is_null_sha1(two))
+		message = "(submodule deleted)";
+	else if (add_submodule_odb(path))
+		message = "(not checked out)";
+	else if (is_null_sha1(one))
+		message = "(new submodule)";
+	else if (!(left = lookup_commit_reference(one)) ||
+		 !(right = lookup_commit_reference(two)))
+		message = "(commits not present)";
+
+	if (!message) {
+		init_revisions(&rev, NULL);
+		setup_revisions(0, NULL, &rev, NULL);
+		rev.left_right = 1;
+		rev.first_parent_only = 1;
+		left->object.flags |= SYMMETRIC_LEFT;
+		add_pending_object(&rev, &left->object, path);
+		add_pending_object(&rev, &right->object, path);
+		merge_bases = get_merge_bases(left, right, 1);
+		if (merge_bases) {
+			if (merge_bases->item == left)
+				fast_forward = 1;
+			else if (merge_bases->item == right)
+				fast_backward = 1;
+		}
+		for (list = merge_bases; list; list = list->next) {
+			list->item->object.flags |= UNINTERESTING;
+			add_pending_object(&rev, &list->item->object,
+				sha1_to_hex(list->item->object.sha1));
+		}
+		if (prepare_revision_walk(&rev))
+			message = "(revision walker failed)";
+	}
+
+	strbuf_addf(&sb, "Submodule %s %s..", path,
+			find_unique_abbrev(one, DEFAULT_ABBREV));
+	if (!fast_backward && !fast_forward)
+		strbuf_addch(&sb, '.');
+	strbuf_addf(&sb, "%s", find_unique_abbrev(two, DEFAULT_ABBREV));
+	if (message)
+		strbuf_addf(&sb, " %s\n", message);
+	else
+		strbuf_addf(&sb, "%s:\n", fast_backward ? " (rewind)" : "");
+	fwrite(sb.buf, sb.len, 1, f);
+
+	if (!message) {
+		while ((commit = get_revision(&rev))) {
+			strbuf_setlen(&sb, 0);
+			if (commit->object.flags & SYMMETRIC_LEFT) {
+				if (del)
+					strbuf_addstr(&sb, del);
+			}
+			else if (add)
+				strbuf_addstr(&sb, add);
+			format_commit_message(commit, format, &sb,
+					rev.date_mode);
+			if (reset)
+				strbuf_addstr(&sb, reset);
+			strbuf_addch(&sb, '\n');
+			fprintf(f, "%s", sb.buf);
+		}
+		clear_commit_marks(left, ~0);
+		clear_commit_marks(right, ~0);
+	}
+}
diff --git a/submodule.h b/submodule.h
new file mode 100644
index 0000000..4c0269d
--- /dev/null
+++ b/submodule.h
@@ -0,0 +1,8 @@
+#ifndef SUBMODULE_H
+#define SUBMODULE_H
+
+void show_submodule_summary(FILE *f, const char *path,
+		unsigned char one[20], unsigned char two[20],
+		const char *del, const char *add, const char *reset);
+
+#endif
-- 
1.6.5.3.g464e1.dirty

^ permalink raw reply related

* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was
From: Björn Steinbrink @ 2009-10-17 19:41 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Julian Phillips, Daniel Barkalow, James Pickens, Jeff King,
	Nicolas Pitre, Jay Soffian, git
In-Reply-To: <7vaazqcry5.fsf@alter.siamese.dyndns.org>

On 2009.10.17 02:04:02 -0700, Junio C Hamano wrote:
> The "save" part of the work-save-then-merge sequence should be made very
> visible to help people get used to the "not up, but work-save-then-merge"
> mental model.  I do not think it would help people in the long run to make
> the "save" step less visible by wrapping the sequence into an unreliable
> "up" script, especially because the script would sometimes work but other
> times *has to* force users to know that what is happening behind the scene
> is work-save-then-merge in order to resolve and recover from conflicts
> anyway.

Hm, which cases would that be? I basically see three cases:

 1) No uncommitted changes => No problem
 2) Uncommitted changes merge cleanly => No problem
 3) Uncommitted changes causes conflicts =>
   - User can resolve
   - User can start over (git update --retry)
   - User can give up (git update --abort)

Of course the user can clearly see that some state was saved (otherwise
you couldn't retry or abort), but I don't see how the user is "forced"
in any way, he just gets those two commands to work with (which
internally just wrap reset + stash apply, making things more
convenient).

I do see problems with a "stash around merge" thing ("stash" around
rebase seems easier, as that could just create a commit and reset later,
but I'm not exactly sure that such smartness is a good idea). As soon as
the merge has conflicts, you need to know that you have to unstash after
committing the merge, but what I have in mind is fast-forward only (or
possibly reset, when upstream was rewritten).  Primarily for users that
don't commit at all, but just look at things [*1*]. And also for the
semi-detached HEAD case, in which you may not commit and in which doing
a merge/rebase is therefore not an option, but git still knows what to
fetch/checkout by using the discussed extra info in HEAD, or by
examining the reflog.

> > OTOH, it might be easier to just tell the user to do the stash thing
> > himself. But I wonder how many users would really know how to get back
> > to the initial state then.
> 
> I agree with the first sentence, but I do not understand what "the initial
> state" you talk about here in the second sentence, sorry.

The state they were in before they did the "git stash" part.

*work on stuff not ready to be committed*
git pull # refused
git stash
git pull
git stash apply # Conflicts, user decides that he wants go back

At that point, you need the reflog (also handle fast-forwards), and do:

git reset --hard HEAD@{1}
git stash apply --index


Of course, a more correct way might be to use commit and rebase instead:

*work on stuff not ready to be committed*
git pull # refused
git add -A # Or whatever
git commit
git pull --rebase # conflicts, decide to abort
git rebase --abort
git reset HEAD^

But that still needs the extra "reset HEAD^" step to really get back to
the state with your uncommitted changes.

The problem with "svn up" is that there's no other way, and no way back.
Git has other ways, but no convenient one for non-committers and no
"obvious" way to go back, should you decide that you actually prefer not
to update after seeing the conflicts.

Anyway, this isn't _my_ itch and to some (large) degree I'm trying to
guess what someone else would expect. If at all, I'm more interested in
a command that figures out which remote tracking branch I checked out,
and that updates it, and updates my work tree/index as well. Uncommitted
changes aren't important to me there. So I'll simply give up on that
part.

Björn


[*1*] One could also say: Users that don't give a damn about git, but
just need it to get the code and maybe have some minor, uncommitted
modifications on top. I'm _not_ thinking about users that actually
commit and do stuff. Those should use merge/rebase/pull, and get a
complaint from "git update" if the update is not a fast-forward one,
telling them what to use instead.

^ permalink raw reply

* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was
From: Daniel Barkalow @ 2009-10-17 20:35 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Christoph Bartoschek, git
In-Reply-To: <7vr5t2h3do.fsf@alter.siamese.dyndns.org>

On Sat, 17 Oct 2009, Junio C Hamano wrote:

> Christoph Bartoschek <bartoschek@gmx.de> writes:
> 
> [jc: added Daniel back to cc list; please do not cull the cc list without
> good reason]
> 
> > Daniel Barkalow wrote:
> >
> >> The upshot of the messages should be:
> >> 
> >>  $ git checkout origin/master
> >>  Since you can't actually change "origin/master" yourself, you'll just
> >>  be sightseeing unless you create a local branch to hold new local work.
> >> 
> >>  $ git branch
> >>  * (not a local branch, but "origin/master")
> >> 
> >>  $ git commit
> >>  You've been sightseeing "origin/master". The commit can't change that
> >>  value, so your commit isn't held in any branch. If you want to create
> >>  a branch to hold it, here's how.
> > ...
> > But then I was not able to verify that the checkout indeed matched the 
> > 1.3.0-beta.  "git status" and "git branch" did not help here. 
> 
> This is not going to help you, but "git reflog" would have helped here.
> 
> The reason my suggesting "git reflog" now won't help you is because the
> word "reflog" does not connect the question "how did I get here" unless
> and until you know git already; in other words, it is not your fault that
> you got lost, but it is showing a wart in the UI.
> 
> If the question you were asking was "does the files I have in my work tree
> after issuing that scary checkout actually match origin/1.3.0-beta?", you
> could have asked that question in a more direct way, and the command to do
> so is "git diff origin/1.3.0-beta".  I do not think this would be asking
> the user to be doing something unreasonably unintuitive.
> 
> If the question you were asking was (and it was not, from the description
> of your experience, but you could be in that situation when you "return
> some weeks later") "how does the checked out history relate to 1.3.0-beta?",
> then there is a way to ask the question in a very direct way, and the
> command to do so is "git show-branch HEAD origin/1.3.0-beta" (or give the
> same argument to "gitk").
> 
> Although it is not _so_ unreasonable to expect "git status" to show the
> information, I suspect it would not be practical.  After all, whenever
> somebody is lost, everything is "status".  For a person who is lost and
> does not know where in the history he is, it might be reasonable to expect
> "status" to give the relationship between your HEAD and some branch/tag,
> while for another person who was hit by "git gui" complaining that he has
> too many loose objects, it might be reasonable for him to expect "status"
> to give the number of loose objects in the repository.  IOW, "status" is
> too broad a word and following the path to cram everything into "status"
> so that any new person who gets lost can get necessary infor from the
> command will unfortunately lead to insanity.
> 
> The second item in the Daniel's transcript above may be an improvement but
> I think it is a wrong economy to record and show 'but "origin/master"'
> (which cannot be correct forever and has to be invalidated once the user
> starts committing or resetting) in the message.

It's easy to invalidate it for reasons of the user going elsewhere: you 
invalidate it when you invalidate MERGE_HEAD (which, incidentally, 
locates a bug in my original patch: there's a third 
"unlink(git_path("MERGE_HEAD"));" I didn't think of, in builtin-merge.c).

I think the case of it going stale, mainly due to updating a ref it uses, 
is a matter of having whatever wants to describe HEAD check if the 
extended sha1 still expands to the same sha1.

I also think that it fits with the git world model to distinguish 
"lvalues" from "non-lvalues". An "lvalue" is something where you can make 
a commit and change the value while the expression stays the same; you can 
assign to it. If your current position is not an "lvalue" and you commit, 
your current position must become a new temporary "lvalue", diverging from 
the thing you can't change. But if you don't assign to it, there's no 
problem with having a non-lvalue be your current position.

> I am wondering if a similar effect to help new users can be had by 
> rewording the message to:
> 
>     $ git branch
>     * (not a local branch; see "git reflog" to learn how you got here)
> 
> The user can see how he got there even after doing something else after
> the checkout (see Nico's write-up in $gmane/130527).  The difference is
> between giving fish and teaching how to catch one himself.

The reflog hint is a good one in general; on the other hand, I think it 
would be generally helpful to have the information in a more 
machine-readable fashion, for a "git checkout (whatever I gave to reset or 
checkout before)".

Perhaps the right implementation is actually to have machine-readable 
descriptions in the HEAD reflog? That would actually lead to the 
interesting:

$ git checkout topic
$ git checkout origin/master
$ git checkout HEAD@{1}
$ git branch
* topic

Actually, we turn out to have a flaw in our reflog explanation: when 
rebase finishes, it doesn't log that it's back to a particular branch.

	-Daniel
*This .sig left intentionally blank*

^ permalink raw reply

* Re: [PATCH 0/3] Generalized "string function" syntax
From: René Scharfe @ 2009-10-17 21:04 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <1255681702-5215-1-git-send-email-gitster@pobox.com>

Junio C Hamano schrieb:
> I mentioned an idea to enhance the pretty=format language with a
> string function syntax that people can extend by adding new functions
> in one of the "What's cooking" messages earlier.  The general syntax
> would be like
> 
> %[function(args...)any string here%]
> 
> where "any string here" part would have the usual pretty=format
> strings. E.g.  git show -s --format='%{w(72,8,4)%s%+b%]' should give
> you a line wrapped commit log message if w(width,in1,in2) is such a
> function.

I pondered line wrapping with format strings briefly a long time ago, and
I always considered it to be more similar to a colour, i.e. a state that
one can change and that is applied to all following text until the next
state change.  (Except that it's always reset at the end of the format
string.)  The example above would then turn into '%w(72,8,4)%s%+b'.

Here's a patch to implement this behaviour.  It leaves the implementation
of the actual wrap function as an exercise to the reader, too. ;-)


 pretty.c |   66 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 66 insertions(+), 0 deletions(-)

diff --git a/pretty.c b/pretty.c
index f5983f8..33464f1 100644
--- a/pretty.c
+++ b/pretty.c
@@ -445,6 +445,7 @@ struct format_commit_context {
 	enum date_mode dmode;
 	unsigned commit_header_parsed:1;
 	unsigned commit_message_parsed:1;
+	size_t width, indent1, indent2;
 
 	/* These offsets are relative to the start of the commit message. */
 	struct chunk author;
@@ -458,6 +459,7 @@ struct format_commit_context {
 	struct chunk abbrev_commit_hash;
 	struct chunk abbrev_tree_hash;
 	struct chunk abbrev_parent_hashes;
+	size_t wrap_start;
 };
 
 static int add_again(struct strbuf *sb, struct chunk *chunk)
@@ -595,6 +597,44 @@ static void format_decoration(struct strbuf *sb, const struct commit *commit)
 		strbuf_addch(sb, ')');
 }
 
+static void strbuf_wrap(struct strbuf *sb, size_t pos, size_t len,
+			size_t width, size_t indent1, size_t indent2)
+{
+	struct strbuf tmp = STRBUF_INIT;
+
+	if (!len)
+		return;
+	if (pos)
+		strbuf_add(&tmp, sb->buf, pos);
+
+	/* XXX: all that's missing is the wrapping code itself.. */
+	strbuf_addf(&tmp, "w(%u,%u,%u)[\n",
+		    (unsigned)width, (unsigned)indent1, (unsigned)indent2);
+	strbuf_add(&tmp, sb->buf + pos, len);
+	strbuf_addstr(&tmp, "\n]");
+
+	if (pos + len < sb->len)
+		strbuf_add(&tmp, sb->buf + pos + len, sb->len - pos - len);
+	strbuf_swap(&tmp, sb);
+	strbuf_release(&tmp);
+}
+
+static void rewrap_message_tail(struct strbuf *sb,
+				struct format_commit_context *c,
+				size_t new_width, size_t new_indent1,
+				size_t new_indent2)
+{
+	if (c->width == new_width && c->indent1 == new_indent1 &&
+	    c->indent2 == new_indent2)
+		return;
+	strbuf_wrap(sb, c->wrap_start, sb->len - c->wrap_start, c->width,
+		    c->indent1, c->indent2);
+	c->wrap_start = sb->len;
+	c->width = new_width;
+	c->indent1 = new_indent1;
+	c->indent2 = new_indent2;
+}
+
 static size_t format_commit_item(struct strbuf *sb, const char *placeholder,
                                void *context)
 {
@@ -645,6 +685,30 @@ static size_t format_commit_item(struct strbuf *sb, const char *placeholder,
 			return 3;
 		} else
 			return 0;
+	case 'w':
+		if (placeholder[1] == '(') {
+			unsigned long width = 0, indent1 = 0, indent2 = 0;
+			char *next;
+			const char *start = placeholder + 2;
+			const char *end = strchr(start, ')');
+			if (!end)
+				return 0;
+			if (end > start) {
+				width = strtoul(start, &next, 10);
+				if (*next == ',') {
+					indent1 = strtoul(next + 1, &next, 10);
+					if (*next == ',') {
+						indent2 = strtoul(next + 1,
+								 &next, 10);
+					}
+				}
+				if (*next != ')')
+					return 0;
+			}
+			rewrap_message_tail(sb, c, width, indent1, indent2);
+			return end - placeholder + 1;
+		} else
+			return 0;
 	}
 
 	/* these depend on the commit */
@@ -748,7 +812,9 @@ void format_commit_message(const struct commit *commit,
 	memset(&context, 0, sizeof(context));
 	context.commit = commit;
 	context.dmode = dmode;
+	context.wrap_start = sb->len;
 	strbuf_expand(sb, format, format_commit_item, &context);
+	rewrap_message_tail(sb, &context, 0, 0, 0);
 }
 
 static void pp_header(enum cmit_fmt fmt,

^ permalink raw reply related

* Re: [PATCH 1/3] format_commit_message(): fix function signature
From: René Scharfe @ 2009-10-17 21:04 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <1255681702-5215-2-git-send-email-gitster@pobox.com>

Junio C Hamano schrieb:
> The format template string was declared as "const void *" for some unknown
> reason, even though it obviously is meant to be passed a string.  Make it
> "const char *".

Yes.  I seem to have introduced that type in commit 7b95089c, but I
can't see (even less remember) why.  Also note that commit message and
header file call the parameter "template", while it's called "format" in
commit.c (where the function used to live back then).  What was I thinking?

Thanks for cleaning up after me.

René

^ permalink raw reply

* Re: [PATCH] Proof-of-concept patch to remember what the detached HEAD was
From: Julian Phillips @ 2009-10-17 22:19 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Björn Steinbrink, Daniel Barkalow, James Pickens, Jeff King,
	Nicolas Pitre, Jay Soffian, git
In-Reply-To: <7vljj97w7u.fsf@alter.siamese.dyndns.org>

On Sat, 17 Oct 2009, Junio C Hamano wrote:

> Julian Phillips <julian@quantumfyre.co.uk> writes:
>
>>>> My interest in this thread is solely that it might provide a mechanism
>>>> to find out which tag was checked out.
>>>
>>> Hmm, what is lacking in "git describe HEAD" for that?  I am not
>>> complaining that you might be asking for something that exists, but I _do_
>>> want to know if something that exists is not a satisfactory solution and
>>> if so how it can be improved.
>>
>> What is lacking is the "checked out" part.  "git describe HEAD" will
>> tell me _a_ tag that matches the currently checked out state.
>> However, it makes no guarantee that it was the one I checked out.  If
>> I tag the code with "v1.0.0", and a colleague later tags it with
>> "this_version_sucks", then when I check out and build the code for the
>> customer the version it reports could well be "this_version_sucks"
>> instead of "v1.0.0" ...
>
> I think I understand why you think showing what you gave to your last "git
> checkout" (e.g. "checkout origin/master" or "checkout v1.0.0") and using
> that as a build identification token is a good idea.  But "origin/master"
> is a moving target---it depends on when you checked it out.  describe uses
> tags and does not use branch heads for a good reason.

For my purposes the branch that I built from is much more useful than the 
output from describe.  Releases are always made from tags, but for builds 
used in the lab it is generally much more useful to know which branch was 
built directly rather than being able to find the exact commit that was 
built.

> "v1.0.0" also is to a lessor degree, as you may have tagged v1.0.0 locally
> and somebody else also has used the tag for a different version, but a tag
> is far less likely to move due to social convention.  "describe --long"
> would make sure this won't be an issue anyway, though.

For any particular release only one person is given the job of making the 
release tag, so we don't have the problem of multiple instances of the 
same tag - but we do need to make sure that the version output is the 
correct tag.

-- 
Julian

  ---
Water, taken in moderation cannot hurt anybody.
 		-- Mark Twain

^ permalink raw reply

* Re: git submodules
From: Nanako Shiraishi @ 2009-10-17 22:30 UTC (permalink / raw)
  To: Jakub Narebski; +Cc: Git Mailing List, Steven Noonan, crawl-ref-discuss
In-Reply-To: <m3tyxydj8f.fsf@localhost.localdomain>

Quoting Jakub Narebski <jnareb@gmail.com>

> Steven Noonan <steven@uplinklabs.net> writes:
>
>> We're using git submodules for the contributing libraries. When I
>> commit changes to those contribs, it correctly shows in the parent
>> repository that those folders have different revisions than what's
>> currently committed. However, if someone pulls those changes, it
>> doesn't automatically update the contribs to match the committed
>> version. But doing a pull or merge _should_ update the working tree to
>> match the committed versions. It does with file data, so why not
>> update the submodules? Especially if the submodule revision matched
>> the committed version -before- the pull. Why are we forced into using
>> 'git submodule update'?
>
> Because you might want not to use most current version of submodule,
> so git-pull shouldn't update submodules by default.  And because
> git-pull didn't learn --recursive option yet.

I don't think your description is correct. Steven is talking about what the command should do by default. If you checked out the current superproject, by default you should get the submodule that matches. If you don't want the most current version, you can checkout an older submodule yourself.

You may want to follow this discussion:

  http://thread.gmane.org/gmane.comp.version-control.git/130155/focus=130330

After stating that he isn't against the idea to make it automatic, Junio describes what needs to be done for it to happen and what are the corner cases that needs to be treated with care.

-- 
Nanako Shiraishi
http://ivory.ap.teacup.com/nanako3/

^ 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