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 #1286 from jmank88/cmd_doc
Browse files Browse the repository at this point in the history
cmd/dep: generate package doc from help command
  • Loading branch information
sdboyer committed Nov 14, 2017
2 parents 80e94e8 + 4d6a8ae commit 4ecb1d1
Show file tree
Hide file tree
Showing 3 changed files with 245 additions and 23 deletions.
143 changes: 143 additions & 0 deletions cmd/dep/doc.go
Original file line number Diff line number Diff line change
@@ -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] [<spec>...]
//
// Project spec:
//
// <import path>[:alt source URL][@<constraint>]
//
//
// 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
114 changes: 91 additions & 23 deletions cmd/dep/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
Expand Down Expand Up @@ -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 <command>")
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.
Expand Down Expand Up @@ -170,7 +203,7 @@ func (c *Config) Run() int {
}

errLogger.Printf("dep: %s: no such command\n", cmdName)
usage()
usage(c.Stderr)
return errorExitCode
}

Expand Down Expand Up @@ -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]
Expand All @@ -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
}
11 changes: 11 additions & 0 deletions cmd/dep/mkdoc.sh
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit 4ecb1d1

Please sign in to comment.