aboutsummaryrefslogtreecommitdiff
path: root/src/libutil
diff options
context:
space:
mode:
authorBen Burdette <bburdette@gmail.com>2020-04-06 10:00:00 -0600
committerBen Burdette <bburdette@gmail.com>2020-04-06 10:00:00 -0600
commit216263c36f7827a1cf578627579f9cb074dc2749 (patch)
treef9cd590c619319be2b3116f03f1f369051797fcc /src/libutil
parent1221ae3dd07959d47d9f27e9d2271671003d2bed (diff)
parentebb20a5356af023498506324bd0f88a99175e295 (diff)
Merge branch 'master' into error-format
Diffstat (limited to 'src/libutil')
-rw-r--r--src/libutil/hash.hh12
-rw-r--r--src/libutil/util.cc39
-rw-r--r--src/libutil/util.hh75
3 files changed, 92 insertions, 34 deletions
diff --git a/src/libutil/hash.hh b/src/libutil/hash.hh
index ffa43ecf5..ea9fca3e7 100644
--- a/src/libutil/hash.hh
+++ b/src/libutil/hash.hh
@@ -80,6 +80,18 @@ struct Hash
or base-64. By default, this is prefixed by the hash type
(e.g. "sha256:"). */
std::string to_string(Base base = Base32, bool includeType = true) const;
+
+ std::string gitRev() const
+ {
+ assert(type == htSHA1);
+ return to_string(Base16, false);
+ }
+
+ std::string gitShortRev() const
+ {
+ assert(type == htSHA1);
+ return std::string(to_string(Base16, false), 0, 7);
+ }
};
diff --git a/src/libutil/util.cc b/src/libutil/util.cc
index 012f1d071..332c1c43a 100644
--- a/src/libutil/util.cc
+++ b/src/libutil/util.cc
@@ -97,10 +97,10 @@ void replaceEnv(std::map<std::string, std::string> newEnv)
}
-Path absPath(Path path, Path dir)
+Path absPath(Path path, std::optional<Path> dir)
{
if (path[0] != '/') {
- if (dir == "") {
+ if (!dir) {
#ifdef __GNU__
/* GNU (aka. GNU/Hurd) doesn't have any limitation on path
lengths and doesn't define `PATH_MAX'. */
@@ -116,7 +116,7 @@ Path absPath(Path path, Path dir)
free(buf);
#endif
}
- path = dir + "/" + path;
+ path = *dir + "/" + path;
}
return canonPath(path);
}
@@ -478,6 +478,17 @@ Path createTempDir(const Path & tmpRoot, const Path & prefix,
}
+std::pair<AutoCloseFD, Path> createTempFile(const Path & prefix)
+{
+ Path tmpl(getEnv("TMPDIR").value_or("/tmp") + "/" + prefix + ".XXXXXX");
+ // Strictly speaking, this is UB, but who cares...
+ AutoCloseFD fd(mkstemp((char *) tmpl.c_str()));
+ if (!fd)
+ throw SysError("creating temporary file '%s'", tmpl);
+ return {std::move(fd), tmpl};
+}
+
+
std::string getUserName()
{
auto pw = getpwuid(geteuid());
@@ -1205,28 +1216,6 @@ template StringSet tokenizeString(std::string_view s, const string & separators)
template vector<string> tokenizeString(std::string_view s, const string & separators);
-string concatStringsSep(const string & sep, const Strings & ss)
-{
- string s;
- for (auto & i : ss) {
- if (s.size() != 0) s += sep;
- s += i;
- }
- return s;
-}
-
-
-string concatStringsSep(const string & sep, const StringSet & ss)
-{
- string s;
- for (auto & i : ss) {
- if (s.size() != 0) s += sep;
- s += i;
- }
- return s;
-}
-
-
string chomp(const string & s)
{
size_t i = s.find_last_not_of(" \n\r\t");
diff --git a/src/libutil/util.hh b/src/libutil/util.hh
index 0b55c6788..fb9a7ed38 100644
--- a/src/libutil/util.hh
+++ b/src/libutil/util.hh
@@ -48,7 +48,7 @@ void clearEnv();
/* Return an absolutized path, resolving paths relative to the
specified directory, or the current directory otherwise. The path
is also canonicalised. */
-Path absPath(Path path, Path dir = "");
+Path absPath(Path path, std::optional<Path> dir = {});
/* Canonicalise a path by removing all `.' or `..' components and
double or trailing slashes. Optionally resolves all symlink
@@ -124,10 +124,6 @@ void deletePath(const Path & path);
void deletePath(const Path & path, unsigned long long & bytesFreed);
-/* Create a temporary directory. */
-Path createTempDir(const Path & tmpRoot = "", const Path & prefix = "nix",
- bool includePid = true, bool useGlobalCounter = true, mode_t mode = 0755);
-
std::string getUserName();
/* Return $HOME or the user's home directory from /etc/passwd. */
@@ -207,6 +203,14 @@ public:
};
+/* Create a temporary directory. */
+Path createTempDir(const Path & tmpRoot = "", const Path & prefix = "nix",
+ bool includePid = true, bool useGlobalCounter = true, mode_t mode = 0755);
+
+/* Create a temporary file, returning a file handle and its path. */
+std::pair<AutoCloseFD, Path> createTempFile(const Path & prefix = "nix");
+
+
class Pipe
{
public:
@@ -347,8 +351,26 @@ template<class C> C tokenizeString(std::string_view s, const string & separators
/* Concatenate the given strings with a separator between the
elements. */
-string concatStringsSep(const string & sep, const Strings & ss);
-string concatStringsSep(const string & sep, const StringSet & ss);
+template<class C>
+string concatStringsSep(const string & sep, const C & ss)
+{
+ string s;
+ for (auto & i : ss) {
+ if (s.size() != 0) s += sep;
+ s += i;
+ }
+ return s;
+}
+
+
+/* Add quotes around a collection of strings. */
+template<class C> Strings quoteStrings(const C & c)
+{
+ Strings res;
+ for (auto & s : c)
+ res.push_back("'" + s + "'");
+ return res;
+}
/* Remove trailing whitespace from a string. */
@@ -426,6 +448,13 @@ void ignoreException();
+/* Tree formatting. */
+constexpr char treeConn[] = "├───";
+constexpr char treeLast[] = "└───";
+constexpr char treeLine[] = "│ ";
+constexpr char treeNull[] = " ";
+
+
/* Truncate a string to 'width' printable characters. If 'filterAll'
is true, all ANSI escape sequences are filtered out. Otherwise,
some escape sequences (such as colour setting) are copied but not
@@ -444,10 +473,11 @@ string base64Decode(const string & s);
/* Get a value for the specified key from an associate container, or a
default value if the key doesn't exist. */
template <class T>
-std::optional<std::string> get(const T & map, const std::string & key)
+std::optional<typename T::mapped_type> get(const T & map, const typename T::key_type & key)
{
auto i = map.find(key);
- return i == map.end() ? std::optional<std::string>() : i->second;
+ if (i == map.end()) return {};
+ return std::optional<typename T::mapped_type>(i->second);
}
@@ -551,4 +581,31 @@ extern PathFilter defaultPathFilter;
AutoCloseFD createUnixDomainSocket(const Path & path, mode_t mode);
+// A Rust/Python-like enumerate() iterator adapter.
+// Borrowed from http://reedbeta.com/blog/python-like-enumerate-in-cpp17.
+template <typename T,
+ typename TIter = decltype(std::begin(std::declval<T>())),
+ typename = decltype(std::end(std::declval<T>()))>
+constexpr auto enumerate(T && iterable)
+{
+ struct iterator
+ {
+ size_t i;
+ TIter iter;
+ bool operator != (const iterator & other) const { return iter != other.iter; }
+ void operator ++ () { ++i; ++iter; }
+ auto operator * () const { return std::tie(i, *iter); }
+ };
+
+ struct iterable_wrapper
+ {
+ T iterable;
+ auto begin() { return iterator{ 0, std::begin(iterable) }; }
+ auto end() { return iterator{ 0, std::end(iterable) }; }
+ };
+
+ return iterable_wrapper{ std::forward<T>(iterable) };
+}
+
+
}