@@ -30,6 +30,7 @@ import (
3030 "github.com/rs/zerolog"
3131 "github.com/spf13/pflag"
3232 internalConfig "github.com/vektra/mockery/v3/internal/config"
33+ internalFile "github.com/vektra/mockery/v3/internal/file"
3334 "github.com/vektra/mockery/v3/internal/logging"
3435 "github.com/vektra/mockery/v3/internal/stackerr"
3536 "github.com/vektra/mockery/v3/template_funcs"
@@ -775,24 +776,39 @@ func (c *Config) buildTemplateData(
775776 interfaceDirPath := filepath .ToSlash (filepath .Dir (ifaceFilePath ))
776777
777778 var interfaceDirRelative string
778- interfaceDirRelativePath , err := filepath . Rel ( filepath . FromSlash ( workingDir ), filepath . FromSlash ( interfaceDirPath ) )
779+ outsideCurrentRepo , err := isPathOutsideCurrentGoModRepo ( workingDir , interfaceDirPath )
779780 if err != nil {
780781 log .Debug ().
781782 Err (err ).
782- Str ("working-dir" , workingDir ).
783- Str ("interfaceDirPath" , interfaceDirPath ).
784- Str ("interface-dir-relative-path" , interfaceDirRelativePath ).
785- Str ("iface-file-path" , ifaceFilePath ).
786- Msg ("can't make path relative to working dir, setting to './'" )
787- interfaceDirRelative = "."
788- } else {
789- interfaceDirRelativePath = filepath .ToSlash (interfaceDirRelativePath )
783+ Msg ("failed to determine whether interface path is outside current go.mod repo" )
784+ }
785+ if outsideCurrentRepo {
790786 log .Debug ().
791787 Str ("working-dir" , workingDir ).
792788 Str ("interfaceDirPath" , interfaceDirPath ).
793- Str ("interface-dir-relative-path" , interfaceDirRelativePath ).
794- Msg ("found relative path" )
795- interfaceDirRelative = interfaceDirRelativePath
789+ Str ("src-package-path" , srcPkg .Types .Path ()).
790+ Msg ("interface path is outside current go.mod repo; using fully-qualified package path" )
791+ interfaceDirRelative = srcPkg .Types .Path ()
792+ } else {
793+ interfaceDirRelativePath , err := filepath .Rel (filepath .FromSlash (workingDir ), filepath .FromSlash (interfaceDirPath ))
794+ if err != nil {
795+ log .Debug ().
796+ Err (err ).
797+ Str ("working-dir" , workingDir ).
798+ Str ("interfaceDirPath" , interfaceDirPath ).
799+ Str ("interface-dir-relative-path" , interfaceDirRelativePath ).
800+ Str ("iface-file-path" , ifaceFilePath ).
801+ Msg ("can't make path relative to working dir, setting to './'" )
802+ interfaceDirRelative = "."
803+ } else {
804+ interfaceDirRelativePath = filepath .ToSlash (interfaceDirRelativePath )
805+ log .Debug ().
806+ Str ("working-dir" , workingDir ).
807+ Str ("interfaceDirPath" , interfaceDirPath ).
808+ Str ("interface-dir-relative-path" , interfaceDirRelativePath ).
809+ Msg ("found relative path" )
810+ interfaceDirRelative = interfaceDirRelativePath
811+ }
796812 }
797813
798814 return TemplateData {
@@ -809,6 +825,27 @@ func (c *Config) buildTemplateData(
809825 }, nil
810826}
811827
828+ func isPathOutsideCurrentGoModRepo (workingDir string , targetPath string ) (bool , error ) {
829+ goModFile , _ , err := internalFile .FindInHierarchy (workingDir , []string {"go.mod" })
830+ if err != nil {
831+ return false , err
832+ }
833+
834+ repoRoot := filepath .ToSlash (filepath .Dir (goModFile ))
835+ targetPath = filepath .ToSlash (filepath .Clean (targetPath ))
836+
837+ relFromRepoRoot , err := filepath .Rel (filepath .FromSlash (repoRoot ), filepath .FromSlash (targetPath ))
838+ // Windows can return an error here if the paths are on different drives.
839+ // In that case, we can just assume the target path is outside the repo.
840+ if err != nil {
841+ //nolint:nilerr // Intentional: treat cross-drive Rel errors as "outside repo", not a fatal error.
842+ return true , nil
843+ }
844+ relFromRepoRoot = filepath .ToSlash (relFromRepoRoot )
845+
846+ return relFromRepoRoot == ".." || strings .HasPrefix (relFromRepoRoot , "../" ), nil
847+ }
848+
812849func (c * Config ) GetReplacement (pkgPath string , typeName string ) * ReplaceType {
813850 pkgMap := c .ReplaceType [pkgPath ]
814851 if pkgMap == nil {
0 commit comments