diff --git a/src/command/install.go b/src/command/install.go new file mode 100644 index 0000000..bf317eb --- /dev/null +++ b/src/command/install.go @@ -0,0 +1,99 @@ +package command + +import ( + "alma/config" + "alma/helpers" + "errors" + "os" + "os/exec" + "path/filepath" + "runtime" + "syscall" + + "github.com/samber/lo" +) + +type InstallCommand struct { +} + +type shellNotFoundError struct { + shell string +} + +func (e *shellNotFoundError) Error() string { + return "Shell not found" +} + +func (InstallCommand) GetName() string { + return "install" +} + +func (InstallCommand) GetHelpText() { + println("Install a package") +} + +func (InstallCommand) Run(args []string) { + moduleInfo, err := helpers.GetModuleInfo(args) + + if err != nil { + println(err.Error()) + return + } + + moduleDirectory := moduleInfo.ModuleDirectory + + dryRun := lo.ContainsBy(args, func(item string) bool { return (item == "-d" || item == "--dry-run") }) + + almaConfigFilePath, err := os.Stat(filepath.Join(moduleDirectory, ".alma-config.json")) + moduleConfiguration := &config.ModuleConfiguration{} + + if err != nil || almaConfigFilePath.IsDir() { + println("Error: .alma-config.json not found") + return + } + + moduleConfiguration = config.LoadModuleConfiguration(filepath.Join(moduleDirectory, ".alma-config.json")) + installCommand := moduleConfiguration.Install + + if dryRun { + println("Dry run, otherwise would run " + installCommand) + return + } + println("Running command: " + installCommand) + + switch runtime.GOOS { + case "linux": + err := runShellCommand("sh", "-c", installCommand) + + var shellNotFoundError *shellNotFoundError + if errors.As(err, &shellNotFoundError) { + println(shellNotFoundError.shell + " not found") + } + + case "windows": + err := runShellCommand("pwsh", "-c", installCommand) + + var shellNotFoundError *shellNotFoundError + if errors.As(err, &shellNotFoundError) { + println(shellNotFoundError.shell + " not found") + } + default: + println("Unsupported OS") + } +} + +func runShellCommand(shellCommand string, args ...string) error { + shell, pwshErrshellErr := exec.LookPath(shellCommand) + if pwshErrshellErr != nil { + return &shellNotFoundError{shell: shellCommand} + } + + shellArgs := append([]string{shellCommand}, args...) + env := os.Environ() + execErr := syscall.Exec(shell, shellArgs, env) + if execErr != nil { + return errors.New("Error running shell command") + } + + return nil +} diff --git a/src/command/link.go b/src/command/link.go index a8e553c..2377c93 100644 --- a/src/command/link.go +++ b/src/command/link.go @@ -34,48 +34,31 @@ Options: } func (LinkCommand) Run(args []string) { - repoName, moduleName := helpers.GetRepositoryAndModuleName(args) + moduleInfo, err := helpers.GetModuleInfo(args) - if moduleName == nil { - println("Module name is required") + if err != nil { + println(err.Error()) return } + moduleDirectory := moduleInfo.ModuleDirectory + targetDirectory := moduleInfo.TargetDirectory + dryRun := lo.ContainsBy(args, func(item string) bool { return (item == "-d" || item == "--dry-run") }) - sourceDirectory, targetDirectory := helpers.GetRepositorySourceAndTargetDirectory(repoName) - if sourceDirectory == nil { - println("Source directory not exists") - return - } - - sourceDirectoryFolderInfo, err := os.Stat(*sourceDirectory) - if err != nil || !sourceDirectoryFolderInfo.IsDir() { - println("Source directory not exists", *sourceDirectory) - return - } - - moduleNameAsPath := strings.ReplaceAll((*moduleName), "/", string(filepath.Separator)) - moduleDirectory := filepath.Join(*sourceDirectory, moduleNameAsPath) - - moduleDirectoryFolderInfo, err := os.Stat(moduleDirectory) - if err != nil || !moduleDirectoryFolderInfo.IsDir() { - println("Module directory not exists", moduleDirectory) - return - } - almaConfigFilePath, err := os.Stat(filepath.Join(moduleDirectory, ".alma-config.json")) moduleConfiguration := &config.ModuleConfiguration{} + if err == nil && !almaConfigFilePath.IsDir() { moduleConfiguration = config.LoadModuleConfiguration(filepath.Join(moduleDirectory, ".alma-config.json")) - targetDirectory1 := helpers.ResolvePath(moduleConfiguration.Target) - targetDirectory = &targetDirectory1 + targetDirectory = helpers.ResolvePath(moduleConfiguration.Target) } + itemsToLink := TraverseTree( &moduleDirectory, - targetDirectory, + &targetDirectory, &moduleDirectory, - targetDirectory, + &targetDirectory, moduleConfiguration, ) diff --git a/src/helpers/repo.go b/src/helpers/repo.go index cc1e49a..c071fcc 100644 --- a/src/helpers/repo.go +++ b/src/helpers/repo.go @@ -1,44 +1,75 @@ package helpers import ( + "alma/models" + "errors" "os" "path" + "path/filepath" "strings" "github.com/samber/lo" ) -func GetRepositoryAndModuleName(args []string) (*string, *string) { +func GetModuleInfo(args []string) (moduleInfo models.ModuleInfo, error error) { + repoName, moduleName := GetRepositoryAndModuleName(args) + + if moduleName == "" { + return models.ModuleInfo{}, errors.New("module name is required") + } + + sourceDirectory, targetDirectory := GetRepositorySourceAndTargetDirectory(repoName) + if sourceDirectory == "" { + return models.ModuleInfo{}, errors.New("source directory not exists") + } + + sourceDirectoryFolderInfo, err := os.Stat(sourceDirectory) + if err != nil || !sourceDirectoryFolderInfo.IsDir() { + return models.ModuleInfo{}, errors.New("source directory not exists") + } + + moduleNameAsPath := strings.ReplaceAll(moduleName, "/", string(filepath.Separator)) + moduleDirectory := filepath.Join(sourceDirectory, moduleNameAsPath) + + return models.ModuleInfo{ + RepositoryName: repoName, + ModuleName: moduleName, + SourceDirectory: sourceDirectory, + TargetDirectory: targetDirectory, + ModuleDirectory: moduleDirectory}, nil +} + +func GetRepositoryAndModuleName(args []string) (string, string) { return getRepositoryAndModuleName(args, false) } -func getRepositoryAndModuleName(args []string, singleParamIsRepository bool) (*string, *string) { - var repositoryName, moduleName *string = nil, nil +func getRepositoryAndModuleName(args []string, singleParamIsRepository bool) (string, string) { + var repositoryName, moduleName string = "", "" usefulArgs := lo.Filter(args, func(arg string, index int) bool { return !strings.HasPrefix(arg, "-") }) if len(usefulArgs) == 1 { if singleParamIsRepository { - repositoryName = &usefulArgs[0] + repositoryName = usefulArgs[0] } else { - moduleName = &usefulArgs[0] + moduleName = usefulArgs[0] } } else if len(usefulArgs) >= 1 { - repositoryName = &usefulArgs[0] - moduleName = &usefulArgs[1] + repositoryName = usefulArgs[0] + moduleName = usefulArgs[1] } return repositoryName, moduleName } -func GetRepositorySourceAndTargetDirectory(repoName *string) (*string, *string) { +func GetRepositorySourceAndTargetDirectory(repoName string) (string, string) { repoSourceDirectory, _ := os.Getwd() repoTargetDirectory, _ := os.Getwd() repoTargetDirectory = path.Join(repoTargetDirectory, "..") - return GetRepositorySourceAndTargetDirectoryWithFallback(repoName, &repoSourceDirectory, &repoTargetDirectory) + return GetRepositorySourceAndTargetDirectoryWithFallback(repoName, repoSourceDirectory, repoTargetDirectory) } -func GetRepositorySourceAndTargetDirectoryWithFallback(repoName *string, sourceFallback *string, targetFallback *string) (*string, *string) { +func GetRepositorySourceAndTargetDirectoryWithFallback(repoName string, sourceFallback string, targetFallback string) (string, string) { //TODO: Use repository configuration return sourceFallback, targetFallback } diff --git a/src/main.go b/src/main.go index 8836daf..7dba050 100644 --- a/src/main.go +++ b/src/main.go @@ -9,6 +9,7 @@ func main() { commands := []command.Command{ command.LinkCommand{}, command.InfoCommand{}, + command.InstallCommand{}, } run(commands, os.Args[1:]) diff --git a/src/models/moduleInfo.go b/src/models/moduleInfo.go new file mode 100644 index 0000000..66d3615 --- /dev/null +++ b/src/models/moduleInfo.go @@ -0,0 +1,9 @@ +package models + +type ModuleInfo struct { + RepositoryName string + ModuleName string + SourceDirectory string + TargetDirectory string + ModuleDirectory string +} diff --git a/src/test_module/.alma-config.json b/src/test_module/.alma-config.json index f79f783..1adf63f 100644 --- a/src/test_module/.alma-config.json +++ b/src/test_module/.alma-config.json @@ -4,7 +4,8 @@ "links": { "test_folder": "test_folder", "test_folder2": "test_folder3" - } + }, + "install": "echo 'INSTALL WORKS!! install command for test_module'" }, "win": { },