diff --git a/instruction.go b/instruction.go index 6485168..afe9ad8 100644 --- a/instruction.go +++ b/instruction.go @@ -284,24 +284,20 @@ func ParseYAMLFile(filename, workdir string) ([]LinkInstruction, error) { expanded := []LinkInstruction{} for _, link := range config.Links { - if strings.Contains(link.Source, "*") { - LogSource("Expanding wildcard source %s in YAML file %s", link.Source, filename) - newlinks, err := ExpandPattern(link.Source, workdir, link.Target) - if err != nil { - return nil, fmt.Errorf("error expanding wildcard: %w", err) - } - // "Clone" the original link instruction for each expanded link - for i := range newlinks { - newlinks[i].Delete = link.Delete - newlinks[i].Hard = link.Hard - newlinks[i].Force = link.Force - } - LogInfo("Expanded wildcard source %s in YAML file %s to %d links", - FormatSourcePath(link.Source), FormatSourcePath(filename), len(newlinks)) - expanded = append(expanded, newlinks...) - } else { - expanded = append(expanded, link) + LogSource("Expanding pattern source %s in YAML file %s", link.Source, filename) + newlinks, err := ExpandPattern(link.Source, workdir, link.Target) + if err != nil { + return nil, fmt.Errorf("error expanding pattern: %w", err) } + // "Clone" the original link instruction for each expanded link + for i := range newlinks { + newlinks[i].Delete = link.Delete + newlinks[i].Hard = link.Hard + newlinks[i].Force = link.Force + } + LogInfo("Expanded pattern %s in YAML file %s to %d links", + FormatSourcePath(link.Source), FormatSourcePath(filename), len(newlinks)) + expanded = append(expanded, newlinks...) } for i := range expanded { @@ -325,34 +321,58 @@ func ParseYAMLFile(filename, workdir string) ([]LinkInstruction, error) { func ExpandPattern(source, workdir, target string) (links []LinkInstruction, err error) { static, pattern := doublestar.SplitPattern(source) if static == "" { - cwd, err := os.Getwd() - if err != nil { - return nil, fmt.Errorf("error getting current working directory: %w", err) - } - static = cwd + static = workdir } LogInfo("Static part: %s", static) LogInfo("Pattern part: %s", pattern) files, err := doublestar.Glob(os.DirFS(static), pattern) if err != nil { - return nil, fmt.Errorf("error expanding wildcard: %w", err) + return nil, fmt.Errorf("error expanding pattern: %w", err) + } + + targetIsFile := false + if info, err := os.Stat(target); err == nil && !info.IsDir() { + targetIsFile = true } for _, file := range files { - ext := filepath.Ext(file) - if ext == "" { - LogInfo("Skipping file %s because it has no extension (Directory?)", file) + if info, err := os.Stat(file); err == nil && info.IsDir() { + // We don't care about matched directories + // We want files within them + if len(files) == 1 { + // Special case: if there is only one file, and it's a directory + // This should only ever happen if our source is a path (and not a glob!) + // And our target is a path, a directory + // ...but it will also happen if the source IS a glob and it happens to match ONE directory + // I think that should happen rarely enough to not be an issue... + links = append(links, LinkInstruction{ + Source: filepath.Join(static, file), + Target: target, + }) + continue + } + LogInfo("Skipping directory %s", file) continue } - link := LinkInstruction{ - Source: file, - Target: filepath.Join(target, file), + + var targetPath string + if targetIsFile && len(files) == 1 { + // Special case: target is a file, and glob matches exactly one file. + // Use target directly (don't append filename). + targetPath = target + } else { + // Default: append filename to target dir. + targetPath = filepath.Join(target, file) } - links = append(links, link) + + links = append(links, LinkInstruction{ + Source: filepath.Join(static, file), + Target: targetPath, + }) } - LogInfo("Expanded wildcard source %s to %d links", FormatSourcePath(source), len(links)) + LogInfo("Expanded pattern %s to %d links", FormatSourcePath(source), len(links)) return } diff --git a/sync.yaml b/sync.yaml index 8f361d1..af3096b 100644 --- a/sync.yaml +++ b/sync.yaml @@ -1,2 +1,6 @@ - source: A/**/* - target: B \ No newline at end of file + target: B +- source: A/go.mod + target: B/go.mod +- source: A + target: B/foo