nix: Add commands to query contents of NARs / binary caches

For example,

  $ NIX_REMOTE=file:///my-cache nix ls-store -lR /nix/store/f4kbgl8shhyy76rkk3nbxr0lz8d2ip7q-binutils-2.23.1
  dr-xr-xr-x                    0 ./bin
  -r-xr-xr-x                30748 ./bin/addr2line
  -r-xr-xr-x                66973 ./bin/ar
  ...

Similarly, "nix ls-nar" lists the contents of a NAR file, "nix
cat-nar" extracts a file from a NAR file, and "nix cat-store" extract
a file from a Nix store.
This commit is contained in:
Eelco Dolstra 2016-02-25 17:57:00 +01:00
parent 24a8f9e27b
commit 00b2c05749
2 changed files with 197 additions and 0 deletions

74
src/nix/cat.cc Normal file
View file

@ -0,0 +1,74 @@
#include "command.hh"
#include "store-api.hh"
#include "fs-accessor.hh"
#include "nar-accessor.hh"
using namespace nix;
struct MixCat : virtual Args
{
std::string path;
void cat(ref<FSAccessor> accessor)
{
auto st = accessor->stat(path);
if (st.type == FSAccessor::Type::tMissing)
throw Error(format("path %1% does not exist") % path);
if (st.type != FSAccessor::Type::tRegular)
throw Error(format("path %1% is not a regular file") % path);
std::cout << accessor->readFile(path);
}
};
struct CmdCatStore : StoreCommand, MixCat
{
CmdCatStore()
{
expectArg("path", &path);
}
std::string name() override
{
return "cat-store";
}
std::string description() override
{
return "print the contents of a store file on stdout";
}
void run(ref<Store> store) override
{
cat(store->getFSAccessor());
}
};
struct CmdCatNar : StoreCommand, MixCat
{
Path narPath;
CmdCatNar()
{
expectArg("nar", &narPath);
expectArg("path", &path);
}
std::string name() override
{
return "cat-nar";
}
std::string description() override
{
return "print the contents of a file inside a NAR file";
}
void run(ref<Store> store) override
{
cat(makeNarAccessor(make_ref<std::string>(readFile(narPath))));
}
};
static RegisterCommand r1(make_ref<CmdCatStore>());
static RegisterCommand r2(make_ref<CmdCatNar>());

123
src/nix/ls.cc Normal file
View file

@ -0,0 +1,123 @@
#include "command.hh"
#include "store-api.hh"
#include "fs-accessor.hh"
#include "nar-accessor.hh"
using namespace nix;
struct MixLs : virtual Args
{
std::string path;
bool recursive = false;
bool verbose = false;
bool showDirectory = false;
MixLs()
{
mkFlag('R', "recursive", "list subdirectories recursively", &recursive);
mkFlag('l', "long", "show more file information", &verbose);
mkFlag('d', "directory", "show directories rather than their contents", &showDirectory);
}
void list(ref<FSAccessor> accessor)
{
std::function<void(const FSAccessor::Stat &, const Path &, const std::string &, bool)> doPath;
auto showFile = [&](const Path & curPath, const std::string & relPath) {
if (verbose) {
auto st = accessor->stat(curPath);
std::string tp =
st.type == FSAccessor::Type::tRegular ?
(st.isExecutable ? "-r-xr-xr-x" : "-r--r--r--") :
st.type == FSAccessor::Type::tSymlink ? "lrwxrwxrwx" :
"dr-xr-xr-x";
std::cout <<
(format("%s %20d %s") % tp % st.fileSize % relPath);
if (st.type == FSAccessor::Type::tSymlink)
std::cout << " -> " << accessor->readLink(curPath)
;
std::cout << "\n";
if (recursive && st.type == FSAccessor::Type::tDirectory)
doPath(st, curPath, relPath, false);
} else {
std::cout << relPath << "\n";
if (recursive) {
auto st = accessor->stat(curPath);
if (st.type == FSAccessor::Type::tDirectory)
doPath(st, curPath, relPath, false);
}
}
};
doPath = [&](const FSAccessor::Stat & st , const Path & curPath,
const std::string & relPath, bool showDirectory)
{
if (st.type == FSAccessor::Type::tDirectory && !showDirectory) {
auto names = accessor->readDirectory(curPath);
for (auto & name : names)
showFile(curPath + "/" + name, relPath + "/" + name);
} else
showFile(curPath, relPath);
};
auto st = accessor->stat(path);
if (st.type == FSAccessor::Type::tMissing)
throw Error(format("path %1% does not exist") % path);
doPath(st, path,
st.type == FSAccessor::Type::tDirectory ? "." : baseNameOf(path),
showDirectory);
}
};
struct CmdLsStore : StoreCommand, MixLs
{
CmdLsStore()
{
expectArg("path", &path);
}
std::string name() override
{
return "ls-store";
}
std::string description() override
{
return "show information about a store path";
}
void run(ref<Store> store) override
{
list(store->getFSAccessor());
}
};
struct CmdLsNar : Command, MixLs
{
Path narPath;
CmdLsNar()
{
expectArg("nar", &narPath);
expectArg("path", &path);
}
std::string name() override
{
return "ls-nar";
}
std::string description() override
{
return "show information about the contents of a NAR file";
}
void run() override
{
list(makeNarAccessor(make_ref<std::string>(readFile(narPath))));
}
};
static RegisterCommand r1(make_ref<CmdLsStore>());
static RegisterCommand r2(make_ref<CmdLsNar>());