fast-import: add a get-mark command

It is sometimes useful for importers to be able to read the SHA-1 corresponding to a mark that they have created via fast-import. For example, they might want to embed the SHA-1 into the commit message of a later commit. Or it might be useful for internal bookkeeping uses, or for logging. Add a "get-mark" command to "git fast-import" that allows the importer to ask for the value of a mark that has been created earlier. Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Michael Haggerty committed Jul 1, 2015 at 17:05 UTC 28c7b1f7b7b70013c2f380c2d720d0c918d3d83a
3 files changed +75 -10
Documentation/git-fast-import.txt
+33 -6
@@ -54,7 +54,7 @@ Options for Frontends
54 ~~~~~~~~~~~~~~~~~~~~~
55
56 --cat-blob-fd=<fd>::
57 - Write responses to `cat-blob` and `ls` queries to the
57 + Write responses to `get-mark`, `cat-blob`, and `ls` queries to the
58 file descriptor <fd> instead of `stdout`. Allows `progress`
59 output intended for the end-user to be separated from other
60 output.
@@ -350,6 +350,11 @@ and control the current import process. More detailed discussion
350 unless the `done` feature was requested using the
351 `--done` command-line option or `feature done` command.
352
353 +`get-mark`::
354 + Causes fast-import to print the SHA-1 corresponding to a mark
355 + to the file descriptor set with `--cat-blob-fd`, or `stdout` if
356 + unspecified.
357 +
358 `cat-blob`::
359 Causes fast-import to print a blob in 'cat-file --batch'
360 format to the file descriptor set with `--cat-blob-fd` or
@@ -930,6 +935,25 @@ Placing a `progress` command immediately after a `checkpoint` will
935 inform the reader when the `checkpoint` has been completed and it
936 can safely access the refs that fast-import updated.
937
938 +`get-mark`
939 +~~~~~~~~~~
940 +Causes fast-import to print the SHA-1 corresponding to a mark to
941 +stdout or to the file descriptor previously arranged with the
942 +`--cat-blob-fd` argument. The command otherwise has no impact on the
943 +current import; its purpose is to retrieve SHA-1s that later commits
944 +might want to refer to in their commit messages.
945 +
946 +....
947 + 'get-mark' SP ':' <idnum> LF
948 +....
949 +
950 +This command can be used anywhere in the stream that comments are
951 +accepted. In particular, the `get-mark` command can be used in the
952 +middle of a commit but not in the middle of a `data` command.
953 +
954 +See ``Responses To Commands'' below for details about how to read
955 +this output safely.
956 +
957 `cat-blob`
958 ~~~~~~~~~~
959 Causes fast-import to print a blob to a file descriptor previously
@@ -1000,7 +1024,8 @@ Output uses the same format as `git ls-tree <tree> -- <path>`:
1024 ====
1025
1026 The <dataref> represents the blob, tree, or commit object at <path>
1003 -and can be used in later 'cat-blob', 'filemodify', or 'ls' commands.
1027 +and can be used in later 'get-mark', 'cat-blob', 'filemodify', or
1028 +'ls' commands.
1029
1030 If there is no file or subtree at that path, 'git fast-import' will
1031 instead report
@@ -1042,9 +1067,11 @@ import-marks-if-exists::
1067 "feature import-marks-if-exists" like a corresponding
1068 command-line option silently skips a nonexistent file.
1069
1070 +get-mark::
1071 cat-blob::
1072 ls::
1047 - Require that the backend support the 'cat-blob' or 'ls' command.
1073 + Require that the backend support the 'get-mark', 'cat-blob',
1074 + or 'ls' command respectively.
1075 Versions of fast-import not supporting the specified command
1076 will exit with a message indicating so.
1077 This lets the import error out early with a clear message,
@@ -1124,11 +1151,11 @@ bidirectional pipes:
1151 git fast-import >fast-import-output
1152 ====
1153
1127 -A frontend set up this way can use `progress`, `ls`, and `cat-blob`
1128 -commands to read information from the import in progress.
1154 +A frontend set up this way can use `progress`, `get-mark`, `ls`, and
1155 +`cat-blob` commands to read information from the import in progress.
1156
1157 To avoid deadlock, such frontends must completely consume any
1131 -pending output from `progress`, `ls`, and `cat-blob` before
1158 +pending output from `progress`, `ls`, `get-mark`, and `cat-blob` before
1159 performing writes to fast-import that might block.
1160
1161 Crash Reports
fast-import.c
+29 -4
@@ -134,16 +134,17 @@ Format of STDIN stream:
134 ts ::= # time since the epoch in seconds, ascii base10 notation;
135 tz ::= # GIT style timezone;
136
137 - # note: comments, ls and cat requests may appear anywhere
138 - # in the input, except within a data command. Any form
139 - # of the data command always escapes the related input
140 - # from comment processing.
137 + # note: comments, get-mark, ls-tree, and cat-blob requests may
138 + # appear anywhere in the input, except within a data command. Any
139 + # form of the data command always escapes the related input from
140 + # comment processing.
141 #
142 # In case it is not clear, the '#' that starts the comment
143 # must be the first character on that line (an lf
144 # preceded it).
145 #
146
147 + get_mark ::= 'get-mark' sp idnum lf;
148 cat_blob ::= 'cat-blob' sp (hexsha1 | idnum) lf;
149 ls_tree ::= 'ls' sp (hexsha1 | idnum) sp path_str lf;
150
@@ -372,6 +373,7 @@ static volatile sig_atomic_t checkpoint_requested;
373 static int cat_blob_fd = STDOUT_FILENO;
374
375 static void parse_argv(void);
376 +static void parse_get_mark(const char *p);
377 static void parse_cat_blob(const char *p);
378 static void parse_ls(const char *p, struct branch *b);
379
@@ -1907,6 +1909,10 @@ static int read_next_command(void)
1909 rc->prev->next = rc;
1910 cmd_tail = rc;
1911 }
1912 + if (skip_prefix(command_buf.buf, "get-mark ", &p)) {
1913 + parse_get_mark(p);
1914 + continue;
1915 + }
1916 if (skip_prefix(command_buf.buf, "cat-blob ", &p)) {
1917 parse_cat_blob(p);
1918 continue;
@@ -2919,6 +2925,23 @@ static void cat_blob(struct object_entry *oe, unsigned char sha1[20])
2925 free(buf);
2926 }
2927
2928 +static void parse_get_mark(const char *p)
2929 +{
2930 + struct object_entry *oe = oe;
2931 + char output[42];
2932 +
2933 + /* get-mark SP <object> LF */
2934 + if (*p != ':')
2935 + die("Not a mark: %s", p);
2936 +
2937 + oe = find_mark(parse_mark_ref_eol(p));
2938 + if (!oe)
2939 + die("Unknown mark: %s", command_buf.buf);
2940 +
2941 + snprintf(output, sizeof(output), "%s\n", sha1_to_hex(oe->idx.sha1));
2942 + cat_blob_write(output, 41);
2943 +}
2944 +
2945 static void parse_cat_blob(const char *p)
2946 {
2947 struct object_entry *oe = oe;
@@ -3243,6 +3266,8 @@ static int parse_one_feature(const char *feature, int from_stream)
3266 option_import_marks(arg, from_stream, 1);
3267 } else if (skip_prefix(feature, "export-marks=", &arg)) {
3268 option_export_marks(arg);
3269 + } else if (!strcmp(feature, "get-mark")) {
3270 + ; /* Don't die - this feature is supported */
3271 } else if (!strcmp(feature, "cat-blob")) {
3272 ; /* Don't die - this feature is supported */
3273 } else if (!strcmp(feature, "relative-marks")) {
t/t9300-fast-import.sh
+13
@@ -2339,6 +2339,19 @@ test_expect_success !MINGW 'R: in-stream cat-blob-fd not respected' '
2339 test_cmp expect actual.1
2340 '
2341
2342 +test_expect_success !MINGW 'R: print mark for new blob' '
2343 + echo "effluentish" | git hash-object --stdin >expect &&
2344 + git fast-import --cat-blob-fd=6 6>actual <<-\EOF &&
2345 + blob
2346 + mark :1
2347 + data <<BLOB_END
2348 + effluentish
2349 + BLOB_END
2350 + get-mark :1
2351 + EOF
2352 + test_cmp expect actual
2353 +'
2354 +
2355 test_expect_success !MINGW 'R: print new blob' '
2356 blob=$(echo "yep yep yep" | git hash-object --stdin) &&
2357 cat >expect <<-EOF &&