@@ -724,8 +724,7 @@ func (d *Discovery) skipDirIfIgnorable(_ log.Logger, path string) error {
724724 }
725725 }
726726
727- // When the filter flag is enabled, let the filters control discovery instead of exclude patterns
728- // When the filter flag is enabled, let the filters control discovery instead of exclude patterns
727+ // When the filter flag is enabled, let the filters control discovery instead of exclude patterns.
729728 // We also avoid early skipping for CLI exclude patterns so reporting can capture excluded units.
730729 if d .filterFlagEnabled {
731730 return nil
@@ -1288,7 +1287,12 @@ func (d *Discovery) Discover(
12881287 }
12891288
12901289 if d .graphTarget != "" {
1291- components = d .filterGraphTarget (l , components )
1290+ var err error
1291+
1292+ components , err = d .filterGraphTarget (components )
1293+ if err != nil {
1294+ return nil , err
1295+ }
12921296 }
12931297
12941298 components = d .applyQueueFilters (opts , components )
@@ -1297,35 +1301,46 @@ func (d *Discovery) Discover(
12971301}
12981302
12991303// filterGraphTarget prunes components to the target path and its dependents.
1300- func (d * Discovery ) filterGraphTarget (l log. Logger , components component.Components ) component.Components {
1304+ func (d * Discovery ) filterGraphTarget (components component.Components ) ( component.Components , error ) {
13011305 if d .graphTarget == "" {
1302- return components
1306+ return components , nil
13031307 }
13041308
1305- targetPath := canonicalizeGraphTarget (l , d .workingDir , d .graphTarget )
1309+ targetPath , err := canonicalizeGraphTarget (d .workingDir , d .graphTarget )
1310+ if err != nil {
1311+ return nil , err
1312+ }
13061313
13071314 dependentUnits := buildDependentsIndex (components )
13081315 propagateTransitiveDependents (dependentUnits )
13091316
13101317 allowed := buildAllowSet (targetPath , dependentUnits )
13111318
1312- return filterByAllowSet (components , allowed )
1319+ return filterByAllowSet (components , allowed ), nil
13131320}
13141321
13151322// canonicalizeGraphTarget resolves the graph target to an absolute, cleaned path.
1316- // Falls back to a cleaned relative path on canonicalization failure, logging at debug level.
1317- func canonicalizeGraphTarget (l log.Logger , baseDir , target string ) string {
1318- targetPath := target
1319- if ! filepath .IsAbs (targetPath ) {
1320- if abs , err := util .CanonicalPath (targetPath , baseDir ); err == nil {
1321- targetPath = abs
1322- } else {
1323- l .Debugf ("Could not canonicalize graph target %s: %v" , targetPath , err )
1324- targetPath = filepath .Clean (targetPath )
1325- }
1323+ // Returns an error if the path cannot be made absolute.
1324+ func canonicalizeGraphTarget (baseDir , target string ) (string , error ) {
1325+ // If already absolute, just clean it
1326+ if filepath .IsAbs (target ) {
1327+ return filepath .Clean (target ), nil
1328+ }
1329+
1330+ // Try canonical path first
1331+ if abs , err := util .CanonicalPath (target , baseDir ); err == nil {
1332+ return abs , nil
1333+ }
1334+
1335+ // Fallback: join with baseDir and make absolute
1336+ joined := filepath .Join (baseDir , filepath .Clean (target ))
1337+
1338+ abs , err := filepath .Abs (joined )
1339+ if err != nil {
1340+ return "" , errors .Errorf ("failed to resolve graph target %q relative to %q: %w" , target , baseDir , err )
13261341 }
13271342
1328- return targetPath
1343+ return abs , nil
13291344}
13301345
13311346// buildDependentsIndex builds an index mapping each unit path to the list of units
0 commit comments