181 lines
4.2 KiB
Go
181 lines
4.2 KiB
Go
package command
|
|
|
|
import (
|
|
"alma/config"
|
|
"alma/helpers"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"github.com/samber/lo"
|
|
)
|
|
|
|
type LinkCommand struct {
|
|
}
|
|
|
|
type itemToLink struct {
|
|
source string
|
|
target string
|
|
}
|
|
|
|
func (LinkCommand) GetName() string {
|
|
return "link"
|
|
}
|
|
|
|
func (LinkCommand) GetHelpText() {
|
|
println(
|
|
`Usage:
|
|
alma link [module]
|
|
alma link [repository] [module]
|
|
|
|
Options:
|
|
--help Show this message
|
|
-d, --dry-run Show what would be linked without actually linking`)
|
|
}
|
|
|
|
func (LinkCommand) Run(args []string) {
|
|
moduleInfo, err := helpers.GetModuleInfo(args)
|
|
|
|
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") })
|
|
|
|
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"))
|
|
targetDirectory = helpers.ResolvePath(moduleConfiguration.Target)
|
|
}
|
|
|
|
itemsToLink := TraverseTree(
|
|
&moduleDirectory,
|
|
&targetDirectory,
|
|
&moduleDirectory,
|
|
&targetDirectory,
|
|
moduleConfiguration,
|
|
)
|
|
|
|
filteredItemsToLink := lo.Filter(itemsToLink, func(item itemToLink, index int) bool {
|
|
for _, exclude := range moduleConfiguration.Exclude {
|
|
sourceRelative := item.source[len(moduleDirectory)+1:]
|
|
if strings.HasPrefix(sourceRelative, exclude) {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
})
|
|
|
|
if dryRun {
|
|
println("Dry run. No links will be created. The following links would be created:")
|
|
}
|
|
|
|
linkItems(filteredItemsToLink, dryRun)
|
|
|
|
// Not yet used things
|
|
|
|
_ = targetDirectory
|
|
_ = moduleConfiguration
|
|
|
|
}
|
|
|
|
func TraverseTree(
|
|
currentDirectory *string,
|
|
currentTargetDirectory *string,
|
|
moduleDirectory *string,
|
|
targetDirectory *string,
|
|
moduleConfiguration *config.ModuleConfiguration) []itemToLink {
|
|
content, err := os.ReadDir(*currentDirectory)
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
|
|
itemsToLink := make([]itemToLink, 0, len(content))
|
|
for _, item := range content {
|
|
if item.IsDir() {
|
|
continue
|
|
}
|
|
|
|
if currentDirectory == moduleDirectory && item.Name() == ".alma-config.json" {
|
|
continue
|
|
}
|
|
|
|
itemConfigTargetPath := moduleConfiguration.Links[item.Name()]
|
|
|
|
var targetPath string
|
|
if itemConfigTargetPath != "" {
|
|
targetPath = helpers.ResolvePathWithDefault(moduleConfiguration.Links[item.Name()], *targetDirectory)
|
|
} else {
|
|
targetPath = filepath.Join(*currentTargetDirectory, item.Name())
|
|
}
|
|
|
|
itemsToLink = append(itemsToLink, itemToLink{
|
|
source: filepath.Join(*currentDirectory, item.Name()),
|
|
target: targetPath,
|
|
})
|
|
}
|
|
|
|
for _, item := range content {
|
|
if !item.IsDir() {
|
|
continue
|
|
}
|
|
|
|
relativePath := getRelativePath(filepath.Join(*currentDirectory, item.Name()), *moduleDirectory)
|
|
|
|
itemConfigTargetPath := moduleConfiguration.Links[relativePath]
|
|
|
|
if itemConfigTargetPath != "" {
|
|
itemsToLink = append(itemsToLink, itemToLink{
|
|
source: filepath.Join(*currentDirectory, item.Name()),
|
|
target: helpers.ResolvePathWithDefault(itemConfigTargetPath, *targetDirectory),
|
|
})
|
|
} else {
|
|
newCurrentDirectory := filepath.Join(*currentDirectory, item.Name())
|
|
newTargetDirectory := filepath.Join(*currentTargetDirectory, item.Name())
|
|
items := TraverseTree(
|
|
&newCurrentDirectory,
|
|
&newTargetDirectory,
|
|
moduleDirectory,
|
|
targetDirectory,
|
|
moduleConfiguration,
|
|
)
|
|
|
|
if items != nil {
|
|
itemsToLink = append(itemsToLink, items...)
|
|
}
|
|
}
|
|
}
|
|
|
|
return itemsToLink
|
|
}
|
|
|
|
func linkItems(itemsToLink []itemToLink, dryRun bool) {
|
|
for _, item := range itemsToLink {
|
|
_, err := os.Stat(item.target)
|
|
if err == nil {
|
|
println("Target already exists", item.target)
|
|
continue
|
|
}
|
|
|
|
if dryRun {
|
|
println("Linking", item.source, item.target)
|
|
continue
|
|
}
|
|
|
|
err = os.Symlink(item.source, item.target)
|
|
if err != nil {
|
|
println("Error while linking", item.source, item.target)
|
|
}
|
|
}
|
|
}
|
|
|
|
func getRelativePath(full string, parent string) string {
|
|
return strings.TrimPrefix(full[len(parent):], string(filepath.Separator))
|
|
}
|