about summary refs log tree commit diff
path: root/third_party/nix/src/nix/ls.cc
blob: b23f83eb782440137744a8c3febbda3dd2375459 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
#include "command.hh"
#include "common-args.hh"
#include "fs-accessor.hh"
#include "json.hh"
#include "nar-accessor.hh"
#include "store-api.hh"

using 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(ref<FSAccessor> accessor) {
    if (path == "/") path = "";

    if (json) {
      JSONPlaceholder jsonRoot(std::cout);
      listNar(jsonRoot, accessor, path, recursive);
    } else
      listText(accessor);
  }
};

struct CmdLsStore : 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 : 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))));
  }
};

static RegisterCommand r1(make_ref<CmdLsStore>());
static RegisterCommand r2(make_ref<CmdLsNar>());