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>
This commit is contained in:
Mike Hommey 2015-06-12 06:34:59 +09:00 committed by Junio C Hamano
parent f86f31ab33
commit 58d121b22b
5 changed files with 16 additions and 6 deletions

View File

@ -104,9 +104,9 @@ static int for_each_replace_name(const char **argv, each_replace_name_fn fn)
continue; continue;
} }
full_hex = sha1_to_hex(sha1); 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 */ /* 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)) { if (read_ref(ref, sha1)) {
error("replace ref '%s' not found.", full_hex); error("replace ref '%s' not found.", full_hex);
had_error = 1; had_error = 1;
@ -134,7 +134,7 @@ static void check_ref_valid(unsigned char object[20],
int force) int force)
{ {
if (snprintf(ref, ref_size, if (snprintf(ref, ref_size,
"refs/replace/%s", "%s%s", git_replace_ref_base,
sha1_to_hex(object)) > ref_size - 1) sha1_to_hex(object)) > ref_size - 1)
die("replace ref name too long: %.*s...", 50, ref); die("replace ref name too long: %.*s...", 50, ref);
if (check_refname_format(ref, 0)) if (check_refname_format(ref, 0))

View File

@ -397,6 +397,7 @@ static inline enum object_type object_type(unsigned int mode)
#define EXEC_PATH_ENVIRONMENT "GIT_EXEC_PATH" #define EXEC_PATH_ENVIRONMENT "GIT_EXEC_PATH"
#define CEILING_DIRECTORIES_ENVIRONMENT "GIT_CEILING_DIRECTORIES" #define CEILING_DIRECTORIES_ENVIRONMENT "GIT_CEILING_DIRECTORIES"
#define NO_REPLACE_OBJECTS_ENVIRONMENT "GIT_NO_REPLACE_OBJECTS" #define NO_REPLACE_OBJECTS_ENVIRONMENT "GIT_NO_REPLACE_OBJECTS"
#define GIT_REPLACE_REF_BASE_ENVIRONMENT "GIT_REPLACE_REF_BASE"
#define GITATTRIBUTES_FILE ".gitattributes" #define GITATTRIBUTES_FILE ".gitattributes"
#define INFOATTRIBUTES_FILE "info/attributes" #define INFOATTRIBUTES_FILE "info/attributes"
#define ATTRIBUTE_MACRO_PREFIX "[attr]" #define ATTRIBUTE_MACRO_PREFIX "[attr]"
@ -622,6 +623,7 @@ extern unsigned long pack_size_limit_cfg;
* been sought but there were none. * been sought but there were none.
*/ */
extern int check_replace_refs; extern int check_replace_refs;
extern char *git_replace_ref_base;
extern int fsync_object_files; extern int fsync_object_files;
extern int core_preload_index; extern int core_preload_index;

View File

@ -47,6 +47,7 @@ const char *askpass_program;
const char *excludes_file; const char *excludes_file;
enum auto_crlf auto_crlf = AUTO_CRLF_FALSE; enum auto_crlf auto_crlf = AUTO_CRLF_FALSE;
int check_replace_refs = 1; int check_replace_refs = 1;
char *git_replace_ref_base;
enum eol core_eol = EOL_UNSET; enum eol core_eol = EOL_UNSET;
enum safe_crlf safe_crlf = SAFE_CRLF_WARN; enum safe_crlf safe_crlf = SAFE_CRLF_WARN;
unsigned whitespace_rule_cfg = WS_DEFAULT_RULE; unsigned whitespace_rule_cfg = WS_DEFAULT_RULE;
@ -110,6 +111,7 @@ const char * const local_repo_env[] = {
GRAFT_ENVIRONMENT, GRAFT_ENVIRONMENT,
INDEX_ENVIRONMENT, INDEX_ENVIRONMENT,
NO_REPLACE_OBJECTS_ENVIRONMENT, NO_REPLACE_OBJECTS_ENVIRONMENT,
GIT_REPLACE_REF_BASE_ENVIRONMENT,
GIT_PREFIX_ENVIRONMENT, GIT_PREFIX_ENVIRONMENT,
GIT_SHALLOW_FILE_ENVIRONMENT, GIT_SHALLOW_FILE_ENVIRONMENT,
GIT_COMMON_DIR_ENVIRONMENT, GIT_COMMON_DIR_ENVIRONMENT,
@ -156,6 +158,7 @@ static void setup_git_env(void)
struct strbuf sb = STRBUF_INIT; struct strbuf sb = STRBUF_INIT;
const char *gitfile; const char *gitfile;
const char *shallow_file; const char *shallow_file;
const char *replace_ref_base;
git_dir = getenv(GIT_DIR_ENVIRONMENT); git_dir = getenv(GIT_DIR_ENVIRONMENT);
if (!git_dir) if (!git_dir)
@ -173,6 +176,9 @@ static void setup_git_env(void)
"info/grafts", &git_graft_env); "info/grafts", &git_graft_env);
if (getenv(NO_REPLACE_OBJECTS_ENVIRONMENT)) if (getenv(NO_REPLACE_OBJECTS_ENVIRONMENT))
check_replace_refs = 0; 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 = expand_namespace(getenv(GIT_NAMESPACE_ENVIRONMENT));
namespace_len = strlen(namespace); namespace_len = strlen(namespace);
shallow_file = getenv(GIT_SHALLOW_FILE_ENVIRONMENT); shallow_file = getenv(GIT_SHALLOW_FILE_ENVIRONMENT);

View File

@ -96,11 +96,12 @@ static int add_ref_decoration(const char *refname, const unsigned char *sha1, in
assert(cb_data == NULL); assert(cb_data == NULL);
if (starts_with(refname, "refs/replace/")) { if (starts_with(refname, git_replace_ref_base)) {
unsigned char original_sha1[20]; unsigned char original_sha1[20];
if (!check_replace_refs) if (!check_replace_refs)
return 0; 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); warning("invalid replace ref %s", refname);
return 0; return 0;
} }

3
refs.c
View File

@ -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) 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) int head_ref_namespaced(each_ref_fn fn, void *cb_data)