mirror of
https://github.com/scm-manager/scm-manager.git
synced 2026-03-03 19:00:52 +01:00
use os specific default directories
- /Users/<your_user_name>/Library/Application Support/SCM-Manager for OSX - %APPDATA%\SCM-Manager for Windows - ~/.scm for Unix
This commit is contained in:
141
scm-core/src/main/java/sonia/scm/BaseDirectory.java
Normal file
141
scm-core/src/main/java/sonia/scm/BaseDirectory.java
Normal file
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package sonia.scm;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import sonia.scm.util.SystemUtil;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* Determines the base directory for SCM-Manager.
|
||||
* This class should not be used directory, use {@link SCMContextProvider#getBaseDirectory()} instead.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
final class BaseDirectory {
|
||||
|
||||
/** Environment variable for the SCM-Manager base directory */
|
||||
static final String ENVIRONMENT_VARIABLE = "SCM_HOME";
|
||||
|
||||
/** Java system property for the SCM-Manager base directory */
|
||||
static final String SYSTEM_PROPERTY = "scm.home";
|
||||
|
||||
/** Classpath resource for the SCM-Manager base directory */
|
||||
@SuppressWarnings("java:S1075") // it is already configurable
|
||||
static final String CLASSPATH_RESOURCE = "/scm.properties";
|
||||
|
||||
/** Property name in resource file */
|
||||
static final String RESOURCE_PROPERTY = "scm.home";
|
||||
|
||||
private final Platform platform;
|
||||
private final String classPathResource;
|
||||
private final Map<String,String> environment;
|
||||
private final Properties systemProperties;
|
||||
|
||||
BaseDirectory(Platform platform, String classPathResource, Map<String, String> environment, Properties systemProperties) {
|
||||
this.platform = platform;
|
||||
this.classPathResource = classPathResource;
|
||||
this.environment = environment;
|
||||
this.systemProperties = systemProperties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the determined base directory.
|
||||
*
|
||||
* @return base directory
|
||||
*/
|
||||
static Path get() {
|
||||
return new BaseDirectory(
|
||||
SystemUtil.getPlatform(),
|
||||
CLASSPATH_RESOURCE,
|
||||
System.getenv(),
|
||||
System.getProperties()
|
||||
).find();
|
||||
}
|
||||
|
||||
Path find() {
|
||||
String directory = getFromResource();
|
||||
if (Strings.isNullOrEmpty(directory)) {
|
||||
directory = getFromSystemProperty();
|
||||
}
|
||||
if (Strings.isNullOrEmpty(directory)) {
|
||||
directory = getFromEnvironmentVariable();
|
||||
}
|
||||
if (Strings.isNullOrEmpty(directory)) {
|
||||
directory = getOsSpecificDefault();
|
||||
}
|
||||
|
||||
return Paths.get(directory);
|
||||
}
|
||||
|
||||
private String getFromResource() {
|
||||
try (InputStream input = BasicContextProvider.class.getResourceAsStream(classPathResource))
|
||||
{
|
||||
if (input != null)
|
||||
{
|
||||
Properties properties = new Properties();
|
||||
properties.load(input);
|
||||
return properties.getProperty(RESOURCE_PROPERTY);
|
||||
}
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
throw new ConfigurationException("could not load properties form resource " + CLASSPATH_RESOURCE, ex);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private String getFromEnvironmentVariable() {
|
||||
return environment.get(ENVIRONMENT_VARIABLE);
|
||||
}
|
||||
|
||||
private String getFromSystemProperty() {
|
||||
return systemProperties.getProperty(SYSTEM_PROPERTY);
|
||||
}
|
||||
|
||||
private String getOsSpecificDefault() {
|
||||
if (platform.isMac()) {
|
||||
return getOsxDefault();
|
||||
} else if (platform.isWindows()) {
|
||||
return getWindowsDefault();
|
||||
}
|
||||
return systemProperties.getProperty("user.home") + "/.scm";
|
||||
}
|
||||
|
||||
private String getOsxDefault() {
|
||||
return systemProperties.getProperty("user.home") + "/Library/Application Support/SCM-Manager";
|
||||
}
|
||||
|
||||
private String getWindowsDefault() {
|
||||
return environment.get("APPDATA") + "\\SCM-Manager";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -21,7 +21,7 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
package sonia.scm;
|
||||
|
||||
//~--- non-JDK imports --------------------------------------------------------
|
||||
@@ -30,21 +30,21 @@ import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.base.Strings;
|
||||
import sonia.scm.util.Util;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.Locale;
|
||||
import java.util.Properties;
|
||||
|
||||
//~--- JDK imports ------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* The default implementation of {@link SCMContextProvider}.
|
||||
*
|
||||
* @author Sebastian Sdorra
|
||||
*/
|
||||
@SuppressWarnings("java:S106") // we can not use logger until base directory is not determined
|
||||
public class BasicContextProvider implements SCMContextProvider
|
||||
{
|
||||
|
||||
@@ -174,58 +174,29 @@ public class BasicContextProvider implements SCMContextProvider
|
||||
*
|
||||
* @return base directory SCM-Manager
|
||||
*/
|
||||
private File findBaseDirectory()
|
||||
{
|
||||
String path = getPathFromResource();
|
||||
private File findBaseDirectory() {
|
||||
File directory = BaseDirectory.get().toFile();
|
||||
|
||||
if (Util.isEmpty(path))
|
||||
{
|
||||
path = System.getProperty(DIRECTORY_PROPERTY);
|
||||
|
||||
if (Util.isEmpty(path))
|
||||
{
|
||||
path = System.getenv(DIRECTORY_ENVIRONMENT);
|
||||
|
||||
if (Util.isEmpty(path))
|
||||
{
|
||||
path = System.getProperty("user.home").concat(File.separator).concat(
|
||||
DIRECTORY_DEFAULT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File directory = new File(path);
|
||||
|
||||
if (!directory.exists() &&!directory.mkdirs())
|
||||
{
|
||||
String msg = "could not create home directory at ".concat(
|
||||
directory.getAbsolutePath());
|
||||
|
||||
// do not use logger
|
||||
// http://www.slf4j.org/codes.html#substituteLogger
|
||||
System.err.println("===================================================");
|
||||
System.err.append("Error: ").println(msg);
|
||||
System.err.println("===================================================");
|
||||
|
||||
throw new IllegalStateException(msg);
|
||||
}
|
||||
else if (directory.exists() && !directory.canWrite())
|
||||
{
|
||||
String msg = "could not modify home directory at ".concat(
|
||||
directory.getAbsolutePath());
|
||||
|
||||
// do not use logger
|
||||
// http://www.slf4j.org/codes.html#substituteLogger
|
||||
System.err.println("===================================================");
|
||||
System.err.append("Error: ").println(msg);
|
||||
System.err.println("===================================================");
|
||||
|
||||
throw new IllegalStateException(msg);
|
||||
if (!directory.exists() &&!directory.mkdirs()) {
|
||||
error("could not create home directory at " + directory.getAbsolutePath());
|
||||
} else if (directory.exists() && !directory.canWrite()) {
|
||||
error("could not modify home directory at " + directory.getAbsolutePath());
|
||||
}
|
||||
|
||||
return directory;
|
||||
}
|
||||
|
||||
|
||||
private void error(String msg) {
|
||||
// do not use logger
|
||||
// http://www.slf4j.org/codes.html#substituteLogger
|
||||
System.err.println("===================================================");
|
||||
System.err.append("Error: ").println(msg);
|
||||
System.err.println("===================================================");
|
||||
|
||||
throw new IllegalStateException(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the current stage.
|
||||
*
|
||||
@@ -256,11 +227,11 @@ public class BasicContextProvider implements SCMContextProvider
|
||||
}
|
||||
|
||||
private String determineVersion() {
|
||||
String version = System.getProperty(VERSION_PROPERTY);
|
||||
if (Strings.isNullOrEmpty(version)) {
|
||||
version = loadVersion();
|
||||
String v = System.getProperty(VERSION_PROPERTY);
|
||||
if (Strings.isNullOrEmpty(v)) {
|
||||
v = loadVersion();
|
||||
}
|
||||
return version;
|
||||
return v;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -304,59 +275,6 @@ public class BasicContextProvider implements SCMContextProvider
|
||||
return properties.getProperty(MAVEN_PROPERTY_VERSION, VERSION_DEFAULT);
|
||||
}
|
||||
|
||||
//~--- get methods ----------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Load path from classpath resource.
|
||||
*
|
||||
*
|
||||
* @return path from classpath resource or null
|
||||
*/
|
||||
private String getPathFromResource()
|
||||
{
|
||||
String path = null;
|
||||
InputStream input = null;
|
||||
|
||||
try
|
||||
{
|
||||
input =
|
||||
BasicContextProvider.class.getResourceAsStream(DIRECTORY_RESOURCE);
|
||||
|
||||
if (input != null)
|
||||
{
|
||||
Properties properties = new Properties();
|
||||
|
||||
properties.load(input);
|
||||
path = properties.getProperty(DIRECTORY_PROPERTY);
|
||||
}
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
throw new ConfigurationException(
|
||||
"could not load properties form resource ".concat(DIRECTORY_RESOURCE),
|
||||
ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
||||
// do not use logger or IOUtil,
|
||||
// http://www.slf4j.org/codes.html#substituteLogger
|
||||
if (input != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
input.close();
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
ex.printStackTrace(System.err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
//~--- fields ---------------------------------------------------------------
|
||||
|
||||
/** The base directory of the SCM-Manager */
|
||||
|
||||
127
scm-core/src/test/java/sonia/scm/BaseDirectoryTest.java
Normal file
127
scm-core/src/test/java/sonia/scm/BaseDirectoryTest.java
Normal file
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package sonia.scm;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import lombok.Builder;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Nested;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
class BaseDirectoryTest {
|
||||
|
||||
@Test
|
||||
void shouldGetFromClassPathResource() {
|
||||
BaseDirectory directory = builder().withClassPathResource("/sonia/scm/basedirectory.properties").create();
|
||||
assertThat(directory.find().toString()).isEqualTo("/tmp/scm_home");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldGetFromSystemProperty() {
|
||||
BaseDirectory directory = builder().withSystemProperty(BaseDirectory.SYSTEM_PROPERTY, "/tmp/scm_home").create();
|
||||
assertThat(directory.find().toString()).isEqualTo("/tmp/scm_home");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldGetFromEnvironmentVariable() {
|
||||
BaseDirectory directory = builder().withEnvironment(BaseDirectory.ENVIRONMENT_VARIABLE, "/tmp/scm_home").create();
|
||||
assertThat(directory.find().toString()).isEqualTo("/tmp/scm_home");
|
||||
}
|
||||
|
||||
@Nested
|
||||
class OsSpecificDefaults {
|
||||
|
||||
@Test
|
||||
void linux() {
|
||||
BaseDirectory directory = builder().withSystemProperty("user.home", "/tmp").create();
|
||||
assertThat(directory.find().toString()).isEqualTo("/tmp/.scm");
|
||||
}
|
||||
|
||||
@Test
|
||||
void osx() {
|
||||
BaseDirectory directory = builder().withOsx().withSystemProperty("user.home", "/tmp").create();
|
||||
assertThat(directory.find().toString()).isEqualTo("/tmp/Library/Application Support/SCM-Manager");
|
||||
}
|
||||
|
||||
@Test
|
||||
void windows() {
|
||||
BaseDirectory directory = builder().withWindows().withEnvironment("APPDATA", "/tmp").create();
|
||||
assertThat(directory.find().toString()).isEqualTo("/tmp\\SCM-Manager");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private BaseDirectoryBuilder builder() {
|
||||
return new BaseDirectoryBuilder();
|
||||
}
|
||||
|
||||
static class BaseDirectoryBuilder {
|
||||
|
||||
private Platform platform = platform("Linux");
|
||||
private String classPathResource = "/scm.properties";
|
||||
private Map<String, String> environment = ImmutableMap.of();
|
||||
private Properties systemProperties = new Properties();
|
||||
|
||||
public BaseDirectoryBuilder withOsx() {
|
||||
this.platform = platform("Mac OS X");
|
||||
return this;
|
||||
}
|
||||
|
||||
public BaseDirectoryBuilder withWindows() {
|
||||
this.platform = platform("Windows");
|
||||
return this;
|
||||
}
|
||||
|
||||
private Platform platform(String osName) {
|
||||
return new Platform(osName, "64", "x86_64");
|
||||
}
|
||||
|
||||
public BaseDirectoryBuilder withClassPathResource(String classPathResource) {
|
||||
this.classPathResource = classPathResource;
|
||||
return this;
|
||||
}
|
||||
|
||||
public BaseDirectoryBuilder withEnvironment(String key, String value) {
|
||||
this.environment = ImmutableMap.of(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BaseDirectoryBuilder withSystemProperty(String key, String value) {
|
||||
systemProperties.put(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public BaseDirectory create() {
|
||||
return new BaseDirectory(platform, classPathResource, environment, systemProperties);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -21,7 +21,7 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
package sonia.scm;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
#
|
||||
# MIT License
|
||||
#
|
||||
# Copyright (c) 2020-present Cloudogu GmbH and Contributors
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in all
|
||||
# copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
# SOFTWARE.
|
||||
#
|
||||
|
||||
scm.home = /tmp/scm_home
|
||||
Reference in New Issue
Block a user