Skip to content

Commit 411826f

Browse files
edolstrajoshuaspenceGraham Dennis
committed
GitAccessor: Allow filters to be applied
Taken from NixOS#13993. Co-authored-by: Josh Spence <jspence@anduril.com> Co-authored-by: Graham Dennis <gdennis@anduril.com>
1 parent e681209 commit 411826f

File tree

2 files changed

+45
-12
lines changed

2 files changed

+45
-12
lines changed

src/libfetchers/git-utils.cc

Lines changed: 39 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -552,10 +552,14 @@ struct GitRepoImpl : GitRepo, std::enable_shared_from_this<GitRepoImpl>
552552
/**
553553
* A 'GitSourceAccessor' with no regard for export-ignore or any other transformations.
554554
*/
555-
ref<GitSourceAccessor> getRawAccessor(const Hash & rev, bool smudgeLfs = false);
555+
ref<GitSourceAccessor> getRawAccessor(const Hash & rev, bool smudgeLfs = false, bool applyFilters = false);
556556

557-
ref<SourceAccessor>
558-
getAccessor(const Hash & rev, bool exportIgnore, std::string displayPrefix, bool smudgeLfs = false) override;
557+
ref<SourceAccessor> getAccessor(
558+
const Hash & rev,
559+
bool exportIgnore,
560+
std::string displayPrefix,
561+
bool smudgeLfs = false,
562+
bool applyFilters = false) override;
559563

560564
ref<SourceAccessor> getAccessor(const WorkdirInfo & wd, bool exportIgnore, MakeNotAllowedError e) override;
561565

@@ -746,17 +750,21 @@ struct GitSourceAccessor : SourceAccessor
746750
struct State
747751
{
748752
ref<GitRepoImpl> repo;
753+
git_oid oid;
749754
Object root;
750755
std::optional<lfs::Fetch> lfsFetch = std::nullopt;
756+
bool applyFilters;
751757
};
752758

753759
Sync<State> state_;
754760

755-
GitSourceAccessor(ref<GitRepoImpl> repo_, const Hash & rev, bool smudgeLfs)
761+
GitSourceAccessor(ref<GitRepoImpl> repo_, const Hash & rev, bool smudgeLfs, bool applyFilters_)
756762
: state_{State{
757763
.repo = repo_,
764+
.oid = hashToOID(rev),
758765
.root = peelToTreeOrBlob(lookupObject(*repo_, hashToOID(rev)).get()),
759766
.lfsFetch = smudgeLfs ? std::make_optional(lfs::Fetch(*repo_, hashToOID(rev))) : std::nullopt,
767+
.applyFilters = applyFilters_,
760768
}}
761769
{
762770
}
@@ -784,7 +792,28 @@ struct GitSourceAccessor : SourceAccessor
784792
}
785793
}
786794

787-
return std::string((const char *) git_blob_rawcontent(blob.get()), git_blob_rawsize(blob.get()));
795+
if (!state->applyFilters)
796+
return std::string((const char *) git_blob_rawcontent(blob.get()), git_blob_rawsize(blob.get()));
797+
else {
798+
// Apply git filters including potential CRLF conversion
799+
git_buf filtered = GIT_BUF_INIT;
800+
git_blob_filter_options opts = GIT_BLOB_FILTER_OPTIONS_INIT;
801+
802+
opts.attr_commit_id = state->oid;
803+
opts.flags = GIT_BLOB_FILTER_ATTRIBUTES_FROM_COMMIT;
804+
805+
int error = git_blob_filter(&filtered, blob.get(), path.rel_c_str(), &opts);
806+
if (error != 0) {
807+
const git_error * e = git_error_last();
808+
std::string errorMsg = e ? e->message : "Unknown error";
809+
git_buf_dispose(&filtered);
810+
throw Error("Failed to filter blob: " + errorMsg);
811+
}
812+
std::string result(filtered.ptr, filtered.size);
813+
git_buf_dispose(&filtered);
814+
815+
return result;
816+
}
788817
}
789818

790819
std::string readFile(const CanonPath & path) override
@@ -1307,17 +1336,17 @@ struct GitFileSystemObjectSinkImpl : GitFileSystemObjectSink
13071336
}
13081337
};
13091338

1310-
ref<GitSourceAccessor> GitRepoImpl::getRawAccessor(const Hash & rev, bool smudgeLfs)
1339+
ref<GitSourceAccessor> GitRepoImpl::getRawAccessor(const Hash & rev, bool smudgeLfs, bool applyFilters)
13111340
{
13121341
auto self = ref<GitRepoImpl>(shared_from_this());
1313-
return make_ref<GitSourceAccessor>(self, rev, smudgeLfs);
1342+
return make_ref<GitSourceAccessor>(self, rev, smudgeLfs, applyFilters);
13141343
}
13151344

1316-
ref<SourceAccessor>
1317-
GitRepoImpl::getAccessor(const Hash & rev, bool exportIgnore, std::string displayPrefix, bool smudgeLfs)
1345+
ref<SourceAccessor> GitRepoImpl::getAccessor(
1346+
const Hash & rev, bool exportIgnore, std::string displayPrefix, bool smudgeLfs, bool applyFilters)
13181347
{
13191348
auto self = ref<GitRepoImpl>(shared_from_this());
1320-
ref<GitSourceAccessor> rawGitAccessor = getRawAccessor(rev, smudgeLfs);
1349+
ref<GitSourceAccessor> rawGitAccessor = getRawAccessor(rev, smudgeLfs, applyFilters);
13211350
rawGitAccessor->setPathDisplay(std::move(displayPrefix));
13221351
if (exportIgnore)
13231352
return make_ref<GitExportIgnoreSourceAccessor>(self, rawGitAccessor, rev);

src/libfetchers/include/nix/fetchers/git-utils.hh

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,8 +88,12 @@ struct GitRepo
8888

8989
virtual bool hasObject(const Hash & oid) = 0;
9090

91-
virtual ref<SourceAccessor>
92-
getAccessor(const Hash & rev, bool exportIgnore, std::string displayPrefix, bool smudgeLfs = false) = 0;
91+
virtual ref<SourceAccessor> getAccessor(
92+
const Hash & rev,
93+
bool exportIgnore,
94+
std::string displayPrefix,
95+
bool smudgeLfs = false,
96+
bool applyFilters = false) = 0;
9397

9498
virtual ref<SourceAccessor>
9599
getAccessor(const WorkdirInfo & wd, bool exportIgnore, MakeNotAllowedError makeNotAllowedError) = 0;

0 commit comments

Comments
 (0)