Skip to content

Commit 85c1186

Browse files
authored
Merge pull request #179 from easyp-tech/feat/path-flag
update --path flag logic on generate
2 parents a2805ea + aaabd7b commit 85c1186

2 files changed

Lines changed: 79 additions & 10 deletions

File tree

internal/api/generate.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ func (g Generate) Action(ctx *cli.Context) error {
6767
}
6868

6969
dir := ctx.String(flagGenerateDirectoryPath.Name)
70-
err = app.Generate(ctx.Context, ".", dir)
70+
err = app.Generate(ctx.Context, workingDir, dir)
7171
if err != nil {
7272
if errors.Is(err, core.ErrEmptyInputFiles) {
7373
logger.Warn("empty input files!")

internal/core/generate.go

Lines changed: 78 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ import (
88
"log/slog"
99
"os"
1010
"os/exec"
11-
"path"
1211
"path/filepath"
12+
"regexp"
1313
"strings"
1414

1515
"github.com/bufbuild/protocompile"
@@ -110,7 +110,18 @@ func (c *Core) Generate(ctx context.Context, root, directory string) error {
110110
}
111111

112112
for _, inputFilesDir := range c.inputs.InputFilesDir {
113-
fsWalker := fs.NewFSWalker(directory, inputFilesDir.Root)
113+
searchPath := filepath.Join(inputFilesDir.Root, inputFilesDir.Path)
114+
// Skip if inputFilesDir.Root and directory don't overlap
115+
if directory != "." && !pathsOverlap(directory, searchPath) {
116+
c.logger.DebugContext(ctx, "skipping inputFilesDir",
117+
slog.String("directory", directory),
118+
slog.String("searchPath", searchPath),
119+
slog.String("reason", "paths don't overlap"),
120+
)
121+
continue
122+
}
123+
124+
fsWalker := fs.NewFSWalker(root, searchPath)
114125
q.Imports = append(q.Imports, inputFilesDir.Root)
115126

116127
err := fsWalker.WalkDir(func(walkPath string, err error) error {
@@ -121,12 +132,13 @@ func (c *Core) Generate(ctx context.Context, root, directory string) error {
121132
return ctx.Err()
122133
case filepath.Ext(walkPath) != ".proto":
123134
return nil
124-
case shouldIgnore(walkPath, []string{path.Join(inputFilesDir.Root, inputFilesDir.Path)}):
125-
c.logger.DebugContext(ctx, "ignore", slog.String("walkPath", walkPath))
126-
135+
case shouldIgnore(walkPath, []string{directory}):
136+
c.logger.DebugContext(ctx, "ignore", slog.String("walkPath", walkPath), slog.String("directory", directory))
127137
return nil
128138
}
129139

140+
// Get file path relative to inputFilesDir.Root
141+
// walkPath starts with inputFilesDir.Root
130142
addedFile := stripPrefix(walkPath, inputFilesDir.Root)
131143
q.Files = append(q.Files, addedFile)
132144

@@ -286,9 +298,9 @@ func (c *Core) Generate(ctx context.Context, root, directory string) error {
286298
// Determine base directory for output files considering plugin.Out
287299
var baseDir string
288300
if plugin.Out != "" {
289-
baseDir = filepath.Join(directory, plugin.Out)
301+
baseDir = filepath.Join(root, plugin.Out)
290302
} else {
291-
baseDir = directory
303+
baseDir = root
292304
}
293305

294306
p := filepath.Join(baseDir, file.GetName())
@@ -354,14 +366,69 @@ func addFileWithInsertionPoint(
354366
return nil
355367
}
356368

369+
// pathsOverlap checks if two paths overlap (one is within another or they are equal).
370+
// It is recommended to pass absolute paths.
371+
func pathsOverlap(a, b string) bool {
372+
na := filepath.Clean(a)
373+
nb := filepath.Clean(b)
374+
375+
// Full match is always overlap
376+
if na == nb {
377+
return true
378+
}
379+
380+
// Add separator at the end to distinguish "/foo/bar" from "/foo/bark"
381+
naSlash := na + string(filepath.Separator)
382+
nbSlash := nb + string(filepath.Separator)
383+
384+
// na is parent of nb
385+
if strings.HasPrefix(nbSlash, naSlash) {
386+
return true
387+
}
388+
389+
// nb is parent of na
390+
if strings.HasPrefix(naSlash, nbSlash) {
391+
return true
392+
}
393+
394+
return false
395+
}
396+
357397
func shouldIgnore(path string, dirs []string) bool {
398+
path = filepath.Clean(path)
358399
if len(dirs) == 0 {
359400
return true
360401
}
361402

362403
for _, dir := range dirs {
363-
if strings.HasPrefix(path, dir) {
364-
return false
404+
dir = filepath.Clean(dir)
405+
406+
// Special case: if dir is ".", match everything
407+
if dir == "." {
408+
slog.Debug("shouldIgnore: dir is '.', matching all paths", "path", path)
409+
return false // Don't ignore - match everything
410+
}
411+
412+
// Check if path starts with dir (prefix matching)
413+
if strings.HasPrefix(path, dir+"/") || path == dir {
414+
slog.Debug("shouldIgnore: path starts with dir", "path", path, "dir", dir)
415+
return false // Don't ignore - path is within directory
416+
}
417+
418+
// Check regex pattern (for wildcard patterns)
419+
// QuoteMeta escapes all special chars (including *), then we convert \* back to .* for wildcard matching
420+
pattern := regexp.QuoteMeta(dir)
421+
pattern = strings.ReplaceAll(pattern, "\\*", ".*")
422+
regexPattern := "^" + pattern
423+
424+
matched, err := regexp.MatchString(regexPattern, path)
425+
if err != nil {
426+
slog.Warn("shouldIgnore: regex match error", "path", path, "dir", dir, "regex", regexPattern, "error", err)
427+
continue
428+
}
429+
if matched {
430+
slog.Debug("shouldIgnore: path matches regex pattern", "path", path, "dir", dir, "regex", regexPattern)
431+
return false // Don't ignore - path matches pattern
365432
}
366433
}
367434

@@ -395,6 +462,8 @@ func (c *Core) getModulePath(ctx context.Context, requestedDependency string) (s
395462
func stripPrefix(path, prefix string) string {
396463
normalizedPath := filepath.ToSlash(path)
397464
normalizedPrefix := filepath.ToSlash(prefix)
465+
// Remove trailing slash from prefix if present
466+
normalizedPrefix = strings.TrimSuffix(normalizedPrefix, "/")
398467

399468
return strings.TrimPrefix(normalizedPath, normalizedPrefix+"/")
400469
}

0 commit comments

Comments
 (0)