Allow to control where the replace refs are looked for
authorMike Hommey <mh@glandium.org>
Thu, 11 Jun 2015 21:34:59 +0000 (06:34 +0900)
committerJunio C Hamano <gitster@pobox.com>
Fri, 12 Jun 2015 22:28:17 +0000 (15:28 -0700)
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>
builtin/replace.c
cache.h
environment.c
log-tree.c
refs.c
index 54bf01acb4ca060a1dae43b399a6aefb1abe4eee..b5b7139645fedfc34eebf63eb2d11bd706d19542 100644 (file)
@@ -104,9 +104,9 @@ static int for_each_replace_name(const char **argv, each_replace_name_fn fn)
                        continue;
                }
                full_hex = sha1_to_hex(sha1);
-               snprintf(ref, sizeof(ref), "refs/replace/%s", full_hex);
+               snprintf(ref, sizeof(ref), "%s%s", git_replace_ref_base, full_hex);
                /* read_ref() may reuse the buffer */
-               full_hex = ref + strlen("refs/replace/");
+               full_hex = ref + strlen(git_replace_ref_base);
                if (read_ref(ref, sha1)) {
                        error("replace ref '%s' not found.", full_hex);
                        had_error = 1;
@@ -134,7 +134,7 @@ static void check_ref_valid(unsigned char object[20],
                            int force)
 {
        if (snprintf(ref, ref_size,
-                    "refs/replace/%s",
+                    "%s%s", git_replace_ref_base,
                     sha1_to_hex(object)) > ref_size - 1)
                die("replace ref name too long: %.*s...", 50, ref);
        if (check_refname_format(ref, 0))
diff --git a/cache.h b/cache.h
index 571c98f5e2406afad1352fcaddd1efff1af65cc1..83b902befba1dd59a336bdc9e484a6c35dd628d6 100644 (file)
--- a/cache.h
+++ b/cache.h
@@ -397,6 +397,7 @@ static inline enum object_type object_type(unsigned int mode)
 #define EXEC_PATH_ENVIRONMENT "GIT_EXEC_PATH"
 #define CEILING_DIRECTORIES_ENVIRONMENT "GIT_CEILING_DIRECTORIES"
 #define NO_REPLACE_OBJECTS_ENVIRONMENT "GIT_NO_REPLACE_OBJECTS"
+#define GIT_REPLACE_REF_BASE_ENVIRONMENT "GIT_REPLACE_REF_BASE"
 #define GITATTRIBUTES_FILE ".gitattributes"
 #define INFOATTRIBUTES_FILE "info/attributes"
 #define ATTRIBUTE_MACRO_PREFIX "[attr]"
@@ -622,6 +623,7 @@ extern unsigned long pack_size_limit_cfg;
  * been sought but there were none.
  */
 extern int check_replace_refs;
+extern char *git_replace_ref_base;
 
 extern int fsync_object_files;
 extern int core_preload_index;
index 61c685b8d93091666891f0091d5005fe62543fc2..01cb28dda922a3ce36836d19d30467381c561f51 100644 (file)
@@ -47,6 +47,7 @@ const char *askpass_program;
 const char *excludes_file;
 enum auto_crlf auto_crlf = AUTO_CRLF_FALSE;
 int check_replace_refs = 1;
+char *git_replace_ref_base;
 enum eol core_eol = EOL_UNSET;
 enum safe_crlf safe_crlf = SAFE_CRLF_WARN;
 unsigned whitespace_rule_cfg = WS_DEFAULT_RULE;
@@ -110,6 +111,7 @@ const char * const local_repo_env[] = {
        GRAFT_ENVIRONMENT,
        INDEX_ENVIRONMENT,
        NO_REPLACE_OBJECTS_ENVIRONMENT,
+       GIT_REPLACE_REF_BASE_ENVIRONMENT,
        GIT_PREFIX_ENVIRONMENT,
        GIT_SHALLOW_FILE_ENVIRONMENT,
        GIT_COMMON_DIR_ENVIRONMENT,
@@ -156,6 +158,7 @@ static void setup_git_env(void)
        struct strbuf sb = STRBUF_INIT;
        const char *gitfile;
        const char *shallow_file;
+       const char *replace_ref_base;
 
        git_dir = getenv(GIT_DIR_ENVIRONMENT);
        if (!git_dir)
@@ -173,6 +176,9 @@ static void setup_git_env(void)
                                           "info/grafts", &git_graft_env);
        if (getenv(NO_REPLACE_OBJECTS_ENVIRONMENT))
                check_replace_refs = 0;
+       replace_ref_base = getenv(GIT_REPLACE_REF_BASE_ENVIRONMENT);
+       git_replace_ref_base = xstrdup(replace_ref_base ? replace_ref_base
+                                                         : "refs/replace/");
        namespace = expand_namespace(getenv(GIT_NAMESPACE_ENVIRONMENT));
        namespace_len = strlen(namespace);
        shallow_file = getenv(GIT_SHALLOW_FILE_ENVIRONMENT);
index 8dba7be92e34e511b1d464983bb6d13861f1555e..9c25bbc1c5c4b90233ac48f4469cdd7cfe3c68ad 100644 (file)
@@ -96,11 +96,12 @@ static int add_ref_decoration(const char *refname, const unsigned char *sha1, in
 
        assert(cb_data == NULL);
 
-       if (starts_with(refname, "refs/replace/")) {
+       if (starts_with(refname, git_replace_ref_base)) {
                unsigned char original_sha1[20];
                if (!check_replace_refs)
                        return 0;
-               if (get_sha1_hex(refname + 13, original_sha1)) {
+               if (get_sha1_hex(refname + strlen(git_replace_ref_base),
+                                original_sha1)) {
                        warning("invalid replace ref %s", refname);
                        return 0;
                }
diff --git a/refs.c b/refs.c
index 8480d8dbf5c78c28d895c9c1a2ac7aa5305f4e5e..6fc65d239f966b8c99ab94da4a2f5fb47108c08a 100644 (file)
--- a/refs.c
+++ b/refs.c
@@ -2106,7 +2106,8 @@ int for_each_remote_ref_submodule(const char *submodule, each_ref_fn fn, void *c
 
 int for_each_replace_ref(each_ref_fn fn, void *cb_data)
 {
-       return do_for_each_ref(&ref_cache, "refs/replace/", fn, 13, 0, cb_data);
+       return do_for_each_ref(&ref_cache, git_replace_ref_base, fn,
+                              strlen(git_replace_ref_base), 0, cb_data);
 }
 
 int head_ref_namespaced(each_ref_fn fn, void *cb_data)