Skip to content

Commit 0005047

Browse files
authored
Merge pull request golang#8 from sdboyer/status
Preliminary status command
2 parents e9418a0 + a398ded commit 0005047

File tree

8 files changed

+372
-72
lines changed

8 files changed

+372
-72
lines changed

analyzer.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Copyright 2016 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package main
6+
7+
import (
8+
"github.com/Masterminds/semver"
9+
"github.com/sdboyer/gps"
10+
)
11+
12+
type analyzer struct{}
13+
14+
func (a analyzer) DeriveManifestAndLock(path string, n gps.ProjectRoot) (gps.Manifest, gps.Lock, error) {
15+
// TODO initial impl would just be looking for our own manifest and lock
16+
return nil, nil, nil
17+
}
18+
19+
func (a analyzer) Info() (name string, version *semver.Version) {
20+
v, _ := semver.NewVersion("v0.0.1")
21+
return "example-analyzer", v
22+
}

lock.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import (
1313
"github.com/sdboyer/gps"
1414
)
1515

16-
type Lock struct {
16+
type lock struct {
1717
Memo []byte
1818
P []gps.LockedProject
1919
}
@@ -32,7 +32,7 @@ type lockedDep struct {
3232
Packages []string `json:"packages"`
3333
}
3434

35-
func ReadLock(r io.Reader) (*Lock, error) {
35+
func readLock(r io.Reader) (*lock, error) {
3636
rl := rawLock{}
3737
err := json.NewDecoder(r).Decode(&rl)
3838
if err != nil {
@@ -43,7 +43,7 @@ func ReadLock(r io.Reader) (*Lock, error) {
4343
if err != nil {
4444
return nil, fmt.Errorf("invalid hash digest in lock's memo field")
4545
}
46-
l := &Lock{
46+
l := &lock{
4747
Memo: b,
4848
P: make([]gps.LockedProject, len(rl.P)),
4949
}
@@ -75,10 +75,10 @@ func ReadLock(r io.Reader) (*Lock, error) {
7575
return l, nil
7676
}
7777

78-
func (l *Lock) InputHash() []byte {
78+
func (l *lock) InputHash() []byte {
7979
return l.Memo
8080
}
8181

82-
func (l *Lock) Projects() []gps.LockedProject {
82+
func (l *lock) Projects() []gps.LockedProject {
8383
return l.P
8484
}

lock_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,20 +38,20 @@ func TestReadLock(t *testing.T) {
3838
]
3939
}`
4040

41-
_, err := ReadLock(strings.NewReader(le))
41+
_, err := readLock(strings.NewReader(le))
4242
if err == nil {
4343
t.Error("Reading lock with invalid props should have caused error, but did not")
4444
} else if !strings.Contains(err.Error(), "both a branch") {
4545
t.Errorf("Unexpected error %q; expected multiple version error", err)
4646
}
4747

48-
l, err := ReadLock(strings.NewReader(lg))
48+
l, err := readLock(strings.NewReader(lg))
4949
if err != nil {
5050
t.Fatalf("Should have read Lock correctly, but got err %q", err)
5151
}
5252

5353
b, _ := hex.DecodeString("2252a285ab27944a4d7adcba8dbd03980f59ba652f12db39fa93b927c345593e")
54-
l2 := &Lock{
54+
l2 := &lock{
5555
Memo: b,
5656
P: []gps.LockedProject{
5757
gps.NewLockedProject(

main.go

Lines changed: 88 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,13 @@ import (
99
"fmt"
1010
"os"
1111
"path/filepath"
12+
"strings"
13+
14+
"github.com/sdboyer/gps"
1215
)
1316

14-
const ManifestName = "manifest.json"
15-
const LockName = "lock.json"
17+
const manifestName = "manifest.json"
18+
const lockName = "lock.json"
1619

1720
func main() {
1821
flag.Parse()
@@ -106,7 +109,7 @@ var initCmd = &command{
106109
Write Manifest file in the root of the project directory.
107110
`,
108111
long: `
109-
Populates Manifest file with current deps of this project.
112+
Populates Manifest file with current deps of this project.
110113
The specified version of each dependent repository is the version
111114
available in the user's workspaces (as specified by GOPATH).
112115
If the dependency is not present in any workspaces it is not be
@@ -116,57 +119,6 @@ var initCmd = &command{
116119
`,
117120
}
118121

119-
var statusCmd = &command{
120-
fn: noop,
121-
name: "status",
122-
short: `[flags] [packages]
123-
Report the status of the current project's dependencies.
124-
`,
125-
long: `
126-
If no packages are specified, for each dependency:
127-
- root import path
128-
- (if present in lock) the currently selected version
129-
- (else) that it's missing from the lock
130-
- whether it's present in the vendor directory (or if it's in
131-
workspace, if that's a thing?)
132-
- the current aggregate constraints on that project (as specified by
133-
the Manifest)
134-
- if -u is specified, whether there are newer versions of this
135-
dependency
136-
- VCS state (uncommitted changes? pruned?)
137-
138-
If packages are specified, or if -a is specified,
139-
for each of those dependencies:
140-
- (if present in lock) the currently selected version
141-
- (else) that it's missing from the lock
142-
- whether it's present in the vendor directory
143-
- The set of possible versions for that project
144-
- The upstream source URL(s) from which the project may be retrieved
145-
- The type of upstream source (git, hg, bzr, svn, registry)
146-
- Other versions that might work, given the current constraints
147-
- The list of all projects that import the project within the current
148-
depgraph
149-
- The current constraint. If more than one project constrains it, both
150-
the aggregate and the individual components (and which project provides
151-
that constraint) are printed
152-
- License information
153-
- Package source location, if fetched from an alternate location
154-
155-
Flags:
156-
-json Output in json format
157-
-f [template] Output in text/template format
158-
159-
-old Only show out of date packages and the current version
160-
-missing Only show missing packages.
161-
-unused Only show unused packages.
162-
-modified Only show modified packages.
163-
164-
-dot Export dependency graph in GraphViz format
165-
166-
The exit code of status is zero if all repositories are in a "good state".
167-
`,
168-
}
169-
170122
var getCmd = &command{
171123
fn: noop,
172124
name: "get",
@@ -179,7 +131,7 @@ var getCmd = &command{
179131
-x dry run
180132
-f force the given package to be updated to the specified
181133
version
182-
134+
183135
Package specs:
184136
<path>[@<version specifier>]
185137
@@ -203,7 +155,7 @@ func findProjectRoot(from string) (string, error) {
203155
var f func(string) (string, error)
204156
f = func(dir string) (string, error) {
205157

206-
fullpath := filepath.Join(dir, ManifestName)
158+
fullpath := filepath.Join(dir, manifestName)
207159

208160
if _, err := os.Stat(fullpath); err == nil {
209161
return dir, nil
@@ -228,3 +180,83 @@ func findProjectRoot(from string) (string, error) {
228180
}
229181
return path, nil
230182
}
183+
184+
type project struct {
185+
// absroot is the absolute path to the root directory of the project.
186+
absroot string
187+
// importroot is the import path of the project's root directory.
188+
importroot gps.ProjectRoot
189+
m *manifest
190+
l *lock
191+
}
192+
193+
// loadProject searches for a project root from the provided path, then loads
194+
// the manifest and lock (if any) it finds there.
195+
//
196+
// If the provided path is empty, it will search from the path indicated by
197+
// os.Getwd().
198+
func loadProject(path string) (*project, error) {
199+
var err error
200+
p := new(project)
201+
202+
switch path {
203+
case "":
204+
p.absroot, err = findProjectRootFromWD()
205+
default:
206+
p.absroot, err = findProjectRoot(path)
207+
}
208+
209+
if err != nil {
210+
return p, err
211+
}
212+
213+
gopath := os.Getenv("GOPATH")
214+
var match bool
215+
for _, gp := range filepath.SplitList(gopath) {
216+
srcprefix := filepath.Join(gp, "src") + string(filepath.Separator)
217+
if strings.HasPrefix(p.absroot, srcprefix) {
218+
gopath = gp
219+
match = true
220+
// filepath.ToSlash because we're dealing with an import path now,
221+
// not an fs path
222+
p.importroot = gps.ProjectRoot(filepath.ToSlash(strings.TrimPrefix(p.absroot, srcprefix)))
223+
break
224+
}
225+
}
226+
if !match {
227+
return nil, fmt.Errorf("could not determine project root - not on GOPATH")
228+
}
229+
230+
mp := filepath.Join(path, manifestName)
231+
mf, err := os.Open(mp)
232+
if err != nil {
233+
// Should be impossible at this point for the manifest file not to
234+
// exist, so this is some other kind of err
235+
return nil, fmt.Errorf("could not open %s: %s", mp, err)
236+
}
237+
defer mf.Close()
238+
239+
p.m, err = readManifest(mf)
240+
if err != nil {
241+
return nil, fmt.Errorf("error while parsing %s: %s", mp, err)
242+
}
243+
244+
lp := filepath.Join(path, lockName)
245+
lf, err := os.Open(lp)
246+
if err != nil {
247+
if os.IsNotExist(err) {
248+
// It's fine for the lock not to exist
249+
return p, nil
250+
}
251+
// But if a lock does exist and we can't open it, that's a problem
252+
return nil, fmt.Errorf("could not open %s: %s", lp, err)
253+
}
254+
255+
defer lf.Close()
256+
p.l, err = readLock(lf)
257+
if err != nil {
258+
return nil, fmt.Errorf("error while parsing %s: %s", lp, err)
259+
}
260+
261+
return p, nil
262+
}

main_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ func TestFindRoot(t *testing.T) {
3535
t.Errorf("findProjectRoot on nonexistent subdir should still work and give %s, got %s", expect, got3)
3636
}
3737

38-
got4, err := findProjectRoot(filepath.Join(expect, ManifestName))
38+
got4, err := findProjectRoot(filepath.Join(expect, manifestName))
3939
if err == nil {
4040
t.Errorf("Should have err'd when trying subdir of file, but returned %s", got4)
4141
}

manifest.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import (
1212
"github.com/sdboyer/gps"
1313
)
1414

15-
type Manifest struct {
15+
type manifest struct {
1616
Dependencies gps.ProjectConstraints
1717
Ovr gps.ProjectConstraints
1818
Ignores []string
@@ -31,14 +31,14 @@ type possibleProps struct {
3131
NetworkName string `json:"network_name"`
3232
}
3333

34-
func ReadManifest(r io.Reader) (*Manifest, error) {
34+
func readManifest(r io.Reader) (*manifest, error) {
3535
rm := rawManifest{}
3636
err := json.NewDecoder(r).Decode(&rm)
3737
if err != nil {
3838
return nil, err
3939
}
4040

41-
m := &Manifest{
41+
m := &manifest{
4242
Dependencies: make(gps.ProjectConstraints, len(rm.Dependencies)),
4343
Ovr: make(gps.ProjectConstraints, len(rm.Overrides)),
4444
Ignores: rm.Ignores,
@@ -90,20 +90,20 @@ func toProps(n string, p possibleProps) (pp gps.ProjectProperties, err error) {
9090
return pp, nil
9191
}
9292

93-
func (m *Manifest) DependencyConstraints() gps.ProjectConstraints {
93+
func (m *manifest) DependencyConstraints() gps.ProjectConstraints {
9494
return m.Dependencies
9595
}
9696

97-
func (m *Manifest) TestDependencyConstraints() gps.ProjectConstraints {
97+
func (m *manifest) TestDependencyConstraints() gps.ProjectConstraints {
9898
// TODO decide whether we're going to incorporate this or not
9999
return nil
100100
}
101101

102-
func (m *Manifest) Overrides() gps.ProjectConstraints {
102+
func (m *manifest) Overrides() gps.ProjectConstraints {
103103
return m.Ovr
104104
}
105105

106-
func (m *Manifest) IgnorePackages() map[string]bool {
106+
func (m *manifest) IgnorePackages() map[string]bool {
107107
if len(m.Ignores) == 0 {
108108
return nil
109109
}

sm.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Copyright 2016 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package main
6+
7+
import (
8+
"fmt"
9+
"os"
10+
"path/filepath"
11+
12+
"github.com/sdboyer/gps"
13+
)
14+
15+
func getSourceManager() (*gps.SourceMgr, error) {
16+
gopath := os.Getenv("GOPATH")
17+
if gopath == "" {
18+
return nil, fmt.Errorf("GOPATH is not set")
19+
}
20+
// Use the first entry in GOPATH for the depcache
21+
first := filepath.SplitList(gopath)[0]
22+
23+
return gps.NewSourceManager(analyzer{}, filepath.Join(first, "depcache"))
24+
}

0 commit comments

Comments
 (0)