Message ID | d7486390d57849971ee6a4ac27a0a784c41623ee.1659122979.git.gitgitgadget@gmail.com (mailing list archive) |
---|---|
State | Superseded |
Headers | show |
Series | log: create tighter default decoration filter | expand |
"Derrick Stolee via GitGitGadget" <gitgitgadget@gmail.com> writes: > + [NAMESPACE_REPLACE] = { > + /* > + * This namespace allows Git to act as if one object ID > + * points to the content of another. Unlike the other > + * ref namespaces, this one can be changed by the > + * GIT_REPLACE_REF_BASE environment variable. This > + * .namespace value will be overwritten in setup_git_env(). > + */ Thanks---it is a shame that we have unnecessary flexibility that requires us to have this code. > + .ref = "refs/replace/", > + .decoration = DECORATION_GRAFTED, > + }, > + [NAMESPACE_NOTES] = { > + /* > + * The refs/notes/commit ref points to the tip of a > + * parallel commit history that adds metadata to commits > + * in the normal history. This branch can be overwritten This is not "branch" but is a ref. > + * by the core.notesRef config variable or the > + * GIT_NOTES_REFS environment variable. > + */ > + .ref = "refs/notes/commit", > + .exact = 1, Allowing just "the default" to be replaced by another "custom default" is a good start, but we probably want to support more than one notes refs, to parallel how "struct display_notes_opt" has extra_notes_refs to allow multiple notes refs to decorate objects.
On 2022.07.29 19:29, Derrick Stolee via GitGitGadget wrote: > diff --git a/refs.h b/refs.h > index 47cb9edbaa8..94e8dedf939 100644 > --- a/refs.h > +++ b/refs.h > @@ -2,6 +2,7 @@ > #define REFS_H > > #include "cache.h" > +#include "commit.h" > > struct object_id; > struct ref_store; > @@ -930,4 +931,49 @@ struct ref_store *get_main_ref_store(struct repository *r); > struct ref_store *get_submodule_ref_store(const char *submodule); > struct ref_store *get_worktree_ref_store(const struct worktree *wt); > > +/* > + * Some of the names specified by refs have special meaning to Git. > + * Organize these namespaces in a comon 'ref_namespaces' array for > + * reference from multiple places in the codebase. > + */ > + > +struct ref_namespace_info { > + char *ref; > + enum decoration_type decoration; > + > + /* > + * If 'exact' is true, then we must match the 'ref' exactly. > + * Otherwise, use a prefix match. > + * > + * 'orig_ref' is for internal use. It represents whether the s/orig_ref/ref_updated/ here I think. > + * 'ref' value was replaced from its original literal version. > + */ > + unsigned exact:1, > + ref_updated:1; > +}; > + > +enum ref_namespace { > + NAMESPACE_HEAD, > + NAMESPACE_BRANCHES, > + NAMESPACE_TAGS, > + NAMESPACE_REMOTE_REFS, > + NAMESPACE_STASH, > + NAMESPACE_REPLACE, > + NAMESPACE_NOTES, > + NAMESPACE_PREFETCH, > + NAMESPACE_REWRITTEN, > + > + /* Must be last */ > + NAMESPACE__COUNT > +}; > + > +/* See refs.c for the contents of this array. */ > +extern struct ref_namespace_info ref_namespaces[]; > + > +/* > + * Some ref namespaces can be modified by config values or environment > + * variables. Modify a namespace as specified by its ref_namespace key. > + */ > +void update_ref_namespace(enum ref_namespace namespace, char *ref); > + > #endif /* REFS_H */ > -- > gitgitgadget >
On 8/3/2022 2:16 AM, Junio C Hamano wrote: > "Derrick Stolee via GitGitGadget" <gitgitgadget@gmail.com> writes: > >> + [NAMESPACE_REPLACE] = { >> + /* >> + * This namespace allows Git to act as if one object ID >> + * points to the content of another. Unlike the other >> + * ref namespaces, this one can be changed by the >> + * GIT_REPLACE_REF_BASE environment variable. This >> + * .namespace value will be overwritten in setup_git_env(). >> + */ > > Thanks---it is a shame that we have unnecessary flexibility that > requires us to have this code. > >> + .ref = "refs/replace/", >> + .decoration = DECORATION_GRAFTED, >> + }, >> + [NAMESPACE_NOTES] = { >> + /* >> + * The refs/notes/commit ref points to the tip of a >> + * parallel commit history that adds metadata to commits >> + * in the normal history. This branch can be overwritten > > This is not "branch" but is a ref. Thanks! >> + * by the core.notesRef config variable or the >> + * GIT_NOTES_REFS environment variable. >> + */ >> + .ref = "refs/notes/commit", >> + .exact = 1, > > Allowing just "the default" to be replaced by another "custom > default" is a good start, but we probably want to support more than > one notes refs, to parallel how "struct display_notes_opt" has > extra_notes_refs to allow multiple notes refs to decorate objects. I imagine that if we allowed multiple notes refs, then we would need to use a ref prefix to define a namespace. If we relaxed that, then we could modify this as follows: .ref = "refs/notes/", /* .exact = 0, */ (The comment is included just to illustrate the change.) There is additional logic in init_notes() to track multiple notes refs, but the change to things that use ref_namespaces would be minimal. Thanks, -Stolee
On 8/3/2022 6:39 PM, Josh Steadmon wrote: > On 2022.07.29 19:29, Derrick Stolee via GitGitGadget wrote: >> + /* >> + * If 'exact' is true, then we must match the 'ref' exactly. >> + * Otherwise, use a prefix match. >> + * >> + * 'orig_ref' is for internal use. It represents whether the > > s/orig_ref/ref_updated/ here I think. Thanks! -Stolee
Derrick Stolee <derrickstolee@github.com> writes: >>> + * by the core.notesRef config variable or the >>> + * GIT_NOTES_REFS environment variable. >>> + */ >>> + .ref = "refs/notes/commit", >>> + .exact = 1, >> >> Allowing just "the default" to be replaced by another "custom >> default" is a good start, but we probably want to support more than >> one notes refs, to parallel how "struct display_notes_opt" has >> extra_notes_refs to allow multiple notes refs to decorate objects. > > I imagine that if we allowed multiple notes refs, then we would need > to use a ref prefix to define a namespace. If we relaxed that, then > we could modify this as follows: > > .ref = "refs/notes/", > /* .exact = 0, */ > > (The comment is included just to illustrate the change.) As I do not think it is so bad to decorate a commit with, say, refs/notes/amlog in "git log --notes" (not "git log --notes=amlog") output if such a commit happens to appear, so limiting to the single notes ref that is given by notes.displayRef and ignoring others like the posted patch felt like an over-engineering that may result in even a negative gain. Treating it just like "tags" and "remotes" hierarchy would match intuition better for people, I suspect. Thanks.
diff --git a/environment.c b/environment.c index b3296ce7d15..9eb22f975c7 100644 --- a/environment.c +++ b/environment.c @@ -185,6 +185,8 @@ void setup_git_env(const char *git_dir) free(git_replace_ref_base); git_replace_ref_base = xstrdup(replace_ref_base ? replace_ref_base : "refs/replace/"); + update_ref_namespace(NAMESPACE_REPLACE, git_replace_ref_base); + free(git_namespace); git_namespace = expand_namespace(getenv(GIT_NAMESPACE_ENVIRONMENT)); shallow_file = getenv(GIT_SHALLOW_FILE_ENVIRONMENT); diff --git a/notes.c b/notes.c index 7452e71cc8d..7bade6d8f69 100644 --- a/notes.c +++ b/notes.c @@ -1005,6 +1005,7 @@ void init_notes(struct notes_tree *t, const char *notes_ref, if (!notes_ref) notes_ref = default_notes_ref(); + update_ref_namespace(NAMESPACE_NOTES, xstrdup(notes_ref)); if (!combine_notes) combine_notes = combine_notes_concatenate; diff --git a/refs.c b/refs.c index ec3134e4842..8e87cc7efb0 100644 --- a/refs.c +++ b/refs.c @@ -20,6 +20,7 @@ #include "repository.h" #include "sigchain.h" #include "date.h" +#include "commit.h" /* * List of all available backends @@ -56,6 +57,88 @@ static unsigned char refname_disposition[256] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 4, 4 }; +struct ref_namespace_info ref_namespaces[] = { + [NAMESPACE_HEAD] = { + .ref = "HEAD", + .decoration = DECORATION_REF_HEAD, + .exact = 1, + }, + [NAMESPACE_BRANCHES] = { + .ref = "refs/heads/", + .decoration = DECORATION_REF_LOCAL, + }, + [NAMESPACE_TAGS] = { + .ref = "refs/tags/", + .decoration = DECORATION_REF_TAG, + }, + [NAMESPACE_REMOTE_REFS] = { + /* + * The default refspec for new remotes copies refs from + * refs/heads/ on the remote into refs/remotes/<remote>/. + * As such, "refs/remotes/" has special handling. + */ + .ref = "refs/remotes/", + .decoration = DECORATION_REF_REMOTE, + }, + [NAMESPACE_STASH] = { + /* + * The single ref "refs/stash" stores the latest stash. + * Older stashes can be found in the reflog. + */ + .ref = "refs/stash", + .exact = 1, + .decoration = DECORATION_REF_STASH, + }, + [NAMESPACE_REPLACE] = { + /* + * This namespace allows Git to act as if one object ID + * points to the content of another. Unlike the other + * ref namespaces, this one can be changed by the + * GIT_REPLACE_REF_BASE environment variable. This + * .namespace value will be overwritten in setup_git_env(). + */ + .ref = "refs/replace/", + .decoration = DECORATION_GRAFTED, + }, + [NAMESPACE_NOTES] = { + /* + * The refs/notes/commit ref points to the tip of a + * parallel commit history that adds metadata to commits + * in the normal history. This branch can be overwritten + * by the core.notesRef config variable or the + * GIT_NOTES_REFS environment variable. + */ + .ref = "refs/notes/commit", + .exact = 1, + }, + [NAMESPACE_PREFETCH] = { + /* + * Prefetch refs are written by the background 'fetch' + * maintenance task. It allows faster foreground fetches + * by advertising these previously-downloaded tips without + * updating refs/remotes/ without user intervention. + */ + .ref = "refs/prefetch/", + }, + [NAMESPACE_REWRITTEN] = { + /* + * Rewritten refs are used by the 'label' command in the + * sequencer. These are particularly useful during an + * interactive rebase that uses the 'merge' command. + */ + .ref = "refs/rewritten/", + }, +}; + +void update_ref_namespace(enum ref_namespace namespace, char *ref) +{ + struct ref_namespace_info *info = &ref_namespaces[namespace]; + if (info->ref_updated) + free(info->ref); + info->ref = ref; + info->ref_updated = 1; +} + /* * Try to read one refname component from the front of refname. * Return the length of the component found, or -1 if the component is diff --git a/refs.h b/refs.h index 47cb9edbaa8..94e8dedf939 100644 --- a/refs.h +++ b/refs.h @@ -2,6 +2,7 @@ #define REFS_H #include "cache.h" +#include "commit.h" struct object_id; struct ref_store; @@ -930,4 +931,49 @@ struct ref_store *get_main_ref_store(struct repository *r); struct ref_store *get_submodule_ref_store(const char *submodule); struct ref_store *get_worktree_ref_store(const struct worktree *wt); +/* + * Some of the names specified by refs have special meaning to Git. + * Organize these namespaces in a comon 'ref_namespaces' array for + * reference from multiple places in the codebase. + */ + +struct ref_namespace_info { + char *ref; + enum decoration_type decoration; + + /* + * If 'exact' is true, then we must match the 'ref' exactly. + * Otherwise, use a prefix match. + * + * 'orig_ref' is for internal use. It represents whether the + * 'ref' value was replaced from its original literal version. + */ + unsigned exact:1, + ref_updated:1; +}; + +enum ref_namespace { + NAMESPACE_HEAD, + NAMESPACE_BRANCHES, + NAMESPACE_TAGS, + NAMESPACE_REMOTE_REFS, + NAMESPACE_STASH, + NAMESPACE_REPLACE, + NAMESPACE_NOTES, + NAMESPACE_PREFETCH, + NAMESPACE_REWRITTEN, + + /* Must be last */ + NAMESPACE__COUNT +}; + +/* See refs.c for the contents of this array. */ +extern struct ref_namespace_info ref_namespaces[]; + +/* + * Some ref namespaces can be modified by config values or environment + * variables. Modify a namespace as specified by its ref_namespace key. + */ +void update_ref_namespace(enum ref_namespace namespace, char *ref); + #endif /* REFS_H */