{"thread":{"id":"39759","subject":"[PATCH] fast-import: add a get-mark command","startedAt":"2015-07-01T15:05:58Z","lastAt":"2015-07-01T15:05:58Z","messageCount":1,"participants":["Michael Haggerty"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"265322","messageId":"38cd45cb4930c4af8f8224c44064af99b2900260.1435762878.git.mhagger@alum.mit.edu","threadId":"39759","inReplyTo":null,"subject":"[PATCH] fast-import: add a get-mark command","fromName":"Michael Haggerty","fromEmail":"mhagger@alum.mit.edu","sentAt":"2015-07-01T15:05:58Z","receivedAt":"2015-07-01T15:05:58Z","isPatch":true,"sender":{"key":"mhagger@alum.mit.edu","avatar":"https://avatars.githubusercontent.com/u/119718?v=4"},"body":"It is sometimes useful for importers to be able to read the SHA-1\ncorresponding to a mark that they have created via fast-import. For\nexample, they might want to embed the SHA-1 into the commit message of\na later commit. Or it might be useful for internal bookkeeping uses,\nor for logging.\n\nAdd a \"get-mark\" command to \"git fast-import\" that allows the importer\nto ask for the value of a mark that has been created earlier.\n\nSigned-off-by: Michael Haggerty <mhagger@alum.mit.edu>\n---\nThis is something that we need for an internal GitHub project, but I\nthink it will also be of general interest.\n\n Documentation/git-fast-import.txt | 39 +++++++++++++++++++++++++++++++++------\n fast-import.c                     | 33 +++++++++++++++++++++++++++++----\n t/t9300-fast-import.sh            | 13 +++++++++++++\n 3 files changed, 75 insertions(+), 10 deletions(-)\n\ndiff --git a/Documentation/git-fast-import.txt b/Documentation/git-fast-import.txt\nindex fd32895..66910aa 100644\n--- a/Documentation/git-fast-import.txt\n+++ b/Documentation/git-fast-import.txt\n@@ -54,7 +54,7 @@ Options for Frontends\n ~~~~~~~~~~~~~~~~~~~~~\n \n --cat-blob-fd=<fd>::\n-\tWrite responses to `cat-blob` and `ls` queries to the\n+\tWrite responses to `get-mark`, `cat-blob`, and `ls` queries to the\n \tfile descriptor <fd> instead of `stdout`.  Allows `progress`\n \toutput intended for the end-user to be separated from other\n \toutput.\n@@ -350,6 +350,11 @@ and control the current import process.  More detailed discussion\n \tunless the `done` feature was requested using the\n \t`--done` command-line option or `feature done` command.\n \n+`get-mark`::\n+\tCauses fast-import to print the SHA-1 corresponding to a mark\n+\tto the file descriptor set with `--cat-blob-fd`, or `stdout` if\n+\tunspecified.\n+\n `cat-blob`::\n \tCauses fast-import to print a blob in 'cat-file --batch'\n \tformat to the file descriptor set with `--cat-blob-fd` or\n@@ -930,6 +935,25 @@ Placing a `progress` command immediately after a `checkpoint` will\n inform the reader when the `checkpoint` has been completed and it\n can safely access the refs that fast-import updated.\n \n+`get-mark`\n+~~~~~~~~~~\n+Causes fast-import to print the SHA-1 corresponding to a mark to\n+stdout or to the file descriptor previously arranged with the\n+`--cat-blob-fd` argument. The command otherwise has no impact on the\n+current import; its purpose is to retrieve SHA-1s that later commits\n+might want to refer to in their commit messages.\n+\n+....\n+\t'get-mark' SP ':' <idnum> LF\n+....\n+\n+This command can be used anywhere in the stream that comments are\n+accepted.  In particular, the `get-mark` command can be used in the\n+middle of a commit but not in the middle of a `data` command.\n+\n+See ``Responses To Commands'' below for details about how to read\n+this output safely.\n+\n `cat-blob`\n ~~~~~~~~~~\n Causes fast-import to print a blob to a file descriptor previously\n@@ -1000,7 +1024,8 @@ Output uses the same format as `git ls-tree <tree> -- <path>`:\n ====\n \n The <dataref> represents the blob, tree, or commit object at <path>\n-and can be used in later 'cat-blob', 'filemodify', or 'ls' commands.\n+and can be used in later 'get-mark', 'cat-blob', 'filemodify', or\n+'ls' commands.\n \n If there is no file or subtree at that path, 'git fast-import' will\n instead report\n@@ -1042,9 +1067,11 @@ import-marks-if-exists::\n \t\"feature import-marks-if-exists\" like a corresponding\n \tcommand-line option silently skips a nonexistent file.\n \n+get-mark::\n cat-blob::\n ls::\n-\tRequire that the backend support the 'cat-blob' or 'ls' command.\n+\tRequire that the backend support the 'get-mark', 'cat-blob',\n+\tor 'ls' command respectively.\n \tVersions of fast-import not supporting the specified command\n \twill exit with a message indicating so.\n \tThis lets the import error out early with a clear message,\n@@ -1124,11 +1151,11 @@ bidirectional pipes:\n \tgit fast-import >fast-import-output\n ====\n \n-A frontend set up this way can use `progress`, `ls`, and `cat-blob`\n-commands to read information from the import in progress.\n+A frontend set up this way can use `progress`, `get-mark`, `ls`, and\n+`cat-blob` commands to read information from the import in progress.\n \n To avoid deadlock, such frontends must completely consume any\n-pending output from `progress`, `ls`, and `cat-blob` before\n+pending output from `progress`, `ls`, `get-mark`, and `cat-blob` before\n performing writes to fast-import that might block.\n \n Crash Reports\ndiff --git a/fast-import.c b/fast-import.c\nindex 6378726..1ba83d6 100644\n--- a/fast-import.c\n+++ b/fast-import.c\n@@ -134,16 +134,17 @@ Format of STDIN stream:\n   ts    ::= # time since the epoch in seconds, ascii base10 notation;\n   tz    ::= # GIT style timezone;\n \n-     # note: comments, ls and cat requests may appear anywhere\n-     # in the input, except within a data command.  Any form\n-     # of the data command always escapes the related input\n-     # from comment processing.\n+     # note: comments, get-mark, ls-tree, and cat-blob requests may\n+     # appear anywhere in the input, except within a data command. Any\n+     # form of the data command always escapes the related input from\n+     # comment processing.\n      #\n      # In case it is not clear, the '#' that starts the comment\n      # must be the first character on that line (an lf\n      # preceded it).\n      #\n \n+  get_mark ::= 'get-mark' sp idnum lf;\n   cat_blob ::= 'cat-blob' sp (hexsha1 | idnum) lf;\n   ls_tree  ::= 'ls' sp (hexsha1 | idnum) sp path_str lf;\n \n@@ -372,6 +373,7 @@ static volatile sig_atomic_t checkpoint_requested;\n static int cat_blob_fd = STDOUT_FILENO;\n \n static void parse_argv(void);\n+static void parse_get_mark(const char *p);\n static void parse_cat_blob(const char *p);\n static void parse_ls(const char *p, struct branch *b);\n \n@@ -1907,6 +1909,10 @@ static int read_next_command(void)\n \t\t\trc->prev->next = rc;\n \t\t\tcmd_tail = rc;\n \t\t}\n+\t\tif (skip_prefix(command_buf.buf, \"get-mark \", &p)) {\n+\t\t\tparse_get_mark(p);\n+\t\t\tcontinue;\n+\t\t}\n \t\tif (skip_prefix(command_buf.buf, \"cat-blob \", &p)) {\n \t\t\tparse_cat_blob(p);\n \t\t\tcontinue;\n@@ -2919,6 +2925,23 @@ static void cat_blob(struct object_entry *oe, unsigned char sha1[20])\n \t\tfree(buf);\n }\n \n+static void parse_get_mark(const char *p)\n+{\n+\tstruct object_entry *oe = oe;\n+\tchar output[42];\n+\n+\t/* get-mark SP <object> LF */\n+\tif (*p != ':')\n+\t\tdie(\"Not a mark: %s\", p);\n+\n+\toe = find_mark(parse_mark_ref_eol(p));\n+\tif (!oe)\n+\t\tdie(\"Unknown mark: %s\", command_buf.buf);\n+\n+\tsnprintf(output, sizeof(output), \"%s\\n\", sha1_to_hex(oe->idx.sha1));\n+\tcat_blob_write(output, 41);\n+}\n+\n static void parse_cat_blob(const char *p)\n {\n \tstruct object_entry *oe = oe;\n@@ -3240,6 +3263,8 @@ static int parse_one_feature(const char *feature, int from_stream)\n \t\toption_import_marks(arg, from_stream, 1);\n \t} else if (skip_prefix(feature, \"export-marks=\", &arg)) {\n \t\toption_export_marks(arg);\n+\t} else if (!strcmp(feature, \"get-mark\")) {\n+\t\t; /* Don't die - this feature is supported */\n \t} else if (!strcmp(feature, \"cat-blob\")) {\n \t\t; /* Don't die - this feature is supported */\n \t} else if (!strcmp(feature, \"relative-marks\")) {\ndiff --git a/t/t9300-fast-import.sh b/t/t9300-fast-import.sh\nindex aac126f..9984c48 100755\n--- a/t/t9300-fast-import.sh\n+++ b/t/t9300-fast-import.sh\n@@ -2339,6 +2339,19 @@ test_expect_success !MINGW 'R: in-stream cat-blob-fd not respected' '\n \ttest_cmp expect actual.1\n '\n \n+test_expect_success !MINGW 'R: print mark for new blob' '\n+\techo \"effluentish\" | git hash-object --stdin >expect &&\n+\tgit fast-import --cat-blob-fd=6 6>actual <<-\\EOF &&\n+\tblob\n+\tmark :1\n+\tdata <<BLOB_END\n+\teffluentish\n+\tBLOB_END\n+\tget-mark :1\n+\tEOF\n+\ttest_cmp expect actual\n+'\n+\n test_expect_success !MINGW 'R: print new blob' '\n \tblob=$(echo \"yep yep yep\" | git hash-object --stdin) &&\n \tcat >expect <<-EOF &&\n-- \n2.1.4\n"}]}