Compare commits
	
		
			4 Commits
		
	
	
		
			bff7cc2a27
			...
			v3.6.1
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 679322a8ac | |||
| 2b973be0c1 | |||
| d21e20d387 | |||
| 0fc5300786 | 
							
								
								
									
										5
									
								
								.vscode/launch.json
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										5
									
								
								.vscode/launch.json
									
									
									
									
										vendored
									
									
								
							@@ -41,9 +41,8 @@
 | 
			
		||||
			"args": [
 | 
			
		||||
				"-loglevel",
 | 
			
		||||
				"trace",
 | 
			
		||||
				"(?-s)LightComponent!anyrange=\"(!num)\"",
 | 
			
		||||
				"*4",
 | 
			
		||||
				"**/Outpost*.xml"
 | 
			
		||||
				"-cook",
 | 
			
		||||
				"cookscoop.yml",
 | 
			
		||||
			]
 | 
			
		||||
		}
 | 
			
		||||
	]
 | 
			
		||||
 
 | 
			
		||||
@@ -4,6 +4,7 @@ import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"modify/logger"
 | 
			
		||||
	"os"
 | 
			
		||||
	"path/filepath"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	"github.com/bmatcuk/doublestar/v4"
 | 
			
		||||
@@ -74,7 +75,15 @@ func AssociateFilesWithCommands(files []string, commands []ModifyCommand) (map[s
 | 
			
		||||
		}
 | 
			
		||||
		for _, command := range commands {
 | 
			
		||||
			for _, glob := range command.Files {
 | 
			
		||||
				matches, err := Matches(file, glob)
 | 
			
		||||
				_, pattern, err := FigureOutGlobRoot(glob)
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					logger.Trace("Failed to figure out glob root for %s: %v", glob, err)
 | 
			
		||||
					continue
 | 
			
		||||
				}
 | 
			
		||||
				file = filepath.Clean(file)
 | 
			
		||||
				file = strings.ReplaceAll(file, "\\", "/")
 | 
			
		||||
 | 
			
		||||
				matches, err := Matches(file, pattern)
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					logger.Trace("Failed to match glob %s with file %s: %v", glob, file, err)
 | 
			
		||||
					continue
 | 
			
		||||
@@ -110,7 +119,7 @@ func AggregateGlobs(commands []ModifyCommand) map[string]struct{} {
 | 
			
		||||
	globs := make(map[string]struct{})
 | 
			
		||||
	for _, command := range commands {
 | 
			
		||||
		for _, glob := range command.Files {
 | 
			
		||||
			glob = strings.Replace(glob, "~", os.Getenv("HOME"), 1)
 | 
			
		||||
			glob = strings.ReplaceAll(glob, "~", os.Getenv("USERPROFILE"))
 | 
			
		||||
			glob = strings.ReplaceAll(glob, "\\", "/")
 | 
			
		||||
			globs[glob] = struct{}{}
 | 
			
		||||
		}
 | 
			
		||||
@@ -119,21 +128,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, err := FigureOutGlobRoot(pattern)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, fmt.Errorf("failed to figure out glob root: %w", err)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		logger.Trace("Processing pattern: %s", pattern)
 | 
			
		||||
		matches, _ := doublestar.Glob(os.DirFS(cwd), 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(root, m)
 | 
			
		||||
			info, err := os.Stat(m)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				logger.Warning("Error getting file info for %s: %v", m, err)
 | 
			
		||||
 
 | 
			
		||||
@@ -3,6 +3,7 @@ package utils
 | 
			
		||||
import (
 | 
			
		||||
	"os"
 | 
			
		||||
	"path/filepath"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	"github.com/stretchr/testify/assert"
 | 
			
		||||
@@ -1269,3 +1270,164 @@ func TestLoadCommandsFromCookFilesNoYamlFiles(t *testing.T) {
 | 
			
		||||
// 		t.Errorf("Expected 0 commands, got: %d", len(commands))
 | 
			
		||||
// 	}
 | 
			
		||||
// }
 | 
			
		||||
 | 
			
		||||
// Absolute path without wildcards returns correct root and pattern
 | 
			
		||||
func TestFigureOutGlobRootWithAbsolutePathNoWildcards(t *testing.T) {
 | 
			
		||||
	// Setup
 | 
			
		||||
	absPath := filepath.Join("C:\\Users", "test", "documents", "file.txt")
 | 
			
		||||
 | 
			
		||||
	// Execute
 | 
			
		||||
	root, pattern, err := FigureOutGlobRoot(absPath)
 | 
			
		||||
 | 
			
		||||
	// Assert
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
	expectedRoot := filepath.Clean(filepath.Join("C:\\Users", "test", "documents"))
 | 
			
		||||
	assert.Equal(t, expectedRoot, root)
 | 
			
		||||
	assert.Equal(t, "file.txt", pattern)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Empty input pattern handling - we expect our "Patter", such as it is, to be a folder
 | 
			
		||||
func TestFigureOutGlobRootWithEmptyPattern(t *testing.T) {
 | 
			
		||||
	// Setup
 | 
			
		||||
	emptyPattern := ""
 | 
			
		||||
 | 
			
		||||
	// Execute
 | 
			
		||||
	root, pattern, err := FigureOutGlobRoot(emptyPattern)
 | 
			
		||||
 | 
			
		||||
	// Assert
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
	cwd, _ := os.Getwd()
 | 
			
		||||
	cwdParts := strings.Split(filepath.Clean(cwd), "\\")
 | 
			
		||||
	expectedRoot := strings.Join(cwdParts[:len(cwdParts)-1], "\\")
 | 
			
		||||
	expectedPattern := cwdParts[len(cwdParts)-1]
 | 
			
		||||
	assert.Equal(t, expectedRoot, root)
 | 
			
		||||
	assert.Equal(t, expectedPattern, pattern)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Relative path is correctly joined with current working directory
 | 
			
		||||
func TestFigureOutGlobRootWithRelativePath(t *testing.T) {
 | 
			
		||||
	// Setup
 | 
			
		||||
	cwd, err := os.Getwd()
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
	relPath := "test/documents/file.txt"
 | 
			
		||||
 | 
			
		||||
	// Execute
 | 
			
		||||
	root, pattern, err := FigureOutGlobRoot(relPath)
 | 
			
		||||
 | 
			
		||||
	// Assert
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
	expectedRoot := filepath.Clean(filepath.Join(cwd, "test/documents"))
 | 
			
		||||
	assert.Equal(t, expectedRoot, root)
 | 
			
		||||
	assert.Equal(t, "file.txt", pattern)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Path with wildcards correctly identifies the last non-wildcard directory as root
 | 
			
		||||
func TestFigureOutGlobRootWithWildcards(t *testing.T) {
 | 
			
		||||
	// Setup
 | 
			
		||||
	inputPattern := filepath.Join("C:\\Users", "test", "documents", "*", "file.txt")
 | 
			
		||||
 | 
			
		||||
	// Execute
 | 
			
		||||
	root, pattern, err := FigureOutGlobRoot(inputPattern)
 | 
			
		||||
 | 
			
		||||
	// Assert
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
	expectedRoot := filepath.Clean(filepath.Join("C:\\Users", "test", "documents"))
 | 
			
		||||
	assert.Equal(t, expectedRoot, root)
 | 
			
		||||
	assert.Equal(t, "*/file.txt", pattern)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Windows-style paths are properly handled and converted
 | 
			
		||||
func TestFigureOutGlobRootWithRelativePathAndWildcards(t *testing.T) {
 | 
			
		||||
	// Setup
 | 
			
		||||
	inputPattern := "documents\\*\\file?.txt"
 | 
			
		||||
	cwd, _ := os.Getwd()
 | 
			
		||||
 | 
			
		||||
	// Execute
 | 
			
		||||
	root, pattern, err := FigureOutGlobRoot(inputPattern)
 | 
			
		||||
 | 
			
		||||
	// Assert
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
	expectedRoot := filepath.Clean(filepath.Join(cwd, "documents"))
 | 
			
		||||
	assert.Equal(t, expectedRoot, root)
 | 
			
		||||
	assert.Equal(t, "*/file?.txt", pattern)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Path with only wildcards (e.g., "*" or "**")
 | 
			
		||||
func TestFigureOutGlobRootWithOnlyWildcards(t *testing.T) {
 | 
			
		||||
	// Setup
 | 
			
		||||
	wildcardPattern := "*"
 | 
			
		||||
 | 
			
		||||
	// Execute
 | 
			
		||||
	root, pattern, err := FigureOutGlobRoot(wildcardPattern)
 | 
			
		||||
 | 
			
		||||
	// Assert
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
	expectedRoot, _ := os.Getwd()
 | 
			
		||||
	assert.Equal(t, expectedRoot, root)
 | 
			
		||||
	assert.Equal(t, "*", pattern)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Multiple path segments are correctly processed and joined
 | 
			
		||||
func TestFigureOutGlobRootWithRelativePathAndWildcards2(t *testing.T) {
 | 
			
		||||
	// Setup
 | 
			
		||||
	cwd, err := os.Getwd()
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
	relPath := filepath.Join("test", "data", "*", "file?.txt")
 | 
			
		||||
 | 
			
		||||
	// Execute
 | 
			
		||||
	root, pattern, err := FigureOutGlobRoot(relPath)
 | 
			
		||||
 | 
			
		||||
	// Assert
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
	expectedRoot := filepath.Clean(filepath.Join(cwd, "test", "data"))
 | 
			
		||||
	assert.Equal(t, expectedRoot, root)
 | 
			
		||||
	assert.Equal(t, "*/file?.txt", pattern)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Path with mixed forward and backward slashes
 | 
			
		||||
func TestFigureOutGlobRootWithMixedSlashes(t *testing.T) {
 | 
			
		||||
	// Setup
 | 
			
		||||
	mixedPath := "C:\\Users/test\\documents\\file.txt"
 | 
			
		||||
 | 
			
		||||
	// Execute
 | 
			
		||||
	root, pattern, err := FigureOutGlobRoot(mixedPath)
 | 
			
		||||
 | 
			
		||||
	// Assert
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
	expectedRoot := filepath.Clean(filepath.Join("C:\\Users", "test", "documents"))
 | 
			
		||||
	assert.Equal(t, expectedRoot, root)
 | 
			
		||||
	assert.Equal(t, "file.txt", pattern)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Path with wildcards in the first segment
 | 
			
		||||
func TestFigureOutGlobRootWithWildcardInFirstSegment(t *testing.T) {
 | 
			
		||||
	// Setup
 | 
			
		||||
	inputPattern := "*\\Users\\test\\documents\\file.txt"
 | 
			
		||||
	cwd, _ := os.Getwd()
 | 
			
		||||
 | 
			
		||||
	// Execute
 | 
			
		||||
	root, pattern, err := FigureOutGlobRoot(inputPattern)
 | 
			
		||||
 | 
			
		||||
	// Assert
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
	expectedRoot := filepath.Clean(cwd)
 | 
			
		||||
	assert.Equal(t, expectedRoot, root)
 | 
			
		||||
	assert.Equal(t, "*/Users/test/documents/file.txt", pattern)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Handling of relative paths with ".." or "." components
 | 
			
		||||
func TestFigureOutGlobRootWithRelativePathAndDotComponents(t *testing.T) {
 | 
			
		||||
	// Setup
 | 
			
		||||
	cwd, err := os.Getwd()
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
	relPath := filepath.Join("..", ".", "test", "documents", "file.txt")
 | 
			
		||||
 | 
			
		||||
	// Execute
 | 
			
		||||
	root, pattern, err := FigureOutGlobRoot(relPath)
 | 
			
		||||
 | 
			
		||||
	// Assert
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
	expectedRoot := filepath.Clean(filepath.Join(cwd, "..", "test", "documents"))
 | 
			
		||||
	assert.Equal(t, expectedRoot, root)
 | 
			
		||||
	assert.Equal(t, "file.txt", pattern)
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user