Merge branch 'master' into no-manifests
This commit is contained in:
		
						commit
						8c79100839
					
				
					 50 changed files with 343 additions and 307 deletions
				
			
		
							
								
								
									
										4
									
								
								.gitignore
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.gitignore
									
										
									
									
										vendored
									
									
								
							|  | @ -79,13 +79,9 @@ Makefile.in | |||
| /src/libexpr/parser-tab.cc | ||||
| /src/libexpr/parser-tab.hh | ||||
| /src/libexpr/parser-tab.output | ||||
| /src/libexpr/nixexpr-ast.hh | ||||
| /src/libexpr/nixexpr-ast.cc | ||||
| /src/libexpr/nix.tbl | ||||
| 
 | ||||
| # /src/libstore/ | ||||
| /src/libstore/derivations-ast.cc | ||||
| /src/libstore/derivations-ast.hh | ||||
| /src/libstore/schema.sql.hh | ||||
| 
 | ||||
| # /src/nix-env/ | ||||
|  |  | |||
							
								
								
									
										17
									
								
								configure.ac
									
										
									
									
									
								
							
							
						
						
									
										17
									
								
								configure.ac
									
										
									
									
									
								
							|  | @ -115,6 +115,23 @@ AC_CHECK_HEADERS([sys/mount.h], [], [], | |||
| ]) | ||||
| 
 | ||||
| 
 | ||||
| # Check for lutimes, optionally used for changing the mtime of | ||||
| # symlinks. | ||||
| AC_CHECK_FUNCS([lutimes]) | ||||
| 
 | ||||
| 
 | ||||
| # Check whether the store optimiser can optimise symlinks. | ||||
| AC_MSG_CHECKING([whether it is possible to create a link to a symlink]) | ||||
| ln -s bla tmp_link | ||||
| if ln tmp_link tmp_link2 2> /dev/null; then | ||||
|     AC_MSG_RESULT(yes) | ||||
|     AC_DEFINE(CAN_LINK_SYMLINK, 1, [Whether link() works on symlinks.]) | ||||
| else | ||||
|     AC_MSG_RESULT(no) | ||||
| fi | ||||
| rm -f tmp_link tmp_link2 | ||||
| 
 | ||||
| 
 | ||||
| # Check for <locale>. | ||||
| AC_LANG_PUSH(C++) | ||||
| AC_CHECK_HEADERS([locale]) | ||||
|  |  | |||
|  | @ -1,6 +1,7 @@ | |||
| all-local: config.nix | ||||
| 
 | ||||
| files = nar.nix buildenv.nix buildenv.pl unpack-channel.nix unpack-channel.sh derivation.nix fetchurl.nix | ||||
| files = nar.nix buildenv.nix buildenv.pl unpack-channel.nix unpack-channel.sh derivation.nix fetchurl.nix \ | ||||
| 	imported-drv-to-derivation.nix | ||||
| 
 | ||||
| install-exec-local: | ||||
| 	$(INSTALL) -d $(DESTDIR)$(datadir)/nix/corepkgs | ||||
|  |  | |||
							
								
								
									
										21
									
								
								corepkgs/imported-drv-to-derivation.nix
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								corepkgs/imported-drv-to-derivation.nix
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,21 @@ | |||
| attrs @ { drvPath, outputs, ... }: | ||||
| 
 | ||||
| let | ||||
| 
 | ||||
|   commonAttrs = (builtins.listToAttrs outputsList) // | ||||
|     { all = map (x: x.value) outputsList; | ||||
|       inherit drvPath; | ||||
|       type = "derivation"; | ||||
|     }; | ||||
| 
 | ||||
|   outputToAttrListElement = outputName: | ||||
|     { name = outputName; | ||||
|       value = commonAttrs // { | ||||
|         outPath = builtins.getAttr outputName attrs; | ||||
|         inherit outputName; | ||||
|       }; | ||||
|     }; | ||||
|      | ||||
|   outputsList = map outputToAttrListElement outputs; | ||||
|      | ||||
| in (builtins.head outputsList).value | ||||
|  | @ -358,6 +358,19 @@ build-use-chroot = /dev /proc /bin</programlisting> | |||
| 
 | ||||
|   </varlistentry> | ||||
| 
 | ||||
|    | ||||
|   <varlistentry><term><literal>auto-optimise-store</literal></term> | ||||
| 
 | ||||
|     <listitem><para>If set to <literal>true</literal> (the default), | ||||
|     Nix automatically detects files in the store that have identical | ||||
|     contents, and replaces them with hard links to a single copy. | ||||
|     This saves disk space.  If set to <literal>false</literal>, you | ||||
|     can still run <command>nix-store --optimise</command> to get rid | ||||
|     of duplicate files.</para></listitem> | ||||
| 
 | ||||
|   </varlistentry> | ||||
| 
 | ||||
| 
 | ||||
| </variablelist> | ||||
| 
 | ||||
| </para> | ||||
|  |  | |||
|  | @ -8,7 +8,7 @@ | |||
| 
 | ||||
| <!--==================================================================--> | ||||
| 
 | ||||
| <section xml:id="ssec-relnotes-1.1"><title>Release 1.1 (TBA)</title> | ||||
| <section xml:id="ssec-relnotes-1.1"><title>Release 1.1 (July 18, 2012)</title> | ||||
| 
 | ||||
| <para>This release has the following improvements:</para> | ||||
| 
 | ||||
|  |  | |||
|  | @ -157,10 +157,6 @@ let | |||
|     rpm_fedora16i386 = makeRPM_i686 (diskImageFuns: diskImageFuns.fedora16i386) 50; | ||||
|     rpm_fedora16x86_64 = makeRPM_x86_64 (diskImageFunsFun: diskImageFunsFun.fedora16x86_64) 50; | ||||
| 
 | ||||
|     rpm_opensuse103i386 = makeRPM_i686 (diskImageFuns: diskImageFuns.opensuse103i386) 40; | ||||
|     rpm_opensuse110i386 = makeRPM_i686 (diskImageFuns: diskImageFuns.opensuse110i386) 50; | ||||
|     rpm_opensuse110x86_64 = makeRPM_x86_64 (diskImageFuns: diskImageFuns.opensuse110x86_64) 50; | ||||
| 
 | ||||
|      | ||||
|     deb_debian60i386 = makeDeb_i686 (diskImageFuns: diskImageFuns.debian60i386) 50; | ||||
|     deb_debian60x86_64 = makeDeb_x86_64 (diskImageFunsFun: diskImageFunsFun.debian60x86_64) 50; | ||||
|  |  | |||
|  | @ -124,6 +124,10 @@ EOF | |||
|         push @instArgs, $arg; | ||||
|     } | ||||
| 
 | ||||
|     elsif ($arg eq "-") { | ||||
|         @exprs = ("-"); | ||||
|     } | ||||
|      | ||||
|     elsif ($arg eq "--verbose" or substr($arg, 0, 2) eq "-v") { | ||||
|         push @buildArgs, $arg; | ||||
|         push @instArgs, $arg; | ||||
|  |  | |||
|  | @ -19,9 +19,9 @@ fi | |||
| 
 | ||||
| export PATH="$HOME/.nix-profile/bin:$PATH" | ||||
| 
 | ||||
| # Subscribe the root user to the NixOS channel by default. | ||||
| # Subscribe the root user to the Nixpkgs channel by default. | ||||
| if [ "$USER" = root -a ! -e $HOME/.nix-channels ]; then | ||||
|     echo "http://nixos.org/releases/nixos/channels/nixos-unstable nixos" > $HOME/.nix-channels | ||||
|     echo "http://nixos.org/releases/nixos/channels/nixpkgs-unstable nixpkgs" > $HOME/.nix-channels | ||||
| fi | ||||
| 
 | ||||
| # Create the per-user garbage collector roots directory. | ||||
|  | @ -43,7 +43,7 @@ fi | |||
| 
 | ||||
| # Set up secure multi-user builds: non-root users build through the | ||||
| # Nix daemon. | ||||
| if test "$USER" != root; then | ||||
| if [ "$USER" != root -a -e @localstatedir@/nix/daemon-socket/socket ]; then | ||||
|     export NIX_REMOTE=daemon | ||||
| else | ||||
|     unset NIX_REMOTE | ||||
|  |  | |||
|  | @ -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 */ | ||||
|  |  | |||
|  | @ -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 */ | ||||
|  |  | |||
|  | @ -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 */ | ||||
|  |  | |||
|  | @ -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 */ | ||||
|  |  | |||
|  | @ -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 */ | ||||
|  |  | |||
|  | @ -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 */ | ||||
|  |  | |||
|  | @ -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 */ | ||||
|  |  | |||
|  | @ -65,7 +65,31 @@ static void prim_import(EvalState & state, Value * * args, Value & 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); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -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 */ | ||||
|  |  | |||
|  | @ -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 */ | ||||
|  |  | |||
|  | @ -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 */ | ||||
|  |  | |||
|  | @ -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 */ | ||||
|  |  | |||
|  | @ -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; | ||||
|  |  | |||
|  | @ -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 */ | ||||
|  |  | |||
|  | @ -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(); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,5 +1,4 @@ | |||
| #ifndef __GLOBALS_H | ||||
| #define __GLOBALS_H | ||||
| #pragma once | ||||
| 
 | ||||
| #include "types.hh" | ||||
| 
 | ||||
|  | @ -118,6 +117,3 @@ void setDefaultsFromEnvironment(); | |||
| 
 | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| #endif /* !__GLOBALS_H */ | ||||
|  |  | |||
|  | @ -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"); | ||||
|  | @ -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)) { | ||||
|  | @ -1135,6 +1143,8 @@ Path LocalStore::addToStoreFromDump(const string & dump, const string & name, | |||
|             } else | ||||
|                 hash = hashPath(htSHA256, dstPath); | ||||
| 
 | ||||
|             optimisePath(dstPath); // FIXME: combine with hashPath()
 | ||||
|              | ||||
|             ValidPathInfo info; | ||||
|             info.path = dstPath; | ||||
|             info.hash = hash.first; | ||||
|  | @ -1189,6 +1199,8 @@ Path LocalStore::addTextToStore(const string & name, const string & s, | |||
| 
 | ||||
|             HashResult hash = hashPath(htSHA256, dstPath); | ||||
| 
 | ||||
|             optimisePath(dstPath); | ||||
|              | ||||
|             ValidPathInfo info; | ||||
|             info.path = dstPath; | ||||
|             info.hash = hash.first; | ||||
|  | @ -1424,6 +1436,8 @@ Path LocalStore::importPath(bool requireSignature, Source & source) | |||
|                here. */ | ||||
|             HashResult hash = hashPath(htSHA256, dstPath); | ||||
| 
 | ||||
|             optimisePath(dstPath); // FIXME: combine with hashPath()
 | ||||
|              | ||||
|             ValidPathInfo info; | ||||
|             info.path = dstPath; | ||||
|             info.hash = hash.first; | ||||
|  |  | |||
|  | @ -1,5 +1,4 @@ | |||
| #ifndef __LOCAL_STORE_H | ||||
| #define __LOCAL_STORE_H | ||||
| #pragma once | ||||
| 
 | ||||
| #include <string> | ||||
| 
 | ||||
|  | @ -87,6 +86,8 @@ private: | |||
|     typedef std::map<Path, RunningSubstituter> RunningSubstituters; | ||||
|     RunningSubstituters runningSubstituters; | ||||
| 
 | ||||
|     Path linksDir; | ||||
|      | ||||
| public: | ||||
| 
 | ||||
|     /* Initialise the local store, upgrading the schema if
 | ||||
|  | @ -168,7 +169,10 @@ 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 */ | ||||
|  |  | |||
|  | @ -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 */ | ||||
|  |  | |||
|  | @ -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). */ | ||||
|        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)); | ||||
| 
 | ||||
|         std::pair<Path, ino_t> prevPath = hashToPath[hash]; | ||||
|     /* Check if this is a known hash. */ | ||||
|     Path linkPath = linksDir + "/" + printHash32(hash); | ||||
| 
 | ||||
|     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); | ||||
| 
 | ||||
|         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. */ | ||||
|     /* 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 (prevPath.second == st.st_ino) { | ||||
|             printMsg(lvlDebug, format("`%1%' is already linked to `%2%'") % path % prevPath.first); | ||||
|     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 % linkPath); | ||||
| 
 | ||||
|             printMsg(lvlTalkative, format("linking `%1%' to `%2%'") % path % prevPath.first); | ||||
|     Path tempLink = (format("%1%/.tmp-link-%2%-%3%") | ||||
|         % nixStore % getpid() % rand()).str(); | ||||
| 
 | ||||
|             Path tempLink = (format("%1%.tmp-%2%-%3%") | ||||
|                 % path % 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). */ | ||||
|     /* 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. */ | ||||
|     /* 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); | ||||
|     /* 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(prevPath.first.c_str(), tempLink.c_str()) == -1) { | ||||
|     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 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); | ||||
|             /* 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 % prevPath.first); | ||||
|         throw SysError(format("cannot link `%1%' to `%2%'") % tempLink % linkPath); | ||||
|     } | ||||
| 
 | ||||
|     /* 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); | ||||
|             /* 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); | ||||
|         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; | ||||
|     } | ||||
| 
 | ||||
|     if (S_ISDIR(st.st_mode)) { | ||||
|         Strings names = readDirectory(path); | ||||
| 	foreach (Strings::iterator, i, names) | ||||
| 	    hashAndLink(dryRun, hashToPath, stats, path + "/" + *i); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| 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); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -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 */ | ||||
|  |  | |||
|  | @ -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 */ | ||||
|  |  | |||
|  | @ -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 */ | ||||
|  |  | |||
|  | @ -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 */ | ||||
|  |  | |||
|  | @ -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 */ | ||||
|  |  | |||
|  | @ -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 */ | ||||
|  |  | |||
|  | @ -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 */ | ||||
|  |  | |||
|  | @ -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 */ | ||||
|  |  | |||
|  | @ -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 */ | ||||
|  |  | |||
|  | @ -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 */ | ||||
|  |  | |||
|  | @ -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 | ||||
|  |  | |||
|  | @ -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 */ | ||||
|  |  | |||
|  | @ -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 */ | ||||
|  |  | |||
|  | @ -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 */ | ||||
|  |  | |||
|  | @ -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 */ | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -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 */ | ||||
|  |  | |||
|  | @ -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; | ||||
|  |  | |||
|  | @ -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 */ | ||||
|  |  | |||
|  | @ -9,7 +9,7 @@ TESTS = init.sh hash.sh lang.sh add.sh simple.sh dependencies.sh \ | |||
|   gc-runtime.sh install-package.sh check-refs.sh filter-source.sh \ | ||||
|   remote-store.sh export.sh export-graph.sh negative-caching.sh \ | ||||
|   binary-patching.sh timeout.sh secure-drv-outputs.sh nix-channel.sh \ | ||||
|   multiple-outputs.sh import-derivation.sh fetchurl.sh | ||||
|   multiple-outputs.sh import-derivation.sh fetchurl.sh optimise-store.sh | ||||
| 
 | ||||
| XFAIL_TESTS = | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										26
									
								
								tests/optimise-store.sh
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								tests/optimise-store.sh
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,26 @@ | |||
| source common.sh | ||||
| 
 | ||||
| clearStore | ||||
| 
 | ||||
| outPath1=$(echo 'with import ./config.nix; mkDerivation { name = "foo1"; builder = builtins.toFile "builder" "mkdir $out; echo hello > $out/foo"; }' | nix-build - --no-out-link) | ||||
| outPath2=$(echo 'with import ./config.nix; mkDerivation { name = "foo2"; builder = builtins.toFile "builder" "mkdir $out; echo hello > $out/foo"; }' | nix-build - --no-out-link) | ||||
| 
 | ||||
| inode1="$(perl -e "print ((lstat('$outPath1/foo'))[1])")" | ||||
| inode2="$(perl -e "print ((lstat('$outPath2/foo'))[1])")" | ||||
| if [ "$inode1" != "$inode2" ]; then | ||||
|     echo "inodes do not match" | ||||
|     exit 1 | ||||
| fi | ||||
| 
 | ||||
| nlink="$(perl -e "print ((lstat('$outPath1/foo'))[3])")" | ||||
| if [ "$nlink" != 3 ]; then | ||||
|     echo "link count incorrect" | ||||
|     exit 1 | ||||
| fi | ||||
| 
 | ||||
| nix-store --gc | ||||
| 
 | ||||
| if [ -n "$(ls $NIX_STORE_DIR/.links)" ]; then | ||||
|     echo ".links directory not empty after GC" | ||||
|     exit 1 | ||||
| fi | ||||
							
								
								
									
										2
									
								
								version
									
										
									
									
									
								
							
							
						
						
									
										2
									
								
								version
									
										
									
									
									
								
							|  | @ -1 +1 @@ | |||
| 1.1 | ||||
| 1.2 | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue