package main import ( "fmt" "os" "path/filepath" "strings" "github.com/bmatcuk/doublestar/v4" ) func IsSymlink(path string) (bool, error) { fileInfo, err := os.Lstat(path) if err != nil { return false, err } // os.ModeSymlink is a bitmask that identifies the symlink mode. // If the file mode & os.ModeSymlink is non-zero, the file is a symlink. return fileInfo.Mode()&os.ModeSymlink != 0, nil } func FileExists(path string) bool { _, err := os.Lstat(path) return err == nil } func NormalizePath(input, workdir string) string { input = filepath.Clean(input) input = filepath.ToSlash(input) input = strings.ReplaceAll(input, "\"", "") if !filepath.IsAbs(input) { LogInfo("Input '%s' is not absolute, prepending work dir '%s'", input, workdir) var err error input = filepath.Join(workdir, input) input, err = filepath.Abs(input) if err != nil { LogError("Failed to get absolute path for %s: %v", FormatSourcePath(input), err) return input } } input = filepath.Clean(input) input = filepath.ToSlash(input) return input } func AreSame(lhs string, rhs string) bool { lhsinfo, err := os.Stat(lhs) if err != nil { return false } rhsinfo, err := os.Stat(rhs) if err != nil { return false } return os.SameFile(lhsinfo, rhsinfo) } func ConvertHome(input string) (string, error) { if strings.HasPrefix(input, "~/") { homedir, err := os.UserHomeDir() if err != nil { return input, fmt.Errorf("unable to convert ~ to user directory with error %+v", err) } return strings.Replace(input, "~", homedir, 1), nil } return input, nil } func GetSyncFilesRecursively(input string, output chan string, status chan error) { defer close(output) defer close(status) workdir, _ := os.Getwd() input = NormalizePath(input, workdir) LogInfo("Searching for sync files recursively starting in %s", FormatPathValue(input)) // Use doublestar to find all sync.yml and sync.yaml files recursively pattern := "**/sync.y*ml" files, err := doublestar.Glob(os.DirFS(input), pattern) if err != nil { LogError("Failed to search for pattern %s: %v", pattern, err) status <- err return } for _, file := range files { fullPath := filepath.Join(input, file) LogInfo("Found sync file: %s", FormatPathValue(fullPath)) output <- fullPath } LogInfo("Completed recursive search for sync files") }