Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 24 additions & 1 deletion src/libfetchers/git-utils.cc
Original file line number Diff line number Diff line change
Expand Up @@ -668,6 +668,7 @@ struct GitSourceAccessor : SourceAccessor
struct State
{
ref<GitRepoImpl> repo;
std::string gitRev;
Object root;
std::optional<lfs::Fetch> lfsFetch = std::nullopt;
};
Expand All @@ -678,6 +679,7 @@ struct GitSourceAccessor : SourceAccessor
: state_{
State {
.repo = repo_,
.gitRev = rev.gitRev(),
.root = peelToTreeOrBlob(lookupObject(*repo_, hashToOID(rev)).get()),
.lfsFetch = smudgeLfs ? std::make_optional(lfs::Fetch(*repo_, hashToOID(rev))) : std::nullopt,
}
Expand Down Expand Up @@ -707,7 +709,28 @@ struct GitSourceAccessor : SourceAccessor
}
}

return std::string((const char *) git_blob_rawcontent(blob.get()), git_blob_rawsize(blob.get()));
// Apply git filters including CRLF conversion
git_buf filtered = GIT_BUF_INIT;
git_blob_filter_options opts = GIT_BLOB_FILTER_OPTIONS_INIT;

git_oid oid;
if (git_oid_fromstr(&oid, state->gitRev.c_str()))
throw Error("cannot convert '%s' to a Git OID", state->gitRev.c_str());

opts.attr_commit_id = oid;
opts.flags = GIT_BLOB_FILTER_ATTRIBUTES_FROM_COMMIT;

int error = git_blob_filter(&filtered, blob.get(), path.rel_c_str(), &opts);
if (error != 0) {
const git_error *e = git_error_last();
std::string errorMsg = e ? e->message : "Unknown error";
git_buf_dispose(&filtered);
throw std::runtime_error("Failed to filter blob: " + errorMsg);
}
std::string result(filtered.ptr, filtered.size);
git_buf_dispose(&filtered);

return result;
}

std::string readFile(const CanonPath & path) override
Expand Down
23 changes: 23 additions & 0 deletions tests/functional/fetchGit.sh
Original file line number Diff line number Diff line change
Expand Up @@ -303,3 +303,26 @@ git -C "$empty" config user.name "Foobar"
git -C "$empty" commit --allow-empty --allow-empty-message --message ""

nix eval --impure --expr "let attrs = builtins.fetchGit $empty; in assert attrs.lastModified != 0; assert attrs.rev != \"0000000000000000000000000000000000000000\"; assert attrs.revCount == 1; true"

# Test a repo with `eol=crlf`.
repo="$TEST_ROOT/crlf"
git init "$repo"
git -C $repo config user.email "[email protected]"
git -C $repo config user.name "Foobar"

echo -n -e 'foo\nbar\nbaz' > "$repo/newlines.txt"
echo -n -e 'foo\nbar\nbaz' > "$repo/test.txt"
git -C "$repo" add newlines.txt test.txt
git -C "$repo" commit -m 'Add files containing LF line endings'
echo 'test.txt eol=crlf' > "$repo/.gitattributes"
git -C "$repo" add .gitattributes
git -C "$repo" commit -m 'Add eol=crlf to gitattributes'
narhash=$(nix eval --raw --impure --expr "(builtins.fetchGit { url = \"$repo\"; ref = \"master\"; }).narHash")
[[ "$narhash" = "sha256-k7u7RAaF+OvrbtT3KCCDQA8e9uOdflUo5zSgsosoLzA=" ]]

# Ensure that NAR hash doesn't depend on user configuration.
rm -rf $TEST_HOME/.cache/nix
export GIT_CONFIG_GLOBAL="$TEST_ROOT/gitconfig"
git config --global core.autocrlf true
new_narhash=$(nix eval --raw --impure --expr "(builtins.fetchGit { url = \"$repo\"; ref = \"master\"; }).narHash")
[[ "$new_narhash" = "$narhash" ]]