mirror of
https://github.com/git/git.git
synced 2024-11-23 18:05:29 +08:00
Merge branch 'ds/disable-replace-refs'
Introduce a mechanism to disable replace refs globally and per repository. * ds/disable-replace-refs: repository: create read_replace_refs setting replace-objects: create wrapper around setting repository: create disable_replace_refs()
This commit is contained in:
commit
d9f9f6b358
@ -805,7 +805,7 @@ static int batch_objects(struct batch_options *opt)
|
|||||||
if (repo_has_promisor_remote(the_repository))
|
if (repo_has_promisor_remote(the_repository))
|
||||||
warning("This repository uses promisor remotes. Some objects may not be loaded.");
|
warning("This repository uses promisor remotes. Some objects may not be loaded.");
|
||||||
|
|
||||||
read_replace_refs = 0;
|
disable_replace_refs();
|
||||||
|
|
||||||
cb.opt = opt;
|
cb.opt = opt;
|
||||||
cb.expand = &data;
|
cb.expand = &data;
|
||||||
|
@ -324,7 +324,7 @@ int cmd_commit_graph(int argc, const char **argv, const char *prefix)
|
|||||||
|
|
||||||
git_config(git_default_config, NULL);
|
git_config(git_default_config, NULL);
|
||||||
|
|
||||||
read_replace_refs = 0;
|
disable_replace_refs();
|
||||||
save_commit_buffer = 0;
|
save_commit_buffer = 0;
|
||||||
|
|
||||||
argc = parse_options(argc, argv, prefix, options,
|
argc = parse_options(argc, argv, prefix, options,
|
||||||
|
@ -929,7 +929,7 @@ int cmd_fsck(int argc, const char **argv, const char *prefix)
|
|||||||
fetch_if_missing = 0;
|
fetch_if_missing = 0;
|
||||||
|
|
||||||
errors_found = 0;
|
errors_found = 0;
|
||||||
read_replace_refs = 0;
|
disable_replace_refs();
|
||||||
save_commit_buffer = 0;
|
save_commit_buffer = 0;
|
||||||
|
|
||||||
argc = parse_options(argc, argv, prefix, fsck_opts, fsck_usage, 0);
|
argc = parse_options(argc, argv, prefix, fsck_opts, fsck_usage, 0);
|
||||||
|
@ -1752,7 +1752,7 @@ int cmd_index_pack(int argc, const char **argv, const char *prefix)
|
|||||||
if (argc == 2 && !strcmp(argv[1], "-h"))
|
if (argc == 2 && !strcmp(argv[1], "-h"))
|
||||||
usage(index_pack_usage);
|
usage(index_pack_usage);
|
||||||
|
|
||||||
read_replace_refs = 0;
|
disable_replace_refs();
|
||||||
fsck_options.walk = mark_link;
|
fsck_options.walk = mark_link;
|
||||||
|
|
||||||
reset_pack_idx_option(&opts);
|
reset_pack_idx_option(&opts);
|
||||||
|
@ -4284,7 +4284,7 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix)
|
|||||||
if (DFS_NUM_STATES > (1 << OE_DFS_STATE_BITS))
|
if (DFS_NUM_STATES > (1 << OE_DFS_STATE_BITS))
|
||||||
BUG("too many dfs states, increase OE_DFS_STATE_BITS");
|
BUG("too many dfs states, increase OE_DFS_STATE_BITS");
|
||||||
|
|
||||||
read_replace_refs = 0;
|
disable_replace_refs();
|
||||||
|
|
||||||
sparse = git_env_bool("GIT_TEST_PACK_SPARSE", -1);
|
sparse = git_env_bool("GIT_TEST_PACK_SPARSE", -1);
|
||||||
if (the_repository->gitdir) {
|
if (the_repository->gitdir) {
|
||||||
|
@ -164,7 +164,7 @@ int cmd_prune(int argc, const char **argv, const char *prefix)
|
|||||||
|
|
||||||
expire = TIME_MAX;
|
expire = TIME_MAX;
|
||||||
save_commit_buffer = 0;
|
save_commit_buffer = 0;
|
||||||
read_replace_refs = 0;
|
disable_replace_refs();
|
||||||
repo_init_revisions(the_repository, &revs, prefix);
|
repo_init_revisions(the_repository, &revs, prefix);
|
||||||
|
|
||||||
argc = parse_options(argc, argv, prefix, options, prune_usage, 0);
|
argc = parse_options(argc, argv, prefix, options, prune_usage, 0);
|
||||||
|
@ -566,7 +566,7 @@ int cmd_replace(int argc, const char **argv, const char *prefix)
|
|||||||
OPT_END()
|
OPT_END()
|
||||||
};
|
};
|
||||||
|
|
||||||
read_replace_refs = 0;
|
disable_replace_refs();
|
||||||
git_config(git_default_config, NULL);
|
git_config(git_default_config, NULL);
|
||||||
|
|
||||||
argc = parse_options(argc, argv, prefix, options, git_replace_usage, 0);
|
argc = parse_options(argc, argv, prefix, options, git_replace_usage, 0);
|
||||||
|
@ -609,7 +609,7 @@ int cmd_unpack_objects(int argc, const char **argv, const char *prefix UNUSED)
|
|||||||
int i;
|
int i;
|
||||||
struct object_id oid;
|
struct object_id oid;
|
||||||
|
|
||||||
read_replace_refs = 0;
|
disable_replace_refs();
|
||||||
|
|
||||||
git_config(git_default_config, NULL);
|
git_config(git_default_config, NULL);
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@ int cmd_upload_pack(int argc, const char **argv, const char *prefix)
|
|||||||
};
|
};
|
||||||
|
|
||||||
packet_trace_identity("upload-pack");
|
packet_trace_identity("upload-pack");
|
||||||
read_replace_refs = 0;
|
disable_replace_refs();
|
||||||
|
|
||||||
argc = parse_options(argc, argv, prefix, options, upload_pack_usage, 0);
|
argc = parse_options(argc, argv, prefix, options, upload_pack_usage, 0);
|
||||||
|
|
||||||
|
@ -204,14 +204,12 @@ static struct commit_graph *alloc_commit_graph(void)
|
|||||||
return g;
|
return g;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern int read_replace_refs;
|
|
||||||
|
|
||||||
static int commit_graph_compatible(struct repository *r)
|
static int commit_graph_compatible(struct repository *r)
|
||||||
{
|
{
|
||||||
if (!r->gitdir)
|
if (!r->gitdir)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (read_replace_refs) {
|
if (replace_refs_enabled(r)) {
|
||||||
prepare_replace_object(r);
|
prepare_replace_object(r);
|
||||||
if (hashmap_get_size(&r->objects->replace_map->map))
|
if (hashmap_get_size(&r->objects->replace_map->map))
|
||||||
return 0;
|
return 0;
|
||||||
|
5
config.c
5
config.c
@ -1841,11 +1841,6 @@ static int git_default_core_config(const char *var, const char *value, void *cb)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!strcmp(var, "core.usereplacerefs")) {
|
|
||||||
read_replace_refs = git_config_bool(var, value);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Add other config variables here and to Documentation/config.txt. */
|
/* Add other config variables here and to Documentation/config.txt. */
|
||||||
return platform_core_config(var, value, cb);
|
return platform_core_config(var, value, cb);
|
||||||
}
|
}
|
||||||
|
@ -62,7 +62,6 @@ const char *editor_program;
|
|||||||
const char *askpass_program;
|
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 read_replace_refs = 1;
|
|
||||||
enum eol core_eol = EOL_UNSET;
|
enum eol core_eol = EOL_UNSET;
|
||||||
int global_conv_flags_eol = CONV_EOL_RNDTRP_WARN;
|
int global_conv_flags_eol = CONV_EOL_RNDTRP_WARN;
|
||||||
char *check_roundtrip_encoding = "SHIFT-JIS";
|
char *check_roundtrip_encoding = "SHIFT-JIS";
|
||||||
@ -183,7 +182,7 @@ void setup_git_env(const char *git_dir)
|
|||||||
strvec_clear(&to_free);
|
strvec_clear(&to_free);
|
||||||
|
|
||||||
if (getenv(NO_REPLACE_OBJECTS_ENVIRONMENT))
|
if (getenv(NO_REPLACE_OBJECTS_ENVIRONMENT))
|
||||||
read_replace_refs = 0;
|
disable_replace_refs();
|
||||||
replace_ref_base = getenv(GIT_REPLACE_REF_BASE_ENVIRONMENT);
|
replace_ref_base = getenv(GIT_REPLACE_REF_BASE_ENVIRONMENT);
|
||||||
git_replace_ref_base = xstrdup(replace_ref_base ? replace_ref_base
|
git_replace_ref_base = xstrdup(replace_ref_base ? replace_ref_base
|
||||||
: "refs/replace/");
|
: "refs/replace/");
|
||||||
|
2
git.c
2
git.c
@ -186,7 +186,7 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
|
|||||||
if (envchanged)
|
if (envchanged)
|
||||||
*envchanged = 1;
|
*envchanged = 1;
|
||||||
} else if (!strcmp(cmd, "--no-replace-objects")) {
|
} else if (!strcmp(cmd, "--no-replace-objects")) {
|
||||||
read_replace_refs = 0;
|
disable_replace_refs();
|
||||||
setenv(NO_REPLACE_OBJECTS_ENVIRONMENT, "1", 1);
|
setenv(NO_REPLACE_OBJECTS_ENVIRONMENT, "1", 1);
|
||||||
if (envchanged)
|
if (envchanged)
|
||||||
*envchanged = 1;
|
*envchanged = 1;
|
||||||
|
@ -156,7 +156,7 @@ static int add_ref_decoration(const char *refname, const struct object_id *oid,
|
|||||||
|
|
||||||
if (starts_with(refname, git_replace_ref_base)) {
|
if (starts_with(refname, git_replace_ref_base)) {
|
||||||
struct object_id original_oid;
|
struct object_id original_oid;
|
||||||
if (!read_replace_refs)
|
if (!replace_refs_enabled(the_repository))
|
||||||
return 0;
|
return 0;
|
||||||
if (get_oid_hex(refname + strlen(git_replace_ref_base),
|
if (get_oid_hex(refname + strlen(git_replace_ref_base),
|
||||||
&original_oid)) {
|
&original_oid)) {
|
||||||
|
@ -64,7 +64,7 @@ void prepare_replace_object(struct repository *r)
|
|||||||
* replacement object's name (replaced recursively, if necessary).
|
* replacement object's name (replaced recursively, if necessary).
|
||||||
* The return value is either oid or a pointer to a
|
* The return value is either oid or a pointer to a
|
||||||
* permanently-allocated value. This function always respects replace
|
* permanently-allocated value. This function always respects replace
|
||||||
* references, regardless of the value of read_replace_refs.
|
* references, regardless of the value of r->settings.read_replace_refs.
|
||||||
*/
|
*/
|
||||||
const struct object_id *do_lookup_replace_object(struct repository *r,
|
const struct object_id *do_lookup_replace_object(struct repository *r,
|
||||||
const struct object_id *oid)
|
const struct object_id *oid)
|
||||||
@ -84,3 +84,29 @@ const struct object_id *do_lookup_replace_object(struct repository *r,
|
|||||||
}
|
}
|
||||||
die(_("replace depth too high for object %s"), oid_to_hex(oid));
|
die(_("replace depth too high for object %s"), oid_to_hex(oid));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This indicator determines whether replace references should be
|
||||||
|
* respected process-wide, regardless of which repository is being
|
||||||
|
* using at the time.
|
||||||
|
*/
|
||||||
|
static int read_replace_refs = 1;
|
||||||
|
|
||||||
|
void disable_replace_refs(void)
|
||||||
|
{
|
||||||
|
read_replace_refs = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int replace_refs_enabled(struct repository *r)
|
||||||
|
{
|
||||||
|
if (!read_replace_refs)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (r->gitdir) {
|
||||||
|
prepare_repo_settings(r);
|
||||||
|
return r->settings.read_replace_refs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* repository has no objects or refs. */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
@ -5,14 +5,6 @@
|
|||||||
#include "repository.h"
|
#include "repository.h"
|
||||||
#include "object-store.h"
|
#include "object-store.h"
|
||||||
|
|
||||||
/*
|
|
||||||
* Do replace refs need to be checked this run? This variable is
|
|
||||||
* initialized to true unless --no-replace-object is used or
|
|
||||||
* $GIT_NO_REPLACE_OBJECTS is set, but is set to false by some
|
|
||||||
* commands that do not want replace references to be active.
|
|
||||||
*/
|
|
||||||
extern int read_replace_refs;
|
|
||||||
|
|
||||||
struct replace_object {
|
struct replace_object {
|
||||||
struct oidmap_entry original;
|
struct oidmap_entry original;
|
||||||
struct object_id replacement;
|
struct object_id replacement;
|
||||||
@ -27,6 +19,18 @@ void prepare_replace_object(struct repository *r);
|
|||||||
const struct object_id *do_lookup_replace_object(struct repository *r,
|
const struct object_id *do_lookup_replace_object(struct repository *r,
|
||||||
const struct object_id *oid);
|
const struct object_id *oid);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Some commands disable replace-refs unconditionally, and otherwise each
|
||||||
|
* repository could alter the core.useReplaceRefs config value.
|
||||||
|
*
|
||||||
|
* Return 1 if and only if all of the following are true:
|
||||||
|
*
|
||||||
|
* a. disable_replace_refs() has not been called.
|
||||||
|
* b. GIT_NO_REPLACE_OBJECTS is unset or zero.
|
||||||
|
* c. the given repository does not have core.useReplaceRefs=false.
|
||||||
|
*/
|
||||||
|
int replace_refs_enabled(struct repository *r);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If object sha1 should be replaced, return the replacement object's
|
* If object sha1 should be replaced, return the replacement object's
|
||||||
* name (replaced recursively, if necessary). The return value is
|
* name (replaced recursively, if necessary). The return value is
|
||||||
@ -41,11 +45,19 @@ const struct object_id *do_lookup_replace_object(struct repository *r,
|
|||||||
static inline const struct object_id *lookup_replace_object(struct repository *r,
|
static inline const struct object_id *lookup_replace_object(struct repository *r,
|
||||||
const struct object_id *oid)
|
const struct object_id *oid)
|
||||||
{
|
{
|
||||||
if (!read_replace_refs ||
|
if (!replace_refs_enabled(r) ||
|
||||||
(r->objects->replace_map_initialized &&
|
(r->objects->replace_map_initialized &&
|
||||||
r->objects->replace_map->map.tablesize == 0))
|
r->objects->replace_map->map.tablesize == 0))
|
||||||
return oid;
|
return oid;
|
||||||
return do_lookup_replace_object(r, oid);
|
return do_lookup_replace_object(r, oid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Some commands override config and environment settings for using
|
||||||
|
* replace references. Use this method to disable the setting and ensure
|
||||||
|
* those other settings will not override this choice. This applies
|
||||||
|
* globally to all in-process repositories.
|
||||||
|
*/
|
||||||
|
void disable_replace_refs(void);
|
||||||
|
|
||||||
#endif /* REPLACE_OBJECT_H */
|
#endif /* REPLACE_OBJECT_H */
|
||||||
|
@ -67,6 +67,7 @@ void prepare_repo_settings(struct repository *r)
|
|||||||
repo_cfg_bool(r, "pack.usebitmapboundarytraversal",
|
repo_cfg_bool(r, "pack.usebitmapboundarytraversal",
|
||||||
&r->settings.pack_use_bitmap_boundary_traversal,
|
&r->settings.pack_use_bitmap_boundary_traversal,
|
||||||
r->settings.pack_use_bitmap_boundary_traversal);
|
r->settings.pack_use_bitmap_boundary_traversal);
|
||||||
|
repo_cfg_bool(r, "core.usereplacerefs", &r->settings.read_replace_refs, 1);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The GIT_TEST_MULTI_PACK_INDEX variable is special in that
|
* The GIT_TEST_MULTI_PACK_INDEX variable is special in that
|
||||||
|
@ -39,6 +39,15 @@ struct repo_settings {
|
|||||||
int pack_read_reverse_index;
|
int pack_read_reverse_index;
|
||||||
int pack_use_bitmap_boundary_traversal;
|
int pack_use_bitmap_boundary_traversal;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Does this repository have core.useReplaceRefs=true (on by
|
||||||
|
* default)? This provides a repository-scoped version of this
|
||||||
|
* config, though it could be disabled process-wide via some Git
|
||||||
|
* builtins or the --no-replace-objects option. See
|
||||||
|
* replace_refs_enabled() for more details.
|
||||||
|
*/
|
||||||
|
int read_replace_refs;
|
||||||
|
|
||||||
struct fsmonitor_settings *fsmonitor; /* lazily loaded */
|
struct fsmonitor_settings *fsmonitor; /* lazily loaded */
|
||||||
|
|
||||||
int index_version;
|
int index_version;
|
||||||
|
@ -594,4 +594,44 @@ test_expect_success 'grep partially-cloned submodule' '
|
|||||||
)
|
)
|
||||||
'
|
'
|
||||||
|
|
||||||
|
test_expect_success 'check scope of core.useReplaceRefs' '
|
||||||
|
git init base &&
|
||||||
|
git init base/sub &&
|
||||||
|
|
||||||
|
echo A >base/a &&
|
||||||
|
echo B >base/b &&
|
||||||
|
echo C >base/sub/c &&
|
||||||
|
echo D >base/sub/d &&
|
||||||
|
|
||||||
|
git -C base/sub add c d &&
|
||||||
|
git -C base/sub commit -m "Add files" &&
|
||||||
|
|
||||||
|
git -C base submodule add ./sub &&
|
||||||
|
git -C base add a b sub &&
|
||||||
|
git -C base commit -m "Add files and submodule" &&
|
||||||
|
|
||||||
|
A=$(git -C base rev-parse HEAD:a) &&
|
||||||
|
B=$(git -C base rev-parse HEAD:b) &&
|
||||||
|
C=$(git -C base/sub rev-parse HEAD:c) &&
|
||||||
|
D=$(git -C base/sub rev-parse HEAD:d) &&
|
||||||
|
|
||||||
|
git -C base replace $A $B &&
|
||||||
|
git -C base/sub replace $C $D &&
|
||||||
|
|
||||||
|
test_must_fail git -C base grep --cached --recurse-submodules A &&
|
||||||
|
test_must_fail git -C base grep --cached --recurse-submodules C &&
|
||||||
|
|
||||||
|
git -C base config core.useReplaceRefs false &&
|
||||||
|
git -C base grep --recurse-submodules A &&
|
||||||
|
test_must_fail git -C base grep --cached --recurse-submodules C &&
|
||||||
|
|
||||||
|
git -C base/sub config core.useReplaceRefs false &&
|
||||||
|
git -C base grep --cached --recurse-submodules A &&
|
||||||
|
git -C base grep --cached --recurse-submodules C &&
|
||||||
|
|
||||||
|
git -C base config --unset core.useReplaceRefs &&
|
||||||
|
test_must_fail git -C base grep --cached --recurse-submodules A &&
|
||||||
|
git -C base grep --cached --recurse-submodules C
|
||||||
|
'
|
||||||
|
|
||||||
test_done
|
test_done
|
||||||
|
Loading…
Reference in New Issue
Block a user