about summary refs log tree commit diff
path: root/src/libstore
diff options
context:
space:
mode:
authorEelco Dolstra <edolstra@gmail.com>2016-11-25T23·37+0100
committerEelco Dolstra <edolstra@gmail.com>2016-11-25T23·38+0100
commit215b70f51e5abd350c9b7db656aedac9d96d0046 (patch)
tree95778448ecdfbc1d8f4c254813cc5d91ed62a832 /src/libstore
parentf78126bfd6b6c8477fcdbc09b2f98772dbe9a1e7 (diff)
Revert "Get rid of unicode quotes (#1140)"
This reverts commit f78126bfd6b6c8477fcdbc09b2f98772dbe9a1e7. There
really is no need for such a massive change...
Diffstat (limited to 'src/libstore')
-rw-r--r--src/libstore/binary-cache-store.cc18
-rw-r--r--src/libstore/build.cc202
-rw-r--r--src/libstore/builtins.cc4
-rw-r--r--src/libstore/crypto.hh4
-rw-r--r--src/libstore/derivations.cc12
-rw-r--r--src/libstore/download.cc20
-rw-r--r--src/libstore/download.hh2
-rw-r--r--src/libstore/export-import.cc8
-rw-r--r--src/libstore/gc.cc76
-rw-r--r--src/libstore/globals.cc6
-rw-r--r--src/libstore/http-binary-cache-store.cc2
-rw-r--r--src/libstore/local-binary-cache-store.cc2
-rw-r--r--src/libstore/local-fs-store.cc8
-rw-r--r--src/libstore/local-store.cc78
-rw-r--r--src/libstore/local-store.hh2
-rw-r--r--src/libstore/misc.cc2
-rw-r--r--src/libstore/nar-accessor.cc8
-rw-r--r--src/libstore/nar-info.cc2
-rw-r--r--src/libstore/optimise-store.cc48
-rw-r--r--src/libstore/pathlocks.cc14
-rw-r--r--src/libstore/profiles.cc10
-rw-r--r--src/libstore/references.cc4
-rw-r--r--src/libstore/remote-fs-accessor.cc2
-rw-r--r--src/libstore/remote-store.cc6
-rw-r--r--src/libstore/s3-binary-cache-store.cc22
-rw-r--r--src/libstore/sqlite.cc4
-rw-r--r--src/libstore/store-api.cc24
-rw-r--r--src/libstore/store-api.hh38
28 files changed, 314 insertions, 314 deletions
diff --git a/src/libstore/binary-cache-store.cc b/src/libstore/binary-cache-store.cc
index 34a73f00204d..3e07a2aa2b60 100644
--- a/src/libstore/binary-cache-store.cc
+++ b/src/libstore/binary-cache-store.cc
@@ -39,7 +39,7 @@ struct BinaryCacheStoreAccessor : public FSAccessor
         std::string restPath = std::string(path, storePath.size());
 
         if (!store->isValidPath(storePath))
-            throw InvalidPath(format("path '%1%' is not a valid store path") % storePath);
+            throw InvalidPath(format("path ‘%1%’ is not a valid store path") % storePath);
 
         auto i = nars.find(storePath);
         if (i != nars.end()) return {i->second, restPath};
@@ -106,7 +106,7 @@ void BinaryCacheStore::init()
             auto value = trim(line.substr(colon + 1, std::string::npos));
             if (name == "StoreDir") {
                 if (value != storeDir)
-                    throw Error(format("binary cache '%s' is for Nix stores with prefix '%s', not '%s'")
+                    throw Error(format("binary cache ‘%s’ is for Nix stores with prefix ‘%s’, not ‘%s’")
                         % getUri() % value % storeDir);
             } else if (name == "WantMassQuery") {
                 wantMassQuery_ = value == "1";
@@ -153,7 +153,7 @@ void BinaryCacheStore::addToStore(const ValidPathInfo & info, const ref<std::str
             if (ref != info.path)
                 queryPathInfo(ref);
         } catch (InvalidPath &) {
-            throw Error(format("cannot add '%s' to the binary cache because the reference '%s' is not valid")
+            throw Error(format("cannot add ‘%s’ to the binary cache because the reference ‘%s’ is not valid")
                 % info.path % ref);
         }
 
@@ -167,7 +167,7 @@ void BinaryCacheStore::addToStore(const ValidPathInfo & info, const ref<std::str
     narInfo->narHash = hashString(htSHA256, *nar);
 
     if (info.narHash && info.narHash != narInfo->narHash)
-        throw Error(format("refusing to copy corrupted path '%1%' to binary cache") % info.path);
+        throw Error(format("refusing to copy corrupted path ‘%1%’ to binary cache") % info.path);
 
     auto accessor_ = std::dynamic_pointer_cast<BinaryCacheStoreAccessor>(accessor);
 
@@ -241,7 +241,7 @@ void BinaryCacheStore::addToStore(const ValidPathInfo & info, const ref<std::str
     narInfo->fileSize = narCompressed->size();
 
     auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(now2 - now1).count();
-    printMsg(lvlTalkative, format("copying path '%1%' (%2% bytes, compressed %3$.1f%% in %4% ms) to binary cache")
+    printMsg(lvlTalkative, format("copying path ‘%1%’ (%2% bytes, compressed %3$.1f%% in %4% ms) to binary cache")
         % narInfo->path % narInfo->narSize
         % ((1.0 - (double) narCompressed->size() / nar->size()) * 100.0)
         % duration);
@@ -282,7 +282,7 @@ void BinaryCacheStore::addToStore(const ValidPathInfo & info, const ref<std::str
 bool BinaryCacheStore::isValidPathUncached(const Path & storePath)
 {
     // FIXME: this only checks whether a .narinfo with a matching hash
-    // part exists. So 'f4kb...-foo' matches 'f4kb...-bar', even
+    // part exists. So ‘f4kb...-foo’ matches ‘f4kb...-bar’, even
     // though they shouldn't. Not easily fixed.
     return fileExists(narInfoFileFor(storePath));
 }
@@ -293,7 +293,7 @@ void BinaryCacheStore::narFromPath(const Path & storePath, Sink & sink)
 
     auto nar = getFile(info->url);
 
-    if (!nar) throw Error(format("file '%s' missing from binary cache") % info->url);
+    if (!nar) throw Error(format("file ‘%s’ missing from binary cache") % info->url);
 
     stats.narRead++;
     stats.narReadCompressedBytes += nar->size();
@@ -303,13 +303,13 @@ void BinaryCacheStore::narFromPath(const Path & storePath, Sink & sink)
     try {
         nar = decompress(info->compression, *nar);
     } catch (UnknownCompressionMethod &) {
-        throw Error(format("binary cache path '%s' uses unknown compression method '%s'")
+        throw Error(format("binary cache path ‘%s’ uses unknown compression method ‘%s’")
             % storePath % info->compression);
     }
 
     stats.narReadBytes += nar->size();
 
-    printMsg(lvlTalkative, format("exporting path '%1%' (%2% bytes)") % storePath % nar->size());
+    printMsg(lvlTalkative, format("exporting path ‘%1%’ (%2% bytes)") % storePath % nar->size());
 
     assert(nar->size() % 8 == 0);
 
diff --git a/src/libstore/build.cc b/src/libstore/build.cc
index 716b0933f259..ba51f85917f3 100644
--- a/src/libstore/build.cc
+++ b/src/libstore/build.cc
@@ -342,7 +342,7 @@ void Goal::waiteeDone(GoalPtr waitee, ExitCode result)
     assert(waitees.find(waitee) != waitees.end());
     waitees.erase(waitee);
 
-    trace(format("waitee '%1%' done; %2% left") %
+    trace(format("waitee ‘%1%’ done; %2% left") %
         waitee->name % waitees.size());
 
     if (result == ecFailed || result == ecNoSubstituters || result == ecIncompleteClosure) ++nrFailed;
@@ -414,7 +414,7 @@ static void commonChildInit(Pipe & logPipe)
     /* Reroute stdin to /dev/null. */
     int fdDevNull = open(pathNullDevice.c_str(), O_RDWR);
     if (fdDevNull == -1)
-        throw SysError(format("cannot open '%1%'") % pathNullDevice);
+        throw SysError(format("cannot open ‘%1%’") % pathNullDevice);
     if (dup2(fdDevNull, STDIN_FILENO) == -1)
         throw SysError("cannot dup null device into stdin");
     close(fdDevNull);
@@ -477,29 +477,29 @@ void UserLock::acquire()
     /* Get the members of the build-users-group. */
     struct group * gr = getgrnam(settings.buildUsersGroup.c_str());
     if (!gr)
-        throw Error(format("the group '%1%' specified in 'build-users-group' does not exist")
+        throw Error(format("the group ‘%1%’ specified in ‘build-users-group’ does not exist")
             % settings.buildUsersGroup);
     gid = gr->gr_gid;
 
     /* Copy the result of getgrnam. */
     Strings users;
     for (char * * p = gr->gr_mem; *p; ++p) {
-        debug(format("found build user '%1%'") % *p);
+        debug(format("found build user ‘%1%’") % *p);
         users.push_back(*p);
     }
 
     if (users.empty())
-        throw Error(format("the build users group '%1%' has no members")
+        throw Error(format("the build users group ‘%1%’ has no members")
             % settings.buildUsersGroup);
 
     /* Find a user account that isn't currently in use for another
        build. */
     for (auto & i : users) {
-        debug(format("trying user '%1%'") % i);
+        debug(format("trying user ‘%1%’") % i);
 
         struct passwd * pw = getpwnam(i.c_str());
         if (!pw)
-            throw Error(format("the user '%1%' in the group '%2%' does not exist")
+            throw Error(format("the user ‘%1%’ in the group ‘%2%’ does not exist")
                 % i % settings.buildUsersGroup);
 
         createDirs(settings.nixStateDir + "/userpool");
@@ -512,7 +512,7 @@ void UserLock::acquire()
 
         AutoCloseFD fd = open(fnUserLock.c_str(), O_RDWR | O_CREAT | O_CLOEXEC, 0600);
         if (!fd)
-            throw SysError(format("opening user lock '%1%'") % fnUserLock);
+            throw SysError(format("opening user lock ‘%1%’") % fnUserLock);
 
         if (lockFile(fd.get(), ltWrite, false)) {
             fdUserLock = std::move(fd);
@@ -522,7 +522,7 @@ void UserLock::acquire()
 
             /* Sanity check... */
             if (uid == getuid() || uid == geteuid())
-                throw Error(format("the Nix user should not be a member of '%1%'")
+                throw Error(format("the Nix user should not be a member of ‘%1%’")
                     % settings.buildUsersGroup);
 
 #if __linux__
@@ -533,7 +533,7 @@ void UserLock::acquire()
             int err = getgrouplist(pw->pw_name, pw->pw_gid,
                 supplementaryGIDs.data(), &ngroups);
             if (err == -1)
-                throw Error(format("failed to get list of supplementary groups for '%1%'") % pw->pw_name);
+                throw Error(format("failed to get list of supplementary groups for ‘%1%’") % pw->pw_name);
 
             supplementaryGIDs.resize(ngroups);
 #endif
@@ -543,7 +543,7 @@ void UserLock::acquire()
     }
 
     throw Error(format("all build users are currently in use; "
-        "consider creating additional users and adding them to the '%1%' group")
+        "consider creating additional users and adding them to the ‘%1%’ group")
         % settings.buildUsersGroup);
 }
 
@@ -630,7 +630,7 @@ HookInstance::HookInstance()
 
         execv(buildHook.c_str(), stringsToCharPtrs(args).data());
 
-        throw SysError(format("executing '%1%'") % buildHook);
+        throw SysError(format("executing ‘%1%’") % buildHook);
     });
 
     pid.setSeparatePG(true);
@@ -910,7 +910,7 @@ DerivationGoal::DerivationGoal(const Path & drvPath, const StringSet & wantedOut
     , buildMode(buildMode)
 {
     state = &DerivationGoal::getDerivation;
-    name = (format("building of '%1%'") % drvPath).str();
+    name = (format("building of ‘%1%’") % drvPath).str();
     trace("created");
 }
 
@@ -1021,7 +1021,7 @@ void DerivationGoal::loadDerivation()
     trace("loading derivation");
 
     if (nrFailed != 0) {
-        printError(format("cannot build missing derivation '%1%'") % drvPath);
+        printError(format("cannot build missing derivation ‘%1%’") % drvPath);
         done(BuildResult::MiscFailure);
         return;
     }
@@ -1062,7 +1062,7 @@ void DerivationGoal::haveDerivation()
         if (drv->outputs.size() != 1 ||
             drv->outputs.find("out") == drv->outputs.end() ||
             drv->outputs["out"].hashAlgo == "")
-            throw Error(format("cannot do a hash build of non-fixed-output derivation '%1%'") % drvPath);
+            throw Error(format("cannot do a hash build of non-fixed-output derivation ‘%1%’") % drvPath);
     }
 
     /* We are first going to try to create the invalid output paths
@@ -1084,7 +1084,7 @@ void DerivationGoal::outputsSubstituted()
     trace("all outputs substituted (maybe)");
 
     if (nrFailed > 0 && nrFailed > nrNoSubstituters + nrIncompleteClosure && !settings.tryFallback) {
-        done(BuildResult::TransientFailure, (format("some substitutes for the outputs of derivation '%1%' failed (usually happens due to networking issues); try '--fallback' to build derivation from source ") % drvPath).str());
+        done(BuildResult::TransientFailure, (format("some substitutes for the outputs of derivation ‘%1%’ failed (usually happens due to networking issues); try ‘--fallback’ to build derivation from source ") % drvPath).str());
         return;
     }
 
@@ -1111,7 +1111,7 @@ void DerivationGoal::outputsSubstituted()
         return;
     }
     if (buildMode == bmCheck && nrInvalid > 0)
-        throw Error(format("some outputs of '%1%' are not valid, so checking is not possible") % drvPath);
+        throw Error(format("some outputs of ‘%1%’ are not valid, so checking is not possible") % drvPath);
 
     /* Otherwise, at least one of the output paths could not be
        produced using a substitute.  So we have to build instead. */
@@ -1128,7 +1128,7 @@ void DerivationGoal::outputsSubstituted()
     for (auto & i : drv->inputSrcs) {
         if (worker.store.isValidPath(i)) continue;
         if (!settings.useSubstitutes)
-            throw Error(format("dependency of '%1%' of '%2%' does not exist, and substitution is disabled")
+            throw Error(format("dependency of ‘%1%’ of ‘%2%’ does not exist, and substitution is disabled")
                 % i % drvPath);
         addWaitee(worker.makeSubstitutionGoal(i));
     }
@@ -1175,7 +1175,7 @@ void DerivationGoal::repairClosure()
     PathSet broken;
     for (auto & i : outputClosure) {
         if (worker.pathContentsGood(i)) continue;
-        printError(format("found corrupted or missing path '%1%' in the output closure of '%2%'") % i % drvPath);
+        printError(format("found corrupted or missing path ‘%1%’ in the output closure of ‘%2%’") % i % drvPath);
         Path drvPath2 = outputsToDrv[i];
         if (drvPath2 == "")
             addWaitee(worker.makeSubstitutionGoal(i, true));
@@ -1196,7 +1196,7 @@ void DerivationGoal::closureRepaired()
 {
     trace("closure repaired");
     if (nrFailed > 0)
-        throw Error(format("some paths in the output closure of derivation '%1%' could not be repaired") % drvPath);
+        throw Error(format("some paths in the output closure of derivation ‘%1%’ could not be repaired") % drvPath);
     done(BuildResult::AlreadyValid);
 }
 
@@ -1207,9 +1207,9 @@ void DerivationGoal::inputsRealised()
 
     if (nrFailed != 0) {
         if (!useDerivation)
-            throw Error(format("some dependencies of '%1%' are missing") % drvPath);
+            throw Error(format("some dependencies of ‘%1%’ are missing") % drvPath);
         printError(
-            format("cannot build derivation '%1%': %2% dependencies couldn't be built")
+            format("cannot build derivation ‘%1%’: %2% dependencies couldn't be built")
             % drvPath % nrFailed);
         done(BuildResult::DependencyFailed);
         return;
@@ -1225,7 +1225,7 @@ void DerivationGoal::inputsRealised()
 
     /* The outputs are referenceable paths. */
     for (auto & i : drv->outputs) {
-        debug(format("building path '%1%'") % i.second.path);
+        debug(format("building path ‘%1%’") % i.second.path);
         allPaths.insert(i.second.path);
     }
 
@@ -1244,7 +1244,7 @@ void DerivationGoal::inputsRealised()
                     worker.store.computeFSClosure(inDrv.outputs[j].path, inputPaths);
                 else
                     throw Error(
-                        format("derivation '%1%' requires non-existent output '%2%' from input derivation '%3%'")
+                        format("derivation ‘%1%’ requires non-existent output ‘%2%’ from input derivation ‘%3%’")
                         % drvPath % j % i.first);
         }
 
@@ -1283,7 +1283,7 @@ void DerivationGoal::tryToBuild()
        goal to sleep until another goal finishes, then try again. */
     for (auto & i : drv->outputs)
         if (pathIsLockedByMe(worker.store.toRealPath(i.second.path))) {
-            debug(format("putting derivation '%1%' to sleep because '%2%' is locked by another goal")
+            debug(format("putting derivation ‘%1%’ to sleep because ‘%2%’ is locked by another goal")
                 % drvPath % i.second.path);
             worker.waitForAnyGoal(shared_from_this());
             return;
@@ -1312,7 +1312,7 @@ void DerivationGoal::tryToBuild()
        build this derivation, so no further checks are necessary. */
     validPaths = checkPathValidity(true, buildMode == bmRepair);
     if (buildMode != bmCheck && validPaths.size() == drv->outputs.size()) {
-        debug(format("skipping build of derivation '%1%', someone beat us to it") % drvPath);
+        debug(format("skipping build of derivation ‘%1%’, someone beat us to it") % drvPath);
         outputLocks.setDeletion(true);
         done(BuildResult::AlreadyValid);
         return;
@@ -1327,7 +1327,7 @@ void DerivationGoal::tryToBuild()
     for (auto & i : drv->outputs) {
         Path path = i.second.path;
         if (worker.store.isValidPath(path)) continue;
-        debug(format("removing invalid path '%1%'") % path);
+        debug(format("removing invalid path ‘%1%’") % path);
         deletePath(worker.store.toRealPath(path));
     }
 
@@ -1396,7 +1396,7 @@ void replaceValidPath(const Path & storePath, const Path tmpPath)
     if (pathExists(storePath))
         rename(storePath.c_str(), oldPath.c_str());
     if (rename(tmpPath.c_str(), storePath.c_str()) == -1)
-        throw SysError(format("moving '%1%' to '%2%'") % tmpPath % storePath);
+        throw SysError(format("moving ‘%1%’ to ‘%2%’") % tmpPath % storePath);
     deletePath(oldPath);
 }
 
@@ -1416,7 +1416,7 @@ void DerivationGoal::buildDone()
        child */
     int status = hook ? hook->pid.wait(true) : pid.wait(true);
 
-    debug(format("builder process for '%1%' finished") % drvPath);
+    debug(format("builder process for ‘%1%’ finished") % drvPath);
 
     /* So the child is gone now. */
     worker.childTerminated(this);
@@ -1470,7 +1470,7 @@ void DerivationGoal::buildDone()
                     if (pathExists(chrootRootDir + i))
                         rename((chrootRootDir + i).c_str(), i.c_str());
 
-            std::string msg = (format("builder for '%1%' %2%")
+            std::string msg = (format("builder for ‘%1%’ %2%")
                 % drvPath % statusToString(status)).str();
 
             if (!settings.verboseBuild && !logTail.empty()) {
@@ -1583,12 +1583,12 @@ HookReply DerivationGoal::tryBuildHook()
         writeToStderr(s);
     }
 
-    debug(format("hook reply is '%1%'") % reply);
+    debug(format("hook reply is ‘%1%’") % reply);
 
     if (reply == "decline" || reply == "postpone")
         return reply == "decline" ? rpDecline : rpPostpone;
     else if (reply != "accept")
-        throw Error(format("bad hook reply '%1%'") % reply);
+        throw Error(format("bad hook reply ‘%1%’") % reply);
 
     printMsg(lvlTalkative, format("using hook to build path(s) %1%") % showPaths(missingPaths));
 
@@ -1631,7 +1631,7 @@ HookReply DerivationGoal::tryBuildHook()
 void chmod_(const Path & path, mode_t mode)
 {
     if (chmod(path.c_str(), mode) == -1)
-        throw SysError(format("setting permissions on '%1%'") % path);
+        throw SysError(format("setting permissions on ‘%1%’") % path);
 }
 
 
@@ -1655,7 +1655,7 @@ void DerivationGoal::startBuilder()
     /* Right platform? */
     if (!drv->canBuildLocally()) {
         throw Error(
-            format("a '%1%' is required to build '%3%', but I am a '%2%'")
+            format("a ‘%1%’ is required to build ‘%3%’, but I am a ‘%2%’")
             % drv->platform % settings.thisSystem % drvPath);
     }
 
@@ -1673,15 +1673,15 @@ void DerivationGoal::startBuilder()
             /* deprecated alias */
             settings.get("build-use-chroot", string("false")));
         if (x != "true" && x != "false" && x != "relaxed")
-            throw Error("option 'build-use-sandbox' must be set to one of 'true', 'false' or 'relaxed'");
+            throw Error("option ‘build-use-sandbox’ must be set to one of ‘true’, ‘false’ or ‘relaxed’");
         if (x == "true") {
             if (get(drv->env, "__noChroot") == "1")
-                throw Error(format("derivation '%1%' has '__noChroot' set, "
-                    "but that's not allowed when 'build-use-sandbox' is 'true'") % drvPath);
+                throw Error(format("derivation ‘%1%’ has ‘__noChroot’ set, "
+                    "but that's not allowed when ‘build-use-sandbox’ is ‘true’") % drvPath);
 #if __APPLE__
             if (additionalSandboxProfile != "")
-                throw Error(format("derivation '%1%' specifies a sandbox profile, "
-                    "but this is only allowed when 'build-use-sandbox' is 'relaxed'") % drvPath);
+                throw Error(format("derivation ‘%1%’ specifies a sandbox profile, "
+                    "but this is only allowed when ‘build-use-sandbox’ is ‘relaxed’") % drvPath);
 #endif
             useChroot = true;
         }
@@ -1795,7 +1795,7 @@ void DerivationGoal::startBuilder()
     string s = get(drv->env, "exportReferencesGraph");
     Strings ss = tokenizeString<Strings>(s);
     if (ss.size() % 2 != 0)
-        throw BuildError(format("odd number of tokens in 'exportReferencesGraph': '%1%'") % s);
+        throw BuildError(format("odd number of tokens in ‘exportReferencesGraph’: ‘%1%’") % s);
     for (Strings::iterator i = ss.begin(); i != ss.end(); ) {
         string fileName = *i++;
         checkStoreName(fileName); /* !!! abuse of this function */
@@ -1803,11 +1803,11 @@ void DerivationGoal::startBuilder()
         /* Check that the store path is valid. */
         Path storePath = *i++;
         if (!worker.store.isInStore(storePath))
-            throw BuildError(format("'exportReferencesGraph' contains a non-store path '%1%'")
+            throw BuildError(format("‘exportReferencesGraph’ contains a non-store path ‘%1%’")
                 % storePath);
         storePath = worker.store.toStorePath(storePath);
         if (!worker.store.isValidPath(storePath))
-            throw BuildError(format("'exportReferencesGraph' contains an invalid path '%1%'")
+            throw BuildError(format("‘exportReferencesGraph’ contains an invalid path ‘%1%’")
                 % storePath);
 
         /* If there are derivations in the graph, then include their
@@ -1846,7 +1846,7 @@ void DerivationGoal::startBuilder()
 
         for (auto & p : filesToChown)
             if (chown(p.c_str(), buildUser.getUID(), buildUser.getGID()) == -1)
-                throw SysError(format("cannot change ownership of '%1%'") % p);
+                throw SysError(format("cannot change ownership of ‘%1%’") % p);
     }
 
 
@@ -1893,7 +1893,7 @@ void DerivationGoal::startBuilder()
                 if (worker.store.isInStore(i.second.source))
                     worker.store.computeFSClosure(worker.store.toStorePath(i.second.source), closure);
             } catch (Error & e) {
-                throw Error(format("while processing 'build-sandbox-paths': %s") % e.what());
+                throw Error(format("while processing ‘build-sandbox-paths’: %s") % e.what());
             }
         for (auto & i : closure)
             dirsInChroot[i] = i;
@@ -1919,7 +1919,7 @@ void DerivationGoal::startBuilder()
                 }
             }
             if (!found)
-                throw Error(format("derivation '%1%' requested impure path '%2%', but it was not in allowed-impure-host-deps ('%3%')") % drvPath % i % allowed);
+                throw Error(format("derivation ‘%1%’ requested impure path ‘%2%’, but it was not in allowed-impure-host-deps (‘%3%’)") % drvPath % i % allowed);
 
             dirsInChroot[i] = i;
         }
@@ -1935,13 +1935,13 @@ void DerivationGoal::startBuilder()
         /* Clean up the chroot directory automatically. */
         autoDelChroot = std::make_shared<AutoDelete>(chrootRootDir);
 
-        printMsg(lvlChatty, format("setting up chroot environment in '%1%'") % chrootRootDir);
+        printMsg(lvlChatty, format("setting up chroot environment in ‘%1%’") % chrootRootDir);
 
         if (mkdir(chrootRootDir.c_str(), 0750) == -1)
-            throw SysError(format("cannot create '%1%'") % chrootRootDir);
+            throw SysError(format("cannot create ‘%1%’") % chrootRootDir);
 
         if (buildUser.enabled() && chown(chrootRootDir.c_str(), 0, buildUser.getGID()) == -1)
-            throw SysError(format("cannot change ownership of '%1%'") % chrootRootDir);
+            throw SysError(format("cannot change ownership of ‘%1%’") % chrootRootDir);
 
         /* Create a writable /tmp in the chroot.  Many builders need
            this.  (Of course they should really respect $TMPDIR
@@ -1985,13 +1985,13 @@ void DerivationGoal::startBuilder()
         chmod_(chrootStoreDir, 01775);
 
         if (buildUser.enabled() && chown(chrootStoreDir.c_str(), 0, buildUser.getGID()) == -1)
-            throw SysError(format("cannot change ownership of '%1%'") % chrootStoreDir);
+            throw SysError(format("cannot change ownership of ‘%1%’") % chrootStoreDir);
 
         for (auto & i : inputPaths) {
             Path r = worker.store.toRealPath(i);
             struct stat st;
             if (lstat(r.c_str(), &st))
-                throw SysError(format("getting attributes of path '%1%'") % i);
+                throw SysError(format("getting attributes of path ‘%1%’") % i);
             if (S_ISDIR(st.st_mode))
                 dirsInChroot[i] = r;
             else {
@@ -2002,7 +2002,7 @@ void DerivationGoal::startBuilder()
                        which is quite possible after a `nix-store
                        --optimise'. */
                     if (errno != EMLINK)
-                        throw SysError(format("linking '%1%' to '%2%'") % p % i);
+                        throw SysError(format("linking ‘%1%’ to ‘%2%’") % p % i);
                     StringSink sink;
                     dumpPath(r, sink);
                     StringSource source(*sink.s);
@@ -2030,7 +2030,7 @@ void DerivationGoal::startBuilder()
     else {
 
         if (pathExists(homeDir))
-            throw Error(format("directory '%1%' exists; please remove it") % homeDir);
+            throw Error(format("directory ‘%1%’ exists; please remove it") % homeDir);
 
         /* We're not doing a chroot build, but we have some valid
            output paths.  Since we can't just overwrite or delete
@@ -2056,7 +2056,7 @@ void DerivationGoal::startBuilder()
     }
 
     if (settings.preBuildHook != "") {
-        printMsg(lvlChatty, format("executing pre-build hook '%1%'")
+        printMsg(lvlChatty, format("executing pre-build hook ‘%1%’")
             % settings.preBuildHook);
         auto args = useChroot ? Strings({drvPath, chrootRootDir}) :
             Strings({ drvPath });
@@ -2075,7 +2075,7 @@ void DerivationGoal::startBuilder()
                 if (line == "extra-sandbox-paths" || line == "extra-chroot-dirs") {
                     state = stExtraChrootDirs;
                 } else {
-                    throw Error(format("unknown pre-build hook command '%1%'")
+                    throw Error(format("unknown pre-build hook command ‘%1%’")
                         % line);
                 }
             } else if (state == stExtraChrootDirs) {
@@ -2093,7 +2093,7 @@ void DerivationGoal::startBuilder()
     }
 
     /* Run the builder. */
-    printMsg(lvlChatty, format("executing builder '%1%'") % drv->builder);
+    printMsg(lvlChatty, format("executing builder ‘%1%’") % drv->builder);
 
     /* Create the log file. */
     Path logFile = openLogFile();
@@ -2288,13 +2288,13 @@ void DerivationGoal::runChild()
                 vector<string> fields = tokenizeString<vector<string> >(i, " ");
                 string fs = decodeOctalEscaped(fields.at(4));
                 if (mount(0, fs.c_str(), 0, MS_PRIVATE, 0) == -1)
-                    throw SysError(format("unable to make filesystem '%1%' private") % fs);
+                    throw SysError(format("unable to make filesystem ‘%1%’ private") % fs);
             }
 
             /* Bind-mount chroot directory to itself, to treat it as a
                different filesystem from /, as needed for pivot_root. */
             if (mount(chrootRootDir.c_str(), chrootRootDir.c_str(), 0, MS_BIND, 0) == -1)
-                throw SysError(format("unable to bind mount '%1%'") % chrootRootDir);
+                throw SysError(format("unable to bind mount ‘%1%’") % chrootRootDir);
 
             /* Set up a nearly empty /dev, unless the user asked to
                bind-mount the host /dev. */
@@ -2340,12 +2340,12 @@ void DerivationGoal::runChild()
                 Path source = i.second.source;
                 Path target = chrootRootDir + i.first;
                 if (source == "/proc") continue; // backwards compatibility
-                debug(format("bind mounting '%1%' to '%2%'") % source % target);
+                debug(format("bind mounting ‘%1%’ to ‘%2%’") % source % target);
                 if (stat(source.c_str(), &st) == -1) {
                     if (i.second.optional && errno == ENOENT)
                         continue;
                     else
-                        throw SysError(format("getting attributes of path '%1%'") % source);
+                        throw SysError(format("getting attributes of path ‘%1%’") % source);
                 }
                 if (S_ISDIR(st.st_mode))
                     createDirs(target);
@@ -2354,7 +2354,7 @@ void DerivationGoal::runChild()
                     writeFile(target, "");
                 }
                 if (mount(source.c_str(), target.c_str(), "", MS_BIND | MS_REC, 0) == -1)
-                    throw SysError(format("bind mount from '%1%' to '%2%' failed") % source % target);
+                    throw SysError(format("bind mount from ‘%1%’ to ‘%2%’ failed") % source % target);
             }
 
             /* Bind a new instance of procfs on /proc. */
@@ -2392,16 +2392,16 @@ void DerivationGoal::runChild()
 
             /* Do the chroot(). */
             if (chdir(chrootRootDir.c_str()) == -1)
-                throw SysError(format("cannot change directory to '%1%'") % chrootRootDir);
+                throw SysError(format("cannot change directory to ‘%1%’") % chrootRootDir);
 
             if (mkdir("real-root", 0) == -1)
                 throw SysError("cannot create real-root directory");
 
             if (pivot_root(".", "real-root") == -1)
-                throw SysError(format("cannot pivot old root directory onto '%1%'") % (chrootRootDir + "/real-root"));
+                throw SysError(format("cannot pivot old root directory onto ‘%1%’") % (chrootRootDir + "/real-root"));
 
             if (chroot(".") == -1)
-                throw SysError(format("cannot change root directory to '%1%'") % chrootRootDir);
+                throw SysError(format("cannot change root directory to ‘%1%’") % chrootRootDir);
 
             if (umount2("real-root", MNT_DETACH) == -1)
                 throw SysError("cannot unmount real root filesystem");
@@ -2422,7 +2422,7 @@ void DerivationGoal::runChild()
 #endif
 
         if (chdir(tmpDirInSandbox.c_str()) == -1)
-            throw SysError(format("changing into '%1%'") % tmpDir);
+            throw SysError(format("changing into ‘%1%’") % tmpDir);
 
         /* Close all other file descriptors. */
         closeMostFDs(set<int>());
@@ -2564,7 +2564,7 @@ void DerivationGoal::runChild()
                 if (lstat(path.c_str(), &st)) {
                     if (i.second.optional && errno == ENOENT)
                         continue;
-                    throw SysError(format("getting attributes of path '%1%'") % path);
+                    throw SysError(format("getting attributes of path ‘%1%’") % path);
                 }
                 if (S_ISDIR(st.st_mode))
                     sandboxProfile += (format("\t(subpath \"%1%\")\n") % path).str();
@@ -2619,7 +2619,7 @@ void DerivationGoal::runChild()
                 if (drv->builder == "builtin:fetchurl")
                     builtinFetchurl(*drv);
                 else
-                    throw Error(format("unsupported builtin function '%1%'") % string(drv->builder, 8));
+                    throw Error(format("unsupported builtin function ‘%1%’") % string(drv->builder, 8));
                 _exit(0);
             } catch (std::exception & e) {
                 writeFull(STDERR_FILENO, "error: " + string(e.what()) + "\n");
@@ -2629,7 +2629,7 @@ void DerivationGoal::runChild()
 
         execve(builder, stringsToCharPtrs(args).data(), stringsToCharPtrs(envStrs).data());
 
-        throw SysError(format("executing '%1%'") % drv->builder);
+        throw SysError(format("executing ‘%1%’") % drv->builder);
 
     } catch (std::exception & e) {
         writeFull(STDERR_FILENO, "\1while setting up the build environment: " + string(e.what()) + "\n");
@@ -2651,7 +2651,7 @@ PathSet parseReferenceSpecifiers(Store & store, const BasicDerivation & drv, str
         else if (drv.outputs.find(i) != drv.outputs.end())
             result.insert(drv.outputs.find(i)->second.path);
         else throw BuildError(
-            format("derivation contains an illegal reference specifier '%1%'") % i);
+            format("derivation contains an illegal reference specifier ‘%1%’") % i);
     }
     return result;
 }
@@ -2694,7 +2694,7 @@ void DerivationGoal::registerOutputs()
                     replaceValidPath(path, actualPath);
                 else
                     if (buildMode != bmCheck && rename(actualPath.c_str(), worker.store.toRealPath(path).c_str()) == -1)
-                        throw SysError(format("moving build output '%1%' from the sandbox to the Nix store") % path);
+                        throw SysError(format("moving build output ‘%1%’ from the sandbox to the Nix store") % path);
             }
             if (buildMode != bmCheck) actualPath = worker.store.toRealPath(path);
         } else {
@@ -2711,9 +2711,9 @@ void DerivationGoal::registerOutputs()
         if (lstat(actualPath.c_str(), &st) == -1) {
             if (errno == ENOENT)
                 throw BuildError(
-                    format("builder for '%1%' failed to produce output path '%2%'")
+                    format("builder for ‘%1%’ failed to produce output path ‘%2%’")
                     % drvPath % path);
-            throw SysError(format("getting attributes of path '%1%'") % actualPath);
+            throw SysError(format("getting attributes of path ‘%1%’") % actualPath);
         }
 
 #ifndef __CYGWIN__
@@ -2723,13 +2723,13 @@ void DerivationGoal::registerOutputs()
            user. */
         if ((!S_ISLNK(st.st_mode) && (st.st_mode & (S_IWGRP | S_IWOTH))) ||
             (buildUser.enabled() && st.st_uid != buildUser.getUID()))
-            throw BuildError(format("suspicious ownership or permission on '%1%'; rejecting this build output") % path);
+            throw BuildError(format("suspicious ownership or permission on ‘%1%’; rejecting this build output") % path);
 #endif
 
         /* Apply hash rewriting if necessary. */
         bool rewritten = false;
         if (!outputRewrites.empty()) {
-            printError(format("warning: rewriting hashes in '%1%'; cross fingers") % path);
+            printError(format("warning: rewriting hashes in ‘%1%’; cross fingers") % path);
 
             /* Canonicalise first.  This ensures that the path we're
                rewriting doesn't contain a hard link to /etc/shadow or
@@ -2760,7 +2760,7 @@ void DerivationGoal::registerOutputs()
                    execute permission. */
                 if (!S_ISREG(st.st_mode) || (st.st_mode & S_IXUSR) != 0)
                     throw BuildError(
-                        format("output path '%1%' should be a non-executable regular file") % path);
+                        format("output path ‘%1%’ should be a non-executable regular file") % path);
             }
 
             /* Check the hash. In hash mode, move the path produced by
@@ -2768,7 +2768,7 @@ void DerivationGoal::registerOutputs()
             Hash h2 = recursive ? hashPath(h.type, actualPath).first : hashFile(h.type, actualPath);
             if (buildMode == bmHash) {
                 Path dest = worker.store.makeFixedOutputPath(recursive, h2, drv->env["name"]);
-                printError(format("build produced path '%1%' with %2% hash '%3%'")
+                printError(format("build produced path ‘%1%’ with %2% hash ‘%3%’")
                     % dest % printHashType(h.type) % printHash16or32(h2));
                 if (worker.store.isValidPath(dest))
                     return;
@@ -2777,14 +2777,14 @@ void DerivationGoal::registerOutputs()
                     PathLocks outputLocks({actualDest});
                     deletePath(actualDest);
                     if (rename(actualPath.c_str(), actualDest.c_str()) == -1)
-                        throw SysError(format("moving '%1%' to '%2%'") % actualPath % dest);
+                        throw SysError(format("moving ‘%1%’ to ‘%2%’") % actualPath % dest);
                 }
                 path = dest;
                 actualPath = actualDest;
             } else {
                 if (h != h2)
                     throw BuildError(
-                        format("output path '%1%' has %2% hash '%3%' when '%4%' was expected")
+                        format("output path ‘%1%’ has %2% hash ‘%3%’ when ‘%4%’ was expected")
                         % path % i.second.hashAlgo % printHash16or32(h2) % printHash16or32(h));
             }
         }
@@ -2798,7 +2798,7 @@ void DerivationGoal::registerOutputs()
            contained in it.  Compute the SHA-256 NAR hash at the same
            time.  The hash is stored in the database so that we can
            verify later on whether nobody has messed with the store. */
-        Activity act(*logger, lvlTalkative, format("scanning for references inside '%1%'") % path);
+        Activity act(*logger, lvlTalkative, format("scanning for references inside ‘%1%’") % path);
         HashResult hash;
         PathSet references = scanForReferences(actualPath, allPaths, hash);
 
@@ -2810,11 +2810,11 @@ void DerivationGoal::registerOutputs()
                     Path dst = worker.store.toRealPath(path + checkSuffix);
                     deletePath(dst);
                     if (rename(actualPath.c_str(), dst.c_str()))
-                        throw SysError(format("renaming '%1%' to '%2%'") % actualPath % dst);
-                    throw Error(format("derivation '%1%' may not be deterministic: output '%2%' differs from '%3%'")
+                        throw SysError(format("renaming ‘%1%’ to ‘%2%’") % actualPath % dst);
+                    throw Error(format("derivation ‘%1%’ may not be deterministic: output ‘%2%’ differs from ‘%3%’")
                         % drvPath % path % dst);
                 } else
-                    throw Error(format("derivation '%1%' may not be deterministic: output '%2%' differs")
+                    throw Error(format("derivation ‘%1%’ may not be deterministic: output ‘%2%’ differs")
                         % drvPath % path);
             }
 
@@ -2834,9 +2834,9 @@ void DerivationGoal::registerOutputs()
         for (auto & i : inputPaths) {
             PathSet::iterator j = references.find(i);
             if (j == references.end())
-                debug(format("unreferenced input: '%1%'") % i);
+                debug(format("unreferenced input: ‘%1%’") % i);
             else
-                debug(format("referenced input: '%1%'") % i);
+                debug(format("referenced input: ‘%1%’") % i);
         }
 
         /* Enforce `allowedReferences' and friends. */
@@ -2872,7 +2872,7 @@ void DerivationGoal::registerOutputs()
                     badPathsStr += "\n\t";
                     badPathsStr += i;
                 }
-                throw BuildError(format("output '%1%' is not allowed to refer to the following paths:%2%") % actualPath % badPathsStr);
+                throw BuildError(format("output ‘%1%’ is not allowed to refer to the following paths:%2%") % actualPath % badPathsStr);
             }
         };
 
@@ -2909,11 +2909,11 @@ void DerivationGoal::registerOutputs()
                 Path prev = i->path + checkSuffix;
                 if (pathExists(prev))
                     throw NotDeterministic(
-                        format("output '%1%' of '%2%' differs from '%3%' from previous round")
+                        format("output ‘%1%’ of ‘%2%’ differs from ‘%3%’ from previous round")
                         % i->path % drvPath % prev);
                 else
                     throw NotDeterministic(
-                        format("output '%1%' of '%2%' differs from previous round")
+                        format("output ‘%1%’ of ‘%2%’ differs from previous round")
                         % i->path % drvPath);
             }
         abort(); // shouldn't happen
@@ -2926,7 +2926,7 @@ void DerivationGoal::registerOutputs()
             if (curRound < nrRounds) {
                 Path dst = i.second.path + checkSuffix;
                 if (rename(i.second.path.c_str(), dst.c_str()))
-                    throw SysError(format("renaming '%1%' to '%2%'") % i.second.path % dst);
+                    throw SysError(format("renaming ‘%1%’ to ‘%2%’") % i.second.path % dst);
             }
         }
 
@@ -2965,7 +2965,7 @@ Path DerivationGoal::openLogFile()
         % (settings.compressLog ? ".bz2" : "")).str();
 
     fdLogFile = open(logFileName.c_str(), O_CREAT | O_WRONLY | O_TRUNC | O_CLOEXEC, 0666);
-    if (!fdLogFile) throw SysError(format("creating log file '%1%'") % logFileName);
+    if (!fdLogFile) throw SysError(format("creating log file ‘%1%’") % logFileName);
 
     logFileSink = std::make_shared<FdSink>(fdLogFile.get());
 
@@ -2993,7 +2993,7 @@ void DerivationGoal::deleteTmpDir(bool force)
     if (tmpDir != "") {
         if (settings.keepFailed && !force) {
             printError(
-                format("note: keeping build directory '%2%'")
+                format("note: keeping build directory ‘%2%’")
                 % drvPath % tmpDir);
             chmod(tmpDir.c_str(), 0755);
         }
@@ -3177,7 +3177,7 @@ SubstitutionGoal::SubstitutionGoal(const Path & storePath, Worker & worker, bool
 {
     this->storePath = storePath;
     state = &SubstitutionGoal::init;
-    name = (format("substitution of '%1%'") % storePath).str();
+    name = (format("substitution of ‘%1%’") % storePath).str();
     trace("created");
 }
 
@@ -3215,7 +3215,7 @@ void SubstitutionGoal::init()
     }
 
     if (settings.readOnlyMode)
-        throw Error(format("cannot substitute path '%1%' - no write access to the Nix store") % storePath);
+        throw Error(format("cannot substitute path ‘%1%’ - no write access to the Nix store") % storePath);
 
     subs = settings.useSubstitutes ? getDefaultSubstituters() : std::list<ref<Store>>();
 
@@ -3230,7 +3230,7 @@ void SubstitutionGoal::tryNext()
     if (subs.size() == 0) {
         /* None left.  Terminate this goal and let someone else deal
            with it. */
-        debug(format("path '%1%' is required, but there is no substituter that can build it") % storePath);
+        debug(format("path ‘%1%’ is required, but there is no substituter that can build it") % storePath);
 
         /* Hack: don't indicate failure if there were no substituters.
            In that case the calling derivation should just do a
@@ -3261,7 +3261,7 @@ void SubstitutionGoal::tryNext()
        signature. LocalStore::addToStore() also checks for this, but
        only after we've downloaded the path. */
     if (worker.store.requireSigs && !info->checkSignatures(worker.store, worker.store.publicKeys)) {
-        printInfo(format("warning: substituter '%s' does not have a valid signature for path '%s'")
+        printInfo(format("warning: substituter ‘%s’ does not have a valid signature for path ‘%s’")
             % sub->getUri() % storePath);
         tryNext();
         return;
@@ -3285,7 +3285,7 @@ void SubstitutionGoal::referencesValid()
     trace("all references realised");
 
     if (nrFailed > 0) {
-        debug(format("some references of path '%1%' could not be realised") % storePath);
+        debug(format("some references of path ‘%1%’ could not be realised") % storePath);
         amDone(nrNoSubstituters > 0 || nrIncompleteClosure > 0 ? ecIncompleteClosure : ecFailed);
         return;
     }
@@ -3312,7 +3312,7 @@ void SubstitutionGoal::tryToRun()
         return;
     }
 
-    printInfo(format("fetching path '%1%'...") % storePath);
+    printInfo(format("fetching path ‘%1%’...") % storePath);
 
     outPipe.create();
 
@@ -3359,7 +3359,7 @@ void SubstitutionGoal::finished()
     worker.markContentsGood(storePath);
 
     printMsg(lvlChatty,
-        format("substitution of path '%1%' succeeded") % storePath);
+        format("substitution of path ‘%1%’ succeeded") % storePath);
 
     amDone(ecSuccess);
 }
@@ -3589,7 +3589,7 @@ void Worker::run(const Goals & _topGoals)
             waitForInput();
         else {
             if (awake.empty() && settings.maxBuildJobs == 0) throw Error(
-                "unable to start any build; either increase '--max-jobs' "
+                "unable to start any build; either increase ‘--max-jobs’ "
                 "or enable distributed builds");
             assert(!awake.empty());
         }
@@ -3744,7 +3744,7 @@ bool Worker::pathContentsGood(const Path & path)
 {
     std::map<Path, bool>::iterator i = pathContentsGoodCache.find(path);
     if (i != pathContentsGoodCache.end()) return i->second;
-    printInfo(format("checking path '%1%'...") % path);
+    printInfo(format("checking path ‘%1%’...") % path);
     auto info = store.queryPathInfo(path);
     bool res;
     if (!pathExists(path))
@@ -3755,7 +3755,7 @@ bool Worker::pathContentsGood(const Path & path)
         res = info->narHash == nullHash || info->narHash == current.first;
     }
     pathContentsGoodCache[path] = res;
-    if (!res) printError(format("path '%1%' is corrupted or missing!") % path);
+    if (!res) printError(format("path ‘%1%’ is corrupted or missing!") % path);
     return res;
 }
 
@@ -3829,7 +3829,7 @@ void LocalStore::ensurePath(const Path & path)
     worker.run(goals);
 
     if (goal->getExitCode() != Goal::ecSuccess)
-        throw Error(worker.exitStatus(), "path '%s' does not exist and cannot be created", path);
+        throw Error(worker.exitStatus(), "path ‘%s’ does not exist and cannot be created", path);
 }
 
 
@@ -3850,7 +3850,7 @@ void LocalStore::repairPath(const Path & path)
             goals.insert(worker.makeDerivationGoal(deriver, StringSet(), bmRepair));
             worker.run(goals);
         } else
-            throw Error(worker.exitStatus(), "cannot repair path '%s'", path);
+            throw Error(worker.exitStatus(), "cannot repair path ‘%s’", path);
     }
 }
 
diff --git a/src/libstore/builtins.cc b/src/libstore/builtins.cc
index a9c86599eed3..a30f30906f01 100644
--- a/src/libstore/builtins.cc
+++ b/src/libstore/builtins.cc
@@ -10,7 +10,7 @@ void builtinFetchurl(const BasicDerivation & drv)
 {
     auto getAttr = [&](const string & name) {
         auto i = drv.env.find(name);
-        if (i == drv.env.end()) throw Error(format("attribute '%s' missing") % name);
+        if (i == drv.env.end()) throw Error(format("attribute ‘%s’ missing") % name);
         return i->second;
     };
 
@@ -56,7 +56,7 @@ void builtinFetchurl(const BasicDerivation & drv)
     auto executable = drv.env.find("executable");
     if (executable != drv.env.end() && executable->second == "1") {
         if (chmod(storePath.c_str(), 0755) == -1)
-            throw SysError(format("making '%1%' executable") % storePath);
+            throw SysError(format("making ‘%1%’ executable") % storePath);
     }
 }
 
diff --git a/src/libstore/crypto.hh b/src/libstore/crypto.hh
index eb299b90f52b..9110af3aa9e5 100644
--- a/src/libstore/crypto.hh
+++ b/src/libstore/crypto.hh
@@ -12,7 +12,7 @@ struct Key
     std::string key;
 
     /* Construct Key from a string in the format
-       '<name>:<key-in-base64>'. */
+       ‘<name>:<key-in-base64>’. */
     Key(const std::string & s);
 
 protected:
@@ -44,7 +44,7 @@ private:
 
 typedef std::map<std::string, PublicKey> PublicKeys;
 
-/* Return true iff 'sig' is a correct signature over 'data' using one
+/* Return true iff ‘sig’ is a correct signature over ‘data’ using one
    of the given public keys. */
 bool verifyDetached(const std::string & data, const std::string & sig,
     const PublicKeys & publicKeys);
diff --git a/src/libstore/derivations.cc b/src/libstore/derivations.cc
index d4bcad7fe1d5..5562d46892a8 100644
--- a/src/libstore/derivations.cc
+++ b/src/libstore/derivations.cc
@@ -21,7 +21,7 @@ void DerivationOutput::parseHashInfo(bool & recursive, Hash & hash) const
 
     HashType hashType = parseHashType(algo);
     if (hashType == htUnknown)
-        throw Error(format("unknown hash algorithm '%1%'") % algo);
+        throw Error(format("unknown hash algorithm ‘%1%’") % algo);
 
     hash = parseHash(hashType, this->hash);
 }
@@ -31,7 +31,7 @@ Path BasicDerivation::findOutput(const string & id) const
 {
     auto i = outputs.find(id);
     if (i == outputs.end())
-        throw Error(format("derivation has no output '%1%'") % id);
+        throw Error(format("derivation has no output ‘%1%’") % id);
     return i->second.path;
 }
 
@@ -97,7 +97,7 @@ static void expect(std::istream & str, const string & s)
     char s2[s.size()];
     str.read(s2, s.size());
     if (string(s2, s.size()) != s)
-        throw FormatError(format("expected string '%1%'") % s);
+        throw FormatError(format("expected string ‘%1%’") % s);
 }
 
 
@@ -124,7 +124,7 @@ static Path parsePath(std::istream & str)
 {
     string s = parseString(str);
     if (s.size() == 0 || s[0] != '/')
-        throw FormatError(format("bad path '%1%' in derivation") % s);
+        throw FormatError(format("bad path ‘%1%’ in derivation") % s);
     return s;
 }
 
@@ -207,7 +207,7 @@ Derivation readDerivation(const Path & drvPath)
     try {
         return parseDerivation(readFile(drvPath));
     } catch (FormatError & e) {
-        throw Error(format("error parsing derivation '%1%': %2%") % drvPath % e.msg());
+        throw Error(format("error parsing derivation ‘%1%’: %2%") % drvPath % e.msg());
     }
 }
 
@@ -220,7 +220,7 @@ Derivation Store::derivationFromPath(const Path & drvPath)
     try {
         return parseDerivation(accessor->readFile(drvPath));
     } catch (FormatError & e) {
-        throw Error(format("error parsing derivation '%1%': %2%") % drvPath % e.msg());
+        throw Error(format("error parsing derivation ‘%1%’: %2%") % drvPath % e.msg());
     }
 }
 
diff --git a/src/libstore/download.cc b/src/libstore/download.cc
index 8682d244ffad..954044c2344f 100644
--- a/src/libstore/download.cc
+++ b/src/libstore/download.cc
@@ -87,7 +87,7 @@ struct CurlDownloader : public Downloader
             if (requestHeaders) curl_slist_free_all(requestHeaders);
             try {
                 if (!done)
-                    fail(DownloadError(Interrupted, format("download of '%s' was interrupted") % request.uri));
+                    fail(DownloadError(Interrupted, format("download of ‘%s’ was interrupted") % request.uri));
             } catch (...) {
                 ignoreException();
             }
@@ -117,7 +117,7 @@ struct CurlDownloader : public Downloader
         {
             size_t realSize = size * nmemb;
             std::string line((char *) contents, realSize);
-            printMsg(lvlVomit, format("got header for '%s': %s") % request.uri % trim(line));
+            printMsg(lvlVomit, format("got header for ‘%s’: %s") % request.uri % trim(line));
             if (line.compare(0, 5, "HTTP/") == 0) { // new response starts
                 result.etag = "";
                 auto ss = tokenizeString<vector<string>>(line, " ");
@@ -176,7 +176,7 @@ struct CurlDownloader : public Downloader
         {
             // FIXME: handle parallel downloads.
             if (showProgress) {
-                std::cerr << (format("downloading '%1%'... ") % request.uri);
+                std::cerr << (format("downloading ‘%1%’... ") % request.uri);
                 std::cerr.flush();
                 startTime = getTime();
             }
@@ -234,7 +234,7 @@ struct CurlDownloader : public Downloader
             if (effectiveUrlCStr)
                 result.effectiveUrl = effectiveUrlCStr;
 
-            debug(format("finished download of '%s'; curl status = %d, HTTP status = %d, body = %d bytes")
+            debug(format("finished download of ‘%s’; curl status = %d, HTTP status = %d, body = %d bytes")
                 % request.uri % code % httpStatus % (result.data ? result.data->size() : 0));
 
             if (code == CURLE_WRITE_ERROR && result.etag == request.expectedETag) {
@@ -261,10 +261,10 @@ struct CurlDownloader : public Downloader
 
                 auto exc =
                     code == CURLE_ABORTED_BY_CALLBACK && _isInterrupted
-                    ? DownloadError(Interrupted, format("download of '%s' was interrupted") % request.uri)
+                    ? DownloadError(Interrupted, format("download of ‘%s’ was interrupted") % request.uri)
                     : httpStatus != 0
-                      ? DownloadError(err, format("unable to download '%s': HTTP error %d") % request.uri % httpStatus)
-                      : DownloadError(err, format("unable to download '%s': %s (%d)") % request.uri % curl_easy_strerror(code) % code);
+                      ? DownloadError(err, format("unable to download ‘%s’: HTTP error %d") % request.uri % httpStatus)
+                      : DownloadError(err, format("unable to download ‘%s’: %s (%d)") % request.uri % curl_easy_strerror(code) % code);
 
                 /* If this is a transient error, then maybe retry the
                    download after a while. */
@@ -534,7 +534,7 @@ Path Downloader::downloadCached(ref<Store> store, const string & url_, bool unpa
                     if (effectiveUrl)
                         *effectiveUrl = url_;
                 } else if (!ss[1].empty()) {
-                    debug(format("verifying previous ETag '%1%'") % ss[1]);
+                    debug(format("verifying previous ETag ‘%1%’") % ss[1]);
                     expectedETag = ss[1];
                 }
             }
@@ -582,7 +582,7 @@ Path Downloader::downloadCached(ref<Store> store, const string & url_, bool unpa
                 unpackedStorePath = "";
         }
         if (unpackedStorePath.empty()) {
-            printInfo(format("unpacking '%1%'...") % url);
+            printInfo(format("unpacking ‘%1%’...") % url);
             Path tmpDir = createTempDir();
             AutoDelete autoDelete(tmpDir, true);
             // FIXME: this requires GNU tar for decompression.
@@ -594,7 +594,7 @@ Path Downloader::downloadCached(ref<Store> store, const string & url_, bool unpa
     }
 
     if (expectedStorePath != "" && storePath != expectedStorePath)
-        throw nix::Error(format("hash mismatch in file downloaded from '%s'") % url);
+        throw nix::Error(format("hash mismatch in file downloaded from ‘%s’") % url);
 
     return storePath;
 }
diff --git a/src/libstore/download.hh b/src/libstore/download.hh
index 6703e013ee72..82b5d641fde9 100644
--- a/src/libstore/download.hh
+++ b/src/libstore/download.hh
@@ -46,7 +46,7 @@ struct Downloader
     DownloadResult download(const DownloadRequest & request);
 
     /* Check if the specified file is already in ~/.cache/nix/tarballs
-       and is more recent than 'tarball-ttl' seconds. Otherwise,
+       and is more recent than ‘tarball-ttl’ seconds. Otherwise,
        use the recorded ETag to verify if the server has a more
        recent version, and if so, download it to the Nix store. */
     Path downloadCached(ref<Store> store, const string & uri, bool unpack, string name = "",
diff --git a/src/libstore/export-import.cc b/src/libstore/export-import.cc
index 1f326d2f09c4..c5618c826c54 100644
--- a/src/libstore/export-import.cc
+++ b/src/libstore/export-import.cc
@@ -33,7 +33,7 @@ void Store::exportPaths(const Paths & paths, Sink & sink)
     logger->incExpected(doneLabel, sorted.size());
 
     for (auto & path : sorted) {
-        Activity act(*logger, lvlInfo, format("exporting path '%s'") % path);
+        Activity act(*logger, lvlInfo, format("exporting path ‘%s’") % path);
         sink << 1;
         exportPath(path, sink);
         logger->incProgress(doneLabel);
@@ -55,7 +55,7 @@ void Store::exportPath(const Path & path, Sink & sink)
        Don't complain if the stored hash is zero (unknown). */
     Hash hash = hashAndWriteSink.currentHash();
     if (hash != info->narHash && info->narHash != Hash(info->narHash.type))
-        throw Error(format("hash of path '%1%' has changed from '%2%' to '%3%'!") % path
+        throw Error(format("hash of path ‘%1%’ has changed from ‘%2%’ to ‘%3%’!") % path
             % printHash(info->narHash) % printHash(hash));
 
     hashAndWriteSink << exportMagic << path << info->references << info->deriver << 0;
@@ -88,7 +88,7 @@ Paths Store::importPaths(Source & source, std::shared_ptr<FSAccessor> accessor,
     while (true) {
         unsigned long long n = readLongLong(source);
         if (n == 0) break;
-        if (n != 1) throw Error("input doesn't look like something created by 'nix-store --export'");
+        if (n != 1) throw Error("input doesn't look like something created by ‘nix-store --export’");
 
         /* Extract the NAR from the source. */
         TeeSource tee(source);
@@ -103,7 +103,7 @@ Paths Store::importPaths(Source & source, std::shared_ptr<FSAccessor> accessor,
 
         info.path = readStorePath(*this, source);
 
-        Activity act(*logger, lvlInfo, format("importing path '%s'") % info.path);
+        Activity act(*logger, lvlInfo, format("importing path ‘%s’") % info.path);
 
         info.references = readStorePaths<PathSet>(*this, source);
 
diff --git a/src/libstore/gc.cc b/src/libstore/gc.cc
index 8f8c0995523d..ae03604faf98 100644
--- a/src/libstore/gc.cc
+++ b/src/libstore/gc.cc
@@ -32,11 +32,11 @@ int LocalStore::openGCLock(LockType lockType)
     Path fnGCLock = (format("%1%/%2%")
         % stateDir % gcLockName).str();
 
-    debug(format("acquiring global GC lock '%1%'") % fnGCLock);
+    debug(format("acquiring global GC lock ‘%1%’") % fnGCLock);
 
     AutoCloseFD fdGCLock = open(fnGCLock.c_str(), O_RDWR | O_CREAT | O_CLOEXEC, 0600);
     if (!fdGCLock)
-        throw SysError(format("opening global GC lock '%1%'") % fnGCLock);
+        throw SysError(format("opening global GC lock ‘%1%’") % fnGCLock);
 
     if (!lockFile(fdGCLock.get(), lockType, false)) {
         printError(format("waiting for the big garbage collector lock..."));
@@ -63,7 +63,7 @@ static void makeSymlink(const Path & link, const Path & target)
 
     /* Atomically replace the old one. */
     if (rename(tempLink.c_str(), link.c_str()) == -1)
-        throw SysError(format("cannot rename '%1%' to '%2%'")
+        throw SysError(format("cannot rename ‘%1%’ to ‘%2%’")
             % tempLink % link);
 }
 
@@ -99,7 +99,7 @@ Path LocalFSStore::addPermRoot(const Path & _storePath,
         /* Don't clobber the link if it already exists and doesn't
            point to the Nix store. */
         if (pathExists(gcRoot) && (!isLink(gcRoot) || !isInStore(readLink(gcRoot))))
-            throw Error(format("cannot create symlink '%1%'; already exists") % gcRoot);
+            throw Error(format("cannot create symlink ‘%1%’; already exists") % gcRoot);
         makeSymlink(gcRoot, storePath);
         addIndirectRoot(gcRoot);
     }
@@ -110,8 +110,8 @@ Path LocalFSStore::addPermRoot(const Path & _storePath,
 
             if (string(gcRoot, 0, rootsDir.size() + 1) != rootsDir + "/")
                 throw Error(format(
-                    "path '%1%' is not a valid garbage collector root; "
-                    "it's not in the directory '%2%'")
+                    "path ‘%1%’ is not a valid garbage collector root; "
+                    "it's not in the directory ‘%2%’")
                     % gcRoot % rootsDir);
         }
 
@@ -131,8 +131,8 @@ Path LocalFSStore::addPermRoot(const Path & _storePath,
         if (roots.find(gcRoot) == roots.end())
             printError(
                 format(
-                    "warning: '%1%' is not in a directory where the garbage collector looks for roots; "
-                    "therefore, '%2%' might be removed by the garbage collector")
+                    "warning: ‘%1%’ is not in a directory where the garbage collector looks for roots; "
+                    "therefore, ‘%2%’ might be removed by the garbage collector")
                 % gcRoot % storePath);
     }
 
@@ -169,14 +169,14 @@ void LocalStore::addTempRoot(const Path & path)
 
             fdGCLock = -1;
 
-            debug(format("acquiring read lock on '%1%'") % state->fnTempRoots);
+            debug(format("acquiring read lock on ‘%1%’") % state->fnTempRoots);
             lockFile(state->fdTempRoots.get(), ltRead, true);
 
             /* Check whether the garbage collector didn't get in our
                way. */
             struct stat st;
             if (fstat(state->fdTempRoots.get(), &st) == -1)
-                throw SysError(format("statting '%1%'") % state->fnTempRoots);
+                throw SysError(format("statting ‘%1%’") % state->fnTempRoots);
             if (st.st_size == 0) break;
 
             /* The garbage collector deleted this file before we could
@@ -188,14 +188,14 @@ void LocalStore::addTempRoot(const Path & path)
 
     /* Upgrade the lock to a write lock.  This will cause us to block
        if the garbage collector is holding our lock. */
-    debug(format("acquiring write lock on '%1%'") % state->fnTempRoots);
+    debug(format("acquiring write lock on ‘%1%’") % state->fnTempRoots);
     lockFile(state->fdTempRoots.get(), ltWrite, true);
 
     string s = path + '\0';
     writeFull(state->fdTempRoots.get(), s);
 
     /* Downgrade to a read lock. */
-    debug(format("downgrading to read lock on '%1%'") % state->fnTempRoots);
+    debug(format("downgrading to read lock on ‘%1%’") % state->fnTempRoots);
     lockFile(state->fdTempRoots.get(), ltRead, true);
 }
 
@@ -210,12 +210,12 @@ void LocalStore::readTempRoots(PathSet & tempRoots, FDs & fds)
     for (auto & i : tempRootFiles) {
         Path path = (format("%1%/%2%/%3%") % stateDir % tempRootsDir % i.name).str();
 
-        debug(format("reading temporary root file '%1%'") % path);
+        debug(format("reading temporary root file ‘%1%’") % path);
         FDPtr fd(new AutoCloseFD(open(path.c_str(), O_CLOEXEC | O_RDWR, 0666)));
         if (!*fd) {
             /* It's okay if the file has disappeared. */
             if (errno == ENOENT) continue;
-            throw SysError(format("opening temporary roots file '%1%'") % path);
+            throw SysError(format("opening temporary roots file ‘%1%’") % path);
         }
 
         /* This should work, but doesn't, for some reason. */
@@ -226,7 +226,7 @@ void LocalStore::readTempRoots(PathSet & tempRoots, FDs & fds)
            only succeed if the owning process has died.  In that case
            we don't care about its temporary roots. */
         if (lockFile(fd->get(), ltWrite, false)) {
-            printError(format("removing stale temporary roots file '%1%'") % path);
+            printError(format("removing stale temporary roots file ‘%1%’") % path);
             unlink(path.c_str());
             writeFull(fd->get(), "d");
             continue;
@@ -235,7 +235,7 @@ void LocalStore::readTempRoots(PathSet & tempRoots, FDs & fds)
         /* Acquire a read lock.  This will prevent the owning process
            from upgrading to a write lock, therefore it will block in
            addTempRoot(). */
-        debug(format("waiting for read lock on '%1%'") % path);
+        debug(format("waiting for read lock on ‘%1%’") % path);
         lockFile(fd->get(), ltRead, true);
 
         /* Read the entire file. */
@@ -246,7 +246,7 @@ void LocalStore::readTempRoots(PathSet & tempRoots, FDs & fds)
 
         while ((end = contents.find((char) 0, pos)) != string::npos) {
             Path root(contents, pos, end - pos);
-            debug(format("got temporary root '%1%'") % root);
+            debug(format("got temporary root ‘%1%’") % root);
             assertStorePath(root);
             tempRoots.insert(root);
             pos = end + 1;
@@ -264,7 +264,7 @@ void LocalStore::findRoots(const Path & path, unsigned char type, Roots & roots)
         if (isStorePath(storePath) && isValidPath(storePath))
             roots[path] = storePath;
         else
-            printInfo(format("skipping invalid root from '%1%' to '%2%'") % path % storePath);
+            printInfo(format("skipping invalid root from ‘%1%’ to ‘%2%’") % path % storePath);
     };
 
     try {
@@ -287,7 +287,7 @@ void LocalStore::findRoots(const Path & path, unsigned char type, Roots & roots)
                 target = absPath(target, dirOf(path));
                 if (!pathExists(target)) {
                     if (isInDir(path, stateDir + "/" + gcRootsDir + "/auto")) {
-                        printInfo(format("removing stale link from '%1%' to '%2%'") % path % target);
+                        printInfo(format("removing stale link from ‘%1%’ to ‘%2%’") % path % target);
                         unlink(path.c_str());
                     }
                 } else {
@@ -310,7 +310,7 @@ void LocalStore::findRoots(const Path & path, unsigned char type, Roots & roots)
     catch (SysError & e) {
         /* We only ignore permanent failures. */
         if (e.errNo == EACCES || e.errNo == ENOENT || e.errNo == ENOTDIR)
-            printInfo(format("cannot read potential root '%1%'") % path);
+            printInfo(format("cannot read potential root ‘%1%’") % path);
         else
             throw;
     }
@@ -447,7 +447,7 @@ void LocalStore::findRuntimeRoots(PathSet & roots)
         if (isInStore(i)) {
             Path path = toStorePath(i);
             if (roots.find(path) == roots.end() && isStorePath(path) && isValidPath(path)) {
-                debug(format("got additional root '%1%'") % path);
+                debug(format("got additional root ‘%1%’") % path);
                 roots.insert(path);
             }
         }
@@ -513,7 +513,7 @@ void LocalStore::deletePathRecursive(GCState & state, const Path & path)
         throw SysError(format("getting status of %1%") % realPath);
     }
 
-    printInfo(format("deleting '%1%'") % path);
+    printInfo(format("deleting ‘%1%’") % path);
 
     state.results.paths.insert(path);
 
@@ -528,14 +528,14 @@ void LocalStore::deletePathRecursive(GCState & state, const Path & path)
         // size.
         try {
             if (chmod(realPath.c_str(), st.st_mode | S_IWUSR) == -1)
-                throw SysError(format("making '%1%' writable") % realPath);
+                throw SysError(format("making ‘%1%’ writable") % realPath);
             Path tmp = trashDir + "/" + baseNameOf(path);
             if (rename(realPath.c_str(), tmp.c_str()))
-                throw SysError(format("unable to rename '%1%' to '%2%'") % realPath % tmp);
+                throw SysError(format("unable to rename ‘%1%’ to ‘%2%’") % realPath % tmp);
             state.bytesInvalidated += size;
         } catch (SysError & e) {
             if (e.errNo == ENOSPC) {
-                printInfo(format("note: can't create move '%1%': %2%") % realPath % e.msg());
+                printInfo(format("note: can't create move ‘%1%’: %2%") % realPath % e.msg());
                 deleteGarbage(state, realPath);
             }
         }
@@ -562,7 +562,7 @@ bool LocalStore::canReachRoot(GCState & state, PathSet & visited, const Path & p
     }
 
     if (state.roots.find(path) != state.roots.end()) {
-        debug(format("cannot delete '%1%' because it's a root") % path);
+        debug(format("cannot delete ‘%1%’ because it's a root") % path);
         state.alive.insert(path);
         return true;
     }
@@ -611,7 +611,7 @@ void LocalStore::tryToDelete(GCState & state, const Path & path)
     auto realPath = realStoreDir + "/" + baseNameOf(path);
     if (realPath == linksDir || realPath == trashDir) return;
 
-    Activity act(*logger, lvlDebug, format("considering whether to delete '%1%'") % path);
+    Activity act(*logger, lvlDebug, format("considering whether to delete ‘%1%’") % path);
 
     if (!isStorePath(path) || !isValidPath(path)) {
         /* A lock file belonging to a path that we're building right
@@ -626,11 +626,11 @@ void LocalStore::tryToDelete(GCState & state, const Path & path)
     PathSet visited;
 
     if (canReachRoot(state, visited, path)) {
-        debug(format("cannot delete '%1%' because it's still reachable") % path);
+        debug(format("cannot delete ‘%1%’ because it's still reachable") % path);
     } else {
         /* No path we visited was a root, so everything is garbage.
-           But we only delete 'path' and its referrers here so that
-           'nix-store --delete' doesn't have the unexpected effect of
+           But we only delete ‘path’ and its referrers here so that
+           ‘nix-store --delete’ doesn't have the unexpected effect of
            recursing into derivations and outputs. */
         state.dead.insert(visited.begin(), visited.end());
         if (state.shouldDelete)
@@ -647,7 +647,7 @@ void LocalStore::tryToDelete(GCState & state, const Path & path)
 void LocalStore::removeUnusedLinks(const GCState & state)
 {
     AutoCloseDir dir = opendir(linksDir.c_str());
-    if (!dir) throw SysError(format("opening directory '%1%'") % linksDir);
+    if (!dir) throw SysError(format("opening directory ‘%1%’") % linksDir);
 
     long long actualSize = 0, unsharedSize = 0;
 
@@ -660,7 +660,7 @@ void LocalStore::removeUnusedLinks(const GCState & state)
 
         struct stat st;
         if (lstat(path.c_str(), &st) == -1)
-            throw SysError(format("statting '%1%'") % path);
+            throw SysError(format("statting ‘%1%’") % path);
 
         if (st.st_nlink != 1) {
             unsigned long long size = st.st_blocks * 512ULL;
@@ -669,17 +669,17 @@ void LocalStore::removeUnusedLinks(const GCState & state)
             continue;
         }
 
-        printMsg(lvlTalkative, format("deleting unused link '%1%'") % path);
+        printMsg(lvlTalkative, format("deleting unused link ‘%1%’") % path);
 
         if (unlink(path.c_str()) == -1)
-            throw SysError(format("deleting '%1%'") % path);
+            throw SysError(format("deleting ‘%1%’") % path);
 
         state.results.bytesFreed += st.st_blocks * 512;
     }
 
     struct stat st;
     if (stat(linksDir.c_str(), &st) == -1)
-        throw SysError(format("statting '%1%'") % linksDir);
+        throw SysError(format("statting ‘%1%’") % linksDir);
     long long overhead = st.st_blocks * 512ULL;
 
     printInfo(format("note: currently hard linking saves %.2f MiB")
@@ -759,7 +759,7 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
             assertStorePath(i);
             tryToDelete(state, i);
             if (state.dead.find(i) == state.dead.end())
-                throw Error(format("cannot delete path '%1%' since it is still alive") % i);
+                throw Error(format("cannot delete path ‘%1%’ since it is still alive") % i);
         }
 
     } else if (options.maxFreed > 0) {
@@ -772,7 +772,7 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
         try {
 
             AutoCloseDir dir = opendir(realStoreDir.c_str());
-            if (!dir) throw SysError(format("opening directory '%1%'") % realStoreDir);
+            if (!dir) throw SysError(format("opening directory ‘%1%’") % realStoreDir);
 
             /* Read the store and immediately delete all paths that
                aren't valid.  When using --max-freed etc., deleting
@@ -825,7 +825,7 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
     fds.clear();
 
     /* Delete the trash directory. */
-    printInfo(format("deleting '%1%'") % trashDir);
+    printInfo(format("deleting ‘%1%’") % trashDir);
     deleteGarbage(state, trashDir);
 
     /* Clean up the links directory. */
diff --git a/src/libstore/globals.cc b/src/libstore/globals.cc
index 84f93ba28522..00b468892529 100644
--- a/src/libstore/globals.cc
+++ b/src/libstore/globals.cc
@@ -103,7 +103,7 @@ void Settings::loadConfFile()
         if (tokens.empty()) continue;
 
         if (tokens.size() < 2 || tokens[1] != "=")
-            throw Error(format("illegal configuration line '%1%' in '%2%'") % line % settingsFile);
+            throw Error(format("illegal configuration line ‘%1%’ in ‘%2%’") % line % settingsFile);
 
         string name = tokens[0];
 
@@ -202,7 +202,7 @@ void Settings::_get(bool & res, const string & name)
     if (i == settings.end()) return;
     if (i->second == "true") res = true;
     else if (i->second == "false") res = false;
-    else throw Error(format("configuration option '%1%' should be either 'true' or 'false', not '%2%'")
+    else throw Error(format("configuration option ‘%1%’ should be either ‘true’ or ‘false’, not ‘%2%’")
         % name % i->second);
 }
 
@@ -229,7 +229,7 @@ template<class N> void Settings::_get(N & res, const string & name)
     SettingsMap::iterator i = settings.find(name);
     if (i == settings.end()) return;
     if (!string2Int(i->second, res))
-        throw Error(format("configuration setting '%1%' should have an integer value") % name);
+        throw Error(format("configuration setting ‘%1%’ should have an integer value") % name);
 }
 
 
diff --git a/src/libstore/http-binary-cache-store.cc b/src/libstore/http-binary-cache-store.cc
index 0e34b08de5a7..9d31f77c921f 100644
--- a/src/libstore/http-binary-cache-store.cc
+++ b/src/libstore/http-binary-cache-store.cc
@@ -38,7 +38,7 @@ public:
             try {
                 BinaryCacheStore::init();
             } catch (UploadToHTTP &) {
-                throw Error(format("'%s' does not appear to be a binary cache") % cacheUri);
+                throw Error(format("‘%s’ does not appear to be a binary cache") % cacheUri);
             }
             diskCache->createCache(cacheUri, storeDir, wantMassQuery_, priority);
         }
diff --git a/src/libstore/local-binary-cache-store.cc b/src/libstore/local-binary-cache-store.cc
index bce4dfd5e234..0f377989bd89 100644
--- a/src/libstore/local-binary-cache-store.cc
+++ b/src/libstore/local-binary-cache-store.cc
@@ -74,7 +74,7 @@ static void atomicWrite(const Path & path, const std::string & s)
     AutoDelete del(tmp, false);
     writeFile(tmp, s);
     if (rename(tmp.c_str(), path.c_str()))
-        throw SysError(format("renaming '%1%' to '%2%'") % tmp % path);
+        throw SysError(format("renaming ‘%1%’ to ‘%2%’") % tmp % path);
     del.cancel();
 }
 
diff --git a/src/libstore/local-fs-store.cc b/src/libstore/local-fs-store.cc
index 6c3e51d06fb7..4571a2211cd2 100644
--- a/src/libstore/local-fs-store.cc
+++ b/src/libstore/local-fs-store.cc
@@ -23,7 +23,7 @@ struct LocalStoreAccessor : public FSAccessor
     {
         Path storePath = store->toStorePath(path);
         if (!store->isValidPath(storePath))
-            throw InvalidPath(format("path '%1%' is not a valid store path") % storePath);
+            throw InvalidPath(format("path ‘%1%’ is not a valid store path") % storePath);
         return store->getRealStoreDir() + std::string(path, store->storeDir.size());
     }
 
@@ -34,11 +34,11 @@ struct LocalStoreAccessor : public FSAccessor
         struct stat st;
         if (lstat(path.c_str(), &st)) {
             if (errno == ENOENT || errno == ENOTDIR) return {Type::tMissing, 0, false};
-            throw SysError(format("getting status of '%1%'") % path);
+            throw SysError(format("getting status of ‘%1%’") % path);
         }
 
         if (!S_ISREG(st.st_mode) && !S_ISDIR(st.st_mode) && !S_ISLNK(st.st_mode))
-            throw Error(format("file '%1%' has unsupported type") % path);
+            throw Error(format("file ‘%1%’ has unsupported type") % path);
 
         return {
             S_ISREG(st.st_mode) ? Type::tRegular :
@@ -80,7 +80,7 @@ ref<FSAccessor> LocalFSStore::getFSAccessor()
 void LocalFSStore::narFromPath(const Path & path, Sink & sink)
 {
     if (!isValidPath(path))
-        throw Error(format("path '%s' is not valid") % path);
+        throw Error(format("path ‘%s’ is not valid") % path);
     dumpPath(getRealStoreDir() + std::string(path, storeDir.size()), sink);
 }
 
diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc
index a9e31dc1237b..612efde7bb8f 100644
--- a/src/libstore/local-store.cc
+++ b/src/libstore/local-store.cc
@@ -71,24 +71,24 @@ LocalStore::LocalStore(const Params & params)
         Path perUserDir = profilesDir + "/per-user";
         createDirs(perUserDir);
         if (chmod(perUserDir.c_str(), 01777) == -1)
-            throw SysError(format("could not set permissions on '%1%' to 1777") % perUserDir);
+            throw SysError(format("could not set permissions on ‘%1%’ to 1777") % perUserDir);
 
         mode_t perm = 01775;
 
         struct group * gr = getgrnam(settings.buildUsersGroup.c_str());
         if (!gr)
-            printError(format("warning: the group '%1%' specified in 'build-users-group' does not exist")
+            printError(format("warning: the group ‘%1%’ specified in ‘build-users-group’ does not exist")
                 % settings.buildUsersGroup);
         else {
             struct stat st;
             if (stat(realStoreDir.c_str(), &st))
-                throw SysError(format("getting attributes of path '%1%'") % realStoreDir);
+                throw SysError(format("getting attributes of path ‘%1%’") % realStoreDir);
 
             if (st.st_uid != 0 || st.st_gid != gr->gr_gid || (st.st_mode & ~S_IFMT) != perm) {
                 if (chown(realStoreDir.c_str(), 0, gr->gr_gid) == -1)
-                    throw SysError(format("changing ownership of path '%1%'") % realStoreDir);
+                    throw SysError(format("changing ownership of path ‘%1%’") % realStoreDir);
                 if (chmod(realStoreDir.c_str(), perm) == -1)
-                    throw SysError(format("changing permissions on path '%1%'") % realStoreDir);
+                    throw SysError(format("changing permissions on path ‘%1%’") % realStoreDir);
             }
         }
     }
@@ -99,10 +99,10 @@ LocalStore::LocalStore(const Params & params)
         struct stat st;
         while (path != "/") {
             if (lstat(path.c_str(), &st))
-                throw SysError(format("getting status of '%1%'") % path);
+                throw SysError(format("getting status of ‘%1%’") % path);
             if (S_ISLNK(st.st_mode))
                 throw Error(format(
-                        "the path '%1%' is a symlink; "
+                        "the path ‘%1%’ is a symlink; "
                         "this is not allowed for the Nix store and its parent directories")
                     % path);
             path = dirOf(path);
@@ -262,7 +262,7 @@ int LocalStore::getSchema()
     if (pathExists(schemaPath)) {
         string s = readFile(schemaPath);
         if (!string2Int(s, curSchema))
-            throw Error(format("'%1%' is corrupt") % schemaPath);
+            throw Error(format("‘%1%’ is corrupt") % schemaPath);
     }
     return curSchema;
 }
@@ -271,14 +271,14 @@ int LocalStore::getSchema()
 void LocalStore::openDB(State & state, bool create)
 {
     if (access(dbDir.c_str(), R_OK | W_OK))
-        throw SysError(format("Nix database directory '%1%' is not writable") % dbDir);
+        throw SysError(format("Nix database directory ‘%1%’ is not writable") % dbDir);
 
     /* Open the Nix database. */
     string dbPath = dbDir + "/db.sqlite";
     auto & db(state.db);
     if (sqlite3_open_v2(dbPath.c_str(), &db.db,
             SQLITE_OPEN_READWRITE | (create ? SQLITE_OPEN_CREATE : 0), 0) != SQLITE_OK)
-        throw Error(format("cannot open Nix database '%1%'") % dbPath);
+        throw Error(format("cannot open Nix database ‘%1%’") % dbPath);
 
     if (sqlite3_busy_timeout(db, 60 * 60 * 1000) != SQLITE_OK)
         throwSQLiteError(db, "setting timeout");
@@ -363,7 +363,7 @@ static void canonicaliseTimestampAndPermissions(const Path & path, const struct
                  | 0444
                  | (st.st_mode & S_IXUSR ? 0111 : 0);
             if (chmod(path.c_str(), mode) == -1)
-                throw SysError(format("changing mode of '%1%' to %2$o") % path % mode);
+                throw SysError(format("changing mode of ‘%1%’ to %2$o") % path % mode);
         }
 
     }
@@ -381,7 +381,7 @@ static void canonicaliseTimestampAndPermissions(const Path & path, const struct
 #else
         if (!S_ISLNK(st.st_mode) && utimes(path.c_str(), times) == -1)
 #endif
-            throw SysError(format("changing modification time of '%1%'") % path);
+            throw SysError(format("changing modification time of ‘%1%’") % path);
     }
 }
 
@@ -390,7 +390,7 @@ void canonicaliseTimestampAndPermissions(const Path & path)
 {
     struct stat st;
     if (lstat(path.c_str(), &st))
-        throw SysError(format("getting attributes of path '%1%'") % path);
+        throw SysError(format("getting attributes of path ‘%1%’") % path);
     canonicaliseTimestampAndPermissions(path, st);
 }
 
@@ -401,11 +401,11 @@ static void canonicalisePathMetaData_(const Path & path, uid_t fromUid, InodesSe
 
     struct stat st;
     if (lstat(path.c_str(), &st))
-        throw SysError(format("getting attributes of path '%1%'") % path);
+        throw SysError(format("getting attributes of path ‘%1%’") % path);
 
     /* Really make sure that the path is of a supported type. */
     if (!(S_ISREG(st.st_mode) || S_ISDIR(st.st_mode) || S_ISLNK(st.st_mode)))
-        throw Error(format("file '%1%' has an unsupported type") % path);
+        throw Error(format("file ‘%1%’ has an unsupported type") % path);
 
     /* Fail if the file is not owned by the build user.  This prevents
        us from messing up the ownership/permissions of files
@@ -416,7 +416,7 @@ static void canonicalisePathMetaData_(const Path & path, uid_t fromUid, InodesSe
     if (fromUid != (uid_t) -1 && st.st_uid != fromUid) {
         assert(!S_ISDIR(st.st_mode));
         if (inodesSeen.find(Inode(st.st_dev, st.st_ino)) == inodesSeen.end())
-            throw BuildError(format("invalid ownership on file '%1%'") % path);
+            throw BuildError(format("invalid ownership on file ‘%1%’") % path);
         mode_t mode = st.st_mode & ~S_IFMT;
         assert(S_ISLNK(st.st_mode) || (st.st_uid == geteuid() && (mode == 0444 || mode == 0555) && st.st_mtime == mtimeStore));
         return;
@@ -440,7 +440,7 @@ static void canonicalisePathMetaData_(const Path & path, uid_t fromUid, InodesSe
         if (!S_ISLNK(st.st_mode) &&
             chown(path.c_str(), geteuid(), getegid()) == -1)
 #endif
-            throw SysError(format("changing owner of '%1%' to %2%")
+            throw SysError(format("changing owner of ‘%1%’ to %2%")
                 % path % geteuid());
     }
 
@@ -460,11 +460,11 @@ void canonicalisePathMetaData(const Path & path, uid_t fromUid, InodesSeen & ino
        be a symlink, since we can't change its ownership. */
     struct stat st;
     if (lstat(path.c_str(), &st))
-        throw SysError(format("getting attributes of path '%1%'") % path);
+        throw SysError(format("getting attributes of path ‘%1%’") % path);
 
     if (st.st_uid != geteuid()) {
         assert(S_ISLNK(st.st_mode));
-        throw Error(format("wrong ownership of top-level store path '%1%'") % path);
+        throw Error(format("wrong ownership of top-level store path ‘%1%’") % path);
     }
 }
 
@@ -485,7 +485,7 @@ void LocalStore::checkDerivationOutputs(const Path & drvPath, const Derivation &
     if (drv.isFixedOutput()) {
         DerivationOutputs::const_iterator out = drv.outputs.find("out");
         if (out == drv.outputs.end())
-            throw Error(format("derivation '%1%' does not have an output named 'out'") % drvPath);
+            throw Error(format("derivation ‘%1%’ does not have an output named ‘out’") % drvPath);
 
         bool recursive; Hash h;
         out->second.parseHashInfo(recursive, h);
@@ -493,7 +493,7 @@ void LocalStore::checkDerivationOutputs(const Path & drvPath, const Derivation &
 
         StringPairs::const_iterator j = drv.env.find("out");
         if (out->second.path != outPath || j == drv.env.end() || j->second != outPath)
-            throw Error(format("derivation '%1%' has incorrect output '%2%', should be '%3%'")
+            throw Error(format("derivation ‘%1%’ has incorrect output ‘%2%’, should be ‘%3%’")
                 % drvPath % out->second.path % outPath);
     }
 
@@ -510,7 +510,7 @@ void LocalStore::checkDerivationOutputs(const Path & drvPath, const Derivation &
             Path outPath = makeOutputPath(i.first, h, drvName);
             StringPairs::const_iterator j = drv.env.find(i.first);
             if (i.second.path != outPath || j == drv.env.end() || j->second != outPath)
-                throw Error(format("derivation '%1%' has incorrect output '%2%', should be '%3%'")
+                throw Error(format("derivation ‘%1%’ has incorrect output ‘%2%’, should be ‘%3%’")
                     % drvPath % i.second.path % outPath);
         }
     }
@@ -568,11 +568,11 @@ Hash parseHashField(const Path & path, const string & s)
 {
     string::size_type colon = s.find(':');
     if (colon == string::npos)
-        throw Error(format("corrupt hash '%1%' in valid-path entry for '%2%'")
+        throw Error(format("corrupt hash ‘%1%’ in valid-path entry for ‘%2%’")
             % s % path);
     HashType ht = parseHashType(string(s, 0, colon));
     if (ht == htUnknown)
-        throw Error(format("unknown hash type '%1%' in valid-path entry for '%2%'")
+        throw Error(format("unknown hash type ‘%1%’ in valid-path entry for ‘%2%’")
             % string(s, 0, colon) % path);
     return parseHash(ht, string(s, colon + 1));
 }
@@ -648,7 +648,7 @@ uint64_t LocalStore::queryValidPathId(State & state, const Path & path)
 {
     auto use(state.stmtQueryPathInfo.use()(path));
     if (!use.next())
-        throw Error(format("path '%1%' is not valid") % path);
+        throw Error(format("path ‘%1%’ is not valid") % path);
     return use.getInt(0);
 }
 
@@ -815,7 +815,7 @@ void LocalStore::querySubstitutablePathInfos(const PathSet & paths,
         if (sub->storeDir != storeDir) continue;
         for (auto & path : paths) {
             if (infos.count(path)) continue;
-            debug(format("checking substituter '%s' for path '%s'")
+            debug(format("checking substituter ‘%s’ for path ‘%s’")
                 % sub->getUri() % path);
             try {
                 auto info = sub->queryPathInfo(path);
@@ -896,7 +896,7 @@ void LocalStore::registerValidPaths(const ValidPathInfos & infos)
    there are no referrers. */
 void LocalStore::invalidatePath(State & state, const Path & path)
 {
-    debug(format("invalidating path '%1%'") % path);
+    debug(format("invalidating path ‘%1%’") % path);
 
     state.stmtInvalidatePath.use()(path).exec();
 
@@ -915,11 +915,11 @@ void LocalStore::addToStore(const ValidPathInfo & info, const ref<std::string> &
 {
     Hash h = hashString(htSHA256, *nar);
     if (h != info.narHash)
-        throw Error(format("hash mismatch importing path '%s'; expected hash '%s', got '%s'") %
+        throw Error(format("hash mismatch importing path ‘%s’; expected hash ‘%s’, got ‘%s’") %
             info.path % info.narHash.to_string() % h.to_string());
 
     if (requireSigs && !dontCheckSigs && !info.checkSignatures(*this, publicKeys))
-        throw Error(format("cannot import path '%s' because it lacks a valid signature") % info.path);
+        throw Error(format("cannot import path ‘%s’ because it lacks a valid signature") % info.path);
 
     addTempRoot(info.path);
 
@@ -1106,7 +1106,7 @@ void LocalStore::invalidatePathChecked(const Path & path)
             PathSet referrers; queryReferrers(*state, path, referrers);
             referrers.erase(path); /* ignore self-references */
             if (!referrers.empty())
-                throw PathInUse(format("cannot delete path '%1%' because it is in use by %2%")
+                throw PathInUse(format("cannot delete path ‘%1%’ because it is in use by %2%")
                     % path % showPaths(referrers));
             invalidatePath(*state, path);
         }
@@ -1151,12 +1151,12 @@ bool LocalStore::verifyStore(bool checkContents, bool repair)
                 auto info = std::const_pointer_cast<ValidPathInfo>(std::shared_ptr<const ValidPathInfo>(queryPathInfo(i)));
 
                 /* Check the content hash (optionally - slow). */
-                printMsg(lvlTalkative, format("checking contents of '%1%'") % i);
+                printMsg(lvlTalkative, format("checking contents of ‘%1%’") % i);
                 HashResult current = hashPath(info->narHash.type, i);
 
                 if (info->narHash != nullHash && info->narHash != current.first) {
-                    printError(format("path '%1%' was modified! "
-                            "expected hash '%2%', got '%3%'")
+                    printError(format("path ‘%1%’ was modified! "
+                            "expected hash ‘%2%’, got ‘%3%’")
                         % i % printHash(info->narHash) % printHash(current.first));
                     if (repair) repairPath(i); else errors = true;
                 } else {
@@ -1165,14 +1165,14 @@ bool LocalStore::verifyStore(bool checkContents, bool repair)
 
                     /* Fill in missing hashes. */
                     if (info->narHash == nullHash) {
-                        printError(format("fixing missing hash on '%1%'") % i);
+                        printError(format("fixing missing hash on ‘%1%’") % i);
                         info->narHash = current.first;
                         update = true;
                     }
 
                     /* Fill in missing narSize fields (from old stores). */
                     if (info->narSize == 0) {
-                        printError(format("updating size field on '%1%' to %2%") % i % current.second);
+                        printError(format("updating size field on ‘%1%’ to %2%") % i % current.second);
                         info->narSize = current.second;
                         update = true;
                     }
@@ -1209,7 +1209,7 @@ void LocalStore::verifyPath(const Path & path, const PathSet & store,
     done.insert(path);
 
     if (!isStorePath(path)) {
-        printError(format("path '%1%' is not in the Nix store") % path);
+        printError(format("path ‘%1%’ is not in the Nix store") % path);
         auto state(_state.lock());
         invalidatePath(*state, path);
         return;
@@ -1228,11 +1228,11 @@ void LocalStore::verifyPath(const Path & path, const PathSet & store,
             }
 
         if (canInvalidate) {
-            printError(format("path '%1%' disappeared, removing from database...") % path);
+            printError(format("path ‘%1%’ disappeared, removing from database...") % path);
             auto state(_state.lock());
             invalidatePath(*state, path);
         } else {
-            printError(format("path '%1%' disappeared, but it still has valid referrers!") % path);
+            printError(format("path ‘%1%’ disappeared, but it still has valid referrers!") % path);
             if (repair)
                 try {
                     repairPath(path);
@@ -1271,7 +1271,7 @@ static void makeMutable(const Path & path)
     AutoCloseFD fd = open(path.c_str(), O_RDONLY | O_NOFOLLOW | O_CLOEXEC);
     if (fd == -1) {
         if (errno == ELOOP) return; // it's a symlink
-        throw SysError(format("opening file '%1%'") % path);
+        throw SysError(format("opening file ‘%1%’") % path);
     }
 
     unsigned int flags = 0, old;
diff --git a/src/libstore/local-store.hh b/src/libstore/local-store.hh
index 42b02ce461e3..511209d8404a 100644
--- a/src/libstore/local-store.hh
+++ b/src/libstore/local-store.hh
@@ -261,7 +261,7 @@ private:
     void queryReferrers(State & state, const Path & path, PathSet & referrers);
 
     /* Add signatures to a ValidPathInfo using the secret keys
-       specified by the 'secret-key-files' option. */
+       specified by the ‘secret-key-files’ option. */
     void signPathInfo(ValidPathInfo & info);
 
     Path getRealStoreDir() override { return realStoreDir; }
diff --git a/src/libstore/misc.cc b/src/libstore/misc.cc
index 8fa84d3a2787..9a88cdc317b6 100644
--- a/src/libstore/misc.cc
+++ b/src/libstore/misc.cc
@@ -245,7 +245,7 @@ Paths Store::topoSortPaths(const PathSet & paths)
 
     dfsVisit = [&](const Path & path, const Path * parent) {
         if (parents.find(path) != parents.end())
-            throw BuildError(format("cycle detected in the references of '%1%' from '%2%'") % path % *parent);
+            throw BuildError(format("cycle detected in the references of ‘%1%’ from ‘%2%’") % path % *parent);
 
         if (visited.find(path) != visited.end()) return;
         visited.insert(path);
diff --git a/src/libstore/nar-accessor.cc b/src/libstore/nar-accessor.cc
index 686ecd727c47..ded19c05d2cd 100644
--- a/src/libstore/nar-accessor.cc
+++ b/src/libstore/nar-accessor.cc
@@ -75,7 +75,7 @@ struct NarIndexer : ParseSink, StringSource
     {
         auto i = members.find(path);
         if (i == members.end())
-            throw Error(format("NAR file does not contain path '%1%'") % path);
+            throw Error(format("NAR file does not contain path ‘%1%’") % path);
         return i;
     }
 };
@@ -103,7 +103,7 @@ struct NarAccessor : public FSAccessor
         auto i = indexer.find(path);
 
         if (i->second.type != FSAccessor::Type::tDirectory)
-            throw Error(format("path '%1%' inside NAR file is not a directory") % path);
+            throw Error(format("path ‘%1%’ inside NAR file is not a directory") % path);
 
         ++i;
         StringSet res;
@@ -120,7 +120,7 @@ struct NarAccessor : public FSAccessor
     {
         auto i = indexer.find(path);
         if (i->second.type != FSAccessor::Type::tRegular)
-            throw Error(format("path '%1%' inside NAR file is not a regular file") % path);
+            throw Error(format("path ‘%1%’ inside NAR file is not a regular file") % path);
         return std::string(*nar, i->second.start, i->second.size);
     }
 
@@ -128,7 +128,7 @@ struct NarAccessor : public FSAccessor
     {
         auto i = indexer.find(path);
         if (i->second.type != FSAccessor::Type::tSymlink)
-            throw Error(format("path '%1%' inside NAR file is not a symlink") % path);
+            throw Error(format("path ‘%1%’ inside NAR file is not a symlink") % path);
         return i->second.target;
     }
 };
diff --git a/src/libstore/nar-info.cc b/src/libstore/nar-info.cc
index 0bd28533c241..201cac671a55 100644
--- a/src/libstore/nar-info.cc
+++ b/src/libstore/nar-info.cc
@@ -6,7 +6,7 @@ namespace nix {
 NarInfo::NarInfo(const Store & store, const std::string & s, const std::string & whence)
 {
     auto corrupt = [&]() {
-        throw Error(format("NAR info file '%1%' is corrupt") % whence);
+        throw Error(format("NAR info file ‘%1%’ is corrupt") % whence);
     };
 
     auto parseHashField = [&](const string & s) {
diff --git a/src/libstore/optimise-store.cc b/src/libstore/optimise-store.cc
index cce3b53d48ed..454c8b49d84b 100644
--- a/src/libstore/optimise-store.cc
+++ b/src/libstore/optimise-store.cc
@@ -20,9 +20,9 @@ static void makeWritable(const Path & path)
 {
     struct stat st;
     if (lstat(path.c_str(), &st))
-        throw SysError(format("getting attributes of path '%1%'") % path);
+        throw SysError(format("getting attributes of path ‘%1%’") % path);
     if (chmod(path.c_str(), st.st_mode | S_IWUSR) == -1)
-        throw SysError(format("changing writability of '%1%'") % path);
+        throw SysError(format("changing writability of ‘%1%’") % path);
 }
 
 
@@ -48,7 +48,7 @@ LocalStore::InodeHash LocalStore::loadInodeHash()
     InodeHash inodeHash;
 
     AutoCloseDir dir = opendir(linksDir.c_str());
-    if (!dir) throw SysError(format("opening directory '%1%'") % linksDir);
+    if (!dir) throw SysError(format("opening directory ‘%1%’") % linksDir);
 
     struct dirent * dirent;
     while (errno = 0, dirent = readdir(dir)) { /* sic */
@@ -56,7 +56,7 @@ LocalStore::InodeHash LocalStore::loadInodeHash()
         // We don't care if we hit non-hash files, anything goes
         inodeHash.insert(dirent->d_ino);
     }
-    if (errno) throw SysError(format("reading directory '%1%'") % linksDir);
+    if (errno) throw SysError(format("reading directory ‘%1%’") % linksDir);
 
     printMsg(lvlTalkative, format("loaded %1% hash inodes") % inodeHash.size());
 
@@ -69,14 +69,14 @@ Strings LocalStore::readDirectoryIgnoringInodes(const Path & path, const InodeHa
     Strings names;
 
     AutoCloseDir dir = opendir(path.c_str());
-    if (!dir) throw SysError(format("opening directory '%1%'") % path);
+    if (!dir) throw SysError(format("opening directory ‘%1%’") % path);
 
     struct dirent * dirent;
     while (errno = 0, dirent = readdir(dir)) { /* sic */
         checkInterrupt();
 
         if (inodeHash.count(dirent->d_ino)) {
-            debug(format("'%1%' is already linked") % dirent->d_name);
+            debug(format("‘%1%’ is already linked") % dirent->d_name);
             continue;
         }
 
@@ -84,7 +84,7 @@ Strings LocalStore::readDirectoryIgnoringInodes(const Path & path, const InodeHa
         if (name == "." || name == "..") continue;
         names.push_back(name);
     }
-    if (errno) throw SysError(format("reading directory '%1%'") % path);
+    if (errno) throw SysError(format("reading directory ‘%1%’") % path);
 
     return names;
 }
@@ -96,7 +96,7 @@ void LocalStore::optimisePath_(OptimiseStats & stats, const Path & path, InodeHa
 
     struct stat st;
     if (lstat(path.c_str(), &st))
-        throw SysError(format("getting attributes of path '%1%'") % path);
+        throw SysError(format("getting attributes of path ‘%1%’") % path);
 
     if (S_ISDIR(st.st_mode)) {
         Strings names = readDirectoryIgnoringInodes(path, inodeHash);
@@ -117,13 +117,13 @@ void LocalStore::optimisePath_(OptimiseStats & stats, const Path & path, InodeHa
        NixOS (example: $fontconfig/var/cache being modified).  Skip
        those files.  FIXME: check the modification time. */
     if (S_ISREG(st.st_mode) && (st.st_mode & S_IWUSR)) {
-        printError(format("skipping suspicious writable file '%1%'") % path);
+        printError(format("skipping suspicious writable file ‘%1%’") % path);
         return;
     }
 
     /* This can still happen on top-level files. */
     if (st.st_nlink > 1 && inodeHash.count(st.st_ino)) {
-        debug(format("'%1%' is already linked, with %2% other file(s)") % path % (st.st_nlink - 2));
+        debug(format("‘%1%’ is already linked, with %2% other file(s)") % path % (st.st_nlink - 2));
         return;
     }
 
@@ -137,7 +137,7 @@ void LocalStore::optimisePath_(OptimiseStats & stats, const Path & path, InodeHa
        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;
-    debug(format("'%1%' has hash '%2%'") % path % printHash(hash));
+    debug(format("‘%1%’ has hash ‘%2%’") % path % printHash(hash));
 
     /* Check if this is a known hash. */
     Path linkPath = linksDir + "/" + printHash32(hash);
@@ -152,7 +152,7 @@ void LocalStore::optimisePath_(OptimiseStats & stats, const Path & path, InodeHa
 
         switch (errno) {
         case EEXIST:
-            /* Fall through if another process created 'linkPath' before
+            /* Fall through if another process created ‘linkPath’ before
                we did. */
             break;
 
@@ -161,11 +161,11 @@ void LocalStore::optimisePath_(OptimiseStats & stats, const Path & path, InodeHa
                full.  When that happens, it's fine to ignore it: we
                just effectively disable deduplication of this
                file.  */
-            printInfo("cannot link '%s' to '%s': %s", linkPath, path, strerror(errno));
+            printInfo("cannot link ‘%s’ to ‘%s’: %s", linkPath, path, strerror(errno));
             return;
 
         default:
-            throw SysError("cannot link '%1%' to '%2%'", linkPath, path);
+            throw SysError("cannot link ‘%1%’ to ‘%2%’", linkPath, path);
         }
     }
 
@@ -173,20 +173,20 @@ void LocalStore::optimisePath_(OptimiseStats & stats, const Path & path, InodeHa
        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);
+        throw SysError(format("getting attributes of path ‘%1%’") % linkPath);
 
     if (st.st_ino == stLink.st_ino) {
-        debug(format("'%1%' is already linked to '%2%'") % path % linkPath);
+        debug(format("‘%1%’ is already linked to ‘%2%’") % path % linkPath);
         return;
     }
 
     if (st.st_size != stLink.st_size) {
-        printError(format("removing corrupted link '%1%'") % linkPath);
+        printError(format("removing corrupted link ‘%1%’") % linkPath);
         unlink(linkPath.c_str());
         goto retry;
     }
 
-    printMsg(lvlTalkative, format("linking '%1%' to '%2%'") % path % linkPath);
+    printMsg(lvlTalkative, format("linking ‘%1%’ to ‘%2%’") % path % linkPath);
 
     /* Make the containing directory writable, but only if it's not
        the store itself (we don't want or need to mess with its
@@ -207,26 +207,26 @@ void LocalStore::optimisePath_(OptimiseStats & stats, const Path & path, InodeHa
                systems).  This is likely to happen with empty files.
                Just shrug and ignore. */
             if (st.st_size)
-                printInfo(format("'%1%' has maximum number of links") % linkPath);
+                printInfo(format("‘%1%’ has maximum number of links") % linkPath);
             return;
         }
-        throw SysError("cannot link '%1%' to '%2%'", tempLink, linkPath);
+        throw SysError("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 (unlink(tempLink.c_str()) == -1)
-            printError(format("unable to unlink '%1%'") % tempLink);
+            printError(format("unable to unlink ‘%1%’") % tempLink);
         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.) */
             if (st.st_size)
-                printInfo(format("'%1%' has maximum number of links") % linkPath);
+                printInfo(format("‘%1%’ has maximum number of links") % linkPath);
             return;
         }
-        throw SysError(format("cannot rename '%1%' to '%2%'") % tempLink % path);
+        throw SysError(format("cannot rename ‘%1%’ to ‘%2%’") % tempLink % path);
     }
 
     stats.filesLinked++;
@@ -243,7 +243,7 @@ void LocalStore::optimiseStore(OptimiseStats & stats)
     for (auto & i : paths) {
         addTempRoot(i);
         if (!isValidPath(i)) continue; /* path was GC'ed, probably */
-        Activity act(*logger, lvlChatty, format("hashing files in '%1%'") % i);
+        Activity act(*logger, lvlChatty, format("hashing files in ‘%1%’") % i);
         optimisePath_(stats, realStoreDir + "/" + baseNameOf(i), inodeHash);
     }
 }
diff --git a/src/libstore/pathlocks.cc b/src/libstore/pathlocks.cc
index b473c837a4ca..8788ee1649fb 100644
--- a/src/libstore/pathlocks.cc
+++ b/src/libstore/pathlocks.cc
@@ -18,7 +18,7 @@ int openLockFile(const Path & path, bool create)
 
     fd = open(path.c_str(), O_CLOEXEC | O_RDWR | (create ? O_CREAT : 0), 0600);
     if (!fd && (create || errno != ENOENT))
-        throw SysError(format("opening lock file '%1%'") % path);
+        throw SysError(format("opening lock file ‘%1%’") % path);
 
     return fd.release();
 }
@@ -106,7 +106,7 @@ bool PathLocks::lockPaths(const PathSet & _paths,
         checkInterrupt();
         Path lockPath = path + ".lock";
 
-        debug(format("locking path '%1%'") % path);
+        debug(format("locking path ‘%1%’") % path);
 
         if (lockedPaths.find(lockPath) != lockedPaths.end())
             throw Error("deadlock: trying to re-acquire self-held lock");
@@ -131,19 +131,19 @@ bool PathLocks::lockPaths(const PathSet & _paths,
                 }
             }
 
-            debug(format("lock acquired on '%1%'") % lockPath);
+            debug(format("lock acquired on ‘%1%’") % lockPath);
 
             /* Check that the lock file hasn't become stale (i.e.,
                hasn't been unlinked). */
             struct stat st;
             if (fstat(fd.get(), &st) == -1)
-                throw SysError(format("statting lock file '%1%'") % lockPath);
+                throw SysError(format("statting lock file ‘%1%’") % lockPath);
             if (st.st_size != 0)
                 /* This lock file has been unlinked, so we're holding
                    a lock on a deleted file.  This means that other
                    processes may create and acquire a lock on
                    `lockPath', and proceed.  So we must retry. */
-                debug(format("open lock file '%1%' has become stale") % lockPath);
+                debug(format("open lock file ‘%1%’ has become stale") % lockPath);
             else
                 break;
         }
@@ -175,9 +175,9 @@ void PathLocks::unlock()
         lockedPaths.erase(i.second);
         if (close(i.first) == -1)
             printError(
-                format("error (ignored): cannot close lock file on '%1%'") % i.second);
+                format("error (ignored): cannot close lock file on ‘%1%’") % i.second);
 
-        debug(format("lock released on '%1%'") % i.second);
+        debug(format("lock released on ‘%1%’") % i.second);
     }
 
     fds.clear();
diff --git a/src/libstore/profiles.cc b/src/libstore/profiles.cc
index 4a607b584506..f24daa8862a1 100644
--- a/src/libstore/profiles.cc
+++ b/src/libstore/profiles.cc
@@ -50,7 +50,7 @@ Generations findGenerations(Path profile, int & curGen)
             gen.number = n;
             struct stat st;
             if (lstat(gen.path.c_str(), &st) != 0)
-                throw SysError(format("statting '%1%'") % gen.path);
+                throw SysError(format("statting ‘%1%’") % gen.path);
             gen.creationTime = st.st_mtime;
             gens.push_back(gen);
         }
@@ -117,7 +117,7 @@ Path createGeneration(ref<LocalFSStore> store, Path profile, Path outPath)
 static void removeFile(const Path & path)
 {
     if (remove(path.c_str()) == -1)
-        throw SysError(format("cannot unlink '%1%'") % path);
+        throw SysError(format("cannot unlink ‘%1%’") % path);
 }
 
 
@@ -149,7 +149,7 @@ void deleteGenerations(const Path & profile, const std::set<unsigned int> & gens
     Generations gens = findGenerations(profile, curGen);
 
     if (gensToDelete.find(curGen) != gensToDelete.end())
-        throw Error(format("cannot delete current generation of profile %1%'") % profile);
+        throw Error(format("cannot delete current generation of profile %1%’") % profile);
 
     for (auto & i : gens) {
         if (gensToDelete.find(i.number) == gensToDelete.end()) continue;
@@ -203,7 +203,7 @@ void deleteGenerationsOlderThan(const Path & profile, const string & timeSpec, b
     int days;
 
     if (!string2Int(strDays, days) || days < 1)
-        throw Error(format("invalid number of days specifier '%1%'") % timeSpec);
+        throw Error(format("invalid number of days specifier ‘%1%’") % timeSpec);
 
     time_t oldTime = curTime - days * 24 * 3600;
 
@@ -222,7 +222,7 @@ void switchLink(Path link, Path target)
 
 void lockProfile(PathLocks & lock, const Path & profile)
 {
-    lock.lockPaths({profile}, (format("waiting for lock on profile '%1%'") % profile).str());
+    lock.lockPaths({profile}, (format("waiting for lock on profile ‘%1%’") % profile).str());
     lock.setDeletion(true);
 }
 
diff --git a/src/libstore/references.cc b/src/libstore/references.cc
index ba9f18b9ca5e..33eab5a240b5 100644
--- a/src/libstore/references.cc
+++ b/src/libstore/references.cc
@@ -37,7 +37,7 @@ static void search(const unsigned char * s, unsigned int len,
         if (!match) continue;
         string ref((const char *) s + i, refLength);
         if (hashes.find(ref) != hashes.end()) {
-            debug(format("found reference to '%1%' at offset '%2%'")
+            debug(format("found reference to ‘%1%’ at offset ‘%2%’")
                   % ref % i);
             seen.insert(ref);
             hashes.erase(ref);
@@ -93,7 +93,7 @@ PathSet scanForReferences(const string & path,
         string baseName = baseNameOf(i);
         string::size_type pos = baseName.find('-');
         if (pos == string::npos)
-            throw Error(format("bad reference '%1%'") % i);
+            throw Error(format("bad reference ‘%1%’") % i);
         string s = string(baseName, 0, pos);
         assert(s.size() == refLength);
         assert(backMap.find(s) == backMap.end());
diff --git a/src/libstore/remote-fs-accessor.cc b/src/libstore/remote-fs-accessor.cc
index 098151f8c0f6..ca14057c2e28 100644
--- a/src/libstore/remote-fs-accessor.cc
+++ b/src/libstore/remote-fs-accessor.cc
@@ -17,7 +17,7 @@ std::pair<ref<FSAccessor>, Path> RemoteFSAccessor::fetch(const Path & path_)
     std::string restPath = std::string(path, storePath.size());
 
     if (!store->isValidPath(storePath))
-        throw InvalidPath(format("path '%1%' is not a valid store path") % storePath);
+        throw InvalidPath(format("path ‘%1%’ is not a valid store path") % storePath);
 
     auto i = nars.find(storePath);
     if (i != nars.end()) return {i->second, restPath};
diff --git a/src/libstore/remote-store.cc b/src/libstore/remote-store.cc
index 5e162b03e45f..77faa2f801f1 100644
--- a/src/libstore/remote-store.cc
+++ b/src/libstore/remote-store.cc
@@ -83,11 +83,11 @@ ref<RemoteStore::Connection> UDSRemoteStore::openConnection()
     struct sockaddr_un addr;
     addr.sun_family = AF_UNIX;
     if (socketPath.size() + 1 >= sizeof(addr.sun_path))
-        throw Error(format("socket path '%1%' is too long") % socketPath);
+        throw Error(format("socket path ‘%1%’ is too long") % socketPath);
     strcpy(addr.sun_path, socketPath.c_str());
 
     if (connect(conn->fd.get(), (struct sockaddr *) &addr, sizeof(addr)) == -1)
-        throw SysError(format("cannot connect to daemon at '%1%'") % socketPath);
+        throw SysError(format("cannot connect to daemon at ‘%1%’") % socketPath);
 
     conn->from.fd = conn->fd.get();
     conn->to.fd = conn->fd.get();
@@ -277,7 +277,7 @@ void RemoteStore::queryPathInfoUncached(const Path & path,
         }
         if (GET_PROTOCOL_MINOR(conn->daemonVersion) >= 17) {
             bool valid = readInt(conn->from) != 0;
-            if (!valid) throw InvalidPath(format("path '%s' is not valid") % path);
+            if (!valid) throw InvalidPath(format("path ‘%s’ is not valid") % path);
         }
         auto info = std::make_shared<ValidPathInfo>();
         info->path = path;
diff --git a/src/libstore/s3-binary-cache-store.cc b/src/libstore/s3-binary-cache-store.cc
index 86ac2a7c485e..1bc8576a8aef 100644
--- a/src/libstore/s3-binary-cache-store.cc
+++ b/src/libstore/s3-binary-cache-store.cc
@@ -81,9 +81,9 @@ struct S3BinaryCacheStoreImpl : public S3BinaryCacheStore
 
             if (!res.IsSuccess()) {
                 if (res.GetError().GetErrorType() != Aws::S3::S3Errors::NO_SUCH_BUCKET)
-                    throw Error(format("AWS error checking bucket '%s': %s") % bucketName % res.GetError().GetMessage());
+                    throw Error(format("AWS error checking bucket ‘%s’: %s") % bucketName % res.GetError().GetMessage());
 
-                checkAws(format("AWS error creating bucket '%s'") % bucketName,
+                checkAws(format("AWS error creating bucket ‘%s’") % bucketName,
                     client->CreateBucket(
                         Aws::S3::Model::CreateBucketRequest()
                         .WithBucket(bucketName)
@@ -132,7 +132,7 @@ struct S3BinaryCacheStoreImpl : public S3BinaryCacheStore
             if (error.GetErrorType() == Aws::S3::S3Errors::UNKNOWN // FIXME
                 && error.GetMessage().find("404") != std::string::npos)
                 return false;
-            throw Error(format("AWS error fetching '%s': %s") % path % error.GetMessage());
+            throw Error(format("AWS error fetching ‘%s’: %s") % path % error.GetMessage());
         }
 
         return true;
@@ -154,14 +154,14 @@ struct S3BinaryCacheStoreImpl : public S3BinaryCacheStore
 
         auto now1 = std::chrono::steady_clock::now();
 
-        auto result = checkAws(format("AWS error uploading '%s'") % path,
+        auto result = checkAws(format("AWS error uploading ‘%s’") % path,
             client->PutObject(request));
 
         auto now2 = std::chrono::steady_clock::now();
 
         auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(now2 - now1).count();
 
-        printInfo(format("uploaded 's3://%1%/%2%' (%3% bytes) in %4% ms")
+        printInfo(format("uploaded ‘s3://%1%/%2%’ (%3% bytes) in %4% ms")
             % bucketName % path % data.size() % duration);
 
         stats.putTimeMs += duration;
@@ -172,7 +172,7 @@ struct S3BinaryCacheStoreImpl : public S3BinaryCacheStore
         std::function<void(std::exception_ptr exc)> failure) override
     {
         sync2async<std::shared_ptr<std::string>>(success, failure, [&]() {
-            debug(format("fetching 's3://%1%/%2%'...") % bucketName % path);
+            debug(format("fetching ‘s3://%1%/%2%’...") % bucketName % path);
 
             auto request =
                 Aws::S3::Model::GetObjectRequest()
@@ -189,7 +189,7 @@ struct S3BinaryCacheStoreImpl : public S3BinaryCacheStore
 
                 auto now1 = std::chrono::steady_clock::now();
 
-                auto result = checkAws(format("AWS error fetching '%s'") % path,
+                auto result = checkAws(format("AWS error fetching ‘%s’") % path,
                     client->GetObject(request));
 
                 auto now2 = std::chrono::steady_clock::now();
@@ -198,7 +198,7 @@ struct S3BinaryCacheStoreImpl : public S3BinaryCacheStore
 
                 auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(now2 - now1).count();
 
-                printMsg(lvlTalkative, format("downloaded 's3://%1%/%2%' (%3% bytes) in %4% ms")
+                printMsg(lvlTalkative, format("downloaded ‘s3://%1%/%2%’ (%3% bytes) in %4% ms")
                     % bucketName % path % res.size() % duration);
 
                 stats.getBytes += res.size();
@@ -219,9 +219,9 @@ struct S3BinaryCacheStoreImpl : public S3BinaryCacheStore
         std::string marker;
 
         do {
-            debug(format("listing bucket 's3://%s' from key '%s'...") % bucketName % marker);
+            debug(format("listing bucket ‘s3://%s’ from key ‘%s’...") % bucketName % marker);
 
-            auto res = checkAws(format("AWS error listing bucket '%s'") % bucketName,
+            auto res = checkAws(format("AWS error listing bucket ‘%s’") % bucketName,
                 client->ListObjects(
                     Aws::S3::Model::ListObjectsRequest()
                     .WithBucket(bucketName)
@@ -230,7 +230,7 @@ struct S3BinaryCacheStoreImpl : public S3BinaryCacheStore
 
             auto & contents = res.GetContents();
 
-            debug(format("got %d keys, next marker '%s'")
+            debug(format("got %d keys, next marker ‘%s’")
                 % contents.size() % res.GetNextMarker());
 
             for (auto object : contents) {
diff --git a/src/libstore/sqlite.cc b/src/libstore/sqlite.cc
index d3d48233bcc3..0197b091cd12 100644
--- a/src/libstore/sqlite.cc
+++ b/src/libstore/sqlite.cc
@@ -39,7 +39,7 @@ SQLite::SQLite(const Path & path)
 {
     if (sqlite3_open_v2(path.c_str(), &db,
             SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, 0) != SQLITE_OK)
-        throw Error(format("cannot open SQLite database '%s'") % path);
+        throw Error(format("cannot open SQLite database ‘%s’") % path);
 }
 
 SQLite::~SQLite()
@@ -55,7 +55,7 @@ SQLite::~SQLite()
 void SQLite::exec(const std::string & stmt)
 {
     if (sqlite3_exec(db, stmt.c_str(), 0, 0, 0) != SQLITE_OK)
-        throwSQLiteError(db, format("executing SQLite statement '%s'") % stmt);
+        throwSQLiteError(db, format("executing SQLite statement ‘%s’") % stmt);
 }
 
 void SQLiteStmt::create(sqlite3 * db, const string & s)
diff --git a/src/libstore/store-api.cc b/src/libstore/store-api.cc
index b14277f9f7a6..37a2d45fefe0 100644
--- a/src/libstore/store-api.cc
+++ b/src/libstore/store-api.cc
@@ -27,14 +27,14 @@ bool Store::isStorePath(const Path & path) const
 void Store::assertStorePath(const Path & path) const
 {
     if (!isStorePath(path))
-        throw Error(format("path '%1%' is not in the Nix store") % path);
+        throw Error(format("path ‘%1%’ is not in the Nix store") % path);
 }
 
 
 Path Store::toStorePath(const Path & path) const
 {
     if (!isInStore(path))
-        throw Error(format("path '%1%' is not in the Nix store") % path);
+        throw Error(format("path ‘%1%’ is not in the Nix store") % path);
     Path::size_type slash = path.find('/', storeDir.size() + 1);
     if (slash == Path::npos)
         return path;
@@ -52,7 +52,7 @@ Path Store::followLinksToStore(const Path & _path) const
         path = absPath(target, dirOf(path));
     }
     if (!isInStore(path))
-        throw Error(format("path '%1%' is not in the Nix store") % path);
+        throw Error(format("path ‘%1%’ is not in the Nix store") % path);
     return path;
 }
 
@@ -85,14 +85,14 @@ void checkStoreName(const string & name)
     /* Disallow names starting with a dot for possible security
        reasons (e.g., "." and ".."). */
     if (string(name, 0, 1) == ".")
-        throw Error(format("illegal name: '%1%'") % name);
+        throw Error(format("illegal name: ‘%1%’") % name);
     for (auto & i : name)
         if (!((i >= 'A' && i <= 'Z') ||
               (i >= 'a' && i <= 'z') ||
               (i >= '0' && i <= '9') ||
               validChars.find(i) != string::npos))
         {
-            throw Error(format("invalid character '%1%' in name '%2%'")
+            throw Error(format("invalid character ‘%1%’ in name ‘%2%’")
                 % i % name);
         }
 }
@@ -312,7 +312,7 @@ void Store::queryPathInfo(const Path & storePath,
             if (res) {
                 stats.narInfoReadAverted++;
                 if (!*res)
-                    throw InvalidPath(format("path '%s' is not valid") % storePath);
+                    throw InvalidPath(format("path ‘%s’ is not valid") % storePath);
                 return success(ref<ValidPathInfo>(*res));
             }
         }
@@ -327,7 +327,7 @@ void Store::queryPathInfo(const Path & storePath,
                         res.first == NarInfoDiskCache::oInvalid ? 0 : res.second);
                     if (res.first == NarInfoDiskCache::oInvalid ||
                         (res.second->path != storePath && storePathToName(storePath) != ""))
-                        throw InvalidPath(format("path '%s' is not valid") % storePath);
+                        throw InvalidPath(format("path ‘%s’ is not valid") % storePath);
                 }
                 return success(ref<ValidPathInfo>(res.second));
             }
@@ -352,7 +352,7 @@ void Store::queryPathInfo(const Path & storePath,
                 || (info->path != storePath && storePathToName(storePath) != ""))
             {
                 stats.narInfoMissing++;
-                return failure(std::make_exception_ptr(InvalidPath(format("path '%s' is not valid") % storePath)));
+                return failure(std::make_exception_ptr(InvalidPath(format("path ‘%s’ is not valid") % storePath)));
             }
 
             callSuccess(success, failure, ref<ValidPathInfo>(info));
@@ -514,7 +514,7 @@ string showPaths(const PathSet & paths)
     string s;
     for (auto & i : paths) {
         if (s.size() != 0) s += ", ";
-        s += "'" + i + "'";
+        s += "‘" + i + "’";
     }
     return s;
 }
@@ -523,7 +523,7 @@ string showPaths(const PathSet & paths)
 std::string ValidPathInfo::fingerprint() const
 {
     if (narSize == 0 || !narHash)
-        throw Error(format("cannot calculate fingerprint of path '%s' because its size/hash is not known")
+        throw Error(format("cannot calculate fingerprint of path ‘%s’ because its size/hash is not known")
             % path);
     return
         "1;" + path + ";"
@@ -542,7 +542,7 @@ void ValidPathInfo::sign(const SecretKey & secretKey)
 bool ValidPathInfo::isContentAddressed(const Store & store) const
 {
     auto warn = [&]() {
-        printError(format("warning: path '%s' claims to be content-addressed but isn't") % path);
+        printError(format("warning: path ‘%s’ claims to be content-addressed but isn't") % path);
     };
 
     if (hasPrefix(ca, "text:")) {
@@ -625,7 +625,7 @@ ref<Store> openStore(const std::string & uri_)
         if (store) return ref<Store>(store);
     }
 
-    throw Error(format("don't know how to open Nix store '%s'") % uri);
+    throw Error(format("don't know how to open Nix store ‘%s’") % uri);
 }
 
 
diff --git a/src/libstore/store-api.hh b/src/libstore/store-api.hh
index 36c2df79ad87..2ea74d90e78e 100644
--- a/src/libstore/store-api.hh
+++ b/src/libstore/store-api.hh
@@ -131,16 +131,16 @@ struct ValidPathInfo
 
        Ideally, the content-addressability assertion would just be a
        Boolean, and the store path would be computed from
-       'storePathToName(path)', 'narHash' and 'references'. However,
+       ‘storePathToName(path)’, ‘narHash’ and ‘references’. However,
        1) we've accumulated several types of content-addressed paths
        over the years; and 2) fixed-output derivations support
        multiple hash algorithms and serialisation methods (flat file
-       vs NAR). Thus, 'ca' has one of the following forms:
+       vs NAR). Thus, ‘ca’ has one of the following forms:
 
-       * 'text:sha256:<sha256 hash of file contents>': For paths
+       * ‘text:sha256:<sha256 hash of file contents>’: For paths
          computed by makeTextPath() / addTextToStore().
 
-       * 'fixed:<r?>:<ht>:<h>': For paths computed by
+       * ‘fixed:<r?>:<ht>:<h>’: For paths computed by
          makeFixedOutputPath() / addToStore().
     */
     std::string ca;
@@ -242,15 +242,15 @@ public:
 
     virtual std::string getUri() = 0;
 
-    /* Return true if 'path' is in the Nix store (but not the Nix
+    /* Return true if ‘path’ is in the Nix store (but not the Nix
        store itself). */
     bool isInStore(const Path & path) const;
 
-    /* Return true if 'path' is a store path, i.e. a direct child of
+    /* Return true if ‘path’ is a store path, i.e. a direct child of
        the Nix store. */
     bool isStorePath(const Path & path) const;
 
-    /* Throw an exception if 'path' is not a store path. */
+    /* Throw an exception if ‘path’ is not a store path. */
     void assertStorePath(const Path & path) const;
 
     /* Chop off the parts after the top-level store name, e.g.,
@@ -363,7 +363,7 @@ public:
 
     /* Query substitute info (i.e. references, derivers and download
        sizes) of a set of paths.  If a path does not have substitute
-       info, it's omitted from the resulting 'infos' map. */
+       info, it's omitted from the resulting ‘infos’ map. */
     virtual void querySubstitutablePathInfos(const PathSet & paths,
         SubstitutablePathInfos & infos) = 0;
 
@@ -401,7 +401,7 @@ public:
     virtual void buildPaths(const PathSet & paths, BuildMode buildMode = bmNormal) = 0;
 
     /* Build a single non-materialized derivation (i.e. not from an
-       on-disk .drv file). Note that 'drvPath' is only used for
+       on-disk .drv file). Note that ‘drvPath’ is only used for
        informational purposes. */
     virtual BuildResult buildDerivation(const Path & drvPath, const BasicDerivation & drv,
         BuildMode buildMode = bmNormal) = 0;
@@ -503,8 +503,8 @@ public:
        relation.  If p refers to q, then p preceeds q in this list. */
     Paths topoSortPaths(const PathSet & paths);
 
-    /* Export multiple paths in the format expected by 'nix-store
-       --import'. */
+    /* Export multiple paths in the format expected by ‘nix-store
+       --import’. */
     void exportPaths(const Paths & paths, Sink & sink);
 
     void exportPath(const Path & path, Sink & sink);
@@ -573,7 +573,7 @@ string storePathToName(const Path & path);
 /* Extract the hash part of the given store path. */
 string storePathToHash(const Path & path);
 
-/* Check whether 'name' is a valid store path name part, i.e. contains
+/* Check whether ‘name’ is a valid store path name part, i.e. contains
    only the characters [a-zA-Z0-9\+\-\.\_\?\=] and doesn't start with
    a dot. */
 void checkStoreName(const string & name);
@@ -596,17 +596,17 @@ void removeTempRoots();
 
 
 /* Return a Store object to access the Nix store denoted by
-   'uri' (slight misnomer...). Supported values are:
+   ‘uri’ (slight misnomer...). Supported values are:
 
-   * 'direct': The Nix store in /nix/store and database in
+   * ‘direct’: The Nix store in /nix/store and database in
      /nix/var/nix/db, accessed directly.
 
-   * 'daemon': The Nix store accessed via a Unix domain socket
+   * ‘daemon’: The Nix store accessed via a Unix domain socket
      connection to nix-daemon.
 
-   * 'file://<path>': A binary cache stored in <path>.
+   * ‘file://<path>’: A binary cache stored in <path>.
 
-   If 'uri' is empty, it defaults to 'direct' or 'daemon' depending on
+   If ‘uri’ is empty, it defaults to ‘direct’ or ‘daemon’ depending on
    whether the user has write access to the local Nix store/database.
    set to true *unless* you're going to collect garbage. */
 ref<Store> openStore(const std::string & uri = getEnv("NIX_REMOTE"));
@@ -622,8 +622,8 @@ enum StoreType {
 StoreType getStoreType(const std::string & uri = getEnv("NIX_REMOTE"), const std::string & stateDir = settings.nixStateDir);
 
 /* Return the default substituter stores, defined by the
-   'substituters' option and various legacy options like
-   'binary-caches'. */
+   ‘substituters’ option and various legacy options like
+   ‘binary-caches’. */
 std::list<ref<Store>> getDefaultSubstituters();