diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/attr.c | 42 | ||||
-rw-r--r-- | src/attr_file.c | 101 | ||||
-rw-r--r-- | src/attr_file.h | 8 | ||||
-rw-r--r-- | src/attrcache.c | 44 | ||||
-rw-r--r-- | src/attrcache.h | 3 | ||||
-rw-r--r-- | src/ignore.c | 19 | ||||
-rw-r--r-- | src/pack-objects.c | 2 |
7 files changed, 118 insertions, 101 deletions
diff --git a/src/attr.c b/src/attr.c index 877bc873b..02a7148e8 100644 --- a/src/attr.c +++ b/src/attr.c @@ -252,15 +252,16 @@ static int preload_attr_file( git_attr_session *attr_session, git_attr_file_source source, const char *base, - const char *file) + const char *file, + bool allow_macros) { int error; git_attr_file *preload = NULL; if (!file) return 0; - if (!(error = git_attr_cache__get( - &preload, repo, attr_session, source, base, file, git_attr_file__parse_buffer))) + if (!(error = git_attr_cache__get(&preload, repo, attr_session, source, base, file, + git_attr_file__parse_buffer, allow_macros))) git_attr_file__free(preload); return error; @@ -324,31 +325,31 @@ static int attr_setup(git_repository *repo, git_attr_session *attr_session) if ((error = system_attr_file(&path, attr_session)) < 0 || (error = preload_attr_file(repo, attr_session, GIT_ATTR_FILE__FROM_FILE, - NULL, path.ptr)) < 0) { + NULL, path.ptr, true)) < 0) { if (error != GIT_ENOTFOUND) goto out; } if ((error = preload_attr_file(repo, attr_session, GIT_ATTR_FILE__FROM_FILE, - NULL, git_repository_attr_cache(repo)->cfg_attr_file)) < 0) + NULL, git_repository_attr_cache(repo)->cfg_attr_file, true)) < 0) goto out; git_buf_clear(&path); /* git_repository_item_path expects an empty buffer, because it uses git_buf_set */ if ((error = git_repository_item_path(&path, repo, GIT_REPOSITORY_ITEM_INFO)) < 0 || (error = preload_attr_file(repo, attr_session, GIT_ATTR_FILE__FROM_FILE, - path.ptr, GIT_ATTR_FILE_INREPO)) < 0) { + path.ptr, GIT_ATTR_FILE_INREPO, true)) < 0) { if (error != GIT_ENOTFOUND) goto out; } if ((workdir = git_repository_workdir(repo)) != NULL && (error = preload_attr_file(repo, attr_session, GIT_ATTR_FILE__FROM_FILE, - workdir, GIT_ATTR_FILE)) < 0) + workdir, GIT_ATTR_FILE, true)) < 0) goto out; if ((error = git_repository_index__weakptr(&idx, repo)) < 0 || (error = preload_attr_file(repo, attr_session, GIT_ATTR_FILE__FROM_INDEX, - NULL, GIT_ATTR_FILE)) < 0) + NULL, GIT_ATTR_FILE, true)) < 0) goto out; if (attr_session) @@ -436,13 +437,14 @@ static int push_attr_file( git_vector *list, git_attr_file_source source, const char *base, - const char *filename) + const char *filename, + bool allow_macros) { int error = 0; git_attr_file *file = NULL; error = git_attr_cache__get(&file, repo, attr_session, - source, base, filename, git_attr_file__parse_buffer); + source, base, filename, git_attr_file__parse_buffer, allow_macros); if (error < 0) return error; @@ -457,16 +459,18 @@ static int push_attr_file( static int push_one_attr(void *ref, const char *path) { - int error = 0, n_src, i; attr_walk_up_info *info = (attr_walk_up_info *)ref; git_attr_file_source src[2]; + int error = 0, n_src, i; + bool allow_macros; n_src = attr_decide_sources( info->flags, info->workdir != NULL, info->index != NULL, src); + allow_macros = info->workdir ? !strcmp(info->workdir, path) : false; for (i = 0; !error && i < n_src; ++i) - error = push_attr_file(info->repo, info->attr_session, - info->files, src[i], path, GIT_ATTR_FILE); + error = push_attr_file(info->repo, info->attr_session, info->files, + src[i], path, GIT_ATTR_FILE, allow_macros); return error; } @@ -515,7 +519,7 @@ static int collect_attr_files( if ((error = git_repository_item_path(&attrfile, repo, GIT_REPOSITORY_ITEM_INFO)) < 0 || (error = push_attr_file(repo, attr_session, files, GIT_ATTR_FILE__FROM_FILE, - attrfile.ptr, GIT_ATTR_FILE_INREPO)) < 0) { + attrfile.ptr, GIT_ATTR_FILE_INREPO, true)) < 0) { if (error != GIT_ENOTFOUND) goto cleanup; } @@ -537,9 +541,8 @@ static int collect_attr_files( goto cleanup; if (git_repository_attr_cache(repo)->cfg_attr_file != NULL) { - error = push_attr_file( - repo, attr_session, files, GIT_ATTR_FILE__FROM_FILE, - NULL, git_repository_attr_cache(repo)->cfg_attr_file); + error = push_attr_file(repo, attr_session, files, GIT_ATTR_FILE__FROM_FILE, + NULL, git_repository_attr_cache(repo)->cfg_attr_file, true); if (error < 0) goto cleanup; } @@ -548,9 +551,8 @@ static int collect_attr_files( error = system_attr_file(&dir, attr_session); if (!error) - error = push_attr_file( - repo, attr_session, files, GIT_ATTR_FILE__FROM_FILE, - NULL, dir.ptr); + error = push_attr_file(repo, attr_session, files, GIT_ATTR_FILE__FROM_FILE, + NULL, dir.ptr, true); else if (error == GIT_ENOTFOUND) error = 0; } diff --git a/src/attr_file.c b/src/attr_file.c index 55838370c..f8769c6e7 100644 --- a/src/attr_file.c +++ b/src/attr_file.c @@ -105,7 +105,8 @@ int git_attr_file__load( git_attr_session *attr_session, git_attr_file_entry *entry, git_attr_file_source source, - git_attr_file_parser parser) + git_attr_file_parser parser, + bool allow_macros) { int error = 0; git_blob *blob = NULL; @@ -177,7 +178,7 @@ int git_attr_file__load( if (attr_session) file->session_key = attr_session->key; - if (parser && (error = parser(repo, file, content_str)) < 0) { + if (parser && (error = parser(repo, file, content_str, allow_macros)) < 0) { git_attr_file__free(file); goto cleanup; } @@ -249,16 +250,15 @@ static bool parse_optimized_patterns( const char *pattern); int git_attr_file__parse_buffer( - git_repository *repo, git_attr_file *attrs, const char *data) + git_repository *repo, git_attr_file *attrs, const char *data, bool allow_macros) { - int error = 0; const char *scan = data, *context = NULL; git_attr_rule *rule = NULL; + int error = 0; - /* if subdir file path, convert context for file paths */ - if (attrs->entry && - git_path_root(attrs->entry->path) < 0 && - !git__suffixcmp(attrs->entry->path, "/" GIT_ATTR_FILE)) + /* If subdir file path, convert context for file paths */ + if (attrs->entry && git_path_root(attrs->entry->path) < 0 && + !git__suffixcmp(attrs->entry->path, "/" GIT_ATTR_FILE)) context = attrs->entry->path; if (git_mutex_lock(&attrs->lock) < 0) { @@ -267,38 +267,38 @@ int git_attr_file__parse_buffer( } while (!error && *scan) { - /* allocate rule if needed */ - if (!rule && !(rule = git__calloc(1, sizeof(*rule)))) { - error = -1; - break; - } - - rule->match.flags = - GIT_ATTR_FNMATCH_ALLOWNEG | GIT_ATTR_FNMATCH_ALLOWMACRO; - - /* parse the next "pattern attr attr attr" line */ - if (!(error = git_attr_fnmatch__parse( - &rule->match, &attrs->pool, context, &scan)) && - !(error = git_attr_assignment__parse( - repo, &attrs->pool, &rule->assigns, &scan))) + /* Allocate rule if needed, otherwise re-use previous rule */ + if (!rule) { + rule = git__calloc(1, sizeof(*rule)); + GIT_ERROR_CHECK_ALLOC(rule); + } else + git_attr_rule__clear(rule); + + rule->match.flags = GIT_ATTR_FNMATCH_ALLOWNEG | GIT_ATTR_FNMATCH_ALLOWMACRO; + + /* Parse the next "pattern attr attr attr" line */ + if ((error = git_attr_fnmatch__parse(&rule->match, &attrs->pool, context, &scan)) < 0 || + (error = git_attr_assignment__parse(repo, &attrs->pool, &rule->assigns, &scan)) < 0) { - if (rule->match.flags & GIT_ATTR_FNMATCH_MACRO) - /* TODO: warning if macro found in file below repo root */ - error = git_attr_cache__insert_macro(repo, rule); - else - error = git_vector_insert(&attrs->rules, rule); + if (error != GIT_ENOTFOUND) + goto out; + error = 0; + continue; } - /* if the rule wasn't a pattern, on to the next */ - if (error < 0) { - git_attr_rule__clear(rule); /* reset rule contents */ - if (error == GIT_ENOTFOUND) - error = 0; - } else { - rule = NULL; /* vector now "owns" the rule */ - } + if (rule->match.flags & GIT_ATTR_FNMATCH_MACRO) { + /* TODO: warning if macro found in file below repo root */ + if (!allow_macros) + continue; + if ((error = git_attr_cache__insert_macro(repo, rule)) < 0) + goto out; + } else if ((error = git_vector_insert(&attrs->rules, rule)) < 0) + goto out; + + rule = NULL; } +out: git_mutex_unlock(&attrs->lock); git_attr_rule__free(rule); @@ -345,33 +345,28 @@ int git_attr_file__lookup_one( int git_attr_file__load_standalone(git_attr_file **out, const char *path) { - int error; - git_attr_file *file; git_buf content = GIT_BUF_INIT; + git_attr_file *file = NULL; + int error; - error = git_attr_file__new(&file, NULL, GIT_ATTR_FILE__FROM_FILE); - if (error < 0) - return error; + if ((error = git_futils_readbuffer(&content, path)) < 0) + goto out; - error = git_attr_cache__alloc_file_entry( - &file->entry, NULL, path, &file->pool); - if (error < 0) { - git_attr_file__free(file); - return error; - } - /* because the cache entry is allocated from the file's own pool, we + /* + * Because the cache entry is allocated from the file's own pool, we * don't have to free it - freeing file+pool will free cache entry, too. */ - if (!(error = git_futils_readbuffer(&content, path))) { - error = git_attr_file__parse_buffer(NULL, file, content.ptr); - git_buf_dispose(&content); - } + if ((error = git_attr_file__new(&file, NULL, GIT_ATTR_FILE__FROM_FILE)) < 0 || + (error = git_attr_file__parse_buffer(NULL, file, content.ptr, true)) < 0 || + (error = git_attr_cache__alloc_file_entry(&file->entry, NULL, path, &file->pool)) < 0) + goto out; + *out = file; +out: if (error < 0) git_attr_file__free(file); - else - *out = file; + git_buf_dispose(&content); return error; } diff --git a/src/attr_file.h b/src/attr_file.h index 7a45516fb..9538f478d 100644 --- a/src/attr_file.h +++ b/src/attr_file.h @@ -131,7 +131,8 @@ extern int git_attr_get_many_with_session( typedef int (*git_attr_file_parser)( git_repository *repo, git_attr_file *file, - const char *data); + const char *data, + bool allow_macros); /* * git_attr_file API @@ -150,7 +151,8 @@ int git_attr_file__load( git_attr_session *attr_session, git_attr_file_entry *ce, git_attr_file_source source, - git_attr_file_parser parser); + git_attr_file_parser parser, + bool allow_macros); int git_attr_file__load_standalone( git_attr_file **out, const char *path); @@ -159,7 +161,7 @@ int git_attr_file__out_of_date( git_repository *repo, git_attr_session *session, git_attr_file *file); int git_attr_file__parse_buffer( - git_repository *repo, git_attr_file *attrs, const char *data); + git_repository *repo, git_attr_file *attrs, const char *data, bool allow_macros); int git_attr_file__clear_rules( git_attr_file *file, bool need_lock); diff --git a/src/attrcache.c b/src/attrcache.c index b88bc0930..b85202bb1 100644 --- a/src/attrcache.c +++ b/src/attrcache.c @@ -208,7 +208,8 @@ int git_attr_cache__get( git_attr_file_source source, const char *base, const char *filename, - git_attr_file_parser parser) + git_attr_file_parser parser, + bool allow_macros) { int error = 0; git_attr_cache *cache = git_repository_attr_cache(repo); @@ -221,7 +222,7 @@ int git_attr_cache__get( /* load file if we don't have one or if existing one is out of date */ if (!file || (error = git_attr_file__out_of_date(repo, attr_session, file)) > 0) - error = git_attr_file__load(&updated, repo, attr_session, entry, source, parser); + error = git_attr_file__load(&updated, repo, attr_session, entry, source, parser, allow_macros); /* if we loaded the file, insert into and/or update cache */ if (updated) { @@ -424,21 +425,36 @@ void git_attr_cache_flush(git_repository *repo) int git_attr_cache__insert_macro(git_repository *repo, git_attr_rule *macro) { git_attr_cache *cache = git_repository_attr_cache(repo); - git_strmap *macros = cache->macros; - int error; - - /* TODO: generate warning log if (macro->assigns.length == 0) */ - if (macro->assigns.length == 0) - return 0; + git_attr_rule *preexisting; + bool locked = false; + int error = 0; - if (attr_cache_lock(cache) < 0) { - git_error_set(GIT_ERROR_OS, "unable to get attr cache lock"); - error = -1; - } else { - error = git_strmap_set(macros, macro->match.pattern, macro); - git_mutex_unlock(&cache->lock); + /* + * Callers assume that if we return success, that the + * macro will have been adopted by the attributes cache. + * Thus, we have to free the macro here if it's not being + * added to the cache. + * + * TODO: generate warning log if (macro->assigns.length == 0) + */ + if (macro->assigns.length == 0) { + git_attr_rule__free(macro); + goto out; } + if ((error = attr_cache_lock(cache)) < 0) + goto out; + locked = true; + + if ((preexisting = git_strmap_get(cache->macros, macro->match.pattern)) != NULL) + git_attr_rule__free(preexisting); + + if ((error = git_strmap_set(cache->macros, macro->match.pattern, macro)) < 0) + goto out; + +out: + if (locked) + attr_cache_unlock(cache); return error; } diff --git a/src/attrcache.h b/src/attrcache.h index f528911ea..4b1d5ce31 100644 --- a/src/attrcache.h +++ b/src/attrcache.h @@ -34,7 +34,8 @@ extern int git_attr_cache__get( git_attr_file_source source, const char *base, const char *filename, - git_attr_file_parser parser); + git_attr_file_parser parser, + bool allow_macros); extern bool git_attr_cache__is_cached( git_repository *repo, diff --git a/src/ignore.c b/src/ignore.c index b17714b2c..0fdadfb13 100644 --- a/src/ignore.c +++ b/src/ignore.c @@ -163,13 +163,15 @@ out: } static int parse_ignore_file( - git_repository *repo, git_attr_file *attrs, const char *data) + git_repository *repo, git_attr_file *attrs, const char *data, bool allow_macros) { int error = 0; int ignore_case = false; const char *scan = data, *context = NULL; git_attr_fnmatch *match = NULL; + GIT_UNUSED(allow_macros); + if (git_repository__cvar(&ignore_case, repo, GIT_CVAR_IGNORECASE) < 0) git_error_clear(); @@ -244,9 +246,8 @@ static int push_ignore_file( int error = 0; git_attr_file *file = NULL; - error = git_attr_cache__get( - &file, ignores->repo, NULL, GIT_ATTR_FILE__FROM_FILE, - base, filename, parse_ignore_file); + error = git_attr_cache__get(&file, ignores->repo, NULL, GIT_ATTR_FILE__FROM_FILE, + base, filename, parse_ignore_file, false); if (error < 0) return error; @@ -272,12 +273,12 @@ static int get_internal_ignores(git_attr_file **out, git_repository *repo) if ((error = git_attr_cache__init(repo)) < 0) return error; - error = git_attr_cache__get( - out, repo, NULL, GIT_ATTR_FILE__IN_MEMORY, NULL, GIT_IGNORE_INTERNAL, NULL); + error = git_attr_cache__get(out, repo, NULL, GIT_ATTR_FILE__IN_MEMORY, NULL, + GIT_IGNORE_INTERNAL, NULL, false); /* if internal rules list is empty, insert default rules */ if (!error && !(*out)->rules.length) - error = parse_ignore_file(repo, *out, GIT_IGNORE_DEFAULT_RULES); + error = parse_ignore_file(repo, *out, GIT_IGNORE_DEFAULT_RULES, false); return error; } @@ -487,7 +488,7 @@ int git_ignore_add_rule(git_repository *repo, const char *rules) if ((error = get_internal_ignores(&ign_internal, repo)) < 0) return error; - error = parse_ignore_file(repo, ign_internal, rules); + error = parse_ignore_file(repo, ign_internal, rules, false); git_attr_file__free(ign_internal); return error; @@ -503,7 +504,7 @@ int git_ignore_clear_internal_rules(git_repository *repo) if (!(error = git_attr_file__clear_rules(ign_internal, true))) error = parse_ignore_file( - repo, ign_internal, GIT_IGNORE_DEFAULT_RULES); + repo, ign_internal, GIT_IGNORE_DEFAULT_RULES, false); git_attr_file__free(ign_internal); return error; diff --git a/src/pack-objects.c b/src/pack-objects.c index 32f51a3fd..49ded4a2e 100644 --- a/src/pack-objects.c +++ b/src/pack-objects.c @@ -223,7 +223,7 @@ int git_packbuilder_insert(git_packbuilder *pb, const git_oid *oid, if (pb->nr_objects >= pb->nr_alloc) { GIT_ERROR_CHECK_ALLOC_ADD(&newsize, pb->nr_alloc, 1024); - GIT_ERROR_CHECK_ALLOC_MULTIPLY(&newsize, newsize, 3 / 2); + GIT_ERROR_CHECK_ALLOC_MULTIPLY(&newsize, newsize / 2, 3); if (!git__is_uint32(newsize)) { git_error_set(GIT_ERROR_NOMEMORY, "packfile too large to fit in memory."); |