Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 12 additions & 18 deletions pkg/executor/executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,9 @@ import (
"github.com/gnodet/mvx/pkg/config"
"github.com/gnodet/mvx/pkg/shell"
"github.com/gnodet/mvx/pkg/tools"
"github.com/gnodet/mvx/pkg/util"
)

// logVerbose prints verbose log messages
func logVerbose(format string, args ...interface{}) {
if os.Getenv("MVX_VERBOSE") == "true" {
fmt.Printf("[VERBOSE] "+format+"\n", args...)
}
}

// Executor handles command execution with proper environment setup
type Executor struct {
config *config.Config
Expand Down Expand Up @@ -166,19 +160,19 @@ func (e *Executor) setupEnvironment(cmdConfig config.CommandConfig) ([]string, e
requiredTools = append(requiredTools, toolName)
}
}
logVerbose("Required tools for command: %v", requiredTools)
util.LogVerbose("Required tools for command: %v", requiredTools)

// Add tool bin directories to PATH
for _, toolName := range requiredTools {
if toolConfig, exists := e.config.Tools[toolName]; exists {
// EnsureTool handles version resolution, installation check, auto-install, and path retrieval
binPath, err := e.toolManager.EnsureTool(toolName, toolConfig)
if err != nil {
logVerbose("Skipping tool %s: %v", toolName, err)
util.LogVerbose("Skipping tool %s: %v", toolName, err)
continue
}

logVerbose("Adding %s bin path to PATH: %s", toolName, binPath)
util.LogVerbose("Adding %s bin path to PATH: %s", toolName, binPath)
pathDirs = append(pathDirs, binPath)
}
}
Expand All @@ -191,9 +185,9 @@ func (e *Executor) setupEnvironment(cmdConfig config.CommandConfig) ([]string, e
newPath = newPath + string(os.PathListSeparator) + currentPath
}
envVars["PATH"] = newPath
logVerbose("Updated PATH with %d tool directories: %s", len(pathDirs), newPath)
util.LogVerbose("Updated PATH with %d tool directories: %s", len(pathDirs), newPath)
} else {
logVerbose("No tool directories added to PATH")
util.LogVerbose("No tool directories added to PATH")
}

// Convert environment map back to slice format
Expand All @@ -219,11 +213,11 @@ func (e *Executor) processScriptString(script string, args []string) string {

// executeScriptWithInterpreter executes a script using the specified interpreter
func (e *Executor) executeScriptWithInterpreter(script, workDir string, env []string, interpreter string) error {
logVerbose("executeScriptWithInterpreter called with interpreter: '%s', script: '%s'", interpreter, script)
util.LogVerbose("executeScriptWithInterpreter called with interpreter: '%s', script: '%s'", interpreter, script)

// Default to native interpreter if not specified
if interpreter == "" || interpreter == "native" {
logVerbose("Using native interpreter")
util.LogVerbose("Using native interpreter")
return e.executeNativeScript(script, workDir, env)
}

Expand All @@ -247,14 +241,14 @@ func (e *Executor) executeNativeScript(script, workDir string, env []string) err
shellArgs = []string{"/c"}
}

logVerbose("Executing native script: %s", script)
logVerbose("Working directory: %s", workDir)
logVerbose("Environment variables count: %d", len(env))
util.LogVerbose("Executing native script: %s", script)
util.LogVerbose("Working directory: %s", workDir)
util.LogVerbose("Environment variables count: %d", len(env))

// Log PATH specifically
for _, envVar := range env {
if strings.HasPrefix(envVar, "PATH=") {
logVerbose("PATH in environment: %s", envVar)
util.LogVerbose("PATH in environment: %s", envVar)
break
}
}
Expand Down
17 changes: 6 additions & 11 deletions pkg/shell/shell.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import (
"path/filepath"
"runtime"
"strings"

"github.com/gnodet/mvx/pkg/util"
)

// MVXShell provides cross-platform command execution
Expand Down Expand Up @@ -629,18 +631,11 @@ func (s *MVXShell) open(args []string) error {
return cmd.Run()
}

// logVerbose prints verbose log messages for mvx-shell
func logVerbose(format string, args ...interface{}) {
if os.Getenv("MVX_VERBOSE") == "true" {
fmt.Printf("[VERBOSE] "+format+"\n", args...)
}
}

// executeExternal executes an external command
func (s *MVXShell) executeExternal(cmd Command) error {
logVerbose("mvx-shell executing external command: %s %v", cmd.Name, cmd.Args)
logVerbose("mvx-shell working directory: %s", s.workDir)
logVerbose("mvx-shell environment variables count: %d", len(s.env))
util.LogVerbose("mvx-shell executing external command: %s %v", cmd.Name, cmd.Args)
util.LogVerbose("mvx-shell working directory: %s", s.workDir)
util.LogVerbose("mvx-shell environment variables count: %d", len(s.env))

execCmd := exec.Command(cmd.Name, cmd.Args...)
execCmd.Dir = s.workDir
Expand Down Expand Up @@ -675,7 +670,7 @@ func (s *MVXShell) executeExternal(cmd Command) error {
// Log PATH specifically
for _, envVar := range env {
if strings.HasPrefix(envVar, "PATH=") {
logVerbose("mvx-shell PATH in environment: %s", envVar)
util.LogVerbose("mvx-shell PATH in environment: %s", envVar)
break
}
}
Expand Down
45 changes: 23 additions & 22 deletions pkg/tools/base_tool.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"sync"

"github.com/gnodet/mvx/pkg/config"
"github.com/gnodet/mvx/pkg/util"
"github.com/gnodet/mvx/pkg/version"
)

Expand Down Expand Up @@ -261,7 +262,7 @@ func (b *BaseTool) VerifyWithConfig(version string, cfg config.ToolConfig, verif
// Set up environment for verification (needed for tools like Maven that depend on Java)
env, err := b.setupVerificationEnvironment(cfg)
if err != nil {
logVerbose("Failed to setup verification environment: %v", err)
util.LogVerbose("Failed to setup verification environment: %v", err)
env = nil // Fall back to default environment
}

Expand All @@ -287,7 +288,7 @@ func (b *BaseTool) setupVerificationEnvironment(cfg config.ToolConfig) ([]string
if tool, err := b.manager.GetTool(b.toolName); err == nil {
if depProvider, ok := tool.(DependencyProvider); ok {
dependencies := depProvider.GetDependencies()
logVerbose("Setting up dependencies for %s verification: %v", b.toolName, dependencies)
util.LogVerbose("Setting up dependencies for %s verification: %v", b.toolName, dependencies)

// Add dependencies to the temporary config
for _, depName := range dependencies {
Expand All @@ -300,7 +301,7 @@ func (b *BaseTool) setupVerificationEnvironment(cfg config.ToolConfig) ([]string
Distribution: installedVersions[0].Distribution,
}
tempConfig.Tools[depName] = depConfig
logVerbose("Added dependency %s %s to verification environment", depName, installedVersions[0].Version)
util.LogVerbose("Added dependency %s %s to verification environment", depName, installedVersions[0].Version)
}
}
}
Expand Down Expand Up @@ -342,15 +343,15 @@ func (b *BaseTool) setupVerificationEnvironment(cfg config.ToolConfig) ([]string
func (b *BaseTool) SetupHomeEnvironment(version string, cfg config.ToolConfig, envVars map[string]string, envVarName string, getPath func(string, config.ToolConfig) (string, error)) error {
binPath, err := getPath(version, cfg)
if err != nil {
logVerbose("Could not determine %s for %s %s: %v", envVarName, b.toolName, version, err)
util.LogVerbose("Could not determine %s for %s %s: %v", envVarName, b.toolName, version, err)
return nil
}

// *_HOME should point to the installation directory, not the bin directory
if strings.HasSuffix(binPath, "/bin") {
homeDir := strings.TrimSuffix(binPath, "/bin")
envVars[envVarName] = homeDir
logVerbose("Set %s=%s for %s %s", envVarName, homeDir, b.toolName, version)
util.LogVerbose("Set %s=%s for %s %s", envVarName, homeDir, b.toolName, version)
}

return nil
Expand Down Expand Up @@ -544,7 +545,7 @@ func (b *BaseTool) getDownloadOptions() DownloadOptions {
func (b *BaseTool) StandardInstall(version string, cfg config.ToolConfig, getDownloadURL func(string) string) error {
// Check if we should use system tool instead of downloading
if UseSystemTool(b.toolName) {
logVerbose("%s=true, forcing use of system %s", getSystemToolEnvVar(b.toolName), b.toolName)
util.LogVerbose("%s=true, forcing use of system %s", getSystemToolEnvVar(b.toolName), b.toolName)

// Try primary binary name in PATH
if toolPath, err := exec.LookPath(b.binaryName); err == nil {
Expand Down Expand Up @@ -665,29 +666,29 @@ func (b *BaseTool) ListInstalledVersions(distribution string) []InstalledVersion
func (b *BaseTool) StandardIsInstalled(versionSpec string, cfg config.ToolConfig, getPath func(string, config.ToolConfig) (string, error)) bool {
if UseSystemTool(b.toolName) {
if _, err := exec.LookPath(b.GetBinaryName()); err == nil {
logVerbose("System %s is available in PATH (MVX_USE_SYSTEM_%s=true)", b.toolName, strings.ToUpper(b.toolName))
util.LogVerbose("System %s is available in PATH (MVX_USE_SYSTEM_%s=true)", b.toolName, strings.ToUpper(b.toolName))
return true
}

logVerbose("System %s not available: not found in environment variables or PATH", b.toolName)
util.LogVerbose("System %s not available: not found in environment variables or PATH", b.toolName)
return false
}

tool, err := b.manager.GetTool(b.toolName)
if err != nil {
logVerbose("Failed to get tool %s: %v", b.toolName, err)
util.LogVerbose("Failed to get tool %s: %v", b.toolName, err)
return false
}

spec, err := version.ParseSpec(versionSpec)
if err != nil {
logVerbose("Failed to parse version spec %q: %v", versionSpec, err)
util.LogVerbose("Failed to parse version spec %q: %v", versionSpec, err)
return false
}

targetVersion, resolveErr := b.resolveTargetVersion(tool, spec, versionSpec, cfg)
if resolveErr != nil {
logVerbose("Failed to resolve target version for %s %s: %v", b.toolName, versionSpec, resolveErr)
util.LogVerbose("Failed to resolve target version for %s %s: %v", b.toolName, versionSpec, resolveErr)
}

installed := b.ListInstalledVersions(cfg.Distribution)
Expand All @@ -700,7 +701,7 @@ func (b *BaseTool) StandardIsInstalled(versionSpec string, cfg config.ToolConfig
for _, inst := range installed {
parsed, err := version.ParseVersion(inst.Version)
if err != nil {
logVerbose("Failed to parse installed version %s: %v", inst.Version, err)
util.LogVerbose("Failed to parse installed version %s: %v", inst.Version, err)
continue
}
if spec.Matches(parsed) {
Expand All @@ -718,7 +719,7 @@ func (b *BaseTool) StandardIsInstalled(versionSpec string, cfg config.ToolConfig

// Check candidates in order, return immediately on first valid installation
for _, candidate := range candidates {
logVerbose(" Checking installed version: %s (%s) at %s", candidate.info.Version, candidate.info.Distribution, candidate.info.Path)
util.LogVerbose(" Checking installed version: %s (%s) at %s", candidate.info.Version, candidate.info.Distribution, candidate.info.Path)

candidateCfg := cfg
candidateCfg.Version = candidate.info.Version
Expand All @@ -728,12 +729,12 @@ func (b *BaseTool) StandardIsInstalled(versionSpec string, cfg config.ToolConfig

binPath, err := getPath(candidate.info.Version, candidateCfg)
if err != nil {
logVerbose("Failed to compute binary path for %s %s: %v", b.toolName, candidate.info.Version, err)
util.LogVerbose("Failed to compute binary path for %s %s: %v", b.toolName, candidate.info.Version, err)
continue
}

if !b.IsInstalled(binPath) {
logVerbose("Binary for %s %s not found at %s", b.toolName, candidate.info.Version, binPath)
util.LogVerbose("Binary for %s %s not found at %s", b.toolName, candidate.info.Version, binPath)
continue
}

Expand All @@ -742,7 +743,7 @@ func (b *BaseTool) StandardIsInstalled(versionSpec string, cfg config.ToolConfig
// This avoids running "java -version", "mvn --version", etc. on every startup

// Found a valid installation - return immediately
logVerbose("Using previously installed %s %s (%s)", b.toolName, candidate.info.Version, candidate.info.Distribution)
util.LogVerbose("Using previously installed %s %s (%s)", b.toolName, candidate.info.Version, candidate.info.Distribution)
return true
}

Expand All @@ -751,26 +752,26 @@ func (b *BaseTool) StandardIsInstalled(versionSpec string, cfg config.ToolConfig
}

if targetVersion == "" {
logVerbose("Resolved target version for %s %s is empty", b.toolName, versionSpec)
util.LogVerbose("Resolved target version for %s %s is empty", b.toolName, versionSpec)
return false
}

installCfg := cfg
installCfg.Version = targetVersion

logVerbose("%s version %s not installed, attempting automatic installation", b.toolName, targetVersion)
util.LogVerbose("%s version %s not installed, attempting automatic installation", b.toolName, targetVersion)
if err := tool.Install(targetVersion, installCfg); err != nil {
logVerbose("Automatic installation of %s %s failed: %v", b.toolName, targetVersion, err)
util.LogVerbose("Automatic installation of %s %s failed: %v", b.toolName, targetVersion, err)
return false
}

if err := tool.Verify(targetVersion, installCfg); err != nil {
logVerbose("Verification after installing %s %s failed: %v", b.toolName, targetVersion, err)
util.LogVerbose("Verification after installing %s %s failed: %v", b.toolName, targetVersion, err)
return false
}

b.clearPathCache()
logVerbose("Successfully installed %s %s on demand", b.toolName, targetVersion)
util.LogVerbose("Successfully installed %s %s on demand", b.toolName, targetVersion)
return true
}

Expand Down Expand Up @@ -817,7 +818,7 @@ func (b *BaseTool) StandardGetPath(version string, cfg config.ToolConfig, getIns
if UseSystemTool(b.toolName) {
// Try primary binary name in PATH
if _, err := exec.LookPath(b.GetBinaryName()); err == nil {
logVerbose("Using system %s from PATH (MVX_USE_SYSTEM_%s=true)", b.toolName, strings.ToUpper(b.toolName))
util.LogVerbose("Using system %s from PATH (MVX_USE_SYSTEM_%s=true)", b.toolName, strings.ToUpper(b.toolName))
b.setCachedPath(cacheKey, "", nil)
return "", nil
}
Expand Down
3 changes: 2 additions & 1 deletion pkg/tools/download.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"time"

"github.com/gnodet/mvx/pkg/config"
"github.com/gnodet/mvx/pkg/util"
)

// DownloadConfig contains configuration for robust downloads with checksum verification
Expand Down Expand Up @@ -72,7 +73,7 @@ func RobustDownload(config *DownloadConfig) (*DownloadResult, error) {
originalURL := config.URL
urlReplacer, err := LoadURLReplacer()
if err != nil {
logVerbose("Warning: failed to load URL replacements: %v", err)
util.LogVerbose("Warning: failed to load URL replacements: %v", err)
} else {
config.URL = urlReplacer.ApplyReplacements(config.URL)
if config.URL != originalURL {
Expand Down
10 changes: 6 additions & 4 deletions pkg/tools/extraction.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import (
"os/exec"
"path/filepath"
"strings"

"github.com/gnodet/mvx/pkg/util"
)

// detectSingleTopLevelDirectory checks if all files in a ZIP archive are under a single top-level directory
Expand Down Expand Up @@ -295,7 +297,7 @@ func extractTarGzFile(src, dest string) error {
}
default:
// Skip other file types (char devices, block devices, etc.)
logVerbose("Skipping unsupported file type %d for %s", header.Typeflag, header.Name)
util.LogVerbose("Skipping unsupported file type %d for %s", header.Typeflag, header.Name)
}
}

Expand Down Expand Up @@ -334,14 +336,14 @@ func createSymlinkSafely(linkname, targetPath string) error {
if existingLink, err := os.Readlink(targetPath); err == nil {
if existingLink == linkname {
// Already the correct symlink, nothing to do
logVerbose("Symlink %s already exists with correct target %s", targetPath, linkname)
util.LogVerbose("Symlink %s already exists with correct target %s", targetPath, linkname)
return nil
}
// Different symlink target, remove and recreate
logVerbose("Removing existing symlink %s (target: %s) to create new one (target: %s)", targetPath, existingLink, linkname)
util.LogVerbose("Removing existing symlink %s (target: %s) to create new one (target: %s)", targetPath, existingLink, linkname)
} else {
// Not a symlink, but some other file/directory exists
logVerbose("Removing existing file/directory %s to create symlink (target: %s)", targetPath, linkname)
util.LogVerbose("Removing existing file/directory %s to create symlink (target: %s)", targetPath, linkname)
}

// Remove existing file/symlink/directory
Expand Down
Loading