This is an automated email from the ASF dual-hosted git repository. pgj pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/couchdb.git
commit a8b4bb2f7659ce09a51ff1346070e75838ac064c Author: Gabor Pali <[email protected]> AuthorDate: Thu Nov 30 02:36:56 2023 +0100 Make the Clouseau development flow more flexible This change features a set of extensions to the integration of Clouseau in the developer setup, added in 2d8a33b9: - Introduce the `--clouseau-dir` option for the `./dev/run` script to allow for ad-hoc integration of Clouseau with CouchDB, even without being configured previously. This facilities experimentation with various alternatives and lets the user switch between them with ease. - The directory specified by `--clouseau-dir` could either hold an unpacked set of JAR files or `git` clone of the Clouseau source code. The script can automagically determine which version is being used and invoke Apache Maven [1] to compile the sources and launch the nodes with the proper classpath. In this latter case, check for JDK 1.7 because that is the edition that could be used for compiling the sources currently. - Modify the `./configure` script to support deploying locally a specific branch of Clouseau's `git` clone instead of a tagged release. - Adjust the `Makefile`s to set `--clouseau-dir` by the `CLOUSEAU_DIR` variable. [1] https://maven.apache.org/ --- Makefile | 15 +++--- Makefile.win | 15 +++--- README-DEV.rst | 25 ++++++++++ configure | 125 ++++++++++++++++++++++++++++++++++--------------- configure.ps1 | 86 +++++++++++++++++----------------- dev/run | 145 +++++++++++++++++++++++++++++++++++++++++++++++---------- 6 files changed, 295 insertions(+), 116 deletions(-) diff --git a/Makefile b/Makefile index 35e0252d8..22c4217ff 100644 --- a/Makefile +++ b/Makefile @@ -262,13 +262,20 @@ elixir: elixir-init devclean --erlang-config rel/files/eunit.config \ --no-eval 'mix test --trace --include test/elixir/test/config/suite.elixir --exclude test/elixir/test/config/skip.elixir $(EXUNIT_OPTS)' +ifneq ($(CLOUSEAU_DIR),) +_WITH_CLOUSEAU="--with-clouseau --clouseau-dir=$(CLOUSEAU_DIR)" +else ifeq ($(with_clouseau), 1) +_WITH_CLOUSEAU="--with-clouseau" +endif + .PHONY: elixir-search # target: elixir-search - Run search tests, requires a configured Clouseau instance elixir-search: export MIX_ENV=integration elixir-search: elixir-init devclean -ifeq ($(with_clouseau), 1) +ifneq ($(_WITH_CLOUSEAU), ) @dev/run -n 1 -q -a adm:pass \ - --with-clouseau \ + "$(_WITH_CLOUSEAU)" \ + "$(TEST_OPTS)" \ --locald-config test/config/test-config.ini \ --no-eval 'mix test --trace --include test/elixir/test/config/search.elixir' else @@ -318,10 +325,6 @@ list-eunit-suites: build-test: @test/build/test-configure.sh -ifeq ($(with_clouseau), 1) -_WITH_CLOUSEAU="--with-clouseau" -endif - .PHONY: mango-test # target: mango-test - Run Mango tests mango-test: devclean all diff --git a/Makefile.win b/Makefile.win index 0354fe29d..4d7a2e9d8 100644 --- a/Makefile.win +++ b/Makefile.win @@ -241,13 +241,20 @@ elixir: elixir-init devclean --erlang-config rel/files/eunit.config \ --no-eval 'mix test --trace --include test\elixir\test\config\suite.elixir --exclude test\elixir\test\config\skip.elixir $(EXUNIT_OPTS)' +ifneq ($(CLOUSEAU_DIR),) +_WITH_CLOUSEAU="--with-clouseau --clouseau-dir=$(CLOUSEAU_DIR)" +else ifeq ($(with_clouseau), 1) +_WITH_CLOUSEAU="--with-clouseau" +endif + .PHONY: elixir-search # target: elixir-search - Run search tests, requires a configured Clouseau instance elixir-search: export MIX_ENV=integration elixir-search: elixir-init devclean -ifeq ($(with_clouseau), 1) +ifneq ($(_WITH_CLOUSEAU), ) @dev\run -n 1 -q -a adm:pass \ - --with-clouseau \ + "$(_WITH_CLOUSEAU)" \ + "$(TEST_OPTS)" \ --locald-config test/config/test-config.ini \ --no-eval 'mix test --trace --include test/elixir/test/config/search.elixir' else @@ -286,10 +293,6 @@ list-eunit-apps: list-eunit-suites: @powershell -Command 'Get-ChildItem -Path src -Recurse -Filter "*_tests?.erl" | ForEach-Object { "{0}" -f $$_.BaseName } | Sort' -ifeq ($(with_clouseau), 1) -_WITH_CLOUSEAU="--with-clouseau" -endif - .PHONY: mango-test # target: mango-test - Run Mango tests mango-test: export COUCHDB_TEST_ADMIN_PARTY_OVERRIDE=1 diff --git a/README-DEV.rst b/README-DEV.rst index 3ab5c6bf6..0988780aa 100644 --- a/README-DEV.rst +++ b/README-DEV.rst @@ -317,6 +317,31 @@ used to configure Clouseau to work with that:: dev/run --with-clouseau --erlang-cookie=brumbrum +It is possible to override Clouseau's location per invocation of +``./dev/run`` in case some other version needs to be exercised for the +moment. This can be done with the help of the ``--clouseau-dir`` +flag. The specified location could be either an unpacked bundle of +JAR files or a git clone of the Clouseau source code repository:: + + dev/run --with-clouseau --clouseau-dir $HOME/git/clouseau.wip + +Through the ``CLOUSEAU_DIR`` variable the same could be forwarded to the +respective test targets, e.g. ``mango-test``:: + + make mango-test CLOUSEAU_DIR=$HOME/git/clouseau.wip + +This can even be done if there was no local Clouseau deployment +configured previously. Mind that this will require building Clouseau +from source, which causes the nodes start up somewhat slower. It also +requires JDK 1.7 and Apache Maven 3.8 to be present, that is why it is +important the set the ``CLOUSEAU_JAVA_HOME`` and the +``CLOUSEAU_M2_HOME`` environment variables accordingly, for instance:: + + asdf install java zulu-7.56.0.11 + asdf plugin add maven + asdf install maven 3.8.8 + export CLOUSEAU_JAVA_HOME=$(asdf where java zulu-7.56.0.11) + export CLOUSEAU_M2_HOME=$(asdf where maven 3.8.8) Static Code Analysis ~~~~~~~~~~~~~~~~~~~~ diff --git a/configure b/configure index a6032da68..9a99df0e5 100755 --- a/configure +++ b/configure @@ -39,6 +39,8 @@ run_erlang() { COUCHDB_USER="$(whoami 2>/dev/null || echo couchdb)" SM_VSN=${SM_VSN:-"91"} +CLOUSEAU_MTH=${CLOUSEAU_MTH:-"dist"} +CLOUSEAU_URI=${CLOUSEAU_URI:-"https://github.com/cloudant-labs/clouseau/releases/download/%s/clouseau-%s-dist.zip"} CLOUSEAU_VSN=${CLOUSEAU_VSN:-"2.22.0"} CLOUSEAU_DIR="$(pwd)"/clouseau ARCH="$(uname -m)" @@ -66,7 +68,9 @@ Options: --erlang-md5 use erlang for md5 hash operations --dev alias for --disable-docs --disable-fauxton --spidermonkey-version VSN specify the version of SpiderMonkey to use (defaults to $SM_VSN) - --clouseau-version VSN specify the version of Clouseau to use (defaults to $CLOUSEAU_VSN) + --clouseau-method MTH specify the method for Clouseau to deploy: git or dist (defaults to $CLOUSEAU_MTH) + --clouseau-uri URI specify the location for retrieving Clouseau (defaults $(printf "$CLOUSEAU_URI" "$CLOUSEAU_VSN" "$CLOUSEAU_VSN")) + --clouseau-version VSN specify the version (tag/branch for git) of Clouseau to use (defaults to $CLOUSEAU_VSN) --skip-deps do not update erlang dependencies --rebar=PATH use rebar by specified path (version >=2.6.0 && <3.0 required) --rebar3=PATH use rebar3 by specified path @@ -220,7 +224,7 @@ parse_opts() { --clouseau-version) if [ -n "$2" ]; then - eval CLOUSEAU_SVN=$2 + eval CLOUSEAU_VSN=$2 shift 2 continue else @@ -236,6 +240,42 @@ parse_opts() { exit 1 ;; + --clouseau-method) + if [ -n "$2" ]; then + eval CLOUSEAU_MTH=$2 + shift 2 + continue + else + printf 'ERROR: "--clouseau-method" requires a non-empty argument.\n' >&2 + exit 1 + fi + ;; + --clouseau-method=?*) + eval CLOUSEAU_MTH=${1#*=} + ;; + --clouseau-method=) + printf 'ERROR: "--clouseau-method" requires a non-empty argument.\n' >&2 + exit 1 + ;; + + --clouseau-uri) + if [ -n "$2" ]; then + eval CLOUSEAU_URI=$2 + shift 2 + continue + else + printf 'ERROR: "--clouseau-uri" requires a non-empty argument.\n' >&2 + exit 1 + fi + ;; + --clouseau-uri=?*) + eval CLOUSEAU_URI=${1#*=} + ;; + --clouseau-uri=) + printf 'ERROR: "--clouseau-uri" requires a non-empty argument.\n' >&2 + exit 1 + ;; + --) # End of options shift break @@ -380,43 +420,56 @@ install_local_erlfmt() { fi } -install_local_clouseau() { - _DIST_URL=https://github.com/cloudant-labs/clouseau/releases/download/"$CLOUSEAU_VSN"/clouseau-"$CLOUSEAU_VSN"-dist.zip - _MAVEN_BASE_URI=https://repo1.maven.org/maven2 - - _SLF4J_SIMPLE_VSN=${SLF4J_SIMPLE_VERSION:-1.7.36} - _SLF4J_SIMPLE_JAR=slf4j-simple-"$_SLF4J_SIMPLE_VSN".jar - _SLF4J_SIMPLE_URL="$_MAVEN_BASE_URI"/org/slf4j/slf4j-simple/"$_SLF4J_SIMPLE_VSN"/"$_SLF4J_SIMPLE_JAR" - - rm -rf "$CLOUSEAU_DIR" - mkdir -p "$CLOUSEAU_DIR" - - if ! curl -sSL --max-redirs 1 -o clouseau.zip "$_DIST_URL"; then - printf "ERROR: %s could not be downloaded.\n" "$_DIST_URL" >&2 - exit 1 - fi - - if ! unzip -q -j clouseau.zip -d "$CLOUSEAU_DIR"; then - printf "ERROR: Clouseau distribution package (clouseau.zip) could not be extracted.\n" >&2 - exit 1 - fi - - rm clouseau.zip +check_local_clouseau_dir() { + _dir="$1" - if ! curl -sSL --max-redirs 1 -o "$CLOUSEAU_DIR"/"$_SLF4J_SIMPLE_JAR" "$_SLF4J_SIMPLE_URL"; then - printf "ERROR: %s could not be downloaded.\n" "$_SLF4J_SIMPLE_URL" >&2 + if [ -e "$_dir" ]; then + printf "ERROR: \"%s\" already exists. Please remove or move it away first.\n" "$_dir" >&2 exit 1 fi +} - cat <<EOF > "$CLOUSEAU_DIR"/clouseau.ini -[clouseau] -EOF - cat <<EOF > "$CLOUSEAU_DIR"/log4j.properties -log4j.rootLogger=debug, CONSOLE -log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender -log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout -log4j.appender.CONSOLE.layout.ConversionPattern=%d{ISO8601} %c [%p] %m%n -EOF +install_local_clouseau() { + case "$CLOUSEAU_MTH" in + dist) + _DIST_URL=$(printf "$CLOUSEAU_URI" "$CLOUSEAU_VSN" "$CLOUSEAU_VSN") + _MAVEN_BASE_URI=https://repo1.maven.org/maven2 + + _SLF4J_SIMPLE_VSN=${SLF4J_SIMPLE_VERSION:-1.7.36} + _SLF4J_SIMPLE_JAR=slf4j-simple-"$_SLF4J_SIMPLE_VSN".jar + _SLF4J_SIMPLE_URL="$_MAVEN_BASE_URI"/org/slf4j/slf4j-simple/"$_SLF4J_SIMPLE_VSN"/"$_SLF4J_SIMPLE_JAR" + + check_local_clouseau_dir "$CLOUSEAU_DIR" + mkdir -p "$CLOUSEAU_DIR" + + echo "Fetching Clouseau from $_DIST_URL..." + if ! curl -sSL --max-redirs 1 -o clouseau.zip "$_DIST_URL"; then + printf "ERROR: %s could not be downloaded.\n" "$_DIST_URL" >&2 + exit 1 + fi + + if ! unzip -q -j clouseau.zip -d "$CLOUSEAU_DIR"; then + printf "ERROR: Clouseau distribution package (clouseau.zip) could not be extracted.\n" >&2 + exit 1 + fi + + rm clouseau.zip + + if ! curl -sSL --max-redirs 1 -o "$CLOUSEAU_DIR"/"$_SLF4J_SIMPLE_JAR" "$_SLF4J_SIMPLE_URL"; then + printf "ERROR: %s could not be downloaded.\n" "$_SLF4J_SIMPLE_URL" >&2 + exit 1 + fi + ;; + + git) + echo "Cloning Clouseau from $CLOUSEAU_URI ($CLOUSEAU_VSN)..." + check_local_clouseau_dir "$CLOUSEAU_DIR" + git clone --depth 1 --branch "$CLOUSEAU_VSN" "$CLOUSEAU_URI" "$CLOUSEAU_DIR" + ;; + + *) printf "ERROR: Invalid deployment method for Clouseau. Please use either \`dist\` or \`git\` verbatim.\n" >&2 + exit 1 + esac } if [ -z "${REBAR}" ]; then @@ -436,8 +489,6 @@ fi if [ $WITH_CLOUSEAU -ne 0 ]; then install_local_clouseau -else - rm -rf "$CLOUSEAU_DIR" fi # only update dependencies, when we are not in a release tarball diff --git a/configure.ps1 b/configure.ps1 index 7d13b5505..6c4a61e6f 100644 --- a/configure.ps1 +++ b/configure.ps1 @@ -13,6 +13,8 @@ -CouchDBUser USER set the username to run as (defaults to current user) -SpiderMonkeyVersion VSN select the version of SpiderMonkey to use (default 91) -ClouseauVersion VSN select the version of Clouseau to use (default 2.22.0) + -ClouseauMethod MTH method for Clouseau to deploy: git or dist (default dist) + -ClouseauUri URI location for retrieving Clouseau (default https://github.com/cloudant-labs/clouseau/releases/download/2.22.0/clouseau-2.22.0-dist.zip) Installation directories: -Prefix PREFIX install architecture-independent files in PREFIX @@ -57,8 +59,12 @@ Param( [ValidateNotNullOrEmpty()] [string]$SpiderMonkeyVersion = "91", # select the version of SpiderMonkey to use (default 91) [ValidateNotNullOrEmpty()] + [string]$ClouseauMethod = "dist", # method for Clouseau to deploy: git or dist (default dist) + [ValidateNotNullOrEmpty()] [string]$ClouseauVersion = "2.22.0", # select the version of Clouseau to use (default 2.22.0) [ValidateNotNullOrEmpty()] + [string]$ClouseauUri = "https://github.com/cloudant-labs/clouseau/releases/download/{0}/clouseau-{0}-dist.zip", # location for retrieving Clouseau (default https://github.com/cloudant-labs/clouseau/releases/download/2.22.0/clouseau-2.22.0-dist.zip) + [ValidateNotNullOrEmpty()] [string]$Prefix = "C:\Program Files\Apache\CouchDB", # install architecture-independent file location (default C:\Program Files\Apache\CouchDB) [ValidateNotNullOrEmpty()] [string]$ExecPrefix = $Prefix, # install architecture-dependent file location (default C:\Program Files\Apache\CouchDB) @@ -278,56 +284,52 @@ $ClouseauDir = "$rootdir\clouseau" if ($EnableClouseau) { - Write-Verbose "===> downloading Clouseau distribution..." if (Test-Path $ClouseauDir) { - Remove-Item -Recurse -Force $ClouseauDir - } - New-Item -Path $ClouseauDir -ItemType Directory | Out-File Null - - $Slf4jVersion = "1.7.36" - $ClouseauDistUrl = "https://github.com/cloudant-labs/clouseau/releases/download/$ClouseauVersion/clouseau-$ClouseauVersion-dist.zip" - $Slf4jSimpleJar = "slf4j-simple-$Slf4jVersion.jar" - $Slf4jSimpleUrl = "https://repo1.maven.org/maven2/org/slf4j/slf4j-simple/$Slf4jVersion/$Slf4jSimpleJar" - - Set-Variable ProgressPreference SilentlyContinue - Invoke-WebRequest -MaximumRedirection 1 -OutFile clouseau.zip $ClouseauDistUrl - If ($LASTEXITCODE -ne 0) { - Write-Output "ERROR: $ClouseauDistUrl could not be downloaded." + Write-Output "ERROR: ""$ClouseauDir"" already exists. Please remove or move it away first." exit 1 } - Expand-Archive clouseau.zip -DestinationPath $ClouseauDir -Force - If ($LASTEXITCODE -ne 0) { - Write-Output "ERROR: Clouseau distribution package (clouseau.zip) could not be extracted." - exit 1 + if ($ClouseauMethod -eq "dist") { + Write-Verbose "===> fetching Clouseau from $ClouseauDistUrl..." + + New-Item -Path $ClouseauDir -ItemType Directory | Out-File Null + + $Slf4jVersion = "1.7.36" + $ClouseauDistUrl = $ClouseauUri -f $ClouseauVersion + $Slf4jSimpleJar = "slf4j-simple-$Slf4jVersion.jar" + $Slf4jSimpleUrl = "https://repo1.maven.org/maven2/org/slf4j/slf4j-simple/$Slf4jVersion/$Slf4jSimpleJar" + + Set-Variable ProgressPreference SilentlyContinue + Invoke-WebRequest -MaximumRedirection 1 -OutFile clouseau.zip $ClouseauDistUrl + If ($LASTEXITCODE -ne 0) { + Write-Output "ERROR: $ClouseauDistUrl could not be downloaded." + exit 1 + } + + Expand-Archive clouseau.zip -DestinationPath $ClouseauDir -Force + If ($LASTEXITCODE -ne 0) { + Write-Output "ERROR: Clouseau distribution package (clouseau.zip) could not be extracted." + exit 1 + } + mv "$ClouseauDir\*\*.jar" "$ClouseauDir" + rm "$ClouseauDir\clouseau-$ClouseauVersion" + rm clouseau.zip + + Invoke-WebRequest -MaximumRedirection 1 -OutFile "$ClouseauDir\$Slf4jSimpleJar" $Slf4jSimpleUrl + If ($LASTEXITCODE -ne 0) { + Write-Output "ERROR: $Slf4jSimpleJarUrl could not be downloaded." + exit 1 + } } - mv "$ClouseauDir\*\*.jar" "$ClouseauDir" - rm "$ClouseauDir\clouseau-$ClouseauVersion" - rm clouseau.zip + elseif ($ClouseauMethod -eq "git") { + Write-Verbose "===> cloning Clouseau from $ClouseauDistUrl ($ClouseauVersion)..." - Invoke-WebRequest -MaximumRedirection 1 -OutFile "$ClouseauDir\$Slf4jSimpleJar" $Slf4jSimpleUrl - If ($LASTEXITCODE -ne 0) { - Write-Output "ERROR: $Slf4jSimpleJarUrl could not be downloaded." - exit 1 + git clone --depth 1 --branch $ClouseauVersion $ClouseauUri $ClouseauDir } - - $ClouseauIni = @" -[clouseau] -"@ - $ClouseauIni | Out-File "$ClouseauDir\clouseau.ini" -encoding ascii - - $Log4JProperties = @" -log4j.rootLogger=debug, CONSOLE -log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender -log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout -log4j.appender.CONSOLE.layout.ConversionPattern=%d{ISO8601} %c [%p] %m%n -"@ - $Log4JProperties | Out-File "$ClouseauDir\log4j.properties" -} -else { - if (Test-Path $ClouseauDir) { - Remove-Item -Recurse -Force $ClouseauDir + else { + Write-Output "ERROR: Invalid deployment method for Clouseau. Please use either `dist` or `git`." + exit 1 } } diff --git a/dev/run b/dev/run index 62dc528d6..dbdfecf03 100755 --- a/dev/run +++ b/dev/run @@ -26,6 +26,7 @@ import os import platform import posixpath import re +import shutil import signal import socket import subprocess as sp @@ -253,6 +254,12 @@ def get_args_parser(): default=None, help="Erlang cookie string", ) + parser.add_option( + "--clouseau-dir", + dest="clouseau_dir", + default=None, + help="Use a specific directory for finding Clouseau files", + ), parser.add_option( "-t", "--enable-tls", @@ -270,6 +277,9 @@ def get_args_parser(): return parser +CLOUSEAU_DIR = "clouseau" + + def setup_context(opts, args): fpath = os.path.abspath(__file__) return { @@ -297,6 +307,7 @@ def setup_context(opts, args): "locald_configs": opts.locald_configs, "with_nouveau": opts.with_nouveau, "with_clouseau": opts.with_clouseau, + "clouseau_dir": opts.clouseau_dir or CLOUSEAU_DIR, "erlang_cookie": opts.erlang_cookie, "enable_tls": opts.enable_tls, "no_tls": opts.no_tls, @@ -525,7 +536,6 @@ def boot_nouveau(ctx): ) -CLOUSEAU_DIR = "clouseau" JAVA_VERSION_RE = re.compile(r'"(\d+\.\d+).*"') @@ -547,6 +557,27 @@ class StartupError(Exception): super().__init__(self.message) +def generate_default_clouseau_ini(path): + print("(generate default clouseau.ini)") + with open(path, "w") as handle: + handle.write( + """[clouseau] +""" + ) + + +def generate_default_log4j_properties(path): + print("(generate default log4j.properties)") + with open(path, "w") as handle: + handle.write( + """log4j.rootLogger=debug, CONSOLE +log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender +log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout +log4j.appender.CONSOLE.layout.ConversionPattern=%d{ISO8601} %c [%p] %m%n +""" + ) + + @log("Start Clouseau node clouseau{idx}") def boot_clouseau(ctx, idx): configure_cmd = ( @@ -554,47 +585,115 @@ def boot_clouseau(ctx, idx): if platform.system() == "Windows" else "./configure --enable-clouseau" ) + clouseau_dir = ctx["clouseau_dir"] - if not os.path.isdir(CLOUSEAU_DIR): + if not os.path.isdir(clouseau_dir): raise StartupError( - "Clouseau deployment cannot be found, please run `{}`".format(configure_cmd) + ( + "Clouseau files cannot be found. " + "Please run `{}` or make `--clouseau-dir` point to a valid directory" + ).format(configure_cmd) ) - clouseau_jdk_home = os.environ.get("CLOUSEAU_JAVA_HOME") or os.environ.get( + clouseau_java_home = os.environ.get("CLOUSEAU_JAVA_HOME") or os.environ.get( "JAVA_HOME" ) - java = clouseau_jdk_home + "/bin/java" if clouseau_jdk_home else "java" + java = ( + clouseau_java_home + "/bin/java" if clouseau_java_home else shutil.which("java") + ) java_version = get_java_version(java) + pom_file = os.path.join(clouseau_dir, "pom.xml") + method = "src" if os.path.isfile(pom_file) else "dist" + if not java_version: print( "Warning: Java version could not be determined, Clouseau may not be able to run" ) else: - if java_version < 1.7 or java_version > 1.8: + if method == "src" and (java_version < 1.7 or 1.7 < java_version): + raise StartupError( + "Java is not suitable to run Clouseau. Please use JDK 1.7 and configure its (root) path in `CLOUSEAU_JAVA_HOME`" + ) + elif java_version < 1.7 or 1.8 < java_version: raise StartupError( "Java is not suitable to run Clouseau. Please use JRE 1.7 or 1.8 and configure its (root) path in `CLOUSEAU_JAVA_HOME`" ) - clouseau_jars = [ - "{}/{}".format(CLOUSEAU_DIR, fname) - for fname in os.listdir(CLOUSEAU_DIR) - if fname.endswith(".jar") - ] + logfname = os.path.join(ctx["devdir"], "logs", "clouseau{}.log".format(idx)) + log = open(logfname, "w") + separator = ";" if platform.system() == "Windows" else ":" - if not clouseau_jars: - raise StartupError("Clouseau has no JAR files") + if method == "src": + target_dir = os.path.join(clouseau_dir, "target") + cp_file = os.path.join(ctx["devdir"], "lib", "clouseau.classpath") - clouseau_ini = "{}/clouseau.ini".format(CLOUSEAU_DIR) - if not os.path.isfile(clouseau_ini): - raise StartupError("Clouseau has no ini file") + # attempt building the sources only once + if idx == 1: + env = os.environ.copy() + if clouseau_java_home: + env["JAVA_HOME"] = clouseau_java_home - log4j_properties = "{}/log4j.properties".format(CLOUSEAU_DIR) - if not os.path.isfile(log4j_properties): - raise StartupError("Clouseau has no Log4J configuration") + clouseau_mvn_home = os.environ.get("CLOUSEAU_M2_HOME") or os.environ.get( + "M2_HOME" + ) + mvn = ( + clouseau_mvn_home + "/bin/mvn" + if clouseau_mvn_home + else shutil.which("mvn") + ) + + if not mvn: + raise StartupError( + "Maven could not be found. Please install Maven 3.8 and configure its (root) path in `CLOUSEAU_M2_HOME`" + ) + + try: + sp.check_call( + [ + mvn, + "-B", + "compile", + "dependency:build-classpath", + "-Dmdep.outputFile={}".format(cp_file), + ], + cwd=clouseau_dir, + env=env, + stdin=sp.PIPE, + stdout=log, + stderr=log, + ) + except Exception as exc: + log.write(str(exc)) + raise StartupError("Could not build Clouseau from sources.") + + with open(cp_file, "r") as handle: + classpath_deps = handle.read().rstrip() + + targets = os.path.join(clouseau_dir, "target", "classes") + classpath = separator.join([classpath_deps, targets]) + else: + clouseau_jars = [ + os.path.join(clouseau_dir, fname) + for fname in os.listdir(clouseau_dir) + if fname.endswith(".jar") + ] + + if not clouseau_jars: + raise StartupError("Clouseau has no JAR files") + + classpath = separator.join(clouseau_jars) + + clouseau_ini = os.path.join(clouseau_dir, "clouseau.ini") + if not os.path.exists(clouseau_ini): + generate_default_clouseau_ini(clouseau_ini) + + log4j_properties = os.path.join(clouseau_dir, "log4j.properties") + if not os.path.exists(log4j_properties): + generate_default_log4j_properties(log4j_properties) clouseau_name = "clouseau{}@127.0.0.1".format(idx) - clouseau_indexes_dir = "{}/clouseau{}/data".format(ctx["devdir"], idx) + clouseau_indexes_dir = os.path.join(ctx["devdir"], "clouseau{}".format(idx), "data") if ctx["erlang_cookie"]: clouseau_cookie = ["-Dclouseau.cookie={}".format(ctx["erlang_cookie"])] @@ -608,8 +707,6 @@ def boot_clouseau(ctx, idx): if alternativeHome: os.environ["HOME"] = alternativeHome - separator = ";" if platform.system() == "Windows" else ":" - cmd = ( [ java, @@ -621,7 +718,7 @@ def boot_clouseau(ctx, idx): "-XX:+UseConcMarkSweepGC", "-XX:+CMSParallelRemarkEnabled", "-cp", - separator.join(clouseau_jars), + classpath, "-Dlog4j.configuration=file:{}".format(log4j_properties), "-Dclouseau.name={}".format(clouseau_name), "-Dclouseau.dir={}".format(clouseau_indexes_dir), @@ -632,8 +729,6 @@ def boot_clouseau(ctx, idx): clouseau_ini, ] ) - logfname = os.path.join(ctx["devdir"], "logs", "clouseau{}.log".format(idx)) - log = open(logfname, "w") try: return sp.Popen(
