mirror of
https://github.com/NixOS/nix.git
synced 2025-11-23 02:39:37 +01:00
Merge remote-tracking branch 'origin/master' into detsys-main
This commit is contained in:
commit
042c2ae3ac
222 changed files with 3295 additions and 1254 deletions
|
|
@ -57,8 +57,7 @@ void Completions::add(std::string completion, std::string description)
|
|||
});
|
||||
}
|
||||
|
||||
bool Completion::operator<(const Completion & other) const
|
||||
{ return completion < other.completion || (completion == other.completion && description < other.description); }
|
||||
auto Completion::operator<=>(const Completion & other) const noexcept = default;
|
||||
|
||||
std::string completionMarker = "___COMPLETE___";
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
#pragma once
|
||||
///@file
|
||||
|
||||
#include <iostream>
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
|
|
@ -11,6 +10,7 @@
|
|||
|
||||
#include "types.hh"
|
||||
#include "experimental-features.hh"
|
||||
#include "ref.hh"
|
||||
|
||||
namespace nix {
|
||||
|
||||
|
|
@ -380,7 +380,7 @@ struct Completion {
|
|||
std::string completion;
|
||||
std::string description;
|
||||
|
||||
bool operator<(const Completion & other) const;
|
||||
auto operator<=>(const Completion & other) const noexcept;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#include "canon-path.hh"
|
||||
#include "util.hh"
|
||||
#include "file-path-impl.hh"
|
||||
#include "strings-inline.hh"
|
||||
|
||||
namespace nix {
|
||||
|
||||
|
|
|
|||
|
|
@ -169,7 +169,7 @@ public:
|
|||
* a directory is always followed directly by its children. For
|
||||
* instance, 'foo' < 'foo/bar' < 'foo!'.
|
||||
*/
|
||||
bool operator < (const CanonPath & x) const
|
||||
auto operator <=> (const CanonPath & x) const
|
||||
{
|
||||
auto i = path.begin();
|
||||
auto j = x.path.begin();
|
||||
|
|
@ -178,10 +178,9 @@ public:
|
|||
if (c_i == '/') c_i = 0;
|
||||
auto c_j = *j;
|
||||
if (c_j == '/') c_j = 0;
|
||||
if (c_i < c_j) return true;
|
||||
if (c_i > c_j) return false;
|
||||
if (auto cmp = c_i <=> c_j; cmp != 0) return cmp;
|
||||
}
|
||||
return i == path.end() && j != x.path.end();
|
||||
return (i != path.end()) <=> (j != x.path.end());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1,17 +1,8 @@
|
|||
#pragma once
|
||||
///@file
|
||||
|
||||
#define DECLARE_ONE_CMP(PRE, QUAL, COMPARATOR, MY_TYPE) \
|
||||
PRE bool QUAL operator COMPARATOR(const MY_TYPE & other) const;
|
||||
#define DECLARE_EQUAL(prefix, qualification, my_type) \
|
||||
DECLARE_ONE_CMP(prefix, qualification, ==, my_type)
|
||||
#define DECLARE_LEQ(prefix, qualification, my_type) \
|
||||
DECLARE_ONE_CMP(prefix, qualification, <, my_type)
|
||||
#define DECLARE_NEQ(prefix, qualification, my_type) \
|
||||
DECLARE_ONE_CMP(prefix, qualification, !=, my_type)
|
||||
|
||||
#define GENERATE_ONE_CMP(PRE, QUAL, COMPARATOR, MY_TYPE, ...) \
|
||||
PRE bool QUAL operator COMPARATOR(const MY_TYPE & other) const { \
|
||||
#define GENERATE_ONE_CMP(PRE, RET, QUAL, COMPARATOR, MY_TYPE, ...) \
|
||||
PRE RET QUAL operator COMPARATOR(const MY_TYPE & other) const noexcept { \
|
||||
__VA_OPT__(const MY_TYPE * me = this;) \
|
||||
auto fields1 = std::tie( __VA_ARGS__ ); \
|
||||
__VA_OPT__(me = &other;) \
|
||||
|
|
@ -19,30 +10,9 @@
|
|||
return fields1 COMPARATOR fields2; \
|
||||
}
|
||||
#define GENERATE_EQUAL(prefix, qualification, my_type, args...) \
|
||||
GENERATE_ONE_CMP(prefix, qualification, ==, my_type, args)
|
||||
#define GENERATE_LEQ(prefix, qualification, my_type, args...) \
|
||||
GENERATE_ONE_CMP(prefix, qualification, <, my_type, args)
|
||||
#define GENERATE_NEQ(prefix, qualification, my_type, args...) \
|
||||
GENERATE_ONE_CMP(prefix, qualification, !=, my_type, args)
|
||||
|
||||
/**
|
||||
* Declare comparison methods without defining them.
|
||||
*/
|
||||
#define DECLARE_CMP(my_type) \
|
||||
DECLARE_EQUAL(,,my_type) \
|
||||
DECLARE_LEQ(,,my_type) \
|
||||
DECLARE_NEQ(,,my_type)
|
||||
|
||||
/**
|
||||
* @param prefix This is for something before each declaration like
|
||||
* `template<classname Foo>`.
|
||||
*
|
||||
* @param my_type the type are defining operators for.
|
||||
*/
|
||||
#define DECLARE_CMP_EXT(prefix, qualification, my_type) \
|
||||
DECLARE_EQUAL(prefix, qualification, my_type) \
|
||||
DECLARE_LEQ(prefix, qualification, my_type) \
|
||||
DECLARE_NEQ(prefix, qualification, my_type)
|
||||
GENERATE_ONE_CMP(prefix, bool, qualification, ==, my_type, args)
|
||||
#define GENERATE_SPACESHIP(prefix, ret, qualification, my_type, args...) \
|
||||
GENERATE_ONE_CMP(prefix, ret, qualification, <=>, my_type, args)
|
||||
|
||||
/**
|
||||
* Awful hacky generation of the comparison operators by doing a lexicographic
|
||||
|
|
@ -55,15 +25,19 @@
|
|||
* will generate comparison operators semantically equivalent to:
|
||||
*
|
||||
* ```
|
||||
* bool operator<(const ClassName& other) {
|
||||
* return field1 < other.field1 && field2 < other.field2 && ...;
|
||||
* auto operator<=>(const ClassName& other) const noexcept {
|
||||
* if (auto cmp = field1 <=> other.field1; cmp != 0)
|
||||
* return cmp;
|
||||
* if (auto cmp = field2 <=> other.field2; cmp != 0)
|
||||
* return cmp;
|
||||
* ...
|
||||
* return 0;
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
#define GENERATE_CMP(args...) \
|
||||
GENERATE_EQUAL(,,args) \
|
||||
GENERATE_LEQ(,,args) \
|
||||
GENERATE_NEQ(,,args)
|
||||
GENERATE_SPACESHIP(,auto,,args)
|
||||
|
||||
/**
|
||||
* @param prefix This is for something before each declaration like
|
||||
|
|
@ -71,7 +45,6 @@
|
|||
*
|
||||
* @param my_type the type are defining operators for.
|
||||
*/
|
||||
#define GENERATE_CMP_EXT(prefix, my_type, args...) \
|
||||
#define GENERATE_CMP_EXT(prefix, ret, my_type, args...) \
|
||||
GENERATE_EQUAL(prefix, my_type ::, my_type, args) \
|
||||
GENERATE_LEQ(prefix, my_type ::, my_type, args) \
|
||||
GENERATE_NEQ(prefix, my_type ::, my_type, args)
|
||||
GENERATE_SPACESHIP(prefix, ret, my_type ::, my_type, args)
|
||||
|
|
|
|||
|
|
@ -9,6 +9,8 @@
|
|||
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
#include "strings.hh"
|
||||
|
||||
namespace nix {
|
||||
|
||||
Config::Config(StringMap initials)
|
||||
|
|
@ -114,7 +116,7 @@ static void parseConfigFiles(const std::string & contents, const std::string & p
|
|||
if (tokens.empty()) continue;
|
||||
|
||||
if (tokens.size() < 2)
|
||||
throw UsageError("illegal configuration line '%1%' in '%2%'", line, path);
|
||||
throw UsageError("syntax error in configuration line '%1%' in '%2%'", line, path);
|
||||
|
||||
auto include = false;
|
||||
auto ignoreMissing = false;
|
||||
|
|
@ -127,7 +129,7 @@ static void parseConfigFiles(const std::string & contents, const std::string & p
|
|||
|
||||
if (include) {
|
||||
if (tokens.size() != 2)
|
||||
throw UsageError("illegal configuration line '%1%' in '%2%'", line, path);
|
||||
throw UsageError("syntax error in configuration line '%1%' in '%2%'", line, path);
|
||||
auto p = absPath(tokens[1], dirOf(path));
|
||||
if (pathExists(p)) {
|
||||
try {
|
||||
|
|
@ -143,7 +145,7 @@ static void parseConfigFiles(const std::string & contents, const std::string & p
|
|||
}
|
||||
|
||||
if (tokens[1] != "=")
|
||||
throw UsageError("illegal configuration line '%1%' in '%2%'", line, path);
|
||||
throw UsageError("syntax error in configuration line '%1%' in '%2%'", line, path);
|
||||
|
||||
std::string name = std::move(tokens[0]);
|
||||
|
||||
|
|
|
|||
|
|
@ -46,27 +46,22 @@ std::ostream & operator <<(std::ostream & os, const HintFmt & hf)
|
|||
/**
|
||||
* An arbitrarily defined value comparison for the purpose of using traces in the key of a sorted container.
|
||||
*/
|
||||
inline bool operator<(const Trace& lhs, const Trace& rhs)
|
||||
inline std::strong_ordering operator<=>(const Trace& lhs, const Trace& rhs)
|
||||
{
|
||||
// `std::shared_ptr` does not have value semantics for its comparison
|
||||
// functions, so we need to check for nulls and compare the dereferenced
|
||||
// values here.
|
||||
if (lhs.pos != rhs.pos) {
|
||||
if (!lhs.pos)
|
||||
return true;
|
||||
if (!rhs.pos)
|
||||
return false;
|
||||
if (*lhs.pos != *rhs.pos)
|
||||
return *lhs.pos < *rhs.pos;
|
||||
if (auto cmp = bool{lhs.pos} <=> bool{rhs.pos}; cmp != 0)
|
||||
return cmp;
|
||||
if (auto cmp = *lhs.pos <=> *rhs.pos; cmp != 0)
|
||||
return cmp;
|
||||
}
|
||||
// This formats a freshly formatted hint string and then throws it away, which
|
||||
// shouldn't be much of a problem because it only runs when pos is equal, and this function is
|
||||
// used for trace printing, which is infrequent.
|
||||
return lhs.hint.str() < rhs.hint.str();
|
||||
return lhs.hint.str() <=> rhs.hint.str();
|
||||
}
|
||||
inline bool operator> (const Trace& lhs, const Trace& rhs) { return rhs < lhs; }
|
||||
inline bool operator<=(const Trace& lhs, const Trace& rhs) { return !(lhs > rhs); }
|
||||
inline bool operator>=(const Trace& lhs, const Trace& rhs) { return !(lhs < rhs); }
|
||||
|
||||
// print lines of code to the ostream, indicating the error column.
|
||||
void printCodeLines(std::ostream & out,
|
||||
|
|
|
|||
|
|
@ -16,16 +16,12 @@
|
|||
*/
|
||||
|
||||
#include "suggestions.hh"
|
||||
#include "ref.hh"
|
||||
#include "types.hh"
|
||||
#include "fmt.hh"
|
||||
|
||||
#include <cstring>
|
||||
#include <list>
|
||||
#include <memory>
|
||||
#include <map>
|
||||
#include <optional>
|
||||
#include <compare>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
|
@ -79,10 +75,7 @@ struct Trace {
|
|||
TracePrint print = TracePrint::Default;
|
||||
};
|
||||
|
||||
inline bool operator<(const Trace& lhs, const Trace& rhs);
|
||||
inline bool operator> (const Trace& lhs, const Trace& rhs);
|
||||
inline bool operator<=(const Trace& lhs, const Trace& rhs);
|
||||
inline bool operator>=(const Trace& lhs, const Trace& rhs);
|
||||
inline std::strong_ordering operator<=>(const Trace& lhs, const Trace& rhs);
|
||||
|
||||
struct ErrorInfo {
|
||||
Verbosity level;
|
||||
|
|
@ -127,6 +120,8 @@ protected:
|
|||
|
||||
public:
|
||||
BaseError(const BaseError &) = default;
|
||||
BaseError& operator=(const BaseError &) = default;
|
||||
BaseError& operator=(BaseError &&) = default;
|
||||
|
||||
template<typename... Args>
|
||||
BaseError(unsigned int status, const Args & ... args)
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
#pragma once
|
||||
///@file
|
||||
|
||||
#include "comparator.hh"
|
||||
#include "error.hh"
|
||||
#include "json-utils.hh"
|
||||
#include "types.hh"
|
||||
|
|
|
|||
|
|
@ -2,8 +2,6 @@
|
|||
///@file
|
||||
|
||||
#include "source-accessor.hh"
|
||||
#include "fs-sink.hh"
|
||||
#include "util.hh"
|
||||
|
||||
namespace nix {
|
||||
|
||||
|
|
|
|||
|
|
@ -23,6 +23,8 @@
|
|||
# include <io.h>
|
||||
#endif
|
||||
|
||||
#include "strings-inline.hh"
|
||||
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
namespace nix {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
#pragma once
|
||||
///@file
|
||||
|
||||
#include "types.hh"
|
||||
#include "serialise.hh"
|
||||
#include "source-accessor.hh"
|
||||
#include "file-system.hh"
|
||||
|
|
@ -41,6 +40,19 @@ struct FileSystemObjectSink
|
|||
virtual void createSymlink(const CanonPath & path, const std::string & target) = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* An extension of `FileSystemObjectSink` that supports file types
|
||||
* that are not supported by Nix's FSO model.
|
||||
*/
|
||||
struct ExtendedFileSystemObjectSink : virtual FileSystemObjectSink
|
||||
{
|
||||
/**
|
||||
* Create a hard link. The target must be the path of a previously
|
||||
* encountered file relative to the root of the FSO.
|
||||
*/
|
||||
virtual void createHardlink(const CanonPath & path, const CanonPath & target) = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Recursively copy file system objects from the source into the sink.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -39,7 +39,8 @@ struct TreeEntry
|
|||
Mode mode;
|
||||
Hash hash;
|
||||
|
||||
GENERATE_CMP(TreeEntry, me->mode, me->hash);
|
||||
bool operator ==(const TreeEntry &) const = default;
|
||||
auto operator <=>(const TreeEntry &) const = default;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ Hash::Hash(HashAlgorithm algo) : algo(algo)
|
|||
}
|
||||
|
||||
|
||||
bool Hash::operator == (const Hash & h2) const
|
||||
bool Hash::operator == (const Hash & h2) const noexcept
|
||||
{
|
||||
if (hashSize != h2.hashSize) return false;
|
||||
for (unsigned int i = 0; i < hashSize; i++)
|
||||
|
|
@ -50,7 +50,7 @@ bool Hash::operator == (const Hash & h2) const
|
|||
}
|
||||
|
||||
|
||||
std::strong_ordering Hash::operator <=> (const Hash & h) const
|
||||
std::strong_ordering Hash::operator <=> (const Hash & h) const noexcept
|
||||
{
|
||||
if (auto cmp = hashSize <=> h.hashSize; cmp != 0) return cmp;
|
||||
for (unsigned int i = 0; i < hashSize; i++) {
|
||||
|
|
|
|||
|
|
@ -88,12 +88,12 @@ public:
|
|||
/**
|
||||
* Check whether two hashes are equal.
|
||||
*/
|
||||
bool operator == (const Hash & h2) const;
|
||||
bool operator == (const Hash & h2) const noexcept;
|
||||
|
||||
/**
|
||||
* Compare how two hashes are ordered.
|
||||
*/
|
||||
std::strong_ordering operator <=> (const Hash & h2) const;
|
||||
std::strong_ordering operator <=> (const Hash & h2) const noexcept;
|
||||
|
||||
/**
|
||||
* Returns the length of a base-16 representation of this hash.
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
#pragma once
|
||||
///@file
|
||||
|
||||
#include "types.hh"
|
||||
#include "error.hh"
|
||||
#include "config.hh"
|
||||
|
||||
|
|
|
|||
|
|
@ -15,11 +15,15 @@ struct MemorySourceAccessor : virtual SourceAccessor
|
|||
* defining what a "file system object" is in Nix.
|
||||
*/
|
||||
struct File {
|
||||
bool operator == (const File &) const noexcept;
|
||||
std::strong_ordering operator <=> (const File &) const noexcept;
|
||||
|
||||
struct Regular {
|
||||
bool executable = false;
|
||||
std::string contents;
|
||||
|
||||
GENERATE_CMP(Regular, me->executable, me->contents);
|
||||
bool operator == (const Regular &) const = default;
|
||||
auto operator <=> (const Regular &) const = default;
|
||||
};
|
||||
|
||||
struct Directory {
|
||||
|
|
@ -27,13 +31,16 @@ struct MemorySourceAccessor : virtual SourceAccessor
|
|||
|
||||
std::map<Name, File, std::less<>> contents;
|
||||
|
||||
GENERATE_CMP(Directory, me->contents);
|
||||
bool operator == (const Directory &) const noexcept;
|
||||
// TODO libc++ 16 (used by darwin) missing `std::map::operator <=>`, can't do yet.
|
||||
bool operator < (const Directory &) const noexcept;
|
||||
};
|
||||
|
||||
struct Symlink {
|
||||
std::string target;
|
||||
|
||||
GENERATE_CMP(Symlink, me->target);
|
||||
bool operator == (const Symlink &) const = default;
|
||||
auto operator <=> (const Symlink &) const = default;
|
||||
};
|
||||
|
||||
using Raw = std::variant<Regular, Directory, Symlink>;
|
||||
|
|
@ -41,14 +48,15 @@ struct MemorySourceAccessor : virtual SourceAccessor
|
|||
|
||||
MAKE_WRAPPER_CONSTRUCTOR(File);
|
||||
|
||||
GENERATE_CMP(File, me->raw);
|
||||
|
||||
Stat lstat() const;
|
||||
};
|
||||
|
||||
File root { File::Directory {} };
|
||||
|
||||
GENERATE_CMP(MemorySourceAccessor, me->root);
|
||||
bool operator == (const MemorySourceAccessor &) const noexcept = default;
|
||||
bool operator < (const MemorySourceAccessor & other) const noexcept {
|
||||
return root < other.root;
|
||||
}
|
||||
|
||||
std::string readFile(const CanonPath & path) override;
|
||||
bool pathExists(const CanonPath & path) override;
|
||||
|
|
@ -72,6 +80,20 @@ struct MemorySourceAccessor : virtual SourceAccessor
|
|||
SourcePath addFile(CanonPath path, std::string && contents);
|
||||
};
|
||||
|
||||
|
||||
inline bool MemorySourceAccessor::File::Directory::operator == (
|
||||
const MemorySourceAccessor::File::Directory &) const noexcept = default;
|
||||
inline bool MemorySourceAccessor::File::Directory::operator < (
|
||||
const MemorySourceAccessor::File::Directory & other) const noexcept
|
||||
{
|
||||
return contents < other.contents;
|
||||
}
|
||||
|
||||
inline bool MemorySourceAccessor::File::operator == (
|
||||
const MemorySourceAccessor::File &) const noexcept = default;
|
||||
inline std::strong_ordering MemorySourceAccessor::File::operator <=> (
|
||||
const MemorySourceAccessor::File &) const noexcept = default;
|
||||
|
||||
/**
|
||||
* Write to a `MemorySourceAccessor` at the given path
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -148,6 +148,7 @@ sources = files(
|
|||
'signature/signer.cc',
|
||||
'source-accessor.cc',
|
||||
'source-path.cc',
|
||||
'strings.cc',
|
||||
'suggestions.cc',
|
||||
'tarfile.cc',
|
||||
'terminal.cc',
|
||||
|
|
@ -215,6 +216,8 @@ headers = [config_h] + files(
|
|||
'source-accessor.hh',
|
||||
'source-path.hh',
|
||||
'split.hh',
|
||||
'strings.hh',
|
||||
'strings-inline.hh',
|
||||
'suggestions.hh',
|
||||
'sync.hh',
|
||||
'tarfile.hh',
|
||||
|
|
|
|||
|
|
@ -17,12 +17,6 @@ Pos::operator std::shared_ptr<Pos>() const
|
|||
return std::make_shared<Pos>(&*this);
|
||||
}
|
||||
|
||||
bool Pos::operator<(const Pos &rhs) const
|
||||
{
|
||||
return std::forward_as_tuple(line, column, origin)
|
||||
< std::forward_as_tuple(rhs.line, rhs.column, rhs.origin);
|
||||
}
|
||||
|
||||
std::optional<LinesOfCode> Pos::getCodeLines() const
|
||||
{
|
||||
if (line == 0)
|
||||
|
|
@ -116,4 +110,50 @@ void Pos::LinesIterator::bump(bool atFirst)
|
|||
input.remove_prefix(eol);
|
||||
}
|
||||
|
||||
std::optional<std::string> Pos::getSnippetUpTo(const Pos & end) const {
|
||||
assert(this->origin == end.origin);
|
||||
|
||||
if (end.line < this->line)
|
||||
return std::nullopt;
|
||||
|
||||
if (auto source = getSource()) {
|
||||
|
||||
auto firstLine = LinesIterator(*source);
|
||||
for (auto i = 1; i < this->line; ++i) {
|
||||
++firstLine;
|
||||
}
|
||||
|
||||
auto lastLine = LinesIterator(*source);
|
||||
for (auto i = 1; i < end.line; ++i) {
|
||||
++lastLine;
|
||||
}
|
||||
|
||||
LinesIterator linesEnd;
|
||||
|
||||
std::string result;
|
||||
for (auto i = firstLine; i != linesEnd; ++i) {
|
||||
auto firstColumn = i == firstLine ? (this->column ? this->column - 1 : 0) : 0;
|
||||
if (firstColumn > i->size())
|
||||
firstColumn = i->size();
|
||||
|
||||
auto lastColumn = i == lastLine ? (end.column ? end.column - 1 : 0) : std::numeric_limits<int>::max();
|
||||
if (lastColumn < firstColumn)
|
||||
lastColumn = firstColumn;
|
||||
if (lastColumn > i->size())
|
||||
lastColumn = i->size();
|
||||
|
||||
result += i->substr(firstColumn, lastColumn - firstColumn);
|
||||
|
||||
if (i == lastLine) {
|
||||
break;
|
||||
} else {
|
||||
result += '\n';
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <variant>
|
||||
|
||||
#include "source-path.hh"
|
||||
|
||||
|
|
@ -22,21 +23,17 @@ struct Pos
|
|||
|
||||
struct Stdin {
|
||||
ref<std::string> source;
|
||||
bool operator==(const Stdin & rhs) const
|
||||
bool operator==(const Stdin & rhs) const noexcept
|
||||
{ return *source == *rhs.source; }
|
||||
bool operator!=(const Stdin & rhs) const
|
||||
{ return *source != *rhs.source; }
|
||||
bool operator<(const Stdin & rhs) const
|
||||
{ return *source < *rhs.source; }
|
||||
std::strong_ordering operator<=>(const Stdin & rhs) const noexcept
|
||||
{ return *source <=> *rhs.source; }
|
||||
};
|
||||
struct String {
|
||||
ref<std::string> source;
|
||||
bool operator==(const String & rhs) const
|
||||
bool operator==(const String & rhs) const noexcept
|
||||
{ return *source == *rhs.source; }
|
||||
bool operator!=(const String & rhs) const
|
||||
{ return *source != *rhs.source; }
|
||||
bool operator<(const String & rhs) const
|
||||
{ return *source < *rhs.source; }
|
||||
std::strong_ordering operator<=>(const String & rhs) const noexcept
|
||||
{ return *source <=> *rhs.source; }
|
||||
};
|
||||
|
||||
typedef std::variant<std::monostate, Stdin, String, SourcePath> Origin;
|
||||
|
|
@ -65,8 +62,16 @@ struct Pos
|
|||
std::optional<LinesOfCode> getCodeLines() const;
|
||||
|
||||
bool operator==(const Pos & rhs) const = default;
|
||||
bool operator!=(const Pos & rhs) const = default;
|
||||
bool operator<(const Pos & rhs) const;
|
||||
auto operator<=>(const Pos & rhs) const = default;
|
||||
|
||||
std::optional<std::string> getSnippetUpTo(const Pos & end) const;
|
||||
|
||||
/**
|
||||
* Get the SourcePath, if the source was loaded from a file.
|
||||
*/
|
||||
std::optional<SourcePath> getSourcePath() const {
|
||||
return *std::get_if<SourcePath>(&origin);
|
||||
}
|
||||
|
||||
struct LinesIterator {
|
||||
using difference_type = size_t;
|
||||
|
|
|
|||
|
|
@ -1,9 +1,7 @@
|
|||
#pragma once
|
||||
///@file
|
||||
|
||||
#include <compare>
|
||||
#include <memory>
|
||||
#include <exception>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace nix {
|
||||
|
|
@ -89,9 +87,9 @@ public:
|
|||
return p != other.p;
|
||||
}
|
||||
|
||||
bool operator < (const ref<T> & other) const
|
||||
auto operator <=> (const ref<T> & other) const
|
||||
{
|
||||
return p < other.p;
|
||||
return p <=> other.p;
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
#include "canon-path.hh"
|
||||
#include "hash.hh"
|
||||
#include "ref.hh"
|
||||
|
||||
namespace nix {
|
||||
|
||||
|
|
@ -151,9 +152,9 @@ struct SourceAccessor : std::enable_shared_from_this<SourceAccessor>
|
|||
return number == x.number;
|
||||
}
|
||||
|
||||
bool operator < (const SourceAccessor & x) const
|
||||
auto operator <=> (const SourceAccessor & x) const
|
||||
{
|
||||
return number < x.number;
|
||||
return number <=> x.number;
|
||||
}
|
||||
|
||||
void setPathDisplay(std::string displayPrefix, std::string displaySuffix = "");
|
||||
|
|
|
|||
|
|
@ -47,19 +47,14 @@ SourcePath SourcePath::operator / (const CanonPath & x) const
|
|||
SourcePath SourcePath::operator / (std::string_view c) const
|
||||
{ return {accessor, path / c}; }
|
||||
|
||||
bool SourcePath::operator==(const SourcePath & x) const
|
||||
bool SourcePath::operator==(const SourcePath & x) const noexcept
|
||||
{
|
||||
return std::tie(*accessor, path) == std::tie(*x.accessor, x.path);
|
||||
}
|
||||
|
||||
bool SourcePath::operator!=(const SourcePath & x) const
|
||||
std::strong_ordering SourcePath::operator<=>(const SourcePath & x) const noexcept
|
||||
{
|
||||
return std::tie(*accessor, path) != std::tie(*x.accessor, x.path);
|
||||
}
|
||||
|
||||
bool SourcePath::operator<(const SourcePath & x) const
|
||||
{
|
||||
return std::tie(*accessor, path) < std::tie(*x.accessor, x.path);
|
||||
return std::tie(*accessor, path) <=> std::tie(*x.accessor, x.path);
|
||||
}
|
||||
|
||||
std::ostream & operator<<(std::ostream & str, const SourcePath & path)
|
||||
|
|
|
|||
|
|
@ -9,6 +9,8 @@
|
|||
#include "canon-path.hh"
|
||||
#include "source-accessor.hh"
|
||||
|
||||
#include <boost/functional/hash.hpp> // for boost::hash_combine
|
||||
|
||||
namespace nix {
|
||||
|
||||
/**
|
||||
|
|
@ -103,9 +105,8 @@ struct SourcePath
|
|||
*/
|
||||
SourcePath operator / (std::string_view c) const;
|
||||
|
||||
bool operator==(const SourcePath & x) const;
|
||||
bool operator!=(const SourcePath & x) const;
|
||||
bool operator<(const SourcePath & x) const;
|
||||
bool operator==(const SourcePath & x) const noexcept;
|
||||
std::strong_ordering operator<=>(const SourcePath & x) const noexcept;
|
||||
|
||||
/**
|
||||
* Convenience wrapper around `SourceAccessor::resolveSymlinks()`.
|
||||
|
|
@ -115,8 +116,21 @@ struct SourcePath
|
|||
{
|
||||
return {accessor, accessor->resolveSymlinks(path, mode)};
|
||||
}
|
||||
|
||||
friend class std::hash<nix::SourcePath>;
|
||||
};
|
||||
|
||||
std::ostream & operator << (std::ostream & str, const SourcePath & path);
|
||||
|
||||
}
|
||||
|
||||
template<>
|
||||
struct std::hash<nix::SourcePath>
|
||||
{
|
||||
std::size_t operator()(const nix::SourcePath & s) const noexcept
|
||||
{
|
||||
std::size_t hash = 0;
|
||||
hash_combine(hash, s.accessor->number, s.path);
|
||||
return hash;
|
||||
}
|
||||
};
|
||||
|
|
|
|||
31
src/libutil/strings-inline.hh
Normal file
31
src/libutil/strings-inline.hh
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
#pragma once
|
||||
|
||||
#include "strings.hh"
|
||||
|
||||
namespace nix {
|
||||
|
||||
template<class C>
|
||||
std::string concatStringsSep(const std::string_view sep, const C & ss)
|
||||
{
|
||||
size_t size = 0;
|
||||
bool tail = false;
|
||||
// need a cast to string_view since this is also called with Symbols
|
||||
for (const auto & s : ss) {
|
||||
if (tail)
|
||||
size += sep.size();
|
||||
size += std::string_view(s).size();
|
||||
tail = true;
|
||||
}
|
||||
std::string s;
|
||||
s.reserve(size);
|
||||
tail = false;
|
||||
for (auto & i : ss) {
|
||||
if (tail)
|
||||
s += sep;
|
||||
s += i;
|
||||
tail = true;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
} // namespace nix
|
||||
19
src/libutil/strings.cc
Normal file
19
src/libutil/strings.cc
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
#include <string>
|
||||
|
||||
#include "strings-inline.hh"
|
||||
#include "util.hh"
|
||||
|
||||
namespace nix {
|
||||
|
||||
template std::string concatStringsSep(std::string_view, const Strings &);
|
||||
template std::string concatStringsSep(std::string_view, const StringSet &);
|
||||
template std::string concatStringsSep(std::string_view, const std::vector<std::string> &);
|
||||
|
||||
typedef std::string_view strings_2[2];
|
||||
template std::string concatStringsSep(std::string_view, const strings_2 &);
|
||||
typedef std::string_view strings_3[3];
|
||||
template std::string concatStringsSep(std::string_view, const strings_3 &);
|
||||
typedef std::string_view strings_4[4];
|
||||
template std::string concatStringsSep(std::string_view, const strings_4 &);
|
||||
|
||||
} // namespace nix
|
||||
21
src/libutil/strings.hh
Normal file
21
src/libutil/strings.hh
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
#pragma once
|
||||
|
||||
#include <list>
|
||||
#include <set>
|
||||
#include <string_view>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace nix {
|
||||
|
||||
/**
|
||||
* Concatenate the given strings with a separator between the elements.
|
||||
*/
|
||||
template<class C>
|
||||
std::string concatStringsSep(const std::string_view sep, const C & ss);
|
||||
|
||||
extern template std::string concatStringsSep(std::string_view, const std::list<std::string> &);
|
||||
extern template std::string concatStringsSep(std::string_view, const std::set<std::string> &);
|
||||
extern template std::string concatStringsSep(std::string_view, const std::vector<std::string> &);
|
||||
|
||||
}
|
||||
|
|
@ -38,8 +38,8 @@ int levenshteinDistance(std::string_view first, std::string_view second)
|
|||
}
|
||||
|
||||
Suggestions Suggestions::bestMatches (
|
||||
std::set<std::string> allMatches,
|
||||
std::string query)
|
||||
const std::set<std::string> & allMatches,
|
||||
std::string_view query)
|
||||
{
|
||||
std::set<Suggestion> res;
|
||||
for (const auto & possibleMatch : allMatches) {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
#pragma once
|
||||
///@file
|
||||
|
||||
#include "comparator.hh"
|
||||
#include "types.hh"
|
||||
#include <set>
|
||||
|
||||
|
|
@ -20,7 +19,8 @@ public:
|
|||
|
||||
std::string to_string() const;
|
||||
|
||||
GENERATE_CMP(Suggestion, me->distance, me->suggestion)
|
||||
bool operator ==(const Suggestion &) const = default;
|
||||
auto operator <=>(const Suggestion &) const = default;
|
||||
};
|
||||
|
||||
class Suggestions {
|
||||
|
|
@ -35,8 +35,8 @@ public:
|
|||
) const;
|
||||
|
||||
static Suggestions bestMatches (
|
||||
std::set<std::string> allMatches,
|
||||
std::string query
|
||||
const std::set<std::string> & allMatches,
|
||||
std::string_view query
|
||||
);
|
||||
|
||||
Suggestions& operator+=(const Suggestions & other);
|
||||
|
|
|
|||
|
|
@ -174,7 +174,7 @@ void unpackTarfile(const Path & tarFile, const Path & destDir)
|
|||
extract_archive(archive, destDir);
|
||||
}
|
||||
|
||||
time_t unpackTarfileToSink(TarArchive & archive, FileSystemObjectSink & parseSink)
|
||||
time_t unpackTarfileToSink(TarArchive & archive, ExtendedFileSystemObjectSink & parseSink)
|
||||
{
|
||||
time_t lastModified = 0;
|
||||
|
||||
|
|
@ -195,7 +195,12 @@ time_t unpackTarfileToSink(TarArchive & archive, FileSystemObjectSink & parseSin
|
|||
|
||||
lastModified = std::max(lastModified, archive_entry_mtime(entry));
|
||||
|
||||
switch (archive_entry_filetype(entry)) {
|
||||
if (auto target = archive_entry_hardlink(entry)) {
|
||||
parseSink.createHardlink(cpath, CanonPath(target));
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (auto type = archive_entry_filetype(entry)) {
|
||||
|
||||
case AE_IFDIR:
|
||||
parseSink.createDirectory(cpath);
|
||||
|
|
@ -232,7 +237,7 @@ time_t unpackTarfileToSink(TarArchive & archive, FileSystemObjectSink & parseSin
|
|||
}
|
||||
|
||||
default:
|
||||
throw Error("file '%s' in tarball has unsupported file type", path);
|
||||
throw Error("file '%s' in tarball has unsupported file type %d", path, type);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -41,6 +41,6 @@ void unpackTarfile(Source & source, const Path & destDir);
|
|||
|
||||
void unpackTarfile(const Path & tarFile, const Path & destDir);
|
||||
|
||||
time_t unpackTarfileToSink(TarArchive & archive, FileSystemObjectSink & parseSink);
|
||||
time_t unpackTarfileToSink(TarArchive & archive, ExtendedFileSystemObjectSink & parseSink);
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
#pragma once
|
||||
///@file
|
||||
|
||||
#include "types.hh"
|
||||
#include <limits>
|
||||
#include <string>
|
||||
|
||||
namespace nix {
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1,12 +1,10 @@
|
|||
#pragma once
|
||||
///@file
|
||||
|
||||
#include "ref.hh"
|
||||
|
||||
#include <list>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <limits>
|
||||
#include <map>
|
||||
#include <variant>
|
||||
#include <vector>
|
||||
|
|
|
|||
|
|
@ -132,7 +132,7 @@ std::string ParsedURL::to_string() const
|
|||
+ (fragment.empty() ? "" : "#" + percentEncode(fragment));
|
||||
}
|
||||
|
||||
bool ParsedURL::operator ==(const ParsedURL & other) const
|
||||
bool ParsedURL::operator ==(const ParsedURL & other) const noexcept
|
||||
{
|
||||
return
|
||||
scheme == other.scheme
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ struct ParsedURL
|
|||
|
||||
std::string to_string() const;
|
||||
|
||||
bool operator ==(const ParsedURL & other) const;
|
||||
bool operator ==(const ParsedURL & other) const noexcept;
|
||||
|
||||
/**
|
||||
* Remove `.` and `..` path elements.
|
||||
|
|
|
|||
|
|
@ -11,6 +11,8 @@
|
|||
#include <sstream>
|
||||
#include <optional>
|
||||
|
||||
#include "strings.hh"
|
||||
|
||||
namespace nix {
|
||||
|
||||
void initLibUtil();
|
||||
|
|
@ -33,13 +35,26 @@ template<class C> C tokenizeString(std::string_view s, std::string_view separato
|
|||
|
||||
|
||||
/**
|
||||
* Concatenate the given strings with a separator between the
|
||||
* elements.
|
||||
* Ignore any empty strings at the start of the list, and then concatenate the
|
||||
* given strings with a separator between the elements.
|
||||
*
|
||||
* @deprecated This function exists for historical reasons. You probably just
|
||||
* want to use `concatStringsSep`.
|
||||
*/
|
||||
template<class C>
|
||||
std::string concatStringsSep(const std::string_view sep, const C & ss)
|
||||
[[deprecated("Consider removing the empty string dropping behavior. If acceptable, use concatStringsSep instead.")]]
|
||||
std::string dropEmptyInitThenConcatStringsSep(const std::string_view sep, const C & ss)
|
||||
{
|
||||
size_t size = 0;
|
||||
|
||||
// TODO? remove to make sure we don't rely on the empty item ignoring behavior,
|
||||
// or just get rid of this function by understanding the remaining calls.
|
||||
// for (auto & i : ss) {
|
||||
// // Make sure we don't rely on the empty item ignoring behavior
|
||||
// assert(!i.empty());
|
||||
// break;
|
||||
// }
|
||||
|
||||
// need a cast to string_view since this is also called with Symbols
|
||||
for (const auto & s : ss) size += sep.size() + std::string_view(s).size();
|
||||
std::string s;
|
||||
|
|
@ -360,4 +375,18 @@ inline std::string operator + (std::string_view s1, const char * s2)
|
|||
return s;
|
||||
}
|
||||
|
||||
/**
|
||||
* hash_combine() from Boost. Hash several hashable values together
|
||||
* into a single hash.
|
||||
*/
|
||||
inline void hash_combine(std::size_t & seed) { }
|
||||
|
||||
template <typename T, typename... Rest>
|
||||
inline void hash_combine(std::size_t & seed, const T & v, Rest... rest)
|
||||
{
|
||||
std::hash<T> hasher;
|
||||
seed ^= hasher(v) + 0x9e3779b9 + (seed<<6) + (seed>>2);
|
||||
hash_combine(seed, rest...);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue