Allow to control where the replace refs are looked for

It can be useful to have grafts or replace refs for specific use-cases while keeping the default "view" of the repository pristine (or with a different set of grafts/replace refs). It is possible to use a different graft file with GIT_GRAFT_FILE, but while replace refs are more powerful, they don't have an equivalent override. Add a GIT_REPLACE_REF_BASE environment variable to control where git is going to look for replace refs. Signed-off-by: Mike Hommey <mh@glandium.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Mike Hommey committed Jun 12, 2015 at 06:34 UTC 58d121b22b5b83a27a1891dcf335458f687cac1e
5 files changed +16 -6
builtin/replace.c
+3 -3
@@ -104,9 +104,9 @@ static int for_each_replace_name(const char **argv, each_replace_name_fn fn)
104 continue;
105 }
106 full_hex = sha1_to_hex(sha1);
107 - snprintf(ref, sizeof(ref), "refs/replace/%s", full_hex);
107 + snprintf(ref, sizeof(ref), "%s%s", git_replace_ref_base, full_hex);
108 /* read_ref() may reuse the buffer */
109 - full_hex = ref + strlen("refs/replace/");
109 + full_hex = ref + strlen(git_replace_ref_base);
110 if (read_ref(ref, sha1)) {
111 error("replace ref '%s' not found.", full_hex);
112 had_error = 1;
@@ -134,7 +134,7 @@ static void check_ref_valid(unsigned char object[20],
134 int force)
135 {
136 if (snprintf(ref, ref_size,
137 - "refs/replace/%s",
137 + "%s%s", git_replace_ref_base,
138 sha1_to_hex(object)) > ref_size - 1)
139 die("replace ref name too long: %.*s...", 50, ref);
140 if (check_refname_format(ref, 0))
cache.h
+2
@@ -397,6 +397,7 @@ static inline enum object_type object_type(unsigned int mode)
397 #define EXEC_PATH_ENVIRONMENT "GIT_EXEC_PATH"
398 #define CEILING_DIRECTORIES_ENVIRONMENT "GIT_CEILING_DIRECTORIES"
399 #define NO_REPLACE_OBJECTS_ENVIRONMENT "GIT_NO_REPLACE_OBJECTS"
400 +#define GIT_REPLACE_REF_BASE_ENVIRONMENT "GIT_REPLACE_REF_BASE"
401 #define GITATTRIBUTES_FILE ".gitattributes"
402 #define INFOATTRIBUTES_FILE "info/attributes"
403 #define ATTRIBUTE_MACRO_PREFIX "[attr]"
@@ -622,6 +623,7 @@ extern unsigned long pack_size_limit_cfg;
623 * been sought but there were none.
624 */
625 extern int check_replace_refs;
626 +extern char *git_replace_ref_base;
627
628 extern int fsync_object_files;
629 extern int core_preload_index;
environment.c
+6
@@ -47,6 +47,7 @@ const char *askpass_program;
47 const char *excludes_file;
48 enum auto_crlf auto_crlf = AUTO_CRLF_FALSE;
49 int check_replace_refs = 1;
50 +char *git_replace_ref_base;
51 enum eol core_eol = EOL_UNSET;
52 enum safe_crlf safe_crlf = SAFE_CRLF_WARN;
53 unsigned whitespace_rule_cfg = WS_DEFAULT_RULE;
@@ -110,6 +111,7 @@ const char * const local_repo_env[] = {
111 GRAFT_ENVIRONMENT,
112 INDEX_ENVIRONMENT,
113 NO_REPLACE_OBJECTS_ENVIRONMENT,
114 + GIT_REPLACE_REF_BASE_ENVIRONMENT,
115 GIT_PREFIX_ENVIRONMENT,
116 GIT_SHALLOW_FILE_ENVIRONMENT,
117 GIT_COMMON_DIR_ENVIRONMENT,
@@ -156,6 +158,7 @@ static void setup_git_env(void)
158 struct strbuf sb = STRBUF_INIT;
159 const char *gitfile;
160 const char *shallow_file;
161 + const char *replace_ref_base;
162
163 git_dir = getenv(GIT_DIR_ENVIRONMENT);
164 if (!git_dir)
@@ -173,6 +176,9 @@ static void setup_git_env(void)
176 "info/grafts", &git_graft_env);
177 if (getenv(NO_REPLACE_OBJECTS_ENVIRONMENT))
178 check_replace_refs = 0;
179 + replace_ref_base = getenv(GIT_REPLACE_REF_BASE_ENVIRONMENT);
180 + git_replace_ref_base = xstrdup(replace_ref_base ? replace_ref_base
181 + : "refs/replace/");
182 namespace = expand_namespace(getenv(GIT_NAMESPACE_ENVIRONMENT));
183 namespace_len = strlen(namespace);
184 shallow_file = getenv(GIT_SHALLOW_FILE_ENVIRONMENT);
log-tree.c
+3 -2
@@ -96,11 +96,12 @@ static int add_ref_decoration(const char *refname, const unsigned char *sha1, in
96
97 assert(cb_data == NULL);
98
99 - if (starts_with(refname, "refs/replace/")) {
99 + if (starts_with(refname, git_replace_ref_base)) {
100 unsigned char original_sha1[20];
101 if (!check_replace_refs)
102 return 0;
103 - if (get_sha1_hex(refname + 13, original_sha1)) {
103 + if (get_sha1_hex(refname + strlen(git_replace_ref_base),
104 + original_sha1)) {
105 warning("invalid replace ref %s", refname);
106 return 0;
107 }
refs.c
+2 -1
@@ -2106,7 +2106,8 @@ int for_each_remote_ref_submodule(const char *submodule, each_ref_fn fn, void *c
2106
2107 int for_each_replace_ref(each_ref_fn fn, void *cb_data)
2108 {
2109 - return do_for_each_ref(&ref_cache, "refs/replace/", fn, 13, 0, cb_data);
2109 + return do_for_each_ref(&ref_cache, git_replace_ref_base, fn,
2110 + strlen(git_replace_ref_base), 0, cb_data);
2111 }
2112
2113 int head_ref_namespaced(each_ref_fn fn, void *cb_data)