mirror of
https://github.com/NixOS/nix.git
synced 2025-11-18 00:12:43 +01:00
nix flake clone: Support all input types
For input types that have no concept of cloning, we now default to copying the entire source tree.
This commit is contained in:
parent
95da93c05b
commit
d07c24f4c8
6 changed files with 34 additions and 14 deletions
|
|
@ -6,6 +6,7 @@
|
||||||
#include "nix/fetchers/fetch-settings.hh"
|
#include "nix/fetchers/fetch-settings.hh"
|
||||||
#include "nix/fetchers/fetch-to-store.hh"
|
#include "nix/fetchers/fetch-to-store.hh"
|
||||||
#include "nix/util/url.hh"
|
#include "nix/util/url.hh"
|
||||||
|
#include "nix/util/archive.hh"
|
||||||
|
|
||||||
#include <nlohmann/json.hpp>
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
|
|
@ -377,10 +378,10 @@ Input Input::applyOverrides(std::optional<std::string> ref, std::optional<Hash>
|
||||||
return scheme->applyOverrides(*this, ref, rev);
|
return scheme->applyOverrides(*this, ref, rev);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Input::clone(const Settings & settings, const std::filesystem::path & destDir) const
|
void Input::clone(const Settings & settings, ref<Store> store, const std::filesystem::path & destDir) const
|
||||||
{
|
{
|
||||||
assert(scheme);
|
assert(scheme);
|
||||||
scheme->clone(settings, *this, destDir);
|
scheme->clone(settings, store, *this, destDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<std::filesystem::path> Input::getSourcePath() const
|
std::optional<std::filesystem::path> Input::getSourcePath() const
|
||||||
|
|
@ -493,9 +494,19 @@ void InputScheme::putFile(
|
||||||
throw Error("input '%s' does not support modifying file '%s'", input.to_string(), path);
|
throw Error("input '%s' does not support modifying file '%s'", input.to_string(), path);
|
||||||
}
|
}
|
||||||
|
|
||||||
void InputScheme::clone(const Settings & settings, const Input & input, const std::filesystem::path & destDir) const
|
void InputScheme::clone(
|
||||||
|
const Settings & settings, ref<Store> store, const Input & input, const std::filesystem::path & destDir) const
|
||||||
{
|
{
|
||||||
throw Error("do not know how to clone input '%s'", input.to_string());
|
if (std::filesystem::exists(destDir))
|
||||||
|
throw Error("cannot clone into existing path %s", destDir);
|
||||||
|
|
||||||
|
auto [accessor, input2] = getAccessor(settings, store, input);
|
||||||
|
|
||||||
|
Activity act(*logger, lvlTalkative, actUnknown, fmt("copying '%s' to %s...", input2.to_string(), destDir));
|
||||||
|
|
||||||
|
auto source = sinkToSource([&](Sink & sink) { accessor->dumpPath(CanonPath::root, sink); });
|
||||||
|
|
||||||
|
restorePath(destDir, *source);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<ExperimentalFeature> InputScheme::experimentalFeature() const
|
std::optional<ExperimentalFeature> InputScheme::experimentalFeature() const
|
||||||
|
|
|
||||||
|
|
@ -278,7 +278,8 @@ struct GitInputScheme : InputScheme
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
void clone(const Settings & settings, const Input & input, const std::filesystem::path & destDir) const override
|
void clone(const Settings & settings, ref<Store> store, const Input & input, const std::filesystem::path & destDir)
|
||||||
|
const override
|
||||||
{
|
{
|
||||||
auto repoInfo = getRepoInfo(input);
|
auto repoInfo = getRepoInfo(input);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -426,12 +426,13 @@ struct GitHubInputScheme : GitArchiveInputScheme
|
||||||
return DownloadUrl{parseURL(url), headers};
|
return DownloadUrl{parseURL(url), headers};
|
||||||
}
|
}
|
||||||
|
|
||||||
void clone(const Settings & settings, const Input & input, const std::filesystem::path & destDir) const override
|
void clone(const Settings & settings, ref<Store> store, const Input & input, const std::filesystem::path & destDir)
|
||||||
|
const override
|
||||||
{
|
{
|
||||||
auto host = getHost(input);
|
auto host = getHost(input);
|
||||||
Input::fromURL(settings, fmt("git+https://%s/%s/%s.git", host, getOwner(input), getRepo(input)))
|
Input::fromURL(settings, fmt("git+https://%s/%s/%s.git", host, getOwner(input), getRepo(input)))
|
||||||
.applyOverrides(input.getRef(), input.getRev())
|
.applyOverrides(input.getRef(), input.getRev())
|
||||||
.clone(settings, destDir);
|
.clone(settings, store, destDir);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -507,7 +508,8 @@ struct GitLabInputScheme : GitArchiveInputScheme
|
||||||
return DownloadUrl{parseURL(url), headers};
|
return DownloadUrl{parseURL(url), headers};
|
||||||
}
|
}
|
||||||
|
|
||||||
void clone(const Settings & settings, const Input & input, const std::filesystem::path & destDir) const override
|
void clone(const Settings & settings, ref<Store> store, const Input & input, const std::filesystem::path & destDir)
|
||||||
|
const override
|
||||||
{
|
{
|
||||||
auto host = maybeGetStrAttr(input.attrs, "host").value_or("gitlab.com");
|
auto host = maybeGetStrAttr(input.attrs, "host").value_or("gitlab.com");
|
||||||
// FIXME: get username somewhere
|
// FIXME: get username somewhere
|
||||||
|
|
@ -515,7 +517,7 @@ struct GitLabInputScheme : GitArchiveInputScheme
|
||||||
settings,
|
settings,
|
||||||
fmt("git+https://%s/%s/%s.git", host, getStrAttr(input.attrs, "owner"), getStrAttr(input.attrs, "repo")))
|
fmt("git+https://%s/%s/%s.git", host, getStrAttr(input.attrs, "owner"), getStrAttr(input.attrs, "repo")))
|
||||||
.applyOverrides(input.getRef(), input.getRev())
|
.applyOverrides(input.getRef(), input.getRev())
|
||||||
.clone(settings, destDir);
|
.clone(settings, store, destDir);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -596,14 +598,15 @@ struct SourceHutInputScheme : GitArchiveInputScheme
|
||||||
return DownloadUrl{parseURL(url), headers};
|
return DownloadUrl{parseURL(url), headers};
|
||||||
}
|
}
|
||||||
|
|
||||||
void clone(const Settings & settings, const Input & input, const std::filesystem::path & destDir) const override
|
void clone(const Settings & settings, ref<Store> store, const Input & input, const std::filesystem::path & destDir)
|
||||||
|
const override
|
||||||
{
|
{
|
||||||
auto host = maybeGetStrAttr(input.attrs, "host").value_or("git.sr.ht");
|
auto host = maybeGetStrAttr(input.attrs, "host").value_or("git.sr.ht");
|
||||||
Input::fromURL(
|
Input::fromURL(
|
||||||
settings,
|
settings,
|
||||||
fmt("git+https://%s/%s/%s", host, getStrAttr(input.attrs, "owner"), getStrAttr(input.attrs, "repo")))
|
fmt("git+https://%s/%s/%s", host, getStrAttr(input.attrs, "owner"), getStrAttr(input.attrs, "repo")))
|
||||||
.applyOverrides(input.getRef(), input.getRev())
|
.applyOverrides(input.getRef(), input.getRev())
|
||||||
.clone(settings, destDir);
|
.clone(settings, store, destDir);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -143,7 +143,7 @@ public:
|
||||||
|
|
||||||
Input applyOverrides(std::optional<std::string> ref, std::optional<Hash> rev) const;
|
Input applyOverrides(std::optional<std::string> ref, std::optional<Hash> rev) const;
|
||||||
|
|
||||||
void clone(const Settings & settings, const std::filesystem::path & destDir) const;
|
void clone(const Settings & settings, ref<Store> store, const std::filesystem::path & destDir) const;
|
||||||
|
|
||||||
std::optional<std::filesystem::path> getSourcePath() const;
|
std::optional<std::filesystem::path> getSourcePath() const;
|
||||||
|
|
||||||
|
|
@ -216,7 +216,8 @@ struct InputScheme
|
||||||
|
|
||||||
virtual Input applyOverrides(const Input & input, std::optional<std::string> ref, std::optional<Hash> rev) const;
|
virtual Input applyOverrides(const Input & input, std::optional<std::string> ref, std::optional<Hash> rev) const;
|
||||||
|
|
||||||
virtual void clone(const Settings & settings, const Input & input, const std::filesystem::path & destDir) const;
|
virtual void clone(
|
||||||
|
const Settings & settings, ref<Store> store, const Input & input, const std::filesystem::path & destDir) const;
|
||||||
|
|
||||||
virtual std::optional<std::filesystem::path> getSourcePath(const Input & input) const;
|
virtual std::optional<std::filesystem::path> getSourcePath(const Input & input) const;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1049,7 +1049,7 @@ struct CmdFlakeClone : FlakeCommand
|
||||||
if (destDir.empty())
|
if (destDir.empty())
|
||||||
throw Error("missing flag '--dest'");
|
throw Error("missing flag '--dest'");
|
||||||
|
|
||||||
getFlakeRef().resolve(fetchSettings, store).input.clone(fetchSettings, destDir);
|
getFlakeRef().resolve(fetchSettings, store).input.clone(fetchSettings, store, destDir);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -369,6 +369,10 @@ tar cfz "$TEST_ROOT"/flake.tar.gz -C "$TEST_ROOT" flake5
|
||||||
|
|
||||||
nix build -o "$TEST_ROOT"/result file://"$TEST_ROOT"/flake.tar.gz
|
nix build -o "$TEST_ROOT"/result file://"$TEST_ROOT"/flake.tar.gz
|
||||||
|
|
||||||
|
nix flake clone "file://$TEST_ROOT/flake.tar.gz" --dest "$TEST_ROOT/unpacked"
|
||||||
|
[[ -e $TEST_ROOT/unpacked/flake.nix ]]
|
||||||
|
expectStderr 1 nix flake clone "file://$TEST_ROOT/flake.tar.gz" --dest "$TEST_ROOT/unpacked" | grep 'existing path'
|
||||||
|
|
||||||
# Building with a tarball URL containing a SRI hash should also work.
|
# Building with a tarball URL containing a SRI hash should also work.
|
||||||
url=$(nix flake metadata --json file://"$TEST_ROOT"/flake.tar.gz | jq -r .url)
|
url=$(nix flake metadata --json file://"$TEST_ROOT"/flake.tar.gz | jq -r .url)
|
||||||
[[ $url =~ sha256- ]]
|
[[ $url =~ sha256- ]]
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue