@@ -8,17 +8,17 @@ import (
8
8
"archive/zip"
9
9
"bytes"
10
10
"context"
11
+ "errors"
11
12
"fmt"
12
13
"io"
13
14
"io/ioutil"
14
- "net/http"
15
15
"os"
16
16
"path/filepath"
17
17
"strings"
18
18
"time"
19
19
20
- "golang.org/x/mod/modfile"
21
20
"golang.org/x/pkgsite/internal/derrors"
21
+ "golang.org/x/pkgsite/internal/proxy"
22
22
"golang.org/x/pkgsite/internal/source"
23
23
)
24
24
@@ -29,96 +29,58 @@ var (
29
29
LocalCommitTime = time.Time {}
30
30
)
31
31
32
- // FetchLocalModule fetches a module from a local directory and process its contents
33
- // to return an internal.Module and other related information. modulePath is not necessary
34
- // if the module has a go.mod file, but if both exist, then they must match.
35
- // FetchResult.Error should be checked to verify that the fetch succeeded. Even if the
36
- // error is non-nil the result may contain useful data.
37
- func FetchLocalModule (ctx context.Context , modulePath , localPath string , sourceClient * source.Client ) * FetchResult {
38
- fr := & FetchResult {
39
- ModulePath : modulePath ,
40
- RequestedVersion : LocalVersion ,
41
- ResolvedVersion : LocalVersion ,
42
- Defer : func () {},
43
- }
44
-
45
- var fi * FetchInfo
46
- defer func () {
47
- if fr .Error != nil {
48
- derrors .Wrap (& fr .Error , "FetchLocalModule(%q, %q)" , modulePath , localPath )
49
- fr .Status = derrors .ToStatus (fr .Error )
50
- }
51
- if fr .Status == 0 {
52
- fr .Status = http .StatusOK
53
- }
54
- if fi != nil {
55
- finishFetchInfo (fi , fr .Status , fr .Error )
56
- }
57
- }()
32
+ // A directoryModuleGetter is a ModuleGetter whose source is a directory in the file system that contains
33
+ // a module's files.
34
+ type directoryModuleGetter struct {
35
+ dir string // the directory containing the module's files
36
+ }
58
37
59
- info , err := os .Stat (localPath )
60
- if err != nil {
61
- fr .Error = fmt .Errorf ("%s: %w" , err .Error (), derrors .NotFound )
62
- return fr
63
- }
38
+ // NewDirectoryModuleGetter returns a ModuleGetter for reading a module from a directory.
39
+ func NewDirectoryModuleGetter (dir string ) ModuleGetter {
40
+ return & directoryModuleGetter {dir : dir }
41
+ }
64
42
65
- if ! info .IsDir () {
66
- fr .Error = fmt .Errorf ("%s not a directory: %w" , localPath , derrors .NotFound )
67
- return fr
68
- }
43
+ // Info returns basic information about the module.
44
+ func (g * directoryModuleGetter ) Info (ctx context.Context , path , version string ) (* proxy.VersionInfo , error ) {
45
+ return & proxy.VersionInfo {
46
+ Version : LocalVersion ,
47
+ Time : LocalCommitTime ,
48
+ }, nil
49
+ }
69
50
70
- fi = & FetchInfo {
71
- ModulePath : fr .ModulePath ,
72
- Version : fr .ResolvedVersion ,
73
- Start : time .Now (),
74
- }
75
- startFetchInfo (fi )
76
-
77
- // Options for module path are either the modulePath parameter or go.mod file.
78
- // Accepted cases:
79
- // - Both are given and are the same.
80
- // - Only one is given. Note that: if modulePath is given and there's no go.mod
81
- // file, then the package is assumed to be using GOPATH.
82
- // Errors:
83
- // - Both are given and are different.
84
- // - Neither is given.
85
- if goModBytes , err := ioutil .ReadFile (filepath .Join (localPath , "go.mod" )); err != nil {
86
- fr .GoModPath = modulePath
87
- fr .HasGoMod = false
88
- } else {
89
- fr .HasGoMod = true
90
- fr .GoModPath = modfile .ModulePath (goModBytes )
91
- if fr .GoModPath != modulePath && modulePath != "" {
92
- fr .Error = fmt .Errorf ("module path=%s, go.mod path=%s: %w" , modulePath , fr .GoModPath , derrors .AlternativeModule )
93
- return fr
51
+ // Mod returns the contents of the module's go.mod file.
52
+ // If the file does not exist, it returns a synthesized one.
53
+ func (g * directoryModuleGetter ) Mod (ctx context.Context , path , version string ) ([]byte , error ) {
54
+ data , err := ioutil .ReadFile (filepath .Join (g .dir , "go.mod" ))
55
+ if errors .Is (err , os .ErrNotExist ) {
56
+ if path == "" {
57
+ return nil , fmt .Errorf ("no module path: %w" , derrors .BadModule )
94
58
}
59
+ return []byte (fmt .Sprintf ("module %s\n " , path )), nil
95
60
}
61
+ return data , err
62
+ }
96
63
97
- if fr .GoModPath == "" {
98
- fr .Error = fmt .Errorf ("no module path: %w" , derrors .BadModule )
99
- return fr
100
- }
101
- fr .ModulePath = fr .GoModPath
64
+ // Zip returns a reader for the module's zip file.
65
+ func (g * directoryModuleGetter ) Zip (ctx context.Context , path , version string ) (* zip.Reader , error ) {
66
+ return createZipReader (g .dir , path , LocalVersion )
67
+ }
102
68
103
- zipReader , err := createZipReader (localPath , fr .GoModPath , LocalVersion )
104
- if err != nil {
105
- fr .Error = fmt .Errorf ("couldn't create a zip: %s, %w" , err .Error (), derrors .BadModule )
106
- return fr
107
- }
69
+ // ZipSize returns the approximate size of the zip file in bytes.
70
+ func (g * directoryModuleGetter ) ZipSize (ctx context.Context , path , version string ) (int64 , error ) {
71
+ return 0 , errors .New ("directoryModuleGetter.ZipSize unimplemented" )
72
+ }
108
73
109
- mod , pvs , err := processZipFile (ctx , fr .GoModPath , LocalVersion , LocalVersion , LocalCommitTime , zipReader , sourceClient )
110
- if err != nil {
111
- fr .Error = err
112
- return fr
113
- }
114
- mod .HasGoMod = fr .HasGoMod
115
- fr .Module = mod
116
- fr .PackageVersionStates = pvs
117
- fr .Module .SourceInfo = nil // version is not known, so even if info is found it most likely is wrong.
118
- for _ , state := range fr .PackageVersionStates {
119
- if state .Status != http .StatusOK {
120
- fr .Status = derrors .ToStatus (derrors .HasIncompletePackages )
121
- }
74
+ // FetchLocalModule fetches a module from a local directory and process its contents
75
+ // to return an internal.Module and other related information. modulePath is not necessary
76
+ // if the module has a go.mod file, but if both exist, then they must match.
77
+ // FetchResult.Error should be checked to verify that the fetch succeeded. Even if the
78
+ // error is non-nil the result may contain useful data.
79
+ func FetchLocalModule (ctx context.Context , modulePath , localPath string , sourceClient * source.Client ) * FetchResult {
80
+ g := NewDirectoryModuleGetter (localPath )
81
+ fr := FetchModule (ctx , modulePath , LocalVersion , g , sourceClient )
82
+ if fr .Error != nil {
83
+ fr .Error = fmt .Errorf ("FetchLocalModule(%q, %q): %w" , modulePath , localPath , fr .Error )
122
84
}
123
85
return fr
124
86
}
0 commit comments