diff --git a/cmd/dep/doc.go b/cmd/dep/doc.go new file mode 100644 index 0000000000..7d7e508872 --- /dev/null +++ b/cmd/dep/doc.go @@ -0,0 +1,143 @@ +// Copyright 2017 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// DO NOT EDIT THIS FILE. GENERATED BY mkdoc.sh. +// Edit the documentation in other files and rerun mkdoc.sh to generate this one. + +// Dep is a tool for managing dependencies for Go projects +// +// Usage: "dep [command]" +// +// Commands: +// +// init Initialize a new project with manifest and lock files +// status Report the status of the project's dependencies +// ensure Ensure a dependency is safely vendored in the project +// prune Prune the vendor tree of unused packages +// version Show the dep version information +// +// Examples: +// dep init set up a new project +// dep ensure install the project's dependencies +// dep ensure -update update the locked versions of all dependencies +// dep ensure -add github.com/pkg/errors add a dependency to the project +// +// Use "dep help [command]" for more information about a command. +// +// Initialize a new project with manifest and lock files +// +// Usage: +// +// init [root] +// +// Initialize the project at filepath root by parsing its dependencies, writing +// manifest and lock files, and vendoring the dependencies. If root isn't +// specified, use the current directory. +// +// When configuration for another dependency management tool is detected, it is +// imported into the initial manifest and lock. Use the -skip-tools flag to +// disable this behavior. The following external tools are supported: +// glide, godep, vndr, govend, gb, gvt. +// +// Any dependencies that are not constrained by external configuration use the +// GOPATH analysis below. +// +// By default, the dependencies are resolved over the network. A version will be +// selected from the versions available from the upstream source per the following +// algorithm: +// +// - Tags conforming to semver (sorted by semver rules) +// - Default branch(es) (sorted lexicographically) +// - Non-semver tags (sorted lexicographically) +// +// An alternate mode can be activated by passing -gopath. In this mode, the version +// of each dependency will reflect the current state of the GOPATH. If a dependency +// doesn't exist in the GOPATH, a version will be selected based on the above +// network version selection algorithm. +// +// A Gopkg.toml file will be written with inferred version constraints for all +// direct dependencies. Gopkg.lock will be written with precise versions, and +// vendor/ will be populated with the precise versions written to Gopkg.lock. +// +// +// Report the status of the project's dependencies +// +// Usage: +// +// status [package...] +// +// With no arguments, print the status of each dependency of the project. +// +// PROJECT Import path +// CONSTRAINT Version constraint, from the manifest +// VERSION Version chosen, from the lock +// REVISION VCS revision of the chosen version +// LATEST Latest VCS revision available +// PKGS USED Number of packages from this project that are actually used +// +// With one or more explicitly specified packages, or with the -detailed flag, +// print an extended status output for each dependency of the project. +// +// TODO Another column description +// FOOBAR Another column description +// +// Status returns exit code zero if all dependencies are in a "good state". +// +// +// Ensure a dependency is safely vendored in the project +// +// Usage: +// +// ensure [-update | -add] [-no-vendor | -vendor-only] [-dry-run] [...] +// +// Project spec: +// +// [:alt source URL][@] +// +// +// Ensure gets a project into a complete, reproducible, and likely compilable state: +// +// * All non-stdlib imports are fulfilled +// * All rules in Gopkg.toml are respected +// * Gopkg.lock records precise versions for all dependencies +// * vendor/ is populated according to Gopkg.lock +// +// Ensure has fast techniques to determine that some of these steps may be +// unnecessary. If that determination is made, ensure may skip some steps. Flags +// may be passed to bypass these checks; -vendor-only will allow an out-of-date +// Gopkg.lock to populate vendor/, and -no-vendor will update Gopkg.lock (if +// needed), but never touch vendor/. +// +// The effect of passing project spec arguments varies slightly depending on the +// combination of flags that are passed. +// +// +// Examples: +// +// dep ensure Populate vendor from existing Gopkg.toml and Gopkg.lock +// dep ensure -add github.com/pkg/foo Introduce a named dependency at its newest version +// dep ensure -add github.com/pkg/foo@^1.0.1 Introduce a named dependency with a particular constraint +// +// For more detailed usage examples, see dep ensure -examples. +// +// +// Prune the vendor tree of unused packages +// +// Usage: +// +// prune +// +// Prune is used to remove unused packages from your vendor tree. +// +// STABILITY NOTICE: this command creates problems for vendor/ verification. As +// such, it may be removed and/or moved out into a separate project later on. +// +// +// Show the dep version information +// +// Usage: +// +// version +// +package main diff --git a/cmd/dep/main.go b/cmd/dep/main.go index 77e635b816..aa29e0a589 100644 --- a/cmd/dep/main.go +++ b/cmd/dep/main.go @@ -2,7 +2,8 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// Command dep is a prototype dependency management tool. +//go:generate ./mkdoc.sh + package main import ( @@ -89,39 +90,71 @@ func (c *Config) Run() int { }, } - outLogger := log.New(c.Stdout, "", 0) - errLogger := log.New(c.Stderr, "", 0) - - usage := func() { - errLogger.Println("dep is a tool for managing dependencies for Go projects") - errLogger.Println() - errLogger.Println("Usage: dep ") - errLogger.Println() - errLogger.Println("Commands:") - errLogger.Println() - w := tabwriter.NewWriter(c.Stderr, 0, 0, 2, ' ', 0) + usage := func(w io.Writer) { + fmt.Fprintln(w, "Dep is a tool for managing dependencies for Go projects") + fmt.Fprintln(w) + fmt.Fprintln(w, "Usage: \"dep [command]\"") + fmt.Fprintln(w) + fmt.Fprintln(w, "Commands:") + fmt.Fprintln(w) + tw := tabwriter.NewWriter(w, 0, 0, 2, ' ', 0) for _, cmd := range commands { if !cmd.Hidden() { - fmt.Fprintf(w, "\t%s\t%s\n", cmd.Name(), cmd.ShortHelp()) + fmt.Fprintf(tw, "\t%s\t%s\n", cmd.Name(), cmd.ShortHelp()) } } - w.Flush() - errLogger.Println() - errLogger.Println("Examples:") + tw.Flush() + fmt.Fprintln(w) + fmt.Fprintln(w, "Examples:") for _, example := range examples { - fmt.Fprintf(w, "\t%s\t%s\n", example[0], example[1]) + fmt.Fprintf(tw, "\t%s\t%s\n", example[0], example[1]) } - w.Flush() - errLogger.Println() - errLogger.Println("Use \"dep help [command]\" for more information about a command.") + tw.Flush() + fmt.Fprintln(w) + fmt.Fprintln(w, "Use \"dep help [command]\" for more information about a command.") } cmdName, printCommandHelp, exit := parseArgs(c.Args) if exit { - usage() + usage(c.Stderr) return errorExitCode } + // 'dep help documentation' generates doc.go. + if printCommandHelp && cmdName == "documentation" { + fmt.Println("// Copyright 2017 The Go Authors. All rights reserved.") + fmt.Println("// Use of this source code is governed by a BSD-style") + fmt.Println("// license that can be found in the LICENSE file.") + fmt.Println() + fmt.Println("// DO NOT EDIT THIS FILE. GENERATED BY mkdoc.sh.") + fmt.Println("// Edit the documentation in other files and rerun mkdoc.sh to generate this one.") + fmt.Println() + + var cw io.Writer = &commentWriter{W: c.Stdout} + usage(cw) + for _, cmd := range commands { + if !cmd.Hidden() { + fmt.Fprintln(cw) + short := cmd.ShortHelp() + fmt.Fprintln(cw, short) + fmt.Fprintln(cw) + fmt.Fprintln(cw, "Usage:") + fmt.Fprintln(cw) + fmt.Fprintln(cw, "", cmd.Name(), cmd.Args()) + if long := cmd.LongHelp(); long != short { + fmt.Fprintln(cw, long) + } + } + } + + fmt.Println("//") + fmt.Println("package main") + return successExitCode + } + + outLogger := log.New(c.Stdout, "", 0) + errLogger := log.New(c.Stderr, "", 0) + for _, cmd := range commands { if cmd.Name() == cmdName { // Build flag set with global flags in there. @@ -170,7 +203,7 @@ func (c *Config) Run() int { } errLogger.Printf("dep: %s: no such command\n", cmdName) - usage() + usage(c.Stderr) return errorExitCode } @@ -217,8 +250,9 @@ func parseArgs(args []string) (cmdName string, printCmdUsage bool, exit bool) { case 2: if isHelpArg() { exit = true + } else { + cmdName = args[1] } - cmdName = args[1] default: if isHelpArg() { cmdName = args[2] @@ -244,3 +278,37 @@ func getEnv(env []string, key string) string { } return "" } + +// commentWriter writes a Go comment to the underlying io.Writer, +// using line comment form (//). +// +// Copied from cmd/go/internal/help/help.go. +type commentWriter struct { + W io.Writer + wroteSlashes bool // Wrote "//" at the beginning of the current line. +} + +func (c *commentWriter) Write(p []byte) (int, error) { + var n int + for i, b := range p { + if !c.wroteSlashes { + s := "//" + if b != '\n' { + s = "// " + } + if _, err := io.WriteString(c.W, s); err != nil { + return n, err + } + c.wroteSlashes = true + } + n0, err := c.W.Write(p[i : i+1]) + n += n0 + if err != nil { + return n, err + } + if b == '\n' { + c.wroteSlashes = false + } + } + return len(p), nil +} diff --git a/cmd/dep/mkdoc.sh b/cmd/dep/mkdoc.sh new file mode 100755 index 0000000000..c2e6941ff4 --- /dev/null +++ b/cmd/dep/mkdoc.sh @@ -0,0 +1,11 @@ +#!/bin/bash +# Copyright 2017 The Go Authors. All rights reserved. +# Use of this source code is governed by a BSD-style +# license that can be found in the LICENSE file. + +set -e + +go build -o dep.latest +./dep.latest help documentation >doc.go +gofmt -w doc.go +rm dep.latest