Permalink
Browse files

Introduce support for OS-specific standard cache directories (#676)

This cleans up the home directories of users and helps making sure that
Coursier's cache is not accidentically backed up by applications or OS
functionality.

The precedence is as follows:

- existing $COURSIER_CACHE environment variable
- existing coursier.cache Java property
- existing operating system specific standards:
  - Linux:   $XDG_CACHE_HOME/coursier, with fallback to ~/.cache/coursier
  - Windows: {SpecialFolder.LocalApplicationData}/cache/Coursier
  - macOS:   $HOME/Library/Caches/Coursier
- existing ~/.coursier/
- fallback to operating system specific standard directory else.

See discussion in #676 (comment)
  • Loading branch information...
soc authored and alexarchambault committed Oct 27, 2017
1 parent e2f47b0 commit 1871610751281a0eb8941418bf7b2f30a4c3e7f4
Showing with 89 additions and 15 deletions.
  1. +3 −0 .gitmodules
  2. +12 −3 build.sbt
  3. +1 −0 directories
  4. +1 −12 paths/src/main/java/coursier/CachePath.java
  5. +72 −0 paths/src/main/java/coursier/CoursierPaths.java
View
@@ -1,3 +1,6 @@
[submodule "tests/metadata"]
path = tests/metadata
url = https://github.com/coursier/test-metadata.git
[submodule "directories"]
path = directories
url = https://github.com/soc/directories.git
View
@@ -85,7 +85,8 @@ lazy val `proxy-tests` = project
lazy val paths = project
.settings(
pureJava,
dontPublish
dontPublish,
addDirectoriesSources
)
lazy val cache = project
@@ -461,6 +462,14 @@ lazy val sharedTestResources = {
unmanagedResourceDirectories.in(Test) += baseDirectory.in(LocalRootProject).value / "tests" / "shared" / "src" / "test" / "resources"
}
lazy val addPathsSources = {
unmanagedSourceDirectories.in(Compile) ++= unmanagedSourceDirectories.in(Compile).in(paths).value
// Using directly the sources of directories, rather than depending on it.
// This is required to use it from the bootstrap module, whose jar is launched as is (so shouldn't require dependencies).
// This is done for the other use of it too, from the cache module, not to have to manage two ways of depending on it.
lazy val addDirectoriesSources = {
unmanagedSourceDirectories.in(Compile) += baseDirectory.in(LocalRootProject).value / "directories" / "src" / "main" / "java"
}
lazy val addPathsSources = Seq(
addDirectoriesSources,
unmanagedSourceDirectories.in(Compile) ++= unmanagedSourceDirectories.in(Compile).in(paths).value
)
Submodule directories added at ed193b
@@ -85,18 +85,7 @@ public static File lockFile(File file) {
}
public static File defaultCacheDirectory() {
// cache this method result so that it's only ever computed once?
String path = System.getenv("COURSIER_CACHE");
if (path == null)
path = System.getProperty("coursier.cache");
if (path == null)
path = System.getProperty("user.home") + "/.coursier/cache/v1"; // shouldn't have put a "v1" component here...
return new File(path).getAbsoluteFile();
return new File(CoursierPaths.cacheDirectory(), "v1");
}
private static ConcurrentHashMap<File, Object> processStructureLocks = new ConcurrentHashMap<File, Object>();
@@ -0,0 +1,72 @@
package coursier;
import java.io.File;
import io.github.soc.directories.ProjectDirectories;
/**
* Computes Coursier's directories according to the standard
* defined by operating system Coursier is running on.
*
* @implNote If more paths e. g. for configuration or application data is required,
* use {@link #coursierDirectories} and do not roll your own logic.
*/
public final class CoursierPaths {
private CoursierPaths() {
throw new Error();
}
private static ProjectDirectories coursierDirectories;
private static volatile File cacheDirectory0 = null;
private static final Object lock = new Object();
// TODO After switching to nio, that logic can be unit tested with mock filesystems.
private static File computeCacheDirectory() {
String path = System.getenv("COURSIER_CACHE");
if (path == null)
path = System.getProperty("coursier.cache");
String xdgPath = coursierDirectories.projectCacheDir;
File xdgDir = new File(xdgPath);
if (path == null) {
if (xdgDir.isDirectory())
path = xdgPath;
}
if (path == null) {
File coursierDotFile = new File(System.getProperty("user.home") + "/.coursier");
if (coursierDotFile.isDirectory())
path = System.getProperty("user.home") + "/.coursier/cache/";
}
if (path == null) {
path = xdgPath;
xdgDir.mkdirs();
}
File coursierCacheDirectory = new File(path).getAbsoluteFile();
if (coursierCacheDirectory.getName().equals("v1"))
coursierCacheDirectory = coursierCacheDirectory.getParentFile();
return coursierCacheDirectory;
}
public static File cacheDirectory() {
if (cacheDirectory0 == null)
synchronized (lock) {
if (cacheDirectory0 == null) {
coursierDirectories = ProjectDirectories.fromProjectName("Coursier");
cacheDirectory0 = computeCacheDirectory();
}
}
return cacheDirectory0;
}
}

0 comments on commit 1871610

Please sign in to comment.