diff options
author | Vicent Martà <vicent@github.com> | 2013-05-24 11:39:56 -0700 |
---|---|---|
committer | Vicent Martà <vicent@github.com> | 2013-05-24 11:39:56 -0700 |
commit | 85281328be6341794341a9a46b54e3a557b2b889 (patch) | |
tree | b0bac0291ac788c6771b02e4ed59e970d2c669c7 | |
parent | 5e57cfa1b34374835f03e8d0ea61c338ed5cd9f0 (diff) | |
parent | 7a5ee3dc923caf2b3b9b5e9b2408340f6ae32d7d (diff) | |
download | libgit2-85281328be6341794341a9a46b54e3a557b2b889.tar.gz |
Merge pull request #1608 from arrbee/various-cleanups-and-tweaks
Various cleanups and tweaks
-rw-r--r-- | include/git2/common.h | 46 | ||||
-rw-r--r-- | include/git2/config.h | 37 | ||||
-rw-r--r-- | include/git2/diff.h | 15 | ||||
-rw-r--r-- | include/git2/errors.h | 4 | ||||
-rw-r--r-- | include/git2/odb_backend.h | 4 | ||||
-rw-r--r-- | include/git2/sys/config.h | 4 | ||||
-rw-r--r-- | src/attr.c | 29 | ||||
-rw-r--r-- | src/attrcache.h | 8 | ||||
-rw-r--r-- | src/cache.c | 5 | ||||
-rw-r--r-- | src/config.c | 24 | ||||
-rw-r--r-- | src/config_file.c | 8 | ||||
-rw-r--r-- | src/diff.c | 4 | ||||
-rw-r--r-- | tests-clar/attr/ignore.c | 35 |
13 files changed, 164 insertions, 59 deletions
diff --git a/include/git2/common.h b/include/git2/common.h index f9e9929ea..b52e13918 100644 --- a/include/git2/common.h +++ b/include/git2/common.h @@ -103,10 +103,10 @@ GIT_EXTERN(void) git_libgit2_version(int *major, int *minor, int *rev); /** * Combinations of these values describe the capabilities of libgit2. */ -enum { +typedef enum { GIT_CAP_THREADS = ( 1 << 0 ), GIT_CAP_HTTPS = ( 1 << 1 ) -}; +} git_cap_t; /** * Query compile time options for libgit2. @@ -114,17 +114,18 @@ enum { * @return A combination of GIT_CAP_* values. * * - GIT_CAP_THREADS - * Libgit2 was compiled with thread support. Note that thread support is still to be seen as a - * 'work in progress'. + * Libgit2 was compiled with thread support. Note that thread support is + * still to be seen as a 'work in progress' - basic object lookups are + * believed to be threadsafe, but other operations may not be. * * - GIT_CAP_HTTPS - * Libgit2 supports the https:// protocol. This requires the open ssl library to be - * found when compiling libgit2. + * Libgit2 supports the https:// protocol. This requires the openssl + * library to be found when compiling libgit2. */ GIT_EXTERN(int) git_libgit2_capabilities(void); -enum { +typedef enum { GIT_OPT_GET_MWINDOW_SIZE, GIT_OPT_SET_MWINDOW_SIZE, GIT_OPT_GET_MWINDOW_MAPPED_LIMIT, @@ -135,7 +136,7 @@ enum { GIT_OPT_SET_CACHE_MAX_SIZE, GIT_OPT_ENABLE_CACHING, GIT_OPT_GET_CACHED_MEMORY -}; +} git_libgit2_opt_t; /** * Set or query a library global option @@ -179,6 +180,35 @@ enum { * > - `level` must be GIT_CONFIG_LEVEL_SYSTEM, GIT_CONFIG_LEVEL_GLOBAL, * > or GIT_CONFIG_LEVEL_XDG. * + * * opts(GIT_OPT_SET_CACHE_OBJECT_LIMIT, git_otype type, size_t size) + * + * > Set the maximum data size for the given type of object to be + * > considered eligible for caching in memory. Setting to value to + * > zero means that that type of object will not be cached. + * > Defaults to 0 for GIT_OBJ_BLOB (i.e. won't cache blobs) and 4k + * > for GIT_OBJ_COMMIT, GIT_OBJ_TREE, and GIT_OBJ_TAG. + * + * * opts(GIT_OPT_SET_CACHE_MAX_SIZE, ssize_t max_storage_bytes) + * + * > Set the maximum total data size that will be cached in memory + * > across all repositories before libgit2 starts evicting objects + * > from the cache. This is a soft limit, in that the library might + * > briefly exceed it, but will start aggressively evicting objects + * > from cache when that happens. The default cache size is 256Mb. + * + * * opts(GIT_OPT_ENABLE_CACHING, int enabled) + * + * > Enable or disable caching completely. + * > + * > Because caches are repository-specific, disabling the cache + * > cannot immediately clear all cached objects, but each cache will + * > be cleared on the next attempt to update anything in it. + * + * * opts(GIT_OPT_GET_CACHED_MEMORY, ssize_t *current, ssize_t *allowed) + * + * > Get the current bytes in cache and the maximum that would be + * > allowed in the cache. + * * @param option Option key * @param ... value to set the option * @return 0 on success, <0 on failure diff --git a/include/git2/config.h b/include/git2/config.h index 8d1a1a5a6..518dcaf16 100644 --- a/include/git2/config.h +++ b/include/git2/config.h @@ -27,18 +27,33 @@ GIT_BEGIN_DECL * git_config_open_default() and git_repository_config() honor those * priority levels as well. */ -enum { - GIT_CONFIG_LEVEL_SYSTEM = 1, /**< System-wide configuration file. */ - GIT_CONFIG_LEVEL_XDG = 2, /**< XDG compatible configuration file (.config/git/config). */ - GIT_CONFIG_LEVEL_GLOBAL = 3, /**< User-specific configuration file, also called Global configuration file. */ - GIT_CONFIG_LEVEL_LOCAL = 4, /**< Repository specific configuration file. */ - GIT_CONFIG_HIGHEST_LEVEL = -1, /**< Represents the highest level of a config file. */ -}; +typedef enum { + /** System-wide configuration file; /etc/gitconfig on Linux systems */ + GIT_CONFIG_LEVEL_SYSTEM = 1, + + /** XDG compatible configuration file; typically ~/.config/git/config */ + GIT_CONFIG_LEVEL_XDG = 2, + + /** User-specific configuration file (also called Global configuration + * file); typically ~/.gitconfig + */ + GIT_CONFIG_LEVEL_GLOBAL = 3, + + /** Repository specific configuration file; $WORK_DIR/.git/config on + * non-bare repos + */ + GIT_CONFIG_LEVEL_LOCAL = 4, + + /** Represents the highest level available config file (i.e. the most + * specific config file available that actually is loaded) + */ + GIT_CONFIG_HIGHEST_LEVEL = -1, +} git_config_level_t; typedef struct { const char *name; const char *value; - unsigned int level; + git_config_level_t level; } git_config_entry; typedef int (*git_config_foreach_cb)(const git_config_entry *, void *); @@ -155,7 +170,7 @@ GIT_EXTERN(int) git_config_new(git_config **out); GIT_EXTERN(int) git_config_add_file_ondisk( git_config *cfg, const char *path, - unsigned int level, + git_config_level_t level, int force); /** @@ -192,7 +207,7 @@ GIT_EXTERN(int) git_config_open_ondisk(git_config **out, const char *path); GIT_EXTERN(int) git_config_open_level( git_config **out, const git_config *parent, - unsigned int level); + git_config_level_t level); /** * Open the global/XDG configuration file according to git's rules @@ -241,7 +256,7 @@ GIT_EXTERN(void) git_config_free(git_config *cfg); * @return 0 or an error code */ GIT_EXTERN(int) git_config_get_entry( - const git_config_entry **out, + const git_config_entry **out, const git_config *cfg, const char *name); diff --git a/include/git2/diff.h b/include/git2/diff.h index 0d4875b43..d26456cb0 100644 --- a/include/git2/diff.h +++ b/include/git2/diff.h @@ -89,9 +89,10 @@ typedef enum { /** Include unmodified files in the diff list */ GIT_DIFF_INCLUDE_UNMODIFIED = (1 << 9), - /** Even with GIT_DIFF_INCLUDE_UNTRACKED, an entire untracked directory - * will be marked with only a single entry in the diff list; this flag - * adds all files under the directory as UNTRACKED entries, too. + /** Even with GIT_DIFF_INCLUDE_UNTRACKED, an entire untracked + * directory will be marked with only a single entry in the diff list + * (a la what core Git does in `git status`); this flag adds *all* + * files under untracked directories as UNTRACKED entries, too. */ GIT_DIFF_RECURSE_UNTRACKED_DIRS = (1 << 10), @@ -103,7 +104,11 @@ typedef enum { /** Use case insensitive filename comparisons */ GIT_DIFF_DELTAS_ARE_ICASE = (1 << 12), - /** When generating patch text, include the content of untracked files */ + /** When generating patch text, include the content of untracked + * files. This automatically turns on GIT_DIFF_INCLUDE_UNTRACKED but + * it does not turn on GIT_DIFF_RECURSE_UNTRACKED_DIRS. Add that + * flag if you want the content of every single UNTRACKED file. + */ GIT_DIFF_INCLUDE_UNTRACKED_CONTENT = (1 << 13), /** Disable updating of the `binary` flag in delta records. This is @@ -139,7 +144,7 @@ typedef enum { * consider UNTRACKED only if it has an actual untracked file in it. * This scan is extra work for a case you often don't care about. This * flag makes libgit2 immediately label an untracked directory as - * UNTRACKED without looking insde it (which differs from core Git). + * UNTRACKED without looking inside it (which differs from core Git). * Of course, ignore rules are still checked for the directory itself. */ GIT_DIFF_FAST_UNTRACKED_DIRS = (1 << 19), diff --git a/include/git2/errors.h b/include/git2/errors.h index 917f0699c..caf9e62b8 100644 --- a/include/git2/errors.h +++ b/include/git2/errors.h @@ -18,7 +18,7 @@ GIT_BEGIN_DECL /** Generic return codes */ -enum { +typedef enum { GIT_OK = 0, GIT_ERROR = -1, GIT_ENOTFOUND = -3, @@ -35,7 +35,7 @@ enum { GIT_PASSTHROUGH = -30, GIT_ITEROVER = -31, -}; +} git_error_code; typedef struct { char *message; diff --git a/include/git2/odb_backend.h b/include/git2/odb_backend.h index 4c2493a25..af1e3e5b9 100644 --- a/include/git2/odb_backend.h +++ b/include/git2/odb_backend.h @@ -59,11 +59,11 @@ GIT_EXTERN(int) git_odb_backend_loose(git_odb_backend **out, const char *objects GIT_EXTERN(int) git_odb_backend_one_pack(git_odb_backend **out, const char *index_file); /** Streaming mode */ -enum { +typedef enum { GIT_STREAM_RDONLY = (1 << 1), GIT_STREAM_WRONLY = (1 << 2), GIT_STREAM_RW = (GIT_STREAM_RDONLY | GIT_STREAM_WRONLY), -}; +} git_odb_stream_t; /** A stream to read/write from a backend */ struct git_odb_stream { diff --git a/include/git2/sys/config.h b/include/git2/sys/config.h index 1c9deba7c..11e59cf03 100644 --- a/include/git2/sys/config.h +++ b/include/git2/sys/config.h @@ -29,7 +29,7 @@ struct git_config_backend { struct git_config *cfg; /* Open means open the file/database and parse if necessary */ - int (*open)(struct git_config_backend *, unsigned int level); + int (*open)(struct git_config_backend *, git_config_level_t level); int (*get)(const struct git_config_backend *, const char *key, const git_config_entry **entry); int (*get_multivar)(struct git_config_backend *, const char *key, const char *regexp, git_config_foreach_cb callback, void *payload); int (*set)(struct git_config_backend *, const char *key, const char *value); @@ -63,7 +63,7 @@ struct git_config_backend { GIT_EXTERN(int) git_config_add_backend( git_config *cfg, git_config_backend *file, - unsigned int level, + git_config_level_t level, int force); /** @} */ diff --git a/src/attr.c b/src/attr.c index 9fe4471f6..6cdff29f9 100644 --- a/src/attr.c +++ b/src/attr.c @@ -596,26 +596,33 @@ static int collect_attr_files( } static int attr_cache__lookup_path( - const char **out, git_config *cfg, const char *key, const char *fallback) + char **out, git_config *cfg, const char *key, const char *fallback) { git_buf buf = GIT_BUF_INIT; int error; + const char *cfgval = NULL; - if (!(error = git_config_get_string(out, cfg, key))) - return 0; + *out = NULL; + + if (!(error = git_config_get_string(&cfgval, cfg, key))) { + + /* expand leading ~/ as needed */ + if (cfgval && cfgval[0] == '~' && cfgval[1] == '/' && + !git_futils_find_global_file(&buf, &cfgval[2])) + *out = git_buf_detach(&buf); + else if (cfgval) + *out = git__strdup(cfgval); - if (error == GIT_ENOTFOUND) { + } else if (error == GIT_ENOTFOUND) { giterr_clear(); error = 0; if (!git_futils_find_xdg_file(&buf, fallback)) *out = git_buf_detach(&buf); - else - *out = NULL; - - git_buf_free(&buf); } + git_buf_free(&buf); + return error; } @@ -696,6 +703,12 @@ void git_attr_cache_flush( git_pool_clear(&cache->pool); + git__free(cache->cfg_attr_file); + cache->cfg_attr_file = NULL; + + git__free(cache->cfg_excl_file); + cache->cfg_excl_file = NULL; + cache->initialized = 0; } diff --git a/src/attrcache.h b/src/attrcache.h index 12cec4bfb..077633b87 100644 --- a/src/attrcache.h +++ b/src/attrcache.h @@ -13,10 +13,10 @@ typedef struct { int initialized; git_pool pool; - git_strmap *files; /* hash path to git_attr_file of rules */ - git_strmap *macros; /* hash name to vector<git_attr_assignment> */ - const char *cfg_attr_file; /* cached value of core.attributesfile */ - const char *cfg_excl_file; /* cached value of core.excludesfile */ + git_strmap *files; /* hash path to git_attr_file of rules */ + git_strmap *macros; /* hash name to vector<git_attr_assignment> */ + char *cfg_attr_file; /* cached value of core.attributesfile */ + char *cfg_excl_file; /* cached value of core.excludesfile */ } git_attr_cache; extern int git_attr_cache__init(git_repository *repo); diff --git a/src/cache.c b/src/cache.c index 1360cc976..dc3af063a 100644 --- a/src/cache.c +++ b/src/cache.c @@ -174,6 +174,11 @@ static void *cache_store(git_cache *cache, git_cached_obj *entry) git_cached_obj_incref(entry); + if (!git_cache__enabled && cache->used_memory > 0) { + git_cache_clear(cache); + return entry; + } + if (!cache_should_store(entry->type, entry->size)) return entry; diff --git a/src/config.c b/src/config.c index e436a31ad..9491d267a 100644 --- a/src/config.c +++ b/src/config.c @@ -23,7 +23,7 @@ typedef struct { git_refcount rc; git_config_backend *file; - unsigned int level; + git_config_level_t level; } file_internal; static void file_internal_free(file_internal *internal) @@ -87,7 +87,7 @@ int git_config_new(git_config **out) int git_config_add_file_ondisk( git_config *cfg, const char *path, - unsigned int level, + git_config_level_t level, int force) { git_config_backend *file = NULL; @@ -138,11 +138,11 @@ int git_config_open_ondisk(git_config **out, const char *path) static int find_internal_file_by_level( file_internal **internal_out, const git_config *cfg, - int level) + git_config_level_t level) { int pos = -1; file_internal *internal; - unsigned int i; + size_t i; /* when passing GIT_CONFIG_HIGHEST_LEVEL, the idea is to get the config file * which has the highest level. As config files are stored in a vector @@ -153,14 +153,14 @@ static int find_internal_file_by_level( pos = 0; } else { git_vector_foreach(&cfg->files, i, internal) { - if (internal->level == (unsigned int)level) + if (internal->level == level) pos = i; } } if (pos == -1) { giterr_set(GITERR_CONFIG, - "No config file exists for the given level '%i'", level); + "No config file exists for the given level '%i'", (int)level); return GIT_ENOTFOUND; } @@ -175,17 +175,17 @@ static int duplicate_level(void **old_raw, void *new_raw) GIT_UNUSED(new_raw); - giterr_set(GITERR_CONFIG, "A file with the same level (%i) has already been added to the config", (*old)->level); + giterr_set(GITERR_CONFIG, "A file with the same level (%i) has already been added to the config", (int)(*old)->level); return GIT_EEXISTS; } static void try_remove_existing_file_internal( git_config *cfg, - unsigned int level) + git_config_level_t level) { int pos = -1; file_internal *internal; - unsigned int i; + size_t i; git_vector_foreach(&cfg->files, i, internal) { if (internal->level == level) @@ -206,7 +206,7 @@ static void try_remove_existing_file_internal( static int git_config__add_internal( git_config *cfg, file_internal *internal, - unsigned int level, + git_config_level_t level, int force) { int result; @@ -238,7 +238,7 @@ int git_config_open_global(git_config **cfg_out, git_config *cfg) int git_config_open_level( git_config **cfg_out, const git_config *cfg_parent, - unsigned int level) + git_config_level_t level) { git_config *cfg; file_internal *internal; @@ -263,7 +263,7 @@ int git_config_open_level( int git_config_add_backend( git_config *cfg, git_config_backend *file, - unsigned int level, + git_config_level_t level, int force) { file_internal *internal; diff --git a/src/config_file.c b/src/config_file.c index e57cd1e53..dec952115 100644 --- a/src/config_file.c +++ b/src/config_file.c @@ -81,10 +81,10 @@ typedef struct { time_t file_mtime; size_t file_size; - unsigned int level; + git_config_level_t level; } diskfile_backend; -static int config_parse(diskfile_backend *cfg_file, unsigned int level); +static int config_parse(diskfile_backend *cfg_file, git_config_level_t level); static int parse_variable(diskfile_backend *cfg, char **var_name, char **var_value); static int config_write(diskfile_backend *cfg, const char *key, const regex_t *preg, const char *value); static char *escape_value(const char *ptr); @@ -181,7 +181,7 @@ static void free_vars(git_strmap *values) git_strmap_free(values); } -static int config_open(git_config_backend *cfg, unsigned int level) +static int config_open(git_config_backend *cfg, git_config_level_t level) { int res; diskfile_backend *b = (diskfile_backend *)cfg; @@ -965,7 +965,7 @@ static int strip_comments(char *line, int in_quotes) return quote_count; } -static int config_parse(diskfile_backend *cfg_file, unsigned int level) +static int config_parse(diskfile_backend *cfg_file, git_config_level_t level) { int c; char *current_section = NULL; diff --git a/src/diff.c b/src/diff.c index d2389f103..b96ff4705 100644 --- a/src/diff.c +++ b/src/diff.c @@ -383,6 +383,10 @@ static int diff_list_apply_options( if (DIFF_FLAG_IS_SET(diff, GIT_DIFF_INCLUDE_TYPECHANGE_TREES)) diff->opts.flags |= GIT_DIFF_INCLUDE_TYPECHANGE; + /* flag INCLUDE_UNTRACKED_CONTENT implies INCLUDE_UNTRACKED */ + if (DIFF_FLAG_IS_SET(diff, GIT_DIFF_INCLUDE_UNTRACKED_CONTENT)) + diff->opts.flags |= GIT_DIFF_INCLUDE_UNTRACKED; + /* load config values that affect diff behavior */ if (git_repository_config__weakptr(&cfg, repo) < 0) return -1; diff --git a/tests-clar/attr/ignore.c b/tests-clar/attr/ignore.c index aa81e9249..8df0eb9de 100644 --- a/tests-clar/attr/ignore.c +++ b/tests-clar/attr/ignore.c @@ -1,6 +1,7 @@ #include "clar_libgit2.h" #include "posix.h" #include "path.h" +#include "fileops.h" static git_repository *g_repo = NULL; @@ -20,7 +21,7 @@ void assert_is_ignored(bool expected, const char *filepath) int is_ignored; cl_git_pass(git_ignore_path_is_ignored(&is_ignored, g_repo, filepath)); - cl_assert_equal_i(expected, is_ignored == 1); + cl_assert_equal_b(expected, is_ignored); } void test_attr_ignore__honor_temporary_rules(void) @@ -46,3 +47,35 @@ void test_attr_ignore__skip_gitignore_directory(void) assert_is_ignored(true, "NewFolder/NewFolder"); assert_is_ignored(true, "NewFolder/NewFolder/File.txt"); } + +void test_attr_ignore__expand_tilde_to_homedir(void) +{ + git_buf path = GIT_BUF_INIT; + git_config *cfg; + + assert_is_ignored(false, "example.global_with_tilde"); + + /* construct fake home with fake global excludes */ + + cl_must_pass(p_mkdir("home", 0777)); + cl_git_pass(git_path_prettify(&path, "home", NULL)); + cl_git_pass(git_libgit2_opts( + GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, path.ptr)); + + cl_git_mkfile("home/globalexcludes", "# found me\n*.global_with_tilde\n"); + + cl_git_pass(git_repository_config(&cfg, g_repo)); + cl_git_pass(git_config_set_string(cfg, "core.excludesfile", "~/globalexcludes")); + git_config_free(cfg); + + git_attr_cache_flush(g_repo); /* must reset to pick up change */ + + assert_is_ignored(true, "example.global_with_tilde"); + + cl_git_pass(git_futils_rmdir_r("home", NULL, GIT_RMDIR_REMOVE_FILES)); + + cl_git_pass(git_libgit2_opts( + GIT_OPT_SET_SEARCH_PATH, GIT_CONFIG_LEVEL_GLOBAL, NULL)); + + git_buf_free(&path); +} |