diff options
author | Edward Thomson <ethomson@edwardthomson.com> | 2021-07-22 15:29:54 -0400 |
---|---|---|
committer | Edward Thomson <ethomson@edwardthomson.com> | 2021-07-22 16:40:42 -0400 |
commit | 1439b9ff05524949b6b3fa6cad716a9bb3cbc249 (patch) | |
tree | f415113d2ad056afda7ed9237d6cf9dbd73df72a | |
parent | 0bd547a8bee02bf984ea5c7acdc8172044fcb3a4 (diff) | |
download | libgit2-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.h | 12 | ||||
-rw-r--r-- | include/git2/filter.h | 12 | ||||
-rw-r--r-- | src/blob.c | 15 | ||||
-rw-r--r-- | src/filter.c | 5 | ||||
-rw-r--r-- | tests/filter/bare.c | 60 | ||||
-rw-r--r-- | tests/resources/crlf.git/objects/05/5c8729cdcc372500a08db659c045e16c4409fb | bin | 0 -> 20 bytes | |||
-rw-r--r-- | tests/resources/crlf.git/objects/1e/c507638b806aba45d6142082885f2a9e88322d | bin | 0 -> 170 bytes | |||
-rw-r--r-- | tests/resources/crlf.git/objects/44/b0be18671a284f1156117b6338edac2663341c | bin | 0 -> 658 bytes | |||
-rw-r--r-- | tests/resources/crlf.git/objects/55/1b8fce462bba005ab6d34a2244d8a3f6b03dd0 | bin | 0 -> 658 bytes | |||
-rw-r--r-- | tests/resources/crlf.git/objects/b8/986fec0f7bde90f78ac72706e782d82f24f2f0 | 3 | ||||
-rw-r--r-- | tests/resources/crlf.git/refs/heads/ident | 1 | ||||
-rw-r--r-- | tests/resources/crlf.git/refs/heads/no-ident | 1 |
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 Binary files differnew file mode 100644 index 000000000..44076ca39 --- /dev/null +++ b/tests/resources/crlf.git/objects/05/5c8729cdcc372500a08db659c045e16c4409fb diff --git a/tests/resources/crlf.git/objects/1e/c507638b806aba45d6142082885f2a9e88322d b/tests/resources/crlf.git/objects/1e/c507638b806aba45d6142082885f2a9e88322d Binary files differnew file mode 100644 index 000000000..ca97967b8 --- /dev/null +++ b/tests/resources/crlf.git/objects/1e/c507638b806aba45d6142082885f2a9e88322d diff --git a/tests/resources/crlf.git/objects/44/b0be18671a284f1156117b6338edac2663341c b/tests/resources/crlf.git/objects/44/b0be18671a284f1156117b6338edac2663341c Binary files differnew file mode 100644 index 000000000..0576e6229 --- /dev/null +++ b/tests/resources/crlf.git/objects/44/b0be18671a284f1156117b6338edac2663341c diff --git a/tests/resources/crlf.git/objects/55/1b8fce462bba005ab6d34a2244d8a3f6b03dd0 b/tests/resources/crlf.git/objects/55/1b8fce462bba005ab6d34a2244d8a3f6b03dd0 Binary files differnew file mode 100644 index 000000000..7501c88e6 --- /dev/null +++ b/tests/resources/crlf.git/objects/55/1b8fce462bba005ab6d34a2244d8a3f6b03dd0 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?13cn
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 |