refs: add array of ref namespaces
Git interprets different meanings to different refs based on their names. Some meanings are cosmetic, like how refs in 'refs/remotes/*' are colored differently from refs in 'refs/heads/*'. Others are more critical, such as how replace refs are interpreted. Before making behavior changes based on ref namespaces, collect all known ref namespaces into a array of ref_namespace_info structs. This array is indexed by the new ref_namespace enum for quick access. As of this change, this array is purely documentation. Future changes will add dependencies on this array. Signed-off-by: Derrick Stolee <derrickstolee@github.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Derrick Stolee committed
Aug 5, 2022 at 17:58 UTC
b9342b3fd6308c351f53075c9c4339913b73451f
4 files changed
+132
environment.c
+2
@@ -185,6 +185,8 @@ void setup_git_env(const char *git_dir)
185
free(git_replace_ref_base);
186
git_replace_ref_base = xstrdup(replace_ref_base ? replace_ref_base
187
: "refs/replace/");
188
+ update_ref_namespace(NAMESPACE_REPLACE, git_replace_ref_base);
189
+
190
free(git_namespace);
191
git_namespace = expand_namespace(getenv(GIT_NAMESPACE_ENVIRONMENT));
192
shallow_file = getenv(GIT_SHALLOW_FILE_ENVIRONMENT);
notes.c
+1
@@ -1005,6 +1005,7 @@ void init_notes(struct notes_tree *t, const char *notes_ref,
1005
1006
if (!notes_ref)
1007
notes_ref = default_notes_ref();
1008
+ update_ref_namespace(NAMESPACE_NOTES, xstrdup(notes_ref));
1009
1010
if (!combine_notes)
1011
combine_notes = combine_notes_concatenate;
refs.c
+83
@@ -20,6 +20,7 @@
20
#include "repository.h"
21
#include "sigchain.h"
22
#include "date.h"
23
+#include "commit.h"
24
25
/*
26
* List of all available backends
@@ -56,6 +57,88 @@ static unsigned char refname_disposition[256] = {
57
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 4, 4
58
};
59
60
+struct ref_namespace_info ref_namespace[] = {
61
+ [NAMESPACE_HEAD] = {
62
+ .ref = "HEAD",
63
+ .decoration = DECORATION_REF_HEAD,
64
+ .exact = 1,
65
+ },
66
+ [NAMESPACE_BRANCHES] = {
67
+ .ref = "refs/heads/",
68
+ .decoration = DECORATION_REF_LOCAL,
69
+ },
70
+ [NAMESPACE_TAGS] = {
71
+ .ref = "refs/tags/",
72
+ .decoration = DECORATION_REF_TAG,
73
+ },
74
+ [NAMESPACE_REMOTE_REFS] = {
75
+ /*
76
+ * The default refspec for new remotes copies refs from
77
+ * refs/heads/ on the remote into refs/remotes/<remote>/.
78
+ * As such, "refs/remotes/" has special handling.
79
+ */
80
+ .ref = "refs/remotes/",
81
+ .decoration = DECORATION_REF_REMOTE,
82
+ },
83
+ [NAMESPACE_STASH] = {
84
+ /*
85
+ * The single ref "refs/stash" stores the latest stash.
86
+ * Older stashes can be found in the reflog.
87
+ */
88
+ .ref = "refs/stash",
89
+ .exact = 1,
90
+ .decoration = DECORATION_REF_STASH,
91
+ },
92
+ [NAMESPACE_REPLACE] = {
93
+ /*
94
+ * This namespace allows Git to act as if one object ID
95
+ * points to the content of another. Unlike the other
96
+ * ref namespaces, this one can be changed by the
97
+ * GIT_REPLACE_REF_BASE environment variable. This
98
+ * .namespace value will be overwritten in setup_git_env().
99
+ */
100
+ .ref = "refs/replace/",
101
+ .decoration = DECORATION_GRAFTED,
102
+ },
103
+ [NAMESPACE_NOTES] = {
104
+ /*
105
+ * The refs/notes/commit ref points to the tip of a
106
+ * parallel commit history that adds metadata to commits
107
+ * in the normal history. This ref can be overwritten
108
+ * by the core.notesRef config variable or the
109
+ * GIT_NOTES_REFS environment variable.
110
+ */
111
+ .ref = "refs/notes/commit",
112
+ .exact = 1,
113
+ },
114
+ [NAMESPACE_PREFETCH] = {
115
+ /*
116
+ * Prefetch refs are written by the background 'fetch'
117
+ * maintenance task. It allows faster foreground fetches
118
+ * by advertising these previously-downloaded tips without
119
+ * updating refs/remotes/ without user intervention.
120
+ */
121
+ .ref = "refs/prefetch/",
122
+ },
123
+ [NAMESPACE_REWRITTEN] = {
124
+ /*
125
+ * Rewritten refs are used by the 'label' command in the
126
+ * sequencer. These are particularly useful during an
127
+ * interactive rebase that uses the 'merge' command.
128
+ */
129
+ .ref = "refs/rewritten/",
130
+ },
131
+};
132
+
133
+void update_ref_namespace(enum ref_namespace namespace, char *ref)
134
+{
135
+ struct ref_namespace_info *info = &ref_namespace[namespace];
136
+ if (info->ref_updated)
137
+ free(info->ref);
138
+ info->ref = ref;
139
+ info->ref_updated = 1;
140
+}
141
+
142
/*
143
* Try to read one refname component from the front of refname.
144
* Return the length of the component found, or -1 if the component is
refs.h
+46
@@ -2,6 +2,7 @@
2
#define REFS_H
3
4
#include "cache.h"
5
+#include "commit.h"
6
7
struct object_id;
8
struct ref_store;
@@ -930,4 +931,49 @@ struct ref_store *get_main_ref_store(struct repository *r);
931
struct ref_store *get_submodule_ref_store(const char *submodule);
932
struct ref_store *get_worktree_ref_store(const struct worktree *wt);
933
934
+/*
935
+ * Some of the names specified by refs have special meaning to Git.
936
+ * Organize these namespaces in a comon 'ref_namespace' array for
937
+ * reference from multiple places in the codebase.
938
+ */
939
+
940
+struct ref_namespace_info {
941
+ char *ref;
942
+ enum decoration_type decoration;
943
+
944
+ /*
945
+ * If 'exact' is true, then we must match the 'ref' exactly.
946
+ * Otherwise, use a prefix match.
947
+ *
948
+ * 'ref_updated' is for internal use. It represents whether the
949
+ * 'ref' value was replaced from its original literal version.
950
+ */
951
+ unsigned exact:1,
952
+ ref_updated:1;
953
+};
954
+
955
+enum ref_namespace {
956
+ NAMESPACE_HEAD,
957
+ NAMESPACE_BRANCHES,
958
+ NAMESPACE_TAGS,
959
+ NAMESPACE_REMOTE_REFS,
960
+ NAMESPACE_STASH,
961
+ NAMESPACE_REPLACE,
962
+ NAMESPACE_NOTES,
963
+ NAMESPACE_PREFETCH,
964
+ NAMESPACE_REWRITTEN,
965
+
966
+ /* Must be last */
967
+ NAMESPACE__COUNT
968
+};
969
+
970
+/* See refs.c for the contents of this array. */
971
+extern struct ref_namespace_info ref_namespace[NAMESPACE__COUNT];
972
+
973
+/*
974
+ * Some ref namespaces can be modified by config values or environment
975
+ * variables. Modify a namespace as specified by its ref_namespace key.
976
+ */
977
+void update_ref_namespace(enum ref_namespace namespace, char *ref);
978
+
979
#endif /* REFS_H */