Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce libgit2 #9240

Merged
merged 23 commits into from
Nov 20, 2023
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
e1b8442
Fetcher cache: Add support for caching facts not related to store paths
edolstra Oct 24, 2023
1d0e3d8
Provide a InputScheme::fetch() built on top of InputScheme::getAccess…
edolstra Oct 24, 2023
ee36a44
GitInputScheme: Use libgit2
edolstra Oct 25, 2023
d88106d
Git fetcher: Improve submodule handling
edolstra Oct 27, 2023
669b074
Cleanup
edolstra Oct 28, 2023
0c5eac9
Git fetcher: Handle submodules for workdirs
edolstra Oct 31, 2023
39ea46a
Merge remote-tracking branch 'origin/master' into libgit2
edolstra Nov 2, 2023
98a120b
Merge remote-tracking branch 'origin/master' into libgit2
edolstra Nov 9, 2023
cf59ea8
configure: Check for libgit2
edolstra Nov 10, 2023
21bb180
Use libgit2 with ssh-exec support
edolstra Nov 14, 2023
d74d2fd
Move statusCallbackTrampoline
edolstra Nov 14, 2023
38b07d6
src/libfetchers/git.cc: Apply suggestion
edolstra Nov 14, 2023
25cf8f1
src/libfetchers/union-input-accessor.cc: Apply suggestion
edolstra Nov 14, 2023
4329bdf
Move comment
edolstra Nov 14, 2023
21140c9
Fix doxygen comments
edolstra Nov 14, 2023
7f576f5
Rename UnionInputAccessor to MountedInputAccessor
edolstra Nov 14, 2023
c257c82
Cleanup
edolstra Nov 14, 2023
6ec6b8a
Improve git submodule error reporting
edolstra Nov 14, 2023
2964a9f
Fix relative submodule handling
edolstra Nov 14, 2023
2890999
Show Git fetch progress
edolstra Nov 15, 2023
5dd4ae8
Remove unused cacheType field
edolstra Nov 15, 2023
7ab91e7
Implement shallow fetching
edolstra Nov 15, 2023
4ab27e5
Merge remote-tracking branch 'upstream/master' into libgit2
Ericson2314 Nov 20, 2023
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
1 change: 1 addition & 0 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,7 @@
bzip2 xz brotli editline
openssl sqlite
libarchive
libgit2
boost
lowdown-nix
libsodium
Expand Down
57 changes: 57 additions & 0 deletions src/libfetchers/cache.cc
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ create table if not exists Cache (
);
)sql";

// FIXME: we should periodically purge/nuke this cache to prevent it
// from growing too big.

struct CacheImpl : Cache
{
struct State
Expand Down Expand Up @@ -47,6 +50,60 @@ struct CacheImpl : Cache
"select info, path, immutable, timestamp from Cache where input = ?");
}

void upsert(
const Attrs & inAttrs,
const Attrs & infoAttrs) override
{
_state.lock()->add.use()
(attrsToJSON(inAttrs).dump())
(attrsToJSON(infoAttrs).dump())
("") // no path
(false)
(time(0)).exec();
}

std::optional<Attrs> lookup(const Attrs & inAttrs) override
{
if (auto res = lookupExpired(inAttrs))
return std::move(res->infoAttrs);
return {};
}

std::optional<Attrs> lookupWithTTL(const Attrs & inAttrs) override
{
if (auto res = lookupExpired(inAttrs)) {
if (!res->expired)
return std::move(res->infoAttrs);
debug("ignoring expired cache entry '%s'",
attrsToJSON(inAttrs).dump());
}
return {};
}

std::optional<Result2> lookupExpired(const Attrs & inAttrs) override
{
auto state(_state.lock());

auto inAttrsJSON = attrsToJSON(inAttrs).dump();

auto stmt(state->lookup.use()(inAttrsJSON));
if (!stmt.next()) {
debug("did not find cache entry for '%s'", inAttrsJSON);
return {};
}

auto infoJSON = stmt.getStr(0);
auto locked = stmt.getInt(2) != 0;
auto timestamp = stmt.getInt(3);

debug("using cache entry '%s' -> '%s'", inAttrsJSON, infoJSON);

return Result2 {
.expired = !locked && (settings.tarballTtl.get() == 0 || timestamp + settings.tarballTtl < time(0)),
.infoAttrs = jsonToAttrs(nlohmann::json::parse(infoJSON)),
};
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This cache behavior is hard to follow, but I suggest we fix that forward.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar for the many interactions with the Inputs object. I can't claim to fully understand how the attributes "evolve", let alone prove to myself that requirements about caching and reproducibility are upheld, but I figure I will have a better understanding after completing something based on

Not a blocker for merging this.


void add(
ref<Store> store,
const Attrs & inAttrs,
Expand Down
38 changes: 38 additions & 0 deletions src/libfetchers/cache.hh
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,44 @@ struct Cache
{
virtual ~Cache() { }

/* A cache for arbitrary Attrs -> Attrs mappings with a timestamp
for expiration. */
edolstra marked this conversation as resolved.
Show resolved Hide resolved

/*
edolstra marked this conversation as resolved.
Show resolved Hide resolved
* Add a value to the cache. The cache is an arbitrary mapping of
* Attrs to Attrs.
*/
virtual void upsert(
const Attrs & inAttrs,
const Attrs & infoAttrs) = 0;

/*
* Look up a key with infinite TTL.
*/
virtual std::optional<Attrs> lookup(
const Attrs & inAttrs) = 0;

/*
* Look up a key. Return nothing if its TTL has exceeded
* `settings.tarballTTL`.
*/
virtual std::optional<Attrs> lookupWithTTL(
const Attrs & inAttrs) = 0;

struct Result2
{
bool expired = false;
Attrs infoAttrs;
};

/*
* Look up a key. Return a bool denoting whether its TTL has
* exceeded `settings.tarballTTL`.
*/
virtual std::optional<Result2> lookupExpired(
const Attrs & inAttrs) = 0;

/* Old cache for things that have a store path. */
virtual void add(
ref<Store> store,
const Attrs & inAttrs,
Expand Down
13 changes: 13 additions & 0 deletions src/libfetchers/fetchers.cc
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "fetchers.hh"
#include "store-api.hh"
#include "input-accessor.hh"

#include <nlohmann/json.hpp>

Expand Down Expand Up @@ -355,6 +356,18 @@ void InputScheme::clone(const Input & input, const Path & destDir) const
throw Error("do not know how to clone input '%s'", input.to_string());
}

std::pair<StorePath, Input> InputScheme::fetch(ref<Store> store, const Input & input)
{
auto [accessor, input2] = getAccessor(store, input);
auto storePath = accessor->root().fetchToStore(store, input2.getName());
return {storePath, input2};
}

std::pair<ref<InputAccessor>, Input> InputScheme::getAccessor(ref<Store> store, const Input & input) const
{
throw UnimplementedError("InputScheme must implement fetch() or getAccessor()");
}

std::optional<ExperimentalFeature> InputScheme::experimentalFeature() const
{
return {};
Expand Down
6 changes: 4 additions & 2 deletions src/libfetchers/fetchers.hh
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#include <memory>
#include <nlohmann/json_fwd.hpp>

namespace nix { class Store; class StorePath; }
namespace nix { class Store; class StorePath; struct InputAccessor; }

namespace nix::fetchers {

Expand Down Expand Up @@ -167,7 +167,9 @@ struct InputScheme
std::string_view contents,
std::optional<std::string> commitMsg) const;

virtual std::pair<StorePath, Input> fetch(ref<Store> store, const Input & input) = 0;
virtual std::pair<StorePath, Input> fetch(ref<Store> store, const Input & input);

virtual std::pair<ref<InputAccessor>, Input> getAccessor(ref<Store> store, const Input & input) const;

/**
* Is this `InputScheme` part of an experimental feature?
Expand Down
Loading
Loading