aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorEelco Dolstra <eelco.dolstra@logicblox.com>2012-07-26 15:14:33 -0400
committerEelco Dolstra <eelco.dolstra@logicblox.com>2012-07-26 15:14:33 -0400
commit8c7910083976e255300efa797030448f5a1cb864 (patch)
treeafbd7a37d0724feb408a2d025364ed3938b5673a /src
parentaa115e22df1c80e8878237a9e704d7d70783a243 (diff)
parent3a4623afbbc1bff85bde33167d36e8c5a4a3df0d (diff)
Merge branch 'master' into no-manifests
Diffstat (limited to 'src')
-rw-r--r--src/libexpr/attr-path.hh9
-rw-r--r--src/libexpr/common-opts.hh7
-rw-r--r--src/libexpr/eval-inline.hh7
-rw-r--r--src/libexpr/eval.hh6
-rw-r--r--src/libexpr/get-drvs.hh6
-rw-r--r--src/libexpr/names.hh11
-rw-r--r--src/libexpr/nixexpr.hh6
-rw-r--r--src/libexpr/primops.cc26
-rw-r--r--src/libexpr/symbol-table.hh5
-rw-r--r--src/libexpr/value-to-xml.hh5
-rw-r--r--src/libexpr/value.hh5
-rw-r--r--src/libmain/shared.hh6
-rw-r--r--src/libstore/build.cc7
-rw-r--r--src/libstore/derivations.hh6
-rw-r--r--src/libstore/gc.cc37
-rw-r--r--src/libstore/globals.hh6
-rw-r--r--src/libstore/local-store.cc32
-rw-r--r--src/libstore/local-store.hh17
-rw-r--r--src/libstore/misc.hh6
-rw-r--r--src/libstore/optimise-store.cc218
-rw-r--r--src/libstore/pathlocks.hh6
-rw-r--r--src/libstore/references.hh5
-rw-r--r--src/libstore/remote-store.hh6
-rw-r--r--src/libstore/store-api.hh6
-rw-r--r--src/libstore/worker-protocol.hh7
-rw-r--r--src/libutil/archive.hh6
-rw-r--r--src/libutil/hash.hh6
-rw-r--r--src/libutil/immutable.hh5
-rw-r--r--src/libutil/serialise.hh6
-rw-r--r--src/libutil/types.hh6
-rw-r--r--src/libutil/util.cc4
-rw-r--r--src/libutil/util.hh8
-rw-r--r--src/libutil/xml-writer.hh6
-rw-r--r--src/nix-env/profiles.hh6
-rw-r--r--src/nix-env/user-env.hh9
-rw-r--r--src/nix-store/dotgraph.hh5
-rw-r--r--src/nix-store/nix-store.cc10
-rw-r--r--src/nix-store/xmlgraph.hh5
38 files changed, 251 insertions, 289 deletions
diff --git a/src/libexpr/attr-path.hh b/src/libexpr/attr-path.hh
index b106da5ef..d3aad7461 100644
--- a/src/libexpr/attr-path.hh
+++ b/src/libexpr/attr-path.hh
@@ -1,20 +1,13 @@
-#ifndef __ATTR_PATH_H
-#define __ATTR_PATH_H
+#pragma once
#include "eval.hh"
#include <string>
#include <map>
-
namespace nix {
-
void findAlongAttrPath(EvalState & state, const string & attrPath,
Bindings & autoArgs, Expr * e, Value & v);
-
}
-
-
-#endif /* !__ATTR_PATH_H */
diff --git a/src/libexpr/common-opts.hh b/src/libexpr/common-opts.hh
index c28641e90..e2e3fe771 100644
--- a/src/libexpr/common-opts.hh
+++ b/src/libexpr/common-opts.hh
@@ -1,9 +1,7 @@
-#ifndef __COMMON_OPTS_H
-#define __COMMON_OPTS_H
+#pragma once
#include "eval.hh"
-
namespace nix {
/* Some common option parsing between nix-env and nix-instantiate. */
@@ -17,6 +15,3 @@ bool parseSearchPathArg(const string & arg, Strings::iterator & i,
Path lookupFileArg(EvalState & state, string s);
}
-
-
-#endif /* !__COMMON_OPTS_H */
diff --git a/src/libexpr/eval-inline.hh b/src/libexpr/eval-inline.hh
index 6026a7d11..57a9e4c63 100644
--- a/src/libexpr/eval-inline.hh
+++ b/src/libexpr/eval-inline.hh
@@ -1,5 +1,4 @@
-#ifndef __EVAL_INLINE_H
-#define __EVAL_INLINE_H
+#pragma once
#include "eval.hh"
@@ -8,7 +7,6 @@
namespace nix {
-
LocalNoInlineNoReturn(void throwEvalError(const char * s))
{
throw EvalError(s);
@@ -55,7 +53,4 @@ inline void EvalState::forceList(Value & v)
throwTypeError("value is %1% while a list was expected", showType(v));
}
-
}
-
-#endif /* !__EVAL_INLINE_H */
diff --git a/src/libexpr/eval.hh b/src/libexpr/eval.hh
index bab9303b0..5103ae8ce 100644
--- a/src/libexpr/eval.hh
+++ b/src/libexpr/eval.hh
@@ -1,5 +1,4 @@
-#ifndef __EVAL_H
-#define __EVAL_H
+#pragma once
#include "value.hh"
#include "nixexpr.hh"
@@ -256,6 +255,3 @@ string showType(const Value & v);
}
-
-
-#endif /* !__EVAL_H */
diff --git a/src/libexpr/get-drvs.hh b/src/libexpr/get-drvs.hh
index 1e5d0a817..25d8baa55 100644
--- a/src/libexpr/get-drvs.hh
+++ b/src/libexpr/get-drvs.hh
@@ -1,5 +1,4 @@
-#ifndef __GET_DRVS_H
-#define __GET_DRVS_H
+#pragma once
#include "eval.hh"
@@ -83,6 +82,3 @@ void getDerivations(EvalState & state, Value & v, const string & pathPrefix,
}
-
-
-#endif /* !__GET_DRVS_H */
diff --git a/src/libexpr/names.hh b/src/libexpr/names.hh
index e189302d6..ebe113e82 100644
--- a/src/libexpr/names.hh
+++ b/src/libexpr/names.hh
@@ -1,12 +1,9 @@
-#ifndef __NAMES_H
-#define __NAMES_H
+#pragma once
#include "types.hh"
-
namespace nix {
-
struct DrvName
{
string fullName;
@@ -19,15 +16,9 @@ struct DrvName
bool matches(DrvName & n);
};
-
typedef list<DrvName> DrvNames;
-
int compareVersions(const string & v1, const string & v2);
DrvNames drvNamesFromArgs(const Strings & opArgs);
-
}
-
-
-#endif /* !__NAMES_H */
diff --git a/src/libexpr/nixexpr.hh b/src/libexpr/nixexpr.hh
index 6eb771a72..4c1a0bb2d 100644
--- a/src/libexpr/nixexpr.hh
+++ b/src/libexpr/nixexpr.hh
@@ -1,5 +1,4 @@
-#ifndef __NIXEXPR_H
-#define __NIXEXPR_H
+#pragma once
#include "value.hh"
#include "symbol-table.hh"
@@ -290,6 +289,3 @@ struct StaticEnv
}
-
-
-#endif /* !__NIXEXPR_H */
diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc
index f20c2f287..5c011c43e 100644
--- a/src/libexpr/primops.cc
+++ b/src/libexpr/primops.cc
@@ -65,7 +65,31 @@ static void prim_import(EvalState & state, Value * * args, Value & v)
}
}
- state.evalFile(path, v);
+ if (isStorePath(path) && store->isValidPath(path) && isDerivation(path)) {
+ Derivation drv = parseDerivation(readFile(path));
+ Value & w = *state.allocValue();
+ state.mkAttrs(w, 1 + drv.outputs.size());
+ mkString(*state.allocAttr(w, state.sDrvPath), path, singleton<PathSet>("=" + path));
+ state.mkList(*state.allocAttr(w, state.symbols.create("outputs")), drv.outputs.size());
+ unsigned int outputs_index = 0;
+
+ Value * outputsVal = w.attrs->find(state.symbols.create("outputs"))->value;
+ foreach (DerivationOutputs::iterator, i, drv.outputs) {
+ mkString(*state.allocAttr(w, state.symbols.create(i->first)),
+ i->second.path, singleton<PathSet>("!" + i->first + "!" + path));
+ mkString(*(outputsVal->list.elems[outputs_index++] = state.allocValue()),
+ i->first);
+ }
+ w.attrs->sort();
+ Value fun;
+ state.mkThunk_(fun,
+ state.parseExprFromFile(state.findFile("nix/imported-drv-to-derivation.nix")));
+ state.forceFunction(fun);
+ mkApp(v, fun, w);
+ state.forceAttrs(v);
+ } else {
+ state.evalFile(path, v);
+ }
}
diff --git a/src/libexpr/symbol-table.hh b/src/libexpr/symbol-table.hh
index 976117a20..143fc495b 100644
--- a/src/libexpr/symbol-table.hh
+++ b/src/libexpr/symbol-table.hh
@@ -1,5 +1,4 @@
-#ifndef __SYMBOL_TABLE_H
-#define __SYMBOL_TABLE_H
+#pragma once
#include "config.h"
@@ -88,5 +87,3 @@ public:
};
}
-
-#endif /* !__SYMBOL_TABLE_H */
diff --git a/src/libexpr/value-to-xml.hh b/src/libexpr/value-to-xml.hh
index 3ebc989ff..97657327e 100644
--- a/src/libexpr/value-to-xml.hh
+++ b/src/libexpr/value-to-xml.hh
@@ -1,5 +1,4 @@
-#ifndef __VALUE_TO_XML_H
-#define __VALUE_TO_XML_H
+#pragma once
#include "nixexpr.hh"
#include "eval.hh"
@@ -13,5 +12,3 @@ void printValueAsXML(EvalState & state, bool strict, bool location,
Value & v, std::ostream & out, PathSet & context);
}
-
-#endif /* !__VALUE_TO_XML_H */
diff --git a/src/libexpr/value.hh b/src/libexpr/value.hh
index 41512d40b..c9ec236c4 100644
--- a/src/libexpr/value.hh
+++ b/src/libexpr/value.hh
@@ -1,5 +1,4 @@
-#ifndef __VALUE_H
-#define __VALUE_H
+#pragma once
#include "symbol-table.hh"
@@ -151,5 +150,3 @@ void mkPath(Value & v, const char * s);
}
-
-#endif /* !__VALUE_H */
diff --git a/src/libmain/shared.hh b/src/libmain/shared.hh
index d198df70d..7849e10e3 100644
--- a/src/libmain/shared.hh
+++ b/src/libmain/shared.hh
@@ -1,5 +1,4 @@
-#ifndef __SHARED_H
-#define __SHARED_H
+#pragma once
#include "util.hh"
@@ -54,6 +53,3 @@ extern int exitCode;
extern char * * argvSaved;
}
-
-
-#endif /* !__SHARED_H */
diff --git a/src/libstore/build.cc b/src/libstore/build.cc
index 4bef6f02d..c57a63db6 100644
--- a/src/libstore/build.cc
+++ b/src/libstore/build.cc
@@ -1533,7 +1533,7 @@ void DerivationGoal::startBuilder()
/* Create a temporary directory where the build will take
place. */
- tmpDir = createTempDir("", "nix-build-" + baseNameOf(drvPath), false, false);
+ tmpDir = createTempDir("", "nix-build-" + baseNameOf(drvPath), false, false, 0700);
/* For convenience, set an environment pointing to the top build
directory. */
@@ -2099,6 +2099,8 @@ void DerivationGoal::computeClosure()
if (allowed.find(*i) == allowed.end())
throw BuildError(format("output is not allowed to refer to path `%1%'") % *i);
}
+
+ worker.store.optimisePath(path); // FIXME: combine with scanForReferences()
}
/* Register each output path as valid, and register the sets of
@@ -2182,6 +2184,7 @@ void DerivationGoal::deleteTmpDir(bool force)
% drvPath % tmpDir);
if (buildUser.enabled() && !amPrivileged())
getOwnership(tmpDir);
+ chmod(tmpDir.c_str(), 0755);
}
else
deletePathWrapped(tmpDir);
@@ -2562,6 +2565,8 @@ void SubstitutionGoal::finished()
HashResult hash = hashPath(htSHA256, storePath);
+ worker.store.optimisePath(storePath); // FIXME: combine with hashPath()
+
ValidPathInfo info2;
info2.path = storePath;
info2.hash = hash.first;
diff --git a/src/libstore/derivations.hh b/src/libstore/derivations.hh
index 27e471d88..8f22b4afa 100644
--- a/src/libstore/derivations.hh
+++ b/src/libstore/derivations.hh
@@ -1,5 +1,4 @@
-#ifndef __DERIVATIONS_H
-#define __DERIVATIONS_H
+#pragma once
#include <map>
@@ -81,6 +80,3 @@ typedef std::map<Path, Hash> DrvHashes;
extern DrvHashes drvHashes;
}
-
-
-#endif /* !__DERIVATIONS_H */
diff --git a/src/libstore/gc.cc b/src/libstore/gc.cc
index f6ed7dd22..874efe4d3 100644
--- a/src/libstore/gc.cc
+++ b/src/libstore/gc.cc
@@ -436,6 +436,8 @@ bool LocalStore::tryToDelete(GCState & state, const Path & path)
{
checkInterrupt();
+ if (path == linksDir) return true;
+
struct stat st;
if (lstat(path.c_str(), &st)) {
if (errno == ENOENT) return true;
@@ -569,6 +571,37 @@ bool LocalStore::tryToDelete(GCState & state, const Path & path)
}
+/* Unlink all files in /nix/store/.links that have a link count of 1,
+ which indicates that there are no other links and so they can be
+ safely deleted. FIXME: race condition with optimisePath(): we
+ might see a link count of 1 just before optimisePath() increases
+ the link count. */
+void LocalStore::removeUnusedLinks()
+{
+ AutoCloseDir dir = opendir(linksDir.c_str());
+ if (!dir) throw SysError(format("opening directory `%1%'") % linksDir);
+
+ struct dirent * dirent;
+ while (errno = 0, dirent = readdir(dir)) {
+ checkInterrupt();
+ string name = dirent->d_name;
+ if (name == "." || name == "..") continue;
+ Path path = linksDir + "/" + name;
+
+ struct stat st;
+ if (lstat(path.c_str(), &st) == -1)
+ throw SysError(format("statting `%1%'") % path);
+
+ if (st.st_nlink != 1) continue;
+
+ printMsg(lvlTalkative, format("deleting unused link `%1%'") % path);
+
+ if (unlink(path.c_str()) == -1)
+ throw SysError(format("deleting `%1%'") % path);
+ }
+}
+
+
void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
{
GCState state(results);
@@ -682,6 +715,10 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
released. */
foreach (PathSet::iterator, i, state.invalidated)
deleteGarbage(state, *i);
+
+ /* Clean up the links directory. */
+ printMsg(lvlError, format("deleting unused links..."));
+ removeUnusedLinks();
}
diff --git a/src/libstore/globals.hh b/src/libstore/globals.hh
index 12a9b9ca1..1c0877a5e 100644
--- a/src/libstore/globals.hh
+++ b/src/libstore/globals.hh
@@ -1,5 +1,4 @@
-#ifndef __GLOBALS_H
-#define __GLOBALS_H
+#pragma once
#include "types.hh"
@@ -118,6 +117,3 @@ void setDefaultsFromEnvironment();
}
-
-
-#endif /* !__GLOBALS_H */
diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc
index aa21774df..ebfcc9467 100644
--- a/src/libstore/local-store.cc
+++ b/src/libstore/local-store.cc
@@ -12,6 +12,7 @@
#include <sys/types.h>
#include <sys/stat.h>
+#include <sys/time.h>
#include <unistd.h>
#include <utime.h>
#include <fcntl.h>
@@ -208,6 +209,7 @@ LocalStore::LocalStore(bool reserveSpace)
/* Create missing state directories if they don't already exist. */
createDirs(nixStore);
+ createDirs(linksDir = nixStore + "/.links");
Path profilesDir = nixStateDir + "/profiles";
createDirs(nixStateDir + "/profiles");
createDirs(nixStateDir + "/temproots");
@@ -444,7 +446,7 @@ void canonicalisePathMetaData(const Path & path, bool recurse)
throw SysError(format("changing owner of `%1%' to %2%")
% path % geteuid());
}
-
+
if (!S_ISLNK(st.st_mode)) {
/* Mask out all type related bits. */
@@ -458,14 +460,20 @@ void canonicalisePathMetaData(const Path & path, bool recurse)
throw SysError(format("changing mode of `%1%' to %2$o") % path % mode);
}
- if (st.st_mtime != mtimeStore) {
- struct utimbuf utimbuf;
- utimbuf.actime = st.st_atime;
- utimbuf.modtime = mtimeStore;
- if (utime(path.c_str(), &utimbuf) == -1)
- throw SysError(format("changing modification time of `%1%'") % path);
- }
-
+ }
+
+ if (st.st_mtime != mtimeStore) {
+ struct timeval times[2];
+ times[0].tv_sec = st.st_atime;
+ times[0].tv_usec = 0;
+ times[1].tv_sec = mtimeStore;
+ times[1].tv_usec = 0;
+#if HAVE_LUTIMES
+ if (lutimes(path.c_str(), times) == -1)
+#else
+ if (!S_ISLNK(st.st_mode) && utimes(path.c_str(), times) == -1)
+#endif
+ throw SysError(format("changing modification time of `%1%'") % path);
}
if (recurse && S_ISDIR(st.st_mode)) {
@@ -1134,6 +1142,8 @@ Path LocalStore::addToStoreFromDump(const string & dump, const string & name,
hash.second = dump.size();
} else
hash = hashPath(htSHA256, dstPath);
+
+ optimisePath(dstPath); // FIXME: combine with hashPath()
ValidPathInfo info;
info.path = dstPath;
@@ -1188,6 +1198,8 @@ Path LocalStore::addTextToStore(const string & name, const string & s,
canonicalisePathMetaData(dstPath);
HashResult hash = hashPath(htSHA256, dstPath);
+
+ optimisePath(dstPath);
ValidPathInfo info;
info.path = dstPath;
@@ -1423,6 +1435,8 @@ Path LocalStore::importPath(bool requireSignature, Source & source)
/* !!! if we were clever, we could prevent the hashPath()
here. */
HashResult hash = hashPath(htSHA256, dstPath);
+
+ optimisePath(dstPath); // FIXME: combine with hashPath()
ValidPathInfo info;
info.path = dstPath;
diff --git a/src/libstore/local-store.hh b/src/libstore/local-store.hh
index 07d8198ec..15dff1d02 100644
--- a/src/libstore/local-store.hh
+++ b/src/libstore/local-store.hh
@@ -1,5 +1,4 @@
-#ifndef __LOCAL_STORE_H
-#define __LOCAL_STORE_H
+#pragma once
#include <string>
@@ -86,6 +85,8 @@ private:
typedef std::map<Path, RunningSubstituter> RunningSubstituters;
RunningSubstituters runningSubstituters;
+
+ Path linksDir;
public:
@@ -168,8 +169,11 @@ public:
/* Optimise the disk space usage of the Nix store by hard-linking
files with the same contents. */
- void optimiseStore(bool dryRun, OptimiseStats & stats);
+ void optimiseStore(OptimiseStats & stats);
+ /* Optimise a single store path. */
+ void optimisePath(const Path & path);
+
/* Check the integrity of the Nix store. */
void verifyStore(bool checkContents);
@@ -260,6 +264,8 @@ private:
int openGCLock(LockType lockType);
+ void removeUnusedLinks();
+
void startSubstituter(const Path & substituter,
RunningSubstituter & runningSubstituter);
@@ -268,6 +274,8 @@ private:
Path importPath(bool requireSignature, Source & source);
void checkDerivationOutputs(const Path & drvPath, const Derivation & drv);
+
+ void optimisePath_(OptimiseStats & stats, const Path & path);
};
@@ -302,6 +310,3 @@ void deletePathWrapped(const Path & path,
void deletePathWrapped(const Path & path);
}
-
-
-#endif /* !__LOCAL_STORE_H */
diff --git a/src/libstore/misc.hh b/src/libstore/misc.hh
index 850c12af4..fe0bbdd79 100644
--- a/src/libstore/misc.hh
+++ b/src/libstore/misc.hh
@@ -1,5 +1,4 @@
-#ifndef __MISC_H
-#define __MISC_H
+#pragma once
#include "derivations.hh"
@@ -35,6 +34,3 @@ void queryMissing(StoreAPI & store, const PathSet & targets,
}
-
-
-#endif /* !__MISC_H */
diff --git a/src/libstore/optimise-store.cc b/src/libstore/optimise-store.cc
index a486e66ef..84a72604b 100644
--- a/src/libstore/optimise-store.cc
+++ b/src/libstore/optimise-store.cc
@@ -1,6 +1,7 @@
#include "util.hh"
#include "local-store.hh"
#include "immutable.hh"
+#include "globals.hh"
#include <sys/types.h>
#include <sys/stat.h>
@@ -12,9 +13,6 @@
namespace nix {
-typedef std::map<Hash, std::pair<Path, ino_t> > HashToPath;
-
-
static void makeWritable(const Path & path)
{
struct stat st;
@@ -51,140 +49,152 @@ struct MakeImmutable
};
-static void hashAndLink(bool dryRun, HashToPath & hashToPath,
- OptimiseStats & stats, const Path & path)
+void LocalStore::optimisePath_(OptimiseStats & stats, const Path & path)
{
struct stat st;
if (lstat(path.c_str(), &st))
throw SysError(format("getting attributes of path `%1%'") % path);
+ if (S_ISDIR(st.st_mode)) {
+ Strings names = readDirectory(path);
+ foreach (Strings::iterator, i, names)
+ optimisePath_(stats, path + "/" + *i);
+ return;
+ }
+
+ /* We can hard link regular files and maybe symlinks. */
+ if (!S_ISREG(st.st_mode)
+#if CAN_LINK_SYMLINK
+ x
+ && !S_ISLNK(st.st_mode)
+#endif
+ ) return;
+
/* Sometimes SNAFUs can cause files in the Nix store to be
modified, in particular when running programs as root under
NixOS (example: $fontconfig/var/cache being modified). Skip
- those files. */
+ those files. FIXME: check the modification time. */
if (S_ISREG(st.st_mode) && (st.st_mode & S_IWUSR)) {
printMsg(lvlError, format("skipping suspicious writable file `%1%'") % path);
return;
}
- /* We can hard link regular files and symlinks. */
- if (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode)) {
+ /* Hash the file. Note that hashPath() returns the hash over the
+ NAR serialisation, which includes the execute bit on the file.
+ Thus, executable and non-executable files with the same
+ contents *won't* be linked (which is good because otherwise the
+ permissions would be screwed up).
- /* Hash the file. Note that hashPath() returns the hash over
- the NAR serialisation, which includes the execute bit on
- the file. Thus, executable and non-executable files with
- the same contents *won't* be linked (which is good because
- otherwise the permissions would be screwed up).
+ Also note that if `path' is a symlink, then we're hashing the
+ contents of the symlink (i.e. the result of readlink()), not
+ the contents of the target (which may not even exist). */
+ Hash hash = hashPath(htSHA256, path).first;
+ stats.totalFiles++;
+ printMsg(lvlDebug, format("`%1%' has hash `%2%'") % path % printHash(hash));
- Also note that if `path' is a symlink, then we're hashing
- the contents of the symlink (i.e. the result of
- readlink()), not the contents of the target (which may not
- even exist). */
- Hash hash = hashPath(htSHA256, path).first;
- stats.totalFiles++;
- printMsg(lvlDebug, format("`%1%' has hash `%2%'") % path % printHash(hash));
+ /* Check if this is a known hash. */
+ Path linkPath = linksDir + "/" + printHash32(hash);
- std::pair<Path, ino_t> prevPath = hashToPath[hash];
-
- if (prevPath.first == "") {
- hashToPath[hash] = std::pair<Path, ino_t>(path, st.st_ino);
- return;
- }
-
- /* Yes! We've seen a file with the same contents. Replace
- the current file with a hard link to that file. */
- stats.sameContents++;
- if (prevPath.second == st.st_ino) {
- printMsg(lvlDebug, format("`%1%' is already linked to `%2%'") % path % prevPath.first);
- return;
- }
+ if (!pathExists(linkPath)) {
+ /* Nope, create a hard link in the links directory. */
+ makeMutable(path);
+ MakeImmutable mk1(path);
+
+ if (link(path.c_str(), linkPath.c_str()) == -1)
+ throw SysError(format("cannot link `%1%' to `%2%'") % linkPath % path);
+
+ return;
+ }
+
+ /* Yes! We've seen a file with the same contents. Replace the
+ current file with a hard link to that file. */
+ struct stat stLink;
+ if (lstat(linkPath.c_str(), &stLink))
+ throw SysError(format("getting attributes of path `%1%'") % linkPath);
+
+ stats.sameContents++;
+ if (st.st_ino == stLink.st_ino) {
+ printMsg(lvlDebug, format("`%1%' is already linked to `%2%'") % path % linkPath);
+ return;
+ }
- if (!dryRun) {
-
- printMsg(lvlTalkative, format("linking `%1%' to `%2%'") % path % prevPath.first);
+ printMsg(lvlTalkative, format("linking `%1%' to `%2%'") % path % linkPath);
- Path tempLink = (format("%1%.tmp-%2%-%3%")
- % path % getpid() % rand()).str();
+ Path tempLink = (format("%1%/.tmp-link-%2%-%3%")
+ % nixStore % getpid() % rand()).str();
- /* Make the containing directory writable, but only if
- it's not the store itself (we don't want or need to
- mess with its permissions). */
- bool mustToggle = !isStorePath(path);
- if (mustToggle) makeWritable(dirOf(path));
+ /* Make the containing directory writable, but only if it's not
+ the store itself (we don't want or need to mess with its
+ permissions). */
+ bool mustToggle = !isStorePath(path);
+ if (mustToggle) makeWritable(dirOf(path));
- /* When we're done, make the directory read-only again and
- reset its timestamp back to 0. */
- MakeReadOnly makeReadOnly(mustToggle ? dirOf(path) : "");
-
- /* If ‘prevPath’ is immutable, we can't create hard links
- to it, so make it mutable first (and make it immutable
- again when we're done). We also have to make ‘path’
- mutable, otherwise rename() will fail to delete it. */
- makeMutable(prevPath.first);
- MakeImmutable mk1(prevPath.first);
-
- makeMutable(path);
- MakeImmutable mk2(path);
-
- if (link(prevPath.first.c_str(), tempLink.c_str()) == -1) {
- if (errno == EMLINK) {
- /* Too many links to the same file (>= 32000 on
- most file systems). This is likely to happen
- with empty files. Just start over, creating
- links to the current file. */
- printMsg(lvlInfo, format("`%1%' has maximum number of links") % prevPath.first);
- hashToPath[hash] = std::pair<Path, ino_t>(path, st.st_ino);
- return;
- }
- throw SysError(format("cannot link `%1%' to `%2%'")
- % tempLink % prevPath.first);
- }
-
- /* Atomically replace the old file with the new hard link. */
- if (rename(tempLink.c_str(), path.c_str()) == -1) {
- if (errno == EMLINK) {
- /* Some filesystems generate too many links on the
- rename, rather than on the original link.
- (Probably it temporarily increases the st_nlink
- field before decreasing it again.) */
- printMsg(lvlInfo, format("`%1%' has maximum number of links") % prevPath.first);
- hashToPath[hash] = std::pair<Path, ino_t>(path, st.st_ino);
-
- /* Unlink the temp link. */
- if (unlink(tempLink.c_str()) == -1)
- printMsg(lvlError, format("unable to unlink `%1%'") % tempLink);
- return;
- }
- throw SysError(format("cannot rename `%1%' to `%2%'")
- % tempLink % path);
- }
- } else
- printMsg(lvlTalkative, format("would link `%1%' to `%2%'") % path % prevPath.first);
-
- stats.filesLinked++;
- stats.bytesFreed += st.st_size;
- stats.blocksFreed += st.st_blocks;
+ /* When we're done, make the directory read-only again and reset
+ its timestamp back to 0. */
+ MakeReadOnly makeReadOnly(mustToggle ? dirOf(path) : "");
+
+ /* If ‘linkPath’ is immutable, we can't create hard links to it,
+ so make it mutable first (and make it immutable again when
+ we're done). We also have to make ‘path’ mutable, otherwise
+ rename() will fail to delete it. */
+ makeMutable(linkPath);
+ MakeImmutable mk1(linkPath);
+
+ makeMutable(path);
+ MakeImmutable mk2(path);
+
+ if (link(linkPath.c_str(), tempLink.c_str()) == -1) {
+ if (errno == EMLINK) {
+ /* Too many links to the same file (>= 32000 on most file
+ systems). This is likely to happen with empty files.
+ Just shrug and ignore. */
+ printMsg(lvlInfo, format("`%1%' has maximum number of links") % linkPath);
+ return;
+ }
+ throw SysError(format("cannot link `%1%' to `%2%'") % tempLink % linkPath);
}
- if (S_ISDIR(st.st_mode)) {
- Strings names = readDirectory(path);
- foreach (Strings::iterator, i, names)
- hashAndLink(dryRun, hashToPath, stats, path + "/" + *i);
+ /* Atomically replace the old file with the new hard link. */
+ if (rename(tempLink.c_str(), path.c_str()) == -1) {
+ if (errno == EMLINK) {
+ /* Some filesystems generate too many links on the rename,
+ rather than on the original link. (Probably it
+ temporarily increases the st_nlink field before
+ decreasing it again.) */
+ printMsg(lvlInfo, format("`%1%' has maximum number of links") % linkPath);
+
+ /* Unlink the temp link. */
+ if (unlink(tempLink.c_str()) == -1)
+ printMsg(lvlError, format("unable to unlink `%1%'") % tempLink);
+ return;
+ }
+ throw SysError(format("cannot rename `%1%' to `%2%'") % tempLink % path);
}
+
+ stats.filesLinked++;
+ stats.bytesFreed += st.st_size;
+ stats.blocksFreed += st.st_blocks;
}
-void LocalStore::optimiseStore(bool dryRun, OptimiseStats & stats)
+void LocalStore::optimiseStore(OptimiseStats & stats)
{
- HashToPath hashToPath;
-
PathSet paths = queryAllValidPaths();
foreach (PathSet::iterator, i, paths) {
addTempRoot(*i);
if (!isValidPath(*i)) continue; /* path was GC'ed, probably */
startNest(nest, lvlChatty, format("hashing files in `%1%'") % *i);
- hashAndLink(dryRun, hashToPath, stats, *i);
+ optimisePath_(stats, *i);
+ }
+}
+
+
+void LocalStore::optimisePath(const Path & path)
+{
+ if (queryBoolSetting("auto-optimise-store", true)) {
+ OptimiseStats stats;
+ optimisePath_(stats, path);
}
}
diff --git a/src/libstore/pathlocks.hh b/src/libstore/pathlocks.hh
index 57ca1584a..8a6b1450d 100644
--- a/src/libstore/pathlocks.hh
+++ b/src/libstore/pathlocks.hh
@@ -1,5 +1,4 @@
-#ifndef __PATHLOCKS_H
-#define __PATHLOCKS_H
+#pragma once
#include "types.hh"
@@ -44,6 +43,3 @@ bool pathIsLockedByMe(const Path & path);
}
-
-
-#endif /* !__PATHLOCKS_H */
diff --git a/src/libstore/references.hh b/src/libstore/references.hh
index 158c08a77..013809d12 100644
--- a/src/libstore/references.hh
+++ b/src/libstore/references.hh
@@ -1,5 +1,4 @@
-#ifndef __REFERENCES_H
-#define __REFERENCES_H
+#pragma once
#include "types.hh"
#include "hash.hh"
@@ -10,5 +9,3 @@ PathSet scanForReferences(const Path & path, const PathSet & refs,
HashResult & hash);
}
-
-#endif /* !__REFERENCES_H */
diff --git a/src/libstore/remote-store.hh b/src/libstore/remote-store.hh
index 68db0640a..ae4c48dad 100644
--- a/src/libstore/remote-store.hh
+++ b/src/libstore/remote-store.hh
@@ -1,5 +1,4 @@
-#ifndef __REMOTE_STORE_H
-#define __REMOTE_STORE_H
+#pragma once
#include <string>
@@ -103,6 +102,3 @@ private:
}
-
-
-#endif /* !__REMOTE_STORE_H */
diff --git a/src/libstore/store-api.hh b/src/libstore/store-api.hh
index 5d8c09f5a..324d802dc 100644
--- a/src/libstore/store-api.hh
+++ b/src/libstore/store-api.hh
@@ -1,5 +1,4 @@
-#ifndef __STOREAPI_H
-#define __STOREAPI_H
+#pragma once
#include "hash.hh"
#include "serialise.hh"
@@ -362,6 +361,3 @@ MakeError(BuildError, Error) /* denotes a permanent build failure */
}
-
-
-#endif /* !__STOREAPI_H */
diff --git a/src/libstore/worker-protocol.hh b/src/libstore/worker-protocol.hh
index d4ac0ea16..9677a46c2 100644
--- a/src/libstore/worker-protocol.hh
+++ b/src/libstore/worker-protocol.hh
@@ -1,6 +1,4 @@
-#ifndef __WORKER_PROTOCOL_H
-#define __WORKER_PROTOCOL_H
-
+#pragma once
namespace nix {
@@ -67,6 +65,3 @@ template<class T> T readStorePaths(Source & from);
}
-
-
-#endif /* !__WORKER_PROTOCOL_H */
diff --git a/src/libutil/archive.hh b/src/libutil/archive.hh
index fff620313..ccac92074 100644
--- a/src/libutil/archive.hh
+++ b/src/libutil/archive.hh
@@ -1,5 +1,4 @@
-#ifndef __ARCHIVE_H
-#define __ARCHIVE_H
+#pragma once
#include "types.hh"
#include "serialise.hh"
@@ -74,6 +73,3 @@ void restorePath(const Path & path, Source & source);
}
-
-
-#endif /* !__ARCHIVE_H */
diff --git a/src/libutil/hash.hh b/src/libutil/hash.hh
index e0b6478cc..781f51742 100644
--- a/src/libutil/hash.hh
+++ b/src/libutil/hash.hh
@@ -1,5 +1,4 @@
-#ifndef __HASH_H
-#define __HASH_H
+#pragma once
#include "types.hh"
#include "serialise.hh"
@@ -109,6 +108,3 @@ public:
}
-
-
-#endif /* !__HASH_H */
diff --git a/src/libutil/immutable.hh b/src/libutil/immutable.hh
index 5a42a4610..8af419004 100644
--- a/src/libutil/immutable.hh
+++ b/src/libutil/immutable.hh
@@ -1,5 +1,4 @@
-#ifndef __IMMUTABLE_H
-#define __IMMUTABLE_H
+#pragma once
#include <types.hh>
@@ -15,5 +14,3 @@ void makeImmutable(const Path & path);
void makeMutable(const Path & path);
}
-
-#endif /* !__IMMUTABLE_H */
diff --git a/src/libutil/serialise.hh b/src/libutil/serialise.hh
index ded4b12a0..42dd27117 100644
--- a/src/libutil/serialise.hh
+++ b/src/libutil/serialise.hh
@@ -1,5 +1,4 @@
-#ifndef __SERIALISE_H
-#define __SERIALISE_H
+#pragma once
#include "types.hh"
@@ -130,6 +129,3 @@ MakeError(SerialisationError, Error)
}
-
-
-#endif /* !__SERIALISE_H */
diff --git a/src/libutil/types.hh b/src/libutil/types.hh
index 844ad6f76..165a46fa2 100644
--- a/src/libutil/types.hh
+++ b/src/libutil/types.hh
@@ -1,5 +1,4 @@
-#ifndef __TYPES_H
-#define __TYPES_H
+#pragma once
#include <string>
#include <list>
@@ -74,6 +73,3 @@ typedef enum {
}
-
-
-#endif /* !__TYPES_H */
diff --git a/src/libutil/util.cc b/src/libutil/util.cc
index b188a9fc0..689fc543a 100644
--- a/src/libutil/util.cc
+++ b/src/libutil/util.cc
@@ -380,7 +380,7 @@ static Path tempName(Path tmpRoot, const Path & prefix, bool includePid,
Path createTempDir(const Path & tmpRoot, const Path & prefix,
- bool includePid, bool useGlobalCounter)
+ bool includePid, bool useGlobalCounter, mode_t mode)
{
static int globalCounter = 0;
int localCounter = 0;
@@ -389,7 +389,7 @@ Path createTempDir(const Path & tmpRoot, const Path & prefix,
while (1) {
checkInterrupt();
Path tmpDir = tempName(tmpRoot, prefix, includePid, counter);
- if (mkdir(tmpDir.c_str(), 0777) == 0) {
+ if (mkdir(tmpDir.c_str(), mode) == 0) {
/* Explicitly set the group of the directory. This is to
work around around problems caused by BSD's group
ownership semantics (directories inherit the group of
diff --git a/src/libutil/util.hh b/src/libutil/util.hh
index ee0f3862a..9b8656f70 100644
--- a/src/libutil/util.hh
+++ b/src/libutil/util.hh
@@ -1,5 +1,4 @@
-#ifndef __UTIL_H
-#define __UTIL_H
+#pragma once
#include "types.hh"
@@ -89,7 +88,7 @@ void makePathReadOnly(const Path & path);
/* Create a temporary directory. */
Path createTempDir(const Path & tmpRoot = "", const Path & prefix = "nix",
- bool includePid = true, bool useGlobalCounter = true);
+ bool includePid = true, bool useGlobalCounter = true, mode_t mode = 0755);
/* Create a directory and all its parents, if necessary. Returns the
list of created directories, in order of creation. */
@@ -333,6 +332,3 @@ void ignoreException();
}
-
-
-#endif /* !__UTIL_H */
diff --git a/src/libutil/xml-writer.hh b/src/libutil/xml-writer.hh
index e5cc5f8c5..fee2eb495 100644
--- a/src/libutil/xml-writer.hh
+++ b/src/libutil/xml-writer.hh
@@ -1,5 +1,4 @@
-#ifndef __XML_WRITER_H
-#define __XML_WRITER_H
+#pragma once
#include <iostream>
#include <string>
@@ -70,6 +69,3 @@ public:
}
-
-
-#endif /* !__XML_WRITER_H */
diff --git a/src/nix-env/profiles.hh b/src/nix-env/profiles.hh
index a64258dae..30d2376d9 100644
--- a/src/nix-env/profiles.hh
+++ b/src/nix-env/profiles.hh
@@ -1,5 +1,4 @@
-#ifndef __PROFILES_H
-#define __PROFILES_H
+#pragma once
#include "types.hh"
#include "pathlocks.hh"
@@ -54,6 +53,3 @@ void lockProfile(PathLocks & lock, const Path & profile);
string optimisticLockProfile(const Path & profile);
}
-
-
-#endif /* !__PROFILES_H */
diff --git a/src/nix-env/user-env.hh b/src/nix-env/user-env.hh
index 4125d8217..f188efe9b 100644
--- a/src/nix-env/user-env.hh
+++ b/src/nix-env/user-env.hh
@@ -1,5 +1,4 @@
-#ifndef __USER_ENV_H
-#define __USER_ENV_H
+#pragma once
#include "get-drvs.hh"
@@ -12,9 +11,3 @@ bool createUserEnv(EvalState & state, DrvInfos & elems,
const string & lockToken);
}
-
-#endif /* !__USER_ENV_H */
-
-
-
-
diff --git a/src/nix-store/dotgraph.hh b/src/nix-store/dotgraph.hh
index 2318e2fde..68410d841 100644
--- a/src/nix-store/dotgraph.hh
+++ b/src/nix-store/dotgraph.hh
@@ -1,5 +1,4 @@
-#ifndef __DOTGRAPH_H
-#define __DOTGRAPH_H
+#pragma once
#include "types.hh"
@@ -8,5 +7,3 @@ namespace nix {
void printDotGraph(const PathSet & roots);
}
-
-#endif /* !__DOTGRAPH_H */
diff --git a/src/nix-store/nix-store.cc b/src/nix-store/nix-store.cc
index 47c76693f..941301d2e 100644
--- a/src/nix-store/nix-store.cc
+++ b/src/nix-store/nix-store.cc
@@ -746,18 +746,12 @@ static void showOptimiseStats(OptimiseStats & stats)
files with the same contents. */
static void opOptimise(Strings opFlags, Strings opArgs)
{
- if (!opArgs.empty())
+ if (!opArgs.empty() || !opFlags.empty())
throw UsageError("no arguments expected");
- bool dryRun = false;
-
- foreach (Strings::iterator, i, opFlags)
- if (*i == "--dry-run") dryRun = true;
- else throw UsageError(format("unknown flag `%1%'") % *i);
-
OptimiseStats stats;
try {
- ensureLocalStore().optimiseStore(dryRun, stats);
+ ensureLocalStore().optimiseStore(stats);
} catch (...) {
showOptimiseStats(stats);
throw;
diff --git a/src/nix-store/xmlgraph.hh b/src/nix-store/xmlgraph.hh
index 2f9908c43..c2216c5a4 100644
--- a/src/nix-store/xmlgraph.hh
+++ b/src/nix-store/xmlgraph.hh
@@ -1,5 +1,4 @@
-#ifndef __XMLGRAPH_H
-#define __XMLGRAPH_H
+#pragma once
#include "types.hh"
@@ -8,5 +7,3 @@ namespace nix {
void printXmlGraph(const PathSet & roots);
}
-
-#endif /* !__XMLGRAPH_H */