Skip to content
This repository was archived by the owner on Sep 9, 2020. It is now read-only.

Commit 68b3f93

Browse files
authored
Merge pull request #1549 from zkry/dep-status-f-doc-and-string-display
Dep status -f doc and string display
2 parents afd48a0 + a3d5085 commit 68b3f93

File tree

2 files changed

+117
-22
lines changed

2 files changed

+117
-22
lines changed

cmd/dep/status.go

Lines changed: 54 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,23 @@ import (
99
"encoding/json"
1010
"flag"
1111
"fmt"
12-
"html/template"
1312
"io"
1413
"io/ioutil"
1514
"log"
1615
"sort"
16+
"strings"
1717
"sync"
1818
"text/tabwriter"
19+
"text/template"
1920

2021
"github.com/golang/dep"
2122
"github.com/golang/dep/gps"
2223
"github.com/golang/dep/gps/paths"
2324
"github.com/pkg/errors"
2425
)
2526

27+
const availableTemplateVariables = "ProjectRoot, Constraint, Version, Revision, Latest, and PackageCount."
28+
2629
const statusShortHelp = `Report the status of the project's dependencies`
2730
const statusLongHelp = `
2831
With no arguments, print the status of each dependency of the project.
@@ -34,9 +37,43 @@ With no arguments, print the status of each dependency of the project.
3437
LATEST Latest VCS revision available
3538
PKGS USED Number of packages from this project that are actually used
3639
40+
You may use the -f flag to create a custom format for the output of the
41+
dep status command. The available fields you can utilize are as follows:
42+
` + availableTemplateVariables + `
43+
3744
Status returns exit code zero if all dependencies are in a "good state".
3845
`
3946

47+
const statusExamples = `
48+
dep status
49+
50+
Displays a table of the various dependencies in the project along with
51+
their properties such as the constraints they are bound by and the
52+
revision they are at.
53+
54+
dep status -f='{{if eq .Constraint "master"}}{{.ProjectRoot}} {{end}}'
55+
56+
Display the list of package names constrained on the master branch.
57+
The -f flag allows you to use Go templates along with it's various
58+
constructs for formating the output data. Available flags are as follows:
59+
` + availableTemplateVariables + `
60+
61+
dep status -json
62+
63+
Displays the dependency information in JSON format as a list of
64+
project objects. Each project object contains keys which correspond
65+
to the table column names from the standard 'dep status' command.
66+
67+
Linux: dep status -dot | dot -T png | display
68+
MacOS: dep status -dot | dot -T png | open -f -a /Applications/Preview.app
69+
Windows: dep status -dot | dot -T png -o status.png; start status.png
70+
71+
Generate a visual representation of the dependency tree using GraphViz.
72+
(Note: in order for this example to work you must first have graphviz
73+
installed on your system)
74+
75+
`
76+
4077
const (
4178
shortRev uint8 = iota
4279
longRev
@@ -56,6 +93,7 @@ func (cmd *statusCommand) LongHelp() string { return statusLongHelp }
5693
func (cmd *statusCommand) Hidden() bool { return false }
5794

5895
func (cmd *statusCommand) Register(fs *flag.FlagSet) {
96+
fs.BoolVar(&cmd.examples, "examples", false, "print detailed usage examples")
5997
fs.BoolVar(&cmd.json, "json", false, "output in JSON format")
6098
fs.StringVar(&cmd.template, "f", "", "output in text/template format")
6199
fs.BoolVar(&cmd.dot, "dot", false, "output the dependency graph in GraphViz format")
@@ -64,6 +102,7 @@ func (cmd *statusCommand) Register(fs *flag.FlagSet) {
64102
}
65103

66104
type statusCommand struct {
105+
examples bool
67106
json bool
68107
template string
69108
output string
@@ -200,7 +239,15 @@ func (out *templateOutput) BasicHeader() error { return nil }
200239
func (out *templateOutput) BasicFooter() error { return nil }
201240

202241
func (out *templateOutput) BasicLine(bs *BasicStatus) error {
203-
return out.tmpl.Execute(out.w, bs)
242+
data := rawStatus{
243+
ProjectRoot: bs.ProjectRoot,
244+
Constraint: bs.getConsolidatedConstraint(),
245+
Version: bs.getConsolidatedVersion(),
246+
Revision: bs.Revision.String(),
247+
Latest: bs.getConsolidatedLatest(shortRev),
248+
PackageCount: bs.PackageCount,
249+
}
250+
return out.tmpl.Execute(out.w, data)
204251
}
205252

206253
func (out *templateOutput) MissingHeader() error { return nil }
@@ -211,6 +258,11 @@ func (out *templateOutput) MissingLine(ms *MissingStatus) error {
211258
}
212259

213260
func (cmd *statusCommand) Run(ctx *dep.Ctx, args []string) error {
261+
if cmd.examples {
262+
ctx.Err.Println(strings.TrimSpace(statusExamples))
263+
return nil
264+
}
265+
214266
if err := cmd.validateFlags(); err != nil {
215267
return err
216268
}

cmd/dep/status_test.go

Lines changed: 63 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"strings"
1414
"testing"
1515
"text/tabwriter"
16+
"text/template"
1617

1718
"github.com/golang/dep"
1819
"github.com/golang/dep/gps"
@@ -41,31 +42,40 @@ func TestBasicLine(t *testing.T) {
4142
project := dep.Project{}
4243
aSemverConstraint, _ := gps.NewSemverConstraint("1.2.3")
4344

45+
templateString := "PR:{{.ProjectRoot}}, Const:{{.Constraint}}, Ver:{{.Version}}, Rev:{{.Revision}}, Lat:{{.Latest}}, PkgCt:{{.PackageCount}}"
46+
equalityTestTemplate := `{{if eq .Constraint "1.2.3"}}Constraint is 1.2.3{{end}}|{{if eq .Version "flooboo"}}Version is flooboo{{end}}|{{if eq .Latest "unknown"}}Latest is unknown{{end}}`
47+
4448
tests := []struct {
45-
name string
46-
status BasicStatus
47-
wantDotStatus []string
48-
wantJSONStatus []string
49-
wantTableStatus []string
49+
name string
50+
status BasicStatus
51+
wantDotStatus []string
52+
wantJSONStatus []string
53+
wantTableStatus []string
54+
wantTemplateStatus []string
55+
wantEqTemplateStatus []string
5056
}{
5157
{
5258
name: "BasicStatus with ProjectRoot only",
5359
status: BasicStatus{
5460
ProjectRoot: "github.com/foo/bar",
5561
},
56-
wantDotStatus: []string{`[label="github.com/foo/bar"];`},
57-
wantJSONStatus: []string{`"Version":""`, `"Revision":""`},
58-
wantTableStatus: []string{`github.com/foo/bar 0`},
62+
wantDotStatus: []string{`[label="github.com/foo/bar"];`},
63+
wantJSONStatus: []string{`"Version":""`, `"Revision":""`},
64+
wantTableStatus: []string{`github.com/foo/bar 0`},
65+
wantTemplateStatus: []string{`PR:github.com/foo/bar, Const:, Ver:, Rev:, Lat:, PkgCt:0`},
66+
wantEqTemplateStatus: []string{`||`},
5967
},
6068
{
6169
name: "BasicStatus with Revision",
6270
status: BasicStatus{
6371
ProjectRoot: "github.com/foo/bar",
6472
Revision: gps.Revision("flooboofoobooo"),
6573
},
66-
wantDotStatus: []string{`[label="github.com/foo/bar\nflooboo"];`},
67-
wantJSONStatus: []string{`"Version":""`, `"Revision":"flooboofoobooo"`, `"Constraint":""`},
68-
wantTableStatus: []string{`github.com/foo/bar flooboo 0`},
74+
wantDotStatus: []string{`[label="github.com/foo/bar\nflooboo"];`},
75+
wantJSONStatus: []string{`"Version":""`, `"Revision":"flooboofoobooo"`, `"Constraint":""`},
76+
wantTableStatus: []string{`github.com/foo/bar flooboo 0`},
77+
wantTemplateStatus: []string{`PR:github.com/foo/bar, Const:, Ver:flooboo, Rev:flooboofoobooo, Lat:, PkgCt:0`},
78+
wantEqTemplateStatus: []string{`|Version is flooboo|`},
6979
},
7080
{
7181
name: "BasicStatus with Version and Revision",
@@ -74,9 +84,11 @@ func TestBasicLine(t *testing.T) {
7484
Version: gps.NewVersion("1.0.0"),
7585
Revision: gps.Revision("flooboofoobooo"),
7686
},
77-
wantDotStatus: []string{`[label="github.com/foo/bar\n1.0.0"];`},
78-
wantJSONStatus: []string{`"Version":"1.0.0"`, `"Revision":"flooboofoobooo"`, `"Constraint":""`},
79-
wantTableStatus: []string{`github.com/foo/bar 1.0.0 flooboo 0`},
87+
wantDotStatus: []string{`[label="github.com/foo/bar\n1.0.0"];`},
88+
wantJSONStatus: []string{`"Version":"1.0.0"`, `"Revision":"flooboofoobooo"`, `"Constraint":""`},
89+
wantTableStatus: []string{`github.com/foo/bar 1.0.0 flooboo 0`},
90+
wantTemplateStatus: []string{`PR:github.com/foo/bar, Const:, Ver:1.0.0, Rev:flooboofoobooo, Lat:, PkgCt:0`},
91+
wantEqTemplateStatus: []string{`||`},
8092
},
8193
{
8294
name: "BasicStatus with Constraint, Version and Revision",
@@ -86,19 +98,23 @@ func TestBasicLine(t *testing.T) {
8698
Version: gps.NewVersion("1.0.0"),
8799
Revision: gps.Revision("revxyz"),
88100
},
89-
wantDotStatus: []string{`[label="github.com/foo/bar\n1.0.0"];`},
90-
wantJSONStatus: []string{`"Revision":"revxyz"`, `"Constraint":"1.2.3"`, `"Version":"1.0.0"`},
91-
wantTableStatus: []string{`github.com/foo/bar 1.2.3 1.0.0 revxyz 0`},
101+
wantDotStatus: []string{`[label="github.com/foo/bar\n1.0.0"];`},
102+
wantJSONStatus: []string{`"Revision":"revxyz"`, `"Constraint":"1.2.3"`, `"Version":"1.0.0"`},
103+
wantTableStatus: []string{`github.com/foo/bar 1.2.3 1.0.0 revxyz 0`},
104+
wantTemplateStatus: []string{`PR:github.com/foo/bar, Const:1.2.3, Ver:1.0.0, Rev:revxyz, Lat:, PkgCt:0`},
105+
wantEqTemplateStatus: []string{`Constraint is 1.2.3||`},
92106
},
93107
{
94108
name: "BasicStatus with update error",
95109
status: BasicStatus{
96110
ProjectRoot: "github.com/foo/bar",
97111
hasError: true,
98112
},
99-
wantDotStatus: []string{`[label="github.com/foo/bar"];`},
100-
wantJSONStatus: []string{`"Version":""`, `"Revision":""`, `"Latest":"unknown"`},
101-
wantTableStatus: []string{`github.com/foo/bar unknown 0`},
113+
wantDotStatus: []string{`[label="github.com/foo/bar"];`},
114+
wantJSONStatus: []string{`"Version":""`, `"Revision":""`, `"Latest":"unknown"`},
115+
wantTableStatus: []string{`github.com/foo/bar unknown 0`},
116+
wantTemplateStatus: []string{`PR:github.com/foo/bar, Const:, Ver:, Rev:, Lat:unknown, PkgCt:0`},
117+
wantEqTemplateStatus: []string{`||Latest is unknown`},
102118
},
103119
}
104120

@@ -149,6 +165,33 @@ func TestBasicLine(t *testing.T) {
149165
t.Errorf("Did not find expected Table status: \n\t(GOT) %v \n\t(WNT) %v", buf.String(), wantStatus)
150166
}
151167
}
168+
169+
buf.Reset()
170+
template, _ := template.New("status").Parse(templateString)
171+
templateout := &templateOutput{w: &buf, tmpl: template}
172+
templateout.BasicHeader()
173+
templateout.BasicLine(&test.status)
174+
templateout.BasicFooter()
175+
176+
for _, wantStatus := range test.wantTemplateStatus {
177+
if ok := strings.Contains(buf.String(), wantStatus); !ok {
178+
t.Errorf("Did not find expected template status: \n\t(GOT) %v \n\t(WNT) %v", buf.String(), wantStatus)
179+
}
180+
}
181+
182+
// The following test is to ensure that certain fields usable with string operations such as .eq
183+
buf.Reset()
184+
template, _ = template.New("status").Parse(equalityTestTemplate)
185+
templateout = &templateOutput{w: &buf, tmpl: template}
186+
templateout.BasicHeader()
187+
templateout.BasicLine(&test.status)
188+
templateout.BasicFooter()
189+
190+
for _, wantStatus := range test.wantEqTemplateStatus {
191+
if ok := strings.Contains(buf.String(), wantStatus); !ok {
192+
t.Errorf("Did not find expected template status: \n\t(GOT) %v \n\t(WNT) %v", buf.String(), wantStatus)
193+
}
194+
}
152195
})
153196
}
154197
}

0 commit comments

Comments
 (0)