diff options
author | Vicent Martí <tanoku@gmail.com> | 2012-05-06 01:22:06 +0400 |
---|---|---|
committer | Vicent Martí <tanoku@gmail.com> | 2012-05-06 01:22:06 +0400 |
commit | 4ef14af93517b3842bc0dfa24147cf10dd029582 (patch) | |
tree | 88f90fa8c9d903f072a2b1c647c51a9899e520c7 | |
parent | f95e8cc07c85034f737872455fce2895186be19d (diff) | |
parent | 282283acc65bab9de231a2b3dc489eb171d5f1cf (diff) |
Merge pull request #664 from arrbee/attrs-from-indexdevelopment-merge
Support git attrs from index (and bare repo)
51 files changed, 867 insertions, 317 deletions
@@ -43,6 +43,7 @@ Ramsay Jones Robert G. Jakabosky Romain Geissler Romain Muller +Russell Belfer Sakari Jokinen Sam Sarath Lakshman diff --git a/include/git2/attr.h b/include/git2/attr.h index 81d1e517b..6a05496dc 100644 --- a/include/git2/attr.h +++ b/include/git2/attr.h @@ -19,42 +19,186 @@ */ GIT_BEGIN_DECL +/** + * GIT_ATTR_TRUE checks if an attribute is set on. In core git + * parlance, this the value for "Set" attributes. + * + * For example, if the attribute file contains: + * + * *.c foo + * + * Then for file `xyz.c` looking up attribute "foo" gives a value for + * which `GIT_ATTR_TRUE(value)` is true. + */ #define GIT_ATTR_TRUE(attr) ((attr) == git_attr__true) + +/** + * GIT_ATTR_FALSE checks if an attribute is set off. In core git + * parlance, this is the value for attributes that are "Unset" (not to + * be confused with values that a "Unspecified"). + * + * For example, if the attribute file contains: + * + * *.h -foo + * + * Then for file `zyx.h` looking up attribute "foo" gives a value for + * which `GIT_ATTR_FALSE(value)` is true. + */ #define GIT_ATTR_FALSE(attr) ((attr) == git_attr__false) -#define GIT_ATTR_UNSPECIFIED(attr) ((attr) == NULL) + +/** + * GIT_ATTR_UNSPECIFIED checks if an attribute is unspecified. This + * may be due to the attribute not being mentioned at all or because + * the attribute was explicitly set unspecified via the `!` operator. + * + * For example, if the attribute file contains: + * + * *.c foo + * *.h -foo + * onefile.c !foo + * + * Then for `onefile.c` looking up attribute "foo" yields a value with + * `GIT_ATTR_UNSPECIFIED(value)` of true. Also, looking up "foo" on + * file `onefile.rb` or looking up "bar" on any file will all give + * `GIT_ATTR_UNSPECIFIED(value)` of true. + */ +#define GIT_ATTR_UNSPECIFIED(attr) (!(attr) || (attr) == git_attr__unset) + +/** + * GIT_ATTR_SET_TO_VALUE checks if an attribute is set to a value (as + * opposied to TRUE, FALSE or UNSPECIFIED). This would be the case if + * for a file with something like: + * + * *.txt eol=lf + * + * Given this, looking up "eol" for `onefile.txt` will give back the + * string "lf" and `GIT_ATTR_SET_TO_VALUE(attr)` will return true. + */ +#define GIT_ATTR_SET_TO_VALUE(attr) \ + ((attr) && (attr) != git_attr__unset && \ + (attr) != git_attr__true && (attr) != git_attr__false) GIT_EXTERN(const char *) git_attr__true; GIT_EXTERN(const char *) git_attr__false; +GIT_EXTERN(const char *) git_attr__unset; + +/** + * Check attribute flags: Reading values from index and working directory. + * + * When checking attributes, it is possible to check attribute files + * in both the working directory (if there is one) and the index (if + * there is one). You can explicitly choose where to check and in + * which order using the following flags. + * + * Core git usually checks the working directory then the index, + * except during a checkout when it checks the index first. It will + * use index only for creating archives or for a bare repo (if an + * index has been specified for the bare repo). + */ +#define GIT_ATTR_CHECK_FILE_THEN_INDEX 0 +#define GIT_ATTR_CHECK_INDEX_THEN_FILE 1 +#define GIT_ATTR_CHECK_INDEX_ONLY 2 +/** + * Check attribute flags: Using the system attributes file. + * + * Normally, attribute checks include looking in the /etc (or system + * equivalent) directory for a `gitattributes` file. Passing this + * flag will cause attribute checks to ignore that file. + */ +#define GIT_ATTR_CHECK_NO_SYSTEM (1 << 2) /** - * Lookup attribute for path returning string caller must free + * Look up the value of one git attribute for path. + * + * @param repo The repository containing the path. + * @param flags A combination of GIT_ATTR_CHECK... flags. + * @param path The path to check for attributes. Relative paths are + * interpreted relative to the repo root. The file does + * not have to exist, but if it does not, then it will be + * treated as a plain file (not a directory). + * @param name The name of the attribute to look up. + * @param value Output of the value of the attribute. Use the GIT_ATTR_... + * macros to test for TRUE, FALSE, UNSPECIFIED, etc. or just + * use the string value for attributes set to a value. You + * should NOT modify or free this value. */ GIT_EXTERN(int) git_attr_get( - git_repository *repo, const char *path, const char *name, + git_repository *repo, + uint32_t flags, + const char *path, + const char *name, const char **value); /** - * Lookup list of attributes for path, populating array of strings + * Look up a list of git attributes for path. + * + * Use this if you have a known list of attributes that you want to + * look up in a single call. This is somewhat more efficient than + * calling `git_attr_get()` multiple times. + * + * For example, you might write: + * + * const char *attrs[] = { "crlf", "diff", "foo" }; + * const char **values[3]; + * git_attr_get_many(repo, 0, "my/fun/file.c", 3, attrs, values); + * + * Then you could loop through the 3 values to get the settings for + * the three attributes you asked about. + * + * @param repo The repository containing the path. + * @param flags A combination of GIT_ATTR_CHECK... flags. + * @param path The path inside the repo to check attributes. This + * does not have to exist, but if it does not, then + * it will be treated as a plain file (i.e. not a directory). + * @param num_attr The number of attributes being looked up + * @param names An array of num_attr strings containing attribute names. + * @param values An array of num_attr entries that will have string + * pointers written into it for the values of the attributes. + * You should not modify or free the values that are written + * into this array (although of course, you should free the + * array itself if you allocated it). */ GIT_EXTERN(int) git_attr_get_many( - git_repository *repo, const char *path, - size_t num_attr, const char **names, + git_repository *repo, + uint32_t flags, + const char *path, + size_t num_attr, + const char **names, const char **values); /** - * Perform an operation on each attribute of a path. + * Loop over all the git attributes for a path. + * + * @param repo The repository containing the path. + * @param flags A combination of GIT_ATTR_CHECK... flags. + * @param path The path inside the repo to check attributes. This + * does not have to exist, but if it does not, then + * it will be treated as a plain file (i.e. not a directory). + * @param callback The function that will be invoked on each attribute + * and attribute value. The name parameter will be the name + * of the attribute and the value will be the value it is + * set to, including possibly NULL if the attribute is + * explicitly set to UNSPECIFIED using the ! sign. This + * will be invoked only once per attribute name, even if + * there are multiple rules for a given file. The highest + * priority rule will be used. + * @param payload Passed on as extra parameter to callback function. */ GIT_EXTERN(int) git_attr_foreach( - git_repository *repo, const char *path, + git_repository *repo, + uint32_t flags, + const char *path, int (*callback)(const char *name, const char *value, void *payload), void *payload); /** * Flush the gitattributes cache. * - * Call this if you have reason to believe that the attributes files - * on disk no longer match the cached contents of memory. + * Call this if you have reason to believe that the attributes files on + * disk no longer match the cached contents of memory. This will cause + * the attributes files to be reloaded the next time that an attribute + * access function is called. */ GIT_EXTERN(void) git_attr_cache_flush( git_repository *repo); @@ -62,7 +206,7 @@ GIT_EXTERN(void) git_attr_cache_flush( /** * Add a macro definition. * - * Macros will automatically be loaded from the top level .gitattributes + * Macros will automatically be loaded from the top level `.gitattributes` * file of the repository (plus the build-in "binary" macro). This * function allows you to add others. For example, to add the default * macro, you would call: diff --git a/src/attr.c b/src/attr.c index 120d12737..b7ac6355d 100644 --- a/src/attr.c +++ b/src/attr.c @@ -6,12 +6,18 @@ GIT__USE_STRMAP; static int collect_attr_files( - git_repository *repo, const char *path, git_vector *files); + git_repository *repo, + uint32_t flags, + const char *path, + git_vector *files); int git_attr_get( - git_repository *repo, const char *pathname, - const char *name, const char **value) + git_repository *repo, + uint32_t flags, + const char *pathname, + const char *name, + const char **value) { int error; git_attr_path path; @@ -26,7 +32,7 @@ int git_attr_get( if (git_attr_path__init(&path, pathname, git_repository_workdir(repo)) < 0) return -1; - if ((error = collect_attr_files(repo, pathname, &files)) < 0) + if ((error = collect_attr_files(repo, flags, pathname, &files)) < 0) goto cleanup; attr.name = name; @@ -58,8 +64,12 @@ typedef struct { } attr_get_many_info; int git_attr_get_many( - git_repository *repo, const char *pathname, - size_t num_attr, const char **names, const char **values) + git_repository *repo, + uint32_t flags, + const char *pathname, + size_t num_attr, + const char **names, + const char **values) { int error; git_attr_path path; @@ -75,7 +85,7 @@ int git_attr_get_many( if (git_attr_path__init(&path, pathname, git_repository_workdir(repo)) < 0) return -1; - if ((error = collect_attr_files(repo, pathname, &files)) < 0) + if ((error = collect_attr_files(repo, flags, pathname, &files)) < 0) goto cleanup; info = git__calloc(num_attr, sizeof(attr_get_many_info)); @@ -119,7 +129,9 @@ cleanup: int git_attr_foreach( - git_repository *repo, const char *pathname, + git_repository *repo, + uint32_t flags, + const char *pathname, int (*callback)(const char *name, const char *value, void *payload), void *payload) { @@ -135,7 +147,7 @@ int git_attr_foreach( if (git_attr_path__init(&path, pathname, git_repository_workdir(repo)) < 0) return -1; - if ((error = collect_attr_files(repo, pathname, &files)) < 0) + if ((error = collect_attr_files(repo, flags, pathname, &files)) < 0) goto cleanup; seen = git_strmap_alloc(); @@ -203,113 +215,231 @@ int git_attr_add_macro( return error; } -bool git_attr_cache__is_cached(git_repository *repo, const char *path) +bool git_attr_cache__is_cached( + git_repository *repo, git_attr_file_source source, const char *path) { - const char *cache_key = path; + git_buf cache_key = GIT_BUF_INIT; git_strmap *files = git_repository_attr_cache(repo)->files; + const char *workdir = git_repository_workdir(repo); + bool rval; + + if (workdir && git__prefixcmp(path, workdir) == 0) + path += strlen(workdir); + if (git_buf_printf(&cache_key, "%d#%s", (int)source, path) < 0) + return false; + + rval = git_strmap_exists(files, git_buf_cstr(&cache_key)); + + git_buf_free(&cache_key); + + return rval; +} + +static int load_attr_file(const char *filename, const char **data) +{ + int error; + git_buf content = GIT_BUF_INIT; + + error = git_futils_readbuffer(&content, filename); + *data = error ? NULL : git_buf_detach(&content); + + return error; +} - if (repo && git__prefixcmp(cache_key, git_repository_workdir(repo)) == 0) - cache_key += strlen(git_repository_workdir(repo)); +static int load_attr_blob_from_index( + git_repository *repo, const char *filename, git_blob **blob) +{ + int error; + git_index *index; + git_index_entry *entry; + + if ((error = git_repository_index__weakptr(&index, repo)) < 0 || + (error = git_index_find(index, filename)) < 0) + return error; - return git_strmap_exists(files, cache_key); + entry = git_index_get(index, error); + + return git_blob_lookup(blob, repo, &entry->oid); } -int git_attr_cache__lookup_or_create_file( +int git_attr_cache__internal_file( git_repository *repo, - const char *key, const char *filename, - int (*loader)(git_repository *, const char *, git_attr_file *), - git_attr_file **file_ptr) + git_attr_file **file) { - int error; + int error = 0; git_attr_cache *cache = git_repository_attr_cache(repo); - git_attr_file *file = NULL; - khiter_t pos; - - pos = git_strmap_lookup_index(cache->files, key); - if (git_strmap_valid_index(cache->files, pos)) { - *file_ptr = git_strmap_value_at(cache->files, pos); - return 0; - } + khiter_t cache_pos = git_strmap_lookup_index(cache->files, filename); - if (loader && git_path_exists(filename) == false) { - *file_ptr = NULL; + if (git_strmap_valid_index(cache->files, cache_pos)) { + *file = git_strmap_value_at(cache->files, cache_pos); return 0; } - if (git_attr_file__new(&file, &cache->pool) < 0) + if (git_attr_file__new(file, 0, filename, &cache->pool) < 0) return -1; - if (loader) - error = loader(repo, filename, file); - else - error = git_attr_file__set_path(repo, key, file); - - if (!error) { - git_strmap_insert(cache->files, file->path, file, error); - if (error > 0) - error = 0; - } - - if (error < 0) { - git_attr_file__free(file); - file = NULL; - } + git_strmap_insert(cache->files, (*file)->key + 2, *file, error); + if (error > 0) + error = 0; - *file_ptr = file; return error; } -/* add git_attr_file to vector of files, loading if needed */ int git_attr_cache__push_file( git_repository *repo, - git_vector *stack, - const char *base, - const char *filename, - int (*loader)(git_repository *, const char *, git_attr_file *)) + const char *base, + const char *filename, + git_attr_file_source source, + git_attr_file_parser parse, + git_vector *stack) { - int error; + int error = 0; git_buf path = GIT_BUF_INIT; + const char *workdir = git_repository_workdir(repo); + const char *relfile, *content = NULL; + git_attr_cache *cache = git_repository_attr_cache(repo); git_attr_file *file = NULL; - const char *cache_key; + git_blob *blob = NULL; - if (base != NULL) { + assert(filename && stack); + + /* join base and path as needed */ + if (base != NULL && git_path_root(filename) < 0) { if (git_buf_joinpath(&path, base, filename) < 0) return -1; filename = path.ptr; } - /* either get attr_file from cache or read from disk */ - cache_key = filename; - if (repo && git__prefixcmp(cache_key, git_repository_workdir(repo)) == 0) - cache_key += strlen(git_repository_workdir(repo)); + relfile = filename; + if (workdir && git__prefixcmp(relfile, workdir) == 0) + relfile += strlen(workdir); + + /* check cache */ + if (cache && cache->files) { + git_buf cache_key = GIT_BUF_INIT; + khiter_t cache_pos; + + if (git_buf_printf(&cache_key, "%d#%s", (int)source, relfile) < 0) + return -1; + + cache_pos = git_strmap_lookup_index(cache->files, cache_key.ptr); + + git_buf_free(&cache_key); + + if (git_strmap_valid_index(cache->files, cache_pos)) { + file = git_strmap_value_at(cache->files, cache_pos); + goto finish; + } + } + + /* if not in cache, load data, parse, and cache */ + + if (source == GIT_ATTR_FILE_FROM_FILE) + error = load_attr_file(filename, &content); + else + error = load_attr_blob_from_index(repo, relfile, &blob); + + if (error) { + /* not finding a file is not an error for this function */ + if (error == GIT_ENOTFOUND) { + giterr_clear(); + error = 0; + } + goto finish; + } + + if (blob) + content = git_blob_rawcontent(blob); - error = git_attr_cache__lookup_or_create_file( - repo, cache_key, filename, loader, &file); + if ((error = git_attr_file__new(&file, source, relfile, &cache->pool)) < 0) + goto finish; + if (parse && (error = parse(repo, content, file)) < 0) + goto finish; + + git_strmap_insert(cache->files, file->key, file, error); + if (error > 0) + error = 0; + +finish: + /* push file onto vector if we found one*/ if (!error && file != NULL) error = git_vector_insert(stack, file); + if (error != 0) + git_attr_file__free(file); + + if (blob) + git_blob_free(blob); + else + git__free((void *)content); + git_buf_free(&path); + return error; } -#define push_attrs(R,S,B,F) \ - git_attr_cache__push_file((R),(S),(B),(F),git_attr_file__from_file) +#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)) typedef struct { git_repository *repo; + uint32_t flags; + const char *workdir; + git_index *index; git_vector *files; } attr_walk_up_info; +int git_attr_cache__decide_sources( + uint32_t flags, bool has_wd, bool has_index, git_attr_file_source *srcs) +{ + int count = 0; + + switch (flags & 0x03) { + case GIT_ATTR_CHECK_FILE_THEN_INDEX: + if (has_wd) + srcs[count++] = GIT_ATTR_FILE_FROM_FILE; + if (has_index) + srcs[count++] = GIT_ATTR_FILE_FROM_INDEX; + break; + case GIT_ATTR_CHECK_INDEX_THEN_FILE: + if (has_index) + srcs[count++] = GIT_ATTR_FILE_FROM_INDEX; + if (has_wd) + srcs[count++] = GIT_ATTR_FILE_FROM_FILE; + break; + case GIT_ATTR_CHECK_INDEX_ONLY: + if (has_index) + srcs[count++] = GIT_ATTR_FILE_FROM_INDEX; + break; + } + + return count; +} + static int push_one_attr(void *ref, git_buf *path) { + int error = 0, n_src, i; attr_walk_up_info *info = (attr_walk_up_info *)ref; - return push_attrs(info->repo, info->files, path->ptr, GIT_ATTR_FILE); + git_attr_file_source src[2]; + + n_src = git_attr_cache__decide_sources( + info->flags, info->workdir != NULL, info->index != NULL, src); + + 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); + + return error; } static int collect_attr_files( - git_repository *repo, const char *path, git_vector *files) + git_repository *repo, + uint32_t flags, + const char *path, + git_vector *files) { int error; git_buf dir = GIT_BUF_INIT; @@ -320,7 +450,11 @@ static int collect_attr_files( git_vector_init(files, 4, NULL) < 0) return -1; - error = git_path_find_dir(&dir, path, workdir); + /* given a unrooted path in a non-bare repo, resolve it */ + if (workdir && git_path_root(path) < 0) + error = git_path_find_dir(&dir, path, workdir); + else + error = git_buf_sets(&dir, path); if (error < 0) goto cleanup; @@ -331,29 +465,36 @@ static int collect_attr_files( * - $GIT_PREFIX/etc/gitattributes */ - error = push_attrs( + error = push_attr_file( repo, files, git_repository_path(repo), GIT_ATTR_FILE_INREPO); if (error < 0) goto cleanup; - info.repo = repo; + info.repo = repo; + info.flags = flags; + info.workdir = workdir; + if (git_repository_index__weakptr(&info.index, repo) < 0) + giterr_clear(); /* no error even if there is no index */ info.files = files; + error = git_path_walk_up(&dir, workdir, push_one_attr, &info); if (error < 0) goto cleanup; if (git_repository_attr_cache(repo)->cfg_attr_file != NULL) { - error = push_attrs( + error = push_attr_file( repo, files, NULL, git_repository_attr_cache(repo)->cfg_attr_file); if (error < 0) goto cleanup; } - error = git_futils_find_system_file(&dir, GIT_ATTR_FILE_SYSTEM); - if (!error) - error = push_attrs(repo, files, NULL, dir.ptr); - else if (error == GIT_ENOTFOUND) - error = 0; + if ((flags & GIT_ATTR_CHECK_NO_SYSTEM) == 0) { + error = git_futils_find_system_file(&dir, GIT_ATTR_FILE_SYSTEM); + if (!error) + error = push_attr_file(repo, files, NULL, dir.ptr); + else if (error == GIT_ENOTFOUND) + error = 0; + } cleanup: if (error < 0) diff --git a/src/attr.h b/src/attr.h index 43caf1b81..a35b1160f 100644 --- a/src/attr.h +++ b/src/attr.h @@ -22,6 +22,9 @@ typedef struct { const char *cfg_excl_file; /* cached value of core.excludesfile */ } git_attr_cache; +typedef int (*git_attr_file_parser)( + git_repository *, const char *, git_attr_file *); + extern int git_attr_cache__init(git_repository *repo); extern int git_attr_cache__insert_macro( @@ -30,21 +33,24 @@ extern int git_attr_cache__insert_macro( extern git_attr_rule *git_attr_cache__lookup_macro( git_repository *repo, const char *name); -extern int git_attr_cache__lookup_or_create_file( +extern int git_attr_cache__push_file( git_repository *repo, - const char *key, + const char *base, const char *filename, - int (*loader)(git_repository *, const char *, git_attr_file *), - git_attr_file **file_ptr); + git_attr_file_source source, + git_attr_file_parser parse, + git_vector *stack); -extern int git_attr_cache__push_file( +extern int git_attr_cache__internal_file( git_repository *repo, - git_vector *stack, - const char *base, - const char *filename, - int (*loader)(git_repository *, const char *, git_attr_file *)); + const char *key, + git_attr_file **file_ptr); /* returns true if path is in cache */ -extern bool git_attr_cache__is_cached(git_repository *repo, const char *path); +extern bool git_attr_cache__is_cached( + git_repository *repo, git_attr_file_source source, const char *path); + +extern int git_attr_cache__decide_sources( + uint32_t flags, bool has_wd, bool has_index, git_attr_file_source *srcs); #endif diff --git a/src/attr_file.c b/src/attr_file.c index 25c21b1fd..ab320a6c4 100644 --- a/src/attr_file.c +++ b/src/attr_file.c @@ -1,15 +1,22 @@ #include "common.h" #include "repository.h" #include "filebuf.h" +#include "git2/blob.h" +#include "git2/tree.h" #include <ctype.h> const char *git_attr__true = "[internal]__TRUE__"; const char *git_attr__false = "[internal]__FALSE__"; +const char *git_attr__unset = "[internal]__UNSET__"; static int sort_by_hash_and_name(const void *a_raw, const void *b_raw); static void git_attr_rule__clear(git_attr_rule *rule); -int git_attr_file__new(git_attr_file **attrs_ptr, git_pool *pool) +int git_attr_file__new( + git_attr_file **attrs_ptr, + git_attr_file_source from, + const char *path, + git_pool *pool) { git_attr_file *attrs = NULL; @@ -25,6 +32,18 @@ int git_attr_file__new(git_attr_file **attrs_ptr, git_pool *pool) attrs->pool_is_allocated = true; } + if (path) { + size_t len = strlen(path); + + attrs->key = git_pool_malloc(attrs->pool, len + 3); + GITERR_CHECK_ALLOC(attrs->key); + + attrs->key[0] = '0' + from; + attrs->key[1] = '#'; + memcpy(&attrs->key[2], path, len); + attrs->key[len + 2] = '\0'; + } + if (git_vector_init(&attrs->rules, 4, NULL) < 0) goto fail; @@ -37,31 +56,7 @@ fail: return -1; } -int git_attr_file__set_path( - git_repository *repo, const char *path, git_attr_file *file) -{ - if (file->path != NULL) { - git__free(file->path); - file->path = NULL; - } - - if (repo == NULL) - file->path = git__strdup(path); - else { - const char *workdir = git_repository_workdir(repo); - - if (workdir && git__prefixcmp(path, workdir) == 0) - file->path = git__strdup(path + strlen(workdir)); - else - file->path = git__strdup(path); - } - - GITERR_CHECK_ALLOC(file->path); - - return 0; -} - -int git_attr_file__from_buffer( +int git_attr_file__parse_buffer( git_repository *repo, const char *buffer, git_attr_file *attrs) { int error = 0; @@ -73,10 +68,10 @@ int git_attr_file__from_buffer( scan = buffer; - if (attrs->path && git__suffixcmp(attrs->path, GIT_ATTR_FILE) == 0) { - context = git__strndup(attrs->path, - strlen(attrs->path) - strlen(GIT_ATTR_FILE)); - GITERR_CHECK_ALLOC(context); + /* if subdir file path, convert context for file paths */ + if (attrs->key && git__suffixcmp(attrs->key, "/" GIT_ATTR_FILE) == 0) { + context = attrs->key + 2; + context[strlen(context) - strlen(GIT_ATTR_FILE)] = '\0'; } while (!error && *scan) { @@ -112,28 +107,34 @@ int git_attr_file__from_buffer( } git_attr_rule__free(rule); - git__free(context); + + /* restore file path used for context */ + if (context) + context[strlen(context)] = '.'; /* first char of GIT_ATTR_FILE */ return error; } -int git_attr_file__from_file( - git_repository *repo, const char *path, git_attr_file *file) +int git_attr_file__new_and_load( + git_attr_file **attrs_ptr, + const char *path) { int error; - git_buf fbuf = GIT_BUF_INIT; + git_buf content = GIT_BUF_INIT; - assert(path && file); + if ((error = git_attr_file__new(attrs_ptr, 0, path, NULL)) < 0) + return error; - if (file->path == NULL && git_attr_file__set_path(repo, path, file) < 0) - return -1; - - if (git_futils_readbuffer(&fbuf, path) < 0) - return -1; + if (!(error = git_futils_readbuffer(&content, path))) + error = git_attr_file__parse_buffer( + NULL, git_buf_cstr(&content), *attrs_ptr); - error = git_attr_file__from_buffer(repo, fbuf.ptr, file); + git_buf_free(&content); - git_buf_free(&fbuf); + if (error) { + git_attr_file__free(*attrs_ptr); + *attrs_ptr = NULL; + } return error; } @@ -151,9 +152,6 @@ void git_attr_file__free(git_attr_file *file) git_vector_free(&file->rules); - git__free(file->path); - file->path = NULL; - if (file->pool_is_allocated) { git_pool_clear(file->pool); git__free(file->pool); @@ -504,7 +502,7 @@ int git_attr_assignment__parse( assign->value = git_attr__false; scan++; } else if (*scan == '!') { - assign->value = NULL; /* explicit unspecified state */ + assign->value = git_attr__unset; /* explicit unspecified state */ scan++; } else if (*scan == '#') /* comment rest of line */ break; diff --git a/src/attr_file.h b/src/attr_file.h index 10851bc49..ec488c4dc 100644 --- a/src/attr_file.h +++ b/src/attr_file.h @@ -48,7 +48,7 @@ typedef struct { } git_attr_assignment; typedef struct { - char *path; /* cache the path this was loaded from */ + char *key; /* cache "source#path" this was loaded from */ git_vector rules; /* vector of <rule*> or <fnmatch*> */ git_pool *pool; bool pool_is_allocated; @@ -61,20 +61,25 @@ typedef struct { int is_dir; } git_attr_path; +typedef enum { + GIT_ATTR_FILE_FROM_FILE = 0, + GIT_ATTR_FILE_FROM_INDEX = 1 +} git_attr_file_source; + /* * git_attr_file API */ -extern int git_attr_file__new(git_attr_file **attrs_ptr, git_pool *pool); +extern int git_attr_file__new( + git_attr_file **attrs_ptr, git_attr_file_source src, const char *path, git_pool *pool); + +extern int git_attr_file__new_and_load( + git_attr_file **attrs_ptr, const char *path); + extern void git_attr_file__free(git_attr_file *file); -extern int git_attr_file__from_buffer( +extern int git_attr_file__parse_buffer( git_repository *repo, const char *buf, git_attr_file *file); -extern int git_attr_file__from_file( - git_repository *repo, const char *path, git_attr_file *file); - -extern int git_attr_file__set_path( - git_repository *repo, const char *path, git_attr_file *file); extern int git_attr_file__lookup_one( git_attr_file *file, diff --git a/src/config_file.c b/src/config_file.c index ed5caf980..746d9655c 100644 --- a/src/config_file.c +++ b/src/config_file.c @@ -265,6 +265,7 @@ static int config_set(git_config_file *cfg, const char *name, const char *value) cvar_free(old_var); if (config_write(b, key, NULL, value) < 0) { + git_strmap_delete(b->values, var->key); cvar_free(var); return -1; } diff --git a/src/crlf.c b/src/crlf.c index b495d2de0..5d09a1f40 100644 --- a/src/crlf.c +++ b/src/crlf.c @@ -82,7 +82,8 @@ static int crlf_load_attributes(struct crlf_attrs *ca, git_repository *repo, con const char *attr_vals[NUM_CONV_ATTRS]; int error; - error = git_attr_get_many(repo, path, NUM_CONV_ATTRS, attr_names, attr_vals); + error = git_attr_get_many( + repo, 0, path, NUM_CONV_ATTRS, attr_names, attr_vals); if (error == GIT_ENOTFOUND) { ca->crlf_action = GIT_CRLF_GUESS; diff --git a/src/diff.c b/src/diff.c index b845f9e8c..524cc9f59 100644 --- a/src/diff.c +++ b/src/diff.c @@ -506,7 +506,7 @@ static int diff_from_iterators( git_diff_list **diff_ptr) { const git_index_entry *oitem, *nitem; - char *ignore_prefix = NULL; + git_buf ignore_prefix = GIT_BUF_INIT; git_diff_list *diff = git_diff_list_alloc(repo, opts); if (!diff) goto fail; @@ -536,8 +536,8 @@ static int diff_from_iterators( git_delta_t delta_type = GIT_DELTA_ADDED; /* contained in ignored parent directory, so this can be skipped. */ - if (ignore_prefix != NULL && - git__prefixcmp(nitem->path, ignore_prefix) == 0) + if (git_buf_len(&ignore_prefix) && + git__prefixcmp(nitem->path, git_buf_cstr(&ignore_prefix)) == 0) { if (git_iterator_advance(new_iter, &nitem) < 0) goto fail; @@ -555,7 +555,7 @@ static int diff_from_iterators( (oitem && git__prefixcmp(oitem->path, nitem->path) == 0)) { if (is_ignored) - ignore_prefix = nitem->path; + git_buf_sets(&ignore_prefix, nitem->path); if (git_iterator_advance_into_directory(new_iter, &nitem) < 0) goto fail; @@ -589,12 +589,16 @@ static int diff_from_iterators( git_iterator_free(old_iter); git_iterator_free(new_iter); + git_buf_free(&ignore_prefix); + *diff_ptr = diff; return 0; fail: git_iterator_free(old_iter); git_iterator_free(new_iter); + git_buf_free(&ignore_prefix); + git_diff_list_free(diff); *diff_ptr = NULL; return -1; diff --git a/src/diff_output.c b/src/diff_output.c index ca28fd01e..c380db996 100644 --- a/src/diff_output.c +++ b/src/diff_output.c @@ -103,7 +103,7 @@ static int diff_output_cb(void *priv, mmbuffer_t *bufs, int len) static int update_file_is_binary_by_attr(git_repository *repo, git_diff_file *file) { const char *value; - if (git_attr_get(repo, file->path, "diff", &value) < 0) + if (git_attr_get(repo, 0, file->path, "diff", &value) < 0) return -1; if (GIT_ATTR_FALSE(value)) diff --git a/src/ignore.c b/src/ignore.c index 20b96c602..fc6194bb5 100644 --- a/src/ignore.c +++ b/src/ignore.c @@ -5,29 +5,22 @@ #define GIT_IGNORE_FILE_INREPO "info/exclude" #define GIT_IGNORE_FILE ".gitignore" -static int load_ignore_file( - git_repository *repo, const char *path, git_attr_file *ignores) +static int parse_ignore_file( + git_repository *repo, const char *buffer, git_attr_file *ignores) { - int error; - git_buf fbuf = GIT_BUF_INIT; + int error = 0; git_attr_fnmatch *match = NULL; const char *scan = NULL; char *context = NULL; - if (ignores->path == NULL) { - if (git_attr_file__set_path(repo, path, ignores) < 0) - return -1; - } + GIT_UNUSED(repo); - if (git__suffixcmp(ignores->path, GIT_IGNORE_FILE) == 0) { - context = git__strndup(ignores->path, - strlen(ignores->path) - strlen(GIT_IGNORE_FILE)); - GITERR_CHECK_ALLOC(context); + if (ignores->key && git__suffixcmp(ignores->key, "/" GIT_IGNORE_FILE) == 0) { + context = ignores->key + 2; + context[strlen(context) - strlen(GIT_IGNORE_FILE)] = '\0'; } - error = git_futils_readbuffer(&fbuf, path); - - scan = fbuf.ptr; + scan = buffer; while (!error && *scan) { if (!match) { @@ -54,23 +47,27 @@ static int load_ignore_file( } } - git_buf_free(&fbuf); git__free(match); - git__free(context); + /* restore file path used for context */ + if (context) + context[strlen(context)] = '.'; /* first char of GIT_IGNORE_FILE */ return error; } -#define push_ignore(R,S,B,F) \ - git_attr_cache__push_file((R),(S),(B),(F),load_ignore_file) +#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)) static int push_one_ignore(void *ref, git_buf *path) { git_ignores *ign = (git_ignores *)ref; - return push_ignore(ign->repo, &ign->ign_path, path->ptr, GIT_IGNORE_FILE); + return push_ignore_file(ign->repo, &ign->ign_path, path->ptr, GIT_IGNORE_FILE); } -int git_ignore__for_path(git_repository *repo, const char *path, git_ignores *ignores) +int git_ignore__for_path( + git_repository *repo, + const char *path, + git_ignores *ignores) { int error = 0; const char *workdir = git_repository_workdir(repo); @@ -86,30 +83,37 @@ int git_ignore__for_path(git_repository *repo, const char *path, git_ignores *ig (error = git_attr_cache__init(repo)) < 0) goto cleanup; - /* translate path into directory within workdir */ - if ((error = git_path_find_dir(&ignores->dir, path, workdir)) < 0) + /* given a unrooted path in a non-bare repo, resolve it */ + if (workdir && git_path_root(path) < 0) + error = git_path_find_dir(&ignores->dir, path, workdir); + else + error = git_buf_sets(&ignores->dir, path); + if (error < 0) goto cleanup; /* set up internals */ - error = git_attr_cache__lookup_or_create_file( - repo, GIT_IGNORE_INTERNAL, NULL, NULL, &ignores->ign_internal); + error = git_attr_cache__internal_file( + repo, GIT_IGNORE_INTERNAL, &ignores->ign_internal); if (error < 0) goto cleanup; /* load .gitignore up the path */ - error = git_path_walk_up(&ignores->dir, workdir, push_one_ignore, ignores); - if (error < 0) - goto cleanup; + if (workdir != NULL) { + error = git_path_walk_up( + &ignores->dir, workdir, push_one_ignore, ignores); + if (error < 0) + goto cleanup; + } /* load .git/info/exclude */ - error = push_ignore(repo, &ignores->ign_global, + error = push_ignore_file(repo, &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(repo, &ignores->ign_global, NULL, + error = push_ignore_file(repo, &ignores->ign_global, NULL, git_repository_attr_cache(repo)->cfg_excl_file); cleanup: @@ -124,7 +128,7 @@ int git_ignore__push_dir(git_ignores *ign, const char *dir) if (git_buf_joinpath(&ign->dir, ign->dir.ptr, dir) < 0) return -1; else - return push_ignore( + return push_ignore_file( ign->repo, &ign->ign_path, ign->dir.ptr, GIT_IGNORE_FILE); } @@ -132,7 +136,7 @@ int git_ignore__pop_dir(git_ignores *ign) { if (ign->ign_path.length > 0) { git_attr_file *file = git_vector_last(&ign->ign_path); - if (git__suffixcmp(ign->dir.ptr, file->path) == 0) + if (git__suffixcmp(ign->dir.ptr, file->key + 2) == 0) git_vector_pop(&ign->ign_path); git_buf_rtruncate_at_char(&ign->dir, '/'); } @@ -163,7 +167,8 @@ static bool ignore_lookup_in_rules( return false; } -int git_ignore__lookup(git_ignores *ignores, const char *pathname, int *ignored) +int git_ignore__lookup( + git_ignores *ignores, const char *pathname, int *ignored) { unsigned int i; git_attr_file *file; diff --git a/src/ignore.h b/src/ignore.h index 49f72bf25..809d2edbd 100644 --- a/src/ignore.h +++ b/src/ignore.h @@ -25,13 +25,14 @@ typedef struct { git_vector ign_global; } git_ignores; -extern int git_ignore__for_path( - git_repository *repo, const char *path, git_ignores *ign); +extern int git_ignore__for_path(git_repository *repo, const char *path, git_ignores *ign); extern int git_ignore__push_dir(git_ignores *ign, const char *dir); + extern int git_ignore__pop_dir(git_ignores *ign); extern void git_ignore__free(git_ignores *ign); + extern int git_ignore__lookup(git_ignores *ign, const char *path, int *ignored); #endif diff --git a/src/object.c b/src/object.c index 8e8eac4e3..e02bd69ba 100644 --- a/src/object.c +++ b/src/object.c @@ -146,7 +146,7 @@ int git_object_lookup_prefix( } if (error < 0) - return -1; + return error; if (type != GIT_OBJ_ANY && type != odb_obj->raw.type) { git_odb_object_free(odb_obj); @@ -292,3 +292,42 @@ size_t git_object__size(git_otype type) return git_objects_table[type].size; } +int git_object__resolve_to_type(git_object **obj, git_otype type) +{ + int error = 0; + git_object *scan, *next; + + if (type == GIT_OBJ_ANY) + return 0; + + scan = *obj; + + while (!error && scan && git_object_type(scan) != type) { + + switch (git_object_type(scan)) { + case GIT_OBJ_COMMIT: + { + git_tree *tree = NULL; + error = git_commit_tree(&tree, (git_commit *)scan); + next = (git_object *)tree; + break; + } + + case GIT_OBJ_TAG: + error = git_tag_target(&next, (git_tag *)scan); + break; + + default: + giterr_set(GITERR_REFERENCE, "Object does not resolve to type"); + error = -1; + next = NULL; + break; + } + + git_object_free(scan); + scan = next; + } + + *obj = scan; + return error; +} @@ -589,7 +589,7 @@ int git_odb_read_prefix( } if (found == 0) - return git_odb__error_notfound("no match for prefix"); + return git_odb__error_notfound("no match for prefix", short_id); if (found > 1) return git_odb__error_ambiguous("multiple matches for prefix"); @@ -684,9 +684,15 @@ int git_odb_open_rstream(git_odb_stream **stream, git_odb *db, const git_oid *oi return error; } -int git_odb__error_notfound(const char *message) +int git_odb__error_notfound(const char *message, const git_oid *oid) { - giterr_set(GITERR_ODB, "Object not found - %s", message); + if (oid != NULL) { + char oid_str[GIT_OID_HEXSZ + 1]; + git_oid_tostr(oid_str, sizeof(oid_str), oid); + giterr_set(GITERR_ODB, "Object not found - %s (%s)", message, oid_str); + } else + giterr_set(GITERR_ODB, "Object not found - %s", message); + return GIT_ENOTFOUND; } @@ -70,7 +70,7 @@ int git_odb__hashlink(git_oid *out, const char *path); /* * Generate a GIT_ENOTFOUND error for the ODB. */ -int git_odb__error_notfound(const char *message); +int git_odb__error_notfound(const char *message, const git_oid *oid); /* * Generate a GIT_EAMBIGUOUS error for the ODB. diff --git a/src/odb_loose.c b/src/odb_loose.c index d028deca5..989b03ab2 100644 --- a/src/odb_loose.c +++ b/src/odb_loose.c @@ -528,7 +528,7 @@ static int locate_object_short_oid( /* Check that directory exists */ if (git_path_isdir(object_location->ptr) == false) - return git_odb__error_notfound("failed to locate from short oid"); + return git_odb__error_notfound("no matching loose object for prefix", short_oid); state.dir_len = git_buf_len(object_location); state.short_oid_len = len; @@ -541,7 +541,7 @@ static int locate_object_short_oid( return error; if (!state.found) - return git_odb__error_notfound("failed to locate from short oid"); + return git_odb__error_notfound("no matching loose object for prefix", short_oid); /* Convert obtained hex formatted oid to raw */ error = git_oid_fromstr(res_oid, (char *)state.res_oid); @@ -590,7 +590,7 @@ static int loose_backend__read_header(size_t *len_p, git_otype *type_p, git_odb_ raw.type = GIT_OBJ_BAD; if (locate_object(&object_path, (loose_backend *)backend, oid) < 0) - error = git_odb__error_notfound("in loose backend"); + error = git_odb__error_notfound("no matching loose object", oid); else if ((error = read_header_loose(&raw, &object_path)) == 0) { *len_p = raw.len; *type_p = raw.type; @@ -610,7 +610,7 @@ static int loose_backend__read(void **buffer_p, size_t *len_p, git_otype *type_p assert(backend && oid); if (locate_object(&object_path, (loose_backend *)backend, oid) < 0) - error = git_odb__error_notfound("in loose backend"); + error = git_odb__error_notfound("no matching loose object", oid); else if ((error = read_loose(&raw, &object_path)) == 0) { *buffer_p = raw.data; *len_p = raw.len; diff --git a/src/odb_pack.c b/src/odb_pack.c index 242200b4a..458f288d9 100644 --- a/src/odb_pack.c +++ b/src/odb_pack.c @@ -242,7 +242,7 @@ static int packfile_refresh_all(struct pack_backend *backend) return 0; if (p_stat(backend->pack_folder, &st) < 0 || !S_ISDIR(st.st_mode)) - return git_odb__error_notfound("failed to refresh packfiles"); + return git_odb__error_notfound("failed to refresh packfiles", NULL); if (st.st_mtime != backend->pack_folder_mtime) { git_buf path = GIT_BUF_INIT; @@ -288,7 +288,7 @@ static int pack_entry_find(struct git_pack_entry *e, struct pack_backend *backen } } - return git_odb__error_notfound("failed to find pack entry"); + return git_odb__error_notfound("failed to find pack entry", oid); } static int pack_entry_find_prefix( @@ -330,7 +330,7 @@ static int pack_entry_find_prefix( } if (!found) - return git_odb__error_notfound("failed to find pack entry"); + return git_odb__error_notfound("no matching pack entry for prefix", short_oid); else if (found > 1) return git_odb__error_ambiguous("found multiple pack entries"); else diff --git a/src/pack.c b/src/pack.c index 8d71138a2..4a6bc6ae8 100644 --- a/src/pack.c +++ b/src/pack.c @@ -375,6 +375,18 @@ int git_packfile_unpack( return error; } +static void *use_git_alloc(void *opaq, unsigned int count, unsigned int size) +{ + GIT_UNUSED(opaq); + return git__calloc(count, size); +} + +static void use_git_free(void *opaq, void *ptr) +{ + GIT_UNUSED(opaq); + git__free(ptr); +} + int packfile_unpack_compressed( git_rawobj *obj, struct git_pack_file *p, @@ -393,6 +405,8 @@ int packfile_unpack_compressed( memset(&stream, 0, sizeof(stream)); stream.next_out = buffer; stream.avail_out = (uInt)size + 1; + stream.zalloc = use_git_alloc; + stream.zfree = use_git_free; st = inflateInit(&stream); if (st != Z_OK) { @@ -541,7 +555,7 @@ static int packfile_open(struct git_pack_file *p) assert(p->index_map.data); if (!p->index_map.data && pack_index_open(p) < 0) - return git_odb__error_notfound("failed to open packfile"); + return git_odb__error_notfound("failed to open packfile", NULL); /* TODO: open with noatime */ p->mwf.fd = git_futils_open_ro(p->pack_name); @@ -615,7 +629,7 @@ int git_packfile_check(struct git_pack_file **pack_out, const char *path) path_len -= strlen(".idx"); if (path_len < 1) { git__free(p); - return git_odb__error_notfound("invalid packfile path"); + return git_odb__error_notfound("invalid packfile path", NULL); } memcpy(p->pack_name, path, path_len); @@ -627,7 +641,7 @@ int git_packfile_check(struct git_pack_file **pack_out, const char *path) strcpy(p->pack_name + path_len, ".pack"); if (p_stat(p->pack_name, &st) < 0 || !S_ISREG(st.st_mode)) { git__free(p); - return git_odb__error_notfound("packfile not found"); + return git_odb__error_notfound("packfile not found", NULL); } /* ok, it looks sane as far as we can check without @@ -733,9 +747,8 @@ static int pack_entry_find_offset( if (pos < (int)p->num_objects) { current = index + pos * stride; - if (!git_oid_ncmp(short_oid, (const git_oid *)current, len)) { + if (!git_oid_ncmp(short_oid, (const git_oid *)current, len)) found = 1; - } } } @@ -749,7 +762,7 @@ static int pack_entry_find_offset( } if (!found) - return git_odb__error_notfound("failed to find offset for pack entry"); + return git_odb__error_notfound("failed to find offset for pack entry", short_oid); if (found > 1) return git_odb__error_ambiguous("found multiple offsets for pack entry"); *offset_out = nth_packed_object_offset(p, pos); diff --git a/src/repository.c b/src/repository.c index cfabee420..d4de38104 100644 --- a/src/repository.c +++ b/src/repository.c @@ -862,3 +862,23 @@ int git_repository_is_bare(git_repository *repo) assert(repo); return repo->is_bare; } + +int git_repository_head_tree(git_tree **tree, git_repository *repo) +{ + git_oid head_oid; + git_object *obj = NULL; + + if (git_reference_name_to_oid(&head_oid, repo, GIT_HEAD_FILE) < 0) { + /* cannot resolve HEAD - probably brand new repo */ + giterr_clear(); + *tree = NULL; + return 0; + } + + if (git_object_lookup(&obj, repo, &head_oid, GIT_OBJ_ANY) < 0 || + git_object__resolve_to_type(&obj, GIT_OBJ_TREE) < 0) + return -1; + + *tree = (git_tree *)obj; + return 0; +} diff --git a/src/repository.h b/src/repository.h index 1ffac58f1..91c69a655 100644 --- a/src/repository.h +++ b/src/repository.h @@ -98,6 +98,8 @@ struct git_repository { * export */ void git_object__free(void *object); +int git_object__resolve_to_type(git_object **obj, git_otype type); + int git_oid__parse(git_oid *oid, const char **buffer_out, const char *buffer_end, const char *header); void git_oid__writebuf(git_buf *buf, const char *header, const git_oid *oid); @@ -106,6 +108,8 @@ GIT_INLINE(git_attr_cache *) git_repository_attr_cache(git_repository *repo) return &repo->attrcache; } +int git_repository_head_tree(git_tree **tree, git_repository *repo); + /* * Weak pointers to repository internals. * diff --git a/src/status.c b/src/status.c index 356cbeb98..ff8535c66 100644 --- a/src/status.c +++ b/src/status.c @@ -18,41 +18,6 @@ #include "git2/diff.h" #include "diff.h" -static int resolve_head_to_tree(git_tree **tree, git_repository *repo) -{ - git_oid head_oid; - git_object *obj = NULL; - - if (git_reference_name_to_oid(&head_oid, repo, GIT_HEAD_FILE) < 0) { - /* cannot resolve HEAD - probably brand new repo */ - giterr_clear(); - *tree = NULL; - return 0; - } - - if (git_object_lookup(&obj, repo, &head_oid, GIT_OBJ_ANY) < 0) - goto fail; - - switch (git_object_type(obj)) { - case GIT_OBJ_TREE: - *tree = (git_tree *)obj; - break; - case GIT_OBJ_COMMIT: - if (git_commit_tree(tree, (git_commit *)obj) < 0) - goto fail; - git_object_free(obj); - break; - default: - goto fail; - } - - return 0; - -fail: - git_object_free(obj); - return -1; -} - static unsigned int index_delta2status(git_delta_t index_status) { unsigned int st = GIT_STATUS_CURRENT; @@ -120,11 +85,8 @@ int git_status_foreach_ext( assert(show <= GIT_STATUS_SHOW_INDEX_THEN_WORKDIR); - switch (resolve_head_to_tree(&head, repo)) { - case 0: break; - case GIT_ENOTFOUND: return 0; - default: return -1; - } + if ((err = git_repository_head_tree(&head, repo)) < 0) + return err; memset(&diffopt, 0, sizeof(diffopt)); memcpy(&diffopt.pathspec, &opts->pathspec, sizeof(diffopt.pathspec)); @@ -405,7 +367,7 @@ int git_status_file( status_entry_update_from_index(e, index); /* Try to find file in HEAD */ - if ((error = resolve_head_to_tree(&tree, repo)) < 0) + if ((error = git_repository_head_tree(&tree, repo)) < 0) goto cleanup; if (tree != NULL) { diff --git a/src/strmap.h b/src/strmap.h index 55fbd7c6e..da5ca0dba 100644 --- a/src/strmap.h +++ b/src/strmap.h @@ -36,18 +36,28 @@ typedef khash_t(str) git_strmap; #define git_strmap_set_value_at(h, idx, v) kh_val(h, idx) = v #define git_strmap_delete_at(h, idx) kh_del(str, h, idx) -#define git_strmap_insert(h, key, val, err) do { \ - khiter_t __pos = kh_put(str, h, key, &err); \ - if (err >= 0) kh_val(h, __pos) = val; \ - } while (0) - -#define git_strmap_insert2(h, key, val, old, err) do { \ - khiter_t __pos = kh_put(str, h, key, &err); \ - if (err >= 0) { \ - old = (err == 0) ? kh_val(h, __pos) : NULL; \ +#define git_strmap_insert(h, key, val, rval) do { \ + khiter_t __pos = kh_put(str, h, key, &rval); \ + if (rval >= 0) { \ + if (rval == 0) kh_key(h, __pos) = key; \ kh_val(h, __pos) = val; \ } } while (0) +#define git_strmap_insert2(h, key, val, oldv, rval) do { \ + khiter_t __pos = kh_put(str, h, key, &rval); \ + if (rval >= 0) { \ + if (rval == 0) { \ + oldv = kh_val(h, __pos); \ + kh_key(h, __pos) = key; \ + } else { oldv = NULL; } \ + kh_val(h, __pos) = val; \ + } } while (0) + +#define git_strmap_delete(h, key) do { \ + khiter_t __pos = git_strmap_lookup_index(h, key); \ + if (git_strmap_valid_index(h, __pos)) \ + git_strmap_delete_at(h, __pos); } while (0) + #define git_strmap_foreach kh_foreach #define git_strmap_foreach_value kh_foreach_value diff --git a/tests-clar/attr/file.c b/tests-clar/attr/file.c index 4e1010230..d19708838 100644 --- a/tests-clar/attr/file.c +++ b/tests-clar/attr/file.c @@ -11,9 +11,9 @@ void test_attr_file__simple_read(void) git_attr_assignment *assign; git_attr_rule *rule; - cl_git_pass(git_attr_file__new(&file, NULL)); - cl_git_pass(git_attr_file__from_file(NULL, cl_fixture("attr/attr0"), file)); - cl_assert_equal_s(cl_fixture("attr/attr0"), file->path); + cl_git_pass(git_attr_file__new_and_load(&file, cl_fixture("attr/attr0"))); + + cl_assert_equal_s(cl_fixture("attr/attr0"), file->key + 2); cl_assert(file->rules.length == 1); rule = get_rule(0); @@ -37,9 +37,9 @@ void test_attr_file__match_variants(void) git_attr_rule *rule; git_attr_assignment *assign; - cl_git_pass(git_attr_file__new(&file, NULL)); - cl_git_pass(git_attr_file__from_file(NULL, cl_fixture("attr/attr1"), file)); - cl_assert_equal_s(cl_fixture("attr/attr1"), file->path); + cl_git_pass(git_attr_file__new_and_load(&file, cl_fixture("attr/attr1"))); + + cl_assert_equal_s(cl_fixture("attr/attr1"), file->key + 2); cl_assert(file->rules.length == 10); /* let's do a thorough check of this rule, then just verify @@ -123,9 +123,9 @@ void test_attr_file__assign_variants(void) git_attr_rule *rule; git_attr_assignment *assign; - cl_git_pass(git_attr_file__new(&file, NULL)); - cl_git_pass(git_attr_file__from_file(NULL, cl_fixture("attr/attr2"), file)); - cl_assert_equal_s(cl_fixture("attr/attr2"), file->path); + cl_git_pass(git_attr_file__new_and_load(&file, cl_fixture("attr/attr2"))); + + cl_assert_equal_s(cl_fixture("attr/attr2"), file->key + 2); cl_assert(file->rules.length == 11); check_one_assign(file, 0, 0, "pat0", "simple", EXPECT_TRUE, NULL); @@ -189,9 +189,8 @@ void test_attr_file__check_attr_examples(void) git_attr_rule *rule; git_attr_assignment *assign; - cl_git_pass(git_attr_file__new(&file, NULL)); - cl_git_pass(git_attr_file__from_file(NULL, cl_fixture("attr/attr3"), file)); - cl_assert_equal_s(cl_fixture("attr/attr3"), file->path); + cl_git_pass(git_attr_file__new_and_load(&file, cl_fixture("attr/attr3"))); + cl_assert_equal_s(cl_fixture("attr/attr3"), file->key + 2); cl_assert(file->rules.length == 3); rule = get_rule(0); @@ -214,7 +213,7 @@ void test_attr_file__check_attr_examples(void) cl_assert(rule->assigns.length == 1); assign = get_assign(rule, 0); cl_assert_equal_s("myAttr", assign->name); - cl_assert(assign->value == NULL); + cl_assert(GIT_ATTR_UNSPECIFIED(assign->value)); rule = get_rule(2); cl_assert_equal_s("README", rule->match.pattern); diff --git a/tests-clar/attr/flags.c b/tests-clar/attr/flags.c new file mode 100644 index 000000000..5081de8b2 --- /dev/null +++ b/tests-clar/attr/flags.c @@ -0,0 +1,108 @@ +#include "clar_libgit2.h" +#include "git2/attr.h" + +void test_attr_flags__cleanup(void) +{ + cl_git_sandbox_cleanup(); +} + +void test_attr_flags__bare(void) +{ + git_repository *repo = cl_git_sandbox_init("testrepo.git"); + const char *value; + + cl_assert(git_repository_is_bare(repo)); + + cl_git_pass(git_attr_get( + repo, GIT_ATTR_CHECK_NO_SYSTEM, "README.md", "diff", &value)); + cl_assert(GIT_ATTR_UNSPECIFIED(value)); +} + +void test_attr_flags__index_vs_workdir(void) +{ + git_repository *repo = cl_git_sandbox_init("attr_index"); + const char *value; + + cl_assert(!git_repository_is_bare(repo)); + + /* wd then index */ + cl_git_pass(git_attr_get( + repo, GIT_ATTR_CHECK_NO_SYSTEM | GIT_ATTR_CHECK_FILE_THEN_INDEX, + "README.md", "bar", &value)); + cl_assert(GIT_ATTR_FALSE(value)); + + cl_git_pass(git_attr_get( + repo, GIT_ATTR_CHECK_NO_SYSTEM | GIT_ATTR_CHECK_FILE_THEN_INDEX, + "README.md", "blargh", &value)); + cl_assert_equal_s(value, "goop"); + + cl_git_pass(git_attr_get( + repo, GIT_ATTR_CHECK_NO_SYSTEM | GIT_ATTR_CHECK_FILE_THEN_INDEX, + "README.txt", "foo", &value)); + cl_assert(GIT_ATTR_FALSE(value)); + + /* index then wd */ + cl_git_pass(git_attr_get( + repo, GIT_ATTR_CHECK_NO_SYSTEM | GIT_ATTR_CHECK_INDEX_THEN_FILE, + "README.md", "bar", &value)); + cl_assert(GIT_ATTR_TRUE(value)); + + cl_git_pass(git_attr_get( + repo, GIT_ATTR_CHECK_NO_SYSTEM | GIT_ATTR_CHECK_INDEX_THEN_FILE, + "README.md", "blargh", &value)); + cl_assert_equal_s(value, "garble"); + + cl_git_pass(git_attr_get( + repo, GIT_ATTR_CHECK_NO_SYSTEM | GIT_ATTR_CHECK_INDEX_THEN_FILE, + "README.txt", "foo", &value)); + cl_assert(GIT_ATTR_TRUE(value)); +} + +void test_attr_flags__subdir(void) +{ + git_repository *repo = cl_git_sandbox_init("attr_index"); + const char *value; + + /* wd then index */ + cl_git_pass(git_attr_get( + repo, GIT_ATTR_CHECK_NO_SYSTEM | GIT_ATTR_CHECK_FILE_THEN_INDEX, + "sub/sub/README.md", "bar", &value)); + cl_assert_equal_s(value, "1234"); + + cl_git_pass(git_attr_get( + repo, GIT_ATTR_CHECK_NO_SYSTEM | GIT_ATTR_CHECK_FILE_THEN_INDEX, + "sub/sub/README.txt", "another", &value)); + cl_assert_equal_s(value, "one"); + + cl_git_pass(git_attr_get( + repo, GIT_ATTR_CHECK_NO_SYSTEM | GIT_ATTR_CHECK_FILE_THEN_INDEX, + "sub/sub/README.txt", "again", &value)); + cl_assert(GIT_ATTR_TRUE(value)); + + cl_git_pass(git_attr_get( + repo, GIT_ATTR_CHECK_NO_SYSTEM | GIT_ATTR_CHECK_FILE_THEN_INDEX, + "sub/sub/README.txt", "beep", &value)); + cl_assert_equal_s(value, "10"); + + /* index then wd */ + cl_git_pass(git_attr_get( + repo, GIT_ATTR_CHECK_NO_SYSTEM | GIT_ATTR_CHECK_INDEX_THEN_FILE, + "sub/sub/README.md", "bar", &value)); + cl_assert_equal_s(value, "1337"); + + cl_git_pass(git_attr_get( + repo, GIT_ATTR_CHECK_NO_SYSTEM | GIT_ATTR_CHECK_INDEX_THEN_FILE, + "sub/sub/README.txt", "another", &value)); + cl_assert_equal_s(value, "one"); + + cl_git_pass(git_attr_get( + repo, GIT_ATTR_CHECK_NO_SYSTEM | GIT_ATTR_CHECK_INDEX_THEN_FILE, + "sub/sub/README.txt", "again", &value)); + cl_assert(GIT_ATTR_TRUE(value)); + + cl_git_pass(git_attr_get( + repo, GIT_ATTR_CHECK_NO_SYSTEM | GIT_ATTR_CHECK_INDEX_THEN_FILE, + "sub/sub/README.txt", "beep", &value)); + cl_assert_equal_s(value, "5"); +} + diff --git a/tests-clar/attr/lookup.c b/tests-clar/attr/lookup.c index 81a4a55d3..b2a6aac64 100644 --- a/tests-clar/attr/lookup.c +++ b/tests-clar/attr/lookup.c @@ -9,9 +9,8 @@ void test_attr_lookup__simple(void) git_attr_path path; const char *value = NULL; - cl_git_pass(git_attr_file__new(&file, NULL)); - cl_git_pass(git_attr_file__from_file(NULL, cl_fixture("attr/attr0"), file)); - cl_assert_equal_s(cl_fixture("attr/attr0"), file->path); + cl_git_pass(git_attr_file__new_and_load(&file, cl_fixture("attr/attr0"))); + cl_assert_equal_s(cl_fixture("attr/attr0"), file->key + 2); cl_assert(file->rules.length == 1); cl_git_pass(git_attr_path__init(&path, "test", NULL)); @@ -130,9 +129,8 @@ void test_attr_lookup__match_variants(void) { NULL, NULL, 0, NULL } }; - cl_git_pass(git_attr_file__new(&file, NULL)); - cl_git_pass(git_attr_file__from_file(NULL, cl_fixture("attr/attr1"), file)); - cl_assert_equal_s(cl_fixture("attr/attr1"), file->path); + cl_git_pass(git_attr_file__new_and_load(&file, cl_fixture("attr/attr1"))); + cl_assert_equal_s(cl_fixture("attr/attr1"), file->key + 2); cl_assert(file->rules.length == 10); cl_git_pass(git_attr_path__init(&path, "/testing/for/pat0", NULL)); @@ -192,8 +190,7 @@ void test_attr_lookup__assign_variants(void) { NULL, NULL, 0, NULL } }; - cl_git_pass(git_attr_file__new(&file, NULL)); - cl_git_pass(git_attr_file__from_file(NULL, cl_fixture("attr/attr2"), file)); + cl_git_pass(git_attr_file__new_and_load(&file, cl_fixture("attr/attr2"))); cl_assert(file->rules.length == 11); run_test_cases(file, cases, 0); @@ -228,8 +225,7 @@ void test_attr_lookup__check_attr_examples(void) { NULL, NULL, 0, NULL } }; - cl_git_pass(git_attr_file__new(&file, NULL)); - cl_git_pass(git_attr_file__from_file(NULL, cl_fixture("attr/attr3"), file)); + cl_git_pass(git_attr_file__new_and_load(&file, cl_fixture("attr/attr3"))); cl_assert(file->rules.length == 3); run_test_cases(file, cases, 0); @@ -254,8 +250,10 @@ void test_attr_lookup__from_buffer(void) { NULL, NULL, 0, NULL } }; - cl_git_pass(git_attr_file__new(&file, NULL)); - cl_git_pass(git_attr_file__from_buffer(NULL, "a* foo\nabc bar\n* baz", file)); + 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_assert(file->rules.length == 3); run_test_cases(file, cases, 0); diff --git a/tests-clar/attr/repo.c b/tests-clar/attr/repo.c index 7423c3045..006a49081 100644 --- a/tests-clar/attr/repo.c +++ b/tests-clar/attr/repo.c @@ -64,13 +64,13 @@ void test_attr_repo__get_one(void) for (scan = test_cases; scan->path != NULL; scan++) { const char *value; - cl_git_pass(git_attr_get(g_repo, scan->path, scan->attr, &value)); + cl_git_pass(git_attr_get(g_repo, 0, scan->path, scan->attr, &value)); attr_check_expected(scan->expected, scan->expected_str, value); } - cl_assert(git_attr_cache__is_cached(g_repo, ".git/info/attributes")); - cl_assert(git_attr_cache__is_cached(g_repo, ".gitattributes")); - cl_assert(git_attr_cache__is_cached(g_repo, "sub/.gitattributes")); + cl_assert(git_attr_cache__is_cached(g_repo, 0, ".git/info/attributes")); + cl_assert(git_attr_cache__is_cached(g_repo, 0, ".gitattributes")); + cl_assert(git_attr_cache__is_cached(g_repo, 0, "sub/.gitattributes")); } void test_attr_repo__get_many(void) @@ -78,21 +78,21 @@ void test_attr_repo__get_many(void) const char *names[4] = { "repoattr", "rootattr", "missingattr", "subattr" }; const char *values[4]; - cl_git_pass(git_attr_get_many(g_repo, "root_test1", 4, names, values)); + cl_git_pass(git_attr_get_many(g_repo, 0, "root_test1", 4, names, values)); cl_assert(GIT_ATTR_TRUE(values[0])); cl_assert(GIT_ATTR_TRUE(values[1])); cl_assert(GIT_ATTR_UNSPECIFIED(values[2])); cl_assert(GIT_ATTR_UNSPECIFIED(values[3])); - cl_git_pass(git_attr_get_many(g_repo, "root_test2", 4, names, values)); + cl_git_pass(git_attr_get_many(g_repo, 0, "root_test2", 4, names, values)); cl_assert(GIT_ATTR_TRUE(values[0])); cl_assert(GIT_ATTR_FALSE(values[1])); cl_assert(GIT_ATTR_UNSPECIFIED(values[2])); cl_assert(GIT_ATTR_UNSPECIFIED(values[3])); - cl_git_pass(git_attr_get_many(g_repo, "sub/subdir_test1", 4, names, values)); + cl_git_pass(git_attr_get_many(g_repo, 0, "sub/subdir_test1", 4, names, values)); cl_assert(GIT_ATTR_TRUE(values[0])); cl_assert(GIT_ATTR_TRUE(values[1])); @@ -118,16 +118,17 @@ void test_attr_repo__foreach(void) int count; count = 0; - cl_git_pass(git_attr_foreach(g_repo, "root_test1", &count_attrs, &count)); + cl_git_pass(git_attr_foreach( + g_repo, 0, "root_test1", &count_attrs, &count)); cl_assert(count == 2); count = 0; - cl_git_pass(git_attr_foreach(g_repo, "sub/subdir_test1", + cl_git_pass(git_attr_foreach(g_repo, 0, "sub/subdir_test1", &count_attrs, &count)); cl_assert(count == 4); /* repoattr, rootattr, subattr, negattr */ count = 0; - cl_git_pass(git_attr_foreach(g_repo, "sub/subdir_test2.txt", + cl_git_pass(git_attr_foreach(g_repo, 0, "sub/subdir_test2.txt", &count_attrs, &count)); cl_assert(count == 6); /* repoattr, rootattr, subattr, reposub, negattr, another */ } @@ -136,19 +137,19 @@ void test_attr_repo__manpage_example(void) { const char *value; - cl_git_pass(git_attr_get(g_repo, "sub/abc", "foo", &value)); + cl_git_pass(git_attr_get(g_repo, 0, "sub/abc", "foo", &value)); cl_assert(GIT_ATTR_TRUE(value)); - cl_git_pass(git_attr_get(g_repo, "sub/abc", "bar", &value)); + cl_git_pass(git_attr_get(g_repo, 0, "sub/abc", "bar", &value)); cl_assert(GIT_ATTR_UNSPECIFIED(value)); - cl_git_pass(git_attr_get(g_repo, "sub/abc", "baz", &value)); + cl_git_pass(git_attr_get(g_repo, 0, "sub/abc", "baz", &value)); cl_assert(GIT_ATTR_FALSE(value)); - cl_git_pass(git_attr_get(g_repo, "sub/abc", "merge", &value)); + cl_git_pass(git_attr_get(g_repo, 0, "sub/abc", "merge", &value)); cl_assert_equal_s("filfre", value); - cl_git_pass(git_attr_get(g_repo, "sub/abc", "frotz", &value)); + cl_git_pass(git_attr_get(g_repo, 0, "sub/abc", "frotz", &value)); cl_assert(GIT_ATTR_UNSPECIFIED(value)); } @@ -159,7 +160,7 @@ void test_attr_repo__macros(void) const char *names3[3] = { "macro2", "multi2", "multi3" }; const char *values[5]; - cl_git_pass(git_attr_get_many(g_repo, "binfile", 5, names, values)); + cl_git_pass(git_attr_get_many(g_repo, 0, "binfile", 5, names, values)); cl_assert(GIT_ATTR_TRUE(values[0])); cl_assert(GIT_ATTR_TRUE(values[1])); @@ -167,7 +168,7 @@ void test_attr_repo__macros(void) cl_assert(GIT_ATTR_FALSE(values[3])); cl_assert(GIT_ATTR_UNSPECIFIED(values[4])); - cl_git_pass(git_attr_get_many(g_repo, "macro_test", 5, names2, values)); + cl_git_pass(git_attr_get_many(g_repo, 0, "macro_test", 5, names2, values)); cl_assert(GIT_ATTR_TRUE(values[0])); cl_assert(GIT_ATTR_TRUE(values[1])); @@ -175,7 +176,7 @@ void test_attr_repo__macros(void) cl_assert(GIT_ATTR_UNSPECIFIED(values[3])); cl_assert_equal_s("77", values[4]); - cl_git_pass(git_attr_get_many(g_repo, "macro_test", 3, names3, values)); + cl_git_pass(git_attr_get_many(g_repo, 0, "macro_test", 3, names3, values)); cl_assert(GIT_ATTR_TRUE(values[0])); cl_assert(GIT_ATTR_FALSE(values[1])); @@ -188,7 +189,7 @@ void test_attr_repo__bad_macros(void) "firstmacro", "secondmacro", "thirdmacro" }; const char *values[6]; - cl_git_pass(git_attr_get_many(g_repo, "macro_bad", 6, names, values)); + cl_git_pass(git_attr_get_many(g_repo, 0, "macro_bad", 6, names, values)); /* these three just confirm that the "mymacro" rule ran */ cl_assert(GIT_ATTR_UNSPECIFIED(values[0])); diff --git a/tests-clar/diff/tree.c b/tests-clar/diff/tree.c index 1e269ae42..06f51a16b 100644 --- a/tests-clar/diff/tree.c +++ b/tests-clar/diff/tree.c @@ -5,7 +5,6 @@ static git_repository *g_repo = NULL; void test_diff_tree__initialize(void) { - g_repo = cl_git_sandbox_init("attr"); } void test_diff_tree__cleanup(void) @@ -19,15 +18,16 @@ void test_diff_tree__0(void) const char *a_commit = "605812a"; const char *b_commit = "370fe9ec22"; const char *c_commit = "f5b0af1fb4f5c"; - git_tree *a = resolve_commit_oid_to_tree(g_repo, a_commit); - git_tree *b = resolve_commit_oid_to_tree(g_repo, b_commit); - git_tree *c = resolve_commit_oid_to_tree(g_repo, c_commit); + git_tree *a, *b, *c; git_diff_options opts = {0}; git_diff_list *diff = NULL; diff_expects exp; - cl_assert(a); - cl_assert(b); + g_repo = cl_git_sandbox_init("attr"); + + cl_assert((a = resolve_commit_oid_to_tree(g_repo, a_commit)) != NULL); + cl_assert((b = resolve_commit_oid_to_tree(g_repo, b_commit)) != NULL); + cl_assert((c = resolve_commit_oid_to_tree(g_repo, c_commit)) != NULL); opts.context_lines = 1; opts.interhunk_lines = 1; @@ -87,12 +87,7 @@ void test_diff_tree__options(void) const char *b_commit = "605812ab7fe421fdd"; const char *c_commit = "f5b0af1fb4f5"; const char *d_commit = "a97cc019851"; - - git_tree *a = resolve_commit_oid_to_tree(g_repo, a_commit); - git_tree *b = resolve_commit_oid_to_tree(g_repo, b_commit); - git_tree *c = resolve_commit_oid_to_tree(g_repo, c_commit); - git_tree *d = resolve_commit_oid_to_tree(g_repo, d_commit); - + git_tree *a, *b, *c, *d; git_diff_options opts = {0}; git_diff_list *diff = NULL; diff_expects actual; @@ -133,8 +128,12 @@ void test_diff_tree__options(void) diff_expects *expected; int i; - cl_assert(a); - cl_assert(b); + g_repo = cl_git_sandbox_init("attr"); + + cl_assert((a = resolve_commit_oid_to_tree(g_repo, a_commit)) != NULL); + cl_assert((b = resolve_commit_oid_to_tree(g_repo, b_commit)) != NULL); + cl_assert((c = resolve_commit_oid_to_tree(g_repo, c_commit)) != NULL); + cl_assert((d = resolve_commit_oid_to_tree(g_repo, d_commit)) != NULL); for (i = 0; test_expects[i].files > 0; i++) { memset(&actual, 0, sizeof(actual)); /* clear accumulator */ @@ -168,3 +167,44 @@ void test_diff_tree__options(void) git_tree_free(c); git_tree_free(d); } + +void test_diff_tree__bare(void) +{ + const char *a_commit = "8496071c1b46c85"; + const char *b_commit = "be3563ae3f79"; + git_tree *a, *b; + git_diff_options opts = {0}; + git_diff_list *diff = NULL; + diff_expects exp; + + g_repo = cl_git_sandbox_init("testrepo.git"); + + cl_assert((a = resolve_commit_oid_to_tree(g_repo, a_commit)) != NULL); + cl_assert((b = resolve_commit_oid_to_tree(g_repo, b_commit)) != NULL); + + opts.context_lines = 1; + opts.interhunk_lines = 1; + + memset(&exp, 0, sizeof(exp)); + + cl_git_pass(git_diff_tree_to_tree(g_repo, &opts, a, b, &diff)); + + cl_git_pass(git_diff_foreach( + diff, &exp, diff_file_fn, diff_hunk_fn, diff_line_fn)); + + cl_assert(exp.files == 3); + cl_assert(exp.file_adds == 2); + cl_assert(exp.file_dels == 0); + cl_assert(exp.file_mods == 1); + + cl_assert(exp.hunks == 3); + + cl_assert(exp.lines == 4); + cl_assert(exp.line_ctxt == 0); + cl_assert(exp.line_adds == 3); + cl_assert(exp.line_dels == 1); + + git_diff_list_free(diff); + git_tree_free(a); + git_tree_free(b); +} diff --git a/tests-clar/resources/attr_index/.gitted/HEAD b/tests-clar/resources/attr_index/.gitted/HEAD new file mode 100644 index 000000000..cb089cd89 --- /dev/null +++ b/tests-clar/resources/attr_index/.gitted/HEAD @@ -0,0 +1 @@ +ref: refs/heads/master diff --git a/tests-clar/resources/attr_index/.gitted/config b/tests-clar/resources/attr_index/.gitted/config new file mode 100644 index 000000000..af107929f --- /dev/null +++ b/tests-clar/resources/attr_index/.gitted/config @@ -0,0 +1,6 @@ +[core] + repositoryformatversion = 0 + filemode = true + bare = false + logallrefupdates = true + ignorecase = true diff --git a/tests-clar/resources/attr_index/.gitted/description b/tests-clar/resources/attr_index/.gitted/description new file mode 100644 index 000000000..498b267a8 --- /dev/null +++ b/tests-clar/resources/attr_index/.gitted/description @@ -0,0 +1 @@ +Unnamed repository; edit this file 'description' to name the repository. diff --git a/tests-clar/resources/attr_index/.gitted/index b/tests-clar/resources/attr_index/.gitted/index Binary files differnew file mode 100644 index 000000000..d87480332 --- /dev/null +++ b/tests-clar/resources/attr_index/.gitted/index diff --git a/tests-clar/resources/attr_index/.gitted/info/exclude b/tests-clar/resources/attr_index/.gitted/info/exclude new file mode 100644 index 000000000..a5196d1be --- /dev/null +++ b/tests-clar/resources/attr_index/.gitted/info/exclude @@ -0,0 +1,6 @@ +# git ls-files --others --exclude-from=.git/info/exclude +# Lines that start with '#' are comments. +# For a project mostly in C, the following would be a good set of +# exclude patterns (uncomment them if you want to use them): +# *.[oa] +# *~ diff --git a/tests-clar/resources/attr_index/.gitted/info/refs b/tests-clar/resources/attr_index/.gitted/info/refs new file mode 100644 index 000000000..60feca293 --- /dev/null +++ b/tests-clar/resources/attr_index/.gitted/info/refs @@ -0,0 +1 @@ +58f7cf825b553ef7c26e5b9f8a23599c1a9ca296 refs/heads/master diff --git a/tests-clar/resources/attr_index/.gitted/logs/HEAD b/tests-clar/resources/attr_index/.gitted/logs/HEAD new file mode 100644 index 000000000..ffd298c04 --- /dev/null +++ b/tests-clar/resources/attr_index/.gitted/logs/HEAD @@ -0,0 +1,4 @@ +0000000000000000000000000000000000000000 67c1640e91ccbaf0793591be09bf572cf40c9a53 Russell Belfer <rb@github.com> 1335817070 -0700 commit (initial): Initial commit +67c1640e91ccbaf0793591be09bf572cf40c9a53 d441d7d88f52c28c2b23940ce4c33756748425f9 Russell Belfer <rb@github.com> 1335817296 -0700 commit: Adding some files in subtrees +d441d7d88f52c28c2b23940ce4c33756748425f9 67c1640e91ccbaf0793591be09bf572cf40c9a53 Russell Belfer <rb@github.com> 1335817353 -0700 HEAD^: updating HEAD +67c1640e91ccbaf0793591be09bf572cf40c9a53 58f7cf825b553ef7c26e5b9f8a23599c1a9ca296 Russell Belfer <rb@github.com> 1335817372 -0700 commit: Adding subtree data diff --git a/tests-clar/resources/attr_index/.gitted/logs/refs/heads/master b/tests-clar/resources/attr_index/.gitted/logs/refs/heads/master new file mode 100644 index 000000000..ffd298c04 --- /dev/null +++ b/tests-clar/resources/attr_index/.gitted/logs/refs/heads/master @@ -0,0 +1,4 @@ +0000000000000000000000000000000000000000 67c1640e91ccbaf0793591be09bf572cf40c9a53 Russell Belfer <rb@github.com> 1335817070 -0700 commit (initial): Initial commit +67c1640e91ccbaf0793591be09bf572cf40c9a53 d441d7d88f52c28c2b23940ce4c33756748425f9 Russell Belfer <rb@github.com> 1335817296 -0700 commit: Adding some files in subtrees +d441d7d88f52c28c2b23940ce4c33756748425f9 67c1640e91ccbaf0793591be09bf572cf40c9a53 Russell Belfer <rb@github.com> 1335817353 -0700 HEAD^: updating HEAD +67c1640e91ccbaf0793591be09bf572cf40c9a53 58f7cf825b553ef7c26e5b9f8a23599c1a9ca296 Russell Belfer <rb@github.com> 1335817372 -0700 commit: Adding subtree data diff --git a/tests-clar/resources/attr_index/.gitted/objects/38/12cfef36615db1788d4e63f90028007e17a348 b/tests-clar/resources/attr_index/.gitted/objects/38/12cfef36615db1788d4e63f90028007e17a348 new file mode 100644 index 000000000..ee2991571 --- /dev/null +++ b/tests-clar/resources/attr_index/.gitted/objects/38/12cfef36615db1788d4e63f90028007e17a348 @@ -0,0 +1,3 @@ +x[ + E*@PJ +]&`w'oMKDq45DF#!!=VZD.L:%L}!dCg*qв-LUkz~6閷W}}>g˾{f%G
\ No newline at end of file diff --git a/tests-clar/resources/attr_index/.gitted/objects/59/d942b8be2784bc96db9b22202c10815c9a077b b/tests-clar/resources/attr_index/.gitted/objects/59/d942b8be2784bc96db9b22202c10815c9a077b new file mode 100644 index 000000000..ff33737db --- /dev/null +++ b/tests-clar/resources/attr_index/.gitted/objects/59/d942b8be2784bc96db9b22202c10815c9a077b @@ -0,0 +1 @@ +x
0@@kR@]<K4nY)l(ahFHcc^
\ No newline at end of file diff --git a/tests-clar/resources/attr_index/.gitted/objects/cd/f17ea3fe625ef812f4dce7f423f4f299287505 b/tests-clar/resources/attr_index/.gitted/objects/cd/f17ea3fe625ef812f4dce7f423f4f299287505 Binary files differnew file mode 100644 index 000000000..2a410057e --- /dev/null +++ b/tests-clar/resources/attr_index/.gitted/objects/cd/f17ea3fe625ef812f4dce7f423f4f299287505 diff --git a/tests-clar/resources/attr_index/.gitted/objects/f7/2502ddd01412bb20796ff812af56fd53b82b52 b/tests-clar/resources/attr_index/.gitted/objects/f7/2502ddd01412bb20796ff812af56fd53b82b52 Binary files differnew file mode 100644 index 000000000..048928000 --- /dev/null +++ b/tests-clar/resources/attr_index/.gitted/objects/f7/2502ddd01412bb20796ff812af56fd53b82b52 diff --git a/tests-clar/resources/attr_index/.gitted/objects/info/packs b/tests-clar/resources/attr_index/.gitted/objects/info/packs new file mode 100644 index 000000000..559dc741c --- /dev/null +++ b/tests-clar/resources/attr_index/.gitted/objects/info/packs @@ -0,0 +1,2 @@ +P pack-4e6438607204ce78827e3885594b2c0bb4f13895.pack + diff --git a/tests-clar/resources/attr_index/.gitted/objects/pack/pack-4e6438607204ce78827e3885594b2c0bb4f13895.idx b/tests-clar/resources/attr_index/.gitted/objects/pack/pack-4e6438607204ce78827e3885594b2c0bb4f13895.idx Binary files differnew file mode 100644 index 000000000..fbef4aa1d --- /dev/null +++ b/tests-clar/resources/attr_index/.gitted/objects/pack/pack-4e6438607204ce78827e3885594b2c0bb4f13895.idx diff --git a/tests-clar/resources/attr_index/.gitted/objects/pack/pack-4e6438607204ce78827e3885594b2c0bb4f13895.pack b/tests-clar/resources/attr_index/.gitted/objects/pack/pack-4e6438607204ce78827e3885594b2c0bb4f13895.pack Binary files differnew file mode 100644 index 000000000..09c9e06d9 --- /dev/null +++ b/tests-clar/resources/attr_index/.gitted/objects/pack/pack-4e6438607204ce78827e3885594b2c0bb4f13895.pack diff --git a/tests-clar/resources/attr_index/.gitted/packed-refs b/tests-clar/resources/attr_index/.gitted/packed-refs new file mode 100644 index 000000000..6b3e4decf --- /dev/null +++ b/tests-clar/resources/attr_index/.gitted/packed-refs @@ -0,0 +1,2 @@ +# pack-refs with: peeled +58f7cf825b553ef7c26e5b9f8a23599c1a9ca296 refs/heads/master diff --git a/tests-clar/resources/attr_index/.gitted/refs/heads/master b/tests-clar/resources/attr_index/.gitted/refs/heads/master new file mode 100644 index 000000000..9b7562931 --- /dev/null +++ b/tests-clar/resources/attr_index/.gitted/refs/heads/master @@ -0,0 +1 @@ +3812cfef36615db1788d4e63f90028007e17a348 diff --git a/tests-clar/resources/attr_index/README.md b/tests-clar/resources/attr_index/README.md new file mode 100644 index 000000000..59d942b8b --- /dev/null +++ b/tests-clar/resources/attr_index/README.md @@ -0,0 +1 @@ +This is contains tests for when the index and work dir differ diff --git a/tests-clar/resources/attr_index/README.txt b/tests-clar/resources/attr_index/README.txt new file mode 100644 index 000000000..874c12b79 --- /dev/null +++ b/tests-clar/resources/attr_index/README.txt @@ -0,0 +1 @@ +This contains files for testing when the index and the workdir differ diff --git a/tests-clar/resources/attr_index/gitattributes b/tests-clar/resources/attr_index/gitattributes new file mode 100644 index 000000000..cdf17ea3f --- /dev/null +++ b/tests-clar/resources/attr_index/gitattributes @@ -0,0 +1,4 @@ +* bar +*.txt -foo beep=10 +*.md blargh=goop -bar + diff --git a/tests-clar/resources/attr_index/sub/sub/.gitattributes b/tests-clar/resources/attr_index/sub/sub/.gitattributes new file mode 100644 index 000000000..060c9a261 --- /dev/null +++ b/tests-clar/resources/attr_index/sub/sub/.gitattributes @@ -0,0 +1,3 @@ +*.txt another=one again +*.md bar=1234 + diff --git a/tests-clar/resources/attr_index/sub/sub/README.md b/tests-clar/resources/attr_index/sub/sub/README.md new file mode 100644 index 000000000..59652e349 --- /dev/null +++ b/tests-clar/resources/attr_index/sub/sub/README.md @@ -0,0 +1 @@ +More testing diff --git a/tests-clar/resources/attr_index/sub/sub/README.txt b/tests-clar/resources/attr_index/sub/sub/README.txt new file mode 100644 index 000000000..59652e349 --- /dev/null +++ b/tests-clar/resources/attr_index/sub/sub/README.txt @@ -0,0 +1 @@ +More testing diff --git a/tests-clar/status/ignore.c b/tests-clar/status/ignore.c index 94f8c3de3..e92d6a577 100644 --- a/tests-clar/status/ignore.c +++ b/tests-clar/status/ignore.c @@ -47,8 +47,8 @@ void test_status_ignore__0(void) } /* confirm that ignore files were cached */ - cl_assert(git_attr_cache__is_cached(g_repo, ".git/info/exclude")); - cl_assert(git_attr_cache__is_cached(g_repo, ".gitignore")); + cl_assert(git_attr_cache__is_cached(g_repo, 0, ".git/info/exclude")); + cl_assert(git_attr_cache__is_cached(g_repo, 0, ".gitignore")); } |