2023-04-06 14:15:50 +03:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include "ref.hh"
|
|
|
|
#include "types.hh"
|
|
|
|
#include "archive.hh"
|
|
|
|
#include "canon-path.hh"
|
|
|
|
#include "repair-flag.hh"
|
2023-10-18 16:32:31 +03:00
|
|
|
#include "hash.hh"
|
2023-04-06 14:15:50 +03:00
|
|
|
|
|
|
|
namespace nix {
|
|
|
|
|
2023-10-18 16:32:31 +03:00
|
|
|
MakeError(RestrictedPathError, Error);
|
|
|
|
|
|
|
|
struct SourcePath;
|
2023-04-06 14:15:50 +03:00
|
|
|
class StorePath;
|
|
|
|
class Store;
|
|
|
|
|
2023-10-18 16:32:31 +03:00
|
|
|
struct InputAccessor : public std::enable_shared_from_this<InputAccessor>
|
2023-04-06 14:15:50 +03:00
|
|
|
{
|
2023-10-18 16:32:31 +03:00
|
|
|
const size_t number;
|
|
|
|
|
|
|
|
InputAccessor();
|
|
|
|
|
|
|
|
virtual ~InputAccessor()
|
|
|
|
{ }
|
|
|
|
|
|
|
|
virtual std::string readFile(const CanonPath & path) = 0;
|
|
|
|
|
|
|
|
virtual bool pathExists(const CanonPath & path) = 0;
|
|
|
|
|
2023-04-24 14:34:46 +03:00
|
|
|
enum Type {
|
|
|
|
tRegular, tSymlink, tDirectory,
|
|
|
|
/**
|
|
|
|
Any other node types that may be encountered on the file system, such as device nodes, sockets, named pipe, and possibly even more exotic things.
|
|
|
|
|
|
|
|
Responsible for `"unknown"` from `builtins.readFileType "/dev/null"`.
|
|
|
|
|
|
|
|
Unlike `DT_UNKNOWN`, this must not be used for deferring the lookup of types.
|
|
|
|
*/
|
|
|
|
tMisc
|
|
|
|
};
|
2023-04-06 14:15:50 +03:00
|
|
|
|
|
|
|
struct Stat
|
|
|
|
{
|
|
|
|
Type type = tMisc;
|
|
|
|
//uint64_t fileSize = 0; // regular files only
|
|
|
|
bool isExecutable = false; // regular files only
|
|
|
|
};
|
|
|
|
|
2023-10-18 16:32:31 +03:00
|
|
|
virtual Stat lstat(const CanonPath & path) = 0;
|
|
|
|
|
|
|
|
std::optional<Stat> maybeLstat(const CanonPath & path);
|
|
|
|
|
2023-04-06 14:15:50 +03:00
|
|
|
typedef std::optional<Type> DirEntry;
|
|
|
|
|
|
|
|
typedef std::map<std::string, DirEntry> DirEntries;
|
2023-10-18 16:32:31 +03:00
|
|
|
|
|
|
|
virtual DirEntries readDirectory(const CanonPath & path) = 0;
|
|
|
|
|
|
|
|
virtual std::string readLink(const CanonPath & path) = 0;
|
|
|
|
|
|
|
|
virtual void dumpPath(
|
|
|
|
const CanonPath & path,
|
|
|
|
Sink & sink,
|
|
|
|
PathFilter & filter = defaultPathFilter);
|
|
|
|
|
|
|
|
Hash hashPath(
|
|
|
|
const CanonPath & path,
|
|
|
|
PathFilter & filter = defaultPathFilter,
|
|
|
|
HashType ht = htSHA256);
|
|
|
|
|
|
|
|
StorePath fetchToStore(
|
|
|
|
ref<Store> store,
|
|
|
|
const CanonPath & path,
|
|
|
|
std::string_view name = "source",
|
|
|
|
PathFilter * filter = nullptr,
|
|
|
|
RepairFlag repair = NoRepair);
|
|
|
|
|
|
|
|
/* Return a corresponding path in the root filesystem, if
|
|
|
|
possible. This is only possible for inputs that are
|
|
|
|
materialized in the root filesystem. */
|
|
|
|
virtual std::optional<CanonPath> getPhysicalPath(const CanonPath & path)
|
|
|
|
{ return std::nullopt; }
|
|
|
|
|
|
|
|
bool operator == (const InputAccessor & x) const
|
|
|
|
{
|
|
|
|
return number == x.number;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool operator < (const InputAccessor & x) const
|
|
|
|
{
|
|
|
|
return number < x.number;
|
|
|
|
}
|
|
|
|
|
|
|
|
void setPathDisplay(std::string displayPrefix, std::string displaySuffix = "");
|
|
|
|
|
|
|
|
virtual std::string showPath(const CanonPath & path);
|
|
|
|
|
|
|
|
SourcePath root();
|
|
|
|
|
|
|
|
/* Return the maximum last-modified time of the files in this
|
|
|
|
tree, if available. */
|
|
|
|
virtual std::optional<time_t> getLastModified()
|
|
|
|
{
|
|
|
|
return std::nullopt;
|
|
|
|
}
|
2023-04-06 14:15:50 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* An abstraction for accessing source files during
|
|
|
|
* evaluation. Currently, it's just a wrapper around `CanonPath` that
|
|
|
|
* accesses files in the regular filesystem, but in the future it will
|
|
|
|
* support fetching files in other ways.
|
|
|
|
*/
|
|
|
|
struct SourcePath
|
|
|
|
{
|
2023-10-18 16:32:31 +03:00
|
|
|
ref<InputAccessor> accessor;
|
2023-04-06 14:15:50 +03:00
|
|
|
CanonPath path;
|
|
|
|
|
|
|
|
std::string_view baseName() const;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Construct the parent of this `SourcePath`. Aborts if `this`
|
|
|
|
* denotes the root.
|
|
|
|
*/
|
|
|
|
SourcePath parent() const;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* If this `SourcePath` denotes a regular file (not a symlink),
|
|
|
|
* return its contents; otherwise throw an error.
|
|
|
|
*/
|
|
|
|
std::string readFile() const
|
2023-10-18 16:32:31 +03:00
|
|
|
{ return accessor->readFile(path); }
|
2023-04-06 14:15:50 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Return whether this `SourcePath` denotes a file (of any type)
|
|
|
|
* that exists
|
|
|
|
*/
|
|
|
|
bool pathExists() const
|
2023-10-18 16:32:31 +03:00
|
|
|
{ return accessor->pathExists(path); }
|
2023-04-06 14:15:50 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Return stats about this `SourcePath`, or throw an exception if
|
|
|
|
* it doesn't exist.
|
|
|
|
*/
|
2023-10-18 16:32:31 +03:00
|
|
|
InputAccessor::Stat lstat() const
|
|
|
|
{ return accessor->lstat(path); }
|
2023-04-06 14:15:50 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Return stats about this `SourcePath`, or std::nullopt if it
|
|
|
|
* doesn't exist.
|
|
|
|
*/
|
2023-10-18 16:32:31 +03:00
|
|
|
std::optional<InputAccessor::Stat> maybeLstat() const
|
|
|
|
{ return accessor->maybeLstat(path); }
|
2023-04-06 14:15:50 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* If this `SourcePath` denotes a directory (not a symlink),
|
|
|
|
* return its directory entries; otherwise throw an error.
|
|
|
|
*/
|
2023-10-18 16:32:31 +03:00
|
|
|
InputAccessor::DirEntries readDirectory() const
|
|
|
|
{ return accessor->readDirectory(path); }
|
2023-04-06 14:15:50 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* If this `SourcePath` denotes a symlink, return its target;
|
|
|
|
* otherwise throw an error.
|
|
|
|
*/
|
|
|
|
std::string readLink() const
|
2023-10-18 16:32:31 +03:00
|
|
|
{ return accessor->readLink(path); }
|
2023-04-06 14:15:50 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Dump this `SourcePath` to `sink` as a NAR archive.
|
|
|
|
*/
|
|
|
|
void dumpPath(
|
|
|
|
Sink & sink,
|
|
|
|
PathFilter & filter = defaultPathFilter) const
|
2023-10-18 16:32:31 +03:00
|
|
|
{ return accessor->dumpPath(path, sink, filter); }
|
2023-04-06 14:15:50 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Copy this `SourcePath` to the Nix store.
|
|
|
|
*/
|
|
|
|
StorePath fetchToStore(
|
|
|
|
ref<Store> store,
|
|
|
|
std::string_view name = "source",
|
|
|
|
PathFilter * filter = nullptr,
|
|
|
|
RepairFlag repair = NoRepair) const;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Return the location of this path in the "real" filesystem, if
|
|
|
|
* it has a physical location.
|
|
|
|
*/
|
|
|
|
std::optional<CanonPath> getPhysicalPath() const
|
2023-10-18 16:32:31 +03:00
|
|
|
{ return accessor->getPhysicalPath(path); }
|
2023-04-06 14:15:50 +03:00
|
|
|
|
|
|
|
std::string to_string() const
|
|
|
|
{ return path.abs(); }
|
|
|
|
|
2023-04-24 14:37:51 +03:00
|
|
|
/**
|
|
|
|
* Append a `CanonPath` to this path.
|
|
|
|
*/
|
2023-04-06 14:15:50 +03:00
|
|
|
SourcePath operator + (const CanonPath & x) const
|
2023-10-18 16:32:31 +03:00
|
|
|
{ return {accessor, path + x}; }
|
2023-04-06 14:15:50 +03:00
|
|
|
|
2023-04-24 14:37:51 +03:00
|
|
|
/**
|
|
|
|
* Append a single component `c` to this path. `c` must not
|
|
|
|
* contain a slash. A slash is implicitly added between this path
|
|
|
|
* and `c`.
|
|
|
|
*/
|
2023-04-06 14:15:50 +03:00
|
|
|
SourcePath operator + (std::string_view c) const
|
2023-10-18 16:32:31 +03:00
|
|
|
{ return {accessor, path + c}; }
|
2023-04-06 14:15:50 +03:00
|
|
|
|
|
|
|
bool operator == (const SourcePath & x) const
|
|
|
|
{
|
2023-10-18 16:32:31 +03:00
|
|
|
return std::tie(accessor, path) == std::tie(x.accessor, x.path);
|
2023-04-06 14:15:50 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
bool operator != (const SourcePath & x) const
|
|
|
|
{
|
2023-10-18 16:32:31 +03:00
|
|
|
return std::tie(accessor, path) != std::tie(x.accessor, x.path);
|
2023-04-06 14:15:50 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
bool operator < (const SourcePath & x) const
|
|
|
|
{
|
2023-10-18 16:32:31 +03:00
|
|
|
return std::tie(accessor, path) < std::tie(x.accessor, x.path);
|
2023-04-06 14:15:50 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Resolve any symlinks in this `SourcePath` (including its
|
|
|
|
* parents). The result is a `SourcePath` in which no element is a
|
|
|
|
* symlink.
|
|
|
|
*/
|
|
|
|
SourcePath resolveSymlinks() const;
|
|
|
|
};
|
|
|
|
|
|
|
|
std::ostream & operator << (std::ostream & str, const SourcePath & path);
|
|
|
|
|
|
|
|
}
|