{"thread":{"id":"26026","subject":"[PATCH 1/2] get_sha1_oneline: allow to input commit_list","startedAt":"2010-12-12T10:56:58Z","lastAt":"2010-12-13T00:29:06Z","messageCount":5,"participants":["Nguyễn Thái Ngọc Duy","Jonathan Nieder","Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":2},"messages":[{"id":"157883","messageId":"1292151419-30678-1-git-send-email-pclouds@gmail.com","threadId":"26026","inReplyTo":null,"subject":"[PATCH 1/2] get_sha1_oneline: allow to input commit_list","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2010-12-12T10:56:58Z","receivedAt":"2010-12-12T10:56:58Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n sha1_name.c |   13 ++++++++++---\n 1 files changed, 10 insertions(+), 3 deletions(-)\n\ndiff --git a/sha1_name.c b/sha1_name.c\nindex 2c3a5fb..c298285 100644\n--- a/sha1_name.c\n+++ b/sha1_name.c\n@@ -690,7 +690,9 @@ static int handle_one_ref(const char *path,\n \treturn 0;\n }\n \n-static int get_sha1_oneline(const char *prefix, unsigned char *sha1)\n+static int get_sha1_oneline(const char *prefix,\n+\t\t\t    unsigned char *sha1,\n+\t\t\t    struct commit_list *original_list)\n {\n \tstruct commit_list *list = NULL, *backup = NULL, *l;\n \tint retval = -1;\n@@ -706,7 +708,12 @@ static int get_sha1_oneline(const char *prefix, unsigned char *sha1)\n \tif (regcomp(&regex, prefix, REG_EXTENDED))\n \t\tdie(\"Invalid search pattern: %s\", prefix);\n \n-\tfor_each_ref(handle_one_ref, &list);\n+\tfor (l = original_list; l; l = l->next) {\n+\t\tcommit_list_insert(l->item, &list);\n+\t\tl->item->object.flags |= ONELINE_SEEN;\n+\t}\n+\tif (!list)\n+\t\tfor_each_ref(handle_one_ref, &list);\n \tfor (l = list; l; l = l->next)\n \t\tcommit_list_insert(l->item, &backup);\n \twhile (list) {\n@@ -1090,7 +1097,7 @@ int get_sha1_with_context_1(const char *name, unsigned char *sha1,\n \t\tint pos;\n \t\tif (namelen > 2 && name[1] == '/')\n \t\t\t/* don't need mode for commit */\n-\t\t\treturn get_sha1_oneline(name + 2, sha1);\n+\t\t\treturn get_sha1_oneline(name + 2, sha1, NULL);\n \t\tif (namelen < 3 ||\n \t\t    name[2] != ':' ||\n \t\t    name[1] < '0' || '3' < name[1])\n-- \n1.7.3.3.476.g893a9\n"},{"id":"157884","messageId":"1292151419-30678-2-git-send-email-pclouds@gmail.com","threadId":"26026","inReplyTo":"1292151419-30678-1-git-send-email-pclouds@gmail.com","subject":"[PATCH 2/2] get_sha1: support ref^{/regex} syntax","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2010-12-12T10:56:59Z","receivedAt":"2010-12-12T10:56:59Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"This works like :/ syntax, but only limited to one ref.\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n No fancy modifiers, but still useful.\n\n Documentation/revisions.txt |    6 +++\n sha1_name.c                 |   35 ++++++++++++++------\n t/t1511-rev-parse-caret.sh  |   73 +++++++++++++++++++++++++++++++++++++++++++\n 3 files changed, 103 insertions(+), 11 deletions(-)\n create mode 100755 t/t1511-rev-parse-caret.sh\n\ndiff --git a/Documentation/revisions.txt b/Documentation/revisions.txt\nindex 3d4b79c..174fa8e 100644\n--- a/Documentation/revisions.txt\n+++ b/Documentation/revisions.txt\n@@ -106,6 +106,12 @@ the `$GIT_DIR/refs` directory or from the `$GIT_DIR/packed-refs` file.\n   and dereference the tag recursively until a non-tag object is\n   found.\n \n+* A suffix '{caret}' to a revision parameter followed by a brace\n+  pair that contains a text led by a slash (e.g. `HEAD^{/fix nasty bug}`):\n+  this is the same as `:/fix nasty bug` syntax below except that\n+  it returns the youngest matching commit which is reachable from\n+  the ref before '{caret}'.\n+\n * A colon, followed by a slash, followed by a text (e.g. `:/fix nasty bug`): this names\n   a commit whose commit message matches the specified regular expression.\n   This name returns the youngest matching commit which is\ndiff --git a/sha1_name.c b/sha1_name.c\nindex c298285..f1a86d9 100644\n--- a/sha1_name.c\n+++ b/sha1_name.c\n@@ -527,6 +527,7 @@ struct object *peel_to_type(const char *name, int namelen,\n \t}\n }\n \n+static int get_sha1_oneline(const char *, unsigned char *, struct commit_list *);\n static int peel_onion(const char *name, int len, unsigned char *sha1)\n {\n \tunsigned char outer[20];\n@@ -562,6 +563,8 @@ static int peel_onion(const char *name, int len, unsigned char *sha1)\n \t\texpected_type = OBJ_BLOB;\n \telse if (sp[0] == '}')\n \t\texpected_type = OBJ_NONE;\n+\telse if (sp[0] == '/')\n+\t\texpected_type = OBJ_COMMIT;\n \telse\n \t\treturn -1;\n \n@@ -576,19 +579,29 @@ static int peel_onion(const char *name, int len, unsigned char *sha1)\n \t\tif (!o || (!o->parsed && !parse_object(o->sha1)))\n \t\t\treturn -1;\n \t\thashcpy(sha1, o->sha1);\n+\t\treturn 0;\n \t}\n-\telse {\n-\t\t/*\n-\t\t * At this point, the syntax look correct, so\n-\t\t * if we do not get the needed object, we should\n-\t\t * barf.\n-\t\t */\n-\t\to = peel_to_type(name, len, o, expected_type);\n-\t\tif (o) {\n-\t\t\thashcpy(sha1, o->sha1);\n-\t\t\treturn 0;\n-\t\t}\n+\n+\t/*\n+\t * At this point, the syntax look correct, so if we do not get\n+\t * the needed object, we should barf.\n+\t */\n+\to = peel_to_type(name, len, o, expected_type);\n+\tif (!o)\n \t\treturn -1;\n+\n+\thashcpy(sha1, o->sha1);\n+\tif (sp[0] == '/') { /* ^{/foo} */\n+\t\tstruct commit_list *list = NULL;\n+\t\tchar *prefix;\n+\t\tint ret;\n+\n+\t\tcommit_list_insert((struct commit *)o, &list);\n+\t\tprefix = xstrndup(sp + 1, name + len - 1 - (sp + 1));\n+\t\tret = get_sha1_oneline(prefix, sha1, list);\n+\t\tfree(prefix);\n+\t\tfree_commit_list(list);\n+\t\treturn ret;\n \t}\n \treturn 0;\n }\ndiff --git a/t/t1511-rev-parse-caret.sh b/t/t1511-rev-parse-caret.sh\nnew file mode 100755\nindex 0000000..5c8439c\n--- /dev/null\n+++ b/t/t1511-rev-parse-caret.sh\n@@ -0,0 +1,73 @@\n+#!/bin/sh\n+\n+test_description='tests for ref^{stuff}'\n+\n+. ./test-lib.sh\n+\n+test_expect_success 'setup' '\n+\techo blob >a-blob &&\n+\tgit tag -a -m blob blob-tag `git hash-object -w a-blob`\n+\tmkdir a-tree &&\n+\techo moreblobs >a-tree/another-blob &&\n+\tgit add . &&\n+\tTREE_SHA1=`git write-tree` &&\n+\tgit tag -a -m tree tree-tag \"$TREE_SHA1\" &&\n+\tgit commit -m Initial &&\n+\tgit tag -a -m commit commit-tag &&\n+\tgit branch ref &&\n+\tgit checkout master &&\n+\techo modified >>a-blob &&\n+\tgit add -u &&\n+\tgit commit -m Modified\n+'\n+\n+test_expect_success 'ref^{non-existent}' '\n+\ttest_must_fail git rev-parse ref^{non-existent}\n+'\n+\n+test_expect_success 'ref^{}' '\n+\tgit rev-parse ref >expected &&\n+\tgit rev-parse ref^{} >actual &&\n+\ttest_cmp expected actual &&\n+\tgit rev-parse commit-tag^{} >actual &&\n+\ttest_cmp expected actual\n+'\n+\n+test_expect_success 'ref^{commit}' '\n+\tgit rev-parse ref >expected &&\n+\tgit rev-parse ref^{commit} >actual &&\n+\ttest_cmp expected actual &&\n+\tgit rev-parse commit-tag^{commit} >actual &&\n+\ttest_cmp expected actual &&\n+\ttest_must_fail git rev-parse tree-tag^{commit} &&\n+\ttest_must_fail git rev-parse blob-tag^{commit}\n+'\n+\n+test_expect_success 'ref^{tree}' '\n+\techo $TREE_SHA1 >expected &&\n+\tgit rev-parse ref^{tree} >actual &&\n+\ttest_cmp expected actual &&\n+\tgit rev-parse commit-tag^{tree} >actual &&\n+\ttest_cmp expected actual &&\n+\tgit rev-parse tree-tag^{tree} >actual &&\n+\ttest_cmp expected actual &&\n+\ttest_must_fail git rev-parse blob-tag^{tree}\n+'\n+\n+test_expect_success 'ref^{/}' '\n+\tgit rev-parse master >expected &&\n+\tgit rev-parse master^{/} >actual &&\n+\ttest_cmp expected actual\n+'\n+\n+test_expect_success 'ref^{/non-existent}' '\n+\ttest_must_fail git rev-parse master^{/non-existent}\n+'\n+\n+test_expect_success 'ref^{/Initial}' '\n+\tgit rev-parse ref >expected &&\n+\tgit rev-parse master^{/Initial} >actual &&\n+\ttest_cmp expected actual\n+'\n+\n+test_done\n-- \n1.7.3.3.476.g893a9\n"},{"id":"157893","messageId":"20101212173411.GA19293@burratino","threadId":"26026","inReplyTo":"1292151419-30678-1-git-send-email-pclouds@gmail.com","subject":"Re: [PATCH 1/2] get_sha1_oneline: allow to input commit_list","fromName":"Jonathan Nieder","fromEmail":"jrnieder@gmail.com","sentAt":"2010-12-12T17:34:11Z","receivedAt":"2010-12-12T17:34:11Z","isPatch":true,"sender":{"key":"jrnieder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/281595?v=4"},"body":"Nguyễn Thái Ngọc Duy wrote:\n\n> [Subject: get_sha1_oneline: allow to input commit_list]\n\nCryptic.  Might be simpler to squash this with the next commit,\nsince the best explanation I can come up with is\n\n\tprepare to extend :/foo syntax to start search at specified refs\n"},{"id":"157894","messageId":"20101212173850.GB19293@burratino","threadId":"26026","inReplyTo":"1292151419-30678-2-git-send-email-pclouds@gmail.com","subject":"Re: [PATCH 2/2] get_sha1: support ref^{/regex} syntax","fromName":"Jonathan Nieder","fromEmail":"jrnieder@gmail.com","sentAt":"2010-12-12T17:38:50Z","receivedAt":"2010-12-12T17:38:50Z","isPatch":true,"sender":{"key":"jrnieder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/281595?v=4"},"body":"Nguyễn Thái Ngọc Duy wrote:\n\n> This works like :/ syntax, but only limited to one ref.\n\nLimited to the ancestors of one commit, not one ref, right?\n\n> --- /dev/null\n> +++ b/t/t1511-rev-parse-caret.sh\n> @@ -0,0 +1,73 @@\n\nNice.\n"},{"id":"157904","messageId":"7vsjy27bxp.fsf@alter.siamese.dyndns.org","threadId":"26026","inReplyTo":"1292151419-30678-1-git-send-email-pclouds@gmail.com","subject":"Re: [PATCH 1/2] get_sha1_oneline: allow to input commit_list","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2010-12-13T00:29:06Z","receivedAt":"2010-12-13T00:29:06Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Nguyễn Thái Ngọc Duy  <pclouds@gmail.com> writes:\n\n> Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n> ---\n>  sha1_name.c |   13 ++++++++++---\n>  1 files changed, 10 insertions(+), 3 deletions(-)\n>\n> diff --git a/sha1_name.c b/sha1_name.c\n> index 2c3a5fb..c298285 100644\n> --- a/sha1_name.c\n> +++ b/sha1_name.c\n> @@ -690,7 +690,9 @@ static int handle_one_ref(const char *path,\n>  \treturn 0;\n>  }\n>  \n> -static int get_sha1_oneline(const char *prefix, unsigned char *sha1)\n> +static int get_sha1_oneline(const char *prefix,\n> +\t\t\t    unsigned char *sha1,\n> +\t\t\t    struct commit_list *original_list)\n>  {\n>  \tstruct commit_list *list = NULL, *backup = NULL, *l;\n>  \tint retval = -1;\n> @@ -706,7 +708,12 @@ static int get_sha1_oneline(const char *prefix, unsigned char *sha1)\n>  \tif (regcomp(&regex, prefix, REG_EXTENDED))\n>  \t\tdie(\"Invalid search pattern: %s\", prefix);\n>  \n> -\tfor_each_ref(handle_one_ref, &list);\n> +\tfor (l = original_list; l; l = l->next) {\n> +\t\tcommit_list_insert(l->item, &list);\n> +\t\tl->item->object.flags |= ONELINE_SEEN;\n> +\t}\n> +\tif (!list)\n> +\t\tfor_each_ref(handle_one_ref, &list);\n\nTwo-and-half yucks.\n\n (1) \"We work on the list you give us, if you give us one, but we work on\n     a list we come up with outselves in a magic way otherwise\" is an API\n     designed with a bad taste.  Why not make the original caller run\n     for-each-ref before calling this function?\n\n (2) Why do you have to copy the list, using commit-list-insert, here?\n\n (3) Even if the above extra copy turns out to be needed, do you need yet\n     another copy in \"backup\"?\n\nInstead of this patch, I would suggest to go this route:\n\n * Remove local varaible \"list\" and make it an input parameter.\n\n * Stop calling for-each-ref from this function.  Instead, have the\n   current caller run for-each-ref to prepare list and feed it to you;\n\n * Stop marking commits with \"ONELINE_SEEN\" from handle-one-ref.  Instead,\n   have the loop to copy list to backup do the marking.\n\nThat way, you make the purpose of the function much more clear.  It gets a\nlist of one or more commits that are in date-order, and finds the most\nrecent commit reachable from them that match the given string, using\nONELINE_SEEN bit as a scratchpad (shouldn't we be using TMP_MARK here, by\nthe way?).  The caller is responsible for giving you a sorted list, but\nthe caller shouldn't care about ONELINE_SEEN bit.\n"}]}