mirror of
https://git.proxmox.com/git/libgit2
synced 2025-11-05 03:42:16 +00:00
Merge pull request #664 from arrbee/attrs-from-index
Support git attrs from index (and bare repo)
This commit is contained in:
commit
4ef14af935
1
AUTHORS
1
AUTHORS
@ -43,6 +43,7 @@ Ramsay Jones
|
|||||||
Robert G. Jakabosky
|
Robert G. Jakabosky
|
||||||
Romain Geissler
|
Romain Geissler
|
||||||
Romain Muller
|
Romain Muller
|
||||||
|
Russell Belfer
|
||||||
Sakari Jokinen
|
Sakari Jokinen
|
||||||
Sam
|
Sam
|
||||||
Sarath Lakshman
|
Sarath Lakshman
|
||||||
|
|||||||
@ -19,42 +19,186 @@
|
|||||||
*/
|
*/
|
||||||
GIT_BEGIN_DECL
|
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)
|
#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_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__true;
|
||||||
GIT_EXTERN(const char *) git_attr__false;
|
GIT_EXTERN(const char *) git_attr__false;
|
||||||
|
GIT_EXTERN(const char *) git_attr__unset;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Lookup attribute for path returning string caller must free
|
* 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)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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_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);
|
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_EXTERN(int) git_attr_get_many(
|
||||||
git_repository *repo, const char *path,
|
git_repository *repo,
|
||||||
size_t num_attr, const char **names,
|
uint32_t flags,
|
||||||
|
const char *path,
|
||||||
|
size_t num_attr,
|
||||||
|
const char **names,
|
||||||
const char **values);
|
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_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),
|
int (*callback)(const char *name, const char *value, void *payload),
|
||||||
void *payload);
|
void *payload);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Flush the gitattributes cache.
|
* Flush the gitattributes cache.
|
||||||
*
|
*
|
||||||
* Call this if you have reason to believe that the attributes files
|
* Call this if you have reason to believe that the attributes files on
|
||||||
* on disk no longer match the cached contents of memory.
|
* 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_EXTERN(void) git_attr_cache_flush(
|
||||||
git_repository *repo);
|
git_repository *repo);
|
||||||
@ -62,7 +206,7 @@ GIT_EXTERN(void) git_attr_cache_flush(
|
|||||||
/**
|
/**
|
||||||
* Add a macro definition.
|
* 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
|
* file of the repository (plus the build-in "binary" macro). This
|
||||||
* function allows you to add others. For example, to add the default
|
* function allows you to add others. For example, to add the default
|
||||||
* macro, you would call:
|
* macro, you would call:
|
||||||
|
|||||||
307
src/attr.c
307
src/attr.c
@ -6,12 +6,18 @@
|
|||||||
GIT__USE_STRMAP;
|
GIT__USE_STRMAP;
|
||||||
|
|
||||||
static int collect_attr_files(
|
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(
|
int git_attr_get(
|
||||||
git_repository *repo, const char *pathname,
|
git_repository *repo,
|
||||||
const char *name, const char **value)
|
uint32_t flags,
|
||||||
|
const char *pathname,
|
||||||
|
const char *name,
|
||||||
|
const char **value)
|
||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
git_attr_path path;
|
git_attr_path path;
|
||||||
@ -26,7 +32,7 @@ int git_attr_get(
|
|||||||
if (git_attr_path__init(&path, pathname, git_repository_workdir(repo)) < 0)
|
if (git_attr_path__init(&path, pathname, git_repository_workdir(repo)) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if ((error = collect_attr_files(repo, pathname, &files)) < 0)
|
if ((error = collect_attr_files(repo, flags, pathname, &files)) < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
attr.name = name;
|
attr.name = name;
|
||||||
@ -58,8 +64,12 @@ typedef struct {
|
|||||||
} attr_get_many_info;
|
} attr_get_many_info;
|
||||||
|
|
||||||
int git_attr_get_many(
|
int git_attr_get_many(
|
||||||
git_repository *repo, const char *pathname,
|
git_repository *repo,
|
||||||
size_t num_attr, const char **names, const char **values)
|
uint32_t flags,
|
||||||
|
const char *pathname,
|
||||||
|
size_t num_attr,
|
||||||
|
const char **names,
|
||||||
|
const char **values)
|
||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
git_attr_path path;
|
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)
|
if (git_attr_path__init(&path, pathname, git_repository_workdir(repo)) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if ((error = collect_attr_files(repo, pathname, &files)) < 0)
|
if ((error = collect_attr_files(repo, flags, pathname, &files)) < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
info = git__calloc(num_attr, sizeof(attr_get_many_info));
|
info = git__calloc(num_attr, sizeof(attr_get_many_info));
|
||||||
@ -119,7 +129,9 @@ cleanup:
|
|||||||
|
|
||||||
|
|
||||||
int git_attr_foreach(
|
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),
|
int (*callback)(const char *name, const char *value, void *payload),
|
||||||
void *payload)
|
void *payload)
|
||||||
{
|
{
|
||||||
@ -135,7 +147,7 @@ int git_attr_foreach(
|
|||||||
if (git_attr_path__init(&path, pathname, git_repository_workdir(repo)) < 0)
|
if (git_attr_path__init(&path, pathname, git_repository_workdir(repo)) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if ((error = collect_attr_files(repo, pathname, &files)) < 0)
|
if ((error = collect_attr_files(repo, flags, pathname, &files)) < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
seen = git_strmap_alloc();
|
seen = git_strmap_alloc();
|
||||||
@ -203,113 +215,231 @@ int git_attr_add_macro(
|
|||||||
return error;
|
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;
|
git_strmap *files = git_repository_attr_cache(repo)->files;
|
||||||
|
const char *workdir = git_repository_workdir(repo);
|
||||||
|
bool rval;
|
||||||
|
|
||||||
if (repo && git__prefixcmp(cache_key, git_repository_workdir(repo)) == 0)
|
if (workdir && git__prefixcmp(path, workdir) == 0)
|
||||||
cache_key += strlen(git_repository_workdir(repo));
|
path += strlen(workdir);
|
||||||
|
if (git_buf_printf(&cache_key, "%d#%s", (int)source, path) < 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
return git_strmap_exists(files, cache_key);
|
rval = git_strmap_exists(files, git_buf_cstr(&cache_key));
|
||||||
|
|
||||||
|
git_buf_free(&cache_key);
|
||||||
|
|
||||||
|
return rval;
|
||||||
}
|
}
|
||||||
|
|
||||||
int git_attr_cache__lookup_or_create_file(
|
static int load_attr_file(const char *filename, const char **data)
|
||||||
git_repository *repo,
|
|
||||||
const char *key,
|
|
||||||
const char *filename,
|
|
||||||
int (*loader)(git_repository *, const char *, git_attr_file *),
|
|
||||||
git_attr_file **file_ptr)
|
|
||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
git_attr_cache *cache = git_repository_attr_cache(repo);
|
git_buf content = GIT_BUF_INIT;
|
||||||
git_attr_file *file = NULL;
|
|
||||||
khiter_t pos;
|
|
||||||
|
|
||||||
pos = git_strmap_lookup_index(cache->files, key);
|
error = git_futils_readbuffer(&content, filename);
|
||||||
if (git_strmap_valid_index(cache->files, pos)) {
|
*data = error ? NULL : git_buf_detach(&content);
|
||||||
*file_ptr = git_strmap_value_at(cache->files, pos);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (loader && git_path_exists(filename) == false) {
|
|
||||||
*file_ptr = NULL;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (git_attr_file__new(&file, &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;
|
|
||||||
}
|
|
||||||
|
|
||||||
*file_ptr = file;
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* add git_attr_file to vector of files, loading if needed */
|
static int load_attr_blob_from_index(
|
||||||
int git_attr_cache__push_file(
|
git_repository *repo, const char *filename, git_blob **blob)
|
||||||
git_repository *repo,
|
|
||||||
git_vector *stack,
|
|
||||||
const char *base,
|
|
||||||
const char *filename,
|
|
||||||
int (*loader)(git_repository *, const char *, git_attr_file *))
|
|
||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
git_buf path = GIT_BUF_INIT;
|
git_index *index;
|
||||||
git_attr_file *file = NULL;
|
git_index_entry *entry;
|
||||||
const char *cache_key;
|
|
||||||
|
|
||||||
if (base != NULL) {
|
if ((error = git_repository_index__weakptr(&index, repo)) < 0 ||
|
||||||
|
(error = git_index_find(index, filename)) < 0)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
entry = git_index_get(index, error);
|
||||||
|
|
||||||
|
return git_blob_lookup(blob, repo, &entry->oid);
|
||||||
|
}
|
||||||
|
|
||||||
|
int git_attr_cache__internal_file(
|
||||||
|
git_repository *repo,
|
||||||
|
const char *filename,
|
||||||
|
git_attr_file **file)
|
||||||
|
{
|
||||||
|
int error = 0;
|
||||||
|
git_attr_cache *cache = git_repository_attr_cache(repo);
|
||||||
|
khiter_t cache_pos = git_strmap_lookup_index(cache->files, filename);
|
||||||
|
|
||||||
|
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, 0, filename, &cache->pool) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
git_strmap_insert(cache->files, (*file)->key + 2, *file, error);
|
||||||
|
if (error > 0)
|
||||||
|
error = 0;
|
||||||
|
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
int git_attr_cache__push_file(
|
||||||
|
git_repository *repo,
|
||||||
|
const char *base,
|
||||||
|
const char *filename,
|
||||||
|
git_attr_file_source source,
|
||||||
|
git_attr_file_parser parse,
|
||||||
|
git_vector *stack)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
git_blob *blob = 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)
|
if (git_buf_joinpath(&path, base, filename) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
filename = path.ptr;
|
filename = path.ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* either get attr_file from cache or read from disk */
|
relfile = filename;
|
||||||
cache_key = filename;
|
if (workdir && git__prefixcmp(relfile, workdir) == 0)
|
||||||
if (repo && git__prefixcmp(cache_key, git_repository_workdir(repo)) == 0)
|
relfile += strlen(workdir);
|
||||||
cache_key += strlen(git_repository_workdir(repo));
|
|
||||||
|
|
||||||
error = git_attr_cache__lookup_or_create_file(
|
/* check cache */
|
||||||
repo, cache_key, filename, loader, &file);
|
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);
|
||||||
|
|
||||||
|
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)
|
if (!error && file != NULL)
|
||||||
error = git_vector_insert(stack, file);
|
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);
|
git_buf_free(&path);
|
||||||
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define push_attrs(R,S,B,F) \
|
#define push_attr_file(R,S,B,F) \
|
||||||
git_attr_cache__push_file((R),(S),(B),(F),git_attr_file__from_file)
|
git_attr_cache__push_file((R),(B),(F),GIT_ATTR_FILE_FROM_FILE,git_attr_file__parse_buffer,(S))
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
git_repository *repo;
|
git_repository *repo;
|
||||||
|
uint32_t flags;
|
||||||
|
const char *workdir;
|
||||||
|
git_index *index;
|
||||||
git_vector *files;
|
git_vector *files;
|
||||||
} attr_walk_up_info;
|
} 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)
|
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;
|
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(
|
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;
|
int error;
|
||||||
git_buf dir = GIT_BUF_INIT;
|
git_buf dir = GIT_BUF_INIT;
|
||||||
@ -320,7 +450,11 @@ static int collect_attr_files(
|
|||||||
git_vector_init(files, 4, NULL) < 0)
|
git_vector_init(files, 4, NULL) < 0)
|
||||||
return -1;
|
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)
|
if (error < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
@ -331,29 +465,36 @@ static int collect_attr_files(
|
|||||||
* - $GIT_PREFIX/etc/gitattributes
|
* - $GIT_PREFIX/etc/gitattributes
|
||||||
*/
|
*/
|
||||||
|
|
||||||
error = push_attrs(
|
error = push_attr_file(
|
||||||
repo, files, git_repository_path(repo), GIT_ATTR_FILE_INREPO);
|
repo, files, git_repository_path(repo), GIT_ATTR_FILE_INREPO);
|
||||||
if (error < 0)
|
if (error < 0)
|
||||||
goto cleanup;
|
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;
|
info.files = files;
|
||||||
|
|
||||||
error = git_path_walk_up(&dir, workdir, push_one_attr, &info);
|
error = git_path_walk_up(&dir, workdir, push_one_attr, &info);
|
||||||
if (error < 0)
|
if (error < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
if (git_repository_attr_cache(repo)->cfg_attr_file != NULL) {
|
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);
|
repo, files, NULL, git_repository_attr_cache(repo)->cfg_attr_file);
|
||||||
if (error < 0)
|
if (error < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
error = git_futils_find_system_file(&dir, GIT_ATTR_FILE_SYSTEM);
|
if ((flags & GIT_ATTR_CHECK_NO_SYSTEM) == 0) {
|
||||||
if (!error)
|
error = git_futils_find_system_file(&dir, GIT_ATTR_FILE_SYSTEM);
|
||||||
error = push_attrs(repo, files, NULL, dir.ptr);
|
if (!error)
|
||||||
else if (error == GIT_ENOTFOUND)
|
error = push_attr_file(repo, files, NULL, dir.ptr);
|
||||||
error = 0;
|
else if (error == GIT_ENOTFOUND)
|
||||||
|
error = 0;
|
||||||
|
}
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
if (error < 0)
|
if (error < 0)
|
||||||
|
|||||||
30
src/attr.h
30
src/attr.h
@ -22,6 +22,9 @@ typedef struct {
|
|||||||
const char *cfg_excl_file; /* cached value of core.excludesfile */
|
const char *cfg_excl_file; /* cached value of core.excludesfile */
|
||||||
} git_attr_cache;
|
} 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__init(git_repository *repo);
|
||||||
|
|
||||||
extern int git_attr_cache__insert_macro(
|
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(
|
extern git_attr_rule *git_attr_cache__lookup_macro(
|
||||||
git_repository *repo, const char *name);
|
git_repository *repo, const char *name);
|
||||||
|
|
||||||
extern int git_attr_cache__lookup_or_create_file(
|
|
||||||
git_repository *repo,
|
|
||||||
const char *key,
|
|
||||||
const char *filename,
|
|
||||||
int (*loader)(git_repository *, const char *, git_attr_file *),
|
|
||||||
git_attr_file **file_ptr);
|
|
||||||
|
|
||||||
extern int git_attr_cache__push_file(
|
extern int git_attr_cache__push_file(
|
||||||
git_repository *repo,
|
git_repository *repo,
|
||||||
git_vector *stack,
|
const char *base,
|
||||||
const char *base,
|
const char *filename,
|
||||||
const char *filename,
|
git_attr_file_source source,
|
||||||
int (*loader)(git_repository *, const char *, git_attr_file *));
|
git_attr_file_parser parse,
|
||||||
|
git_vector *stack);
|
||||||
|
|
||||||
|
extern int git_attr_cache__internal_file(
|
||||||
|
git_repository *repo,
|
||||||
|
const char *key,
|
||||||
|
git_attr_file **file_ptr);
|
||||||
|
|
||||||
/* returns true if path is in cache */
|
/* 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
|
#endif
|
||||||
|
|||||||
@ -1,15 +1,22 @@
|
|||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "repository.h"
|
#include "repository.h"
|
||||||
#include "filebuf.h"
|
#include "filebuf.h"
|
||||||
|
#include "git2/blob.h"
|
||||||
|
#include "git2/tree.h"
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
|
||||||
const char *git_attr__true = "[internal]__TRUE__";
|
const char *git_attr__true = "[internal]__TRUE__";
|
||||||
const char *git_attr__false = "[internal]__FALSE__";
|
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 int sort_by_hash_and_name(const void *a_raw, const void *b_raw);
|
||||||
static void git_attr_rule__clear(git_attr_rule *rule);
|
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;
|
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;
|
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)
|
if (git_vector_init(&attrs->rules, 4, NULL) < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
@ -37,31 +56,7 @@ fail:
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int git_attr_file__set_path(
|
int git_attr_file__parse_buffer(
|
||||||
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(
|
|
||||||
git_repository *repo, const char *buffer, git_attr_file *attrs)
|
git_repository *repo, const char *buffer, git_attr_file *attrs)
|
||||||
{
|
{
|
||||||
int error = 0;
|
int error = 0;
|
||||||
@ -73,10 +68,10 @@ int git_attr_file__from_buffer(
|
|||||||
|
|
||||||
scan = buffer;
|
scan = buffer;
|
||||||
|
|
||||||
if (attrs->path && git__suffixcmp(attrs->path, GIT_ATTR_FILE) == 0) {
|
/* if subdir file path, convert context for file paths */
|
||||||
context = git__strndup(attrs->path,
|
if (attrs->key && git__suffixcmp(attrs->key, "/" GIT_ATTR_FILE) == 0) {
|
||||||
strlen(attrs->path) - strlen(GIT_ATTR_FILE));
|
context = attrs->key + 2;
|
||||||
GITERR_CHECK_ALLOC(context);
|
context[strlen(context) - strlen(GIT_ATTR_FILE)] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
while (!error && *scan) {
|
while (!error && *scan) {
|
||||||
@ -112,28 +107,34 @@ int git_attr_file__from_buffer(
|
|||||||
}
|
}
|
||||||
|
|
||||||
git_attr_rule__free(rule);
|
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;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
int git_attr_file__from_file(
|
int git_attr_file__new_and_load(
|
||||||
git_repository *repo, const char *path, git_attr_file *file)
|
git_attr_file **attrs_ptr,
|
||||||
|
const char *path)
|
||||||
{
|
{
|
||||||
int error;
|
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)
|
if (!(error = git_futils_readbuffer(&content, path)))
|
||||||
return -1;
|
error = git_attr_file__parse_buffer(
|
||||||
|
NULL, git_buf_cstr(&content), *attrs_ptr);
|
||||||
|
|
||||||
if (git_futils_readbuffer(&fbuf, path) < 0)
|
git_buf_free(&content);
|
||||||
return -1;
|
|
||||||
|
|
||||||
error = git_attr_file__from_buffer(repo, fbuf.ptr, file);
|
if (error) {
|
||||||
|
git_attr_file__free(*attrs_ptr);
|
||||||
git_buf_free(&fbuf);
|
*attrs_ptr = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
@ -151,9 +152,6 @@ void git_attr_file__free(git_attr_file *file)
|
|||||||
|
|
||||||
git_vector_free(&file->rules);
|
git_vector_free(&file->rules);
|
||||||
|
|
||||||
git__free(file->path);
|
|
||||||
file->path = NULL;
|
|
||||||
|
|
||||||
if (file->pool_is_allocated) {
|
if (file->pool_is_allocated) {
|
||||||
git_pool_clear(file->pool);
|
git_pool_clear(file->pool);
|
||||||
git__free(file->pool);
|
git__free(file->pool);
|
||||||
@ -504,7 +502,7 @@ int git_attr_assignment__parse(
|
|||||||
assign->value = git_attr__false;
|
assign->value = git_attr__false;
|
||||||
scan++;
|
scan++;
|
||||||
} else if (*scan == '!') {
|
} else if (*scan == '!') {
|
||||||
assign->value = NULL; /* explicit unspecified state */
|
assign->value = git_attr__unset; /* explicit unspecified state */
|
||||||
scan++;
|
scan++;
|
||||||
} else if (*scan == '#') /* comment rest of line */
|
} else if (*scan == '#') /* comment rest of line */
|
||||||
break;
|
break;
|
||||||
|
|||||||
@ -48,7 +48,7 @@ typedef struct {
|
|||||||
} git_attr_assignment;
|
} git_attr_assignment;
|
||||||
|
|
||||||
typedef struct {
|
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_vector rules; /* vector of <rule*> or <fnmatch*> */
|
||||||
git_pool *pool;
|
git_pool *pool;
|
||||||
bool pool_is_allocated;
|
bool pool_is_allocated;
|
||||||
@ -61,20 +61,25 @@ typedef struct {
|
|||||||
int is_dir;
|
int is_dir;
|
||||||
} git_attr_path;
|
} 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
|
* 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 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);
|
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(
|
extern int git_attr_file__lookup_one(
|
||||||
git_attr_file *file,
|
git_attr_file *file,
|
||||||
|
|||||||
@ -265,6 +265,7 @@ static int config_set(git_config_file *cfg, const char *name, const char *value)
|
|||||||
cvar_free(old_var);
|
cvar_free(old_var);
|
||||||
|
|
||||||
if (config_write(b, key, NULL, value) < 0) {
|
if (config_write(b, key, NULL, value) < 0) {
|
||||||
|
git_strmap_delete(b->values, var->key);
|
||||||
cvar_free(var);
|
cvar_free(var);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -82,7 +82,8 @@ static int crlf_load_attributes(struct crlf_attrs *ca, git_repository *repo, con
|
|||||||
const char *attr_vals[NUM_CONV_ATTRS];
|
const char *attr_vals[NUM_CONV_ATTRS];
|
||||||
int error;
|
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) {
|
if (error == GIT_ENOTFOUND) {
|
||||||
ca->crlf_action = GIT_CRLF_GUESS;
|
ca->crlf_action = GIT_CRLF_GUESS;
|
||||||
|
|||||||
12
src/diff.c
12
src/diff.c
@ -506,7 +506,7 @@ static int diff_from_iterators(
|
|||||||
git_diff_list **diff_ptr)
|
git_diff_list **diff_ptr)
|
||||||
{
|
{
|
||||||
const git_index_entry *oitem, *nitem;
|
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);
|
git_diff_list *diff = git_diff_list_alloc(repo, opts);
|
||||||
if (!diff)
|
if (!diff)
|
||||||
goto fail;
|
goto fail;
|
||||||
@ -536,8 +536,8 @@ static int diff_from_iterators(
|
|||||||
git_delta_t delta_type = GIT_DELTA_ADDED;
|
git_delta_t delta_type = GIT_DELTA_ADDED;
|
||||||
|
|
||||||
/* contained in ignored parent directory, so this can be skipped. */
|
/* contained in ignored parent directory, so this can be skipped. */
|
||||||
if (ignore_prefix != NULL &&
|
if (git_buf_len(&ignore_prefix) &&
|
||||||
git__prefixcmp(nitem->path, ignore_prefix) == 0)
|
git__prefixcmp(nitem->path, git_buf_cstr(&ignore_prefix)) == 0)
|
||||||
{
|
{
|
||||||
if (git_iterator_advance(new_iter, &nitem) < 0)
|
if (git_iterator_advance(new_iter, &nitem) < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
@ -555,7 +555,7 @@ static int diff_from_iterators(
|
|||||||
(oitem && git__prefixcmp(oitem->path, nitem->path) == 0))
|
(oitem && git__prefixcmp(oitem->path, nitem->path) == 0))
|
||||||
{
|
{
|
||||||
if (is_ignored)
|
if (is_ignored)
|
||||||
ignore_prefix = nitem->path;
|
git_buf_sets(&ignore_prefix, nitem->path);
|
||||||
|
|
||||||
if (git_iterator_advance_into_directory(new_iter, &nitem) < 0)
|
if (git_iterator_advance_into_directory(new_iter, &nitem) < 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
@ -589,12 +589,16 @@ static int diff_from_iterators(
|
|||||||
|
|
||||||
git_iterator_free(old_iter);
|
git_iterator_free(old_iter);
|
||||||
git_iterator_free(new_iter);
|
git_iterator_free(new_iter);
|
||||||
|
git_buf_free(&ignore_prefix);
|
||||||
|
|
||||||
*diff_ptr = diff;
|
*diff_ptr = diff;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
git_iterator_free(old_iter);
|
git_iterator_free(old_iter);
|
||||||
git_iterator_free(new_iter);
|
git_iterator_free(new_iter);
|
||||||
|
git_buf_free(&ignore_prefix);
|
||||||
|
|
||||||
git_diff_list_free(diff);
|
git_diff_list_free(diff);
|
||||||
*diff_ptr = NULL;
|
*diff_ptr = NULL;
|
||||||
return -1;
|
return -1;
|
||||||
|
|||||||
@ -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)
|
static int update_file_is_binary_by_attr(git_repository *repo, git_diff_file *file)
|
||||||
{
|
{
|
||||||
const char *value;
|
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;
|
return -1;
|
||||||
|
|
||||||
if (GIT_ATTR_FALSE(value))
|
if (GIT_ATTR_FALSE(value))
|
||||||
|
|||||||
73
src/ignore.c
73
src/ignore.c
@ -5,29 +5,22 @@
|
|||||||
#define GIT_IGNORE_FILE_INREPO "info/exclude"
|
#define GIT_IGNORE_FILE_INREPO "info/exclude"
|
||||||
#define GIT_IGNORE_FILE ".gitignore"
|
#define GIT_IGNORE_FILE ".gitignore"
|
||||||
|
|
||||||
static int load_ignore_file(
|
static int parse_ignore_file(
|
||||||
git_repository *repo, const char *path, git_attr_file *ignores)
|
git_repository *repo, const char *buffer, git_attr_file *ignores)
|
||||||
{
|
{
|
||||||
int error;
|
int error = 0;
|
||||||
git_buf fbuf = GIT_BUF_INIT;
|
|
||||||
git_attr_fnmatch *match = NULL;
|
git_attr_fnmatch *match = NULL;
|
||||||
const char *scan = NULL;
|
const char *scan = NULL;
|
||||||
char *context = NULL;
|
char *context = NULL;
|
||||||
|
|
||||||
if (ignores->path == NULL) {
|
GIT_UNUSED(repo);
|
||||||
if (git_attr_file__set_path(repo, path, ignores) < 0)
|
|
||||||
return -1;
|
if (ignores->key && git__suffixcmp(ignores->key, "/" GIT_IGNORE_FILE) == 0) {
|
||||||
|
context = ignores->key + 2;
|
||||||
|
context[strlen(context) - strlen(GIT_IGNORE_FILE)] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (git__suffixcmp(ignores->path, GIT_IGNORE_FILE) == 0) {
|
scan = buffer;
|
||||||
context = git__strndup(ignores->path,
|
|
||||||
strlen(ignores->path) - strlen(GIT_IGNORE_FILE));
|
|
||||||
GITERR_CHECK_ALLOC(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
error = git_futils_readbuffer(&fbuf, path);
|
|
||||||
|
|
||||||
scan = fbuf.ptr;
|
|
||||||
|
|
||||||
while (!error && *scan) {
|
while (!error && *scan) {
|
||||||
if (!match) {
|
if (!match) {
|
||||||
@ -54,23 +47,27 @@ static int load_ignore_file(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
git_buf_free(&fbuf);
|
|
||||||
git__free(match);
|
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;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define push_ignore(R,S,B,F) \
|
#define push_ignore_file(R,S,B,F) \
|
||||||
git_attr_cache__push_file((R),(S),(B),(F),load_ignore_file)
|
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)
|
static int push_one_ignore(void *ref, git_buf *path)
|
||||||
{
|
{
|
||||||
git_ignores *ign = (git_ignores *)ref;
|
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;
|
int error = 0;
|
||||||
const char *workdir = git_repository_workdir(repo);
|
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)
|
(error = git_attr_cache__init(repo)) < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
/* translate path into directory within workdir */
|
/* given a unrooted path in a non-bare repo, resolve it */
|
||||||
if ((error = git_path_find_dir(&ignores->dir, path, workdir)) < 0)
|
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;
|
goto cleanup;
|
||||||
|
|
||||||
/* set up internals */
|
/* set up internals */
|
||||||
error = git_attr_cache__lookup_or_create_file(
|
error = git_attr_cache__internal_file(
|
||||||
repo, GIT_IGNORE_INTERNAL, NULL, NULL, &ignores->ign_internal);
|
repo, GIT_IGNORE_INTERNAL, &ignores->ign_internal);
|
||||||
if (error < 0)
|
if (error < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
/* load .gitignore up the path */
|
/* load .gitignore up the path */
|
||||||
error = git_path_walk_up(&ignores->dir, workdir, push_one_ignore, ignores);
|
if (workdir != NULL) {
|
||||||
if (error < 0)
|
error = git_path_walk_up(
|
||||||
goto cleanup;
|
&ignores->dir, workdir, push_one_ignore, ignores);
|
||||||
|
if (error < 0)
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
/* load .git/info/exclude */
|
/* 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);
|
git_repository_path(repo), GIT_IGNORE_FILE_INREPO);
|
||||||
if (error < 0)
|
if (error < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
/* load core.excludesfile */
|
/* load core.excludesfile */
|
||||||
if (git_repository_attr_cache(repo)->cfg_excl_file != NULL)
|
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);
|
git_repository_attr_cache(repo)->cfg_excl_file);
|
||||||
|
|
||||||
cleanup:
|
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)
|
if (git_buf_joinpath(&ign->dir, ign->dir.ptr, dir) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
else
|
else
|
||||||
return push_ignore(
|
return push_ignore_file(
|
||||||
ign->repo, &ign->ign_path, ign->dir.ptr, GIT_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) {
|
if (ign->ign_path.length > 0) {
|
||||||
git_attr_file *file = git_vector_last(&ign->ign_path);
|
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_vector_pop(&ign->ign_path);
|
||||||
git_buf_rtruncate_at_char(&ign->dir, '/');
|
git_buf_rtruncate_at_char(&ign->dir, '/');
|
||||||
}
|
}
|
||||||
@ -163,7 +167,8 @@ static bool ignore_lookup_in_rules(
|
|||||||
return false;
|
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;
|
unsigned int i;
|
||||||
git_attr_file *file;
|
git_attr_file *file;
|
||||||
|
|||||||
@ -25,13 +25,14 @@ typedef struct {
|
|||||||
git_vector ign_global;
|
git_vector ign_global;
|
||||||
} git_ignores;
|
} git_ignores;
|
||||||
|
|
||||||
extern int git_ignore__for_path(
|
extern int git_ignore__for_path(git_repository *repo, const char *path, git_ignores *ign);
|
||||||
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__push_dir(git_ignores *ign, const char *dir);
|
||||||
|
|
||||||
extern int git_ignore__pop_dir(git_ignores *ign);
|
extern int git_ignore__pop_dir(git_ignores *ign);
|
||||||
|
|
||||||
extern void git_ignore__free(git_ignores *ign);
|
extern void git_ignore__free(git_ignores *ign);
|
||||||
|
|
||||||
extern int git_ignore__lookup(git_ignores *ign, const char *path, int *ignored);
|
extern int git_ignore__lookup(git_ignores *ign, const char *path, int *ignored);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
41
src/object.c
41
src/object.c
@ -146,7 +146,7 @@ int git_object_lookup_prefix(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (error < 0)
|
if (error < 0)
|
||||||
return -1;
|
return error;
|
||||||
|
|
||||||
if (type != GIT_OBJ_ANY && type != odb_obj->raw.type) {
|
if (type != GIT_OBJ_ANY && type != odb_obj->raw.type) {
|
||||||
git_odb_object_free(odb_obj);
|
git_odb_object_free(odb_obj);
|
||||||
@ -292,3 +292,42 @@ size_t git_object__size(git_otype type)
|
|||||||
return git_objects_table[type].size;
|
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;
|
||||||
|
}
|
||||||
|
|||||||
12
src/odb.c
12
src/odb.c
@ -589,7 +589,7 @@ int git_odb_read_prefix(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (found == 0)
|
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)
|
if (found > 1)
|
||||||
return git_odb__error_ambiguous("multiple matches for prefix");
|
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;
|
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;
|
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.
|
* 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.
|
* Generate a GIT_EAMBIGUOUS error for the ODB.
|
||||||
|
|||||||
@ -528,7 +528,7 @@ static int locate_object_short_oid(
|
|||||||
|
|
||||||
/* Check that directory exists */
|
/* Check that directory exists */
|
||||||
if (git_path_isdir(object_location->ptr) == false)
|
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.dir_len = git_buf_len(object_location);
|
||||||
state.short_oid_len = len;
|
state.short_oid_len = len;
|
||||||
@ -541,7 +541,7 @@ static int locate_object_short_oid(
|
|||||||
return error;
|
return error;
|
||||||
|
|
||||||
if (!state.found)
|
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 */
|
/* Convert obtained hex formatted oid to raw */
|
||||||
error = git_oid_fromstr(res_oid, (char *)state.res_oid);
|
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;
|
raw.type = GIT_OBJ_BAD;
|
||||||
|
|
||||||
if (locate_object(&object_path, (loose_backend *)backend, oid) < 0)
|
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) {
|
else if ((error = read_header_loose(&raw, &object_path)) == 0) {
|
||||||
*len_p = raw.len;
|
*len_p = raw.len;
|
||||||
*type_p = raw.type;
|
*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);
|
assert(backend && oid);
|
||||||
|
|
||||||
if (locate_object(&object_path, (loose_backend *)backend, oid) < 0)
|
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) {
|
else if ((error = read_loose(&raw, &object_path)) == 0) {
|
||||||
*buffer_p = raw.data;
|
*buffer_p = raw.data;
|
||||||
*len_p = raw.len;
|
*len_p = raw.len;
|
||||||
|
|||||||
@ -242,7 +242,7 @@ static int packfile_refresh_all(struct pack_backend *backend)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (p_stat(backend->pack_folder, &st) < 0 || !S_ISDIR(st.st_mode))
|
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) {
|
if (st.st_mtime != backend->pack_folder_mtime) {
|
||||||
git_buf path = GIT_BUF_INIT;
|
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(
|
static int pack_entry_find_prefix(
|
||||||
@ -330,7 +330,7 @@ static int pack_entry_find_prefix(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!found)
|
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)
|
else if (found > 1)
|
||||||
return git_odb__error_ambiguous("found multiple pack entries");
|
return git_odb__error_ambiguous("found multiple pack entries");
|
||||||
else
|
else
|
||||||
|
|||||||
25
src/pack.c
25
src/pack.c
@ -375,6 +375,18 @@ int git_packfile_unpack(
|
|||||||
return error;
|
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(
|
int packfile_unpack_compressed(
|
||||||
git_rawobj *obj,
|
git_rawobj *obj,
|
||||||
struct git_pack_file *p,
|
struct git_pack_file *p,
|
||||||
@ -393,6 +405,8 @@ int packfile_unpack_compressed(
|
|||||||
memset(&stream, 0, sizeof(stream));
|
memset(&stream, 0, sizeof(stream));
|
||||||
stream.next_out = buffer;
|
stream.next_out = buffer;
|
||||||
stream.avail_out = (uInt)size + 1;
|
stream.avail_out = (uInt)size + 1;
|
||||||
|
stream.zalloc = use_git_alloc;
|
||||||
|
stream.zfree = use_git_free;
|
||||||
|
|
||||||
st = inflateInit(&stream);
|
st = inflateInit(&stream);
|
||||||
if (st != Z_OK) {
|
if (st != Z_OK) {
|
||||||
@ -541,7 +555,7 @@ static int packfile_open(struct git_pack_file *p)
|
|||||||
assert(p->index_map.data);
|
assert(p->index_map.data);
|
||||||
|
|
||||||
if (!p->index_map.data && pack_index_open(p) < 0)
|
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 */
|
/* TODO: open with noatime */
|
||||||
p->mwf.fd = git_futils_open_ro(p->pack_name);
|
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");
|
path_len -= strlen(".idx");
|
||||||
if (path_len < 1) {
|
if (path_len < 1) {
|
||||||
git__free(p);
|
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);
|
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");
|
strcpy(p->pack_name + path_len, ".pack");
|
||||||
if (p_stat(p->pack_name, &st) < 0 || !S_ISREG(st.st_mode)) {
|
if (p_stat(p->pack_name, &st) < 0 || !S_ISREG(st.st_mode)) {
|
||||||
git__free(p);
|
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
|
/* 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) {
|
if (pos < (int)p->num_objects) {
|
||||||
current = index + pos * stride;
|
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;
|
found = 1;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -749,7 +762,7 @@ static int pack_entry_find_offset(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!found)
|
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)
|
if (found > 1)
|
||||||
return git_odb__error_ambiguous("found multiple offsets for pack entry");
|
return git_odb__error_ambiguous("found multiple offsets for pack entry");
|
||||||
*offset_out = nth_packed_object_offset(p, pos);
|
*offset_out = nth_packed_object_offset(p, pos);
|
||||||
|
|||||||
@ -862,3 +862,23 @@ int git_repository_is_bare(git_repository *repo)
|
|||||||
assert(repo);
|
assert(repo);
|
||||||
return repo->is_bare;
|
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;
|
||||||
|
}
|
||||||
|
|||||||
@ -98,6 +98,8 @@ struct git_repository {
|
|||||||
* export */
|
* export */
|
||||||
void git_object__free(void *object);
|
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);
|
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);
|
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;
|
return &repo->attrcache;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int git_repository_head_tree(git_tree **tree, git_repository *repo);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Weak pointers to repository internals.
|
* Weak pointers to repository internals.
|
||||||
*
|
*
|
||||||
|
|||||||
44
src/status.c
44
src/status.c
@ -18,41 +18,6 @@
|
|||||||
#include "git2/diff.h"
|
#include "git2/diff.h"
|
||||||
#include "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)
|
static unsigned int index_delta2status(git_delta_t index_status)
|
||||||
{
|
{
|
||||||
unsigned int st = GIT_STATUS_CURRENT;
|
unsigned int st = GIT_STATUS_CURRENT;
|
||||||
@ -120,11 +85,8 @@ int git_status_foreach_ext(
|
|||||||
|
|
||||||
assert(show <= GIT_STATUS_SHOW_INDEX_THEN_WORKDIR);
|
assert(show <= GIT_STATUS_SHOW_INDEX_THEN_WORKDIR);
|
||||||
|
|
||||||
switch (resolve_head_to_tree(&head, repo)) {
|
if ((err = git_repository_head_tree(&head, repo)) < 0)
|
||||||
case 0: break;
|
return err;
|
||||||
case GIT_ENOTFOUND: return 0;
|
|
||||||
default: return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(&diffopt, 0, sizeof(diffopt));
|
memset(&diffopt, 0, sizeof(diffopt));
|
||||||
memcpy(&diffopt.pathspec, &opts->pathspec, sizeof(diffopt.pathspec));
|
memcpy(&diffopt.pathspec, &opts->pathspec, sizeof(diffopt.pathspec));
|
||||||
@ -405,7 +367,7 @@ int git_status_file(
|
|||||||
status_entry_update_from_index(e, index);
|
status_entry_update_from_index(e, index);
|
||||||
|
|
||||||
/* Try to find file in HEAD */
|
/* 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;
|
goto cleanup;
|
||||||
|
|
||||||
if (tree != NULL) {
|
if (tree != NULL) {
|
||||||
|
|||||||
28
src/strmap.h
28
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_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_delete_at(h, idx) kh_del(str, h, idx)
|
||||||
|
|
||||||
#define git_strmap_insert(h, key, val, err) do { \
|
#define git_strmap_insert(h, key, val, rval) do { \
|
||||||
khiter_t __pos = kh_put(str, h, key, &err); \
|
khiter_t __pos = kh_put(str, h, key, &rval); \
|
||||||
if (err >= 0) kh_val(h, __pos) = val; \
|
if (rval >= 0) { \
|
||||||
} while (0)
|
if (rval == 0) kh_key(h, __pos) = key; \
|
||||||
|
|
||||||
#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; \
|
|
||||||
kh_val(h, __pos) = val; \
|
kh_val(h, __pos) = val; \
|
||||||
} } while (0)
|
} } 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 kh_foreach
|
||||||
#define git_strmap_foreach_value kh_foreach_value
|
#define git_strmap_foreach_value kh_foreach_value
|
||||||
|
|
||||||
|
|||||||
@ -11,9 +11,9 @@ void test_attr_file__simple_read(void)
|
|||||||
git_attr_assignment *assign;
|
git_attr_assignment *assign;
|
||||||
git_attr_rule *rule;
|
git_attr_rule *rule;
|
||||||
|
|
||||||
cl_git_pass(git_attr_file__new(&file, NULL));
|
cl_git_pass(git_attr_file__new_and_load(&file, cl_fixture("attr/attr0")));
|
||||||
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_assert_equal_s(cl_fixture("attr/attr0"), file->key + 2);
|
||||||
cl_assert(file->rules.length == 1);
|
cl_assert(file->rules.length == 1);
|
||||||
|
|
||||||
rule = get_rule(0);
|
rule = get_rule(0);
|
||||||
@ -37,9 +37,9 @@ void test_attr_file__match_variants(void)
|
|||||||
git_attr_rule *rule;
|
git_attr_rule *rule;
|
||||||
git_attr_assignment *assign;
|
git_attr_assignment *assign;
|
||||||
|
|
||||||
cl_git_pass(git_attr_file__new(&file, NULL));
|
cl_git_pass(git_attr_file__new_and_load(&file, cl_fixture("attr/attr1")));
|
||||||
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_assert_equal_s(cl_fixture("attr/attr1"), file->key + 2);
|
||||||
cl_assert(file->rules.length == 10);
|
cl_assert(file->rules.length == 10);
|
||||||
|
|
||||||
/* let's do a thorough check of this rule, then just verify
|
/* 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_rule *rule;
|
||||||
git_attr_assignment *assign;
|
git_attr_assignment *assign;
|
||||||
|
|
||||||
cl_git_pass(git_attr_file__new(&file, NULL));
|
cl_git_pass(git_attr_file__new_and_load(&file, cl_fixture("attr/attr2")));
|
||||||
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_assert_equal_s(cl_fixture("attr/attr2"), file->key + 2);
|
||||||
cl_assert(file->rules.length == 11);
|
cl_assert(file->rules.length == 11);
|
||||||
|
|
||||||
check_one_assign(file, 0, 0, "pat0", "simple", EXPECT_TRUE, NULL);
|
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_rule *rule;
|
||||||
git_attr_assignment *assign;
|
git_attr_assignment *assign;
|
||||||
|
|
||||||
cl_git_pass(git_attr_file__new(&file, NULL));
|
cl_git_pass(git_attr_file__new_and_load(&file, cl_fixture("attr/attr3")));
|
||||||
cl_git_pass(git_attr_file__from_file(NULL, cl_fixture("attr/attr3"), file));
|
cl_assert_equal_s(cl_fixture("attr/attr3"), file->key + 2);
|
||||||
cl_assert_equal_s(cl_fixture("attr/attr3"), file->path);
|
|
||||||
cl_assert(file->rules.length == 3);
|
cl_assert(file->rules.length == 3);
|
||||||
|
|
||||||
rule = get_rule(0);
|
rule = get_rule(0);
|
||||||
@ -214,7 +213,7 @@ void test_attr_file__check_attr_examples(void)
|
|||||||
cl_assert(rule->assigns.length == 1);
|
cl_assert(rule->assigns.length == 1);
|
||||||
assign = get_assign(rule, 0);
|
assign = get_assign(rule, 0);
|
||||||
cl_assert_equal_s("myAttr", assign->name);
|
cl_assert_equal_s("myAttr", assign->name);
|
||||||
cl_assert(assign->value == NULL);
|
cl_assert(GIT_ATTR_UNSPECIFIED(assign->value));
|
||||||
|
|
||||||
rule = get_rule(2);
|
rule = get_rule(2);
|
||||||
cl_assert_equal_s("README", rule->match.pattern);
|
cl_assert_equal_s("README", rule->match.pattern);
|
||||||
|
|||||||
108
tests-clar/attr/flags.c
Normal file
108
tests-clar/attr/flags.c
Normal file
@ -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");
|
||||||
|
}
|
||||||
|
|
||||||
@ -9,9 +9,8 @@ void test_attr_lookup__simple(void)
|
|||||||
git_attr_path path;
|
git_attr_path path;
|
||||||
const char *value = NULL;
|
const char *value = NULL;
|
||||||
|
|
||||||
cl_git_pass(git_attr_file__new(&file, NULL));
|
cl_git_pass(git_attr_file__new_and_load(&file, cl_fixture("attr/attr0")));
|
||||||
cl_git_pass(git_attr_file__from_file(NULL, cl_fixture("attr/attr0"), file));
|
cl_assert_equal_s(cl_fixture("attr/attr0"), file->key + 2);
|
||||||
cl_assert_equal_s(cl_fixture("attr/attr0"), file->path);
|
|
||||||
cl_assert(file->rules.length == 1);
|
cl_assert(file->rules.length == 1);
|
||||||
|
|
||||||
cl_git_pass(git_attr_path__init(&path, "test", NULL));
|
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 }
|
{ NULL, NULL, 0, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
cl_git_pass(git_attr_file__new(&file, NULL));
|
cl_git_pass(git_attr_file__new_and_load(&file, cl_fixture("attr/attr1")));
|
||||||
cl_git_pass(git_attr_file__from_file(NULL, cl_fixture("attr/attr1"), file));
|
cl_assert_equal_s(cl_fixture("attr/attr1"), file->key + 2);
|
||||||
cl_assert_equal_s(cl_fixture("attr/attr1"), file->path);
|
|
||||||
cl_assert(file->rules.length == 10);
|
cl_assert(file->rules.length == 10);
|
||||||
|
|
||||||
cl_git_pass(git_attr_path__init(&path, "/testing/for/pat0", NULL));
|
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 }
|
{ NULL, NULL, 0, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
cl_git_pass(git_attr_file__new(&file, NULL));
|
cl_git_pass(git_attr_file__new_and_load(&file, cl_fixture("attr/attr2")));
|
||||||
cl_git_pass(git_attr_file__from_file(NULL, cl_fixture("attr/attr2"), file));
|
|
||||||
cl_assert(file->rules.length == 11);
|
cl_assert(file->rules.length == 11);
|
||||||
|
|
||||||
run_test_cases(file, cases, 0);
|
run_test_cases(file, cases, 0);
|
||||||
@ -228,8 +225,7 @@ void test_attr_lookup__check_attr_examples(void)
|
|||||||
{ NULL, NULL, 0, NULL }
|
{ NULL, NULL, 0, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
cl_git_pass(git_attr_file__new(&file, NULL));
|
cl_git_pass(git_attr_file__new_and_load(&file, cl_fixture("attr/attr3")));
|
||||||
cl_git_pass(git_attr_file__from_file(NULL, cl_fixture("attr/attr3"), file));
|
|
||||||
cl_assert(file->rules.length == 3);
|
cl_assert(file->rules.length == 3);
|
||||||
|
|
||||||
run_test_cases(file, cases, 0);
|
run_test_cases(file, cases, 0);
|
||||||
@ -254,8 +250,10 @@ void test_attr_lookup__from_buffer(void)
|
|||||||
{ NULL, NULL, 0, NULL }
|
{ NULL, NULL, 0, NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
cl_git_pass(git_attr_file__new(&file, NULL));
|
cl_git_pass(git_attr_file__new(&file, 0, NULL, NULL));
|
||||||
cl_git_pass(git_attr_file__from_buffer(NULL, "a* foo\nabc bar\n* baz", file));
|
|
||||||
|
cl_git_pass(git_attr_file__parse_buffer(NULL, "a* foo\nabc bar\n* baz", file));
|
||||||
|
|
||||||
cl_assert(file->rules.length == 3);
|
cl_assert(file->rules.length == 3);
|
||||||
|
|
||||||
run_test_cases(file, cases, 0);
|
run_test_cases(file, cases, 0);
|
||||||
|
|||||||
@ -64,13 +64,13 @@ void test_attr_repo__get_one(void)
|
|||||||
|
|
||||||
for (scan = test_cases; scan->path != NULL; scan++) {
|
for (scan = test_cases; scan->path != NULL; scan++) {
|
||||||
const char *value;
|
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);
|
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, 0, ".git/info/attributes"));
|
||||||
cl_assert(git_attr_cache__is_cached(g_repo, ".gitattributes"));
|
cl_assert(git_attr_cache__is_cached(g_repo, 0, ".gitattributes"));
|
||||||
cl_assert(git_attr_cache__is_cached(g_repo, "sub/.gitattributes"));
|
cl_assert(git_attr_cache__is_cached(g_repo, 0, "sub/.gitattributes"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_attr_repo__get_many(void)
|
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 *names[4] = { "repoattr", "rootattr", "missingattr", "subattr" };
|
||||||
const char *values[4];
|
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[0]));
|
||||||
cl_assert(GIT_ATTR_TRUE(values[1]));
|
cl_assert(GIT_ATTR_TRUE(values[1]));
|
||||||
cl_assert(GIT_ATTR_UNSPECIFIED(values[2]));
|
cl_assert(GIT_ATTR_UNSPECIFIED(values[2]));
|
||||||
cl_assert(GIT_ATTR_UNSPECIFIED(values[3]));
|
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_TRUE(values[0]));
|
||||||
cl_assert(GIT_ATTR_FALSE(values[1]));
|
cl_assert(GIT_ATTR_FALSE(values[1]));
|
||||||
cl_assert(GIT_ATTR_UNSPECIFIED(values[2]));
|
cl_assert(GIT_ATTR_UNSPECIFIED(values[2]));
|
||||||
cl_assert(GIT_ATTR_UNSPECIFIED(values[3]));
|
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[0]));
|
||||||
cl_assert(GIT_ATTR_TRUE(values[1]));
|
cl_assert(GIT_ATTR_TRUE(values[1]));
|
||||||
@ -118,16 +118,17 @@ void test_attr_repo__foreach(void)
|
|||||||
int count;
|
int count;
|
||||||
|
|
||||||
count = 0;
|
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);
|
cl_assert(count == 2);
|
||||||
|
|
||||||
count = 0;
|
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));
|
&count_attrs, &count));
|
||||||
cl_assert(count == 4); /* repoattr, rootattr, subattr, negattr */
|
cl_assert(count == 4); /* repoattr, rootattr, subattr, negattr */
|
||||||
|
|
||||||
count = 0;
|
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));
|
&count_attrs, &count));
|
||||||
cl_assert(count == 6); /* repoattr, rootattr, subattr, reposub, negattr, another */
|
cl_assert(count == 6); /* repoattr, rootattr, subattr, reposub, negattr, another */
|
||||||
}
|
}
|
||||||
@ -136,19 +137,19 @@ void test_attr_repo__manpage_example(void)
|
|||||||
{
|
{
|
||||||
const char *value;
|
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_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_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_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_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));
|
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 *names3[3] = { "macro2", "multi2", "multi3" };
|
||||||
const char *values[5];
|
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[0]));
|
||||||
cl_assert(GIT_ATTR_TRUE(values[1]));
|
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_FALSE(values[3]));
|
||||||
cl_assert(GIT_ATTR_UNSPECIFIED(values[4]));
|
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[0]));
|
||||||
cl_assert(GIT_ATTR_TRUE(values[1]));
|
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(GIT_ATTR_UNSPECIFIED(values[3]));
|
||||||
cl_assert_equal_s("77", values[4]);
|
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_TRUE(values[0]));
|
||||||
cl_assert(GIT_ATTR_FALSE(values[1]));
|
cl_assert(GIT_ATTR_FALSE(values[1]));
|
||||||
@ -188,7 +189,7 @@ void test_attr_repo__bad_macros(void)
|
|||||||
"firstmacro", "secondmacro", "thirdmacro" };
|
"firstmacro", "secondmacro", "thirdmacro" };
|
||||||
const char *values[6];
|
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 */
|
/* these three just confirm that the "mymacro" rule ran */
|
||||||
cl_assert(GIT_ATTR_UNSPECIFIED(values[0]));
|
cl_assert(GIT_ATTR_UNSPECIFIED(values[0]));
|
||||||
|
|||||||
@ -5,7 +5,6 @@ static git_repository *g_repo = NULL;
|
|||||||
|
|
||||||
void test_diff_tree__initialize(void)
|
void test_diff_tree__initialize(void)
|
||||||
{
|
{
|
||||||
g_repo = cl_git_sandbox_init("attr");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void test_diff_tree__cleanup(void)
|
void test_diff_tree__cleanup(void)
|
||||||
@ -19,15 +18,16 @@ void test_diff_tree__0(void)
|
|||||||
const char *a_commit = "605812a";
|
const char *a_commit = "605812a";
|
||||||
const char *b_commit = "370fe9ec22";
|
const char *b_commit = "370fe9ec22";
|
||||||
const char *c_commit = "f5b0af1fb4f5c";
|
const char *c_commit = "f5b0af1fb4f5c";
|
||||||
git_tree *a = resolve_commit_oid_to_tree(g_repo, a_commit);
|
git_tree *a, *b, *c;
|
||||||
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_diff_options opts = {0};
|
git_diff_options opts = {0};
|
||||||
git_diff_list *diff = NULL;
|
git_diff_list *diff = NULL;
|
||||||
diff_expects exp;
|
diff_expects exp;
|
||||||
|
|
||||||
cl_assert(a);
|
g_repo = cl_git_sandbox_init("attr");
|
||||||
cl_assert(b);
|
|
||||||
|
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.context_lines = 1;
|
||||||
opts.interhunk_lines = 1;
|
opts.interhunk_lines = 1;
|
||||||
@ -87,12 +87,7 @@ void test_diff_tree__options(void)
|
|||||||
const char *b_commit = "605812ab7fe421fdd";
|
const char *b_commit = "605812ab7fe421fdd";
|
||||||
const char *c_commit = "f5b0af1fb4f5";
|
const char *c_commit = "f5b0af1fb4f5";
|
||||||
const char *d_commit = "a97cc019851";
|
const char *d_commit = "a97cc019851";
|
||||||
|
git_tree *a, *b, *c, *d;
|
||||||
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_diff_options opts = {0};
|
git_diff_options opts = {0};
|
||||||
git_diff_list *diff = NULL;
|
git_diff_list *diff = NULL;
|
||||||
diff_expects actual;
|
diff_expects actual;
|
||||||
@ -133,8 +128,12 @@ void test_diff_tree__options(void)
|
|||||||
diff_expects *expected;
|
diff_expects *expected;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
cl_assert(a);
|
g_repo = cl_git_sandbox_init("attr");
|
||||||
cl_assert(b);
|
|
||||||
|
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++) {
|
for (i = 0; test_expects[i].files > 0; i++) {
|
||||||
memset(&actual, 0, sizeof(actual)); /* clear accumulator */
|
memset(&actual, 0, sizeof(actual)); /* clear accumulator */
|
||||||
@ -168,3 +167,44 @@ void test_diff_tree__options(void)
|
|||||||
git_tree_free(c);
|
git_tree_free(c);
|
||||||
git_tree_free(d);
|
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);
|
||||||
|
}
|
||||||
|
|||||||
1
tests-clar/resources/attr_index/.gitted/HEAD
Normal file
1
tests-clar/resources/attr_index/.gitted/HEAD
Normal file
@ -0,0 +1 @@
|
|||||||
|
ref: refs/heads/master
|
||||||
6
tests-clar/resources/attr_index/.gitted/config
Normal file
6
tests-clar/resources/attr_index/.gitted/config
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
[core]
|
||||||
|
repositoryformatversion = 0
|
||||||
|
filemode = true
|
||||||
|
bare = false
|
||||||
|
logallrefupdates = true
|
||||||
|
ignorecase = true
|
||||||
1
tests-clar/resources/attr_index/.gitted/description
Normal file
1
tests-clar/resources/attr_index/.gitted/description
Normal file
@ -0,0 +1 @@
|
|||||||
|
Unnamed repository; edit this file 'description' to name the repository.
|
||||||
BIN
tests-clar/resources/attr_index/.gitted/index
Normal file
BIN
tests-clar/resources/attr_index/.gitted/index
Normal file
Binary file not shown.
6
tests-clar/resources/attr_index/.gitted/info/exclude
Normal file
6
tests-clar/resources/attr_index/.gitted/info/exclude
Normal file
@ -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]
|
||||||
|
# *~
|
||||||
1
tests-clar/resources/attr_index/.gitted/info/refs
Normal file
1
tests-clar/resources/attr_index/.gitted/info/refs
Normal file
@ -0,0 +1 @@
|
|||||||
|
58f7cf825b553ef7c26e5b9f8a23599c1a9ca296 refs/heads/master
|
||||||
4
tests-clar/resources/attr_index/.gitted/logs/HEAD
Normal file
4
tests-clar/resources/attr_index/.gitted/logs/HEAD
Normal file
@ -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
|
||||||
@ -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
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
x•<>[
|
||||||
|
Γ Eϋν*ά@‹<>PJι
|
||||||
|
]€<>™&“`ΜώλϊwΈ<77>'o¥ΜMΈK«D’ ‚q•4¤ΚΛμ5DFΛ#<23>δ!!<21>=VZ›DΟ.³L<>†:ƒ%L<>}ƒ!dC<>¬<>g›¶*ίηqΠ²Θ-LUήkz~η6<CEB7>ι–·ς<C2B7>Ϊ«νΰ<06>Wε”}ν}«<C2AD>>Εg<CE95>ΛΎΥ{f<>βϊ%ρ΅Gς
|
||||||
@ -0,0 +1 @@
|
|||||||
|
x
ÃÑ €0@¿<>âÍà‡“¸@kR”’@ßÂ]½ã<¶K4±ÜnÕÔÅY‰á<E280B0>)l(a¨hF˜Hcƒcÿ^Ô<18>
|
||||||
Binary file not shown.
Binary file not shown.
@ -0,0 +1,2 @@
|
|||||||
|
P pack-4e6438607204ce78827e3885594b2c0bb4f13895.pack
|
||||||
|
|
||||||
Binary file not shown.
Binary file not shown.
2
tests-clar/resources/attr_index/.gitted/packed-refs
Normal file
2
tests-clar/resources/attr_index/.gitted/packed-refs
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
# pack-refs with: peeled
|
||||||
|
58f7cf825b553ef7c26e5b9f8a23599c1a9ca296 refs/heads/master
|
||||||
@ -0,0 +1 @@
|
|||||||
|
3812cfef36615db1788d4e63f90028007e17a348
|
||||||
1
tests-clar/resources/attr_index/README.md
Normal file
1
tests-clar/resources/attr_index/README.md
Normal file
@ -0,0 +1 @@
|
|||||||
|
This is contains tests for when the index and work dir differ
|
||||||
1
tests-clar/resources/attr_index/README.txt
Normal file
1
tests-clar/resources/attr_index/README.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
This contains files for testing when the index and the workdir differ
|
||||||
4
tests-clar/resources/attr_index/gitattributes
Normal file
4
tests-clar/resources/attr_index/gitattributes
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
* bar
|
||||||
|
*.txt -foo beep=10
|
||||||
|
*.md blargh=goop -bar
|
||||||
|
|
||||||
3
tests-clar/resources/attr_index/sub/sub/.gitattributes
vendored
Normal file
3
tests-clar/resources/attr_index/sub/sub/.gitattributes
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
*.txt another=one again
|
||||||
|
*.md bar=1234
|
||||||
|
|
||||||
1
tests-clar/resources/attr_index/sub/sub/README.md
Normal file
1
tests-clar/resources/attr_index/sub/sub/README.md
Normal file
@ -0,0 +1 @@
|
|||||||
|
More testing
|
||||||
1
tests-clar/resources/attr_index/sub/sub/README.txt
Normal file
1
tests-clar/resources/attr_index/sub/sub/README.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
More testing
|
||||||
@ -47,8 +47,8 @@ void test_status_ignore__0(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* confirm that ignore files were cached */
|
/* 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, 0, ".git/info/exclude"));
|
||||||
cl_assert(git_attr_cache__is_cached(g_repo, ".gitignore"));
|
cl_assert(git_attr_cache__is_cached(g_repo, 0, ".gitignore"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user