{"thread":{"id":"26123","subject":"[PATCH/RFC] get_sha1: allow users to extend ..^{%..} syntax","startedAt":"2010-12-22T15:33:46Z","lastAt":"2010-12-22T15:33:46Z","messageCount":1,"participants":["Nguyễn Thái Ngọc Duy"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"158491","messageId":"1293032026-32704-1-git-send-email-pclouds@gmail.com","threadId":"26123","inReplyTo":null,"subject":"[PATCH/RFC] get_sha1: allow users to extend ..^{%..} syntax","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2010-12-22T15:33:46Z","receivedAt":"2010-12-22T15:33:46Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"This allows users to add abitrary sth^{%foo} syntax that translates\nfrom an SHA-1 to another SHA-1, where \"foo\" refers to an alias\n\"sha1-foo\" or \"foo\". If either is found, %sha1% in the alias will be\nreplaced with SHA-1 of \"sth\". The alias command is supposed to print\ntranslated SHA-1 to stdout.\n\nAnother syntax is sth^{%foo:args} where %arg% in the alias will be\nreplaced with \"args\" from the syntax. This gives users much more\nflexibilty in extending SHA-1 syntax. I'm not sure if I should support\nmultiple arguments though.\n\nMy mind is still with the :/ syntax. So as an example,\n\ngit config alias.sha1-topic 'rev-list --merges --grep=%arg% --max-count=1 %sha1%'\ngit rev-parse origin/pu^{%topic:nd/struct-pathspec}\n\nwould give me sha-1 of my topic. This is supposed to be faster than\nstandard :/ syntax because it only searches merges. I can also make it\nmore accurate to my liking by adjust --grep= freely. Unfortunately\ngit-rev-list takes ~1 sec to run. Maybe I can detect rev-list command\nand run it internally without run_command().\n\nThe intention is that a similar syntax can be used for branch\ntranslation too, i.e ref@{%...}.\n\nOne of the rising issues is that every time this syntax is evaluated,\nexternal process will be run again. Some cache might help. I should\nalso take alias code out of git.c for reuse here.\n\nSo comments? (This patch looks bad, I know)\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n sha1_name.c |   87 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n 1 files changed, 87 insertions(+), 0 deletions(-)\n\ndiff --git a/sha1_name.c b/sha1_name.c\nindex c5c59ce..6b40cec 100644\n--- a/sha1_name.c\n+++ b/sha1_name.c\n@@ -6,6 +6,7 @@\n #include \"tree-walk.h\"\n #include \"refs.h\"\n #include \"remote.h\"\n+#include \"run-command.h\"\n \n static int get_sha1_oneline(const char *, unsigned char *, struct commit_list *);\n \n@@ -529,6 +530,86 @@ struct object *peel_to_type(const char *name, int namelen,\n \t}\n }\n \n+static int peel_alias_onion(const char *name, int len, const char *sp,\n+\t\t\t    unsigned char *sha1)\n+{\n+\tint alias_len;\n+\tstruct strbuf sb = STRBUF_INIT;\n+\tstruct strbuf cmd = STRBUF_INIT;\n+\tstruct child_process cp;\n+\tconst char **argv;\n+\tint count, hex_len;\n+\tchar *s, *arg;\n+\tchar hex[40];\n+\n+\tlen--;\t\t\t/* remove the last '}' */\n+\targ = strchr(sp, ':');\n+\tif (arg)\n+\t\talias_len = arg - sp;\n+\telse\n+\t\talias_len = len - (sp - name);\n+\tstrbuf_add(&sb, \"sha1-\", 5);\n+\tstrbuf_add(&sb, sp, alias_len);\n+\ts = alias_lookup(sb.buf);\n+\tif (!s) {\n+\t\tstrbuf_reset(&sb);\n+\t\tstrbuf_add(&sb, sp, alias_len);\n+\t\ts = alias_lookup(sb.buf);\n+\t}\n+\tstrbuf_release(&sb);\n+\tif (!s)\n+\t\treturn error(\"unable to find alias for %s\", name);\n+\n+\tstrbuf_attach(&cmd, s, strlen(s), strlen(s)+1);\n+\ts = strstr(cmd.buf, \"%sha1%\");\n+\tif (!s) {\n+\t\terror(\"%%sha1%% not found, not an sha1 alias:\\n%s\", cmd.buf);\n+\t\tstrbuf_release(&cmd);\n+\t\treturn -1;\n+\t}\n+\tstrbuf_splice(&cmd, s - cmd.buf, 6, sha1_to_hex(sha1), 40);\n+\tif (arg) {\n+\t\tint arg_len = len - (++arg - name);\n+\t\ts = strstr(cmd.buf, \"%arg%\");\n+\t\tif (!s) {\n+\t\t\terror(\"%%arg%% not found, not an sha1 alias:\\n%s\", cmd.buf);\n+\t\t\tstrbuf_release(&cmd);\n+\t\t\treturn -1;\n+\t\t}\n+\t\tstrbuf_splice(&cmd, s - cmd.buf, 5, arg, arg_len);\n+\t}\n+\n+\tcount = split_cmdline(cmd.buf, &argv);\n+\tif (count < 0) {\n+\t\terror(\"Bad alias.%s string: %s\", cmd.buf, split_cmdline_strerror(count));\n+\t\tstrbuf_release(&cmd);\n+\t\treturn -1;\n+\t}\n+\n+\tmemset(&cp, 0, sizeof(cp));\n+\tcp.git_cmd = 1;\n+\tcp.in = 0;\n+\tcp.out = -1;\n+\tcp.argv = argv;\n+\ttrace_argv_printf(argv, \"trace: sha1 alias expansion: %s =>\", cmd.buf);\n+\tif (start_command(&cp)) {\n+\t\terror(\"Failed to run %s\", cmd.buf);\n+\t\tstrbuf_release(&cmd);\n+\t\treturn -1;\n+\t}\n+\thex_len = xread(cp.out, hex, 40);\n+\tclose(cp.out);\n+\tif (finish_command(&cp)) {\n+\t\terror(\"Failed to finish %s\", cmd.buf);\n+\t\tstrbuf_release(&cmd);\n+\t\treturn -1;\n+\t}\n+\tstrbuf_release(&cmd);\n+\tif (hex_len != 40 || get_sha1_hex(hex, sha1))\n+\t\treturn error(\"failed to get result SHA-1 from ...%s\", sp-3);\n+\treturn 0;\n+}\n+\n static int peel_onion(const char *name, int len, unsigned char *sha1)\n {\n \tunsigned char outer[20];\n@@ -566,6 +647,12 @@ static int peel_onion(const char *name, int len, unsigned char *sha1)\n \t\texpected_type = OBJ_NONE;\n \telse if (sp[0] == '/')\n \t\texpected_type = OBJ_COMMIT;\n+\telse if (sp[0] == '%') {\n+\t\tif (get_sha1_1(name, sp - name - 2, outer))\n+\t\t\treturn -1;\n+\t\thashcpy(sha1, outer);\n+\t\treturn peel_alias_onion(name, len, sp + 1, sha1);\n+\t}\n \telse\n \t\treturn -1;\n \n-- \n1.7.3.3.476.g10a82\n"}]}