diff options
Diffstat (limited to 'third_party/nix/src/nix/ls.cc')
-rw-r--r-- | third_party/nix/src/nix/ls.cc | 137 |
1 files changed, 137 insertions, 0 deletions
diff --git a/third_party/nix/src/nix/ls.cc b/third_party/nix/src/nix/ls.cc new file mode 100644 index 000000000000..1da722babbd3 --- /dev/null +++ b/third_party/nix/src/nix/ls.cc @@ -0,0 +1,137 @@ +#include "libmain/common-args.hh" +#include "libstore/fs-accessor.hh" +#include "libstore/nar-accessor.hh" +#include "libstore/store-api.hh" +#include "libutil/json.hh" +#include "nix/command.hh" + +namespace nix { +struct MixLs : virtual Args, MixJSON { + 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 listText(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); + } + + void list(const ref<FSAccessor>& accessor) { + if (path == "/") { + path = ""; + } + + if (json) { + JSONPlaceholder jsonRoot(std::cout); + listNar(jsonRoot, accessor, path, recursive); + } else { + listText(accessor); + } + } +}; + +struct CmdLsStore final : StoreCommand, MixLs { + CmdLsStore() { expectArg("path", &path); } + + Examples examples() override { + return { + Example{"To list the contents of a store path in a binary cache:", + "nix ls-store --store https://cache.nixos.org/ -lR " + "/nix/store/0i2jd68mp5g6h2sa5k9c85rb80sn8hi9-hello-2.10"}, + }; + } + + 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 final : Command, MixLs { + Path narPath; + + CmdLsNar() { + expectArg("nar", &narPath); + expectArg("path", &path); + } + + Examples examples() override { + return { + Example{"To list a specific file in a NAR:", + "nix ls-nar -l hello.nar /bin/hello"}, + }; + } + + 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, true)))); + } +}; +} // namespace nix + +static nix::RegisterCommand r1(nix::make_ref<nix::CmdLsStore>()); +static nix::RegisterCommand r2(nix::make_ref<nix::CmdLsNar>()); |