aboutsummaryrefslogtreecommitdiff
path: root/src/libexpr
diff options
context:
space:
mode:
authorEelco Dolstra <edolstra@gmail.com>2017-10-30 11:49:03 +0100
committerEelco Dolstra <edolstra@gmail.com>2017-10-30 11:49:03 +0100
commite38382895deef4c136b7425f480884d122f3c5ae (patch)
tree5b92f8dddb73187022697b9655244e70b3d791db /src/libexpr
parentf9686885be54a9b0f8947713a414de4ad3182037 (diff)
builtins.fetchGit: Return an attrset with revision info
This adds rev, shortRev and revCount attributes, equal to what Hydra provides. E.g. $ nix eval '(fetchGit https://github.com/NixOS/patchelf.git)' { outPath = "/nix/store/ghigrkw02l440g8vfxa9wj4c3zpfmw99-source"; rev = "29c085fd9d3fc972f75b3961905d6b4ecce7eb2b"; revCount = 303; shortRev = "29c085f"; }
Diffstat (limited to 'src/libexpr')
-rw-r--r--src/libexpr/parser.y2
-rw-r--r--src/libexpr/primops/fetchgit.cc58
-rw-r--r--src/libexpr/primops/fetchgit.hh12
3 files changed, 54 insertions, 18 deletions
diff --git a/src/libexpr/parser.y b/src/libexpr/parser.y
index 669312bb7..eee315228 100644
--- a/src/libexpr/parser.y
+++ b/src/libexpr/parser.y
@@ -667,7 +667,7 @@ std::pair<bool, std::string> EvalState::resolveSearchPathElem(const SearchPathEl
try {
if (hasPrefix(elem.second, "git://") || hasSuffix(elem.second, ".git"))
// FIXME: support specifying revision/branch
- res = { true, exportGit(store, elem.second, "master") };
+ res = { true, exportGit(store, elem.second, "master").storePath };
else
res = { true, getDownloader()->downloadCached(store, elem.second, true) };
} catch (DownloadError & e) {
diff --git a/src/libexpr/primops/fetchgit.cc b/src/libexpr/primops/fetchgit.cc
index 18107f5cd..38bffd8db 100644
--- a/src/libexpr/primops/fetchgit.cc
+++ b/src/libexpr/primops/fetchgit.cc
@@ -1,3 +1,4 @@
+#include "fetchgit.hh"
#include "primops.hh"
#include "eval-inline.hh"
#include "download.hh"
@@ -8,11 +9,13 @@
#include <regex>
+#include <nlohmann/json.hpp>
+
using namespace std::string_literals;
namespace nix {
-Path exportGit(ref<Store> store, const std::string & uri,
+GitInfo exportGit(ref<Store> store, const std::string & uri,
const std::string & ref, const std::string & rev,
const std::string & name)
{
@@ -56,36 +59,56 @@ Path exportGit(ref<Store> store, const std::string & uri,
}
// FIXME: check whether rev is an ancestor of ref.
- std::string commitHash = rev != "" ? rev : chomp(readFile(localRefFile));
+ GitInfo gitInfo;
+ gitInfo.rev = rev != "" ? rev : chomp(readFile(localRefFile));
+ gitInfo.shortRev = std::string(gitInfo.rev, 0, 7);
- printTalkative("using revision %s of repo '%s'", uri, commitHash);
+ printTalkative("using revision %s of repo '%s'", uri, gitInfo.rev);
- std::string storeLinkName = hashString(htSHA512, name + std::string("\0"s) + commitHash).to_string(Base32, false);
+ std::string storeLinkName = hashString(htSHA512, name + std::string("\0"s) + gitInfo.rev).to_string(Base32, false);
Path storeLink = cacheDir + "/" + storeLinkName + ".link";
PathLocks storeLinkLock({storeLink}, fmt("waiting for lock on '%1%'...", storeLink));
- if (pathExists(storeLink)) {
- auto storePath = readLink(storeLink);
- store->addTempRoot(storePath);
- if (store->isValidPath(storePath)) {
- return storePath;
+ try {
+ // FIXME: doesn't handle empty lines
+ auto json = nlohmann::json::parse(readFile(storeLink));
+
+ assert(json["uri"] == uri && json["name"] == name && json["rev"] == gitInfo.rev);
+
+ gitInfo.storePath = json["storePath"];
+
+ if (store->isValidPath(gitInfo.storePath)) {
+ gitInfo.revCount = json["revCount"];
+ return gitInfo;
}
+
+ } catch (SysError & e) {
+ if (e.errNo != ENOENT) throw;
}
// FIXME: should pipe this, or find some better way to extract a
// revision.
- auto tar = runProgram("git", true, { "-C", cacheDir, "archive", commitHash });
+ auto tar = runProgram("git", true, { "-C", cacheDir, "archive", gitInfo.rev });
Path tmpDir = createTempDir();
AutoDelete delTmpDir(tmpDir, true);
runProgram("tar", true, { "x", "-C", tmpDir }, tar);
- auto storePath = store->addToStore(name, tmpDir);
+ gitInfo.storePath = store->addToStore(name, tmpDir);
+
+ gitInfo.revCount = std::stoull(runProgram("git", true, { "-C", cacheDir, "rev-list", "--count", gitInfo.rev }));
+
+ nlohmann::json json;
+ json["storePath"] = gitInfo.storePath;
+ json["uri"] = uri;
+ json["name"] = name;
+ json["rev"] = gitInfo.rev;
+ json["revCount"] = gitInfo.revCount;
- replaceSymlink(storePath, storeLink);
+ writeFile(storeLink, json.dump());
- return storePath;
+ return gitInfo;
}
static void prim_fetchGit(EvalState & state, const Pos & pos, Value * * args, Value & v)
@@ -127,9 +150,14 @@ static void prim_fetchGit(EvalState & state, const Pos & pos, Value * * args, Va
} else
url = state.forceStringNoCtx(*args[0], pos);
- Path storePath = exportGit(state.store, url, ref, rev, name);
+ auto gitInfo = exportGit(state.store, url, ref, rev, name);
- mkString(v, storePath, PathSet({storePath}));
+ state.mkAttrs(v, 8);
+ mkString(*state.allocAttr(v, state.sOutPath), gitInfo.storePath, PathSet({gitInfo.storePath}));
+ mkString(*state.allocAttr(v, state.symbols.create("rev")), gitInfo.rev);
+ mkString(*state.allocAttr(v, state.symbols.create("shortRev")), gitInfo.shortRev);
+ mkInt(*state.allocAttr(v, state.symbols.create("revCount")), gitInfo.revCount);
+ v.attrs->sort();
}
static RegisterPrimOp r("fetchGit", 1, prim_fetchGit);
diff --git a/src/libexpr/primops/fetchgit.hh b/src/libexpr/primops/fetchgit.hh
index 4bf34b76f..056b6fcbe 100644
--- a/src/libexpr/primops/fetchgit.hh
+++ b/src/libexpr/primops/fetchgit.hh
@@ -2,13 +2,21 @@
#include <string>
-#include "ref.hh"
+#include "util.hh"
namespace nix {
class Store;
-Path exportGit(ref<Store> store, const std::string & uri,
+struct GitInfo
+{
+ Path storePath;
+ std::string rev;
+ std::string shortRev;
+ uint64_t revCount = 0;
+};
+
+GitInfo exportGit(ref<Store> store, const std::string & uri,
const std::string & ref, const std::string & rev = "",
const std::string & name = "");