@@ -34,8 +34,8 @@ import (
34
34
// like Mercurial, Git, or Subversion.
35
35
type Cmd struct {
36
36
Name string
37
- Cmd string // name of binary to invoke command
38
- RootNames []string // filename indicating the root of a checkout directory
37
+ Cmd string // name of binary to invoke command
38
+ RootNames []rootName // filename and mode indicating the root of a checkout directory
39
39
40
40
CreateCmd []string // commands to download a fresh copy of a repository
41
41
DownloadCmd []string // commands to download updates into an existing repository
@@ -150,9 +150,11 @@ func vcsByCmd(cmd string) *Cmd {
150
150
151
151
// vcsHg describes how to use Mercurial.
152
152
var vcsHg = & Cmd {
153
- Name : "Mercurial" ,
154
- Cmd : "hg" ,
155
- RootNames : []string {".hg" },
153
+ Name : "Mercurial" ,
154
+ Cmd : "hg" ,
155
+ RootNames : []rootName {
156
+ {filename : ".hg" , isDir : true },
157
+ },
156
158
157
159
CreateCmd : []string {"clone -U -- {repo} {dir}" },
158
160
DownloadCmd : []string {"pull" },
@@ -238,9 +240,11 @@ func parseRevTime(out []byte) (string, time.Time, error) {
238
240
239
241
// vcsGit describes how to use Git.
240
242
var vcsGit = & Cmd {
241
- Name : "Git" ,
242
- Cmd : "git" ,
243
- RootNames : []string {".git" },
243
+ Name : "Git" ,
244
+ Cmd : "git" ,
245
+ RootNames : []rootName {
246
+ {filename : ".git" , isDir : true },
247
+ },
244
248
245
249
CreateCmd : []string {"clone -- {repo} {dir}" , "-go-internal-cd {dir} submodule update --init --recursive" },
246
250
DownloadCmd : []string {"pull --ff-only" , "submodule update --init --recursive" },
@@ -352,9 +356,11 @@ func gitStatus(vcsGit *Cmd, rootDir string) (Status, error) {
352
356
353
357
// vcsBzr describes how to use Bazaar.
354
358
var vcsBzr = & Cmd {
355
- Name : "Bazaar" ,
356
- Cmd : "bzr" ,
357
- RootNames : []string {".bzr" },
359
+ Name : "Bazaar" ,
360
+ Cmd : "bzr" ,
361
+ RootNames : []rootName {
362
+ {filename : ".bzr" , isDir : true },
363
+ },
358
364
359
365
CreateCmd : []string {"branch -- {repo} {dir}" },
360
366
@@ -473,9 +479,11 @@ func bzrStatus(vcsBzr *Cmd, rootDir string) (Status, error) {
473
479
474
480
// vcsSvn describes how to use Subversion.
475
481
var vcsSvn = & Cmd {
476
- Name : "Subversion" ,
477
- Cmd : "svn" ,
478
- RootNames : []string {".svn" },
482
+ Name : "Subversion" ,
483
+ Cmd : "svn" ,
484
+ RootNames : []rootName {
485
+ {filename : ".svn" , isDir : true },
486
+ },
479
487
480
488
CreateCmd : []string {"checkout -- {repo} {dir}" },
481
489
DownloadCmd : []string {"update" },
@@ -524,9 +532,12 @@ const fossilRepoName = ".fossil"
524
532
525
533
// vcsFossil describes how to use Fossil (fossil-scm.org)
526
534
var vcsFossil = & Cmd {
527
- Name : "Fossil" ,
528
- Cmd : "fossil" ,
529
- RootNames : []string {".fslckout" , "_FOSSIL_" },
535
+ Name : "Fossil" ,
536
+ Cmd : "fossil" ,
537
+ RootNames : []rootName {
538
+ {filename : ".fslckout" , isDir : false },
539
+ {filename : "_FOSSIL_" , isDir : false },
540
+ },
530
541
531
542
CreateCmd : []string {"-go-internal-mkdir {dir} clone -- {repo} " + filepath .Join ("{dir}" , fossilRepoName ), "-go-internal-cd {dir} open .fossil" },
532
543
DownloadCmd : []string {"up" },
@@ -814,12 +825,7 @@ func FromDir(dir, srcRoot string, allowNesting bool) (repoDir string, vcsCmd *Cm
814
825
origDir := dir
815
826
for len (dir ) > len (srcRoot ) {
816
827
for _ , vcs := range vcsList {
817
- if fi , err := statAny (dir , vcs .RootNames ); err == nil {
818
- // git submodule contains .git file, but its directory is not a
819
- // git repository root.
820
- if ! fi .IsDir () && fi .Name () == ".git" {
821
- continue
822
- }
828
+ if isVCSRoot (dir , vcs .RootNames ) {
823
829
// Record first VCS we find.
824
830
// If allowNesting is false (as it is in GOPATH), keep looking for
825
831
// repositories in parent directories and report an error if one is
@@ -832,10 +838,6 @@ func FromDir(dir, srcRoot string, allowNesting bool) (repoDir string, vcsCmd *Cm
832
838
}
833
839
continue
834
840
}
835
- // Allow .git inside .git, which can arise due to submodules.
836
- if vcsCmd == vcs && vcs .Cmd == "git" {
837
- continue
838
- }
839
841
// Otherwise, we have one VCS inside a different VCS.
840
842
return "" , nil , fmt .Errorf ("directory %q uses %s, but parent %q uses %s" ,
841
843
repoDir , vcsCmd .Cmd , dir , vcs .Cmd )
@@ -855,23 +857,22 @@ func FromDir(dir, srcRoot string, allowNesting bool) (repoDir string, vcsCmd *Cm
855
857
return repoDir , vcsCmd , nil
856
858
}
857
859
858
- // statAny provides FileInfo for the first filename found in the directory.
859
- // Otherwise, it returns the last error seen.
860
- func statAny (dir string , filenames []string ) (os.FileInfo , error ) {
861
- if len (filenames ) == 0 {
862
- return nil , errors .New ("invalid argument: no filenames provided" )
863
- }
864
-
865
- var err error
866
- var fi os.FileInfo
867
- for _ , name := range filenames {
868
- fi , err = os .Stat (filepath .Join (dir , name ))
869
- if err == nil {
870
- return fi , nil
860
+ // isVCSRoot identifies a VCS root by checking whether the directory contains
861
+ // any of the listed root names.
862
+ func isVCSRoot (dir string , rootNames []rootName ) bool {
863
+ for _ , root := range rootNames {
864
+ fi , err := os .Stat (filepath .Join (dir , root .filename ))
865
+ if err == nil && fi .IsDir () == root .isDir {
866
+ return true
871
867
}
872
868
}
873
869
874
- return nil , err
870
+ return false
871
+ }
872
+
873
+ type rootName struct {
874
+ filename string
875
+ isDir bool
875
876
}
876
877
877
878
type vcsNotFoundError struct {
@@ -1031,15 +1032,11 @@ func CheckNested(vcs *Cmd, dir, srcRoot string) error {
1031
1032
otherDir := dir
1032
1033
for len (otherDir ) > len (srcRoot ) {
1033
1034
for _ , otherVCS := range vcsList {
1034
- if _ , err := statAny (otherDir , otherVCS .RootNames ); err == nil {
1035
+ if isVCSRoot (otherDir , otherVCS .RootNames ) {
1035
1036
// Allow expected vcs in original dir.
1036
1037
if otherDir == dir && otherVCS == vcs {
1037
1038
continue
1038
1039
}
1039
- // Allow .git inside .git, which can arise due to submodules.
1040
- if otherVCS == vcs && vcs .Cmd == "git" {
1041
- continue
1042
- }
1043
1040
// Otherwise, we have one VCS inside a different VCS.
1044
1041
return fmt .Errorf ("directory %q uses %s, but parent %q uses %s" , dir , vcs .Cmd , otherDir , otherVCS .Cmd )
1045
1042
}
0 commit comments