mirror of
https://github.com/git/git.git
synced 2024-04-25 12:35:11 +02:00
Merge branch 'ds/sparse-index-protections' into next
Builds on top of the sparse-index infrastructure to mark operations that are not ready to mark with the sparse index, causing them to fall back on fully-populated index that they always have worked with. * ds/sparse-index-protections: (26 commits) name-hash: use expand_to_path() sparse-index: expand_to_path() name-hash: don't add directories to name_hash revision: ensure full index resolve-undo: ensure full index read-cache: ensure full index pathspec: ensure full index merge-recursive: ensure full index entry: ensure full index dir: ensure full index update-index: ensure full index stash: ensure full index rm: ensure full index merge-index: ensure full index ls-files: ensure full index grep: ensure full index fsck: ensure full index difftool: ensure full index commit: ensure full index checkout: ensure full index ...
This commit is contained in:
commit
f1c40f89ba
|
@ -85,8 +85,41 @@ index, as well.
|
|||
|
||||
Next, consumers of the index will be guarded against operating on a
|
||||
sparse-index by inserting calls to `ensure_full_index()` or
|
||||
`expand_index_to_path()`. After these guards are in place, we can begin
|
||||
leaving sparse-directory entries in the in-memory index structure.
|
||||
`expand_index_to_path()`. If a specific path is requested, then those will
|
||||
be protected from within the `index_file_exists()` and `index_name_pos()`
|
||||
API calls: they will call `ensure_full_index()` if necessary. The
|
||||
intention here is to preserve existing behavior when interacting with a
|
||||
sparse-checkout. We don't want a change to happen by accident, without
|
||||
tests. Many of these locations may not need any change before removing the
|
||||
guards, but we should not do so without tests to ensure the expected
|
||||
behavior happens.
|
||||
|
||||
It may be desirable to _change_ the behavior of some commands in the
|
||||
presence of a sparse index or more generally in any sparse-checkout
|
||||
scenario. In such cases, these should be carefully communicated and
|
||||
tested. No such behavior changes are intended during this phase.
|
||||
|
||||
During a scan of the codebase, not every iteration of the cache entries
|
||||
needs an `ensure_full_index()` check. The basic reasons include:
|
||||
|
||||
1. The loop is scanning for entries with non-zero stage. These entries
|
||||
are not collapsed into a sparse-directory entry.
|
||||
|
||||
2. The loop is scanning for submodules. These entries are not collapsed
|
||||
into a sparse-directory entry.
|
||||
|
||||
3. The loop is part of the index API, especially around reading or
|
||||
writing the format.
|
||||
|
||||
4. The loop is checking for correct order of cache entries and that is
|
||||
correct if and only if the sparse-directory entries are in the correct
|
||||
location.
|
||||
|
||||
5. The loop ignores entries with the `SKIP_WORKTREE` bit set, or is
|
||||
otherwise already aware of sparse directory entries.
|
||||
|
||||
6. The sparse-index is disabled at this point when using the split-index
|
||||
feature, so no effort is made to protect the split-index API.
|
||||
|
||||
Even after inserting these guards, we will keep expanding sparse-indexes
|
||||
for most Git commands using the `command_requires_full_index` repository
|
||||
|
|
14
attr.c
14
attr.c
|
@ -733,7 +733,7 @@ static struct attr_stack *read_attr_from_file(const char *path, unsigned flags)
|
|||
return res;
|
||||
}
|
||||
|
||||
static struct attr_stack *read_attr_from_index(const struct index_state *istate,
|
||||
static struct attr_stack *read_attr_from_index(struct index_state *istate,
|
||||
const char *path,
|
||||
unsigned flags)
|
||||
{
|
||||
|
@ -763,7 +763,7 @@ static struct attr_stack *read_attr_from_index(const struct index_state *istate,
|
|||
return res;
|
||||
}
|
||||
|
||||
static struct attr_stack *read_attr(const struct index_state *istate,
|
||||
static struct attr_stack *read_attr(struct index_state *istate,
|
||||
const char *path, unsigned flags)
|
||||
{
|
||||
struct attr_stack *res = NULL;
|
||||
|
@ -855,7 +855,7 @@ static void push_stack(struct attr_stack **attr_stack_p,
|
|||
}
|
||||
}
|
||||
|
||||
static void bootstrap_attr_stack(const struct index_state *istate,
|
||||
static void bootstrap_attr_stack(struct index_state *istate,
|
||||
struct attr_stack **stack)
|
||||
{
|
||||
struct attr_stack *e;
|
||||
|
@ -894,7 +894,7 @@ static void bootstrap_attr_stack(const struct index_state *istate,
|
|||
push_stack(stack, e, NULL, 0);
|
||||
}
|
||||
|
||||
static void prepare_attr_stack(const struct index_state *istate,
|
||||
static void prepare_attr_stack(struct index_state *istate,
|
||||
const char *path, int dirlen,
|
||||
struct attr_stack **stack)
|
||||
{
|
||||
|
@ -1094,7 +1094,7 @@ static void determine_macros(struct all_attrs_item *all_attrs,
|
|||
* If check->check_nr is non-zero, only attributes in check[] are collected.
|
||||
* Otherwise all attributes are collected.
|
||||
*/
|
||||
static void collect_some_attrs(const struct index_state *istate,
|
||||
static void collect_some_attrs(struct index_state *istate,
|
||||
const char *path,
|
||||
struct attr_check *check)
|
||||
{
|
||||
|
@ -1123,7 +1123,7 @@ static void collect_some_attrs(const struct index_state *istate,
|
|||
fill(path, pathlen, basename_offset, check->stack, check->all_attrs, rem);
|
||||
}
|
||||
|
||||
void git_check_attr(const struct index_state *istate,
|
||||
void git_check_attr(struct index_state *istate,
|
||||
const char *path,
|
||||
struct attr_check *check)
|
||||
{
|
||||
|
@ -1140,7 +1140,7 @@ void git_check_attr(const struct index_state *istate,
|
|||
}
|
||||
}
|
||||
|
||||
void git_all_attrs(const struct index_state *istate,
|
||||
void git_all_attrs(struct index_state *istate,
|
||||
const char *path, struct attr_check *check)
|
||||
{
|
||||
int i;
|
||||
|
|
4
attr.h
4
attr.h
|
@ -190,14 +190,14 @@ void attr_check_free(struct attr_check *check);
|
|||
*/
|
||||
const char *git_attr_name(const struct git_attr *);
|
||||
|
||||
void git_check_attr(const struct index_state *istate,
|
||||
void git_check_attr(struct index_state *istate,
|
||||
const char *path, struct attr_check *check);
|
||||
|
||||
/*
|
||||
* Retrieve all attributes that apply to the specified path.
|
||||
* check holds the attributes and their values.
|
||||
*/
|
||||
void git_all_attrs(const struct index_state *istate,
|
||||
void git_all_attrs(struct index_state *istate,
|
||||
const char *path, struct attr_check *check);
|
||||
|
||||
enum git_attr_direction {
|
||||
|
|
|
@ -141,6 +141,8 @@ static int renormalize_tracked_files(const struct pathspec *pathspec, int flags)
|
|||
{
|
||||
int i, retval = 0;
|
||||
|
||||
/* TODO: audit for interaction with sparse-index. */
|
||||
ensure_full_index(&the_index);
|
||||
for (i = 0; i < active_nr; i++) {
|
||||
struct cache_entry *ce = active_cache[i];
|
||||
|
||||
|
|
|
@ -120,6 +120,8 @@ static void checkout_all(const char *prefix, int prefix_length)
|
|||
int i, errs = 0;
|
||||
struct cache_entry *last_ce = NULL;
|
||||
|
||||
/* TODO: audit for interaction with sparse-index. */
|
||||
ensure_full_index(&the_index);
|
||||
for (i = 0; i < active_nr ; i++) {
|
||||
struct cache_entry *ce = active_cache[i];
|
||||
if (ce_stage(ce) != checkout_stage
|
||||
|
|
|
@ -369,6 +369,9 @@ static int checkout_worktree(const struct checkout_opts *opts,
|
|||
NULL);
|
||||
|
||||
enable_delayed_checkout(&state);
|
||||
|
||||
/* TODO: audit for interaction with sparse-index. */
|
||||
ensure_full_index(&the_index);
|
||||
for (pos = 0; pos < active_nr; pos++) {
|
||||
struct cache_entry *ce = active_cache[pos];
|
||||
if (ce->ce_flags & CE_MATCHED) {
|
||||
|
@ -513,6 +516,8 @@ static int checkout_paths(const struct checkout_opts *opts,
|
|||
* Make sure all pathspecs participated in locating the paths
|
||||
* to be checked out.
|
||||
*/
|
||||
/* TODO: audit for interaction with sparse-index. */
|
||||
ensure_full_index(&the_index);
|
||||
for (pos = 0; pos < active_nr; pos++)
|
||||
if (opts->overlay_mode)
|
||||
mark_ce_for_checkout_overlay(active_cache[pos],
|
||||
|
|
|
@ -261,6 +261,8 @@ static int list_paths(struct string_list *list, const char *with_tree,
|
|||
free(max_prefix);
|
||||
}
|
||||
|
||||
/* TODO: audit for interaction with sparse-index. */
|
||||
ensure_full_index(&the_index);
|
||||
for (i = 0; i < active_nr; i++) {
|
||||
const struct cache_entry *ce = active_cache[i];
|
||||
struct string_list_item *item;
|
||||
|
@ -976,6 +978,8 @@ static int prepare_to_commit(const char *index_file, const char *prefix,
|
|||
if (get_oid(parent, &oid)) {
|
||||
int i, ita_nr = 0;
|
||||
|
||||
/* TODO: audit for interaction with sparse-index. */
|
||||
ensure_full_index(&the_index);
|
||||
for (i = 0; i < active_nr; i++)
|
||||
if (ce_intent_to_add(active_cache[i]))
|
||||
ita_nr++;
|
||||
|
|
|
@ -585,6 +585,9 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix,
|
|||
setenv("GIT_DIFFTOOL_DIRDIFF", "true", 1);
|
||||
rc = run_command_v_opt(helper_argv, flags);
|
||||
|
||||
/* TODO: audit for interaction with sparse-index. */
|
||||
ensure_full_index(&wtindex);
|
||||
|
||||
/*
|
||||
* If the diff includes working copy files and those
|
||||
* files were modified during the diff, then the changes
|
||||
|
|
|
@ -881,6 +881,8 @@ int cmd_fsck(int argc, const char **argv, const char *prefix)
|
|||
verify_index_checksum = 1;
|
||||
verify_ce_order = 1;
|
||||
read_cache();
|
||||
/* TODO: audit for interaction with sparse-index. */
|
||||
ensure_full_index(&the_index);
|
||||
for (i = 0; i < active_nr; i++) {
|
||||
unsigned int mode;
|
||||
struct blob *blob;
|
||||
|
|
|
@ -504,6 +504,8 @@ static int grep_cache(struct grep_opt *opt,
|
|||
if (repo_read_index(repo) < 0)
|
||||
die(_("index file corrupt"));
|
||||
|
||||
/* TODO: audit for interaction with sparse-index. */
|
||||
ensure_full_index(repo->index);
|
||||
for (nr = 0; nr < repo->index->cache_nr; nr++) {
|
||||
const struct cache_entry *ce = repo->index->cache[nr];
|
||||
|
||||
|
|
|
@ -57,7 +57,7 @@ static const char *tag_modified = "";
|
|||
static const char *tag_skip_worktree = "";
|
||||
static const char *tag_resolve_undo = "";
|
||||
|
||||
static void write_eolinfo(const struct index_state *istate,
|
||||
static void write_eolinfo(struct index_state *istate,
|
||||
const struct cache_entry *ce, const char *path)
|
||||
{
|
||||
if (show_eol) {
|
||||
|
@ -122,7 +122,7 @@ static void print_debug(const struct cache_entry *ce)
|
|||
}
|
||||
}
|
||||
|
||||
static void show_dir_entry(const struct index_state *istate,
|
||||
static void show_dir_entry(struct index_state *istate,
|
||||
const char *tag, struct dir_entry *ent)
|
||||
{
|
||||
int len = max_prefix_len;
|
||||
|
@ -139,7 +139,7 @@ static void show_dir_entry(const struct index_state *istate,
|
|||
write_name(ent->name);
|
||||
}
|
||||
|
||||
static void show_other_files(const struct index_state *istate,
|
||||
static void show_other_files(struct index_state *istate,
|
||||
const struct dir_struct *dir)
|
||||
{
|
||||
int i;
|
||||
|
@ -152,7 +152,7 @@ static void show_other_files(const struct index_state *istate,
|
|||
}
|
||||
}
|
||||
|
||||
static void show_killed_files(const struct index_state *istate,
|
||||
static void show_killed_files(struct index_state *istate,
|
||||
const struct dir_struct *dir)
|
||||
{
|
||||
int i;
|
||||
|
@ -254,7 +254,7 @@ static void show_ce(struct repository *repo, struct dir_struct *dir,
|
|||
}
|
||||
}
|
||||
|
||||
static void show_ru_info(const struct index_state *istate)
|
||||
static void show_ru_info(struct index_state *istate)
|
||||
{
|
||||
struct string_list_item *item;
|
||||
|
||||
|
@ -317,6 +317,8 @@ static void show_files(struct repository *repo, struct dir_struct *dir)
|
|||
|
||||
if (!(show_cached || show_stage || show_deleted || show_modified))
|
||||
return;
|
||||
/* TODO: audit for interaction with sparse-index. */
|
||||
ensure_full_index(repo->index);
|
||||
for (i = 0; i < repo->index->cache_nr; i++) {
|
||||
const struct cache_entry *ce = repo->index->cache[i];
|
||||
struct stat st;
|
||||
|
@ -494,6 +496,8 @@ void overlay_tree_on_index(struct index_state *istate,
|
|||
die("bad tree-ish %s", tree_name);
|
||||
|
||||
/* Hoist the unmerged entries up to stage #3 to make room */
|
||||
/* TODO: audit for interaction with sparse-index. */
|
||||
ensure_full_index(istate);
|
||||
for (i = 0; i < istate->cache_nr; i++) {
|
||||
struct cache_entry *ce = istate->cache[i];
|
||||
if (!ce_stage(ce))
|
||||
|
|
|
@ -58,6 +58,8 @@ static void merge_one_path(const char *path)
|
|||
static void merge_all(void)
|
||||
{
|
||||
int i;
|
||||
/* TODO: audit for interaction with sparse-index. */
|
||||
ensure_full_index(&the_index);
|
||||
for (i = 0; i < active_nr; i++) {
|
||||
const struct cache_entry *ce = active_cache[i];
|
||||
if (!ce_stage(ce))
|
||||
|
@ -80,6 +82,9 @@ int cmd_merge_index(int argc, const char **argv, const char *prefix)
|
|||
|
||||
read_cache();
|
||||
|
||||
/* TODO: audit for interaction with sparse-index. */
|
||||
ensure_full_index(&the_index);
|
||||
|
||||
i = 1;
|
||||
if (!strcmp(argv[i], "-o")) {
|
||||
one_shot = 1;
|
||||
|
|
|
@ -293,6 +293,8 @@ int cmd_rm(int argc, const char **argv, const char *prefix)
|
|||
|
||||
seen = xcalloc(pathspec.nr, 1);
|
||||
|
||||
/* TODO: audit for interaction with sparse-index. */
|
||||
ensure_full_index(&the_index);
|
||||
for (i = 0; i < active_nr; i++) {
|
||||
const struct cache_entry *ce = active_cache[i];
|
||||
if (!ce_path_match(&the_index, ce, &pathspec, seen))
|
||||
|
|
|
@ -1412,6 +1412,8 @@ static int do_push_stash(const struct pathspec *ps, const char *stash_msg, int q
|
|||
int i;
|
||||
char *ps_matched = xcalloc(ps->nr, 1);
|
||||
|
||||
/* TODO: audit for interaction with sparse-index. */
|
||||
ensure_full_index(&the_index);
|
||||
for (i = 0; i < active_nr; i++)
|
||||
ce_path_match(&the_index, active_cache[i], ps,
|
||||
ps_matched);
|
||||
|
|
|
@ -745,6 +745,8 @@ static int do_reupdate(int ac, const char **av,
|
|||
*/
|
||||
has_head = 0;
|
||||
redo:
|
||||
/* TODO: audit for interaction with sparse-index. */
|
||||
ensure_full_index(&the_index);
|
||||
for (pos = 0; pos < active_nr; pos++) {
|
||||
const struct cache_entry *ce = active_cache[pos];
|
||||
struct cache_entry *old = NULL;
|
||||
|
|
7
cache.h
7
cache.h
|
@ -350,6 +350,7 @@ void add_name_hash(struct index_state *istate, struct cache_entry *ce);
|
|||
void remove_name_hash(struct index_state *istate, struct cache_entry *ce);
|
||||
void free_name_hash(struct index_state *istate);
|
||||
|
||||
void ensure_full_index(struct index_state *istate);
|
||||
|
||||
/* Cache entry creation and cleanup */
|
||||
|
||||
|
@ -800,7 +801,7 @@ struct cache_entry *index_file_exists(struct index_state *istate, const char *na
|
|||
* index_name_pos(&index, "f", 1) -> -3
|
||||
* index_name_pos(&index, "g", 1) -> -5
|
||||
*/
|
||||
int index_name_pos(const struct index_state *, const char *name, int namelen);
|
||||
int index_name_pos(struct index_state *, const char *name, int namelen);
|
||||
|
||||
/*
|
||||
* Some functions return the negative complement of an insert position when a
|
||||
|
@ -850,8 +851,8 @@ int add_file_to_index(struct index_state *, const char *path, int flags);
|
|||
int chmod_index_entry(struct index_state *, struct cache_entry *ce, char flip);
|
||||
int ce_same_name(const struct cache_entry *a, const struct cache_entry *b);
|
||||
void set_object_name_for_intent_to_add_entry(struct cache_entry *ce);
|
||||
int index_name_is_other(const struct index_state *, const char *, int);
|
||||
void *read_blob_data_from_index(const struct index_state *, const char *, unsigned long *);
|
||||
int index_name_is_other(struct index_state *, const char *, int);
|
||||
void *read_blob_data_from_index(struct index_state *, const char *, unsigned long *);
|
||||
|
||||
/* do stat comparison even if CE_VALID is true */
|
||||
#define CE_MATCH_IGNORE_VALID 01
|
||||
|
|
20
convert.c
20
convert.c
|
@ -127,7 +127,7 @@ static const char *gather_convert_stats_ascii(const char *data, unsigned long si
|
|||
}
|
||||
}
|
||||
|
||||
const char *get_cached_convert_stats_ascii(const struct index_state *istate,
|
||||
const char *get_cached_convert_stats_ascii(struct index_state *istate,
|
||||
const char *path)
|
||||
{
|
||||
const char *ret;
|
||||
|
@ -211,7 +211,7 @@ static void check_global_conv_flags_eol(const char *path,
|
|||
}
|
||||
}
|
||||
|
||||
static int has_crlf_in_index(const struct index_state *istate, const char *path)
|
||||
static int has_crlf_in_index(struct index_state *istate, const char *path)
|
||||
{
|
||||
unsigned long sz;
|
||||
void *data;
|
||||
|
@ -485,7 +485,7 @@ static int encode_to_worktree(const char *path, const char *src, size_t src_len,
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int crlf_to_git(const struct index_state *istate,
|
||||
static int crlf_to_git(struct index_state *istate,
|
||||
const char *path, const char *src, size_t len,
|
||||
struct strbuf *buf,
|
||||
enum convert_crlf_action crlf_action, int conv_flags)
|
||||
|
@ -1293,7 +1293,7 @@ static int git_path_check_ident(struct attr_check_item *check)
|
|||
|
||||
static struct attr_check *check;
|
||||
|
||||
void convert_attrs(const struct index_state *istate,
|
||||
void convert_attrs(struct index_state *istate,
|
||||
struct conv_attrs *ca, const char *path)
|
||||
{
|
||||
struct attr_check_item *ccheck = NULL;
|
||||
|
@ -1355,7 +1355,7 @@ void reset_parsed_attributes(void)
|
|||
user_convert_tail = NULL;
|
||||
}
|
||||
|
||||
int would_convert_to_git_filter_fd(const struct index_state *istate, const char *path)
|
||||
int would_convert_to_git_filter_fd(struct index_state *istate, const char *path)
|
||||
{
|
||||
struct conv_attrs ca;
|
||||
|
||||
|
@ -1374,7 +1374,7 @@ int would_convert_to_git_filter_fd(const struct index_state *istate, const char
|
|||
return apply_filter(path, NULL, 0, -1, NULL, ca.drv, CAP_CLEAN, NULL, NULL);
|
||||
}
|
||||
|
||||
const char *get_convert_attr_ascii(const struct index_state *istate, const char *path)
|
||||
const char *get_convert_attr_ascii(struct index_state *istate, const char *path)
|
||||
{
|
||||
struct conv_attrs ca;
|
||||
|
||||
|
@ -1400,7 +1400,7 @@ const char *get_convert_attr_ascii(const struct index_state *istate, const char
|
|||
return "";
|
||||
}
|
||||
|
||||
int convert_to_git(const struct index_state *istate,
|
||||
int convert_to_git(struct index_state *istate,
|
||||
const char *path, const char *src, size_t len,
|
||||
struct strbuf *dst, int conv_flags)
|
||||
{
|
||||
|
@ -1434,7 +1434,7 @@ int convert_to_git(const struct index_state *istate,
|
|||
return ret | ident_to_git(src, len, dst, ca.ident);
|
||||
}
|
||||
|
||||
void convert_to_git_filter_fd(const struct index_state *istate,
|
||||
void convert_to_git_filter_fd(struct index_state *istate,
|
||||
const char *path, int fd, struct strbuf *dst,
|
||||
int conv_flags)
|
||||
{
|
||||
|
@ -1511,7 +1511,7 @@ int convert_to_working_tree_ca(const struct conv_attrs *ca,
|
|||
meta, NULL);
|
||||
}
|
||||
|
||||
int renormalize_buffer(const struct index_state *istate, const char *path,
|
||||
int renormalize_buffer(struct index_state *istate, const char *path,
|
||||
const char *src, size_t len, struct strbuf *dst)
|
||||
{
|
||||
struct conv_attrs ca;
|
||||
|
@ -1972,7 +1972,7 @@ struct stream_filter *get_stream_filter_ca(const struct conv_attrs *ca,
|
|||
return filter;
|
||||
}
|
||||
|
||||
struct stream_filter *get_stream_filter(const struct index_state *istate,
|
||||
struct stream_filter *get_stream_filter(struct index_state *istate,
|
||||
const char *path,
|
||||
const struct object_id *oid)
|
||||
{
|
||||
|
|
22
convert.h
22
convert.h
|
@ -84,19 +84,19 @@ struct conv_attrs {
|
|||
const char *working_tree_encoding; /* Supported encoding or default encoding if NULL */
|
||||
};
|
||||
|
||||
void convert_attrs(const struct index_state *istate,
|
||||
void convert_attrs(struct index_state *istate,
|
||||
struct conv_attrs *ca, const char *path);
|
||||
|
||||
extern enum eol core_eol;
|
||||
extern char *check_roundtrip_encoding;
|
||||
const char *get_cached_convert_stats_ascii(const struct index_state *istate,
|
||||
const char *get_cached_convert_stats_ascii(struct index_state *istate,
|
||||
const char *path);
|
||||
const char *get_wt_convert_stats_ascii(const char *path);
|
||||
const char *get_convert_attr_ascii(const struct index_state *istate,
|
||||
const char *get_convert_attr_ascii(struct index_state *istate,
|
||||
const char *path);
|
||||
|
||||
/* returns 1 if *dst was used */
|
||||
int convert_to_git(const struct index_state *istate,
|
||||
int convert_to_git(struct index_state *istate,
|
||||
const char *path, const char *src, size_t len,
|
||||
struct strbuf *dst, int conv_flags);
|
||||
int convert_to_working_tree_ca(const struct conv_attrs *ca,
|
||||
|
@ -108,7 +108,7 @@ int async_convert_to_working_tree_ca(const struct conv_attrs *ca,
|
|||
size_t len, struct strbuf *dst,
|
||||
const struct checkout_metadata *meta,
|
||||
void *dco);
|
||||
static inline int convert_to_working_tree(const struct index_state *istate,
|
||||
static inline int convert_to_working_tree(struct index_state *istate,
|
||||
const char *path, const char *src,
|
||||
size_t len, struct strbuf *dst,
|
||||
const struct checkout_metadata *meta)
|
||||
|
@ -117,7 +117,7 @@ static inline int convert_to_working_tree(const struct index_state *istate,
|
|||
convert_attrs(istate, &ca, path);
|
||||
return convert_to_working_tree_ca(&ca, path, src, len, dst, meta);
|
||||
}
|
||||
static inline int async_convert_to_working_tree(const struct index_state *istate,
|
||||
static inline int async_convert_to_working_tree(struct index_state *istate,
|
||||
const char *path, const char *src,
|
||||
size_t len, struct strbuf *dst,
|
||||
const struct checkout_metadata *meta,
|
||||
|
@ -129,20 +129,20 @@ static inline int async_convert_to_working_tree(const struct index_state *istate
|
|||
}
|
||||
int async_query_available_blobs(const char *cmd,
|
||||
struct string_list *available_paths);
|
||||
int renormalize_buffer(const struct index_state *istate,
|
||||
int renormalize_buffer(struct index_state *istate,
|
||||
const char *path, const char *src, size_t len,
|
||||
struct strbuf *dst);
|
||||
static inline int would_convert_to_git(const struct index_state *istate,
|
||||
static inline int would_convert_to_git(struct index_state *istate,
|
||||
const char *path)
|
||||
{
|
||||
return convert_to_git(istate, path, NULL, 0, NULL, 0);
|
||||
}
|
||||
/* Precondition: would_convert_to_git_filter_fd(path) == true */
|
||||
void convert_to_git_filter_fd(const struct index_state *istate,
|
||||
void convert_to_git_filter_fd(struct index_state *istate,
|
||||
const char *path, int fd,
|
||||
struct strbuf *dst,
|
||||
int conv_flags);
|
||||
int would_convert_to_git_filter_fd(const struct index_state *istate,
|
||||
int would_convert_to_git_filter_fd(struct index_state *istate,
|
||||
const char *path);
|
||||
|
||||
/*
|
||||
|
@ -176,7 +176,7 @@ void reset_parsed_attributes(void);
|
|||
|
||||
struct stream_filter; /* opaque */
|
||||
|
||||
struct stream_filter *get_stream_filter(const struct index_state *istate,
|
||||
struct stream_filter *get_stream_filter(struct index_state *istate,
|
||||
const char *path,
|
||||
const struct object_id *);
|
||||
struct stream_filter *get_stream_filter_ca(const struct conv_attrs *ca,
|
||||
|
|
14
dir.c
14
dir.c
|
@ -306,7 +306,7 @@ static int do_read_blob(const struct object_id *oid, struct oid_stat *oid_stat,
|
|||
* [1] Only if DO_MATCH_DIRECTORY is passed; otherwise, this is NOT a match.
|
||||
* [2] Only if DO_MATCH_LEADING_PATHSPEC is passed; otherwise, not a match.
|
||||
*/
|
||||
static int match_pathspec_item(const struct index_state *istate,
|
||||
static int match_pathspec_item(struct index_state *istate,
|
||||
const struct pathspec_item *item, int prefix,
|
||||
const char *name, int namelen, unsigned flags)
|
||||
{
|
||||
|
@ -429,7 +429,7 @@ static int match_pathspec_item(const struct index_state *istate,
|
|||
* pathspec did not match any names, which could indicate that the
|
||||
* user mistyped the nth pathspec.
|
||||
*/
|
||||
static int do_match_pathspec(const struct index_state *istate,
|
||||
static int do_match_pathspec(struct index_state *istate,
|
||||
const struct pathspec *ps,
|
||||
const char *name, int namelen,
|
||||
int prefix, char *seen,
|
||||
|
@ -500,7 +500,7 @@ static int do_match_pathspec(const struct index_state *istate,
|
|||
return retval;
|
||||
}
|
||||
|
||||
static int match_pathspec_with_flags(const struct index_state *istate,
|
||||
static int match_pathspec_with_flags(struct index_state *istate,
|
||||
const struct pathspec *ps,
|
||||
const char *name, int namelen,
|
||||
int prefix, char *seen, unsigned flags)
|
||||
|
@ -516,7 +516,7 @@ static int match_pathspec_with_flags(const struct index_state *istate,
|
|||
return negative ? 0 : positive;
|
||||
}
|
||||
|
||||
int match_pathspec(const struct index_state *istate,
|
||||
int match_pathspec(struct index_state *istate,
|
||||
const struct pathspec *ps,
|
||||
const char *name, int namelen,
|
||||
int prefix, char *seen, int is_dir)
|
||||
|
@ -529,7 +529,7 @@ int match_pathspec(const struct index_state *istate,
|
|||
/**
|
||||
* Check if a submodule is a superset of the pathspec
|
||||
*/
|
||||
int submodule_path_match(const struct index_state *istate,
|
||||
int submodule_path_match(struct index_state *istate,
|
||||
const struct pathspec *ps,
|
||||
const char *submodule_name,
|
||||
char *seen)
|
||||
|
@ -892,7 +892,7 @@ void add_pattern(const char *string, const char *base,
|
|||
add_pattern_to_hashsets(pl, pattern);
|
||||
}
|
||||
|
||||
static int read_skip_worktree_file_from_index(const struct index_state *istate,
|
||||
static int read_skip_worktree_file_from_index(struct index_state *istate,
|
||||
const char *path,
|
||||
size_t *size_out, char **data_out,
|
||||
struct oid_stat *oid_stat)
|
||||
|
@ -3542,6 +3542,8 @@ static void connect_wt_gitdir_in_nested(const char *sub_worktree,
|
|||
if (repo_read_index(&subrepo) < 0)
|
||||
die(_("index file corrupt in repo %s"), subrepo.gitdir);
|
||||
|
||||
/* TODO: audit for interaction with sparse-index. */
|
||||
ensure_full_index(subrepo.index);
|
||||
for (i = 0; i < subrepo.index->cache_nr; i++) {
|
||||
const struct cache_entry *ce = subrepo.index->cache[i];
|
||||
|
||||
|
|
8
dir.h
8
dir.h
|
@ -354,7 +354,7 @@ int count_slashes(const char *s);
|
|||
int simple_length(const char *match);
|
||||
int no_wildcard(const char *string);
|
||||
char *common_prefix(const struct pathspec *pathspec);
|
||||
int match_pathspec(const struct index_state *istate,
|
||||
int match_pathspec(struct index_state *istate,
|
||||
const struct pathspec *pathspec,
|
||||
const char *name, int namelen,
|
||||
int prefix, char *seen, int is_dir);
|
||||
|
@ -493,12 +493,12 @@ int git_fnmatch(const struct pathspec_item *item,
|
|||
const char *pattern, const char *string,
|
||||
int prefix);
|
||||
|
||||
int submodule_path_match(const struct index_state *istate,
|
||||
int submodule_path_match(struct index_state *istate,
|
||||
const struct pathspec *ps,
|
||||
const char *submodule_name,
|
||||
char *seen);
|
||||
|
||||
static inline int ce_path_match(const struct index_state *istate,
|
||||
static inline int ce_path_match(struct index_state *istate,
|
||||
const struct cache_entry *ce,
|
||||
const struct pathspec *pathspec,
|
||||
char *seen)
|
||||
|
@ -507,7 +507,7 @@ static inline int ce_path_match(const struct index_state *istate,
|
|||
S_ISDIR(ce->ce_mode) || S_ISGITLINK(ce->ce_mode));
|
||||
}
|
||||
|
||||
static inline int dir_path_match(const struct index_state *istate,
|
||||
static inline int dir_path_match(struct index_state *istate,
|
||||
const struct dir_entry *ent,
|
||||
const struct pathspec *pathspec,
|
||||
int prefix, char *seen)
|
||||
|
|
2
entry.c
2
entry.c
|
@ -423,6 +423,8 @@ static void mark_colliding_entries(const struct checkout *state,
|
|||
|
||||
ce->ce_flags |= CE_MATCHED;
|
||||
|
||||
/* TODO: audit for interaction with sparse-index. */
|
||||
ensure_full_index(state->istate);
|
||||
for (i = 0; i < state->istate->cache_nr; i++) {
|
||||
struct cache_entry *dup = state->istate->cache[i];
|
||||
|
||||
|
|
|
@ -2564,7 +2564,7 @@ static int blob_unchanged(struct merge_options *opt,
|
|||
struct strbuf basebuf = STRBUF_INIT;
|
||||
struct strbuf sidebuf = STRBUF_INIT;
|
||||
int ret = 0; /* assume changed for safety */
|
||||
const struct index_state *idx = &opt->priv->attr_index;
|
||||
struct index_state *idx = &opt->priv->attr_index;
|
||||
|
||||
if (!idx->initialized)
|
||||
initialize_attr_index(opt);
|
||||
|
|
|
@ -522,6 +522,8 @@ static struct string_list *get_unmerged(struct index_state *istate)
|
|||
|
||||
unmerged->strdup_strings = 1;
|
||||
|
||||
/* TODO: audit for interaction with sparse-index. */
|
||||
ensure_full_index(istate);
|
||||
for (i = 0; i < istate->cache_nr; i++) {
|
||||
struct string_list_item *item;
|
||||
struct stage_data *e;
|
||||
|
@ -3014,7 +3016,7 @@ static int blob_unchanged(struct merge_options *opt,
|
|||
struct strbuf obuf = STRBUF_INIT;
|
||||
struct strbuf abuf = STRBUF_INIT;
|
||||
int ret = 0; /* assume changed for safety */
|
||||
const struct index_state *idx = opt->repo->index;
|
||||
struct index_state *idx = opt->repo->index;
|
||||
|
||||
if (a->mode != o->mode)
|
||||
return 0;
|
||||
|
|
11
name-hash.c
11
name-hash.c
|
@ -8,6 +8,7 @@
|
|||
#include "cache.h"
|
||||
#include "thread-utils.h"
|
||||
#include "trace2.h"
|
||||
#include "sparse-index.h"
|
||||
|
||||
struct dir_entry {
|
||||
struct hashmap_entry ent;
|
||||
|
@ -109,8 +110,11 @@ static void hash_index_entry(struct index_state *istate, struct cache_entry *ce)
|
|||
if (ce->ce_flags & CE_HASHED)
|
||||
return;
|
||||
ce->ce_flags |= CE_HASHED;
|
||||
hashmap_entry_init(&ce->ent, memihash(ce->name, ce_namelen(ce)));
|
||||
hashmap_add(&istate->name_hash, &ce->ent);
|
||||
|
||||
if (!S_ISSPARSEDIR(ce->ce_mode)) {
|
||||
hashmap_entry_init(&ce->ent, memihash(ce->name, ce_namelen(ce)));
|
||||
hashmap_add(&istate->name_hash, &ce->ent);
|
||||
}
|
||||
|
||||
if (ignore_case)
|
||||
add_dir_entry(istate, ce);
|
||||
|
@ -680,6 +684,7 @@ int index_dir_exists(struct index_state *istate, const char *name, int namelen)
|
|||
struct dir_entry *dir;
|
||||
|
||||
lazy_init_name_hash(istate);
|
||||
expand_to_path(istate, name, namelen, 0);
|
||||
dir = find_dir_entry(istate, name, namelen);
|
||||
return dir && dir->nr;
|
||||
}
|
||||
|
@ -690,6 +695,7 @@ void adjust_dirname_case(struct index_state *istate, char *name)
|
|||
const char *ptr = startPtr;
|
||||
|
||||
lazy_init_name_hash(istate);
|
||||
expand_to_path(istate, name, strlen(name), 0);
|
||||
while (*ptr) {
|
||||
while (*ptr && *ptr != '/')
|
||||
ptr++;
|
||||
|
@ -713,6 +719,7 @@ struct cache_entry *index_file_exists(struct index_state *istate, const char *na
|
|||
unsigned int hash = memihash(name, namelen);
|
||||
|
||||
lazy_init_name_hash(istate);
|
||||
expand_to_path(istate, name, namelen, icase);
|
||||
|
||||
ce = hashmap_get_entry_from_hash(&istate->name_hash, hash, NULL,
|
||||
struct cache_entry, ent);
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
* to use find_pathspecs_matching_against_index() instead.
|
||||
*/
|
||||
void add_pathspec_matches_against_index(const struct pathspec *pathspec,
|
||||
const struct index_state *istate,
|
||||
struct index_state *istate,
|
||||
char *seen)
|
||||
{
|
||||
int num_unmatched = 0, i;
|
||||
|
@ -36,6 +36,8 @@ void add_pathspec_matches_against_index(const struct pathspec *pathspec,
|
|||
num_unmatched++;
|
||||
if (!num_unmatched)
|
||||
return;
|
||||
/* TODO: audit for interaction with sparse-index. */
|
||||
ensure_full_index(istate);
|
||||
for (i = 0; i < istate->cache_nr; i++) {
|
||||
const struct cache_entry *ce = istate->cache[i];
|
||||
ce_path_match(istate, ce, pathspec, seen);
|
||||
|
@ -51,7 +53,7 @@ void add_pathspec_matches_against_index(const struct pathspec *pathspec,
|
|||
* given pathspecs achieves against all items in the index.
|
||||
*/
|
||||
char *find_pathspecs_matching_against_index(const struct pathspec *pathspec,
|
||||
const struct index_state *istate)
|
||||
struct index_state *istate)
|
||||
{
|
||||
char *seen = xcalloc(pathspec->nr, 1);
|
||||
add_pathspec_matches_against_index(pathspec, istate, seen);
|
||||
|
@ -702,7 +704,7 @@ void clear_pathspec(struct pathspec *pathspec)
|
|||
pathspec->nr = 0;
|
||||
}
|
||||
|
||||
int match_pathspec_attrs(const struct index_state *istate,
|
||||
int match_pathspec_attrs(struct index_state *istate,
|
||||
const char *name, int namelen,
|
||||
const struct pathspec_item *item)
|
||||
{
|
||||
|
|
|
@ -150,11 +150,11 @@ static inline int ps_strcmp(const struct pathspec_item *item,
|
|||
}
|
||||
|
||||
void add_pathspec_matches_against_index(const struct pathspec *pathspec,
|
||||
const struct index_state *istate,
|
||||
struct index_state *istate,
|
||||
char *seen);
|
||||
char *find_pathspecs_matching_against_index(const struct pathspec *pathspec,
|
||||
const struct index_state *istate);
|
||||
int match_pathspec_attrs(const struct index_state *istate,
|
||||
struct index_state *istate);
|
||||
int match_pathspec_attrs(struct index_state *istate,
|
||||
const char *name, int namelen,
|
||||
const struct pathspec_item *item);
|
||||
|
||||
|
|
35
read-cache.c
35
read-cache.c
|
@ -549,7 +549,7 @@ int cache_name_stage_compare(const char *name1, int len1, int stage1, const char
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int index_name_stage_pos(const struct index_state *istate, const char *name, int namelen, int stage)
|
||||
static int index_name_stage_pos(struct index_state *istate, const char *name, int namelen, int stage)
|
||||
{
|
||||
int first, last;
|
||||
|
||||
|
@ -567,10 +567,31 @@ static int index_name_stage_pos(const struct index_state *istate, const char *na
|
|||
}
|
||||
first = next+1;
|
||||
}
|
||||
|
||||
if (istate->sparse_index &&
|
||||
first > 0) {
|
||||
/* Note: first <= istate->cache_nr */
|
||||
struct cache_entry *ce = istate->cache[first - 1];
|
||||
|
||||
/*
|
||||
* If we are in a sparse-index _and_ the entry before the
|
||||
* insertion position is a sparse-directory entry that is
|
||||
* an ancestor of 'name', then we need to expand the index
|
||||
* and search again. This will only trigger once, because
|
||||
* thereafter the index is fully expanded.
|
||||
*/
|
||||
if (S_ISSPARSEDIR(ce->ce_mode) &&
|
||||
ce_namelen(ce) < namelen &&
|
||||
!strncmp(name, ce->name, ce_namelen(ce))) {
|
||||
ensure_full_index(istate);
|
||||
return index_name_stage_pos(istate, name, namelen, stage);
|
||||
}
|
||||
}
|
||||
|
||||
return -first-1;
|
||||
}
|
||||
|
||||
int index_name_pos(const struct index_state *istate, const char *name, int namelen)
|
||||
int index_name_pos(struct index_state *istate, const char *name, int namelen)
|
||||
{
|
||||
return index_name_stage_pos(istate, name, namelen, 0);
|
||||
}
|
||||
|
@ -1556,6 +1577,8 @@ int refresh_index(struct index_state *istate, unsigned int flags,
|
|||
*/
|
||||
preload_index(istate, pathspec, 0);
|
||||
trace2_region_enter("index", "refresh", NULL);
|
||||
/* TODO: audit for interaction with sparse-index. */
|
||||
ensure_full_index(istate);
|
||||
for (i = 0; i < istate->cache_nr; i++) {
|
||||
struct cache_entry *ce, *new_entry;
|
||||
int cache_errno = 0;
|
||||
|
@ -2478,6 +2501,8 @@ int repo_index_has_changes(struct repository *repo,
|
|||
diff_flush(&opt);
|
||||
return opt.flags.has_changes != 0;
|
||||
} else {
|
||||
/* TODO: audit for interaction with sparse-index. */
|
||||
ensure_full_index(istate);
|
||||
for (i = 0; sb && i < istate->cache_nr; i++) {
|
||||
if (i)
|
||||
strbuf_addch(sb, ' ');
|
||||
|
@ -3390,8 +3415,8 @@ int repo_read_index_unmerged(struct repository *repo)
|
|||
* We helpfully remove a trailing "/" from directories so that
|
||||
* the output of read_directory can be used as-is.
|
||||
*/
|
||||
int index_name_is_other(const struct index_state *istate, const char *name,
|
||||
int namelen)
|
||||
int index_name_is_other(struct index_state *istate, const char *name,
|
||||
int namelen)
|
||||
{
|
||||
int pos;
|
||||
if (namelen && name[namelen - 1] == '/')
|
||||
|
@ -3409,7 +3434,7 @@ int index_name_is_other(const struct index_state *istate, const char *name,
|
|||
return 1;
|
||||
}
|
||||
|
||||
void *read_blob_data_from_index(const struct index_state *istate,
|
||||
void *read_blob_data_from_index(struct index_state *istate,
|
||||
const char *path, unsigned long *size)
|
||||
{
|
||||
int pos, len;
|
||||
|
|
|
@ -172,6 +172,8 @@ void unmerge_marked_index(struct index_state *istate)
|
|||
if (!istate->resolve_undo)
|
||||
return;
|
||||
|
||||
/* TODO: audit for interaction with sparse-index. */
|
||||
ensure_full_index(istate);
|
||||
for (i = 0; i < istate->cache_nr; i++) {
|
||||
const struct cache_entry *ce = istate->cache[i];
|
||||
if (ce->ce_flags & CE_MATCHED)
|
||||
|
@ -186,6 +188,8 @@ void unmerge_index(struct index_state *istate, const struct pathspec *pathspec)
|
|||
if (!istate->resolve_undo)
|
||||
return;
|
||||
|
||||
/* TODO: audit for interaction with sparse-index. */
|
||||
ensure_full_index(istate);
|
||||
for (i = 0; i < istate->cache_nr; i++) {
|
||||
const struct cache_entry *ce = istate->cache[i];
|
||||
if (!ce_path_match(istate, ce, pathspec, NULL))
|
||||
|
|
|
@ -1680,6 +1680,8 @@ static void do_add_index_objects_to_pending(struct rev_info *revs,
|
|||
{
|
||||
int i;
|
||||
|
||||
/* TODO: audit for interaction with sparse-index. */
|
||||
ensure_full_index(istate);
|
||||
for (i = 0; i < istate->cache_nr; i++) {
|
||||
struct cache_entry *ce = istate->cache[i];
|
||||
struct blob *blob;
|
||||
|
|
|
@ -283,3 +283,76 @@ void ensure_full_index(struct index_state *istate)
|
|||
|
||||
trace2_region_leave("index", "ensure_full_index", istate->repo);
|
||||
}
|
||||
|
||||
/*
|
||||
* This static global helps avoid infinite recursion between
|
||||
* expand_to_path() and index_file_exists().
|
||||
*/
|
||||
static int in_expand_to_path = 0;
|
||||
|
||||
void expand_to_path(struct index_state *istate,
|
||||
const char *path, size_t pathlen, int icase)
|
||||
{
|
||||
struct strbuf path_mutable = STRBUF_INIT;
|
||||
size_t substr_len;
|
||||
|
||||
/* prevent extra recursion */
|
||||
if (in_expand_to_path)
|
||||
return;
|
||||
|
||||
if (!istate || !istate->sparse_index)
|
||||
return;
|
||||
|
||||
if (!istate->repo)
|
||||
istate->repo = the_repository;
|
||||
|
||||
in_expand_to_path = 1;
|
||||
|
||||
/*
|
||||
* We only need to actually expand a region if the
|
||||
* following are both true:
|
||||
*
|
||||
* 1. 'path' is not already in the index.
|
||||
* 2. Some parent directory of 'path' is a sparse directory.
|
||||
*/
|
||||
|
||||
if (index_file_exists(istate, path, pathlen, icase))
|
||||
goto cleanup;
|
||||
|
||||
strbuf_add(&path_mutable, path, pathlen);
|
||||
strbuf_addch(&path_mutable, '/');
|
||||
|
||||
/* Check the name hash for all parent directories */
|
||||
substr_len = 0;
|
||||
while (substr_len < pathlen) {
|
||||
char temp;
|
||||
char *replace = strchr(path_mutable.buf + substr_len, '/');
|
||||
|
||||
if (!replace)
|
||||
break;
|
||||
|
||||
/* replace the character _after_ the slash */
|
||||
replace++;
|
||||
temp = *replace;
|
||||
*replace = '\0';
|
||||
if (index_file_exists(istate, path_mutable.buf,
|
||||
path_mutable.len, icase)) {
|
||||
/*
|
||||
* We found a parent directory in the name-hash
|
||||
* hashtable, because only sparse directory entries
|
||||
* have a trailing '/' character. Since "path" wasn't
|
||||
* in the index, perhaps it exists within this
|
||||
* sparse-directory. Expand accordingly.
|
||||
*/
|
||||
ensure_full_index(istate);
|
||||
break;
|
||||
}
|
||||
|
||||
*replace = temp;
|
||||
substr_len = replace - path_mutable.buf;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
strbuf_release(&path_mutable);
|
||||
in_expand_to_path = 0;
|
||||
}
|
||||
|
|
|
@ -2,9 +2,21 @@
|
|||
#define SPARSE_INDEX_H__
|
||||
|
||||
struct index_state;
|
||||
void ensure_full_index(struct index_state *istate);
|
||||
int convert_to_sparse(struct index_state *istate);
|
||||
|
||||
/*
|
||||
* Some places in the codebase expect to search for a specific path.
|
||||
* This path might be outside of the sparse-checkout definition, in
|
||||
* which case a sparse-index may not contain a path for that index.
|
||||
*
|
||||
* Given an index and a path, check to see if a leading directory for
|
||||
* 'path' exists in the index as a sparse directory. In that case,
|
||||
* expand that sparse directory to a full range of cache entries and
|
||||
* populate the index accordingly.
|
||||
*/
|
||||
void expand_to_path(struct index_state *istate,
|
||||
const char *path, size_t pathlen, int icase);
|
||||
|
||||
struct repository;
|
||||
int set_sparse_index_config(struct repository *repo, int enable);
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ static struct oid_array ref_tips_after_fetch;
|
|||
* will be disabled because we can't guess what might be configured in
|
||||
* .gitmodules unless the user resolves the conflict.
|
||||
*/
|
||||
int is_gitmodules_unmerged(const struct index_state *istate)
|
||||
int is_gitmodules_unmerged(struct index_state *istate)
|
||||
{
|
||||
int pos = index_name_pos(istate, GITMODULES_FILE, strlen(GITMODULES_FILE));
|
||||
if (pos < 0) { /* .gitmodules not found or isn't merged */
|
||||
|
@ -301,7 +301,7 @@ int is_submodule_populated_gently(const char *path, int *return_error_code)
|
|||
/*
|
||||
* Dies if the provided 'prefix' corresponds to an unpopulated submodule
|
||||
*/
|
||||
void die_in_unpopulated_submodule(const struct index_state *istate,
|
||||
void die_in_unpopulated_submodule(struct index_state *istate,
|
||||
const char *prefix)
|
||||
{
|
||||
int i, prefixlen;
|
||||
|
@ -331,7 +331,7 @@ void die_in_unpopulated_submodule(const struct index_state *istate,
|
|||
/*
|
||||
* Dies if any paths in the provided pathspec descends into a submodule
|
||||
*/
|
||||
void die_path_inside_submodule(const struct index_state *istate,
|
||||
void die_path_inside_submodule(struct index_state *istate,
|
||||
const struct pathspec *ps)
|
||||
{
|
||||
int i, j;
|
||||
|
|
|
@ -39,7 +39,7 @@ struct submodule_update_strategy {
|
|||
};
|
||||
#define SUBMODULE_UPDATE_STRATEGY_INIT {SM_UPDATE_UNSPECIFIED, NULL}
|
||||
|
||||
int is_gitmodules_unmerged(const struct index_state *istate);
|
||||
int is_gitmodules_unmerged(struct index_state *istate);
|
||||
int is_writing_gitmodules_ok(void);
|
||||
int is_staging_gitmodules_ok(struct index_state *istate);
|
||||
int update_path_in_gitmodules(const char *oldpath, const char *newpath);
|
||||
|
@ -60,9 +60,9 @@ int is_submodule_active(struct repository *repo, const char *path);
|
|||
* Otherwise the return error code is the same as of resolve_gitdir_gently.
|
||||
*/
|
||||
int is_submodule_populated_gently(const char *path, int *return_error_code);
|
||||
void die_in_unpopulated_submodule(const struct index_state *istate,
|
||||
void die_in_unpopulated_submodule(struct index_state *istate,
|
||||
const char *prefix);
|
||||
void die_path_inside_submodule(const struct index_state *istate,
|
||||
void die_path_inside_submodule(struct index_state *istate,
|
||||
const struct pathspec *ps);
|
||||
enum submodule_update_type parse_submodule_update_type(const char *value);
|
||||
int parse_submodule_update_strategy(const char *value,
|
||||
|
|
Loading…
Reference in New Issue