summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEdward Thomson <ethomson@edwardthomson.com>2021-07-22 15:29:54 -0400
committerEdward Thomson <ethomson@edwardthomson.com>2021-07-22 16:40:42 -0400
commit1439b9ff05524949b6b3fa6cad716a9bb3cbc249 (patch)
treef415113d2ad056afda7ed9237d6cf9dbd73df72a
parent0bd547a8bee02bf984ea5c7acdc8172044fcb3a4 (diff)
downloadlibgit2-1439b9ff05524949b6b3fa6cad716a9bb3cbc249.tar.gz
filter: introduce GIT_BLOB_FILTER_ATTRIBUTES_FROM_COMMIT
Provide a mechanism to filter using attribute data from a specific commit (making use of `GIT_ATTR_CHECK_INCLUDE_COMMIT`).
-rw-r--r--include/git2/blob.h12
-rw-r--r--include/git2/filter.h12
-rw-r--r--src/blob.c15
-rw-r--r--src/filter.c5
-rw-r--r--tests/filter/bare.c60
-rw-r--r--tests/resources/crlf.git/objects/05/5c8729cdcc372500a08db659c045e16c4409fbbin0 -> 20 bytes
-rw-r--r--tests/resources/crlf.git/objects/1e/c507638b806aba45d6142082885f2a9e88322dbin0 -> 170 bytes
-rw-r--r--tests/resources/crlf.git/objects/44/b0be18671a284f1156117b6338edac2663341cbin0 -> 658 bytes
-rw-r--r--tests/resources/crlf.git/objects/55/1b8fce462bba005ab6d34a2244d8a3f6b03dd0bin0 -> 658 bytes
-rw-r--r--tests/resources/crlf.git/objects/b8/986fec0f7bde90f78ac72706e782d82f24f2f03
-rw-r--r--tests/resources/crlf.git/refs/heads/ident1
-rw-r--r--tests/resources/crlf.git/refs/heads/no-ident1
12 files changed, 104 insertions, 5 deletions
diff --git a/include/git2/blob.h b/include/git2/blob.h
index 3f6738675..fceb5c771 100644
--- a/include/git2/blob.h
+++ b/include/git2/blob.h
@@ -114,6 +114,12 @@ typedef enum {
* in the HEAD commit.
*/
GIT_BLOB_FILTER_ATTRIBUTES_FROM_HEAD = (1 << 2),
+
+ /**
+ * When set, filters will be loaded from a `.gitattributes` file
+ * in the specified commit.
+ */
+ GIT_BLOB_FILTER_ATTRIBUTES_FROM_COMMIT = (1 << 3),
} git_blob_filter_flag_t;
/**
@@ -128,6 +134,12 @@ typedef struct {
/** Flags to control the filtering process, see `git_blob_filter_flag_t` above */
uint32_t flags;
+
+ /**
+ * The commit to load attributes from, when
+ * `GIT_BLOB_FILTER_ATTRIBUTES_FROM_COMMIT` is specified.
+ */
+ git_oid *commit_id;
} git_blob_filter_options;
#define GIT_BLOB_FILTER_OPTIONS_VERSION 1
diff --git a/include/git2/filter.h b/include/git2/filter.h
index 545815171..044c3b870 100644
--- a/include/git2/filter.h
+++ b/include/git2/filter.h
@@ -49,6 +49,12 @@ typedef enum {
/** Load attributes from `.gitattributes` in the root of HEAD */
GIT_FILTER_ATTRIBUTES_FROM_HEAD = (1u << 2),
+
+ /**
+ * Load attributes from `.gitattributes` in a given commit.
+ * This can only be specified in a `git_filter_options`.
+ */
+ GIT_FILTER_ATTRIBUTES_FROM_COMMIT = (1u << 3),
} git_filter_flag_t;
/**
@@ -59,6 +65,12 @@ typedef struct {
/** See `git_filter_flag_t` above */
uint32_t flags;
+
+ /**
+ * The commit to load attributes from, when
+ * `GIT_FILTER_ATTRIBUTES_FROM_COMMIT` is specified.
+ */
+ git_oid *commit_id;
} git_filter_options;
#define GIT_FILTER_OPTIONS_VERSION 1
diff --git a/src/blob.c b/src/blob.c
index 169e34503..01ebf075e 100644
--- a/src/blob.c
+++ b/src/blob.c
@@ -421,7 +421,7 @@ int git_blob_filter(
int error = 0;
git_filter_list *fl = NULL;
git_blob_filter_options opts = GIT_BLOB_FILTER_OPTIONS_INIT;
- git_filter_flag_t flags = GIT_FILTER_DEFAULT;
+ git_filter_options filter_opts = GIT_FILTER_OPTIONS_INIT;
GIT_ASSERT_ARG(blob);
GIT_ASSERT_ARG(path);
@@ -441,14 +441,19 @@ int git_blob_filter(
return 0;
if ((opts.flags & GIT_BLOB_FILTER_NO_SYSTEM_ATTRIBUTES) != 0)
- flags |= GIT_FILTER_NO_SYSTEM_ATTRIBUTES;
+ filter_opts.flags |= GIT_FILTER_NO_SYSTEM_ATTRIBUTES;
if ((opts.flags & GIT_BLOB_FILTER_ATTRIBUTES_FROM_HEAD) != 0)
- flags |= GIT_FILTER_ATTRIBUTES_FROM_HEAD;
+ filter_opts.flags |= GIT_FILTER_ATTRIBUTES_FROM_HEAD;
- if (!(error = git_filter_list_load(
+ if ((opts.flags & GIT_BLOB_FILTER_ATTRIBUTES_FROM_COMMIT) != 0) {
+ filter_opts.flags |= GIT_FILTER_ATTRIBUTES_FROM_COMMIT;
+ filter_opts.commit_id = opts.commit_id;
+ }
+
+ if (!(error = git_filter_list_load_ext(
&fl, git_blob_owner(blob), blob, path,
- GIT_FILTER_TO_WORKTREE, flags))) {
+ GIT_FILTER_TO_WORKTREE, &filter_opts))) {
error = git_filter_list_apply_to_blob(out, fl, blob);
diff --git a/src/filter.c b/src/filter.c
index 3309ab716..eed175e88 100644
--- a/src/filter.c
+++ b/src/filter.c
@@ -443,6 +443,11 @@ static int filter_list_check_attributes(
if ((src->options.flags & GIT_FILTER_ATTRIBUTES_FROM_HEAD) != 0)
attr_opts.flags |= GIT_ATTR_CHECK_INCLUDE_HEAD;
+ if ((src->options.flags & GIT_FILTER_ATTRIBUTES_FROM_COMMIT) != 0) {
+ attr_opts.flags |= GIT_ATTR_CHECK_INCLUDE_COMMIT;
+ attr_opts.commit_id = src->options.commit_id;
+ }
+
error = git_attr_get_many_with_session(
strs, repo, filter_session->attr_session, &attr_opts, src->path, fdef->nattrs, fdef->attrs);
diff --git a/tests/filter/bare.c b/tests/filter/bare.c
index 7319b5203..f8e34232f 100644
--- a/tests/filter/bare.c
+++ b/tests/filter/bare.c
@@ -132,3 +132,63 @@ void test_filter_bare__sanitizes(void)
git_blob_free(blob);
}
+void test_filter_bare__from_specific_commit_one(void)
+{
+ git_blob_filter_options opts = GIT_BLOB_FILTER_OPTIONS_INIT;
+ git_blob *blob;
+ git_buf buf = { 0 };
+ git_oid commit_id;
+
+ cl_git_pass(git_oid_fromstr(&commit_id, "b8986fec0f7bde90f78ac72706e782d82f24f2f0"));
+
+ opts.flags |= GIT_BLOB_FILTER_NO_SYSTEM_ATTRIBUTES;
+ opts.flags |= GIT_BLOB_FILTER_ATTRIBUTES_FROM_COMMIT;
+ opts.commit_id = &commit_id;
+
+ cl_git_pass(git_revparse_single(
+ (git_object **)&blob, g_repo, "055c872")); /* ident */
+
+ cl_assert_equal_s("$Id$\n", git_blob_rawcontent(blob));
+
+ cl_git_pass(git_blob_filter(&buf, blob, "ident.bin", &opts));
+ cl_assert_equal_s("$Id$\n", buf.ptr);
+
+ cl_git_pass(git_blob_filter(&buf, blob, "ident.identlf", &opts));
+ cl_assert_equal_s("$Id: 055c8729cdcc372500a08db659c045e16c4409fb $\n", buf.ptr);
+
+ git_buf_dispose(&buf);
+ git_blob_free(blob);
+}
+
+void test_filter_bare__from_specific_commit_with_no_attributes_file(void)
+{
+ git_blob_filter_options opts = GIT_BLOB_FILTER_OPTIONS_INIT;
+ git_blob *blob;
+ git_buf buf = { 0 };
+ git_oid commit_id;
+
+ cl_git_pass(git_oid_fromstr(&commit_id, "5afb6a14a864e30787857dd92af837e8cdd2cb1b"));
+
+ opts.flags |= GIT_BLOB_FILTER_NO_SYSTEM_ATTRIBUTES;
+ opts.flags |= GIT_BLOB_FILTER_ATTRIBUTES_FROM_COMMIT;
+ opts.commit_id = &commit_id;
+
+ cl_git_pass(git_revparse_single(
+ (git_object **)&blob, g_repo, "799770d")); /* all-lf */
+
+ cl_assert_equal_s(ALL_LF_TEXT_RAW, git_blob_rawcontent(blob));
+
+ cl_git_pass(git_blob_filter(&buf, blob, "file.bin", &opts));
+ cl_assert_equal_s(ALL_LF_TEXT_RAW, buf.ptr);
+
+ /* we never convert CRLF -> LF on platforms that have LF */
+ cl_git_pass(git_blob_filter(&buf, blob, "file.lf", &opts));
+ cl_assert_equal_s(ALL_LF_TEXT_RAW, buf.ptr);
+
+ /* we never convert CRLF -> LF on platforms that have LF */
+ cl_git_pass(git_blob_filter(&buf, blob, "file.crlf", &opts));
+ cl_assert_equal_s(ALL_LF_TEXT_RAW, buf.ptr);
+
+ git_buf_dispose(&buf);
+ git_blob_free(blob);
+}
diff --git a/tests/resources/crlf.git/objects/05/5c8729cdcc372500a08db659c045e16c4409fb b/tests/resources/crlf.git/objects/05/5c8729cdcc372500a08db659c045e16c4409fb
new file mode 100644
index 000000000..44076ca39
--- /dev/null
+++ b/tests/resources/crlf.git/objects/05/5c8729cdcc372500a08db659c045e16c4409fb
Binary files differ
diff --git a/tests/resources/crlf.git/objects/1e/c507638b806aba45d6142082885f2a9e88322d b/tests/resources/crlf.git/objects/1e/c507638b806aba45d6142082885f2a9e88322d
new file mode 100644
index 000000000..ca97967b8
--- /dev/null
+++ b/tests/resources/crlf.git/objects/1e/c507638b806aba45d6142082885f2a9e88322d
Binary files differ
diff --git a/tests/resources/crlf.git/objects/44/b0be18671a284f1156117b6338edac2663341c b/tests/resources/crlf.git/objects/44/b0be18671a284f1156117b6338edac2663341c
new file mode 100644
index 000000000..0576e6229
--- /dev/null
+++ b/tests/resources/crlf.git/objects/44/b0be18671a284f1156117b6338edac2663341c
Binary files differ
diff --git a/tests/resources/crlf.git/objects/55/1b8fce462bba005ab6d34a2244d8a3f6b03dd0 b/tests/resources/crlf.git/objects/55/1b8fce462bba005ab6d34a2244d8a3f6b03dd0
new file mode 100644
index 000000000..7501c88e6
--- /dev/null
+++ b/tests/resources/crlf.git/objects/55/1b8fce462bba005ab6d34a2244d8a3f6b03dd0
Binary files differ
diff --git a/tests/resources/crlf.git/objects/b8/986fec0f7bde90f78ac72706e782d82f24f2f0 b/tests/resources/crlf.git/objects/b8/986fec0f7bde90f78ac72706e782d82f24f2f0
new file mode 100644
index 000000000..d745d20e6
--- /dev/null
+++ b/tests/resources/crlf.git/objects/b8/986fec0f7bde90f78ac72706e782d82f24f2f0
@@ -0,0 +1,3 @@
+xM
+0]s%3Dt $b6FQ2McnSWU`6*CĽGw,|S,\#Y8t); qȳ
+5VG-~ۥ2=`ֲml?13 cn H]aj@U \ No newline at end of file
diff --git a/tests/resources/crlf.git/refs/heads/ident b/tests/resources/crlf.git/refs/heads/ident
new file mode 100644
index 000000000..8732f0cb9
--- /dev/null
+++ b/tests/resources/crlf.git/refs/heads/ident
@@ -0,0 +1 @@
+b8986fec0f7bde90f78ac72706e782d82f24f2f0
diff --git a/tests/resources/crlf.git/refs/heads/no-ident b/tests/resources/crlf.git/refs/heads/no-ident
new file mode 100644
index 000000000..fa9a6737b
--- /dev/null
+++ b/tests/resources/crlf.git/refs/heads/no-ident
@@ -0,0 +1 @@
+1ec507638b806aba45d6142082885f2a9e88322d