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

Commit

Permalink
Merge pull request #1549 from zkry/dep-status-f-doc-and-string-display
Browse files Browse the repository at this point in the history
Dep status -f doc and string display
  • Loading branch information
darkowlzz authored Mar 4, 2018
2 parents afd48a0 + a3d5085 commit 68b3f93
Show file tree
Hide file tree
Showing 2 changed files with 117 additions and 22 deletions.
56 changes: 54 additions & 2 deletions cmd/dep/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,23 @@ import (
"encoding/json"
"flag"
"fmt"
"html/template"
"io"
"io/ioutil"
"log"
"sort"
"strings"
"sync"
"text/tabwriter"
"text/template"

"github.com/golang/dep"
"github.com/golang/dep/gps"
"github.com/golang/dep/gps/paths"
"github.com/pkg/errors"
)

const availableTemplateVariables = "ProjectRoot, Constraint, Version, Revision, Latest, and PackageCount."

const statusShortHelp = `Report the status of the project's dependencies`
const statusLongHelp = `
With no arguments, print the status of each dependency of the project.
Expand All @@ -34,9 +37,43 @@ With no arguments, print the status of each dependency of the project.
LATEST Latest VCS revision available
PKGS USED Number of packages from this project that are actually used
You may use the -f flag to create a custom format for the output of the
dep status command. The available fields you can utilize are as follows:
` + availableTemplateVariables + `
Status returns exit code zero if all dependencies are in a "good state".
`

const statusExamples = `
dep status
Displays a table of the various dependencies in the project along with
their properties such as the constraints they are bound by and the
revision they are at.
dep status -f='{{if eq .Constraint "master"}}{{.ProjectRoot}} {{end}}'
Display the list of package names constrained on the master branch.
The -f flag allows you to use Go templates along with it's various
constructs for formating the output data. Available flags are as follows:
` + availableTemplateVariables + `
dep status -json
Displays the dependency information in JSON format as a list of
project objects. Each project object contains keys which correspond
to the table column names from the standard 'dep status' command.
Linux: dep status -dot | dot -T png | display
MacOS: dep status -dot | dot -T png | open -f -a /Applications/Preview.app
Windows: dep status -dot | dot -T png -o status.png; start status.png
Generate a visual representation of the dependency tree using GraphViz.
(Note: in order for this example to work you must first have graphviz
installed on your system)
`

const (
shortRev uint8 = iota
longRev
Expand All @@ -56,6 +93,7 @@ func (cmd *statusCommand) LongHelp() string { return statusLongHelp }
func (cmd *statusCommand) Hidden() bool { return false }

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

type statusCommand struct {
examples bool
json bool
template string
output string
Expand Down Expand Up @@ -200,7 +239,15 @@ func (out *templateOutput) BasicHeader() error { return nil }
func (out *templateOutput) BasicFooter() error { return nil }

func (out *templateOutput) BasicLine(bs *BasicStatus) error {
return out.tmpl.Execute(out.w, bs)
data := rawStatus{
ProjectRoot: bs.ProjectRoot,
Constraint: bs.getConsolidatedConstraint(),
Version: bs.getConsolidatedVersion(),
Revision: bs.Revision.String(),
Latest: bs.getConsolidatedLatest(shortRev),
PackageCount: bs.PackageCount,
}
return out.tmpl.Execute(out.w, data)
}

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

func (cmd *statusCommand) Run(ctx *dep.Ctx, args []string) error {
if cmd.examples {
ctx.Err.Println(strings.TrimSpace(statusExamples))
return nil
}

if err := cmd.validateFlags(); err != nil {
return err
}
Expand Down
83 changes: 63 additions & 20 deletions cmd/dep/status_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"strings"
"testing"
"text/tabwriter"
"text/template"

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

templateString := "PR:{{.ProjectRoot}}, Const:{{.Constraint}}, Ver:{{.Version}}, Rev:{{.Revision}}, Lat:{{.Latest}}, PkgCt:{{.PackageCount}}"
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}}`

tests := []struct {
name string
status BasicStatus
wantDotStatus []string
wantJSONStatus []string
wantTableStatus []string
name string
status BasicStatus
wantDotStatus []string
wantJSONStatus []string
wantTableStatus []string
wantTemplateStatus []string
wantEqTemplateStatus []string
}{
{
name: "BasicStatus with ProjectRoot only",
status: BasicStatus{
ProjectRoot: "github.com/foo/bar",
},
wantDotStatus: []string{`[label="github.com/foo/bar"];`},
wantJSONStatus: []string{`"Version":""`, `"Revision":""`},
wantTableStatus: []string{`github.com/foo/bar 0`},
wantDotStatus: []string{`[label="github.com/foo/bar"];`},
wantJSONStatus: []string{`"Version":""`, `"Revision":""`},
wantTableStatus: []string{`github.com/foo/bar 0`},
wantTemplateStatus: []string{`PR:github.com/foo/bar, Const:, Ver:, Rev:, Lat:, PkgCt:0`},
wantEqTemplateStatus: []string{`||`},
},
{
name: "BasicStatus with Revision",
status: BasicStatus{
ProjectRoot: "github.com/foo/bar",
Revision: gps.Revision("flooboofoobooo"),
},
wantDotStatus: []string{`[label="github.com/foo/bar\nflooboo"];`},
wantJSONStatus: []string{`"Version":""`, `"Revision":"flooboofoobooo"`, `"Constraint":""`},
wantTableStatus: []string{`github.com/foo/bar flooboo 0`},
wantDotStatus: []string{`[label="github.com/foo/bar\nflooboo"];`},
wantJSONStatus: []string{`"Version":""`, `"Revision":"flooboofoobooo"`, `"Constraint":""`},
wantTableStatus: []string{`github.com/foo/bar flooboo 0`},
wantTemplateStatus: []string{`PR:github.com/foo/bar, Const:, Ver:flooboo, Rev:flooboofoobooo, Lat:, PkgCt:0`},
wantEqTemplateStatus: []string{`|Version is flooboo|`},
},
{
name: "BasicStatus with Version and Revision",
Expand All @@ -74,9 +84,11 @@ func TestBasicLine(t *testing.T) {
Version: gps.NewVersion("1.0.0"),
Revision: gps.Revision("flooboofoobooo"),
},
wantDotStatus: []string{`[label="github.com/foo/bar\n1.0.0"];`},
wantJSONStatus: []string{`"Version":"1.0.0"`, `"Revision":"flooboofoobooo"`, `"Constraint":""`},
wantTableStatus: []string{`github.com/foo/bar 1.0.0 flooboo 0`},
wantDotStatus: []string{`[label="github.com/foo/bar\n1.0.0"];`},
wantJSONStatus: []string{`"Version":"1.0.0"`, `"Revision":"flooboofoobooo"`, `"Constraint":""`},
wantTableStatus: []string{`github.com/foo/bar 1.0.0 flooboo 0`},
wantTemplateStatus: []string{`PR:github.com/foo/bar, Const:, Ver:1.0.0, Rev:flooboofoobooo, Lat:, PkgCt:0`},
wantEqTemplateStatus: []string{`||`},
},
{
name: "BasicStatus with Constraint, Version and Revision",
Expand All @@ -86,19 +98,23 @@ func TestBasicLine(t *testing.T) {
Version: gps.NewVersion("1.0.0"),
Revision: gps.Revision("revxyz"),
},
wantDotStatus: []string{`[label="github.com/foo/bar\n1.0.0"];`},
wantJSONStatus: []string{`"Revision":"revxyz"`, `"Constraint":"1.2.3"`, `"Version":"1.0.0"`},
wantTableStatus: []string{`github.com/foo/bar 1.2.3 1.0.0 revxyz 0`},
wantDotStatus: []string{`[label="github.com/foo/bar\n1.0.0"];`},
wantJSONStatus: []string{`"Revision":"revxyz"`, `"Constraint":"1.2.3"`, `"Version":"1.0.0"`},
wantTableStatus: []string{`github.com/foo/bar 1.2.3 1.0.0 revxyz 0`},
wantTemplateStatus: []string{`PR:github.com/foo/bar, Const:1.2.3, Ver:1.0.0, Rev:revxyz, Lat:, PkgCt:0`},
wantEqTemplateStatus: []string{`Constraint is 1.2.3||`},
},
{
name: "BasicStatus with update error",
status: BasicStatus{
ProjectRoot: "github.com/foo/bar",
hasError: true,
},
wantDotStatus: []string{`[label="github.com/foo/bar"];`},
wantJSONStatus: []string{`"Version":""`, `"Revision":""`, `"Latest":"unknown"`},
wantTableStatus: []string{`github.com/foo/bar unknown 0`},
wantDotStatus: []string{`[label="github.com/foo/bar"];`},
wantJSONStatus: []string{`"Version":""`, `"Revision":""`, `"Latest":"unknown"`},
wantTableStatus: []string{`github.com/foo/bar unknown 0`},
wantTemplateStatus: []string{`PR:github.com/foo/bar, Const:, Ver:, Rev:, Lat:unknown, PkgCt:0`},
wantEqTemplateStatus: []string{`||Latest is unknown`},
},
}

Expand Down Expand Up @@ -149,6 +165,33 @@ func TestBasicLine(t *testing.T) {
t.Errorf("Did not find expected Table status: \n\t(GOT) %v \n\t(WNT) %v", buf.String(), wantStatus)
}
}

buf.Reset()
template, _ := template.New("status").Parse(templateString)
templateout := &templateOutput{w: &buf, tmpl: template}
templateout.BasicHeader()
templateout.BasicLine(&test.status)
templateout.BasicFooter()

for _, wantStatus := range test.wantTemplateStatus {
if ok := strings.Contains(buf.String(), wantStatus); !ok {
t.Errorf("Did not find expected template status: \n\t(GOT) %v \n\t(WNT) %v", buf.String(), wantStatus)
}
}

// The following test is to ensure that certain fields usable with string operations such as .eq
buf.Reset()
template, _ = template.New("status").Parse(equalityTestTemplate)
templateout = &templateOutput{w: &buf, tmpl: template}
templateout.BasicHeader()
templateout.BasicLine(&test.status)
templateout.BasicFooter()

for _, wantStatus := range test.wantEqTemplateStatus {
if ok := strings.Contains(buf.String(), wantStatus); !ok {
t.Errorf("Did not find expected template status: \n\t(GOT) %v \n\t(WNT) %v", buf.String(), wantStatus)
}
}
})
}
}
Expand Down

0 comments on commit 68b3f93

Please sign in to comment.