diff --git a/.vscode/launch.json b/.vscode/launch.json index 17f8277..0de5940 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -41,9 +41,8 @@ "args": [ "-loglevel", "trace", - "(?-s)LightComponent!anyrange=\"(!num)\"", - "*4", - "**/Outpost*.xml" + "-cook", + "cookscoop.yml", ] } ] diff --git a/utils/modifycommand.go b/utils/modifycommand.go index b11ed42..267139e 100644 --- a/utils/modifycommand.go +++ b/utils/modifycommand.go @@ -120,62 +120,84 @@ func AggregateGlobs(commands []ModifyCommand) map[string]struct{} { return globs } +func FigureOutGlobRoot(inputPattern string) (root, pattern string, err error) { + logger.Debug("Starting to figure out glob root for input pattern: %s", inputPattern) + + cwd, err := os.Getwd() + if err != nil { + logger.Error("Failed to get current working directory: %v", err) + return "", inputPattern, fmt.Errorf("failed to get current working directory: %w", err) + } + logger.Trace("Current working directory: %s", cwd) + + root = inputPattern + if !filepath.IsAbs(inputPattern) { + root = filepath.Join(cwd, inputPattern) + logger.Info("Input pattern is not absolute. Using combined path: %s", root) + } + root = filepath.Clean(root) + logger.Debug("Cleaned root path: %s", root) + + // In either case (whatever our root may be), we have to figure out + // Where to start, what our FS will be + // The best place would be the last sure entry + // That is to say the final directory that is not a wildcard + + finalroot := "" + // TODO: This will probably explode on linux because oooooooooo we have to be clever oooooooooo / on linux \\ on windows ooooooooooo + parts := strings.Split(root, "\\") + lastIndex := len(parts) - 1 + logger.Debug("Split root into parts: %v", parts) + + // In the case our pattern ends with a file (and many of them do) + // Look for only the folders, we cannot mount a file as a FS + // In any case we have to match files so they have to be the last part + for i := 0; i < len(parts)-1; i++ { + part := parts[i] + logger.Trace("Processing part: %s", part) + if part == "*" || part == "**" || part == "?" || part == "[" { + lastIndex = i + logger.Debug("Found wildcard part: %s, updating lastIndex to: %d", part, lastIndex) + break + } + // We can't use join here because it joins C: and Users as C:Users + // Instead of C:/Users/ + // God damn it + if finalroot != "" { + finalroot = finalroot + "/" + part + } else { + finalroot = finalroot + part + } + } + finalroot = filepath.Clean(finalroot) + logger.Debug("Final root after processing: %s", finalroot) + + // After all this juggling our pattern is whatever is left after the finalroot + // Which is, in "worst" case, only a file + pattern = strings.Join(parts[lastIndex:], "/") + logger.Info("Determined pattern: %s", pattern) + + return finalroot, pattern, nil +} + func ExpandGLobs(patterns map[string]struct{}) ([]string, error) { var files []string filesMap := make(map[string]bool) - cwd, err := os.Getwd() - if err != nil { - return nil, fmt.Errorf("failed to get current working directory: %w", err) - } - - logger.Debug("Expanding patterns from directory: %s", cwd) for pattern := range patterns { - root := pattern - if !filepath.IsAbs(pattern) { - root = filepath.Join(cwd, pattern) + root, pattern, err := FigureOutGlobRoot(pattern) + if err != nil { + return nil, fmt.Errorf("failed to figure out glob root: %w", err) } - root = filepath.Clean(root) - // In either case (whatever our root may be), we have to figure out - // Where to start, what our FS will be - // The best place would be the last sure entry - // That is to say the final directory that is not a wildcard - - finalroot := "" - // TODO: This will probably explode on linux because oooooooooo we have to be clever oooooooooo / on linux \\ on windows ooooooooooo - parts := strings.Split(root, "\\") - lastIndex := len(parts) - 1 - // In the case our pattern ends with a file (and many of them do) - // Look for only the folders, we cannot mount a file as a FS - // In any case we have to match files so they have to be the last part - for i := 0; i < len(parts)-1; i++ { - part := parts[i] - if part == "*" || part == "?" || part == "[" { - lastIndex = i - break - } - // We can't use join here because it joins C: and Users as C:Users - // Instead of C:/Users/ - // God damn it - if finalroot != "" { - finalroot = finalroot + "/" + part - } else { - finalroot = finalroot + part - } - } - finalroot = filepath.Clean(finalroot) - // After all this juggling our pattern is whatever is left after the finalroot - // Which is, in "worst" case, only a file - pattern = strings.Join(parts[lastIndex:], "/") logger.Trace("Processing pattern: %s", pattern) - matches, err := doublestar.Glob(os.DirFS(finalroot), pattern) + matches, err := doublestar.Glob(os.DirFS(root), pattern) if err != nil { return nil, fmt.Errorf("failed to glob pattern %s: %w", pattern, err) } logger.Debug("Found %d matches for pattern %s", len(matches), pattern) for _, m := range matches { - m = filepath.Join(finalroot, m) + m = filepath.Join(root, m) info, err := os.Stat(m) if err != nil { logger.Warning("Error getting file info for %s: %v", m, err)