Commit 96dc1ffdc864c883e632989d75c32f602b107c83

Edward Thomson 2021-05-22T20:14:47

attr: the attr source is now a struct We may want to extend the attribute source; use a structure instead of an enum.

diff --git a/src/attr_file.c b/src/attr_file.c
index f6f1d33..db16a47 100644
--- a/src/attr_file.c
+++ b/src/attr_file.c
@@ -33,7 +33,7 @@ static void attr_file_free(git_attr_file *file)
 int git_attr_file__new(
 	git_attr_file **out,
 	git_attr_file_entry *entry,
-	git_attr_file_source_t source_type)
+	git_attr_file_source *source)
 {
 	git_attr_file *attrs = git__calloc(1, sizeof(git_attr_file));
 	GIT_ERROR_CHECK_ALLOC(attrs);
@@ -48,7 +48,7 @@ int git_attr_file__new(
 
 	GIT_REFCOUNT_INC(attrs);
 	attrs->entry = entry;
-	attrs->source_type = source_type;
+	memcpy(&attrs->source, source, sizeof(git_attr_file_source));
 	*out = attrs;
 	return 0;
 
@@ -108,7 +108,7 @@ int git_attr_file__load(
 	git_repository *repo,
 	git_attr_session *attr_session,
 	git_attr_file_entry *entry,
-	git_attr_file_source_t source_type,
+	git_attr_file_source *source,
 	git_attr_file_parser parser,
 	bool allow_macros)
 {
@@ -128,7 +128,7 @@ int git_attr_file__load(
 
 	*out = NULL;
 
-	switch (source_type) {
+	switch (source->type) {
 	case GIT_ATTR_FILE_SOURCE_MEMORY:
 		/* in-memory attribute file doesn't need data */
 		break;
@@ -182,11 +182,11 @@ int git_attr_file__load(
 		break;
 	}
 	default:
-		git_error_set(GIT_ERROR_INVALID, "unknown file source %d", source_type);
+		git_error_set(GIT_ERROR_INVALID, "unknown file source %d", source->type);
 		return -1;
 	}
 
-	if ((error = git_attr_file__new(&file, entry, source_type)) < 0)
+	if ((error = git_attr_file__new(&file, entry, source)) < 0)
 		goto cleanup;
 
 	/* advance over a UTF8 BOM */
@@ -210,11 +210,11 @@ int git_attr_file__load(
 	/* write cache breakers */
 	if (nonexistent)
 		file->nonexistent = 1;
-	else if (source_type == GIT_ATTR_FILE_SOURCE_INDEX)
+	else if (source->type == GIT_ATTR_FILE_SOURCE_INDEX)
 		git_oid_cpy(&file->cache_data.oid, git_blob_id(blob));
-	else if (source_type == GIT_ATTR_FILE_SOURCE_HEAD)
+	else if (source->type == GIT_ATTR_FILE_SOURCE_HEAD)
 		git_oid_cpy(&file->cache_data.oid, git_tree_id(tree));
-	else if (source_type == GIT_ATTR_FILE_SOURCE_FILE)
+	else if (source->type == GIT_ATTR_FILE_SOURCE_FILE)
 		git_futils_filestamp_set_from_stat(&file->cache_data.stamp, &st);
 	/* else always cacheable */
 
@@ -245,7 +245,7 @@ int git_attr_file__out_of_date(
 	else if (file->nonexistent)
 		return 1;
 
-	switch (file->source_type) {
+	switch (file->source.type) {
 	case GIT_ATTR_FILE_SOURCE_MEMORY:
 		return 0;
 
@@ -278,7 +278,7 @@ int git_attr_file__out_of_date(
 	}
 
 	default:
-		git_error_set(GIT_ERROR_INVALID, "invalid file type %d", file->source_type);
+		git_error_set(GIT_ERROR_INVALID, "invalid file type %d", file->source.type);
 		return -1;
 	}
 }
@@ -389,6 +389,7 @@ int git_attr_file__lookup_one(
 int git_attr_file__load_standalone(git_attr_file **out, const char *path)
 {
 	git_buf content = GIT_BUF_INIT;
+	git_attr_file_source source = { GIT_ATTR_FILE_SOURCE_FILE };
 	git_attr_file *file = NULL;
 	int error;
 
@@ -400,7 +401,7 @@ int git_attr_file__load_standalone(git_attr_file **out, const char *path)
 	 * don't have to free it - freeing file+pool will free cache entry, too.
 	 */
 
-	if ((error = git_attr_file__new(&file, NULL, GIT_ATTR_FILE_SOURCE_FILE)) < 0 ||
+	if ((error = git_attr_file__new(&file, NULL, &source)) < 0 ||
 	    (error = git_attr_file__parse_buffer(NULL, file, content.ptr, true)) < 0 ||
 	    (error = git_attr_cache__alloc_file_entry(&file->entry, NULL, NULL, path, &file->pool)) < 0)
 		goto out;
diff --git a/src/attr_file.h b/src/attr_file.h
index 330aed3..6f5318d 100644
--- a/src/attr_file.h
+++ b/src/attr_file.h
@@ -45,6 +45,10 @@ typedef enum {
 	GIT_ATTR_FILE_NUM_SOURCES   = 4
 } git_attr_file_source_t;
 
+typedef struct {
+	git_attr_file_source_t type;
+} git_attr_file_source;
+
 extern const char *git_attr__true;
 extern const char *git_attr__false;
 extern const char *git_attr__unset;
@@ -81,7 +85,7 @@ typedef struct {
 	git_refcount rc;
 	git_mutex lock;
 	git_attr_file_entry *entry;
-	git_attr_file_source_t source_type;
+	git_attr_file_source source;
 	git_vector rules;			/* vector of <rule*> or <fnmatch*> */
 	git_pool pool;
 	unsigned int nonexistent:1;
@@ -142,7 +146,7 @@ typedef int (*git_attr_file_parser)(
 int git_attr_file__new(
 	git_attr_file **out,
 	git_attr_file_entry *entry,
-	git_attr_file_source_t source_type);
+	git_attr_file_source *source);
 
 void git_attr_file__free(git_attr_file *file);
 
@@ -151,7 +155,7 @@ int git_attr_file__load(
 	git_repository *repo,
 	git_attr_session *attr_session,
 	git_attr_file_entry *ce,
-	git_attr_file_source_t source_type,
+	git_attr_file_source *source,
 	git_attr_file_parser parser,
 	bool allow_macros);
 
diff --git a/src/attrcache.c b/src/attrcache.c
index 322e601..1f842c6 100644
--- a/src/attrcache.c
+++ b/src/attrcache.c
@@ -112,7 +112,7 @@ static int attr_cache_upsert(git_attr_cache *cache, git_attr_file *file)
 	 * Replace the existing value if another thread has
 	 * created it in the meantime.
 	 */
-	old = git_atomic_swap(entry->file[file->source_type], file);
+	old = git_atomic_swap(entry->file[file->source.type], file);
 
 	if (old) {
 		GIT_REFCOUNT_OWN(old, NULL);
@@ -136,7 +136,7 @@ static int attr_cache_remove(git_attr_cache *cache, git_attr_file *file)
 		return error;
 
 	if ((entry = attr_cache_lookup_entry(cache, file->entry->path)) != NULL)
-		old = git_atomic_compare_and_swap(&entry->file[file->source_type], file, NULL);
+		old = git_atomic_compare_and_swap(&entry->file[file->source.type], file, NULL);
 
 	attr_cache_unlock(cache);
 
@@ -220,6 +220,7 @@ int git_attr_cache__get(
 	git_attr_cache *cache = git_repository_attr_cache(repo);
 	git_attr_file_entry *entry = NULL;
 	git_attr_file *file = NULL, *updated = NULL;
+	git_attr_file_source source = { source_type };
 
 	if ((error = attr_cache_lookup(&file, &entry, repo, attr_session,
 	                               source_type, base, filename)) < 0)
@@ -228,7 +229,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_type, parser,
+		                            entry, &source, parser,
 		                            allow_macros);
 
 	/* if we loaded the file, insert into and/or update cache */
diff --git a/tests/attr/lookup.c b/tests/attr/lookup.c
index 29a66b0..bfb2e87 100644
--- a/tests/attr/lookup.c
+++ b/tests/attr/lookup.c
@@ -236,6 +236,7 @@ void test_attr_lookup__check_attr_examples(void)
 void test_attr_lookup__from_buffer(void)
 {
 	git_attr_file *file;
+	git_attr_file_source source = {0};
 
 	struct attr_expected cases[] = {
 		{ "abc", "foo", EXPECT_TRUE, NULL },
@@ -250,7 +251,7 @@ void test_attr_lookup__from_buffer(void)
 		{ NULL, NULL, 0, NULL }
 	};
 
-	cl_git_pass(git_attr_file__new(&file, NULL, 0));
+	cl_git_pass(git_attr_file__new(&file, NULL, &source));
 
 	cl_git_pass(git_attr_file__parse_buffer(NULL, file, "a* foo\nabc bar\n* baz", true));