diff options
author | Klaus Aehlig <aehlig@google.com> | 2018-07-18 00:11:02 -0700 |
---|---|---|
committer | Copybara-Service <copybara-piper@google.com> | 2018-07-18 00:12:14 -0700 |
commit | a22ad80b416e5f603fe9e82ba05f72cf42573f86 (patch) | |
tree | f80dbf5becd565fd28c75f47bcc8d00253834b04 /src/main/java/com/google/devtools/build/lib/bazel | |
parent | f09a7f5f70280d8fb3a85a4d292f31a876dfb8ac (diff) |
RepositoryCache: support hard linkning
Instead of copying files found in a cache hit, support adding
a hard link. This should save disk space if the same files from
cache are used in many workspaces. Fixes #5568.
Change-Id: Ie8192f9669d8420283e18e0813f3160a515ba8fe
PiperOrigin-RevId: 205034815
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/bazel')
3 files changed, 26 insertions, 6 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/bazel/BazelRepositoryModule.java b/src/main/java/com/google/devtools/build/lib/bazel/BazelRepositoryModule.java index 89f40e0a27..2b05a506e1 100644 --- a/src/main/java/com/google/devtools/build/lib/bazel/BazelRepositoryModule.java +++ b/src/main/java/com/google/devtools/build/lib/bazel/BazelRepositoryModule.java @@ -230,6 +230,7 @@ public class BazelRepositoryModule extends BlazeModule { RepositoryOptions repoOptions = env.getOptions().getOptions(RepositoryOptions.class); if (repoOptions != null) { + repositoryCache.setHardlink(repoOptions.useHardlinks); if (repoOptions.experimentalRepositoryCache != null) { Path repositoryCachePath; if (repoOptions.experimentalRepositoryCache.isAbsolute()) { diff --git a/src/main/java/com/google/devtools/build/lib/bazel/repository/RepositoryOptions.java b/src/main/java/com/google/devtools/build/lib/bazel/repository/RepositoryOptions.java index d3ced966e2..5b06cab1a3 100644 --- a/src/main/java/com/google/devtools/build/lib/bazel/repository/RepositoryOptions.java +++ b/src/main/java/com/google/devtools/build/lib/bazel/repository/RepositoryOptions.java @@ -47,6 +47,16 @@ public class RepositoryOptions extends OptionsBase { public PathFragment experimentalRepositoryCache; @Option( + name = "experimental_repository_cache_hardlinks", + defaultValue = "false", + documentationCategory = OptionDocumentationCategory.BAZEL_CLIENT_OPTIONS, + effectTags = {OptionEffectTag.BAZEL_INTERNAL_CONFIGURATION}, + help = + "If set, the repository cache will hardlink the file in case of a" + + " cache hit, rather than copying. This is inteded to save disk space.") + public boolean useHardlinks; + + @Option( name = "distdir", oldName = "experimental_distdir", defaultValue = "null", diff --git a/src/main/java/com/google/devtools/build/lib/bazel/repository/cache/RepositoryCache.java b/src/main/java/com/google/devtools/build/lib/bazel/repository/cache/RepositoryCache.java index 956d826e9c..aa1904009c 100644 --- a/src/main/java/com/google/devtools/build/lib/bazel/repository/cache/RepositoryCache.java +++ b/src/main/java/com/google/devtools/build/lib/bazel/repository/cache/RepositoryCache.java @@ -76,6 +76,7 @@ public class RepositoryCache { @Nullable private Path repositoryCachePath; @Nullable private Path contentAddressablePath; + private boolean useHardlinks; public void setRepositoryCachePath(@Nullable Path repositoryCachePath) { this.repositoryCachePath = repositoryCachePath; @@ -83,6 +84,10 @@ public class RepositoryCache { ? repositoryCachePath.getRelative(CAS_DIR) : null; } + public void setHardlink(boolean useHardlinks) { + this.useHardlinks = useHardlinks; + } + /** * @return true iff the cache path is set. */ @@ -103,11 +108,11 @@ public class RepositoryCache { } /** - * Copies a cached value to a specified directory, if it exists. + * Copy or hardlink cached value to a specified directory, if it exists. * - * We're using copying instead of symlinking because symlinking require weird checks to verify - * that the symlink still points to an existing artifact. e.g. cleaning up the central cache but - * not the workspace cache. + * <p>We're using hardlinking instead of symlinking because symlinking require weird checks to + * verify that the symlink still points to an existing artifact. e.g. cleaning up the central + * cache but not the workspace cache. * * @param cacheKey The string key to cache the value by. * @param targetPath The path where the cache value should be copied to. @@ -118,7 +123,7 @@ public class RepositoryCache { */ @Nullable public synchronized Path get(String cacheKey, Path targetPath, KeyType keyType) - throws IOException { + throws IOException { Preconditions.checkState(isEnabled()); assertKeyIsValid(cacheKey, keyType); @@ -138,7 +143,11 @@ public class RepositoryCache { } FileSystemUtils.createDirectoryAndParents(targetPath.getParentDirectory()); - FileSystemUtils.copyFile(cacheValue, targetPath); + if (useHardlinks) { + FileSystemUtils.createHardLink(targetPath, cacheValue); + } else { + FileSystemUtils.copyFile(cacheValue, targetPath); + } FileSystemUtils.touchFile(cacheValue); return targetPath; |