Skip to content

Commit 63a949d

Browse files
committed
fix: Consolidating some duplicate logic
1 parent 649fdeb commit 63a949d

File tree

6 files changed

+31
-60
lines changed

6 files changed

+31
-60
lines changed

internal/component/component.go

Lines changed: 6 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,12 @@
88
package component
99

1010
import (
11-
"path/filepath"
1211
"slices"
1312
"sort"
1413
"sync"
1514

1615
"github.com/gruntwork-io/terragrunt/internal/errors"
16+
"github.com/gruntwork-io/terragrunt/internal/util"
1717
)
1818

1919
// Kind is the type of Terragrunt component.
@@ -255,7 +255,7 @@ func NewThreadSafeComponents(components Components) *ThreadSafeComponents {
255255

256256
// Pre-populate resolved paths cache for initial components
257257
for _, c := range components {
258-
tsc.resolvedPaths[c.Path()] = resolvePath(c.Path())
258+
tsc.resolvedPaths[c.Path()] = util.ResolvePath(c.Path())
259259
}
260260

261261
return tsc
@@ -269,7 +269,7 @@ func (tsc *ThreadSafeComponents) resolvedPathFor(path string) string {
269269
return resolved
270270
}
271271

272-
return resolvePath(path)
272+
return util.ResolvePath(path)
273273
}
274274

275275
// EnsureComponent adds a component to the components list if it's not already present.
@@ -293,7 +293,7 @@ func (tsc *ThreadSafeComponents) findComponent(c Component) (Component, bool) {
293293
tsc.mu.RLock()
294294
defer tsc.mu.RUnlock()
295295

296-
searchResolved := resolvePath(c.Path())
296+
searchResolved := util.ResolvePath(c.Path())
297297

298298
idx := slices.IndexFunc(tsc.components, func(cc Component) bool {
299299
return tsc.resolvedPathFor(cc.Path()) == searchResolved
@@ -313,7 +313,7 @@ func (tsc *ThreadSafeComponents) addComponent(c Component) (Component, bool) {
313313
tsc.mu.Lock()
314314
defer tsc.mu.Unlock()
315315

316-
searchResolved := resolvePath(c.Path())
316+
searchResolved := util.ResolvePath(c.Path())
317317

318318
// Do one last check to see if the component is already in the components list
319319
// to avoid a TOCTOU race condition. Uses resolved paths for comparison.
@@ -339,7 +339,7 @@ func (tsc *ThreadSafeComponents) FindByPath(path string) Component {
339339
tsc.mu.RLock()
340340
defer tsc.mu.RUnlock()
341341

342-
resolvedSearchPath := resolvePath(path)
342+
resolvedSearchPath := util.ResolvePath(path)
343343

344344
for _, c := range tsc.components {
345345
if tsc.resolvedPathFor(c.Path()) == resolvedSearchPath {
@@ -369,14 +369,3 @@ func (tsc *ThreadSafeComponents) Len() int {
369369

370370
return len(tsc.components)
371371
}
372-
373-
// resolvePath resolves symlinks in a path for consistent comparison across platforms.
374-
// On macOS, /var is a symlink to /private/var, so paths must be resolved.
375-
func resolvePath(path string) string {
376-
resolved, err := filepath.EvalSymlinks(path)
377-
if err != nil {
378-
return path
379-
}
380-
381-
return resolved
382-
}

internal/discovery/discovery.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -631,10 +631,10 @@ func buildDependentsIndex(components component.Components) map[string][]string {
631631
dependentUnits := make(map[string][]string)
632632

633633
for _, c := range components {
634-
cPath := resolvePath(c.Path())
634+
cPath := util.ResolvePath(c.Path())
635635

636636
for _, dep := range c.Dependencies() {
637-
depPath := resolvePath(dep.Path())
637+
depPath := util.ResolvePath(dep.Path())
638638
dependentUnits[depPath] = util.RemoveDuplicates(append(dependentUnits[depPath], cPath))
639639
}
640640
}
@@ -697,7 +697,7 @@ func filterByAllowSet(components component.Components, allowed map[string]struct
697697
filtered := make(component.Components, 0, len(components))
698698

699699
for _, c := range components {
700-
resolvedPath := resolvePath(c.Path())
700+
resolvedPath := util.ResolvePath(c.Path())
701701
if _, ok := allowed[resolvedPath]; ok {
702702
filtered = append(filtered, c)
703703
}

internal/discovery/helpers.go

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -28,17 +28,6 @@ const (
2828
// DefaultConfigFilenames are the default Terragrunt config filenames used in discovery.
2929
var DefaultConfigFilenames = []string{config.DefaultTerragruntConfigPath, config.DefaultStackFile}
3030

31-
// resolvePath resolves symlinks in a path for consistent comparison across platforms.
32-
// On macOS, /var is a symlink to /private/var, so paths must be resolved.
33-
func resolvePath(path string) string {
34-
resolved, err := filepath.EvalSymlinks(path)
35-
if err != nil {
36-
return path
37-
}
38-
39-
return resolved
40-
}
41-
4231
// isExternal checks if a component path is outside the given working directory.
4332
// A path is considered external if it's not within or equal to the working directory.
4433
// We conservatively evaluate paths as external if we cannot determine their absolute path.

internal/discovery/phase_graph.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -546,20 +546,20 @@ func (p *GraphPhase) discoverDependentsUpstream(
546546
return nil
547547
}
548548

549-
resolvedTargetPath := resolvePath(target.Path())
549+
resolvedTargetPath := util.ResolvePath(target.Path())
550550

551551
// When the target is from a worktree, we need to compare using relative suffixes
552552
// because the absolute paths will differ (worktree vs original directory).
553553
// We resolve paths to handle symlinks (e.g., /var -> /private/var on macOS).
554554
targetRelSuffix := ""
555555

556556
if targetDCtx := target.DiscoveryContext(); targetDCtx != nil && targetDCtx.WorkingDir != "" {
557-
resolvedWorkingDir := resolvePath(targetDCtx.WorkingDir)
557+
resolvedWorkingDir := util.ResolvePath(targetDCtx.WorkingDir)
558558
targetRelSuffix = strings.TrimPrefix(resolvedTargetPath, resolvedWorkingDir)
559559
}
560560

561561
// Resolve discovery.workingDir for consistent path comparison.
562-
resolvedDiscoveryWorkingDir := resolvePath(discovery.workingDir)
562+
resolvedDiscoveryWorkingDir := util.ResolvePath(discovery.workingDir)
563563

564564
var (
565565
errs []error
@@ -724,7 +724,7 @@ func (p *GraphPhase) discoverDependentsUpstream(
724724

725725
// Compare paths: first try exact match, then try relative suffix match
726726
// for worktree scenarios where target is in a different directory.
727-
resolvedDep := resolvePath(dep)
727+
resolvedDep := util.ResolvePath(dep)
728728

729729
switch {
730730
case resolvedDep == resolvedTargetPath:
@@ -913,7 +913,7 @@ func extractDependencyPaths(cfg *config.TerragruntConfig, c component.Component)
913913
depPath = filepath.Clean(filepath.Join(c.Path(), depPath))
914914
}
915915

916-
depPath = resolvePath(depPath)
916+
depPath = util.ResolvePath(depPath)
917917
deduped[depPath] = struct{}{}
918918
}
919919

@@ -923,7 +923,7 @@ func extractDependencyPaths(cfg *config.TerragruntConfig, c component.Component)
923923
dependency = filepath.Clean(filepath.Join(c.Path(), dependency))
924924
}
925925

926-
dependency = resolvePath(dependency)
926+
dependency = util.ResolvePath(dependency)
927927
deduped[dependency] = struct{}{}
928928
}
929929
}

internal/filter/evaluator.go

Lines changed: 4 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -275,7 +275,7 @@ func evaluateGraphExpression(l log.Logger, expr *GraphExpression, components com
275275
}
276276

277277
for _, target := range targetMatches {
278-
traverseGraph(l, target, resultSet, visited, graphDirectionDependencies, depth, warnOnLimit)
278+
traverseGraph(l, target, resultSet, visited, GraphDirectionDependencies, depth, warnOnLimit)
279279
}
280280
}
281281

@@ -291,7 +291,7 @@ func evaluateGraphExpression(l log.Logger, expr *GraphExpression, components com
291291
}
292292

293293
for _, target := range targetMatches {
294-
traverseGraph(l, target, resultSet, visited, graphDirectionDependents, depth, warnOnLimit)
294+
traverseGraph(l, target, resultSet, visited, GraphDirectionDependents, depth, warnOnLimit)
295295
}
296296
}
297297

@@ -322,25 +322,6 @@ func evaluateGitFilter(filter *GitExpression, components component.Components) (
322322
return results, nil
323323
}
324324

325-
// graphDirection represents the direction of graph traversal.
326-
type graphDirection int
327-
328-
const (
329-
graphDirectionDependencies graphDirection = iota
330-
graphDirectionDependents
331-
)
332-
333-
func (d graphDirection) String() string {
334-
switch d {
335-
case graphDirectionDependencies:
336-
return "dependencies"
337-
case graphDirectionDependents:
338-
return "dependents"
339-
}
340-
341-
return "unknown"
342-
}
343-
344325
// traverseGraph recursively traverses the graph in the specified direction (dependencies or dependents).
345326
// The visited map tracks the maximum remaining depth at which each node was visited, allowing re-traversal
346327
// when a node is reached with more remaining depth (e.g., from a closer target).
@@ -350,7 +331,7 @@ func traverseGraph(
350331
c component.Component,
351332
resultSet map[string]component.Component,
352333
visited map[string]int,
353-
direction graphDirection,
334+
direction GraphDirection,
354335
remainingDepth int,
355336
warnOnLimit bool,
356337
) {
@@ -379,7 +360,7 @@ func traverseGraph(
379360
visited[path] = remainingDepth
380361

381362
var relatedComponents []component.Component
382-
if direction == graphDirectionDependencies {
363+
if direction == GraphDirectionDependencies {
383364
relatedComponents = c.Dependencies()
384365
} else {
385366
relatedComponents = c.Dependents()

internal/util/file.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1188,6 +1188,18 @@ func SanitizePath(baseDir string, file string) (string, error) {
11881188
return fullPath, nil
11891189
}
11901190

1191+
// ResolvePath resolves symlinks in a path for consistent comparison across platforms.
1192+
// On macOS, /var is a symlink to /private/var, so paths must be resolved.
1193+
// Returns the original path if symlink resolution fails.
1194+
func ResolvePath(path string) string {
1195+
resolved, err := filepath.EvalSymlinks(path)
1196+
if err != nil {
1197+
return path
1198+
}
1199+
1200+
return resolved
1201+
}
1202+
11911203
// MoveFile attempts to rename a file from source to destination, if this fails
11921204
// due to invalid cross-device link it falls back to copying the file contents
11931205
// and deleting the original file.

0 commit comments

Comments
 (0)