Unverified Commit 6de48085 by Edward Thomson Committed by GitHub

Merge pull request #5189 from libgit2/ethomson/attrs_from_head

Optionally read `.gitattributes` from HEAD
parents aaa48d06 cdbbb364
......@@ -119,13 +119,20 @@ GIT_EXTERN(git_attr_value_t) git_attr_value(const char *attr);
#define GIT_ATTR_CHECK_INDEX_ONLY 2
/**
* Check attribute flags: Using the system attributes file.
* Check attribute flags: controlling extended attribute behavior.
*
* Normally, attribute checks include looking in the /etc (or system
* equivalent) directory for a `gitattributes` file. Passing this
* flag will cause attribute checks to ignore that file.
* equivalent) directory for a `gitattributes` file. Passing the
* `GIT_ATTR_CHECK_NO_SYSTEM` flag will cause attribute checks to
* ignore that file.
*
* Passing the `GIT_ATTR_CHECK_INCLUDE_HEAD` flag will use attributes
* from a `.gitattributes` file in the repository at the HEAD revision.
*/
#define GIT_ATTR_CHECK_NO_SYSTEM (1 << 2)
#define GIT_ATTR_CHECK_NO_SYSTEM (1 << 2)
#define GIT_ATTR_CHECK_INCLUDE_HEAD (1 << 3)
/**
* Look up the value of one git attribute for path.
......
......@@ -97,6 +97,39 @@ GIT_EXTERN(const void *) git_blob_rawcontent(const git_blob *blob);
GIT_EXTERN(git_off_t) git_blob_rawsize(const git_blob *blob);
/**
* Flags to control the functionality of `git_blob_filter`.
*/
typedef enum {
/** When set, filters will not be applied to binary files. */
GIT_BLOB_FILTER_CHECK_FOR_BINARY = (1 << 0),
/**
* When set, filters will not load configuration from the
* system-wide `gitattributes` in `/etc` (or system equivalent).
*/
GIT_BLOB_FILTER_NO_SYSTEM_ATTRIBUTES = (1 << 1),
/**
* When set, filters will be loaded from a `.gitattributes` file
* in the HEAD commit.
*/
GIT_BLOB_FILTER_ATTTRIBUTES_FROM_HEAD = (1 << 2),
} git_blob_filter_flag_t;
/**
* The options used when applying filter options to a file.
*/
typedef struct {
int version;
/** Flags to control the filtering process */
git_blob_filter_flag_t flags;
} git_blob_filter_options;
#define GIT_BLOB_FILTER_OPTIONS_VERSION 1
#define GIT_BLOB_FILTER_OPTIONS_INIT {GIT_BLOB_FILTER_OPTIONS_VERSION, GIT_BLOB_FILTER_CHECK_FOR_BINARY}
/**
* Get a buffer with the filtered content of a blob.
*
* This applies filters as if the blob was being checked out to the
......@@ -115,15 +148,14 @@ GIT_EXTERN(git_off_t) git_blob_rawsize(const git_blob *blob);
* @param out The git_buf to be filled in
* @param blob Pointer to the blob
* @param as_path Path used for file attribute lookups, etc.
* @param check_for_binary_data Should this test if blob content contains
* NUL bytes / looks like binary data before applying filters?
* @param opts Options to use for filtering the blob
* @return 0 on success or an error code
*/
GIT_EXTERN(int) git_blob_filtered_content(
GIT_EXTERN(int) git_blob_filter(
git_buf *out,
git_blob *blob,
const char *as_path,
int check_for_binary_data);
git_blob_filter_options *opts);
/**
* Read a file from the working folder of a repository
......
......@@ -90,6 +90,13 @@ GIT_EXTERN(int) git_blob_create_fromstream_commit(
GIT_EXTERN(int) git_blob_create_frombuffer(
git_oid *id, git_repository *repo, const void *buffer, size_t len);
/** Deprecated in favor of @see git_blob_filter */
GIT_EXTERN(int) git_blob_filtered_content(
git_buf *out,
git_blob *blob,
const char *as_path,
int check_for_binary_data);
/**@}*/
/** @name Deprecated Buffer Functions
......
......@@ -40,7 +40,15 @@ typedef enum {
*/
typedef enum {
GIT_FILTER_DEFAULT = 0u,
/** Don't error for `safecrlf` violations, allow them to continue. */
GIT_FILTER_ALLOW_UNSAFE = (1u << 0),
/** Don't load `/etc/gitattributes` (or the system equivalent) */
GIT_FILTER_NO_SYSTEM_ATTRIBUTES = (1u << 1),
/** Load attributes from `.gitattributes` in the root of HEAD */
GIT_FILTER_ATTRIBUTES_FROM_HEAD = (1u << 2),
} git_filter_flag_t;
/**
......
......@@ -305,7 +305,10 @@ static int system_attr_file(
return 0;
}
static int attr_setup(git_repository *repo, git_attr_session *attr_session)
static int attr_setup(
git_repository *repo,
git_attr_session *attr_session,
uint32_t flags)
{
git_buf path = GIT_BUF_INIT;
git_index *idx = NULL;
......@@ -352,6 +355,11 @@ static int attr_setup(git_repository *repo, git_attr_session *attr_session)
NULL, GIT_ATTR_FILE, true)) < 0)
goto out;
if ((flags & GIT_ATTR_CHECK_INCLUDE_HEAD) != 0 &&
(error = preload_attr_file(repo, attr_session, GIT_ATTR_FILE__FROM_HEAD,
NULL, GIT_ATTR_FILE, true)) < 0)
goto out;
if (attr_session)
attr_session->init_setup = 1;
......@@ -428,6 +436,9 @@ static int attr_decide_sources(
break;
}
if ((flags & GIT_ATTR_CHECK_INCLUDE_HEAD) != 0)
srcs[count++] = GIT_ATTR_FILE__FROM_HEAD;
return count;
}
......@@ -460,7 +471,7 @@ static int push_attr_file(
static int push_one_attr(void *ref, const char *path)
{
attr_walk_up_info *info = (attr_walk_up_info *)ref;
git_attr_file_source src[2];
git_attr_file_source src[GIT_ATTR_FILE_NUM_SOURCES];
int error = 0, n_src, i;
bool allow_macros;
......@@ -499,7 +510,7 @@ static int collect_attr_files(
const char *workdir = git_repository_workdir(repo);
attr_walk_up_info info = { NULL };
if ((error = attr_setup(repo, attr_session)) < 0)
if ((error = attr_setup(repo, attr_session, flags)) < 0)
return error;
/* Resolve path in a non-bare repo */
......
......@@ -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;
......
......@@ -40,8 +40,9 @@ typedef enum {
GIT_ATTR_FILE__IN_MEMORY = 0,
GIT_ATTR_FILE__FROM_FILE = 1,
GIT_ATTR_FILE__FROM_INDEX = 2,
GIT_ATTR_FILE__FROM_HEAD = 3,
GIT_ATTR_FILE_NUM_SOURCES = 3
GIT_ATTR_FILE_NUM_SOURCES = 4
} git_attr_file_source;
extern const char *git_attr__true;
......
......@@ -400,25 +400,40 @@ int git_blob_is_binary(const git_blob *blob)
return git_buf_text_is_binary(&content);
}
int git_blob_filtered_content(
int git_blob_filter(
git_buf *out,
git_blob *blob,
const char *path,
int check_for_binary_data)
git_blob_filter_options *given_opts)
{
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;
assert(blob && path && out);
git_buf_sanitize(out);
if (check_for_binary_data && git_blob_is_binary(blob))
GIT_ERROR_CHECK_VERSION(
given_opts, GIT_BLOB_FILTER_OPTIONS_VERSION, "git_blob_filter_options");
if (given_opts != NULL)
memcpy(&opts, given_opts, sizeof(git_blob_filter_options));
if ((opts.flags & GIT_BLOB_FILTER_CHECK_FOR_BINARY) != 0 &&
git_blob_is_binary(blob))
return 0;
if ((opts.flags & GIT_BLOB_FILTER_NO_SYSTEM_ATTRIBUTES) != 0)
flags |= GIT_FILTER_NO_SYSTEM_ATTRIBUTES;
if ((opts.flags & GIT_BLOB_FILTER_ATTTRIBUTES_FROM_HEAD) != 0)
flags |= GIT_FILTER_ATTRIBUTES_FROM_HEAD;
if (!(error = git_filter_list_load(
&fl, git_blob_owner(blob), blob, path,
GIT_FILTER_TO_WORKTREE, GIT_FILTER_DEFAULT))) {
GIT_FILTER_TO_WORKTREE, flags))) {
error = git_filter_list_apply_to_blob(out, fl, blob);
......@@ -460,3 +475,19 @@ int git_blob_create_fromstream_commit(
{
return git_blob_create_from_stream_commit(out, stream);
}
int git_blob_filtered_content(
git_buf *out,
git_blob *blob,
const char *path,
int check_for_binary_data)
{
git_blob_filter_options opts = GIT_BLOB_FILTER_OPTIONS_INIT;
if (check_for_binary_data)
opts.flags |= GIT_BLOB_FILTER_CHECK_FOR_BINARY;
else
opts.flags &= ~GIT_BLOB_FILTER_CHECK_FOR_BINARY;
return git_blob_filter(out, blob, path, &opts);
}
......@@ -428,13 +428,21 @@ static int filter_list_check_attributes(
git_filter_def *fdef,
const git_filter_source *src)
{
int error;
size_t i;
const char **strs = git__calloc(fdef->nattrs, sizeof(const char *));
uint32_t flags = 0;
size_t i;
int error;
GIT_ERROR_CHECK_ALLOC(strs);
if ((src->flags & GIT_FILTER_NO_SYSTEM_ATTRIBUTES) != 0)
flags |= GIT_ATTR_CHECK_NO_SYSTEM;
if ((src->flags & GIT_FILTER_ATTRIBUTES_FROM_HEAD) != 0)
flags |= GIT_ATTR_CHECK_INCLUDE_HEAD;
error = git_attr_get_many_with_session(
strs, repo, attr_session, 0, src->path, fdef->nattrs, fdef->attrs);
strs, repo, attr_session, flags, src->path, fdef->nattrs, fdef->attrs);
/* if no values were found but no matches are needed, it's okay! */
if (error == GIT_ENOTFOUND && !fdef->nmatches) {
......
#include "clar_libgit2.h"
#include "crlf.h"
static git_repository *g_repo = NULL;
static git_blob_filter_options filter_opts = GIT_BLOB_FILTER_OPTIONS_INIT;
void test_filter_bare__initialize(void)
{
cl_fixture_sandbox("crlf.git");
cl_git_pass(git_repository_open(&g_repo, "crlf.git"));
filter_opts.flags |= GIT_BLOB_FILTER_NO_SYSTEM_ATTRIBUTES;
filter_opts.flags |= GIT_BLOB_FILTER_ATTTRIBUTES_FROM_HEAD;
}
void test_filter_bare__cleanup(void)
{
git_repository_free(g_repo);
cl_fixture_cleanup("crlf.git");
}
void test_filter_bare__all_crlf(void)
{
git_blob *blob;
git_buf buf = { 0 };
cl_git_pass(git_revparse_single(
(git_object **)&blob, g_repo, "a9a2e89")); /* all-crlf */
cl_assert_equal_s(ALL_CRLF_TEXT_RAW, git_blob_rawcontent(blob));
cl_git_pass(git_blob_filter(&buf, blob, "file.bin", &filter_opts));
cl_assert_equal_s(ALL_CRLF_TEXT_RAW, buf.ptr);
cl_git_pass(git_blob_filter(&buf, blob, "file.crlf", &filter_opts));
/* in this case, raw content has crlf in it already */
cl_assert_equal_s(ALL_CRLF_TEXT_AS_CRLF, buf.ptr);
cl_git_pass(git_blob_filter(&buf, blob, "file.lf", &filter_opts));
/* we never convert CRLF -> LF on platforms that have LF */
cl_assert_equal_s(ALL_CRLF_TEXT_AS_CRLF, buf.ptr);
cl_git_pass(git_blob_filter(&buf, blob, "file.txt", &filter_opts));
/* in this case, raw content has crlf in it already */
cl_assert_equal_s(ALL_CRLF_TEXT_AS_CRLF, buf.ptr);
git_buf_dispose(&buf);
git_blob_free(blob);
}
void test_filter_bare__from_lf(void)
{
git_blob *blob;
git_buf buf = { 0 };
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", &filter_opts));
cl_assert_equal_s(ALL_LF_TEXT_RAW, buf.ptr);
cl_git_pass(git_blob_filter(&buf, blob, "file.crlf", &filter_opts));
/* in this case, raw content has crlf in it already */
cl_assert_equal_s(ALL_LF_TEXT_AS_CRLF, buf.ptr);
cl_git_pass(git_blob_filter(&buf, blob, "file.lf", &filter_opts));
/* we never convert CRLF -> LF on platforms that have LF */
cl_assert_equal_s(ALL_LF_TEXT_AS_LF, buf.ptr);
git_buf_dispose(&buf);
git_blob_free(blob);
}
void test_filter_bare__nested_attributes(void)
{
git_blob *blob;
git_buf buf = { 0 };
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, "raw/file.bin", &filter_opts));
cl_assert_equal_s(ALL_LF_TEXT_RAW, buf.ptr);
cl_git_pass(git_blob_filter(&buf, blob, "raw/file.crlf", &filter_opts));
cl_assert_equal_s(ALL_LF_TEXT_RAW, buf.ptr);
cl_git_pass(git_blob_filter(&buf, blob, "raw/file.lf", &filter_opts));
cl_assert_equal_s(ALL_LF_TEXT_RAW, buf.ptr);
git_buf_dispose(&buf);
git_blob_free(blob);
}
void test_filter_bare__sanitizes(void)
{
git_blob *blob;
git_buf buf = GIT_BUF_INIT;
cl_git_pass(git_revparse_single(
(git_object **)&blob, g_repo, "e69de29")); /* zero-byte */
cl_assert_equal_i(0, git_blob_rawsize(blob));
cl_assert_equal_s("", git_blob_rawcontent(blob));
cl_git_pass(git_blob_filter(&buf, blob, "file.bin", &filter_opts));
cl_assert_equal_sz(0, buf.size);
cl_assert_equal_s("", buf.ptr);
git_buf_dispose(&buf);
cl_git_pass(git_blob_filter(&buf, blob, "file.crlf", &filter_opts));
cl_assert_equal_sz(0, buf.size);
cl_assert_equal_s("", buf.ptr);
git_buf_dispose(&buf);
cl_git_pass(git_blob_filter(&buf, blob, "file.lf", &filter_opts));
cl_assert_equal_sz(0, buf.size);
cl_assert_equal_s("", buf.ptr);
git_buf_dispose(&buf);
git_blob_free(blob);
}
......@@ -30,16 +30,16 @@ void test_filter_blob__all_crlf(void)
cl_assert_equal_s(ALL_CRLF_TEXT_RAW, git_blob_rawcontent(blob));
cl_git_pass(git_blob_filtered_content(&buf, blob, "file.bin", 1));
cl_git_pass(git_blob_filter(&buf, blob, "file.bin", NULL));
cl_assert_equal_s(ALL_CRLF_TEXT_RAW, buf.ptr);
cl_git_pass(git_blob_filtered_content(&buf, blob, "file.crlf", 1));
cl_git_pass(git_blob_filter(&buf, blob, "file.crlf", NULL));
/* in this case, raw content has crlf in it already */
cl_assert_equal_s(ALL_CRLF_TEXT_AS_CRLF, buf.ptr);
cl_git_pass(git_blob_filtered_content(&buf, blob, "file.lf", 1));
cl_git_pass(git_blob_filter(&buf, blob, "file.lf", NULL));
/* we never convert CRLF -> LF on platforms that have LF */
cl_assert_equal_s(ALL_CRLF_TEXT_AS_CRLF, buf.ptr);
......@@ -48,6 +48,34 @@ void test_filter_blob__all_crlf(void)
git_blob_free(blob);
}
void test_filter_blob__from_lf(void)
{
git_blob *blob;
git_buf buf = { 0 };
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", NULL));
cl_assert_equal_s(ALL_LF_TEXT_RAW, buf.ptr);
cl_git_pass(git_blob_filter(&buf, blob, "file.crlf", NULL));
/* in this case, raw content has crlf in it already */
cl_assert_equal_s(ALL_LF_TEXT_AS_CRLF, buf.ptr);
cl_git_pass(git_blob_filter(&buf, blob, "file.lf", NULL));
/* we never convert CRLF -> LF on platforms that have LF */
cl_assert_equal_s(ALL_LF_TEXT_AS_LF, buf.ptr);
git_buf_dispose(&buf);
git_blob_free(blob);
}
void test_filter_blob__sanitizes(void)
{
git_blob *blob;
......@@ -60,19 +88,19 @@ void test_filter_blob__sanitizes(void)
cl_assert_equal_s("", git_blob_rawcontent(blob));
memset(&buf, 0, sizeof(git_buf));
cl_git_pass(git_blob_filtered_content(&buf, blob, "file.bin", 1));
cl_git_pass(git_blob_filter(&buf, blob, "file.bin", NULL));
cl_assert_equal_sz(0, buf.size);
cl_assert_equal_s("", buf.ptr);
git_buf_dispose(&buf);
memset(&buf, 0, sizeof(git_buf));
cl_git_pass(git_blob_filtered_content(&buf, blob, "file.crlf", 1));
cl_git_pass(git_blob_filter(&buf, blob, "file.crlf", NULL));
cl_assert_equal_sz(0, buf.size);
cl_assert_equal_s("", buf.ptr);
git_buf_dispose(&buf);
memset(&buf, 0, sizeof(git_buf));
cl_git_pass(git_blob_filtered_content(&buf, blob, "file.lf", 1));
cl_git_pass(git_blob_filter(&buf, blob, "file.lf", NULL));
cl_assert_equal_sz(0, buf.size);
cl_assert_equal_s("", buf.ptr);
git_buf_dispose(&buf);
......@@ -99,15 +127,15 @@ void test_filter_blob__ident(void)
cl_assert_equal_s(
"Some text\n$Id$\nGoes there\n", git_blob_rawcontent(blob));
cl_git_pass(git_blob_filtered_content(&buf, blob, "filter.bin", 1));
cl_git_pass(git_blob_filter(&buf, blob, "filter.bin", NULL));
cl_assert_equal_s(
"Some text\n$Id$\nGoes there\n", buf.ptr);
cl_git_pass(git_blob_filtered_content(&buf, blob, "filter.identcrlf", 1));
cl_git_pass(git_blob_filter(&buf, blob, "filter.identcrlf", NULL));
cl_assert_equal_s(
"Some text\r\n$Id: 3164f585d548ac68027d22b104f2d8100b2b6845 $\r\nGoes there\r\n", buf.ptr);
cl_git_pass(git_blob_filtered_content(&buf, blob, "filter.identlf", 1));
cl_git_pass(git_blob_filter(&buf, blob, "filter.identlf", NULL));
cl_assert_equal_s(
"Some text\n$Id: 3164f585d548ac68027d22b104f2d8100b2b6845 $\nGoes there\n", buf.ptr);
......
......@@ -208,7 +208,7 @@ void test_filter_custom__order_dependency(void)
& git_index_get_bypath(index, "hero.1.rev-ident", 0)->id));
cl_assert_equal_s(
"\n!nuf evaH\n$dI$\ntset a si sihT", git_blob_rawcontent(blob));
cl_git_pass(git_blob_filtered_content(&buf, blob, "hero.1.rev-ident", 0));
cl_git_pass(git_blob_filter(&buf, blob, "hero.1.rev-ident", NULL));
/* no expansion because id was reversed at checkin and now at ident
* time, reverse is not applied yet */
cl_assert_equal_s(
......@@ -219,7 +219,7 @@ void test_filter_custom__order_dependency(void)
& git_index_get_bypath(index, "hero.2.rev-ident", 0)->id));
cl_assert_equal_s(
"\n!yzarC\n$Id$\ntset rehtonA", git_blob_rawcontent(blob));
cl_git_pass(git_blob_filtered_content(&buf, blob, "hero.2.rev-ident", 0));
cl_git_pass(git_blob_filter(&buf, blob, "hero.2.rev-ident", NULL));
/* expansion because reverse was applied at checkin and at ident time,
* reverse is not applied yet */
cl_assert_equal_s(
......
#include "clar_libgit2.h"
#include "crlf.h"
#include "path.h"
static git_repository *g_repo = NULL;
static git_buf system_attr_path = GIT_BUF_INIT;
void test_filter_systemattrs__initialize(void)
{
g_repo = cl_git_sandbox_init("crlf");
cl_must_pass(p_unlink("crlf/.gitattributes"));
cl_git_pass(git_libgit2_opts(
GIT_OPT_GET_SEARCH_PATH, GIT_CONFIG_LEVEL_SYSTEM, &system_attr_path));
cl_git_pass(git_buf_joinpath(&system_attr_path,
system_attr_path.ptr, "gitattributes"));
cl_git_mkfile(system_attr_path.ptr,
"*.txt text\n"
"*.bin binary\n"
"*.crlf text eol=crlf\n"
"*.lf text eol=lf\n");
}
void test_filter_systemattrs__cleanup(void)
{
cl_must_pass(p_unlink(system_attr_path.ptr));
git_buf_dispose(&system_attr_path);
cl_git_sandbox_cleanup();
}
void test_filter_systemattrs__reads_system_attributes(void)
{
git_blob *blob;
git_buf buf = { 0 };
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", NULL));
cl_assert_equal_s(ALL_LF_TEXT_RAW, buf.ptr);
cl_git_pass(git_blob_filter(&buf, blob, "file.crlf", NULL));
cl_assert_equal_s(ALL_LF_TEXT_AS_CRLF, buf.ptr);
cl_git_pass(git_blob_filter(&buf, blob, "file.lf", NULL));
cl_assert_equal_s(ALL_LF_TEXT_AS_LF, buf.ptr);
git_buf_dispose(&buf);
git_blob_free(blob);
}
void test_filter_systemattrs__disables_system_attributes(void)
{
git_blob *blob;
git_buf buf = { 0 };
git_blob_filter_options opts = GIT_BLOB_FILTER_OPTIONS_INIT;
opts.flags |= GIT_BLOB_FILTER_NO_SYSTEM_ATTRIBUTES;
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);
/* No attributes mean these are all treated literally */
cl_git_pass(git_blob_filter(&buf, blob, "file.crlf", &opts));
cl_assert_equal_s(ALL_LF_TEXT_RAW, buf.ptr);
cl_git_pass(git_blob_filter(&buf, blob, "file.lf", &opts));
cl_assert_equal_s(ALL_LF_TEXT_RAW, buf.ptr);
git_buf_dispose(&buf);
git_blob_free(blob);
}
ref: refs/heads/master
[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true
ignorecase = true
precomposeunicode = true
[remote "origin"]
url = /Users/ethomson/libgit2/libgit2-3/tests/resources/crlf.git
fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
remote = origin
merge = refs/heads/master
0000000000000000000000000000000000000000 6b9d5748663795f573ea857276eb2a5f8330efa0 Edward Thomson <ethomson@edwardthomson.com> 1563721143 +0100 clone: from /Users/ethomson/libgit2/libgit2-3/tests/resources/crlf.git
6b9d5748663795f573ea857276eb2a5f8330efa0 124f4293444614aa8da53be149792c2e43e9bfd9 Edward Thomson <ethomson@edwardthomson.com> 1563721187 +0100 commit: subdir with no translation
0000000000000000000000000000000000000000 6b9d5748663795f573ea857276eb2a5f8330efa0 Edward Thomson <ethomson@edwardthomson.com> 1563721143 +0100 clone: from /Users/ethomson/libgit2/libgit2-3/tests/resources/crlf.git
6b9d5748663795f573ea857276eb2a5f8330efa0 124f4293444614aa8da53be149792c2e43e9bfd9 Edward Thomson <ethomson@edwardthomson.com> 1563721187 +0100 commit: subdir with no translation
0000000000000000000000000000000000000000 6b9d5748663795f573ea857276eb2a5f8330efa0 Edward Thomson <ethomson@edwardthomson.com> 1563721143 +0100 clone: from /Users/ethomson/libgit2/libgit2-3/tests/resources/crlf.git
# pack-refs with: peeled fully-peeled sorted
9687e444bcbb85645cb496080434c292f1b57182 refs/remotes/origin/empty-files
6b9d5748663795f573ea857276eb2a5f8330efa0 refs/remotes/origin/master
9687e444bcbb85645cb496080434c292f1b57182
124f4293444614aa8da53be149792c2e43e9bfd9
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment