mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-02 16:20:01 +00:00
Support for core.ignorecase
This commit is contained in:
parent
e8776d30f7
commit
ec40b7f99f
@ -47,6 +47,7 @@ enum {
|
||||
GIT_DIFF_INCLUDE_UNMODIFIED = (1 << 9),
|
||||
GIT_DIFF_RECURSE_UNTRACKED_DIRS = (1 << 10),
|
||||
GIT_DIFF_DISABLE_PATHSPEC_MATCH = (1 << 11),
|
||||
GIT_DIFF_DELTAS_ARE_ICASE = (1 << 12)
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -376,6 +376,7 @@ int git_attr_cache__push_file(
|
||||
const char *filename,
|
||||
git_attr_file_source source,
|
||||
git_attr_file_parser parse,
|
||||
void* parsedata,
|
||||
git_vector *stack)
|
||||
{
|
||||
int error = 0;
|
||||
@ -436,7 +437,7 @@ int git_attr_cache__push_file(
|
||||
goto finish;
|
||||
}
|
||||
|
||||
if (parse && (error = parse(repo, content, file)) < 0)
|
||||
if (parse && (error = parse(repo, parsedata, content, file)) < 0)
|
||||
goto finish;
|
||||
|
||||
git_strmap_insert(cache->files, file->key, file, error); //-V595
|
||||
@ -468,7 +469,7 @@ finish:
|
||||
}
|
||||
|
||||
#define push_attr_file(R,S,B,F) \
|
||||
git_attr_cache__push_file((R),(B),(F),GIT_ATTR_FILE_FROM_FILE,git_attr_file__parse_buffer,(S))
|
||||
git_attr_cache__push_file((R),(B),(F),GIT_ATTR_FILE_FROM_FILE,git_attr_file__parse_buffer,NULL,(S))
|
||||
|
||||
typedef struct {
|
||||
git_repository *repo;
|
||||
@ -517,7 +518,7 @@ static int push_one_attr(void *ref, git_buf *path)
|
||||
for (i = 0; !error && i < n_src; ++i)
|
||||
error = git_attr_cache__push_file(
|
||||
info->repo, path->ptr, GIT_ATTR_FILE, src[i],
|
||||
git_attr_file__parse_buffer, info->files);
|
||||
git_attr_file__parse_buffer, NULL, info->files);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ typedef struct {
|
||||
} git_attr_cache;
|
||||
|
||||
typedef int (*git_attr_file_parser)(
|
||||
git_repository *, const char *, git_attr_file *);
|
||||
git_repository *, void *, const char *, git_attr_file *);
|
||||
|
||||
extern int git_attr_cache__init(git_repository *repo);
|
||||
|
||||
@ -41,6 +41,7 @@ extern int git_attr_cache__push_file(
|
||||
const char *filename,
|
||||
git_attr_file_source source,
|
||||
git_attr_file_parser parse,
|
||||
void *parsedata, /* passed through to parse function */
|
||||
git_vector *stack);
|
||||
|
||||
extern int git_attr_cache__internal_file(
|
||||
|
@ -53,7 +53,7 @@ fail:
|
||||
}
|
||||
|
||||
int git_attr_file__parse_buffer(
|
||||
git_repository *repo, const char *buffer, git_attr_file *attrs)
|
||||
git_repository *repo, void *parsedata, const char *buffer, git_attr_file *attrs)
|
||||
{
|
||||
int error = 0;
|
||||
const char *scan = NULL;
|
||||
@ -123,7 +123,7 @@ int git_attr_file__new_and_load(
|
||||
|
||||
if (!(error = git_futils_readbuffer(&content, path)))
|
||||
error = git_attr_file__parse_buffer(
|
||||
NULL, git_buf_cstr(&content), *attrs_ptr);
|
||||
NULL, NULL, git_buf_cstr(&content), *attrs_ptr);
|
||||
|
||||
git_buf_free(&content);
|
||||
|
||||
@ -207,16 +207,17 @@ bool git_attr_fnmatch__match(
|
||||
const git_attr_path *path)
|
||||
{
|
||||
int fnm;
|
||||
int icase_flags = (match->flags & GIT_ATTR_FNMATCH_ICASE) ? FNM_CASEFOLD : 0;
|
||||
|
||||
if (match->flags & GIT_ATTR_FNMATCH_DIRECTORY && !path->is_dir)
|
||||
return false;
|
||||
|
||||
if (match->flags & GIT_ATTR_FNMATCH_FULLPATH)
|
||||
fnm = p_fnmatch(match->pattern, path->path, FNM_PATHNAME);
|
||||
fnm = p_fnmatch(match->pattern, path->path, FNM_PATHNAME | icase_flags);
|
||||
else if (path->is_dir)
|
||||
fnm = p_fnmatch(match->pattern, path->basename, FNM_LEADING_DIR);
|
||||
fnm = p_fnmatch(match->pattern, path->basename, FNM_LEADING_DIR | icase_flags);
|
||||
else
|
||||
fnm = p_fnmatch(match->pattern, path->basename, 0);
|
||||
fnm = p_fnmatch(match->pattern, path->basename, icase_flags);
|
||||
|
||||
return (fnm == FNM_NOMATCH) ? false : true;
|
||||
}
|
||||
|
@ -23,6 +23,7 @@
|
||||
#define GIT_ATTR_FNMATCH_IGNORE (1U << 4)
|
||||
#define GIT_ATTR_FNMATCH_HASWILD (1U << 5)
|
||||
#define GIT_ATTR_FNMATCH_ALLOWSPACE (1U << 6)
|
||||
#define GIT_ATTR_FNMATCH_ICASE (1U << 7)
|
||||
|
||||
extern const char *git_attr__true;
|
||||
extern const char *git_attr__false;
|
||||
@ -96,7 +97,7 @@ extern void git_attr_file__free(git_attr_file *file);
|
||||
extern void git_attr_file__clear_rules(git_attr_file *file);
|
||||
|
||||
extern int git_attr_file__parse_buffer(
|
||||
git_repository *repo, const char *buf, git_attr_file *file);
|
||||
git_repository *repo, void *parsedata, const char *buf, git_attr_file *file);
|
||||
|
||||
extern int git_attr_file__lookup_one(
|
||||
git_attr_file *file,
|
||||
|
64
src/diff.c
64
src/diff.c
@ -574,6 +574,22 @@ static int maybe_modified(
|
||||
diff, status, oitem, omode, nitem, nmode, use_noid);
|
||||
}
|
||||
|
||||
static int git_index_entry_cmp_case(const void *a, const void *b)
|
||||
{
|
||||
const git_index_entry *entry_a = a;
|
||||
const git_index_entry *entry_b = b;
|
||||
|
||||
return strcmp(entry_a->path, entry_b->path);
|
||||
}
|
||||
|
||||
static int git_index_entry_cmp_icase(const void *a, const void *b)
|
||||
{
|
||||
const git_index_entry *entry_a = a;
|
||||
const git_index_entry *entry_b = b;
|
||||
|
||||
return strcasecmp(entry_a->path, entry_b->path);
|
||||
}
|
||||
|
||||
static int diff_from_iterators(
|
||||
git_repository *repo,
|
||||
const git_diff_options *opts, /**< can be NULL for defaults */
|
||||
@ -584,12 +600,36 @@ static int diff_from_iterators(
|
||||
const git_index_entry *oitem, *nitem;
|
||||
git_buf ignore_prefix = GIT_BUF_INIT;
|
||||
git_diff_list *diff = git_diff_list_alloc(repo, opts);
|
||||
git_vector_cmp entry_compare;
|
||||
|
||||
if (!diff)
|
||||
goto fail;
|
||||
|
||||
diff->old_src = old_iter->type;
|
||||
diff->new_src = new_iter->type;
|
||||
|
||||
/* Use case-insensitive compare if either iterator has
|
||||
* the ignore_case bit set */
|
||||
if (!old_iter->ignore_case && !new_iter->ignore_case) {
|
||||
entry_compare = git_index_entry_cmp_case;
|
||||
diff->opts.flags &= ~GIT_DIFF_DELTAS_ARE_ICASE;
|
||||
} else {
|
||||
entry_compare = git_index_entry_cmp_icase;
|
||||
diff->opts.flags |= GIT_DIFF_DELTAS_ARE_ICASE;
|
||||
|
||||
/* If one of the iterators doesn't have ignore_case set,
|
||||
* then that's unfortunate because we'll have to spool
|
||||
* its data, sort it icase, and then use that for our
|
||||
* merge join to the other iterator that is icase sorted */
|
||||
if (!old_iter->ignore_case) {
|
||||
if (git_iterator_spoolandsort(&old_iter, old_iter, git_index_entry_cmp_icase, true) < 0)
|
||||
goto fail;
|
||||
} else if (!new_iter->ignore_case) {
|
||||
if (git_iterator_spoolandsort(&new_iter, new_iter, git_index_entry_cmp_icase, true) < 0)
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
if (git_iterator_current(old_iter, &oitem) < 0 ||
|
||||
git_iterator_current(new_iter, &nitem) < 0)
|
||||
goto fail;
|
||||
@ -598,7 +638,7 @@ static int diff_from_iterators(
|
||||
while (oitem || nitem) {
|
||||
|
||||
/* create DELETED records for old items not matched in new */
|
||||
if (oitem && (!nitem || strcmp(oitem->path, nitem->path) < 0)) {
|
||||
if (oitem && (!nitem || entry_compare(oitem, nitem) < 0)) {
|
||||
if (diff_delta__from_one(diff, GIT_DELTA_DELETED, oitem) < 0 ||
|
||||
git_iterator_advance(old_iter, &oitem) < 0)
|
||||
goto fail;
|
||||
@ -607,12 +647,12 @@ static int diff_from_iterators(
|
||||
/* create ADDED, TRACKED, or IGNORED records for new items not
|
||||
* matched in old (and/or descend into directories as needed)
|
||||
*/
|
||||
else if (nitem && (!oitem || strcmp(oitem->path, nitem->path) > 0)) {
|
||||
else if (nitem && (!oitem || entry_compare(oitem, nitem) > 0)) {
|
||||
git_delta_t delta_type = GIT_DELTA_UNTRACKED;
|
||||
|
||||
/* check if contained in ignored parent directory */
|
||||
if (git_buf_len(&ignore_prefix) &&
|
||||
git__prefixcmp(nitem->path, git_buf_cstr(&ignore_prefix)) == 0)
|
||||
ITERATOR_PREFIXCMP(*old_iter, nitem->path, git_buf_cstr(&ignore_prefix)) == 0)
|
||||
delta_type = GIT_DELTA_IGNORED;
|
||||
|
||||
if (S_ISDIR(nitem->mode)) {
|
||||
@ -620,7 +660,7 @@ static int diff_from_iterators(
|
||||
* it or if the user requested the contents of untracked
|
||||
* directories and it is not under an ignored directory.
|
||||
*/
|
||||
if ((oitem && git__prefixcmp(oitem->path, nitem->path) == 0) ||
|
||||
if ((oitem && ITERATOR_PREFIXCMP(*old_iter, oitem->path, nitem->path) == 0) ||
|
||||
(delta_type == GIT_DELTA_UNTRACKED &&
|
||||
(diff->opts.flags & GIT_DIFF_RECURSE_UNTRACKED_DIRS) != 0))
|
||||
{
|
||||
@ -674,7 +714,7 @@ static int diff_from_iterators(
|
||||
* (or ADDED and DELETED pair if type changed)
|
||||
*/
|
||||
else {
|
||||
assert(oitem && nitem && strcmp(oitem->path, nitem->path) == 0);
|
||||
assert(oitem && nitem && entry_compare(oitem->path, nitem->path) == 0);
|
||||
|
||||
if (maybe_modified(old_iter, oitem, new_iter, nitem, diff) < 0 ||
|
||||
git_iterator_advance(old_iter, &oitem) < 0 ||
|
||||
@ -805,6 +845,7 @@ int git_diff_merge(
|
||||
git_pool onto_pool;
|
||||
git_vector onto_new;
|
||||
git_diff_delta *delta;
|
||||
bool ignore_case = false;
|
||||
unsigned int i, j;
|
||||
|
||||
assert(onto && from);
|
||||
@ -816,10 +857,21 @@ int git_diff_merge(
|
||||
git_pool_init(&onto_pool, 1, 0) < 0)
|
||||
return -1;
|
||||
|
||||
if ((onto->opts.flags & GIT_DIFF_DELTAS_ARE_ICASE) != 0 ||
|
||||
(from->opts.flags & GIT_DIFF_DELTAS_ARE_ICASE) != 0)
|
||||
{
|
||||
ignore_case = true;
|
||||
|
||||
/* This function currently only supports merging diff lists that
|
||||
* are sorted identically. */
|
||||
assert((onto->opts.flags & GIT_DIFF_DELTAS_ARE_ICASE) != 0 &&
|
||||
(from->opts.flags & GIT_DIFF_DELTAS_ARE_ICASE) != 0);
|
||||
}
|
||||
|
||||
for (i = 0, j = 0; i < onto->deltas.length || j < from->deltas.length; ) {
|
||||
git_diff_delta *o = GIT_VECTOR_GET(&onto->deltas, i);
|
||||
const git_diff_delta *f = GIT_VECTOR_GET(&from->deltas, j);
|
||||
int cmp = !f ? -1 : !o ? 1 : strcmp(o->old_file.path, f->old_file.path);
|
||||
int cmp = !f ? -1 : !o ? 1 : STRCMP_CASESELECT(ignore_case, o->old_file.path, f->old_file.path);
|
||||
|
||||
if (cmp < 0) {
|
||||
delta = diff_delta__dup(o, &onto_pool);
|
||||
|
51
src/ignore.c
51
src/ignore.c
@ -1,20 +1,37 @@
|
||||
#include "git2/ignore.h"
|
||||
#include "ignore.h"
|
||||
#include "path.h"
|
||||
#include "config.h"
|
||||
|
||||
#define GIT_IGNORE_INTERNAL "[internal]exclude"
|
||||
#define GIT_IGNORE_FILE_INREPO "info/exclude"
|
||||
#define GIT_IGNORE_FILE ".gitignore"
|
||||
|
||||
static int parse_ignore_file(
|
||||
git_repository *repo, const char *buffer, git_attr_file *ignores)
|
||||
git_repository *repo, void *parsedata, const char *buffer, git_attr_file *ignores)
|
||||
{
|
||||
int error = 0;
|
||||
git_attr_fnmatch *match = NULL;
|
||||
const char *scan = NULL;
|
||||
char *context = NULL;
|
||||
bool ignore_case = false;
|
||||
git_config *cfg = NULL;
|
||||
int val;
|
||||
|
||||
GIT_UNUSED(repo);
|
||||
/* Prefer to have the caller pass in a git_ignores as the parsedata object.
|
||||
* If they did not, then we can (much more slowly) find the value of
|
||||
* ignore_case by using the repository object. */
|
||||
if (parsedata != NULL) {
|
||||
ignore_case = ((git_ignores *)parsedata)->ignore_case;
|
||||
} else {
|
||||
if ((error = git_repository_config(&cfg, repo)) < 0)
|
||||
return error;
|
||||
|
||||
if (git_config_get_bool(&val, cfg, "core.ignorecase") == 0)
|
||||
ignore_case = (val != 0);
|
||||
|
||||
git_config_free(cfg);
|
||||
}
|
||||
|
||||
if (ignores->key && git__suffixcmp(ignores->key, "/" GIT_IGNORE_FILE) == 0) {
|
||||
context = ignores->key + 2;
|
||||
@ -31,6 +48,9 @@ static int parse_ignore_file(
|
||||
|
||||
match->flags = GIT_ATTR_FNMATCH_ALLOWSPACE;
|
||||
|
||||
if (ignore_case)
|
||||
match->flags |= GIT_ATTR_FNMATCH_ICASE;
|
||||
|
||||
if (!(error = git_attr_fnmatch__parse(
|
||||
match, ignores->pool, context, &scan)))
|
||||
{
|
||||
@ -58,13 +78,13 @@ static int parse_ignore_file(
|
||||
return error;
|
||||
}
|
||||
|
||||
#define push_ignore_file(R,S,B,F) \
|
||||
git_attr_cache__push_file((R),(B),(F),GIT_ATTR_FILE_FROM_FILE,parse_ignore_file,(S))
|
||||
#define push_ignore_file(R,IGN,S,B,F) \
|
||||
git_attr_cache__push_file((R),(B),(F),GIT_ATTR_FILE_FROM_FILE,parse_ignore_file,(IGN),(S))
|
||||
|
||||
static int push_one_ignore(void *ref, git_buf *path)
|
||||
{
|
||||
git_ignores *ign = (git_ignores *)ref;
|
||||
return push_ignore_file(ign->repo, &ign->ign_path, path->ptr, GIT_IGNORE_FILE);
|
||||
return push_ignore_file(ign->repo, ign, &ign->ign_path, path->ptr, GIT_IGNORE_FILE);
|
||||
}
|
||||
|
||||
int git_ignore__for_path(
|
||||
@ -74,6 +94,8 @@ int git_ignore__for_path(
|
||||
{
|
||||
int error = 0;
|
||||
const char *workdir = git_repository_workdir(repo);
|
||||
git_config *cfg = NULL;
|
||||
int val;
|
||||
|
||||
assert(ignores);
|
||||
|
||||
@ -81,6 +103,17 @@ int git_ignore__for_path(
|
||||
git_buf_init(&ignores->dir, 0);
|
||||
ignores->ign_internal = NULL;
|
||||
|
||||
/* Set the ignore_case flag appropriately */
|
||||
if ((error = git_repository_config(&cfg, repo)) < 0)
|
||||
goto cleanup;
|
||||
|
||||
if (git_config_get_bool(&val, cfg, "core.ignorecase") == 0)
|
||||
ignores->ignore_case = (val != 0);
|
||||
else
|
||||
ignores->ignore_case = 0;
|
||||
|
||||
git_config_free(cfg);
|
||||
|
||||
if ((error = git_vector_init(&ignores->ign_path, 8, NULL)) < 0 ||
|
||||
(error = git_vector_init(&ignores->ign_global, 2, NULL)) < 0 ||
|
||||
(error = git_attr_cache__init(repo)) < 0)
|
||||
@ -109,14 +142,14 @@ int git_ignore__for_path(
|
||||
}
|
||||
|
||||
/* load .git/info/exclude */
|
||||
error = push_ignore_file(repo, &ignores->ign_global,
|
||||
error = push_ignore_file(repo, ignores, &ignores->ign_global,
|
||||
git_repository_path(repo), GIT_IGNORE_FILE_INREPO);
|
||||
if (error < 0)
|
||||
goto cleanup;
|
||||
|
||||
/* load core.excludesfile */
|
||||
if (git_repository_attr_cache(repo)->cfg_excl_file != NULL)
|
||||
error = push_ignore_file(repo, &ignores->ign_global, NULL,
|
||||
error = push_ignore_file(repo, ignores, &ignores->ign_global, NULL,
|
||||
git_repository_attr_cache(repo)->cfg_excl_file);
|
||||
|
||||
cleanup:
|
||||
@ -132,7 +165,7 @@ int git_ignore__push_dir(git_ignores *ign, const char *dir)
|
||||
return -1;
|
||||
else
|
||||
return push_ignore_file(
|
||||
ign->repo, &ign->ign_path, ign->dir.ptr, GIT_IGNORE_FILE);
|
||||
ign->repo, ign, &ign->ign_path, ign->dir.ptr, GIT_IGNORE_FILE);
|
||||
}
|
||||
|
||||
int git_ignore__pop_dir(git_ignores *ign)
|
||||
@ -223,7 +256,7 @@ int git_ignore_add_rule(
|
||||
git_attr_file *ign_internal;
|
||||
|
||||
if (!(error = get_internal_ignores(&ign_internal, repo)))
|
||||
error = parse_ignore_file(repo, rules, ign_internal);
|
||||
error = parse_ignore_file(repo, NULL, rules, ign_internal);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ typedef struct {
|
||||
git_attr_file *ign_internal;
|
||||
git_vector ign_path;
|
||||
git_vector ign_global;
|
||||
unsigned int ignore_case:1;
|
||||
} git_ignores;
|
||||
|
||||
extern int git_ignore__for_path(git_repository *repo, const char *path, git_ignores *ign);
|
||||
|
62
src/index.c
62
src/index.c
@ -99,6 +99,13 @@ static int index_srch(const void *key, const void *array_member)
|
||||
return strcmp(key, entry->path);
|
||||
}
|
||||
|
||||
static int index_isrch(const void *key, const void *array_member)
|
||||
{
|
||||
const git_index_entry *entry = array_member;
|
||||
|
||||
return strcasecmp(key, entry->path);
|
||||
}
|
||||
|
||||
static int index_cmp(const void *a, const void *b)
|
||||
{
|
||||
const git_index_entry *entry_a = a;
|
||||
@ -107,6 +114,14 @@ static int index_cmp(const void *a, const void *b)
|
||||
return strcmp(entry_a->path, entry_b->path);
|
||||
}
|
||||
|
||||
static int index_icmp(const void *a, const void *b)
|
||||
{
|
||||
const git_index_entry *entry_a = a;
|
||||
const git_index_entry *entry_b = b;
|
||||
|
||||
return strcasecmp(entry_a->path, entry_b->path);
|
||||
}
|
||||
|
||||
static int unmerged_srch(const void *key, const void *array_member)
|
||||
{
|
||||
const git_index_entry_unmerged *entry = array_member;
|
||||
@ -147,6 +162,14 @@ static unsigned int index_merge_mode(
|
||||
return index_create_mode(mode);
|
||||
}
|
||||
|
||||
static void index_set_ignore_case(git_index *index, bool ignore_case)
|
||||
{
|
||||
index->entries._cmp = ignore_case ? index_icmp : index_cmp;
|
||||
index->entries_search = ignore_case ? index_isrch : index_srch;
|
||||
index->entries.sorted = 0;
|
||||
git_vector_sort(&index->entries);
|
||||
}
|
||||
|
||||
int git_index_open(git_index **index_out, const char *index_path)
|
||||
{
|
||||
git_index *index;
|
||||
@ -162,6 +185,8 @@ int git_index_open(git_index **index_out, const char *index_path)
|
||||
if (git_vector_init(&index->entries, 32, index_cmp) < 0)
|
||||
return -1;
|
||||
|
||||
index->entries_search = index_srch;
|
||||
|
||||
/* Check if index file is stored on disk already */
|
||||
if (git_path_exists(index->index_file_path) == true)
|
||||
index->on_disk = 1;
|
||||
@ -228,8 +253,12 @@ void git_index_clear(git_index *index)
|
||||
|
||||
int git_index_set_caps(git_index *index, unsigned int caps)
|
||||
{
|
||||
int old_ignore_case;
|
||||
|
||||
assert(index);
|
||||
|
||||
old_ignore_case = index->ignore_case;
|
||||
|
||||
if (caps == GIT_INDEXCAP_FROM_OWNER) {
|
||||
git_config *cfg;
|
||||
int val;
|
||||
@ -255,6 +284,11 @@ int git_index_set_caps(git_index *index, unsigned int caps)
|
||||
index->no_symlinks = ((caps & GIT_INDEXCAP_NO_SYMLINKS) != 0);
|
||||
}
|
||||
|
||||
if (old_ignore_case != index->ignore_case)
|
||||
{
|
||||
index_set_ignore_case(index, index->ignore_case);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -552,14 +586,14 @@ int git_index_remove(git_index *index, int position)
|
||||
|
||||
int git_index_find(git_index *index, const char *path)
|
||||
{
|
||||
return git_vector_bsearch2(&index->entries, index_srch, path);
|
||||
return git_vector_bsearch2(&index->entries, index->entries_search, path);
|
||||
}
|
||||
|
||||
unsigned int git_index__prefix_position(git_index *index, const char *path)
|
||||
{
|
||||
unsigned int pos;
|
||||
|
||||
git_vector_bsearch3(&pos, &index->entries, index_srch, path);
|
||||
git_vector_bsearch3(&pos, &index->entries, index->entries_search, path);
|
||||
|
||||
return pos;
|
||||
}
|
||||
@ -938,16 +972,28 @@ static int write_disk_entry(git_filebuf *file, git_index_entry *entry)
|
||||
|
||||
static int write_entries(git_index *index, git_filebuf *file)
|
||||
{
|
||||
int error = 0;
|
||||
unsigned int i;
|
||||
git_vector case_sorted;
|
||||
git_index_entry *entry;
|
||||
git_vector *out = &index->entries;
|
||||
|
||||
for (i = 0; i < index->entries.length; ++i) {
|
||||
git_index_entry *entry;
|
||||
entry = git_vector_get(&index->entries, i);
|
||||
if (write_disk_entry(file, entry) < 0)
|
||||
return -1;
|
||||
/* If index->entries is sorted case-insensitively, then we need
|
||||
* to re-sort it case-sensitively before writing */
|
||||
if (index->ignore_case) {
|
||||
git_vector_dup(&case_sorted, &index->entries, index_cmp);
|
||||
git_vector_sort(&case_sorted);
|
||||
out = &case_sorted;
|
||||
}
|
||||
|
||||
return 0;
|
||||
git_vector_foreach(out, i, entry)
|
||||
if ((error = write_disk_entry(file, entry)) < 0)
|
||||
break;
|
||||
|
||||
if (index->ignore_case)
|
||||
git_vector_free(&case_sorted);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
static int write_index(git_index *index, git_filebuf *file)
|
||||
|
@ -34,6 +34,8 @@ struct git_index {
|
||||
git_tree_cache *tree;
|
||||
|
||||
git_vector unmerged;
|
||||
|
||||
git_vector_cmp entries_search;
|
||||
};
|
||||
|
||||
extern void git_index__init_entry_from_stat(struct stat *st, git_index_entry *entry);
|
||||
|
189
src/iterator.c
189
src/iterator.c
@ -17,6 +17,7 @@
|
||||
(P)->base.type = GIT_ITERATOR_ ## NAME_UC; \
|
||||
(P)->base.start = start ? git__strdup(start) : NULL; \
|
||||
(P)->base.end = end ? git__strdup(end) : NULL; \
|
||||
(P)->base.ignore_case = 0; \
|
||||
(P)->base.current = NAME_LC ## _iterator__current; \
|
||||
(P)->base.at_end = NAME_LC ## _iterator__at_end; \
|
||||
(P)->base.advance = NAME_LC ## _iterator__advance; \
|
||||
@ -336,7 +337,7 @@ static int index_iterator__current(
|
||||
|
||||
if (ie != NULL &&
|
||||
ii->base.end != NULL &&
|
||||
git__prefixcmp(ie->path, ii->base.end) > 0)
|
||||
ITERATOR_PREFIXCMP(ii->base, ie->path, ii->base.end) > 0)
|
||||
{
|
||||
ii->current = git_index_entrycount(ii->index);
|
||||
ie = NULL;
|
||||
@ -401,6 +402,7 @@ int git_iterator_for_index_range(
|
||||
if ((error = git_repository_index(&ii->index, repo)) < 0)
|
||||
git__free(ii);
|
||||
else {
|
||||
ii->base.ignore_case = ii->index->ignore_case;
|
||||
ii->current = start ? git_index__prefix_position(ii->index, start) : 0;
|
||||
*iter = (git_iterator *)ii;
|
||||
}
|
||||
@ -428,12 +430,30 @@ typedef struct {
|
||||
int is_ignored;
|
||||
} workdir_iterator;
|
||||
|
||||
static workdir_iterator_frame *workdir_iterator__alloc_frame(void)
|
||||
static int git_path_with_stat_cmp_case(const void *a, const void *b)
|
||||
{
|
||||
const git_path_with_stat *path_with_stat_a = a;
|
||||
const git_path_with_stat *path_with_stat_b = b;
|
||||
|
||||
return strcmp(path_with_stat_a->path, path_with_stat_b->path);
|
||||
}
|
||||
|
||||
static int git_path_with_stat_cmp_icase(const void *a, const void *b)
|
||||
{
|
||||
const git_path_with_stat *path_with_stat_a = a;
|
||||
const git_path_with_stat *path_with_stat_b = b;
|
||||
|
||||
return strcasecmp(path_with_stat_a->path, path_with_stat_b->path);
|
||||
}
|
||||
|
||||
static workdir_iterator_frame *workdir_iterator__alloc_frame(workdir_iterator *wi)
|
||||
{
|
||||
workdir_iterator_frame *wf = git__calloc(1, sizeof(workdir_iterator_frame));
|
||||
git_vector_cmp entry_compare = CASESELECT(wi->base.ignore_case, git_path_with_stat_cmp_icase, git_path_with_stat_cmp_case);
|
||||
|
||||
if (wf == NULL)
|
||||
return NULL;
|
||||
if (git_vector_init(&wf->entries, 0, git_path_with_stat_cmp) != 0) {
|
||||
if (git_vector_init(&wf->entries, 0, entry_compare) != 0) {
|
||||
git__free(wf);
|
||||
return NULL;
|
||||
}
|
||||
@ -453,16 +473,22 @@ static void workdir_iterator__free_frame(workdir_iterator_frame *wf)
|
||||
|
||||
static int workdir_iterator__update_entry(workdir_iterator *wi);
|
||||
|
||||
static int workdir_iterator__entry_cmp(const void *prefix, const void *item)
|
||||
static int workdir_iterator__entry_cmp_case(const void *prefix, const void *item)
|
||||
{
|
||||
const git_path_with_stat *ps = item;
|
||||
return git__prefixcmp((const char *)prefix, ps->path);
|
||||
}
|
||||
|
||||
static int workdir_iterator__entry_cmp_icase(const void *prefix, const void *item)
|
||||
{
|
||||
const git_path_with_stat *ps = item;
|
||||
return git__prefixcmp_icase((const char *)prefix, ps->path);
|
||||
}
|
||||
|
||||
static int workdir_iterator__expand_dir(workdir_iterator *wi)
|
||||
{
|
||||
int error;
|
||||
workdir_iterator_frame *wf = workdir_iterator__alloc_frame();
|
||||
workdir_iterator_frame *wf = workdir_iterator__alloc_frame(wi);
|
||||
GITERR_CHECK_ALLOC(wf);
|
||||
|
||||
error = git_path_dirload_with_stat(wi->path.ptr, wi->root_len, &wf->entries);
|
||||
@ -476,12 +502,15 @@ static int workdir_iterator__expand_dir(workdir_iterator *wi)
|
||||
if (!wi->stack)
|
||||
wf->start = wi->base.start;
|
||||
else if (wi->stack->start &&
|
||||
git__prefixcmp(wi->stack->start, wi->path.ptr + wi->root_len) == 0)
|
||||
ITERATOR_PREFIXCMP(wi->base, wi->stack->start, wi->path.ptr + wi->root_len) == 0)
|
||||
wf->start = wi->stack->start;
|
||||
|
||||
if (wf->start)
|
||||
git_vector_bsearch3(
|
||||
&wf->index, &wf->entries, workdir_iterator__entry_cmp, wf->start);
|
||||
&wf->index,
|
||||
&wf->entries,
|
||||
CASESELECT(wi->base.ignore_case, workdir_iterator__entry_cmp_icase, workdir_iterator__entry_cmp_case),
|
||||
wf->start);
|
||||
|
||||
wf->next = wi->stack;
|
||||
wi->stack = wf;
|
||||
@ -526,8 +555,8 @@ static int workdir_iterator__advance(
|
||||
next = git_vector_get(&wf->entries, ++wf->index);
|
||||
if (next != NULL) {
|
||||
/* match git's behavior of ignoring anything named ".git" */
|
||||
if (strcmp(next->path, DOT_GIT "/") == 0 ||
|
||||
strcmp(next->path, DOT_GIT) == 0)
|
||||
if (STRCMP_CASESELECT(wi->base.ignore_case, next->path, DOT_GIT "/") == 0 ||
|
||||
STRCMP_CASESELECT(wi->base.ignore_case, next->path, DOT_GIT) == 0)
|
||||
continue;
|
||||
/* else found a good entry */
|
||||
break;
|
||||
@ -604,13 +633,14 @@ static int workdir_iterator__update_entry(workdir_iterator *wi)
|
||||
return -1;
|
||||
|
||||
if (wi->base.end &&
|
||||
git__prefixcmp(wi->path.ptr + wi->root_len, wi->base.end) > 0)
|
||||
ITERATOR_PREFIXCMP(wi->base, wi->path.ptr + wi->root_len, wi->base.end) > 0)
|
||||
return 0;
|
||||
|
||||
wi->entry.path = ps->path;
|
||||
|
||||
/* skip over .git entry */
|
||||
if (strcmp(ps->path, DOT_GIT "/") == 0 || strcmp(ps->path, DOT_GIT) == 0)
|
||||
if (STRCMP_CASESELECT(wi->base.ignore_case, ps->path, DOT_GIT "/") == 0 ||
|
||||
STRCMP_CASESELECT(wi->base.ignore_case, ps->path, DOT_GIT) == 0)
|
||||
return workdir_iterator__advance((git_iterator *)wi, NULL);
|
||||
|
||||
/* if there is an error processing the entry, treat as ignored */
|
||||
@ -656,6 +686,7 @@ int git_iterator_for_workdir_range(
|
||||
{
|
||||
int error;
|
||||
workdir_iterator *wi;
|
||||
git_index *index;
|
||||
|
||||
assert(iter && repo);
|
||||
|
||||
@ -666,6 +697,17 @@ int git_iterator_for_workdir_range(
|
||||
|
||||
wi->repo = repo;
|
||||
|
||||
if ((error = git_repository_index(&index, repo)) < 0) {
|
||||
git__free(wi);
|
||||
return error;
|
||||
}
|
||||
|
||||
/* Set the ignore_case flag for the workdir iterator to match
|
||||
* that of the index. */
|
||||
wi->base.ignore_case = index->ignore_case;
|
||||
|
||||
git_index_free(index);
|
||||
|
||||
if (git_buf_sets(&wi->path, git_repository_workdir(repo)) < 0 ||
|
||||
git_path_to_dir(&wi->path) < 0 ||
|
||||
git_ignore__for_path(repo, "", &wi->ignores) < 0)
|
||||
@ -690,6 +732,129 @@ int git_iterator_for_workdir_range(
|
||||
return error;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
git_iterator base;
|
||||
git_iterator *wrapped;
|
||||
git_vector entries;
|
||||
git_vector_cmp comparer;
|
||||
git_pool entry_pool;
|
||||
git_pool string_pool;
|
||||
unsigned int position;
|
||||
} spoolandsort_iterator;
|
||||
|
||||
static int spoolandsort_iterator__current(
|
||||
git_iterator *self, const git_index_entry **entry)
|
||||
{
|
||||
spoolandsort_iterator *si = (spoolandsort_iterator *)self;
|
||||
|
||||
if (si->position < si->entries.length)
|
||||
*entry = (const git_index_entry *)git_vector_get_const(&si->entries, si->position);
|
||||
else
|
||||
*entry = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int spoolandsort_iterator__at_end(git_iterator *self)
|
||||
{
|
||||
spoolandsort_iterator *si = (spoolandsort_iterator *)self;
|
||||
|
||||
return 0 == si->entries.length || si->entries.length - 1 <= si->position;
|
||||
}
|
||||
|
||||
static int spoolandsort_iterator__advance(
|
||||
git_iterator *self, const git_index_entry **entry)
|
||||
{
|
||||
spoolandsort_iterator *si = (spoolandsort_iterator *)self;
|
||||
|
||||
if (si->position < si->entries.length)
|
||||
*entry = (const git_index_entry *)git_vector_get_const(&si->entries, ++si->position);
|
||||
else
|
||||
*entry = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int spoolandsort_iterator__seek(git_iterator *self, const char *prefix)
|
||||
{
|
||||
GIT_UNUSED(self);
|
||||
GIT_UNUSED(prefix);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int spoolandsort_iterator__reset(git_iterator *self)
|
||||
{
|
||||
spoolandsort_iterator *si = (spoolandsort_iterator *)self;
|
||||
|
||||
si->position = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void spoolandsort_iterator__free(git_iterator *self)
|
||||
{
|
||||
spoolandsort_iterator *si = (spoolandsort_iterator *)self;
|
||||
|
||||
git_pool_clear(&si->string_pool);
|
||||
git_pool_clear(&si->entry_pool);
|
||||
git_vector_free(&si->entries);
|
||||
git_iterator_free(si->wrapped);
|
||||
}
|
||||
|
||||
int git_iterator_spoolandsort_range(
|
||||
git_iterator **iter,
|
||||
git_iterator *towrap,
|
||||
git_vector_cmp comparer,
|
||||
bool ignore_case,
|
||||
const char *start,
|
||||
const char *end)
|
||||
{
|
||||
spoolandsort_iterator *si;
|
||||
const git_index_entry *item;
|
||||
|
||||
assert(iter && towrap && comparer);
|
||||
|
||||
ITERATOR_BASE_INIT(si, spoolandsort, SPOOLANDSORT);
|
||||
si->base.ignore_case = ignore_case;
|
||||
si->wrapped = towrap;
|
||||
si->comparer = comparer;
|
||||
si->position = 0;
|
||||
|
||||
if (git_vector_init(&si->entries, 16, si->comparer) < 0 ||
|
||||
git_iterator_current(towrap, &item) < 0 ||
|
||||
git_pool_init(&si->entry_pool, sizeof(git_index_entry), 0) ||
|
||||
git_pool_init(&si->string_pool, 1, 0))
|
||||
{
|
||||
git__free(si);
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (item)
|
||||
{
|
||||
git_index_entry *clone = git_pool_malloc(&si->entry_pool, 1);
|
||||
memcpy(clone, item, sizeof(git_index_entry));
|
||||
|
||||
if (item->path)
|
||||
{
|
||||
clone->path = git_pool_strdup(&si->string_pool, item->path);
|
||||
}
|
||||
|
||||
git_vector_insert(&si->entries, clone);
|
||||
|
||||
if (git_iterator_advance(towrap, &item) < 0)
|
||||
{
|
||||
git__free(si);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
git_vector_sort(&si->entries);
|
||||
|
||||
*iter = (git_iterator *)si;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int git_iterator_current_tree_entry(
|
||||
git_iterator *iter, const git_tree_entry **tree_entry)
|
||||
@ -737,6 +902,6 @@ int git_iterator_cmp(
|
||||
if (!path_prefix)
|
||||
return -1;
|
||||
|
||||
return git__prefixcmp(entry->path, path_prefix);
|
||||
return ITERATOR_PREFIXCMP(*iter, entry->path, path_prefix);
|
||||
}
|
||||
|
||||
|
@ -9,6 +9,11 @@
|
||||
|
||||
#include "common.h"
|
||||
#include "git2/index.h"
|
||||
#include "vector.h"
|
||||
|
||||
#define ITERATOR_PREFIXCMP(ITER, STR, PREFIX) (((ITER) ## .ignore_case) ? \
|
||||
git__prefixcmp_icase((STR), (PREFIX)) : \
|
||||
git__prefixcmp((STR), (PREFIX)))
|
||||
|
||||
typedef struct git_iterator git_iterator;
|
||||
|
||||
@ -16,7 +21,8 @@ typedef enum {
|
||||
GIT_ITERATOR_EMPTY = 0,
|
||||
GIT_ITERATOR_TREE = 1,
|
||||
GIT_ITERATOR_INDEX = 2,
|
||||
GIT_ITERATOR_WORKDIR = 3
|
||||
GIT_ITERATOR_WORKDIR = 3,
|
||||
GIT_ITERATOR_SPOOLANDSORT = 4
|
||||
} git_iterator_type_t;
|
||||
|
||||
struct git_iterator {
|
||||
@ -29,6 +35,7 @@ struct git_iterator {
|
||||
int (*seek)(git_iterator *, const char *prefix);
|
||||
int (*reset)(git_iterator *);
|
||||
void (*free)(git_iterator *);
|
||||
unsigned int ignore_case:1;
|
||||
};
|
||||
|
||||
extern int git_iterator_for_nothing(git_iterator **iter);
|
||||
@ -63,6 +70,17 @@ GIT_INLINE(int) git_iterator_for_workdir(
|
||||
return git_iterator_for_workdir_range(iter, repo, NULL, NULL);
|
||||
}
|
||||
|
||||
extern int git_iterator_spoolandsort_range(
|
||||
git_iterator **iter, git_iterator *towrap,
|
||||
git_vector_cmp comparer, bool ignore_case,
|
||||
const char *start, const char *end);
|
||||
|
||||
GIT_INLINE(int) git_iterator_spoolandsort(
|
||||
git_iterator **iter, git_iterator *towrap,
|
||||
git_vector_cmp comparer, bool ignore_case)
|
||||
{
|
||||
return git_iterator_spoolandsort_range(iter, towrap, comparer, ignore_case, NULL, NULL);
|
||||
}
|
||||
|
||||
/* Entry is not guaranteed to be fully populated. For a tree iterator,
|
||||
* we will only populate the mode, oid and path, for example. For a workdir
|
||||
|
18
src/status.c
18
src/status.c
@ -82,6 +82,7 @@ int git_status_foreach_ext(
|
||||
opts ? opts->show : GIT_STATUS_SHOW_INDEX_AND_WORKDIR;
|
||||
git_diff_delta *i2h, *w2i;
|
||||
size_t i, j, i_max, j_max;
|
||||
bool ignore_case = false;
|
||||
|
||||
assert(show <= GIT_STATUS_SHOW_INDEX_THEN_WORKDIR);
|
||||
|
||||
@ -124,11 +125,26 @@ int git_status_foreach_ext(
|
||||
i_max = idx2head ? idx2head->deltas.length : 0;
|
||||
j_max = wd2idx ? wd2idx->deltas.length : 0;
|
||||
|
||||
if (idx2head && wd2idx &&
|
||||
(0 != (idx2head->opts.flags & GIT_DIFF_DELTAS_ARE_ICASE) ||
|
||||
0 != (wd2idx->opts.flags & GIT_DIFF_DELTAS_ARE_ICASE)))
|
||||
{
|
||||
/* Then use the ignore-case sorter... */
|
||||
ignore_case = true;
|
||||
|
||||
/* and assert that both are ignore-case sorted. If this function
|
||||
* ever needs to support merge joining result sets that are not sorted
|
||||
* by the same function, then it will need to be extended to do a spool
|
||||
* and sort on one of the results before merge joining */
|
||||
assert(0 != (idx2head->opts.flags & GIT_DIFF_DELTAS_ARE_ICASE) &&
|
||||
0 != (wd2idx->opts.flags & GIT_DIFF_DELTAS_ARE_ICASE));
|
||||
}
|
||||
|
||||
for (i = 0, j = 0; !err && (i < i_max || j < j_max); ) {
|
||||
i2h = idx2head ? GIT_VECTOR_GET(&idx2head->deltas,i) : NULL;
|
||||
w2i = wd2idx ? GIT_VECTOR_GET(&wd2idx->deltas,j) : NULL;
|
||||
|
||||
cmp = !w2i ? -1 : !i2h ? 1 : strcmp(i2h->old_file.path, w2i->old_file.path);
|
||||
cmp = !w2i ? -1 : !i2h ? 1 : STRCMP_CASESELECT(ignore_case, i2h->old_file.path, w2i->old_file.path);
|
||||
|
||||
if (cmp < 0) {
|
||||
if (cb(i2h->old_file.path, index_delta2status(i2h->status), cbdata))
|
||||
|
@ -199,6 +199,11 @@ int git__prefixcmp(const char *str, const char *prefix)
|
||||
}
|
||||
}
|
||||
|
||||
int git__prefixcmp_icase(const char *str, const char *prefix)
|
||||
{
|
||||
return strncasecmp(str, prefix, strlen(prefix));
|
||||
}
|
||||
|
||||
int git__suffixcmp(const char *str, const char *suffix)
|
||||
{
|
||||
size_t a = strlen(str);
|
||||
|
@ -70,7 +70,14 @@ GIT_INLINE(void *) git__realloc(void *ptr, size_t size)
|
||||
|
||||
#define git__free(ptr) free(ptr)
|
||||
|
||||
#define STRCMP_CASESELECT(IGNORE_CASE, STR1, STR2) \
|
||||
((IGNORE_CASE) ? strcasecmp((STR1), (STR2)) : strcmp((STR1), (STR2)))
|
||||
|
||||
#define CASESELECT(IGNORE_CASE, ICASE, CASE) \
|
||||
((IGNORE_CASE) ? (ICASE) : (CASE))
|
||||
|
||||
extern int git__prefixcmp(const char *str, const char *prefix);
|
||||
extern int git__prefixcmp_icase(const char *str, const char *prefix);
|
||||
extern int git__suffixcmp(const char *str, const char *suffix);
|
||||
|
||||
extern int git__strtol32(int32_t *n, const char *buff, const char **end_buf, int base);
|
||||
|
16
src/vector.c
16
src/vector.c
@ -24,6 +24,22 @@ static int resize_vector(git_vector *v)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int git_vector_dup(git_vector *v, git_vector *src, git_vector_cmp cmp)
|
||||
{
|
||||
assert(v && src);
|
||||
|
||||
v->_alloc_size = src->length;
|
||||
v->_cmp = cmp;
|
||||
v->length = src->length;
|
||||
v->sorted = src->sorted && cmp == src->_cmp;
|
||||
v->contents = git__malloc(src->length * sizeof(void *));
|
||||
GITERR_CHECK_ALLOC(v->contents);
|
||||
|
||||
memcpy(v->contents, src->contents, src->length * sizeof(void *));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void git_vector_free(git_vector *v)
|
||||
{
|
||||
assert(v);
|
||||
|
@ -24,6 +24,7 @@ typedef struct git_vector {
|
||||
int git_vector_init(git_vector *v, size_t initial_size, git_vector_cmp cmp);
|
||||
void git_vector_free(git_vector *v);
|
||||
void git_vector_clear(git_vector *v);
|
||||
int git_vector_dup(git_vector *v, git_vector *src, git_vector_cmp cmp);
|
||||
void git_vector_swap(git_vector *a, git_vector *b);
|
||||
|
||||
void git_vector_sort(git_vector *v);
|
||||
|
@ -252,7 +252,7 @@ void test_attr_lookup__from_buffer(void)
|
||||
|
||||
cl_git_pass(git_attr_file__new(&file, 0, NULL, NULL));
|
||||
|
||||
cl_git_pass(git_attr_file__parse_buffer(NULL, "a* foo\nabc bar\n* baz", file));
|
||||
cl_git_pass(git_attr_file__parse_buffer(NULL, NULL, "a* foo\nabc bar\n* baz", file));
|
||||
|
||||
cl_assert(file->rules.length == 3);
|
||||
|
||||
|
@ -90,6 +90,56 @@ static const int entry_count2 = 15;
|
||||
|
||||
/* entries for a copy of tests/resources/status with some mods */
|
||||
|
||||
static const char *entry_paths3_icase[] = {
|
||||
".HEADER",
|
||||
"42-is-not-prime.sigh",
|
||||
"current_file",
|
||||
"current_file/",
|
||||
"file_deleted",
|
||||
"ignored_file",
|
||||
"modified_file",
|
||||
"new_file",
|
||||
"README.md",
|
||||
"staged_changes",
|
||||
"staged_changes_file_deleted",
|
||||
"staged_changes_modified_file",
|
||||
"staged_delete_file_deleted",
|
||||
"staged_delete_modified_file",
|
||||
"staged_new_file",
|
||||
"staged_new_file_deleted_file",
|
||||
"staged_new_file_modified_file",
|
||||
"subdir",
|
||||
"subdir/current_file",
|
||||
"subdir/deleted_file",
|
||||
"subdir/modified_file",
|
||||
"\xe8\xbf\x99",
|
||||
};
|
||||
|
||||
static const unsigned int entry_statuses3_icase[] = {
|
||||
GIT_STATUS_WT_NEW,
|
||||
GIT_STATUS_WT_NEW,
|
||||
GIT_STATUS_WT_DELETED,
|
||||
GIT_STATUS_WT_NEW,
|
||||
GIT_STATUS_WT_DELETED,
|
||||
GIT_STATUS_IGNORED,
|
||||
GIT_STATUS_WT_MODIFIED,
|
||||
GIT_STATUS_WT_NEW,
|
||||
GIT_STATUS_WT_NEW,
|
||||
GIT_STATUS_INDEX_MODIFIED,
|
||||
GIT_STATUS_WT_DELETED | GIT_STATUS_INDEX_MODIFIED,
|
||||
GIT_STATUS_WT_MODIFIED | GIT_STATUS_INDEX_MODIFIED,
|
||||
GIT_STATUS_INDEX_DELETED,
|
||||
GIT_STATUS_WT_NEW | GIT_STATUS_INDEX_DELETED,
|
||||
GIT_STATUS_INDEX_NEW,
|
||||
GIT_STATUS_WT_DELETED | GIT_STATUS_INDEX_NEW,
|
||||
GIT_STATUS_WT_MODIFIED | GIT_STATUS_INDEX_NEW,
|
||||
GIT_STATUS_WT_NEW,
|
||||
GIT_STATUS_WT_DELETED,
|
||||
GIT_STATUS_WT_DELETED,
|
||||
GIT_STATUS_WT_DELETED,
|
||||
GIT_STATUS_WT_NEW,
|
||||
};
|
||||
|
||||
static const char *entry_paths3[] = {
|
||||
".HEADER",
|
||||
"42-is-not-prime.sigh",
|
||||
|
@ -110,7 +110,13 @@ void test_status_worktree__swap_subdir_and_file(void)
|
||||
{
|
||||
status_entry_counts counts;
|
||||
git_repository *repo = cl_git_sandbox_init("status");
|
||||
git_index *index;
|
||||
git_status_options opts;
|
||||
bool ignore_case;
|
||||
|
||||
cl_git_pass(git_repository_index(&index, repo));
|
||||
ignore_case = index->ignore_case;
|
||||
git_index_free(index);
|
||||
|
||||
/* first alter the contents of the worktree */
|
||||
cl_git_pass(p_rename("status/current_file", "status/swap"));
|
||||
@ -124,8 +130,8 @@ void test_status_worktree__swap_subdir_and_file(void)
|
||||
/* now get status */
|
||||
memset(&counts, 0x0, sizeof(status_entry_counts));
|
||||
counts.expected_entry_count = entry_count3;
|
||||
counts.expected_paths = entry_paths3;
|
||||
counts.expected_statuses = entry_statuses3;
|
||||
counts.expected_paths = ignore_case ? entry_paths3_icase : entry_paths3;
|
||||
counts.expected_statuses = ignore_case ? entry_statuses3_icase : entry_statuses3;
|
||||
|
||||
memset(&opts, 0, sizeof(opts));
|
||||
opts.flags = GIT_STATUS_OPT_INCLUDE_UNTRACKED |
|
||||
|
Loading…
Reference in New Issue
Block a user