int git_attr_file__parse_buffer( git_repository *repo, const char *buffer, git_attr_file *attrs) { int error = 0; const char *scan = NULL; char *context = NULL; git_attr_rule *rule = NULL; assert(buffer && attrs); scan = buffer; /* if subdir file path, convert context for file paths */ if (attrs->key && git__suffixcmp(attrs->key, "/" GIT_ATTR_FILE) == 0) { context = attrs->key + 2; context[strlen(context) - strlen(GIT_ATTR_FILE)] = '\0'; } while (!error && *scan) { /* allocate rule if needed */ if (!rule && !(rule = git__calloc(1, sizeof(git_attr_rule)))) { error = -1; break; } /* 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))) { if (rule->match.flags & GIT_ATTR_FNMATCH_MACRO) /* should generate error/warning if this is coming from any * file other than .gitattributes at repo root. */ error = git_attr_cache__insert_macro(repo, rule); else error = git_vector_insert(&attrs->rules, rule); } /* 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 */ } } git_attr_rule__free(rule); /* restore file path used for context */ if (context) context[strlen(context)] = '.'; /* first char of GIT_ATTR_FILE */ return error; }
int git_attr_file__parse_buffer( git_repository *repo, git_attr_file *attrs, const char *data) { int error = 0; const char *scan = data, *context = NULL; git_attr_rule *rule = NULL; /* 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) { giterr_set(GITERR_OS, "Failed to lock attribute file"); return -1; } 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))) { 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 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 */ } } git_mutex_unlock(&attrs->lock); git_attr_rule__free(rule); return error; }
void git_attr_file__clear_rules(git_attr_file *file) { unsigned int i; git_attr_rule *rule; git_vector_foreach(&file->rules, i, rule) git_attr_rule__free(rule); git_vector_free(&file->rules); }
int git_attr_file__clear_rules(git_attr_file *file, bool need_lock) { unsigned int i; git_attr_rule *rule; if (need_lock && git_mutex_lock(&file->lock) < 0) { giterr_set(GITERR_OS, "Failed to lock attribute file"); return -1; } git_vector_foreach(&file->rules, i, rule) git_attr_rule__free(rule); git_vector_free(&file->rules); if (need_lock) git_mutex_unlock(&file->lock); return 0; }
void git_attr_file__free(git_attr_file *file) { unsigned int i; git_attr_rule *rule; if (!file) return; git_vector_foreach(&file->rules, i, rule) git_attr_rule__free(rule); git_vector_free(&file->rules); if (file->pool_is_allocated) { git_pool_clear(file->pool); git__free(file->pool); } file->pool = NULL; git__free(file); }