Skip to content

Commit ee76f92

Browse files
glandiumgitster
authored andcommitted
notes: allow treeish expressions as notes ref
init_notes() is the main point of entry to the notes API. It ensures that the input can be used as ref, because it needs a ref to update to store notes tree after modifying it. There however are many use cases where notes tree is only read, e.g. "git log --notes=...". Any notes-shaped treeish could be used for such purpose, but it is not allowed due to existing restriction. Allow treeish expressions to be used in the case the notes tree is going to be used without write "permissions". Add a flag to distinguish whether the notes tree is intended to be used read-only, or will be updated. With this change, operations that use notes read-only can be fed any notes-shaped tree-ish can be used, e.g. git log --notes=notes@{1}. Signed-off-by: Mike Hommey <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 7548842 commit ee76f92

File tree

7 files changed

+55
-30
lines changed

7 files changed

+55
-30
lines changed

Documentation/pretty-options.txt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ people using 80-column terminals.
4343
commit may be copied to the output.
4444

4545
ifndef::git-rev-list[]
46-
--notes[=<ref>]::
46+
--notes[=<treeish>]::
4747
Show the notes (see linkgit:git-notes[1]) that annotate the
4848
commit, when showing the commit log message. This is the default
4949
for `git log`, `git show` and `git whatchanged` commands when
@@ -54,8 +54,8 @@ By default, the notes shown are from the notes refs listed in the
5454
'core.notesRef' and 'notes.displayRef' variables (or corresponding
5555
environment overrides). See linkgit:git-config[1] for more details.
5656
+
57-
With an optional '<ref>' argument, show this notes ref instead of the
58-
default notes ref(s). The ref specifies the full refname when it begins
57+
With an optional '<treeish>' argument, use the treeish to find the notes
58+
to display. The treeish can specify the full refname when it begins
5959
with `refs/notes/`; when it begins with `notes/`, `refs/` and otherwise
6060
`refs/notes/` is prefixed to form a full name of the ref.
6161
+
@@ -71,7 +71,7 @@ being displayed. Examples: "--notes=foo" will show only notes from
7171
"--notes --notes=foo --no-notes --notes=bar" will only show notes
7272
from "refs/notes/bar".
7373

74-
--show-notes[=<ref>]::
74+
--show-notes[=<treeish>]::
7575
--[no-]standard-notes::
7676
These options are deprecated. Use the above --notes/--no-notes
7777
options instead.

builtin/notes.c

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -286,7 +286,7 @@ static int notes_copy_from_stdin(int force, const char *rewrite_cmd)
286286
if (!c)
287287
return 0;
288288
} else {
289-
init_notes(NULL, NULL, NULL, 0);
289+
init_notes(NULL, NULL, NULL, NOTES_INIT_WRITABLE);
290290
t = &default_notes_tree;
291291
}
292292

@@ -329,15 +329,18 @@ static int notes_copy_from_stdin(int force, const char *rewrite_cmd)
329329
return ret;
330330
}
331331

332-
static struct notes_tree *init_notes_check(const char *subcommand)
332+
static struct notes_tree *init_notes_check(const char *subcommand,
333+
int flags)
333334
{
334335
struct notes_tree *t;
335-
init_notes(NULL, NULL, NULL, 0);
336+
const char *ref;
337+
init_notes(NULL, NULL, NULL, flags);
336338
t = &default_notes_tree;
337339

338-
if (!starts_with(t->ref, "refs/notes/"))
340+
ref = (flags & NOTES_INIT_WRITABLE) ? t->update_ref : t->ref;
341+
if (!starts_with(ref, "refs/notes/"))
339342
die("Refusing to %s notes in %s (outside of refs/notes/)",
340-
subcommand, t->ref);
343+
subcommand, ref);
341344
return t;
342345
}
343346

@@ -360,7 +363,7 @@ static int list(int argc, const char **argv, const char *prefix)
360363
usage_with_options(git_notes_list_usage, options);
361364
}
362365

363-
t = init_notes_check("list");
366+
t = init_notes_check("list", 0);
364367
if (argc) {
365368
if (get_sha1(argv[0], object))
366369
die(_("Failed to resolve '%s' as a valid ref."), argv[0]);
@@ -420,7 +423,7 @@ static int add(int argc, const char **argv, const char *prefix)
420423
if (get_sha1(object_ref, object))
421424
die(_("Failed to resolve '%s' as a valid ref."), object_ref);
422425

423-
t = init_notes_check("add");
426+
t = init_notes_check("add", NOTES_INIT_WRITABLE);
424427
note = get_note(t, object);
425428

426429
if (note) {
@@ -511,7 +514,7 @@ static int copy(int argc, const char **argv, const char *prefix)
511514
if (get_sha1(object_ref, object))
512515
die(_("Failed to resolve '%s' as a valid ref."), object_ref);
513516

514-
t = init_notes_check("copy");
517+
t = init_notes_check("copy", NOTES_INIT_WRITABLE);
515518
note = get_note(t, object);
516519

517520
if (note) {
@@ -589,7 +592,7 @@ static int append_edit(int argc, const char **argv, const char *prefix)
589592
if (get_sha1(object_ref, object))
590593
die(_("Failed to resolve '%s' as a valid ref."), object_ref);
591594

592-
t = init_notes_check(argv[0]);
595+
t = init_notes_check(argv[0], NOTES_INIT_WRITABLE);
593596
note = get_note(t, object);
594597

595598
prepare_note_data(object, &d, edit ? note : NULL);
@@ -652,7 +655,7 @@ static int show(int argc, const char **argv, const char *prefix)
652655
if (get_sha1(object_ref, object))
653656
die(_("Failed to resolve '%s' as a valid ref."), object_ref);
654657

655-
t = init_notes_check("show");
658+
t = init_notes_check("show", 0);
656659
note = get_note(t, object);
657660

658661
if (!note)
@@ -809,7 +812,7 @@ static int merge(int argc, const char **argv, const char *prefix)
809812
expand_notes_ref(&remote_ref);
810813
o.remote_ref = remote_ref.buf;
811814

812-
t = init_notes_check("merge");
815+
t = init_notes_check("merge", NOTES_INIT_WRITABLE);
813816

814817
if (strategy) {
815818
if (parse_notes_merge_strategy(strategy, &o.strategy)) {
@@ -901,7 +904,7 @@ static int remove_cmd(int argc, const char **argv, const char *prefix)
901904
argc = parse_options(argc, argv, prefix, options,
902905
git_notes_remove_usage, 0);
903906

904-
t = init_notes_check("remove");
907+
t = init_notes_check("remove", NOTES_INIT_WRITABLE);
905908

906909
if (!argc && !from_stdin) {
907910
retval = remove_one_note(t, "HEAD", flag);
@@ -943,7 +946,7 @@ static int prune(int argc, const char **argv, const char *prefix)
943946
usage_with_options(git_notes_prune_usage, options);
944947
}
945948

946-
t = init_notes_check("prune");
949+
t = init_notes_check("prune", NOTES_INIT_WRITABLE);
947950

948951
prune_notes(t, (verbose ? NOTES_PRUNE_VERBOSE : 0) |
949952
(show_only ? NOTES_PRUNE_VERBOSE|NOTES_PRUNE_DRYRUN : 0) );

notes-cache.c

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,14 +32,14 @@ void notes_cache_init(struct notes_cache *c, const char *name,
3232
const char *validity)
3333
{
3434
struct strbuf ref = STRBUF_INIT;
35-
int flags = 0;
35+
int flags = NOTES_INIT_WRITABLE;
3636

3737
memset(c, 0, sizeof(*c));
3838
c->validity = xstrdup(validity);
3939

4040
strbuf_addf(&ref, "refs/notes/%s", name);
4141
if (!notes_cache_match_validity(ref.buf, validity))
42-
flags = NOTES_INIT_EMPTY;
42+
flags |= NOTES_INIT_EMPTY;
4343
init_notes(&c->tree, ref.buf, combine_notes_overwrite, flags);
4444
strbuf_release(&ref);
4545
}
@@ -49,7 +49,8 @@ int notes_cache_write(struct notes_cache *c)
4949
unsigned char tree_sha1[20];
5050
unsigned char commit_sha1[20];
5151

52-
if (!c || !c->tree.initialized || !c->tree.ref || !*c->tree.ref)
52+
if (!c || !c->tree.initialized || !c->tree.update_ref ||
53+
!*c->tree.update_ref)
5354
return -1;
5455
if (!c->tree.dirty)
5556
return 0;
@@ -59,8 +60,8 @@ int notes_cache_write(struct notes_cache *c)
5960
if (commit_tree(c->validity, strlen(c->validity), tree_sha1, NULL,
6061
commit_sha1, NULL, NULL) < 0)
6162
return -1;
62-
if (update_ref("update notes cache", c->tree.ref, commit_sha1, NULL,
63-
0, UPDATE_REFS_QUIET_ON_ERR) < 0)
63+
if (update_ref("update notes cache", c->tree.update_ref, commit_sha1,
64+
NULL, 0, UPDATE_REFS_QUIET_ON_ERR) < 0)
6465
return -1;
6566

6667
return 0;

notes-utils.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ void commit_notes(struct notes_tree *t, const char *msg)
3737

3838
if (!t)
3939
t = &default_notes_tree;
40-
if (!t->initialized || !t->ref || !*t->ref)
40+
if (!t->initialized || !t->update_ref || !*t->update_ref)
4141
die(_("Cannot commit uninitialized/unreferenced notes tree"));
4242
if (!t->dirty)
4343
return; /* don't have to commit an unchanged tree */
@@ -48,7 +48,7 @@ void commit_notes(struct notes_tree *t, const char *msg)
4848

4949
create_notes_commit(t, NULL, buf.buf, buf.len, commit_sha1);
5050
strbuf_insert(&buf, 0, "notes: ", 7); /* commit message starts at index 7 */
51-
update_ref(buf.buf, t->ref, commit_sha1, NULL, 0,
51+
update_ref(buf.buf, t->update_ref, commit_sha1, NULL, 0,
5252
UPDATE_REFS_DIE_ON_ERR);
5353

5454
strbuf_release(&buf);
@@ -148,7 +148,7 @@ struct notes_rewrite_cfg *init_copy_notes_for_rewrite(const char *cmd)
148148
free(c);
149149
return NULL;
150150
}
151-
c->trees = load_notes_trees(c->refs);
151+
c->trees = load_notes_trees(c->refs, NOTES_INIT_WRITABLE);
152152
string_list_clear(c->refs, 0);
153153
free(c->refs);
154154
return c;

notes.c

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1011,13 +1011,16 @@ void init_notes(struct notes_tree *t, const char *notes_ref,
10111011
t->first_non_note = NULL;
10121012
t->prev_non_note = NULL;
10131013
t->ref = xstrdup_or_null(notes_ref);
1014+
t->update_ref = (flags & NOTES_INIT_WRITABLE) ? t->ref : NULL;
10141015
t->combine_notes = combine_notes;
10151016
t->initialized = 1;
10161017
t->dirty = 0;
10171018

10181019
if (flags & NOTES_INIT_EMPTY || !notes_ref ||
1019-
read_ref(notes_ref, object_sha1))
1020+
get_sha1_treeish(notes_ref, object_sha1))
10201021
return;
1022+
if (flags & NOTES_INIT_WRITABLE && read_ref(notes_ref, object_sha1))
1023+
die("Cannot use notes ref %s", notes_ref);
10211024
if (get_tree_entry(object_sha1, "", sha1, &mode))
10221025
die("Failed to read notes tree referenced by %s (%s)",
10231026
notes_ref, sha1_to_hex(object_sha1));
@@ -1027,15 +1030,15 @@ void init_notes(struct notes_tree *t, const char *notes_ref,
10271030
load_subtree(t, &root_tree, t->root, 0);
10281031
}
10291032

1030-
struct notes_tree **load_notes_trees(struct string_list *refs)
1033+
struct notes_tree **load_notes_trees(struct string_list *refs, int flags)
10311034
{
10321035
struct string_list_item *item;
10331036
int counter = 0;
10341037
struct notes_tree **trees;
10351038
trees = xmalloc((refs->nr+1) * sizeof(struct notes_tree *));
10361039
for_each_string_list_item(item, refs) {
10371040
struct notes_tree *t = xcalloc(1, sizeof(struct notes_tree));
1038-
init_notes(t, item->string, combine_notes_ignore, 0);
1041+
init_notes(t, item->string, combine_notes_ignore, flags);
10391042
trees[counter++] = t;
10401043
}
10411044
trees[counter] = NULL;
@@ -1071,7 +1074,7 @@ void init_display_notes(struct display_notes_opt *opt)
10711074
item->string);
10721075
}
10731076

1074-
display_notes_trees = load_notes_trees(&display_notes_refs);
1077+
display_notes_trees = load_notes_trees(&display_notes_refs, 0);
10751078
string_list_clear(&display_notes_refs, 0);
10761079
}
10771080

notes.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ extern struct notes_tree {
4444
struct int_node *root;
4545
struct non_note *first_non_note, *prev_non_note;
4646
char *ref;
47+
char *update_ref;
4748
combine_notes_fn combine_notes;
4849
int initialized;
4950
int dirty;
@@ -71,6 +72,13 @@ const char *default_notes_ref(void);
7172
*/
7273
#define NOTES_INIT_EMPTY 1
7374

75+
/*
76+
* By default, the notes tree is only readable, and the notes ref can be
77+
* any treeish. The notes tree can however be made writable with this flag,
78+
* in which case only strict ref names can be used.
79+
*/
80+
#define NOTES_INIT_WRITABLE 2
81+
7482
/*
7583
* Initialize the given notes_tree with the notes tree structure at the given
7684
* ref. If given ref is NULL, the value of the $GIT_NOTES_REF environment
@@ -276,7 +284,7 @@ void format_display_notes(const unsigned char *object_sha1,
276284
* Load the notes tree from each ref listed in 'refs'. The output is
277285
* an array of notes_tree*, terminated by a NULL.
278286
*/
279-
struct notes_tree **load_notes_trees(struct string_list *refs);
287+
struct notes_tree **load_notes_trees(struct string_list *refs, int flags);
280288

281289
/*
282290
* Add all refs that match 'glob' to the 'list'.

t/t3301-notes.sh

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,16 @@ test_expect_success 'edit existing notes' '
8383
test_must_fail git notes show HEAD^
8484
'
8585

86+
test_expect_success 'show notes from treeish' '
87+
test "b3" = "$(git notes --ref commits^{tree} show)" &&
88+
test "b4" = "$(git notes --ref commits@{1} show)"
89+
'
90+
91+
test_expect_success 'cannot edit notes from non-ref' '
92+
test_must_fail git notes --ref commits^{tree} edit &&
93+
test_must_fail git notes --ref commits@{1} edit
94+
'
95+
8696
test_expect_success 'cannot "git notes add -m" where notes already exists' '
8797
test_must_fail git notes add -m "b2" &&
8898
test_path_is_missing .git/NOTES_EDITMSG &&

0 commit comments

Comments
 (0)