@matheusbsbs / matheus-bagliano / commits / 348f199b2d
Fork 0

builtin-notes: Refactor handling of -F option to allow combining -m and -F

By moving the -F option handling into a separate function (parse_file_arg), we can start allowing several -F options, and mixed usage of -m and -F options. Each -m/-F given appends to the note message, in the order they are given on the command-line. The patch includes tests verifying correct behaviour of the new functionality. Signed-off-by: Johan Herland <johan@herland.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Johan Herland committed Feb 13, 2010 at 22:28 UTC 348f199b2d9250a82453323c90b7e8d3d9462220
2 files changed +73 -44
builtin-notes.c
+51 -43
@@ -34,6 +34,11 @@ static const char note_template[] =
34 "# Write/edit the notes for the following object:\n"
35 "#\n";
36
37 +struct msg_arg {
38 + int given;
39 + struct strbuf buf;
40 +};
41 +
42 static int list_each_note(const unsigned char *object_sha1,
43 const unsigned char *note_sha1, char *note_path,
44 void *cb_data)
@@ -93,15 +98,13 @@ static void write_commented_object(int fd, const unsigned char *object)
98 sha1_to_hex(object));
99 }
100
96 -static void create_note(const unsigned char *object,
97 - struct strbuf *buf,
98 - int skip_editor, int append_only,
99 - const unsigned char *prev,
101 +static void create_note(const unsigned char *object, struct msg_arg *msg,
102 + int append_only, const unsigned char *prev,
103 unsigned char *result)
104 {
105 char *path = NULL;
106
104 - if (!skip_editor) {
107 + if (!msg->given) {
108 int fd;
109
110 /* write the template message before editing: */
@@ -118,34 +121,33 @@ static void create_note(const unsigned char *object,
121
122 close(fd);
123
121 - if (launch_editor(path, buf, NULL)) {
124 + if (launch_editor(path, &(msg->buf), NULL)) {
125 die("Please supply the note contents using either -m" \
126 " or -F option");
127 }
128 + stripspace(&(msg->buf), 1);
129 }
130
127 - stripspace(buf, 1);
128 -
131 if (prev && append_only) {
132 /* Append buf to previous note contents */
133 unsigned long size;
134 enum object_type type;
135 char *prev_buf = read_sha1_file(prev, &type, &size);
136
135 - strbuf_grow(buf, size + 1);
136 - if (buf->len && prev_buf && size)
137 - strbuf_insert(buf, 0, "\n", 1);
137 + strbuf_grow(&(msg->buf), size + 1);
138 + if (msg->buf.len && prev_buf && size)
139 + strbuf_insert(&(msg->buf), 0, "\n", 1);
140 if (prev_buf && size)
139 - strbuf_insert(buf, 0, prev_buf, size);
141 + strbuf_insert(&(msg->buf), 0, prev_buf, size);
142 free(prev_buf);
143 }
144
143 - if (!buf->len) {
145 + if (!msg->buf.len) {
146 fprintf(stderr, "Removing note for object %s\n",
147 sha1_to_hex(object));
148 hashclr(result);
149 } else {
148 - if (write_sha1_file(buf->buf, buf->len, blob_type, result)) {
150 + if (write_sha1_file(msg->buf.buf, msg->buf.len, blob_type, result)) {
151 error("unable to write note object");
152 if (path)
153 error("The note contents has been left in %s",
@@ -160,20 +162,39 @@ static void create_note(const unsigned char *object,
162 }
163 }
164
163 -struct msg_arg {
164 - int given;
165 - struct strbuf buf;
166 -};
167 -
165 static int parse_msg_arg(const struct option *opt, const char *arg, int unset)
166 {
167 struct msg_arg *msg = opt->value;
168
169 if (!arg)
170 return -1;
171 +
172 + strbuf_grow(&(msg->buf), strlen(arg) + 2);
173 if (msg->buf.len)
175 - strbuf_addstr(&(msg->buf), "\n\n");
174 + strbuf_addstr(&(msg->buf), "\n");
175 strbuf_addstr(&(msg->buf), arg);
176 + stripspace(&(msg->buf), 0);
177 +
178 + msg->given = 1;
179 + return 0;
180 +}
181 +
182 +static int parse_file_arg(const struct option *opt, const char *arg, int unset)
183 +{
184 + struct msg_arg *msg = opt->value;
185 +
186 + if (!arg)
187 + return -1;
188 +
189 + if (msg->buf.len)
190 + strbuf_addstr(&(msg->buf), "\n");
191 + if (!strcmp(arg, "-")) {
192 + if (strbuf_read(&(msg->buf), 0, 1024) < 0)
193 + die_errno("cannot read '%s'", arg);
194 + } else if (strbuf_read_file(&(msg->buf), arg, 1024) < 0)
195 + die_errno("could not open or read '%s'", arg);
196 + stripspace(&(msg->buf), 0);
197 +
198 msg->given = 1;
199 return 0;
200 }
@@ -220,7 +241,6 @@ int commit_notes(struct notes_tree *t, const char *msg)
241
242 int cmd_notes(int argc, const char **argv, const char *prefix)
243 {
223 - struct strbuf buf = STRBUF_INIT;
244 struct notes_tree *t;
245 unsigned char object[20], new_note[20];
246 const unsigned char *note;
@@ -230,13 +250,13 @@ int cmd_notes(int argc, const char **argv, const char *prefix)
250 int list = 0, add = 0, append = 0, edit = 0, show = 0, remove = 0,
251 prune = 0, force = 0;
252 int given_object;
233 - const char *msgfile = NULL;
253 struct msg_arg msg = { 0, STRBUF_INIT };
254 struct option options[] = {
255 OPT_GROUP("Notes options"),
237 - OPT_CALLBACK('m', "message", &msg, "msg",
256 + OPT_CALLBACK('m', "message", &msg, "MSG",
257 "note contents as a string", parse_msg_arg),
239 - OPT_FILENAME('F', "file", &msgfile, "note contents in a file"),
258 + OPT_CALLBACK('F', "file", &msg, "FILE",
259 + "note contents in a file", parse_file_arg),
260 OPT_BOOLEAN('f', "force", &force, "replace existing notes"),
261 OPT_END()
262 };
@@ -265,21 +285,17 @@ int cmd_notes(int argc, const char **argv, const char *prefix)
285 if (list + add + append + edit + show + remove + prune != 1)
286 usage_with_options(git_notes_usage, options);
287
268 - if ((msg.given || msgfile) && !(add || append || edit)) {
288 + if (msg.given && !(add || append || edit)) {
289 error("cannot use -m/-F options with %s subcommand.", argv[0]);
290 usage_with_options(git_notes_usage, options);
291 }
292
273 - if ((msg.given || msgfile) && edit) {
293 + if (msg.given && edit) {
294 fprintf(stderr, "The -m and -F options has been deprecated for"
295 " the 'edit' subcommand.\n"
296 "Please use 'git notes add -f -m/-F' instead.\n");
297 }
298
279 - if (msg.given && msgfile) {
280 - error("mixing -m and -F options is not allowed.");
281 - usage_with_options(git_notes_usage, options);
282 - }
299
300 if (force && !add) {
301 error("cannot use -f option with %s subcommand.", argv[0]);
@@ -341,24 +357,16 @@ int cmd_notes(int argc, const char **argv, const char *prefix)
357 }
358 }
359
344 - if (remove)
345 - strbuf_reset(&buf);
346 - else if (msg.given)
347 - strbuf_addbuf(&buf, &(msg.buf));
348 - else if (msgfile) {
349 - if (!strcmp(msgfile, "-")) {
350 - if (strbuf_read(&buf, 0, 1024) < 0)
351 - die_errno("cannot read '%s'", msgfile);
352 - } else if (strbuf_read_file(&buf, msgfile, 1024) < 0)
353 - die_errno("could not open or read '%s'", msgfile);
360 + if (remove) {
361 + msg.given = 1;
362 + strbuf_reset(&(msg.buf));
363 }
364
365 if (prune) {
366 hashclr(new_note);
367 prune_notes(t);
368 } else {
360 - create_note(object, &buf, msg.given || msgfile || remove,
361 - append, note, new_note);
369 + create_note(object, &msg, append, note, new_note);
370 if (is_null_sha1(new_note))
371 remove_note(t, object);
372 else
@@ -369,6 +377,6 @@ int cmd_notes(int argc, const char **argv, const char *prefix)
377 commit_notes(t, logmsg);
378
379 free_notes(t);
372 - strbuf_release(&buf);
380 + strbuf_release(&(msg.buf));
381 return 0;
382 }
t/t3301-notes.sh
+22 -1
@@ -284,8 +284,29 @@ test_expect_success 'verify non-creation of note with -m ""' '
284 ! git notes show
285 '
286
287 +cat > expect-combine_m_and_F << EOF
288 +foo
289 +
290 +xyzzy
291 +
292 +bar
293 +
294 +zyxxy
295 +
296 +baz
297 +EOF
298 +
299 +test_expect_success 'create note with combination of -m and -F' '
300 + echo "xyzzy" > note_a &&
301 + echo "zyxxy" > note_b &&
302 + git notes add -m "foo" -F note_a -m "bar" -F note_b -m "baz" &&
303 + git notes show > output &&
304 + test_cmp expect-combine_m_and_F output
305 +'
306 +
307 test_expect_success 'remove note with "git notes remove" (setup)' '
288 - git notes remove HEAD^
308 + git notes remove HEAD^ &&
309 + git notes remove
310 '
311
312 cat > expect-rm-remove << EOF