about summary refs log tree commit diff
path: root/third_party/nix/src/libstore/local-binary-cache-store.cc
blob: 4555de5047833d917082a851969510438fba5036 (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
#include <utility>

#include <absl/strings/match.h>

#include "libstore/binary-cache-store.hh"
#include "libstore/globals.hh"
#include "libstore/nar-info-disk-cache.hh"

namespace nix {

class LocalBinaryCacheStore : public BinaryCacheStore {
 private:
  Path binaryCacheDir;

 public:
  LocalBinaryCacheStore(const Params& params, Path binaryCacheDir)
      : BinaryCacheStore(params), binaryCacheDir(std::move(binaryCacheDir)) {}

  void init() override;

  std::string getUri() override { return "file://" + binaryCacheDir; }

 protected:
  bool fileExists(const std::string& path) override;

  void upsertFile(const std::string& path, const std::string& data,
                  const std::string& mimeType) override;

  void getFile(const std::string& path, Sink& sink) override {
    try {
      readFile(binaryCacheDir + "/" + path, sink);
    } catch (SysError& e) {
      if (e.errNo == ENOENT) {
        throw NoSuchBinaryCacheFile("file '%s' does not exist in binary cache",
                                    path);
      }
    }
  }

  PathSet queryAllValidPaths() override {
    PathSet paths;

    for (auto& entry : readDirectory(binaryCacheDir)) {
      if (entry.name.size() != 40 || !absl::EndsWith(entry.name, ".narinfo")) {
        continue;
      }
      paths.insert(storeDir + "/" +
                   entry.name.substr(0, entry.name.size() - 8));
    }

    return paths;
  }
};

void LocalBinaryCacheStore::init() {
  createDirs(binaryCacheDir + "/nar");
  BinaryCacheStore::init();
}

static void atomicWrite(const Path& path, const std::string& s) {
  Path tmp = path + ".tmp." + std::to_string(getpid());
  AutoDelete del(tmp, false);
  writeFile(tmp, s);
  if (rename(tmp.c_str(), path.c_str()) != 0) {
    throw SysError(format("renaming '%1%' to '%2%'") % tmp % path);
  }
  del.cancel();
}

bool LocalBinaryCacheStore::fileExists(const std::string& path) {
  return pathExists(binaryCacheDir + "/" + path);
}

void LocalBinaryCacheStore::upsertFile(const std::string& path,
                                       const std::string& data,
                                       const std::string& mimeType) {
  atomicWrite(binaryCacheDir + "/" + path, data);
}

static RegisterStoreImplementation regStore(
    [](const std::string& uri,
       const Store::Params& params) -> std::shared_ptr<Store> {
      if (getEnv("_NIX_FORCE_HTTP_BINARY_CACHE_STORE") == "1" ||
          std::string(uri, 0, 7) != "file://") {
        return nullptr;
      }
      auto store =
          std::make_shared<LocalBinaryCacheStore>(params, std::string(uri, 7));
      store->init();
      return store;
    });

}  // namespace nix