summaryrefslogtreecommitdiff
path: root/src/attr_file.c
diff options
context:
space:
mode:
authorEdward Thomson <ethomson@edwardthomson.com>2019-07-21 14:11:03 +0100
committerEdward Thomson <ethomson@edwardthomson.com>2019-08-11 20:47:59 +0100
commit4fd5748c4bbc0fba3db9fb2fb20e01261339b9d9 (patch)
tree77da3e9a547b5b9bad7c6bbd4e2f6a05f12f560c /src/attr_file.c
parenta5392eae3d40dc7789de581406e35a1ce7487e1e (diff)
downloadlibgit2-4fd5748c4bbc0fba3db9fb2fb20e01261339b9d9.tar.gz
attr: optionally read attributes from repository
When `GIT_ATTR_CHECK_INCLUDE_HEAD` is specified, read `gitattribute` files that are checked into the repository at the HEAD revision.
Diffstat (limited to 'src/attr_file.c')
-rw-r--r--src/attr_file.c43
1 files changed, 40 insertions, 3 deletions
diff --git a/src/attr_file.c b/src/attr_file.c
index f8769c6e7..a1b4c7324 100644
--- a/src/attr_file.c
+++ b/src/attr_file.c
@@ -109,6 +109,8 @@ int git_attr_file__load(
bool allow_macros)
{
int error = 0;
+ git_tree *tree = NULL;
+ git_tree_entry *tree_entry = NULL;
git_blob *blob = NULL;
git_buf content = GIT_BUF_INIT;
const char *content_str;
@@ -117,6 +119,8 @@ int git_attr_file__load(
bool nonexistent = false;
int bom_offset;
git_bom_t bom;
+ git_oid id;
+ git_off_t blobsize;
*out = NULL;
@@ -125,9 +129,6 @@ int git_attr_file__load(
/* in-memory attribute file doesn't need data */
break;
case GIT_ATTR_FILE__FROM_INDEX: {
- git_oid id;
- git_off_t blobsize;
-
if ((error = attr_file_oid_from_index(&id, repo, entry->path)) < 0 ||
(error = git_blob_lookup(&blob, repo, &id)) < 0)
return error;
@@ -157,6 +158,25 @@ int git_attr_file__load(
break;
}
+ case GIT_ATTR_FILE__FROM_HEAD: {
+ if ((error = git_repository_head_tree(&tree, repo)) < 0 ||
+ (error = git_tree_entry_bypath(&tree_entry, tree, entry->path)) < 0 ||
+ (error = git_blob_lookup(&blob, repo, git_tree_entry_id(tree_entry))) < 0)
+ goto cleanup;
+
+ /*
+ * Do not assume that data straight from the ODB is NULL-terminated;
+ * copy the contents of a file to a buffer to work on.
+ */
+ blobsize = git_blob_rawsize(blob);
+
+ GIT_ERROR_CHECK_BLOBSIZE(blobsize);
+ if ((error = git_buf_put(&content,
+ git_blob_rawcontent(blob), (size_t)blobsize)) < 0)
+ goto cleanup;
+
+ break;
+ }
default:
git_error_set(GIT_ERROR_INVALID, "unknown file source %d", source);
return -1;
@@ -188,6 +208,8 @@ int git_attr_file__load(
file->nonexistent = 1;
else if (source == GIT_ATTR_FILE__FROM_INDEX)
git_oid_cpy(&file->cache_data.oid, git_blob_id(blob));
+ else if (source == GIT_ATTR_FILE__FROM_HEAD)
+ git_oid_cpy(&file->cache_data.oid, git_tree_id(tree));
else if (source == GIT_ATTR_FILE__FROM_FILE)
git_futils_filestamp_set_from_stat(&file->cache_data.stamp, &st);
/* else always cacheable */
@@ -196,6 +218,8 @@ int git_attr_file__load(
cleanup:
git_blob_free(blob);
+ git_tree_entry_free(tree_entry);
+ git_tree_free(tree);
git_buf_dispose(&content);
return error;
@@ -236,6 +260,19 @@ int git_attr_file__out_of_date(
return (git_oid__cmp(&file->cache_data.oid, &id) != 0);
}
+ case GIT_ATTR_FILE__FROM_HEAD: {
+ git_tree *tree;
+ int error;
+
+ if ((error = git_repository_head_tree(&tree, repo)) < 0)
+ return error;
+
+ error = git_oid__cmp(&file->cache_data.oid, git_tree_id(tree));
+
+ git_tree_free(tree);
+ return error;
+ }
+
default:
git_error_set(GIT_ERROR_INVALID, "invalid file type %d", file->source);
return -1;