{"thread":{"id":"8975","subject":"[PATCH 0/4] Make --decorate more useful","startedAt":"2007-07-11T01:28:25Z","lastAt":"2007-07-21T22:26:11Z","messageCount":11,"participants":["Johannes Schindelin","Theodore Tso","Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":4},"messages":[{"id":"46995","messageId":"Pine.LNX.4.64.0707110220340.4047@racer.site","threadId":"8975","inReplyTo":null,"subject":"[PATCH 0/4] Make --decorate more useful","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2007-07-11T01:28:25Z","receivedAt":"2007-07-11T01:28:25Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"\nThis series is meant to (partially) replace the patch I posted in\n\nhttp://article.gmane.org/gmane.comp.version-control.git/24383\n\nOften it is useful to find out what feature came in when, to quickly\nfind out if some version of the software is sufficient, or if the\nother person has to upgrade.\n\nWith this series applied, you can say\n\n\tgit log --decorate=tag -S<some keyword> <file>\n\nto find out what that version was, indeed you even get a human readable\nname for that commit, in addition to the commit name.\n\nJohannes Schindelin (4):\n      Move add_name_decoration() and add_ref_decoration() to commit.[ch]\n      Move the --decorate option from builtin-log.c to revision.c.\n      --decorate now decorates ancestors, too\n      --decorate: prefer shorter names\n\n Documentation/git-log.txt        |    3 -\n Documentation/pretty-options.txt |   15 ++++++\n builtin-log.c                    |   39 +-------------\n commit.c                         |  104 ++++++++++++++++++++++++++++++++++++++\n commit.h                         |    5 ++\n log-tree.c                       |    4 ++\n revision.c                       |   47 +++++++++++++++++\n revision.h                       |    9 +++\n 8 files changed, 186 insertions(+), 40 deletions(-)\n"},{"id":"46996","messageId":"Pine.LNX.4.64.0707110228470.4047@racer.site","threadId":"8975","inReplyTo":"Pine.LNX.4.64.0707110220340.4047@racer.site","subject":"[PATCH 1/4] Move add_name_decoration() and add_ref_decoration() to commit.[ch]","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2007-07-11T01:28:58Z","receivedAt":"2007-07-11T01:28:58Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"\nThe functions add_{name,ref}_decoration() should really be in\ncommit.[ch], since the struct they are modifying is there, too.\n\nSigned-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n---\n builtin-log.c |   25 -------------------------\n commit.c      |   25 +++++++++++++++++++++++++\n commit.h      |    3 +++\n 3 files changed, 28 insertions(+), 25 deletions(-)\n\ndiff --git a/builtin-log.c b/builtin-log.c\nindex 13bae31..c14eea5 100644\n--- a/builtin-log.c\n+++ b/builtin-log.c\n@@ -21,31 +21,6 @@ static const char *fmt_patch_subject_prefix = \"PATCH\";\n /* this is in builtin-diff.c */\n void add_head(struct rev_info *revs);\n \n-static void add_name_decoration(const char *prefix, const char *name, struct object *obj)\n-{\n-\tint plen = strlen(prefix);\n-\tint nlen = strlen(name);\n-\tstruct name_decoration *res = xmalloc(sizeof(struct name_decoration) + plen + nlen);\n-\tmemcpy(res->name, prefix, plen);\n-\tmemcpy(res->name + plen, name, nlen + 1);\n-\tres->next = add_decoration(&name_decoration, obj, res);\n-}\n-\n-static int add_ref_decoration(const char *refname, const unsigned char *sha1, int flags, void *cb_data)\n-{\n-\tstruct object *obj = parse_object(sha1);\n-\tif (!obj)\n-\t\treturn 0;\n-\tadd_name_decoration(\"\", refname, obj);\n-\twhile (obj->type == OBJ_TAG) {\n-\t\tobj = ((struct tag *)obj)->tagged;\n-\t\tif (!obj)\n-\t\t\tbreak;\n-\t\tadd_name_decoration(\"tag: \", refname, obj);\n-\t}\n-\treturn 0;\n-}\n-\n static void cmd_log_init(int argc, const char **argv, const char *prefix,\n \t\t      struct rev_info *rev)\n {\ndiff --git a/commit.c b/commit.c\nindex 03436b1..c0748ed 100644\n--- a/commit.c\n+++ b/commit.c\n@@ -1553,3 +1553,28 @@ int in_merge_bases(struct commit *commit, struct commit **reference, int num)\n \tfree_commit_list(bases);\n \treturn ret;\n }\n+\n+void add_name_decoration(const char *prefix, const char *name, struct object *obj)\n+{\n+\tint plen = strlen(prefix);\n+\tint nlen = strlen(name);\n+\tstruct name_decoration *res = xmalloc(sizeof(struct name_decoration) + plen + nlen);\n+\tmemcpy(res->name, prefix, plen);\n+\tmemcpy(res->name + plen, name, nlen + 1);\n+\tres->next = add_decoration(&name_decoration, obj, res);\n+}\n+\n+int add_ref_decoration(const char *refname, const unsigned char *sha1, int flags, void *cb_data)\n+{\n+\tstruct object *obj = parse_object(sha1);\n+\tif (!obj)\n+\t\treturn 0;\n+\tadd_name_decoration(\"\", refname, obj);\n+\twhile (obj->type == OBJ_TAG) {\n+\t\tobj = ((struct tag *)obj)->tagged;\n+\t\tif (!obj)\n+\t\t\tbreak;\n+\t\tadd_name_decoration(\"tag: \", refname, obj);\n+\t}\n+\treturn 0;\n+}\ndiff --git a/commit.h b/commit.h\nindex 467872e..787ae5e 100644\n--- a/commit.h\n+++ b/commit.h\n@@ -29,6 +29,9 @@ struct name_decoration {\n \tchar name[1];\n };\n \n+void add_name_decoration(const char *prefix, const char *name, struct object *obj);\n+int add_ref_decoration(const char *refname, const unsigned char *sha1, int flags, void *cb_data);\n+\n struct commit *lookup_commit(const unsigned char *sha1);\n struct commit *lookup_commit_reference(const unsigned char *sha1);\n struct commit *lookup_commit_reference_gently(const unsigned char *sha1,\n-- \n1.5.3.rc0.2783.gf3f7\n"},{"id":"46997","messageId":"Pine.LNX.4.64.0707110229120.4047@racer.site","threadId":"8975","inReplyTo":"Pine.LNX.4.64.0707110220340.4047@racer.site","subject":"[PATCH 2/4] Move the --decorate option from builtin-log.c to revision.c.","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2007-07-11T01:29:19Z","receivedAt":"2007-07-11T01:29:19Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"\nIt is more logical to have the --decorate option in revision, like\nmany others affecting the way how commits are shown.\n\nSigned-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n---\n Documentation/git-log.txt        |    3 ---\n Documentation/pretty-options.txt |    4 ++++\n builtin-log.c                    |   14 ++------------\n revision.c                       |    4 ++++\n 4 files changed, 10 insertions(+), 15 deletions(-)\n\ndiff --git a/Documentation/git-log.txt b/Documentation/git-log.txt\nindex 7adcdef..b55a87e 100644\n--- a/Documentation/git-log.txt\n+++ b/Documentation/git-log.txt\n@@ -51,9 +51,6 @@ include::pretty-options.txt[]\n \ta record about how the tip of a reference was changed.\n \tSee also gitlink:git-reflog[1].\n \n---decorate::\n-\tPrint out the ref names of any commits that are shown.\n-\n --full-diff::\n \tWithout this flag, \"git log -p <paths>...\" shows commits that\n \ttouch the specified paths, and diffs about the same specified\ndiff --git a/Documentation/pretty-options.txt b/Documentation/pretty-options.txt\nindex 746bc5b..3b21e0d 100644\n--- a/Documentation/pretty-options.txt\n+++ b/Documentation/pretty-options.txt\n@@ -20,3 +20,7 @@ people using 80-column terminals.\n \tcommand to re-code the commit log message in the encoding\n \tpreferred by the user.  For non plumbing commands this\n \tdefaults to UTF-8.\n+\n+--decorate::\n+\tWhen a commit is shown, and it matches a ref, print that ref name\n+\tin brackets after the commit name.\ndiff --git a/builtin-log.c b/builtin-log.c\nindex c14eea5..59372bb 100644\n--- a/builtin-log.c\n+++ b/builtin-log.c\n@@ -24,9 +24,6 @@ void add_head(struct rev_info *revs);\n static void cmd_log_init(int argc, const char **argv, const char *prefix,\n \t\t      struct rev_info *rev)\n {\n-\tint i;\n-\tint decorate = 0;\n-\n \trev->abbrev = DEFAULT_ABBREV;\n \trev->commit_format = CMIT_FMT_DEFAULT;\n \trev->verbose_header = 1;\n@@ -40,15 +37,8 @@ static void cmd_log_init(int argc, const char **argv, const char *prefix,\n \t\tif (rev->diffopt.nr_paths != 1)\n \t\t\tusage(\"git logs can only follow renames on one pathname at a time\");\n \t}\n-\tfor (i = 1; i < argc; i++) {\n-\t\tconst char *arg = argv[i];\n-\t\tif (!strcmp(arg, \"--decorate\")) {\n-\t\t\tif (!decorate)\n-\t\t\t\tfor_each_ref(add_ref_decoration, NULL);\n-\t\t\tdecorate = 1;\n-\t\t} else\n-\t\t\tdie(\"unrecognized argument: %s\", arg);\n-\t}\n+\tif (argc > 1)\n+\t\tdie(\"unrecognized argument: %s\", argv[1]);\n }\n \n static int cmd_log_walk(struct rev_info *rev)\ndiff --git a/revision.c b/revision.c\nindex 33ee9ee..7683d0a 100644\n--- a/revision.c\n+++ b/revision.c\n@@ -1176,6 +1176,10 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch\n \t\t\t\trevs->reverse ^= 1;\n \t\t\t\tcontinue;\n \t\t\t}\n+\t\t\tif (!strcmp(arg, \"--decorate\")) {\n+\t\t\t\tfor_each_ref(add_ref_decoration, NULL);\n+\t\t\t\tcontinue;\n+\t\t\t}\n \n \t\t\topts = diff_opt_parse(&revs->diffopt, argv+i, argc-i);\n \t\t\tif (opts > 0) {\n-- \n1.5.3.rc0.2783.gf3f7\n"},{"id":"46998","messageId":"Pine.LNX.4.64.0707110229320.4047@racer.site","threadId":"8975","inReplyTo":"Pine.LNX.4.64.0707110220340.4047@racer.site","subject":"[PATCH 3/4] --decorate now decorates ancestors, too","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2007-07-11T01:29:49Z","receivedAt":"2007-07-11T01:29:49Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"\nThe option --decorate changed default behavior: Earlier, it decorated\ncommits pointed to by any ref.  The new behavior is this: decorate the\nwith the given refs and its ancestors, i.e.\n\n\tgit log --decorate next master\n\nwill show \"next\", \"next^\", \"next~2\", ..., \"master\", \"master^\", ...\nin parenthesis after the commit name.\n\nHowever, you can still get the old behavior by giving --decorate=<mode>.\nThe available modes are:\n\n- 'given'\tthe new default behavior,\n- 'given-refs'\tonly decorate with the given refs, not their ancestors,\n- 'tag'\t\tdecorate with all tag refs and their ancestors,\n- 'tag-refs'\tdecorate with all tag refs, but not their ancestors,\n- 'any'\t\tdecorate with all refs and their ancestors,\n- 'any-ref'\tdecorate only with the refs, not their ancestors\n\nThe old behavior was 'any-ref'.\n\nNOTE: Calling \"git log --decorate=tag <commit>\" is _not_ the same as\ncalling \"git log <commit> | git -p name-rev --stdin\":\n\nFor one, the latter will only try to name 40-character hex sequences\n(which the former does not care about), but then it will also try\nto name such sequences in the commit messages and the diffs.\n\nMore importantly, though, \"--decorate=tag\" will only build the names\nwhile traversing commits, which makes it faster, but will fail to\ncorrectly identify something like \"git log --decorate=tag v0.99~2\".\n\nSigned-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n---\n Documentation/pretty-options.txt |   17 ++++++++--\n commit.c                         |   68 +++++++++++++++++++++++++++++++++++--\n commit.h                         |    4 ++-\n log-tree.c                       |    4 ++\n revision.c                       |   43 +++++++++++++++++++++++-\n revision.h                       |    9 +++++\n 6 files changed, 136 insertions(+), 9 deletions(-)\n\ndiff --git a/Documentation/pretty-options.txt b/Documentation/pretty-options.txt\nindex 3b21e0d..f82b1e9 100644\n--- a/Documentation/pretty-options.txt\n+++ b/Documentation/pretty-options.txt\n@@ -21,6 +21,17 @@ people using 80-column terminals.\n \tpreferred by the user.  For non plumbing commands this\n \tdefaults to UTF-8.\n \n---decorate::\n-\tWhen a commit is shown, and it matches a ref, print that ref name\n-\tin brackets after the commit name.\n+--decorate[=<mode>]::\n+\tWhen a commit is shown, decorate its commit name with the refs\n+\tspecified on the command line or their ancestors which point to\n+\tthat commit.\n++\n+You can influence the behaviour by givin a mode:\n+- 'given' is the default mode,\n+- 'given-refs' skips the decoration for ancestors,\n+- 'tag-refs' decorates only the tagged commits,\n+- 'tag' decorates tagged commits and their ancestors,\n+- 'any-ref' means that those commits are decorated that match any ref\n+  exactly, but no ancestors, and\n+- 'any' means that all commits that are pointed at by _any_ reachable\n+  commit are decorated by the appropriate names.\ndiff --git a/commit.c b/commit.c\nindex c0748ed..3aa21cc 100644\n--- a/commit.c\n+++ b/commit.c\n@@ -1554,13 +1554,24 @@ int in_merge_bases(struct commit *commit, struct commit **reference, int num)\n \treturn ret;\n }\n \n-void add_name_decoration(const char *prefix, const char *name, struct object *obj)\n+void add_name_decoration(const char *prefix, const char *name, int generation, struct object *obj)\n {\n \tint plen = strlen(prefix);\n \tint nlen = strlen(name);\n-\tstruct name_decoration *res = xmalloc(sizeof(struct name_decoration) + plen + nlen);\n+\tstruct name_decoration *res, *existing;\n+\n+\tres = xmalloc(sizeof(struct name_decoration) + plen + nlen);\n \tmemcpy(res->name, prefix, plen);\n \tmemcpy(res->name + plen, name, nlen + 1);\n+\n+\tfor (existing = lookup_decoration(&name_decoration, obj);\n+\t\t\texisting; existing = existing->next)\n+\t\tif (!strcmp(existing->name, res->name)) {\n+\t\t\tfree(res);\n+\t\t\treturn;\n+\t\t}\n+\n+\tres->generation = generation;\n \tres->next = add_decoration(&name_decoration, obj, res);\n }\n \n@@ -1569,12 +1580,61 @@ int add_ref_decoration(const char *refname, const unsigned char *sha1, int flags\n \tstruct object *obj = parse_object(sha1);\n \tif (!obj)\n \t\treturn 0;\n-\tadd_name_decoration(\"\", refname, obj);\n+\tif (!prefixcmp(refname, \"refs/heads/\"))\n+\t\trefname += 11;\n+\telse if (!prefixcmp(refname, \"refs/tags/\"))\n+\t\trefname += 10;\n+\telse if (!prefixcmp(refname, \"refs/remotes/\"))\n+\t\trefname += 13;\n+\telse if (!prefixcmp(refname, \"refs/\"))\n+\t\trefname += 5;\n+\tadd_name_decoration(\"\", refname, 0, obj);\n \twhile (obj->type == OBJ_TAG) {\n \t\tobj = ((struct tag *)obj)->tagged;\n \t\tif (!obj)\n \t\t\tbreak;\n-\t\tadd_name_decoration(\"tag: \", refname, obj);\n+\t\tadd_name_decoration(\"tag: \", refname, 0, obj);\n \t}\n \treturn 0;\n }\n+\n+void add_name_decoration_to_parents(struct commit *commit)\n+{\n+\tstruct name_decoration *decoration, *decor;\n+\tstruct commit_list *parents;\n+\tint parent_nr;\n+\n+\tparents = commit->parents;\n+\tif (!parents)\n+\t\treturn;\n+\n+\tdecoration = lookup_decoration(&name_decoration, &commit->object);\n+\tif (!decoration)\n+\t\treturn;\n+\n+\tfor (decor = decoration; decor; decor = decor->next)\n+\t\tadd_name_decoration(\"\", decor->name, decor->generation + 1,\n+\t\t\t\t&parents->item->object);\n+\n+\tparent_nr = 1;\n+\twhile (parents->next) {\n+\t\tchar buffer[PATH_MAX];\n+\t\tparents = parents->next;\n+\t\tparent_nr++;\n+\t\tfor (decor = decoration; decor; decor = decor->next) {\n+\t\t\tif (decor->generation < 2)\n+\t\t\t\tsnprintf(buffer, sizeof(buffer),\n+\t\t\t\t\t\t\"%s%s^%d\", decor->name,\n+\t\t\t\t\t\tdecor->generation ? \"^\" : \"\",\n+\t\t\t\t\t\tparent_nr);\n+\t\t\telse\n+\t\t\t\tsnprintf(buffer, sizeof(buffer),\n+\t\t\t\t\t\t\"%s~%d^%d\", decor->name,\n+\t\t\t\t\t\tdecor->generation, parent_nr);\n+\t\t\tadd_name_decoration(\"\", buffer, 0,\n+\t\t\t\t\t&parents->item->object);\n+\t\t}\n+\t}\n+}\n+\n+\ndiff --git a/commit.h b/commit.h\nindex 787ae5e..8dafc7b 100644\n--- a/commit.h\n+++ b/commit.h\n@@ -26,11 +26,13 @@ extern const char *commit_type;\n extern struct decoration name_decoration;\n struct name_decoration {\n \tstruct name_decoration *next;\n+\tint generation;\n \tchar name[1];\n };\n \n-void add_name_decoration(const char *prefix, const char *name, struct object *obj);\n+void add_name_decoration(const char *prefix, const char *name, int generation, struct object *obj);\n int add_ref_decoration(const char *refname, const unsigned char *sha1, int flags, void *cb_data);\n+void add_name_decoration_to_parents(struct commit *commit);\n \n struct commit *lookup_commit(const unsigned char *sha1);\n struct commit *lookup_commit_reference(const unsigned char *sha1);\ndiff --git a/log-tree.c b/log-tree.c\nindex 8624d5a..eb7641a 100644\n--- a/log-tree.c\n+++ b/log-tree.c\n@@ -26,6 +26,10 @@ static void show_decorations(struct commit *commit)\n \tprefix = \" (\";\n \twhile (decoration) {\n \t\tprintf(\"%s%s\", prefix, decoration->name);\n+\t\tif (decoration->generation == 1)\n+\t\t\tputchar('^');\n+\t\telse if (decoration->generation > 1)\n+\t\t\tprintf(\"~%d\", decoration->generation);\n \t\tprefix = \", \";\n \t\tdecoration = decoration->next;\n \t}\ndiff --git a/revision.c b/revision.c\nindex 7683d0a..79880b4 100644\n--- a/revision.c\n+++ b/revision.c\n@@ -641,6 +641,10 @@ static int add_parents_only(struct rev_info *revs, const char *arg, int flags)\n \tif (it->type != OBJ_COMMIT)\n \t\treturn 0;\n \tcommit = (struct commit *)it;\n+\tif (revs->decorate & DECORATE_GIVEN_REFS)\n+\t\tadd_name_decoration(\"\", arg, 0, it);\n+\tif (revs->decorate & DECORATE_RECURSIVE)\n+\t\tadd_name_decoration_to_parents(commit);\n \tfor (parents = commit->parents; parents; parents = parents->next) {\n \t\tit = &parents->item->object;\n \t\tit->flags |= flags;\n@@ -778,6 +782,11 @@ int handle_revision_arg(const char *arg, struct rev_info *revs,\n \t\t\t\tverify_non_filename(revs->prefix, arg);\n \t\t\t}\n \n+\t\t\tif (revs->decorate & DECORATE_GIVEN_REFS) {\n+\t\t\t\tadd_name_decoration(\"\", this, 0, &a->object);\n+\t\t\t\tadd_name_decoration(\"\", next, 0, &b->object);\n+\t\t\t}\n+\n \t\t\tif (symmetric) {\n \t\t\t\texclude = get_merge_bases(a, b, 1);\n \t\t\t\tadd_pending_commit_list(revs, exclude,\n@@ -817,6 +826,8 @@ int handle_revision_arg(const char *arg, struct rev_info *revs,\n \tif (!cant_be_filename)\n \t\tverify_non_filename(revs->prefix, arg);\n \tobject = get_reference(revs, arg, sha1, flags ^ local_flags);\n+\tif (revs->decorate & DECORATE_GIVEN_REFS)\n+\t\tadd_name_decoration(\"\", arg, 0, object);\n \tadd_pending_object_with_mode(revs, object, arg, mode);\n \treturn 0;\n }\n@@ -1177,7 +1188,29 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch\n \t\t\t\tcontinue;\n \t\t\t}\n \t\t\tif (!strcmp(arg, \"--decorate\")) {\n-\t\t\t\tfor_each_ref(add_ref_decoration, NULL);\n+\t\t\t\trevs->decorate = DECORATE_GIVEN_REFS |\n+\t\t\t\t\tDECORATE_RECURSIVE;\n+\t\t\t\tcontinue;\n+\t\t\t}\n+\t\t\tif (!prefixcmp(arg, \"--decorate=\")) {\n+\t\t\t\tif (!strcmp(arg + 11, \"any-ref\"))\n+\t\t\t\t\trevs->decorate = DECORATE_ALL_REFS;\n+\t\t\t\telse if (!strcmp(arg + 11, \"given-refs\"))\n+\t\t\t\t\trevs->decorate = DECORATE_GIVEN_REFS;\n+\t\t\t\telse if (!strcmp(arg + 11, \"given\"))\n+\t\t\t\t\trevs->decorate = DECORATE_GIVEN_REFS |\n+\t\t\t\t\t\tDECORATE_RECURSIVE;\n+\t\t\t\telse if (!strcmp(arg + 11, \"any\"))\n+\t\t\t\t\trevs->decorate = DECORATE_GIVEN_REFS |\n+\t\t\t\t\t\tDECORATE_ALL_REFS |\n+\t\t\t\t\t\tDECORATE_RECURSIVE;\n+\t\t\t\telse if (!strcmp(arg + 11, \"tag-refs\"))\n+\t\t\t\t\trevs->decorate = DECORATE_TAG_REFS;\n+\t\t\t\telse if (!strcmp(arg + 11, \"tag\"))\n+\t\t\t\t\trevs->decorate = DECORATE_TAG_REFS |\n+\t\t\t\t\t\tDECORATE_RECURSIVE;\n+\t\t\t\telse\n+\t\t\t\t\tdie(\"Unknown argument: %s\", arg);\n \t\t\t\tcontinue;\n \t\t\t}\n \n@@ -1213,6 +1246,11 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch\n \t\t}\n \t}\n \n+\tif (revs->decorate & DECORATE_ALL_REFS)\n+\t\tfor_each_ref(add_ref_decoration, NULL);\n+\tif (revs->decorate & DECORATE_TAG_REFS)\n+\t\tfor_each_tag_ref(add_ref_decoration, NULL);\n+\n \tif (revs->grep_filter)\n \t\trevs->grep_filter->regflags |= regflags;\n \n@@ -1372,6 +1410,9 @@ static struct commit *get_revision_1(struct rev_info *revs)\n \t\trevs->commits = entry->next;\n \t\tfree(entry);\n \n+\t\tif (revs->decorate & DECORATE_RECURSIVE)\n+\t\t\tadd_name_decoration_to_parents(commit);\n+\n \t\tif (revs->reflog_info)\n \t\t\tfake_reflog_parent(revs->reflog_info, commit);\n \ndiff --git a/revision.h b/revision.h\nindex f46b4d5..0c3dc67 100644\n--- a/revision.h\n+++ b/revision.h\n@@ -16,6 +16,14 @@ struct log_info;\n \n typedef void (prune_fn_t)(struct rev_info *revs, struct commit *commit);\n \n+enum decorate {\n+\tDECORATE_NONE = 0,\n+\tDECORATE_RECURSIVE = 1,\n+\tDECORATE_ALL_REFS = 2,\n+\tDECORATE_TAG_REFS = 4,\n+\tDECORATE_GIVEN_REFS = 8,\n+};\n+\n struct rev_info {\n \t/* Starting list */\n \tstruct commit_list *commits;\n@@ -65,6 +73,7 @@ struct rev_info {\n \tunsigned int\tshown_one:1,\n \t\t\tabbrev_commit:1;\n \tenum date_mode date_mode;\n+\tenum decorate\tdecorate;\n \n \tconst char **ignore_packed; /* pretend objects in these are unpacked */\n \tint num_ignore_packed;\n-- \n1.5.3.rc0.2783.gf3f7\n"},{"id":"46999","messageId":"Pine.LNX.4.64.0707110230030.4047@racer.site","threadId":"8975","inReplyTo":"Pine.LNX.4.64.0707110220340.4047@racer.site","subject":"[PATCH 4/4] --decorate: prefer shorter names","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2007-07-11T01:30:11Z","receivedAt":"2007-07-11T01:30:11Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"\nWhen saying \"--decorate=any\", the decoration could get huge pretty\nquickly.  Especially in a project like git.git, where there is a\nlot of back and forth merging, older commits can be named in a\nthousand ways.\n\nHowever, usually you are only interested in short names.  For example,\nmost people are not interested in the fact that the initial commit\ncan be named by ways like v0.99~31^2~37^2^2~508^2^2~195^2~114, if you\ncan reference it by v0.99~954 instead.\n\nSigned-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n---\n commit.c   |   39 +++++++++++++++++++++++++++++----------\n commit.h   |    4 ++--\n revision.c |   10 ++++++----\n 3 files changed, 37 insertions(+), 16 deletions(-)\n\ndiff --git a/commit.c b/commit.c\nindex 3aa21cc..4128ef4 100644\n--- a/commit.c\n+++ b/commit.c\n@@ -1554,25 +1554,43 @@ int in_merge_bases(struct commit *commit, struct commit **reference, int num)\n \treturn ret;\n }\n \n-void add_name_decoration(const char *prefix, const char *name, int generation, struct object *obj)\n+void add_name_decoration(const char *prefix, const char *name, int generation, int distance, struct object *obj)\n {\n \tint plen = strlen(prefix);\n \tint nlen = strlen(name);\n \tstruct name_decoration *res, *existing;\n+\tint free_existing = 0;\n+\n+\texisting = lookup_decoration(&name_decoration, obj);\n+\tif (existing && existing->distance < distance)\n+\t\treturn;\n+\n+\tif (existing && existing->distance > distance)\n+\t\tfree_existing = 1;\n \n \tres = xmalloc(sizeof(struct name_decoration) + plen + nlen);\n \tmemcpy(res->name, prefix, plen);\n \tmemcpy(res->name + plen, name, nlen + 1);\n \n-\tfor (existing = lookup_decoration(&name_decoration, obj);\n-\t\t\texisting; existing = existing->next)\n-\t\tif (!strcmp(existing->name, res->name)) {\n-\t\t\tfree(res);\n-\t\t\treturn;\n-\t\t}\n+\tif (!free_existing)\n+\t\tfor (; existing; existing = existing->next)\n+\t\t\tif (!strcmp(existing->name, res->name)) {\n+\t\t\t\tfree(res);\n+\t\t\t\treturn;\n+\t\t\t}\n \n \tres->generation = generation;\n+\tres->distance = distance;\n \tres->next = add_decoration(&name_decoration, obj, res);\n+\n+\tif (free_existing) {\n+\t\tfor (existing = res->next; existing; ) {\n+\t\t\tstruct name_decoration *next = existing->next;\n+\t\t\tfree(existing);\n+\t\t\texisting = next;\n+\t\t}\n+\t\tres->next = NULL;\n+\t}\n }\n \n int add_ref_decoration(const char *refname, const unsigned char *sha1, int flags, void *cb_data)\n@@ -1588,12 +1606,12 @@ int add_ref_decoration(const char *refname, const unsigned char *sha1, int flags\n \t\trefname += 13;\n \telse if (!prefixcmp(refname, \"refs/\"))\n \t\trefname += 5;\n-\tadd_name_decoration(\"\", refname, 0, obj);\n+\tadd_name_decoration(\"\", refname, 0, 0, obj);\n \twhile (obj->type == OBJ_TAG) {\n \t\tobj = ((struct tag *)obj)->tagged;\n \t\tif (!obj)\n \t\t\tbreak;\n-\t\tadd_name_decoration(\"tag: \", refname, 0, obj);\n+\t\tadd_name_decoration(\"tag: \", refname, 0, 0, obj);\n \t}\n \treturn 0;\n }\n@@ -1614,7 +1632,7 @@ void add_name_decoration_to_parents(struct commit *commit)\n \n \tfor (decor = decoration; decor; decor = decor->next)\n \t\tadd_name_decoration(\"\", decor->name, decor->generation + 1,\n-\t\t\t\t&parents->item->object);\n+\t\t\t\tdecor->distance + 1, &parents->item->object);\n \n \tparent_nr = 1;\n \twhile (parents->next) {\n@@ -1632,6 +1650,7 @@ void add_name_decoration_to_parents(struct commit *commit)\n \t\t\t\t\t\t\"%s~%d^%d\", decor->name,\n \t\t\t\t\t\tdecor->generation, parent_nr);\n \t\t\tadd_name_decoration(\"\", buffer, 0,\n+\t\t\t\t\tdecor->distance + 256,\n \t\t\t\t\t&parents->item->object);\n \t\t}\n \t}\ndiff --git a/commit.h b/commit.h\nindex 8dafc7b..9b2bd55 100644\n--- a/commit.h\n+++ b/commit.h\n@@ -26,11 +26,11 @@ extern const char *commit_type;\n extern struct decoration name_decoration;\n struct name_decoration {\n \tstruct name_decoration *next;\n-\tint generation;\n+\tint generation, distance;\n \tchar name[1];\n };\n \n-void add_name_decoration(const char *prefix, const char *name, int generation, struct object *obj);\n+void add_name_decoration(const char *prefix, const char *name, int generation, int distance, struct object *obj);\n int add_ref_decoration(const char *refname, const unsigned char *sha1, int flags, void *cb_data);\n void add_name_decoration_to_parents(struct commit *commit);\n \ndiff --git a/revision.c b/revision.c\nindex 79880b4..796275d 100644\n--- a/revision.c\n+++ b/revision.c\n@@ -642,7 +642,7 @@ static int add_parents_only(struct rev_info *revs, const char *arg, int flags)\n \t\treturn 0;\n \tcommit = (struct commit *)it;\n \tif (revs->decorate & DECORATE_GIVEN_REFS)\n-\t\tadd_name_decoration(\"\", arg, 0, it);\n+\t\tadd_name_decoration(\"\", arg, 0, 0, it);\n \tif (revs->decorate & DECORATE_RECURSIVE)\n \t\tadd_name_decoration_to_parents(commit);\n \tfor (parents = commit->parents; parents; parents = parents->next) {\n@@ -783,8 +783,10 @@ int handle_revision_arg(const char *arg, struct rev_info *revs,\n \t\t\t}\n \n \t\t\tif (revs->decorate & DECORATE_GIVEN_REFS) {\n-\t\t\t\tadd_name_decoration(\"\", this, 0, &a->object);\n-\t\t\t\tadd_name_decoration(\"\", next, 0, &b->object);\n+\t\t\t\tadd_name_decoration(\"\", this, 0, 0,\n+\t\t\t\t\t\t&a->object);\n+\t\t\t\tadd_name_decoration(\"\", next, 0, 0,\n+\t\t\t\t\t\t&b->object);\n \t\t\t}\n \n \t\t\tif (symmetric) {\n@@ -827,7 +829,7 @@ int handle_revision_arg(const char *arg, struct rev_info *revs,\n \t\tverify_non_filename(revs->prefix, arg);\n \tobject = get_reference(revs, arg, sha1, flags ^ local_flags);\n \tif (revs->decorate & DECORATE_GIVEN_REFS)\n-\t\tadd_name_decoration(\"\", arg, 0, object);\n+\t\tadd_name_decoration(\"\", arg, 0, 0, object);\n \tadd_pending_object_with_mode(revs, object, arg, mode);\n \treturn 0;\n }\n-- \n1.5.3.rc0.2783.gf3f7\n"},{"id":"47000","messageId":"20070711022714.GI27033@thunk.org","threadId":"8975","inReplyTo":"Pine.LNX.4.64.0707110229320.4047@racer.site","subject":"Re: [PATCH 3/4] --decorate now decorates ancestors, too","fromName":"Theodore Tso","fromEmail":"tytso@mit.edu","sentAt":"2007-07-11T02:27:14Z","receivedAt":"2007-07-11T02:27:14Z","isPatch":true,"sender":{"key":"tytso@mit.edu","avatar":"https://avatars.githubusercontent.com/u/51416?v=4"},"body":"On Wed, Jul 11, 2007 at 02:29:49AM +0100, Johannes Schindelin wrote:\n> \n> The option --decorate changed default behavior: Earlier, it decorated\n> commits pointed to by any ref.  The new behavior is this: decorate the\n> with the given refs and its ancestors, i.e.\n> \n> \tgit log --decorate next master\n> \n> will show \"next\", \"next^\", \"next~2\", ..., \"master\", \"master^\", ...\n> in parenthesis after the commit name.\n\nI'm wondering how useful the default is.  The arguments get used for\ntwo things; both for git-log to decide what revisions to display, and\nwhich refs to decorate, right?  I'm not sure that overloading is such\na great idea.\n\nAlso, I note that \"git log --decorate\" does nothing at all.  Maybe it\nwould be better to keep the default to be \"any-ref\" instead of \"given\"?\n\n\t\t      \t \t   \t    - Ted\n"},{"id":"47189","messageId":"7v4pk9v4tp.fsf@assigned-by-dhcp.cox.net","threadId":"8975","inReplyTo":"Pine.LNX.4.64.0707110229120.4047@racer.site","subject":"Re: [PATCH 2/4] Move the --decorate option from builtin-log.c to revision.c.","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2007-07-12T18:45:38Z","receivedAt":"2007-07-12T18:45:38Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n\n> ---decorate::\n> -\tPrint out the ref names of any commits that are shown.\n> -\n> ...\n> +\n> +--decorate::\n> +\tWhen a commit is shown, and it matches a ref, print that ref name\n> +\tin brackets after the commit name.\n\nThe character-pair ( and ) are usually called parentheses, not\nbrackets.\n\nOther than that, these two code movements and refactorings feel\na sane thing to do.\n"},{"id":"47190","messageId":"7vmyy1tq96.fsf@assigned-by-dhcp.cox.net","threadId":"8975","inReplyTo":"20070711022714.GI27033@thunk.org","subject":"Re: [PATCH 3/4] --decorate now decorates ancestors, too","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2007-07-12T18:45:41Z","receivedAt":"2007-07-12T18:45:41Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Theodore Tso <tytso@mit.edu> writes:\n\n> On Wed, Jul 11, 2007 at 02:29:49AM +0100, Johannes Schindelin wrote:\n>> \n>> The option --decorate changed default behavior: Earlier, it decorated\n>> commits pointed to by any ref.  The new behavior is this: decorate the\n>> with the given refs and its ancestors, i.e.\n>> \n>> \tgit log --decorate next master\n>> \n>> will show \"next\", \"next^\", \"next~2\", ..., \"master\", \"master^\", ...\n>> in parenthesis after the commit name.\n>\n> I'm wondering how useful the default is.  The arguments get used for\n> two things; both for git-log to decide what revisions to display, and\n> which refs to decorate, right?  I'm not sure that overloading is such\n> a great idea.\n>\n> Also, I note that \"git log --decorate\" does nothing at all.  Maybe it\n> would be better to keep the default to be \"any-ref\" instead of \"given\"?\n\nI think defaulting to \"given\" is a regression.  It could be\nargued that \"tag-ref\" or \"tag\" might be a better default\n(judging from my experience with \"name-rev\"), but keeping\n\"any-ref\" would probably be the safest.\n\nBut in general I do not see (\"I haven't realized\" might turn out\nto be a better expression) much value in this series yet except\nfor the initial clean-up patches, while I think this option\nwould be quite expensive in terms of memory footprints on\nprojects with nontrivial size of history.  I dunno.\n"},{"id":"47271","messageId":"Pine.LNX.4.64.0707131626200.14781@racer.site","threadId":"8975","inReplyTo":"7v4pk9v4tp.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH 2/4] Move the --decorate option from builtin-log.c to revision.c.","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2007-07-13T15:38:53Z","receivedAt":"2007-07-13T15:38:53Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Thu, 12 Jul 2007, Junio C Hamano wrote:\n\n> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n> \n> > ---decorate::\n> > -\tPrint out the ref names of any commits that are shown.\n> > -\n> > ...\n> > +\n> > +--decorate::\n> > +\tWhen a commit is shown, and it matches a ref, print that ref name\n> > +\tin brackets after the commit name.\n> \n> The character-pair ( and ) are usually called parentheses, not\n> brackets.\n\nOkay.  You want me to resend, or will you fix it?\n\nCiao,\nDscho\n"},{"id":"47298","messageId":"Pine.LNX.4.64.0707140123141.14781@racer.site","threadId":"8975","inReplyTo":"7vmyy1tq96.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH 3/4] --decorate now decorates ancestors, too","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2007-07-14T00:23:40Z","receivedAt":"2007-07-14T00:23:40Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Thu, 12 Jul 2007, Junio C Hamano wrote:\n\n> Theodore Tso <tytso@mit.edu> writes:\n> \n> > On Wed, Jul 11, 2007 at 02:29:49AM +0100, Johannes Schindelin wrote:\n> >> \n> >> The option --decorate changed default behavior: Earlier, it decorated\n> >> commits pointed to by any ref.  The new behavior is this: decorate the\n> >> with the given refs and its ancestors, i.e.\n> >> \n> >> \tgit log --decorate next master\n> >> \n> >> will show \"next\", \"next^\", \"next~2\", ..., \"master\", \"master^\", ...\n> >> in parenthesis after the commit name.\n> >\n> > I'm wondering how useful the default is.  The arguments get used for\n> > two things; both for git-log to decide what revisions to display, and\n> > which refs to decorate, right?  I'm not sure that overloading is such\n> > a great idea.\n> >\n> > Also, I note that \"git log --decorate\" does nothing at all.  Maybe it\n> > would be better to keep the default to be \"any-ref\" instead of \"given\"?\n> \n> I think defaulting to \"given\" is a regression.  It could be\n> argued that \"tag-ref\" or \"tag\" might be a better default\n> (judging from my experience with \"name-rev\"), but keeping\n> \"any-ref\" would probably be the safest.\n\nOkay, fair enough.  I kind of expected people to disagree as of the \ndefault mode.  My preference would have been \"tag\", since I need that \nquite often, but I am willing to put my wishes aside there.\n\nProbably I should follow up with a replacement patch, and a config \nvariable \"commit.decorateMode\" patch, leaving the default at \"any-ref\"?\n\n> But in general I do not see (\"I haven't realized\" might turn out to be a \n> better expression) much value in this series yet except for the initial \n> clean-up patches, while I think this option would be quite expensive in \n> terms of memory footprints on projects with nontrivial size of history.  \n> I dunno.\n\nThere are a few points I want to make to convince you:\n\n- I need this quite often to see which version introduced a certain \n  feature.  This is most visible on IRC, where people ask \"how can I do X, \n  I have version Y\", and me responding \"There is a feature P, but \n  unfortunately, it is only available from revision Q~N\" where Q > Y.\n\n  I really want other people to do this easily, without having to know how \n  name-rev (which has a dash in its name, and thus is kind of \n  plumbing-ish) works.\n\n\n- It is _not_ expensive.  It only ever allocates something in the case of \n  merges (at least that's how I designed it), and should free the used \n  memory when the commit name is not used at all (but maybe I forgot that \n  part...).  So you will have at most one allocation of a few bytes per \n  merge, and I really do not see how this could break down for \n  pathological, but real-world, cases.\n\n- 40-character commit names seem to be really hard on people.\n\nTo drive the 3rd point home: I often see people confused as to what those \nlong commit names are.  They do not even realise that they are _object_ \nnames, actually, not only applicable to commit objects.\n\nIMHO a great way to teach users that commit names are equivalent to \nshortcuts like \"v1.5.0-rc1~20\" would be to even enable decoration by tags \nby default.\n\nCiao,\nDscho\n"},{"id":"48064","messageId":"Pine.LNX.4.64.0707212322260.14781@racer.site","threadId":"8975","inReplyTo":"7vmyy1tq96.fsf@assigned-by-dhcp.cox.net","subject":"Re: [PATCH 3/4] --decorate now decorates ancestors, too","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2007-07-21T22:26:11Z","receivedAt":"2007-07-21T22:26:11Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Thu, 12 Jul 2007, Junio C Hamano wrote:\n\n> But in general I do not see (\"I haven't realized\" might turn out to be a \n> better expression) much value in this series yet except for the initial \n> clean-up patches, while I think this option would be quite expensive in \n> terms of memory footprints on projects with nontrivial size of history.  \n> I dunno.\n\nIt would not, since you do not have to say \"--decorate\" at all.  However, \nif you do want the functionality this patch provides, you have to jump \nthrough hoops right now.  ATM an alias is my work around, since I run \n'master' as you requested:\n\ngit config --global alias.decoratelog '!sh -c\n\t\"(case \\\"\\$0\\\" in\n\t\tsh) git log --color;;\n\t\t*) git log --color \\\"\\$0\\\" \\\"\\$@\\\";;\n\t esac) |\n\t git -p name-rev --tags --stdin\"'\n\nUgly, ain't it?\n\nAnd I still have to look up at which release certain features were \nintroduced every day.\n\nCiao,\nDscho\n"}]}