Commit 160baa0d authored by Thomas Rast's avatar Thomas Rast Committed by Junio C Hamano

notes: implement 'git notes copy --stdin'

This implements a mass-copy command that takes a sequence of lines in
the format

  <from-sha1> SP <to-sha1> [ SP <rest> ] LF

on stdin, and copies each <from-sha1>'s notes to the <to-sha1>.  The
<rest> is ignored.  The intent, of course, is that this can read the
same input that the 'post-rewrite' hook gets.

The copy_note() function is exposed for everyone's and in particular
the next commit's use.
Signed-off-by: default avatarThomas Rast <[email protected]>
Acked-by: default avatarJohan Herland <[email protected]>
Signed-off-by: default avatarJunio C Hamano <[email protected]>
parent b079feed
......@@ -10,7 +10,7 @@ SYNOPSIS
[verse]
'git notes' [list [<object>]]
'git notes' add [-f] [-F <file> | -m <msg> | (-c | -C) <object>] [<object>]
'git notes' copy [-f] <from-object> <to-object>
'git notes' copy [-f] ( --stdin | <from-object> <to-object> )
'git notes' append [-F <file> | -m <msg> | (-c | -C) <object>] [<object>]
'git notes' edit [<object>]
'git notes' show [<object>]
......@@ -56,6 +56,16 @@ copy::
objects has none. (use -f to overwrite existing notes to the
second object). This subcommand is equivalent to:
`git notes add [-f] -C $(git notes list <from-object>) <to-object>`
+
In `\--stdin` mode, take lines in the format
+
----------
<from-object> SP <to-object> [ SP <rest> ] LF
----------
+
on standard input, and copy the notes from each <from-object> to its
corresponding <to-object>. (The optional `<rest>` is ignored so that
the command can read the input given to the `post-rewrite` hook.)
append::
Append to the notes of an existing object (defaults to HEAD).
......
......@@ -278,6 +278,46 @@ int commit_notes(struct notes_tree *t, const char *msg)
return 0;
}
int notes_copy_from_stdin(int force)
{
struct strbuf buf = STRBUF_INIT;
struct notes_tree *t;
int ret = 0;
init_notes(NULL, NULL, NULL, 0);
t = &default_notes_tree;
while (strbuf_getline(&buf, stdin, '\n') != EOF) {
unsigned char from_obj[20], to_obj[20];
struct strbuf **split;
int err;
split = strbuf_split(&buf, ' ');
if (!split[0] || !split[1])
die("Malformed input line: '%s'.", buf.buf);
strbuf_rtrim(split[0]);
strbuf_rtrim(split[1]);
if (get_sha1(split[0]->buf, from_obj))
die("Failed to resolve '%s' as a valid ref.", split[0]->buf);
if (get_sha1(split[1]->buf, to_obj))
die("Failed to resolve '%s' as a valid ref.", split[1]->buf);
err = copy_note(t, from_obj, to_obj, force, combine_notes_overwrite);
if (err) {
error("Failed to copy notes from '%s' to '%s'",
split[0]->buf, split[1]->buf);
ret = 1;
}
strbuf_list_free(split);
}
commit_notes(t, "Notes added by 'git notes copy'");
free_notes(t);
return ret;
}
int cmd_notes(int argc, const char **argv, const char *prefix)
{
struct notes_tree *t;
......@@ -287,7 +327,7 @@ int cmd_notes(int argc, const char **argv, const char *prefix)
char logmsg[100];
int list = 0, add = 0, copy = 0, append = 0, edit = 0, show = 0,
remove = 0, prune = 0, force = 0;
remove = 0, prune = 0, force = 0, from_stdin = 0;
int given_object = 0, i = 1, retval = 0;
struct msg_arg msg = { 0, 0, STRBUF_INIT };
struct option options[] = {
......@@ -301,6 +341,7 @@ int cmd_notes(int argc, const char **argv, const char *prefix)
OPT_CALLBACK('C', "reuse-message", &msg, "OBJECT",
"reuse specified note object", parse_reuse_arg),
OPT_BOOLEAN('f', "force", &force, "replace existing notes"),
OPT_BOOLEAN(0, "stdin", &from_stdin, "read objects from stdin"),
OPT_END()
};
......@@ -349,8 +390,21 @@ int cmd_notes(int argc, const char **argv, const char *prefix)
usage_with_options(git_notes_usage, options);
}
if (!copy && from_stdin) {
error("cannot use --stdin with %s subcommand.", argv[0]);
usage_with_options(git_notes_usage, options);
}
if (copy) {
const char *from_ref;
if (from_stdin) {
if (argc > 1) {
error("too many parameters");
usage_with_options(git_notes_usage, options);
} else {
return notes_copy_from_stdin(force);
}
}
if (argc < 3) {
error("too few parameters");
usage_with_options(git_notes_usage, options);
......
......@@ -1185,3 +1185,21 @@ void format_display_notes(const unsigned char *object_sha1,
format_note(display_notes_trees[i], object_sha1, sb,
output_encoding, flags);
}
int copy_note(struct notes_tree *t,
const unsigned char *from_obj, const unsigned char *to_obj,
int force, combine_notes_fn combine_fn)
{
const unsigned char *note = get_note(t, from_obj);
const unsigned char *existing_note = get_note(t, to_obj);
if (!force && existing_note)
return 1;
if (note)
add_note(t, to_obj, note, combine_fn);
else if (existing_note)
add_note(t, to_obj, null_sha1, combine_fn);
return 0;
}
......@@ -99,6 +99,15 @@ void remove_note(struct notes_tree *t, const unsigned char *object_sha1);
const unsigned char *get_note(struct notes_tree *t,
const unsigned char *object_sha1);
/*
* Copy a note from one object to another in the given notes_tree.
*
* Fails if the to_obj already has a note unless 'force' is true.
*/
int copy_note(struct notes_tree *t,
const unsigned char *from_obj, const unsigned char *to_obj,
int force, combine_notes_fn combine_fn);
/*
* Flags controlling behaviour of for_each_note()
*
......
......@@ -776,4 +776,38 @@ test_expect_success 'cannot copy note from object without notes' '
test_must_fail git notes copy HEAD^ HEAD
'
cat > expect << EOF
commit e5d4fb5698d564ab8c73551538ecaf2b0c666185
Author: A U Thor <[email protected]>
Date: Thu Apr 7 15:25:13 2005 -0700
13th
Notes (other):
yet another note
$whitespace
yet another note
commit 7038787dfe22a14c3867ce816dbba39845359719
Author: A U Thor <[email protected]>
Date: Thu Apr 7 15:24:13 2005 -0700
12th
Notes (other):
other note
$whitespace
yet another note
EOF
test_expect_success 'git notes copy --stdin' '
(echo $(git rev-parse HEAD~3) $(git rev-parse HEAD^); \
echo $(git rev-parse HEAD~2) $(git rev-parse HEAD)) |
git notes copy --stdin &&
git log -2 > output &&
test_cmp expect output &&
test "$(git notes list HEAD)" = "$(git notes list HEAD~2)" &&
test "$(git notes list HEAD^)" = "$(git notes list HEAD~3)"
'
test_done
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment