From 8860fd42fcf5a7853f7d7c2198793183320293ff Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Thu, 11 Jan 2007 11:47:48 +0100 Subject: Teach the revision walker to walk by reflogs with --walk-reflogs When called with "--walk-reflogs", as long as there are reflogs available, the walker will take this information into account, rather than the parent information in the commit object. Signed-off-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- reflog-walk.c | 235 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 235 insertions(+) create mode 100644 reflog-walk.c (limited to 'reflog-walk.c') diff --git a/reflog-walk.c b/reflog-walk.c new file mode 100644 index 0000000000..d4b49c7354 --- /dev/null +++ b/reflog-walk.c @@ -0,0 +1,235 @@ +#include "cache.h" +#include "commit.h" +#include "refs.h" +#include "diff.h" +#include "revision.h" +#include "path-list.h" + +struct complete_reflogs { + char *ref; + struct reflog_info { + unsigned char osha1[20], nsha1[20]; + char *email; + unsigned long timestamp; + int tz; + char *message; + } *items; + int nr, alloc; +}; + +static int read_one_reflog(unsigned char *osha1, unsigned char *nsha1, + const char *email, unsigned long timestamp, int tz, + const char *message, void *cb_data) +{ + struct complete_reflogs *array = cb_data; + struct reflog_info *item; + + if (array->nr >= array->alloc) { + array->alloc = alloc_nr(array->nr + 1); + array->items = xrealloc(array->items, array->alloc * + sizeof(struct reflog_info)); + } + item = array->items + array->nr; + memcpy(item->osha1, osha1, 20); + memcpy(item->nsha1, nsha1, 20); + item->email = xstrdup(email); + item->timestamp = timestamp; + item->tz = tz; + item->message = xstrdup(message); + array->nr++; + return 0; +} + +static struct complete_reflogs *read_complete_reflog(const char *ref) +{ + struct complete_reflogs *reflogs = + xcalloc(sizeof(struct complete_reflogs), 1); + reflogs->ref = xstrdup(ref); + for_each_reflog_ent(ref, read_one_reflog, reflogs); + if (reflogs->nr == 0) { + unsigned char sha1[20]; + const char *name = resolve_ref(ref, sha1, 1, NULL); + if (name) + for_each_reflog_ent(name, read_one_reflog, reflogs); + } + if (reflogs->nr == 0) { + int len = strlen(ref); + char *refname = xmalloc(len + 12); + sprintf(refname, "refs/%s", ref); + for_each_reflog_ent(refname, read_one_reflog, reflogs); + if (reflogs->nr == 0) { + sprintf(refname, "refs/heads/%s", ref); + for_each_reflog_ent(refname, read_one_reflog, reflogs); + } + free(refname); + } + return reflogs; +} + +static int get_reflog_recno_by_time(struct complete_reflogs *array, + unsigned long timestamp) +{ + int i; + for (i = array->nr - 1; i >= 0; i++) + if (timestamp >= array->items[i].timestamp) + return i; + return -1; +} + +struct commit_info_lifo { + struct commit_info { + struct commit *commit; + void *util; + } *items; + int nr, alloc; +}; + +static struct commit_info *get_commit_info(struct commit *commit, + struct commit_info_lifo *lifo, int pop) +{ + int i; + for (i = 0; i < lifo->nr; i++) + if (lifo->items[i].commit == commit) { + struct commit_info *result = &lifo->items[i]; + if (pop) { + if (i + 1 < lifo->nr) + memmove(lifo->items + i, + lifo->items + i + 1, + (lifo->nr - i) * + sizeof(struct commit_info)); + lifo->nr--; + } + return result; + } + return NULL; +} + +static void add_commit_info(struct commit *commit, void *util, + struct commit_info_lifo *lifo) +{ + struct commit_info *info; + if (lifo->nr >= lifo->alloc) { + lifo->alloc = alloc_nr(lifo->nr + 1); + lifo->items = xrealloc(lifo->items, + lifo->alloc * sizeof(struct commit_info)); + } + info = lifo->items + lifo->nr; + info->commit = commit; + info->util = util; + lifo->nr++; +} + +struct commit_reflog { + int flag, recno; + struct complete_reflogs *reflogs; +}; + +struct reflog_walk_info { + struct commit_info_lifo reflogs; + struct path_list complete_reflogs; + struct commit_reflog *last_commit_reflog; +}; + +void init_reflog_walk(struct reflog_walk_info** info) +{ + *info = xcalloc(sizeof(struct reflog_walk_info), 1); +} + +void add_reflog_for_walk(struct reflog_walk_info *info, + struct commit *commit, const char *name) +{ + unsigned long timestamp = 0; + int recno = -1; + struct path_list_item *item; + struct complete_reflogs *reflogs; + char *branch, *at = strchr(name, '@'); + struct commit_reflog *commit_reflog; + + branch = xstrdup(name); + if (at && at[1] == '{') { + char *ep; + branch[at - name] = '\0'; + recno = strtoul(at + 2, &ep, 10); + if (*ep != '}') { + recno = -1; + timestamp = approxidate(at + 2); + } + } else + recno = 0; + + item = path_list_lookup(branch, &info->complete_reflogs); + if (item) + reflogs = item->util; + else { + reflogs = read_complete_reflog(branch); + if (!reflogs || reflogs->nr == 0) + die("No reflogs found for '%s'", branch); + path_list_insert(branch, &info->complete_reflogs)->util + = reflogs; + } + + commit_reflog = xcalloc(sizeof(struct commit_reflog), 1); + if (recno < 0) { + commit_reflog->flag = 1; + commit_reflog->recno = get_reflog_recno_by_time(reflogs, timestamp); + if (commit_reflog->recno < 0) { + free(branch); + free(commit_reflog); + return; + } + } else + commit_reflog->recno = reflogs->nr - recno - 1; + commit_reflog->reflogs = reflogs; + + add_commit_info(commit, commit_reflog, &info->reflogs); +} + +void fake_reflog_parent(struct reflog_walk_info *info, struct commit *commit) +{ + struct commit_info *commit_info = + get_commit_info(commit, &info->reflogs, 0); + struct commit_reflog *commit_reflog; + struct reflog_info *reflog; + + info->last_commit_reflog = NULL; + if (!commit_info) + return; + + commit_reflog = commit_info->util; + if (commit_reflog->recno < 0) { + commit->parents = NULL; + return; + } + + reflog = &commit_reflog->reflogs->items[commit_reflog->recno]; + info->last_commit_reflog = commit_reflog; + commit_reflog->recno--; + commit_info->commit = (struct commit *)parse_object(reflog->osha1); + if (!commit_info->commit) { + commit->parents = NULL; + return; + } + + commit->parents = xcalloc(sizeof(struct commit_list), 1); + commit->parents->item = commit_info->commit; + commit->object.flags &= ~(ADDED | SEEN | SHOWN); +} + +void show_reflog_message(struct reflog_walk_info* info) +{ + if (info && info->last_commit_reflog) { + struct commit_reflog *commit_reflog = info->last_commit_reflog; + struct reflog_info *info; + + printf("Reflog: %s@{", commit_reflog->reflogs->ref); + info = &commit_reflog->reflogs->items[commit_reflog->recno + 1]; + if (commit_reflog->flag) + printf("%s", show_rfc2822_date(info->timestamp, + info->tz)); + else + printf("%d", commit_reflog->reflogs->nr + - 2 - commit_reflog->recno); + printf("} (%s)\nReflog message: %s", + info->email, info->message); + } +} -- cgit v1.2.3 From db055e65d20b20f8f32eb85ee1a2417d3b95c1c7 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Sat, 20 Jan 2007 03:28:19 +0100 Subject: --walk-reflogs: disallow uninteresting commits Do not allow uninteresting commits with --walk-reflogs, since it is not clear what should be shown in these cases: $ git log --walk-reflogs master..next $ git log --walk-reflogs ^master Signed-off-by: Johannes Schindelin --- reflog-walk.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'reflog-walk.c') diff --git a/reflog-walk.c b/reflog-walk.c index d4b49c7354..2d974116de 100644 --- a/reflog-walk.c +++ b/reflog-walk.c @@ -145,6 +145,9 @@ void add_reflog_for_walk(struct reflog_walk_info *info, char *branch, *at = strchr(name, '@'); struct commit_reflog *commit_reflog; + if (commit->object.flags & UNINTERESTING) + die ("Cannot walk reflogs for %s", name); + branch = xstrdup(name); if (at && at[1] == '{') { char *ep; -- cgit v1.2.3 From 53645a3a62977d5efd96ca9f3654985802212a9d Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sat, 20 Jan 2007 00:47:34 -0800 Subject: reflog-walk: build fixes Dependency on reflog-walk.h was missing in the Makefile, and reflog-walk.c did not even include it. Signed-off-by: Junio C Hamano --- reflog-walk.c | 1 + 1 file changed, 1 insertion(+) (limited to 'reflog-walk.c') diff --git a/reflog-walk.c b/reflog-walk.c index 2d974116de..989a7aee95 100644 --- a/reflog-walk.c +++ b/reflog-walk.c @@ -4,6 +4,7 @@ #include "diff.h" #include "revision.h" #include "path-list.h" +#include "reflog-walk.h" struct complete_reflogs { char *ref; -- cgit v1.2.3 From 4d12a471230625da73be464f5a20b7480a6b8ecb Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sat, 20 Jan 2007 00:51:41 -0800 Subject: Fix --walk-reflog with --pretty=oneline Now, "git log --abbrev-commit --pretty=o --walk-reflogs HEAD" is reasonably pleasant to use. Signed-off-by: Junio C Hamano --- reflog-walk.c | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) (limited to 'reflog-walk.c') diff --git a/reflog-walk.c b/reflog-walk.c index 989a7aee95..8ccbe97760 100644 --- a/reflog-walk.c +++ b/reflog-walk.c @@ -219,21 +219,32 @@ void fake_reflog_parent(struct reflog_walk_info *info, struct commit *commit) commit->object.flags &= ~(ADDED | SEEN | SHOWN); } -void show_reflog_message(struct reflog_walk_info* info) +void show_reflog_message(struct reflog_walk_info* info, int oneline) { if (info && info->last_commit_reflog) { struct commit_reflog *commit_reflog = info->last_commit_reflog; struct reflog_info *info; - printf("Reflog: %s@{", commit_reflog->reflogs->ref); - info = &commit_reflog->reflogs->items[commit_reflog->recno + 1]; - if (commit_reflog->flag) - printf("%s", show_rfc2822_date(info->timestamp, - info->tz)); - else - printf("%d", commit_reflog->reflogs->nr - - 2 - commit_reflog->recno); - printf("} (%s)\nReflog message: %s", - info->email, info->message); + info = &commit_reflog->reflogs->items[commit_reflog->recno+1]; + if (oneline) { + printf("%s@{", commit_reflog->reflogs->ref); + if (commit_reflog->flag) + printf("%s", show_date(info->timestamp, 0, 1)); + else + printf("%d", commit_reflog->reflogs->nr + - 2 - commit_reflog->recno); + printf("}: "); + } + else { + printf("Reflog: %s@{", commit_reflog->reflogs->ref); + if (commit_reflog->flag) + printf("%s", show_rfc2822_date(info->timestamp, + info->tz)); + else + printf("%d", commit_reflog->reflogs->nr + - 2 - commit_reflog->recno); + printf("} (%s)\nReflog message: %s", + info->email, info->message); + } } } -- cgit v1.2.3 From 40ab7c33cd6dfdf887ed15baee1325ee445eced7 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Sat, 20 Jan 2007 10:49:15 +0100 Subject: --walk-reflogs: actually find the right commit by date. Embarassing thinko. Signed-off-by: Johannes Schindelin --- reflog-walk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'reflog-walk.c') diff --git a/reflog-walk.c b/reflog-walk.c index 8ccbe97760..8e2cd2fcf6 100644 --- a/reflog-walk.c +++ b/reflog-walk.c @@ -71,7 +71,7 @@ static int get_reflog_recno_by_time(struct complete_reflogs *array, unsigned long timestamp) { int i; - for (i = array->nr - 1; i >= 0; i++) + for (i = array->nr - 1; i >= 0; i--) if (timestamp >= array->items[i].timestamp) return i; return -1; -- cgit v1.2.3 From 903b45fe1808f72e712a118bf115b9dc07d02420 Mon Sep 17 00:00:00 2001 From: Nicolas Pitre Date: Sat, 27 Jan 2007 22:40:36 -0500 Subject: git-log -g --pretty=oneline should display the reflog message In the context of reflog output the reflog message is more useful than the commit message's first line. When relevant the reflog message will contain that line anyway. Signed-off-by: Nicolas Pitre Signed-off-by: Junio C Hamano --- reflog-walk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'reflog-walk.c') diff --git a/reflog-walk.c b/reflog-walk.c index 8e2cd2fcf6..82621601d6 100644 --- a/reflog-walk.c +++ b/reflog-walk.c @@ -233,7 +233,7 @@ void show_reflog_message(struct reflog_walk_info* info, int oneline) else printf("%d", commit_reflog->reflogs->nr - 2 - commit_reflog->recno); - printf("}: "); + printf("}: %s", info->message); } else { printf("Reflog: %s@{", commit_reflog->reflogs->ref); -- cgit v1.2.3 From d271fd5311da7e475b02ef11507155fa912f0553 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Fri, 2 Feb 2007 00:07:24 +0100 Subject: Teach the '@{...}' notation to git-log -g Signed-off-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- reflog-walk.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'reflog-walk.c') diff --git a/reflog-walk.c b/reflog-walk.c index 82621601d6..653ec956f0 100644 --- a/reflog-walk.c +++ b/reflog-walk.c @@ -165,6 +165,14 @@ void add_reflog_for_walk(struct reflog_walk_info *info, if (item) reflogs = item->util; else { + if (*branch == '\0') { + unsigned char sha1[20]; + const char *head = resolve_ref("HEAD", sha1, 0, NULL); + if (!head) + die ("No current branch"); + free(branch); + branch = xstrdup(head); + } reflogs = read_complete_reflog(branch); if (!reflogs || reflogs->nr == 0) die("No reflogs found for '%s'", branch); -- cgit v1.2.3 From 4e244cbc5cc4c8a43982d4023bc0d9fb0b0c7d43 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Thu, 8 Feb 2007 21:58:33 +0100 Subject: log --reflog: honour --relative-date If you say "git log -g --relative-date", it is very likely that you want to see the reflog names in terms of a relative date. Signed-off-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- reflog-walk.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'reflog-walk.c') diff --git a/reflog-walk.c b/reflog-walk.c index 653ec956f0..afe1577d76 100644 --- a/reflog-walk.c +++ b/reflog-walk.c @@ -227,7 +227,8 @@ void fake_reflog_parent(struct reflog_walk_info *info, struct commit *commit) commit->object.flags &= ~(ADDED | SEEN | SHOWN); } -void show_reflog_message(struct reflog_walk_info* info, int oneline) +void show_reflog_message(struct reflog_walk_info* info, int oneline, + int relative_date) { if (info && info->last_commit_reflog) { struct commit_reflog *commit_reflog = info->last_commit_reflog; @@ -236,7 +237,7 @@ void show_reflog_message(struct reflog_walk_info* info, int oneline) info = &commit_reflog->reflogs->items[commit_reflog->recno+1]; if (oneline) { printf("%s@{", commit_reflog->reflogs->ref); - if (commit_reflog->flag) + if (commit_reflog->flag || relative_date) printf("%s", show_date(info->timestamp, 0, 1)); else printf("%d", commit_reflog->reflogs->nr @@ -245,9 +246,10 @@ void show_reflog_message(struct reflog_walk_info* info, int oneline) } else { printf("Reflog: %s@{", commit_reflog->reflogs->ref); - if (commit_reflog->flag) - printf("%s", show_rfc2822_date(info->timestamp, - info->tz)); + if (commit_reflog->flag || relative_date) + printf("%s", show_date(info->timestamp, + info->tz, + relative_date)); else printf("%d", commit_reflog->reflogs->nr - 2 - commit_reflog->recno); -- cgit v1.2.3 From eb3a48221fd4a0b38c31976028dbab7df51be6d4 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Fri, 9 Feb 2007 01:28:23 +0100 Subject: log --reflog: use dwim_log Since "git log origin/master" uses dwim_log() to match "refs/remotes/origin/master", it makes sense to do that for "git log --reflog", too. Signed-off-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- reflog-walk.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'reflog-walk.c') diff --git a/reflog-walk.c b/reflog-walk.c index afe1577d76..c983858259 100644 --- a/reflog-walk.c +++ b/reflog-walk.c @@ -174,6 +174,19 @@ void add_reflog_for_walk(struct reflog_walk_info *info, branch = xstrdup(head); } reflogs = read_complete_reflog(branch); + if (!reflogs || reflogs->nr == 0) { + unsigned char sha1[20]; + char *b; + if (dwim_log(branch, strlen(branch), sha1, &b) == 1) { + if (reflogs) { + free(reflogs->ref); + free(reflogs); + } + free(branch); + branch = b; + reflogs = read_complete_reflog(branch); + } + } if (!reflogs || reflogs->nr == 0) die("No reflogs found for '%s'", branch); path_list_insert(branch, &info->complete_reflogs)->util -- cgit v1.2.3 From 7b69b873faf3cfd592bb64a496c6982a540aa7ea Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Tue, 24 Jul 2007 00:39:50 +0100 Subject: git log -g: Complain, but do not fail, when no reflogs are there When asking "git log -g --all", clearly you want to see only those refs that do have reflogs, but you do not want it to fail, either. So instead of die()ing, complain about it, but move on to the other refs. Signed-off-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- reflog-walk.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'reflog-walk.c') diff --git a/reflog-walk.c b/reflog-walk.c index c983858259..ee1456b45a 100644 --- a/reflog-walk.c +++ b/reflog-walk.c @@ -136,7 +136,7 @@ void init_reflog_walk(struct reflog_walk_info** info) *info = xcalloc(sizeof(struct reflog_walk_info), 1); } -void add_reflog_for_walk(struct reflog_walk_info *info, +int add_reflog_for_walk(struct reflog_walk_info *info, struct commit *commit, const char *name) { unsigned long timestamp = 0; @@ -188,7 +188,7 @@ void add_reflog_for_walk(struct reflog_walk_info *info, } } if (!reflogs || reflogs->nr == 0) - die("No reflogs found for '%s'", branch); + return -1; path_list_insert(branch, &info->complete_reflogs)->util = reflogs; } @@ -200,13 +200,14 @@ void add_reflog_for_walk(struct reflog_walk_info *info, if (commit_reflog->recno < 0) { free(branch); free(commit_reflog); - return; + return -1; } } else commit_reflog->recno = reflogs->nr - recno - 1; commit_reflog->reflogs = reflogs; add_commit_info(commit, commit_reflog, &info->reflogs); + return 0; } void fake_reflog_parent(struct reflog_walk_info *info, struct commit *commit) -- cgit v1.2.3 From c455c87c5cd42bbbe586b31cea1143132f3a39e4 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Mon, 21 Jul 2008 19:03:49 +0100 Subject: Rename path_list to string_list The name path_list was correct for the first usage of that data structure, but it really is a general-purpose string list. $ perl -i -pe 's/path-list/string-list/g' $(git grep -l path-list) $ perl -i -pe 's/path_list/string_list/g' $(git grep -l path_list) $ git mv path-list.h string-list.h $ git mv path-list.c string-list.c $ perl -i -pe 's/has_path/has_string/g' $(git grep -l has_path) $ perl -i -pe 's/path/string/g' string-list.[ch] $ git mv Documentation/technical/api-path-list.txt \ Documentation/technical/api-string-list.txt $ perl -i -pe 's/strdup_paths/strdup_strings/g' $(git grep -l strdup_paths) ... and then fix all users of string-list to access the member "string" instead of "path". Documentation/technical/api-string-list.txt needed some rewrapping, too. Signed-off-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- reflog-walk.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'reflog-walk.c') diff --git a/reflog-walk.c b/reflog-walk.c index ee1456b45a..f751fdc8d8 100644 --- a/reflog-walk.c +++ b/reflog-walk.c @@ -3,7 +3,7 @@ #include "refs.h" #include "diff.h" #include "revision.h" -#include "path-list.h" +#include "string-list.h" #include "reflog-walk.h" struct complete_reflogs { @@ -127,7 +127,7 @@ struct commit_reflog { struct reflog_walk_info { struct commit_info_lifo reflogs; - struct path_list complete_reflogs; + struct string_list complete_reflogs; struct commit_reflog *last_commit_reflog; }; @@ -141,7 +141,7 @@ int add_reflog_for_walk(struct reflog_walk_info *info, { unsigned long timestamp = 0; int recno = -1; - struct path_list_item *item; + struct string_list_item *item; struct complete_reflogs *reflogs; char *branch, *at = strchr(name, '@'); struct commit_reflog *commit_reflog; @@ -161,7 +161,7 @@ int add_reflog_for_walk(struct reflog_walk_info *info, } else recno = 0; - item = path_list_lookup(branch, &info->complete_reflogs); + item = string_list_lookup(branch, &info->complete_reflogs); if (item) reflogs = item->util; else { @@ -189,7 +189,7 @@ int add_reflog_for_walk(struct reflog_walk_info *info, } if (!reflogs || reflogs->nr == 0) return -1; - path_list_insert(branch, &info->complete_reflogs)->util + string_list_insert(branch, &info->complete_reflogs)->util = reflogs; } -- cgit v1.2.3 From cd4371208a0e9f882f6fd4b4dd28d6911848ec79 Mon Sep 17 00:00:00 2001 From: Jeff King Date: Fri, 20 Mar 2009 02:00:43 -0400 Subject: make oneline reflog dates more consistent with multiline format The multiline reflog format (e.g., as shown by "git log -g") will show HEAD@{} rather than HEAD@{} in two situations: 1. If the user gave branch@{} syntax to specify the reflog 2. If the user gave a --date= specifier It uses the "normal" date format in case 1, and the user-specified format in case 2. The oneline reflog format (e.g., "git reflog show" or "git log -g --oneline") will show the date in the same two circumstances. However, it _always_ shows the date as a relative date, and it always ignores the timezone. In case 2, it seems ridiculous to trigger the date but use a format totally different from what the user requested. For case 1, it is arguable that the user might want to see the relative date by default; however, the multiline version shows the normal format. This patch does three things: - refactors the "relative_date" parameter to show_reflog_message to be an actual date_mode enum, since this is how it is used (it is passed to show_date) - uses the passed date_mode parameter in the oneline format (making it consistent with the multiline format) - does not ignore the timezone parameter in oneline mode Signed-off-by: Jeff King Signed-off-by: Junio C Hamano --- reflog-walk.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'reflog-walk.c') diff --git a/reflog-walk.c b/reflog-walk.c index f751fdc8d8..fd065f4e1a 100644 --- a/reflog-walk.c +++ b/reflog-walk.c @@ -242,7 +242,7 @@ void fake_reflog_parent(struct reflog_walk_info *info, struct commit *commit) } void show_reflog_message(struct reflog_walk_info* info, int oneline, - int relative_date) + enum date_mode dmode) { if (info && info->last_commit_reflog) { struct commit_reflog *commit_reflog = info->last_commit_reflog; @@ -251,8 +251,10 @@ void show_reflog_message(struct reflog_walk_info* info, int oneline, info = &commit_reflog->reflogs->items[commit_reflog->recno+1]; if (oneline) { printf("%s@{", commit_reflog->reflogs->ref); - if (commit_reflog->flag || relative_date) - printf("%s", show_date(info->timestamp, 0, 1)); + if (commit_reflog->flag || dmode) + printf("%s", show_date(info->timestamp, + info->tz, + dmode)); else printf("%d", commit_reflog->reflogs->nr - 2 - commit_reflog->recno); @@ -260,10 +262,10 @@ void show_reflog_message(struct reflog_walk_info* info, int oneline, } else { printf("Reflog: %s@{", commit_reflog->reflogs->ref); - if (commit_reflog->flag || relative_date) + if (commit_reflog->flag || dmode) printf("%s", show_date(info->timestamp, info->tz, - relative_date)); + dmode)); else printf("%d", commit_reflog->reflogs->nr - 2 - commit_reflog->recno); -- cgit v1.2.3 From 4b25d091ba53c758fae0096b8c0662371857b9d9 Mon Sep 17 00:00:00 2001 From: Felipe Contreras Date: Fri, 1 May 2009 12:06:36 +0300 Subject: Fix a bunch of pointer declarations (codestyle) Essentially; s/type* /type */ as per the coding guidelines. Signed-off-by: Felipe Contreras Signed-off-by: Junio C Hamano --- reflog-walk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'reflog-walk.c') diff --git a/reflog-walk.c b/reflog-walk.c index fd065f4e1a..5623ea6b48 100644 --- a/reflog-walk.c +++ b/reflog-walk.c @@ -241,7 +241,7 @@ void fake_reflog_parent(struct reflog_walk_info *info, struct commit *commit) commit->object.flags &= ~(ADDED | SEEN | SHOWN); } -void show_reflog_message(struct reflog_walk_info* info, int oneline, +void show_reflog_message(struct reflog_walk_info *info, int oneline, enum date_mode dmode) { if (info && info->last_commit_reflog) { -- cgit v1.2.3 From 72b103fec7af967d295410c2fd3899bc6e8386e2 Mon Sep 17 00:00:00 2001 From: Thomas Rast Date: Mon, 19 Oct 2009 17:48:09 +0200 Subject: reflog-walk: refactor the branch@{num} formatting We'll use the same output in an upcoming commit, so refactor its formatting (which was duplicated anyway) into a separate function. Signed-off-by: Thomas Rast Signed-off-by: Junio C Hamano --- reflog-walk.c | 54 ++++++++++++++++++++++++++++++++---------------------- 1 file changed, 32 insertions(+), 22 deletions(-) (limited to 'reflog-walk.c') diff --git a/reflog-walk.c b/reflog-walk.c index 5623ea6b48..596bafebdd 100644 --- a/reflog-walk.c +++ b/reflog-walk.c @@ -241,36 +241,46 @@ void fake_reflog_parent(struct reflog_walk_info *info, struct commit *commit) commit->object.flags &= ~(ADDED | SEEN | SHOWN); } -void show_reflog_message(struct reflog_walk_info *info, int oneline, +void get_reflog_selector(struct strbuf *sb, + struct reflog_walk_info *reflog_info, + enum date_mode dmode) +{ + struct commit_reflog *commit_reflog = reflog_info->last_commit_reflog; + struct reflog_info *info; + + if (!commit_reflog) + return; + + strbuf_addf(sb, "%s@{", commit_reflog->reflogs->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)); + } else { + strbuf_addf(sb, "%d", commit_reflog->reflogs->nr + - 2 - commit_reflog->recno); + } + + strbuf_addch(sb, '}'); +} + +void show_reflog_message(struct reflog_walk_info *reflog_info, int oneline, enum date_mode dmode) { - if (info && info->last_commit_reflog) { - struct commit_reflog *commit_reflog = info->last_commit_reflog; + if (reflog_info && reflog_info->last_commit_reflog) { + struct commit_reflog *commit_reflog = reflog_info->last_commit_reflog; struct reflog_info *info; + struct strbuf selector = STRBUF_INIT; info = &commit_reflog->reflogs->items[commit_reflog->recno+1]; + get_reflog_selector(&selector, reflog_info, dmode); if (oneline) { - printf("%s@{", commit_reflog->reflogs->ref); - if (commit_reflog->flag || dmode) - printf("%s", show_date(info->timestamp, - info->tz, - dmode)); - else - printf("%d", commit_reflog->reflogs->nr - - 2 - commit_reflog->recno); - printf("}: %s", info->message); + printf("%s: %s", selector.buf, info->message); } else { - printf("Reflog: %s@{", commit_reflog->reflogs->ref); - if (commit_reflog->flag || dmode) - printf("%s", show_date(info->timestamp, - info->tz, - dmode)); - else - printf("%d", commit_reflog->reflogs->nr - - 2 - commit_reflog->recno); - printf("} (%s)\nReflog message: %s", - info->email, info->message); + printf("Reflog: %s (%s)\nReflog message: %s", + selector.buf, info->email, info->message); } + + strbuf_release(&selector); } } -- cgit v1.2.3 From 8f8f5476cd6542387d435c242752404cf144005f Mon Sep 17 00:00:00 2001 From: Thomas Rast Date: Mon, 19 Oct 2009 17:48:10 +0200 Subject: Introduce new pretty formats %g[sdD] for reflog information 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 Signed-off-by: Junio C Hamano --- reflog-walk.c | 35 ++++++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) (limited to 'reflog-walk.c') diff --git a/reflog-walk.c b/reflog-walk.c index 596bafebdd..caba4f743f 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); } -- cgit v1.2.3 From 78a395d371ec9fd14297178ec98b8b1042a64fb6 Mon Sep 17 00:00:00 2001 From: Julian Phillips Date: Sat, 26 Jun 2010 00:41:35 +0100 Subject: string_list: Fix argument order for string_list_insert Update the definition and callers of string_list_insert to use the string_list as the first argument. This helps make the string_list API easier to use by being more consistent. Signed-off-by: Julian Phillips Signed-off-by: Junio C Hamano --- reflog-walk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'reflog-walk.c') diff --git a/reflog-walk.c b/reflog-walk.c index caba4f743f..f125f37461 100644 --- a/reflog-walk.c +++ b/reflog-walk.c @@ -190,7 +190,7 @@ int add_reflog_for_walk(struct reflog_walk_info *info, } if (!reflogs || reflogs->nr == 0) return -1; - string_list_insert(branch, &info->complete_reflogs)->util + string_list_insert(&info->complete_reflogs, branch)->util = reflogs; } -- cgit v1.2.3 From e8c8b7139c87c3e3017d3bff07f91c4349850d58 Mon Sep 17 00:00:00 2001 From: Julian Phillips Date: Sat, 26 Jun 2010 00:41:37 +0100 Subject: string_list: Fix argument order for string_list_lookup Update the definition and callers of string_list_lookup to use the string_list as the first argument. This helps make the string_list API easier to use by being more consistent. Signed-off-by: Julian Phillips Signed-off-by: Junio C Hamano --- reflog-walk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'reflog-walk.c') diff --git a/reflog-walk.c b/reflog-walk.c index f125f37461..4879615cad 100644 --- a/reflog-walk.c +++ b/reflog-walk.c @@ -162,7 +162,7 @@ int add_reflog_for_walk(struct reflog_walk_info *info, } else recno = 0; - item = string_list_lookup(branch, &info->complete_reflogs); + item = string_list_lookup(&info->complete_reflogs, branch); if (item) reflogs = item->util; else { -- cgit v1.2.3 From ffa1eeaeea38f6d667e304f9b12c890b7c14d088 Mon Sep 17 00:00:00 2001 From: Jeff King Date: Sun, 21 Nov 2010 23:42:53 -0500 Subject: reflogs: clear flags properly in corner case The reflog-walking mechanism is based on the regular revision traversal. We just rewrite the parents of each commit in fake_reflog_parent to point to the commit in the next reflog entry instead of the real parents. However, the regular revision traversal tries not to show the same commit twice, and so sets the SHOWN flag on each commit it shows. In a reflog, however, we may want to see the same commit more than once if it appears in the reflog multiple times (which easily happens, for example, if you do a reset to a prior state). The fake_reflog_parent function takes care of this by clearing flags, including SHOWN. Unfortunately, it does so at the very end of the function, and it is possible to return early from the function if there is no fake parent to set up (e.g., because we are at the very first reflog entry on the branch). In such a case the flag is not cleared, and the entry is skipped by the revision traversal machinery as already shown. You can see this by walking the log of a ref which is set to its very first commit more than once (the test below shows such a situation). In this case the reflog walk will fail to show the entry for the initial creation of the ref. We don't want to simply move the flag-clearing to the top of the function; we want to make sure flags set during the fake-parent installation are also cleared. Instead, let's hoist the flag-clearing out of the fake_reflog_parent function entirely. It's not really about fake parents anyway, and the only caller is the get_revision machinery. Reported-by: Martin von Zweigbergk Signed-off-by: Jeff King Acked-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- reflog-walk.c | 1 - 1 file changed, 1 deletion(-) (limited to 'reflog-walk.c') diff --git a/reflog-walk.c b/reflog-walk.c index caba4f743f..0cf2f7dbad 100644 --- a/reflog-walk.c +++ b/reflog-walk.c @@ -239,7 +239,6 @@ void fake_reflog_parent(struct reflog_walk_info *info, struct commit *commit) commit->parents = xcalloc(sizeof(struct commit_list), 1); commit->parents->item = commit_info->commit; - commit->object.flags &= ~(ADDED | SEEN | SHOWN); } void get_reflog_selector(struct strbuf *sb, -- cgit v1.2.3