From bc469ff20da60709fb93427fd88e37013f2278ba Mon Sep 17 00:00:00 2001 From: carson Date: Mon, 7 Feb 2022 20:17:26 -0700 Subject: [PATCH] Offer a `recurseParent()` config option This change allows you to configure a recursive search through parent directories for a .env file. This is useful in a multi-module project when you want to share a common .env file across multiple modules. --- .../github/cdimascio/dotenv/DotenvBuilder.java | 13 ++++++++++++- .../cdimascio/dotenv/internal/DotenvReader.java | 17 ++++++++++++++++- src/test/java/tests/BasicTests.java | 12 ++++++++++++ src/test/resources/parent_demo/keep.txt | 0 4 files changed, 40 insertions(+), 2 deletions(-) create mode 100644 src/test/resources/parent_demo/keep.txt diff --git a/src/main/java/io/github/cdimascio/dotenv/DotenvBuilder.java b/src/main/java/io/github/cdimascio/dotenv/DotenvBuilder.java index 6c44776..8cb83cc 100644 --- a/src/main/java/io/github/cdimascio/dotenv/DotenvBuilder.java +++ b/src/main/java/io/github/cdimascio/dotenv/DotenvBuilder.java @@ -17,6 +17,7 @@ public class DotenvBuilder { private boolean systemProperties = false; private boolean throwIfMissing = true; private boolean throwIfMalformed = true; + private boolean recurse = false; /** * Sets the directory containing the .env file. @@ -55,6 +56,16 @@ public DotenvBuilder ignoreIfMalformed() { return this; } + + /** + * Recursively search parent directories for a .env file + * @return this {@link DotenvBuilder} + */ + public DotenvBuilder recurseParents() { + recurse = true; + return this; + } + /** * Sets each environment variable as system properties. * @return this {@link DotenvBuilder} @@ -71,7 +82,7 @@ public DotenvBuilder systemProperties() { */ public Dotenv load() throws DotenvException { DotenvParser reader = new DotenvParser( - new DotenvReader(directoryPath, filename), + new DotenvReader(directoryPath, filename, recurse), throwIfMissing, throwIfMalformed); List env = reader.parse(); diff --git a/src/main/java/io/github/cdimascio/dotenv/internal/DotenvReader.java b/src/main/java/io/github/cdimascio/dotenv/internal/DotenvReader.java index 37c7802..ecb95d7 100644 --- a/src/main/java/io/github/cdimascio/dotenv/internal/DotenvReader.java +++ b/src/main/java/io/github/cdimascio/dotenv/internal/DotenvReader.java @@ -17,15 +17,18 @@ public class DotenvReader { private final String directory; private final String filename; + private final boolean recurse; /** * Creates a dotenv reader * @param directory the directory containing the .env file * @param filename the file name of the .env file e.g. .env + * @param recurse */ - public DotenvReader(String directory, String filename) { + public DotenvReader(String directory, String filename, boolean recurse) { this.directory = directory; this.filename = filename; + this.recurse = recurse; } /** @@ -50,6 +53,18 @@ public List read() throws DotenvException, IOException { return Files .lines(path) .collect(Collectors.toList()); + } else if (recurse) { + Path parent = path.getParent().getParent(); // get the parent of the parent of the current .env file + while (parent != null) { + Path fileInParent = parent.resolve(filename); // resolve a .env file in it + if (Files.exists(fileInParent)) { + return Files + .lines(fileInParent) + .collect(Collectors.toList()); + } else { + parent = parent.getParent(); + } + } } try { diff --git a/src/test/java/tests/BasicTests.java b/src/test/java/tests/BasicTests.java index 48a8625..4c7d59d 100644 --- a/src/test/java/tests/BasicTests.java +++ b/src/test/java/tests/BasicTests.java @@ -141,4 +141,16 @@ private void assertHostEnvVar(Dotenv env) { assertEquals(expectedHome, actualHome); } } + + @Test + public void parentDirectory() { + var dotenv = Dotenv.configure() + .directory("./src/test/resources/parent_demo") + .recurseParents() + .ignoreIfMalformed() + .load(); + assertEquals("my test ev 1", dotenv.get("MY_TEST_EV1")); + + assertHostEnvVar(dotenv); + } } diff --git a/src/test/resources/parent_demo/keep.txt b/src/test/resources/parent_demo/keep.txt new file mode 100644 index 0000000..e69de29