update docker.go
move to pkg
update docs
update name and copyright
change --sinceId to --since-id, update completion and docs
Docker-DCO-1.1-Signed-off-by: Victor Vieux <victor@docker.com> (github: vieux)
| ... | ... |
@@ -7,11 +7,11 @@ import ( |
| 7 | 7 |
"encoding/base64" |
| 8 | 8 |
"encoding/json" |
| 9 | 9 |
"errors" |
| 10 |
- "flag" |
|
| 11 | 10 |
"fmt" |
| 12 | 11 |
"github.com/dotcloud/docker/archive" |
| 13 | 12 |
"github.com/dotcloud/docker/auth" |
| 14 | 13 |
"github.com/dotcloud/docker/engine" |
| 14 |
+ flag "github.com/dotcloud/docker/pkg/mflag" |
|
| 15 | 15 |
"github.com/dotcloud/docker/pkg/term" |
| 16 | 16 |
"github.com/dotcloud/docker/registry" |
| 17 | 17 |
"github.com/dotcloud/docker/utils" |
| ... | ... |
@@ -164,10 +164,10 @@ func MkBuildContext(dockerfile string, files [][2]string) (archive.Archive, erro |
| 164 | 164 |
|
| 165 | 165 |
func (cli *DockerCli) CmdBuild(args ...string) error {
|
| 166 | 166 |
cmd := cli.Subcmd("build", "[OPTIONS] PATH | URL | -", "Build a new container image from the source code at PATH")
|
| 167 |
- tag := cmd.String("t", "", "Repository name (and optionally a tag) to be applied to the resulting image in case of success")
|
|
| 168 |
- suppressOutput := cmd.Bool("q", false, "Suppress verbose build output")
|
|
| 169 |
- noCache := cmd.Bool("no-cache", false, "Do not use cache when building the image")
|
|
| 170 |
- rm := cmd.Bool("rm", false, "Remove intermediate containers after a successful build")
|
|
| 167 |
+ tag := cmd.String([]string{"t", "-tag"}, "", "Repository name (and optionally a tag) to be applied to the resulting image in case of success")
|
|
| 168 |
+ suppressOutput := cmd.Bool([]string{"q", "-quiet"}, false, "Suppress verbose build output")
|
|
| 169 |
+ noCache := cmd.Bool([]string{"#no-cache", "-no-cache"}, false, "Do not use cache when building the image")
|
|
| 170 |
+ rm := cmd.Bool([]string{"#rm", "-rm"}, false, "Remove intermediate containers after a successful build")
|
|
| 171 | 171 |
if err := cmd.Parse(args); err != nil {
|
| 172 | 172 |
return nil |
| 173 | 173 |
} |
| ... | ... |
@@ -253,9 +253,9 @@ func (cli *DockerCli) CmdLogin(args ...string) error {
|
| 253 | 253 |
|
| 254 | 254 |
var username, password, email string |
| 255 | 255 |
|
| 256 |
- cmd.StringVar(&username, "u", "", "username") |
|
| 257 |
- cmd.StringVar(&password, "p", "", "password") |
|
| 258 |
- cmd.StringVar(&email, "e", "", "email") |
|
| 256 |
+ cmd.StringVar(&username, []string{"u", "-username"}, "", "username")
|
|
| 257 |
+ cmd.StringVar(&password, []string{"p", "-password"}, "", "password")
|
|
| 258 |
+ cmd.StringVar(&email, []string{"e", "-email"}, "", "email")
|
|
| 259 | 259 |
err := cmd.Parse(args) |
| 260 | 260 |
if err != nil {
|
| 261 | 261 |
return nil |
| ... | ... |
@@ -504,7 +504,7 @@ func (cli *DockerCli) CmdInfo(args ...string) error {
|
| 504 | 504 |
|
| 505 | 505 |
func (cli *DockerCli) CmdStop(args ...string) error {
|
| 506 | 506 |
cmd := cli.Subcmd("stop", "[OPTIONS] CONTAINER [CONTAINER...]", "Stop a running container (Send SIGTERM, and then SIGKILL after grace period)")
|
| 507 |
- nSeconds := cmd.Int("t", 10, "Number of seconds to wait for the container to stop before killing it.")
|
|
| 507 |
+ nSeconds := cmd.Int([]string{"t", "-time"}, 10, "Number of seconds to wait for the container to stop before killing it.")
|
|
| 508 | 508 |
if err := cmd.Parse(args); err != nil {
|
| 509 | 509 |
return nil |
| 510 | 510 |
} |
| ... | ... |
@@ -531,7 +531,7 @@ func (cli *DockerCli) CmdStop(args ...string) error {
|
| 531 | 531 |
|
| 532 | 532 |
func (cli *DockerCli) CmdRestart(args ...string) error {
|
| 533 | 533 |
cmd := cli.Subcmd("restart", "[OPTIONS] CONTAINER [CONTAINER...]", "Restart a running container")
|
| 534 |
- nSeconds := cmd.Int("t", 10, "Number of seconds to try to stop for before killing the container. Once killed it will then be restarted. Default=10")
|
|
| 534 |
+ nSeconds := cmd.Int([]string{"t", "-time"}, 10, "Number of seconds to try to stop for before killing the container. Once killed it will then be restarted. Default=10")
|
|
| 535 | 535 |
if err := cmd.Parse(args); err != nil {
|
| 536 | 536 |
return nil |
| 537 | 537 |
} |
| ... | ... |
@@ -574,8 +574,8 @@ func (cli *DockerCli) forwardAllSignals(cid string) chan os.Signal {
|
| 574 | 574 |
|
| 575 | 575 |
func (cli *DockerCli) CmdStart(args ...string) error {
|
| 576 | 576 |
cmd := cli.Subcmd("start", "CONTAINER [CONTAINER...]", "Restart a stopped container")
|
| 577 |
- attach := cmd.Bool("a", false, "Attach container's stdout/stderr and forward all signals to the process")
|
|
| 578 |
- openStdin := cmd.Bool("i", false, "Attach container's stdin")
|
|
| 577 |
+ attach := cmd.Bool([]string{"a", "-attach"}, false, "Attach container's stdout/stderr and forward all signals to the process")
|
|
| 578 |
+ openStdin := cmd.Bool([]string{"i", "-interactive"}, false, "Attach container's stdin")
|
|
| 579 | 579 |
if err := cmd.Parse(args); err != nil {
|
| 580 | 580 |
return nil |
| 581 | 581 |
} |
| ... | ... |
@@ -660,7 +660,7 @@ func (cli *DockerCli) CmdStart(args ...string) error {
|
| 660 | 660 |
|
| 661 | 661 |
func (cli *DockerCli) CmdInspect(args ...string) error {
|
| 662 | 662 |
cmd := cli.Subcmd("inspect", "CONTAINER|IMAGE [CONTAINER|IMAGE...]", "Return low-level information on a container/image")
|
| 663 |
- tmplStr := cmd.String("format", "", "Format the output using the given go template.")
|
|
| 663 |
+ tmplStr := cmd.String([]string{"f", "#format", "-format"}, "", "Format the output using the given go template.")
|
|
| 664 | 664 |
if err := cmd.Parse(args); err != nil {
|
| 665 | 665 |
return nil |
| 666 | 666 |
} |
| ... | ... |
@@ -846,8 +846,8 @@ func (cli *DockerCli) CmdRmi(args ...string) error {
|
| 846 | 846 |
|
| 847 | 847 |
func (cli *DockerCli) CmdHistory(args ...string) error {
|
| 848 | 848 |
cmd := cli.Subcmd("history", "[OPTIONS] IMAGE", "Show the history of an image")
|
| 849 |
- quiet := cmd.Bool("q", false, "only show numeric IDs")
|
|
| 850 |
- noTrunc := cmd.Bool("notrunc", false, "Don't truncate output")
|
|
| 849 |
+ quiet := cmd.Bool([]string{"q", "-quiet"}, false, "only show numeric IDs")
|
|
| 850 |
+ noTrunc := cmd.Bool([]string{"#notrunc", "-no-trunc"}, false, "Don't truncate output")
|
|
| 851 | 851 |
|
| 852 | 852 |
if err := cmd.Parse(args); err != nil {
|
| 853 | 853 |
return nil |
| ... | ... |
@@ -906,8 +906,8 @@ func (cli *DockerCli) CmdHistory(args ...string) error {
|
| 906 | 906 |
|
| 907 | 907 |
func (cli *DockerCli) CmdRm(args ...string) error {
|
| 908 | 908 |
cmd := cli.Subcmd("rm", "[OPTIONS] CONTAINER [CONTAINER...]", "Remove one or more containers")
|
| 909 |
- v := cmd.Bool("v", false, "Remove the volumes associated to the container")
|
|
| 910 |
- link := cmd.Bool("link", false, "Remove the specified link and not the underlying container")
|
|
| 909 |
+ v := cmd.Bool([]string{"v", "-volumes"}, false, "Remove the volumes associated to the container")
|
|
| 910 |
+ link := cmd.Bool([]string{"l", "#link", "-link"}, false, "Remove the specified link and not the underlying container")
|
|
| 911 | 911 |
|
| 912 | 912 |
if err := cmd.Parse(args); err != nil {
|
| 913 | 913 |
return nil |
| ... | ... |
@@ -1058,7 +1058,7 @@ func (cli *DockerCli) CmdPush(args ...string) error {
|
| 1058 | 1058 |
|
| 1059 | 1059 |
func (cli *DockerCli) CmdPull(args ...string) error {
|
| 1060 | 1060 |
cmd := cli.Subcmd("pull", "NAME", "Pull an image or a repository from the registry")
|
| 1061 |
- tag := cmd.String("t", "", "Download tagged image in repository")
|
|
| 1061 |
+ tag := cmd.String([]string{"t", "-tag"}, "", "Download tagged image in repository")
|
|
| 1062 | 1062 |
if err := cmd.Parse(args); err != nil {
|
| 1063 | 1063 |
return nil |
| 1064 | 1064 |
} |
| ... | ... |
@@ -1118,11 +1118,11 @@ func (cli *DockerCli) CmdPull(args ...string) error {
|
| 1118 | 1118 |
|
| 1119 | 1119 |
func (cli *DockerCli) CmdImages(args ...string) error {
|
| 1120 | 1120 |
cmd := cli.Subcmd("images", "[OPTIONS] [NAME]", "List images")
|
| 1121 |
- quiet := cmd.Bool("q", false, "only show numeric IDs")
|
|
| 1122 |
- all := cmd.Bool("a", false, "show all images (by default filter out the intermediate images used to build)")
|
|
| 1123 |
- noTrunc := cmd.Bool("notrunc", false, "Don't truncate output")
|
|
| 1124 |
- flViz := cmd.Bool("viz", false, "output graph in graphviz format")
|
|
| 1125 |
- flTree := cmd.Bool("tree", false, "output graph in tree format")
|
|
| 1121 |
+ quiet := cmd.Bool([]string{"q", "-quiet"}, false, "only show numeric IDs")
|
|
| 1122 |
+ all := cmd.Bool([]string{"a", "-all"}, false, "show all images (by default filter out the intermediate images used to build)")
|
|
| 1123 |
+ noTrunc := cmd.Bool([]string{"#notrunc", "-no-trunc"}, false, "Don't truncate output")
|
|
| 1124 |
+ flViz := cmd.Bool([]string{"v", "#viz", "-viz"}, false, "output graph in graphviz format")
|
|
| 1125 |
+ flTree := cmd.Bool([]string{"t", "#tree", "-tree"}, false, "output graph in tree format")
|
|
| 1126 | 1126 |
|
| 1127 | 1127 |
if err := cmd.Parse(args); err != nil {
|
| 1128 | 1128 |
return nil |
| ... | ... |
@@ -1329,14 +1329,14 @@ func displayablePorts(ports []APIPort) string {
|
| 1329 | 1329 |
|
| 1330 | 1330 |
func (cli *DockerCli) CmdPs(args ...string) error {
|
| 1331 | 1331 |
cmd := cli.Subcmd("ps", "[OPTIONS]", "List containers")
|
| 1332 |
- quiet := cmd.Bool("q", false, "Only display numeric IDs")
|
|
| 1333 |
- size := cmd.Bool("s", false, "Display sizes")
|
|
| 1334 |
- all := cmd.Bool("a", false, "Show all containers. Only running containers are shown by default.")
|
|
| 1335 |
- noTrunc := cmd.Bool("notrunc", false, "Don't truncate output")
|
|
| 1336 |
- nLatest := cmd.Bool("l", false, "Show only the latest created container, include non-running ones.")
|
|
| 1337 |
- since := cmd.String("sinceId", "", "Show only containers created since Id, include non-running ones.")
|
|
| 1338 |
- before := cmd.String("beforeId", "", "Show only container created before Id, include non-running ones.")
|
|
| 1339 |
- last := cmd.Int("n", -1, "Show n last created containers, include non-running ones.")
|
|
| 1332 |
+ quiet := cmd.Bool([]string{"q", "-quiet"}, false, "Only display numeric IDs")
|
|
| 1333 |
+ size := cmd.Bool([]string{"s", "-size"}, false, "Display sizes")
|
|
| 1334 |
+ all := cmd.Bool([]string{"a", "-all"}, false, "Show all containers. Only running containers are shown by default.")
|
|
| 1335 |
+ noTrunc := cmd.Bool([]string{"#notrunc", "-no-trunc"}, false, "Don't truncate output")
|
|
| 1336 |
+ nLatest := cmd.Bool([]string{"l", "-latest"}, false, "Show only the latest created container, include non-running ones.")
|
|
| 1337 |
+ since := cmd.String([]string{"#sinceId", "-since-id"}, "", "Show only containers created since Id, include non-running ones.")
|
|
| 1338 |
+ before := cmd.String([]string{"#beforeId", "-before-id"}, "", "Show only container created before Id, include non-running ones.")
|
|
| 1339 |
+ last := cmd.Int([]string{"n"}, -1, "Show n last created containers, include non-running ones.")
|
|
| 1340 | 1340 |
|
| 1341 | 1341 |
if err := cmd.Parse(args); err != nil {
|
| 1342 | 1342 |
return nil |
| ... | ... |
@@ -1418,9 +1418,9 @@ func (cli *DockerCli) CmdPs(args ...string) error {
|
| 1418 | 1418 |
|
| 1419 | 1419 |
func (cli *DockerCli) CmdCommit(args ...string) error {
|
| 1420 | 1420 |
cmd := cli.Subcmd("commit", "[OPTIONS] CONTAINER [REPOSITORY[:TAG]]", "Create a new image from a container's changes")
|
| 1421 |
- flComment := cmd.String("m", "", "Commit message")
|
|
| 1422 |
- flAuthor := cmd.String("author", "", "Author (eg. \"John Hannibal Smith <hannibal@a-team.com>\"")
|
|
| 1423 |
- flConfig := cmd.String("run", "", "Config automatically applied when the image is run. "+`(ex: -run='{"Cmd": ["cat", "/world"], "PortSpecs": ["22"]}')`)
|
|
| 1421 |
+ flComment := cmd.String([]string{"m", "-message"}, "", "Commit message")
|
|
| 1422 |
+ flAuthor := cmd.String([]string{"a", "#author", "-author"}, "", "Author (eg. \"John Hannibal Smith <hannibal@a-team.com>\"")
|
|
| 1423 |
+ flConfig := cmd.String([]string{"#run", "-run"}, "", "Config automatically applied when the image is run. "+`(ex: -run='{"Cmd": ["cat", "/world"], "PortSpecs": ["22"]}')`)
|
|
| 1424 | 1424 |
if err := cmd.Parse(args); err != nil {
|
| 1425 | 1425 |
return nil |
| 1426 | 1426 |
} |
| ... | ... |
@@ -1470,7 +1470,7 @@ func (cli *DockerCli) CmdCommit(args ...string) error {
|
| 1470 | 1470 |
|
| 1471 | 1471 |
func (cli *DockerCli) CmdEvents(args ...string) error {
|
| 1472 | 1472 |
cmd := cli.Subcmd("events", "[OPTIONS]", "Get real time events from the server")
|
| 1473 |
- since := cmd.String("since", "", "Show previously created events and then stream.")
|
|
| 1473 |
+ since := cmd.String([]string{"#since", "-since"}, "", "Show previously created events and then stream.")
|
|
| 1474 | 1474 |
if err := cmd.Parse(args); err != nil {
|
| 1475 | 1475 |
return nil |
| 1476 | 1476 |
} |
| ... | ... |
@@ -1557,7 +1557,7 @@ func (cli *DockerCli) CmdDiff(args ...string) error {
|
| 1557 | 1557 |
|
| 1558 | 1558 |
func (cli *DockerCli) CmdLogs(args ...string) error {
|
| 1559 | 1559 |
cmd := cli.Subcmd("logs", "CONTAINER", "Fetch the logs of a container")
|
| 1560 |
- follow := cmd.Bool("f", false, "Follow log output")
|
|
| 1560 |
+ follow := cmd.Bool([]string{"f", "-follow"}, false, "Follow log output")
|
|
| 1561 | 1561 |
if err := cmd.Parse(args); err != nil {
|
| 1562 | 1562 |
return nil |
| 1563 | 1563 |
} |
| ... | ... |
@@ -1593,8 +1593,8 @@ func (cli *DockerCli) CmdLogs(args ...string) error {
|
| 1593 | 1593 |
|
| 1594 | 1594 |
func (cli *DockerCli) CmdAttach(args ...string) error {
|
| 1595 | 1595 |
cmd := cli.Subcmd("attach", "[OPTIONS] CONTAINER", "Attach to a running container")
|
| 1596 |
- noStdin := cmd.Bool("nostdin", false, "Do not attach stdin")
|
|
| 1597 |
- proxy := cmd.Bool("sig-proxy", true, "Proxify all received signal to the process (even in non-tty mode)")
|
|
| 1596 |
+ noStdin := cmd.Bool([]string{"#nostdin", "-no-stdin"}, false, "Do not attach stdin")
|
|
| 1597 |
+ proxy := cmd.Bool([]string{"#sig-proxy", "-sig-proxy"}, true, "Proxify all received signal to the process (even in non-tty mode)")
|
|
| 1598 | 1598 |
if err := cmd.Parse(args); err != nil {
|
| 1599 | 1599 |
return nil |
| 1600 | 1600 |
} |
| ... | ... |
@@ -1657,9 +1657,9 @@ func (cli *DockerCli) CmdAttach(args ...string) error {
|
| 1657 | 1657 |
|
| 1658 | 1658 |
func (cli *DockerCli) CmdSearch(args ...string) error {
|
| 1659 | 1659 |
cmd := cli.Subcmd("search", "TERM", "Search the docker index for images")
|
| 1660 |
- noTrunc := cmd.Bool("notrunc", false, "Don't truncate output")
|
|
| 1661 |
- trusted := cmd.Bool("trusted", false, "Only show trusted builds")
|
|
| 1662 |
- stars := cmd.Int("stars", 0, "Only displays with at least xxx stars")
|
|
| 1660 |
+ noTrunc := cmd.Bool([]string{"#notrunc", "-no-trunc"}, false, "Don't truncate output")
|
|
| 1661 |
+ trusted := cmd.Bool([]string{"t", "#trusted", "-trusted"}, false, "Only show trusted builds")
|
|
| 1662 |
+ stars := cmd.Int([]string{"s", "#stars", "-stars"}, 0, "Only displays with at least xxx stars")
|
|
| 1663 | 1663 |
if err := cmd.Parse(args); err != nil {
|
| 1664 | 1664 |
return nil |
| 1665 | 1665 |
} |
| ... | ... |
@@ -1712,7 +1712,7 @@ type ports []int |
| 1712 | 1712 |
|
| 1713 | 1713 |
func (cli *DockerCli) CmdTag(args ...string) error {
|
| 1714 | 1714 |
cmd := cli.Subcmd("tag", "[OPTIONS] IMAGE REPOSITORY[:TAG]", "Tag an image into a repository")
|
| 1715 |
- force := cmd.Bool("f", false, "Force")
|
|
| 1715 |
+ force := cmd.Bool([]string{"f", "#force", "-force"}, false, "Force")
|
|
| 1716 | 1716 |
if err := cmd.Parse(args); err != nil {
|
| 1717 | 1717 |
return nil |
| 1718 | 1718 |
} |
| ... | ... |
@@ -1766,36 +1766,36 @@ func parseRun(cmd *flag.FlagSet, args []string, capabilities *Capabilities) (*Co |
| 1766 | 1766 |
flVolumesFrom ListOpts |
| 1767 | 1767 |
flLxcOpts ListOpts |
| 1768 | 1768 |
|
| 1769 |
- flAutoRemove = cmd.Bool("rm", false, "Automatically remove the container when it exits (incompatible with -d)")
|
|
| 1770 |
- flDetach = cmd.Bool("d", false, "Detached mode: Run container in the background, print new container id")
|
|
| 1771 |
- flNetwork = cmd.Bool("n", true, "Enable networking for this container")
|
|
| 1772 |
- flPrivileged = cmd.Bool("privileged", false, "Give extended privileges to this container")
|
|
| 1773 |
- flPublishAll = cmd.Bool("P", false, "Publish all exposed ports to the host interfaces")
|
|
| 1774 |
- flStdin = cmd.Bool("i", false, "Keep stdin open even if not attached")
|
|
| 1775 |
- flTty = cmd.Bool("t", false, "Allocate a pseudo-tty")
|
|
| 1776 |
- flContainerIDFile = cmd.String("cidfile", "", "Write the container ID to the file")
|
|
| 1777 |
- flEntrypoint = cmd.String("entrypoint", "", "Overwrite the default entrypoint of the image")
|
|
| 1778 |
- flHostname = cmd.String("h", "", "Container host name")
|
|
| 1779 |
- flMemoryString = cmd.String("m", "", "Memory limit (format: <number><optional unit>, where unit = b, k, m or g)")
|
|
| 1780 |
- flUser = cmd.String("u", "", "Username or UID")
|
|
| 1781 |
- flWorkingDir = cmd.String("w", "", "Working directory inside the container")
|
|
| 1782 |
- flCpuShares = cmd.Int64("c", 0, "CPU shares (relative weight)")
|
|
| 1769 |
+ flAutoRemove = cmd.Bool([]string{"#rm", "-rm"}, false, "Automatically remove the container when it exits (incompatible with -d)")
|
|
| 1770 |
+ flDetach = cmd.Bool([]string{"d", "-detach"}, false, "Detached mode: Run container in the background, print new container id")
|
|
| 1771 |
+ flNetwork = cmd.Bool([]string{"n", "-networking"}, true, "Enable networking for this container")
|
|
| 1772 |
+ flPrivileged = cmd.Bool([]string{"#privileged", "-privileged"}, false, "Give extended privileges to this container")
|
|
| 1773 |
+ flPublishAll = cmd.Bool([]string{"P", "-publish-all"}, false, "Publish all exposed ports to the host interfaces")
|
|
| 1774 |
+ flStdin = cmd.Bool([]string{"i", "-interactive"}, false, "Keep stdin open even if not attached")
|
|
| 1775 |
+ flTty = cmd.Bool([]string{"t", "-tty"}, false, "Allocate a pseudo-tty")
|
|
| 1776 |
+ flContainerIDFile = cmd.String([]string{"#cidfile", "-cidfile"}, "", "Write the container ID to the file")
|
|
| 1777 |
+ flEntrypoint = cmd.String([]string{"#entrypoint", "-entrypoint"}, "", "Overwrite the default entrypoint of the image")
|
|
| 1778 |
+ flHostname = cmd.String([]string{"h", "-hostname"}, "", "Container host name")
|
|
| 1779 |
+ flMemoryString = cmd.String([]string{"m", "-memory"}, "", "Memory limit (format: <number><optional unit>, where unit = b, k, m or g)")
|
|
| 1780 |
+ flUser = cmd.String([]string{"u", "-username"}, "", "Username or UID")
|
|
| 1781 |
+ flWorkingDir = cmd.String([]string{"w", "-workdir"}, "", "Working directory inside the container")
|
|
| 1782 |
+ flCpuShares = cmd.Int64([]string{"c", "-cpu-shares"}, 0, "CPU shares (relative weight)")
|
|
| 1783 | 1783 |
|
| 1784 | 1784 |
// For documentation purpose |
| 1785 |
- _ = cmd.Bool("sig-proxy", true, "Proxify all received signal to the process (even in non-tty mode)")
|
|
| 1786 |
- _ = cmd.String("name", "", "Assign a name to the container")
|
|
| 1785 |
+ _ = cmd.Bool([]string{"#sig-proxy", "-sig-proxy"}, true, "Proxify all received signal to the process (even in non-tty mode)")
|
|
| 1786 |
+ _ = cmd.String([]string{"#name", "-name"}, "", "Assign a name to the container")
|
|
| 1787 | 1787 |
) |
| 1788 | 1788 |
|
| 1789 |
- cmd.Var(&flAttach, "a", "Attach to stdin, stdout or stderr.") |
|
| 1790 |
- cmd.Var(&flVolumes, "v", "Bind mount a volume (e.g. from the host: -v /host:/container, from docker: -v /container)") |
|
| 1791 |
- cmd.Var(&flLinks, "link", "Add link to another container (name:alias)") |
|
| 1792 |
- cmd.Var(&flEnv, "e", "Set environment variables") |
|
| 1789 |
+ cmd.Var(&flAttach, []string{"a", "-attach"}, "Attach to stdin, stdout or stderr.")
|
|
| 1790 |
+ cmd.Var(&flVolumes, []string{"v", "-volume"}, "Bind mount a volume (e.g. from the host: -v /host:/container, from docker: -v /container)")
|
|
| 1791 |
+ cmd.Var(&flLinks, []string{"#link", "-link"}, "Add link to another container (name:alias)")
|
|
| 1792 |
+ cmd.Var(&flEnv, []string{"e", "-env"}, "Set environment variables")
|
|
| 1793 | 1793 |
|
| 1794 |
- cmd.Var(&flPublish, "p", fmt.Sprintf("Publish a container's port to the host (format: %s) (use 'docker port' to see the actual mapping)", PortSpecTemplateFormat))
|
|
| 1795 |
- cmd.Var(&flExpose, "expose", "Expose a port from the container without publishing it to your host") |
|
| 1796 |
- cmd.Var(&flDns, "dns", "Set custom dns servers") |
|
| 1797 |
- cmd.Var(&flVolumesFrom, "volumes-from", "Mount volumes from the specified container(s)") |
|
| 1798 |
- cmd.Var(&flLxcOpts, "lxc-conf", "Add custom lxc options -lxc-conf=\"lxc.cgroup.cpuset.cpus = 0,1\"") |
|
| 1794 |
+ cmd.Var(&flPublish, []string{"p", "-publish"}, fmt.Sprintf("Publish a container's port to the host (format: %s) (use 'docker port' to see the actual mapping)", PortSpecTemplateFormat))
|
|
| 1795 |
+ cmd.Var(&flExpose, []string{"#expose", "-expose"}, "Expose a port from the container without publishing it to your host")
|
|
| 1796 |
+ cmd.Var(&flDns, []string{"#dns", "-dns"}, "Set custom dns servers")
|
|
| 1797 |
+ cmd.Var(&flVolumesFrom, []string{"#volumes-from", "-volumes-from"}, "Mount volumes from the specified container(s)")
|
|
| 1798 |
+ cmd.Var(&flLxcOpts, []string{"#lxc-conf", "-lxc-conf"}, "Add custom lxc options -lxc-conf=\"lxc.cgroup.cpuset.cpus = 0,1\"")
|
|
| 1799 | 1799 |
|
| 1800 | 1800 |
if err := cmd.Parse(args); err != nil {
|
| 1801 | 1801 |
return nil, nil, cmd, err |
| ... | ... |
@@ -1892,7 +1892,7 @@ func parseRun(cmd *flag.FlagSet, args []string, capabilities *Capabilities) (*Co |
| 1892 | 1892 |
// Merge in exposed ports to the map of published ports |
| 1893 | 1893 |
for _, e := range flExpose.GetAll() {
|
| 1894 | 1894 |
if strings.Contains(e, ":") {
|
| 1895 |
- return nil, nil, cmd, fmt.Errorf("Invalid port format for -expose: %s", e)
|
|
| 1895 |
+ return nil, nil, cmd, fmt.Errorf("Invalid port format for --expose: %s", e)
|
|
| 1896 | 1896 |
} |
| 1897 | 1897 |
p := NewPort(splitProtoPort(e)) |
| 1898 | 1898 |
if _, exists := ports[p]; !exists {
|
| ... | ... |
@@ -25,7 +25,7 @@ __docker_containers_all() |
| 25 | 25 |
{
|
| 26 | 26 |
local containers |
| 27 | 27 |
containers="$( docker ps -a -q )" |
| 28 |
- names="$( docker inspect -format '{{.Name}}' $containers | sed 's,^/,,' )"
|
|
| 28 |
+ names="$( docker inspect --format '{{.Name}}' $containers | sed 's,^/,,' )"
|
|
| 29 | 29 |
COMPREPLY=( $( compgen -W "$names $containers" -- "$cur" ) ) |
| 30 | 30 |
} |
| 31 | 31 |
|
| ... | ... |
@@ -33,7 +33,7 @@ __docker_containers_running() |
| 33 | 33 |
{
|
| 34 | 34 |
local containers |
| 35 | 35 |
containers="$( docker ps -q )" |
| 36 |
- names="$( docker inspect -format '{{.Name}}' $containers | sed 's,^/,,' )"
|
|
| 36 |
+ names="$( docker inspect --format '{{.Name}}' $containers | sed 's,^/,,' )"
|
|
| 37 | 37 |
COMPREPLY=( $( compgen -W "$names $containers" -- "$cur" ) ) |
| 38 | 38 |
} |
| 39 | 39 |
|
| ... | ... |
@@ -41,7 +41,7 @@ __docker_containers_stopped() |
| 41 | 41 |
{
|
| 42 | 42 |
local containers |
| 43 | 43 |
containers="$( comm -13 <(docker ps -q | sort -u) <(docker ps -a -q | sort -u) )" |
| 44 |
- names="$( docker inspect -format '{{.Name}}' $containers | sed 's,^/,,' )"
|
|
| 44 |
+ names="$( docker inspect --format '{{.Name}}' $containers | sed 's,^/,,' )"
|
|
| 45 | 45 |
COMPREPLY=( $( compgen -W "$names $containers" -- "$cur" ) ) |
| 46 | 46 |
} |
| 47 | 47 |
|
| ... | ... |
@@ -73,7 +73,7 @@ __docker_containers_and_images() |
| 73 | 73 |
{
|
| 74 | 74 |
local containers images |
| 75 | 75 |
containers="$( docker ps -a -q )" |
| 76 |
- names="$( docker inspect -format '{{.Name}}' $containers | sed 's,^/,,' )"
|
|
| 76 |
+ names="$( docker inspect --format '{{.Name}}' $containers | sed 's,^/,,' )"
|
|
| 77 | 77 |
images="$( docker images | awk 'NR>1{print $1":"$2}' )"
|
| 78 | 78 |
COMPREPLY=( $( compgen -W "$images $names $containers" -- "$cur" ) ) |
| 79 | 79 |
__ltrim_colon_completions "$cur" |
| ... | ... |
@@ -118,7 +118,7 @@ _docker_build() |
| 118 | 118 |
|
| 119 | 119 |
case "$cur" in |
| 120 | 120 |
-*) |
| 121 |
- COMPREPLY=( $( compgen -W "-no-cache -t -q -rm" -- "$cur" ) ) |
|
| 121 |
+ COMPREPLY=( $( compgen -W "--no-cache -t -q --rm" -- "$cur" ) ) |
|
| 122 | 122 |
;; |
| 123 | 123 |
*) |
| 124 | 124 |
_filedir |
| ... | ... |
@@ -138,7 +138,7 @@ _docker_commit() |
| 138 | 138 |
|
| 139 | 139 |
case "$cur" in |
| 140 | 140 |
-*) |
| 141 |
- COMPREPLY=( $( compgen -W "-author -m -run" -- "$cur" ) ) |
|
| 141 |
+ COMPREPLY=( $( compgen -W "--author -m --run" -- "$cur" ) ) |
|
| 142 | 142 |
;; |
| 143 | 143 |
*) |
| 144 | 144 |
local counter=$cpos |
| ... | ... |
@@ -191,7 +191,7 @@ _docker_events() |
| 191 | 191 |
|
| 192 | 192 |
case "$cur" in |
| 193 | 193 |
-*) |
| 194 |
- COMPREPLY=( $( compgen -W "-since" -- "$cur" ) ) |
|
| 194 |
+ COMPREPLY=( $( compgen -W "--since" -- "$cur" ) ) |
|
| 195 | 195 |
;; |
| 196 | 196 |
*) |
| 197 | 197 |
;; |
| ... | ... |
@@ -223,7 +223,7 @@ _docker_images() |
| 223 | 223 |
{
|
| 224 | 224 |
case "$cur" in |
| 225 | 225 |
-*) |
| 226 |
- COMPREPLY=( $( compgen -W "-a -notrunc -q -viz" -- "$cur" ) ) |
|
| 226 |
+ COMPREPLY=( $( compgen -W "-a --no-trunc -q --viz" -- "$cur" ) ) |
|
| 227 | 227 |
;; |
| 228 | 228 |
*) |
| 229 | 229 |
local counter=$cpos |
| ... | ... |
@@ -308,7 +308,7 @@ _docker_port() |
| 308 | 308 |
_docker_ps() |
| 309 | 309 |
{
|
| 310 | 310 |
case "$prev" in |
| 311 |
- -beforeId|-n|-sinceId) |
|
| 311 |
+ -before-id|-n|-since-id) |
|
| 312 | 312 |
return |
| 313 | 313 |
;; |
| 314 | 314 |
*) |
| ... | ... |
@@ -317,7 +317,7 @@ _docker_ps() |
| 317 | 317 |
|
| 318 | 318 |
case "$cur" in |
| 319 | 319 |
-*) |
| 320 |
- COMPREPLY=( $( compgen -W "-a -beforeId -l -n -notrunc -q -s -sinceId" -- "$cur" ) ) |
|
| 320 |
+ COMPREPLY=( $( compgen -W "-a --before-id -l -n --no-trunc -q -s --since-id" -- "$cur" ) ) |
|
| 321 | 321 |
;; |
| 322 | 322 |
*) |
| 323 | 323 |
;; |
| ... | ... |
@@ -388,13 +388,13 @@ _docker_rmi() |
| 388 | 388 |
_docker_run() |
| 389 | 389 |
{
|
| 390 | 390 |
case "$prev" in |
| 391 |
- -cidfile) |
|
| 391 |
+ --cidfile) |
|
| 392 | 392 |
_filedir |
| 393 | 393 |
;; |
| 394 |
- -volumes-from) |
|
| 394 |
+ --volumes-from) |
|
| 395 | 395 |
__docker_containers_all |
| 396 | 396 |
;; |
| 397 |
- -a|-c|-dns|-e|-entrypoint|-h|-lxc-conf|-m|-p|-u|-v|-w) |
|
| 397 |
+ -a|-c|--dns|-e|--entrypoint|-h|--lxc-conf|-m|-p|-u|-v|-w) |
|
| 398 | 398 |
return |
| 399 | 399 |
;; |
| 400 | 400 |
*) |
| ... | ... |
@@ -403,13 +403,13 @@ _docker_run() |
| 403 | 403 |
|
| 404 | 404 |
case "$cur" in |
| 405 | 405 |
-*) |
| 406 |
- COMPREPLY=( $( compgen -W "-a -c -cidfile -d -dns -e -entrypoint -h -i -lxc-conf -m -n -p -privileged -t -u -v -volumes-from -w" -- "$cur" ) ) |
|
| 406 |
+ COMPREPLY=( $( compgen -W "-a -c --cidfile -d --dns -e --entrypoint -h -i --lxc-conf -m -n -p --privileged -t -u -v --volumes-from -w" -- "$cur" ) ) |
|
| 407 | 407 |
;; |
| 408 | 408 |
*) |
| 409 | 409 |
local counter=$cpos |
| 410 | 410 |
while [ $counter -le $cword ]; do |
| 411 | 411 |
case "${words[$counter]}" in
|
| 412 |
- -a|-c|-cidfile|-dns|-e|-entrypoint|-h|-lxc-conf|-m|-p|-u|-v|-volumes-from|-w) |
|
| 412 |
+ -a|-c|--cidfile|--dns|-e|--entrypoint|-h|--lxc-conf|-m|-p|-u|-v|--volumes-from|-w) |
|
| 413 | 413 |
(( counter++ )) |
| 414 | 414 |
;; |
| 415 | 415 |
-*) |
| ... | ... |
@@ -430,7 +430,7 @@ _docker_run() |
| 430 | 430 |
|
| 431 | 431 |
_docker_search() |
| 432 | 432 |
{
|
| 433 |
- COMPREPLY=( $( compgen -W "-notrunc" "-stars" "-trusted" -- "$cur" ) ) |
|
| 433 |
+ COMPREPLY=( $( compgen -W "--no-trunc" "--stars" "--trusted" -- "$cur" ) ) |
|
| 434 | 434 |
} |
| 435 | 435 |
|
| 436 | 436 |
_docker_start() |
| ... | ... |
@@ -174,7 +174,7 @@ __docker_subcommand () {
|
| 174 | 174 |
(ps) |
| 175 | 175 |
_arguments '-a[Show all containers. Only running containers are shown by default]' \ |
| 176 | 176 |
'-h[Show help]' \ |
| 177 |
- '-beforeId=-[Show only container created before Id, include non-running one]:containers:__docker_containers' \ |
|
| 177 |
+ '-before-id=-[Show only container created before Id, include non-running one]:containers:__docker_containers' \ |
|
| 178 | 178 |
'-n=-[Show n last created containers, include non-running one]:n:(1 5 10 25 50)' |
| 179 | 179 |
;; |
| 180 | 180 |
(tag) |
| ... | ... |
@@ -189,9 +189,9 @@ __docker_subcommand () {
|
| 189 | 189 |
'-a=-[Attach to stdin, stdout or stderr]:toggle:(true false)' \ |
| 190 | 190 |
'-c=-[CPU shares (relative weight)]:CPU shares: ' \ |
| 191 | 191 |
'-d[Detached mode: leave the container running in the background]' \ |
| 192 |
- '*-dns=[Set custom dns servers]:dns server: ' \ |
|
| 192 |
+ '*--dns=[Set custom dns servers]:dns server: ' \ |
|
| 193 | 193 |
'*-e=[Set environment variables]:environment variable: ' \ |
| 194 |
- '-entrypoint=-[Overwrite the default entrypoint of the image]:entry point: ' \ |
|
| 194 |
+ '--entrypoint=-[Overwrite the default entrypoint of the image]:entry point: ' \ |
|
| 195 | 195 |
'-h=-[Container host name]:hostname:_hosts' \ |
| 196 | 196 |
'-i[Keep stdin open even if not attached]' \ |
| 197 | 197 |
'-m=-[Memory limit (in bytes)]:limit: ' \ |
| ... | ... |
@@ -199,7 +199,7 @@ __docker_subcommand () {
|
| 199 | 199 |
'-t=-[Allocate a pseudo-tty]:toggle:(true false)' \ |
| 200 | 200 |
'-u=-[Username or UID]:user:_users' \ |
| 201 | 201 |
'*-v=-[Bind mount a volume (e.g. from the host: -v /host:/container, from docker: -v /container)]:volume: '\ |
| 202 |
- '-volumes-from=-[Mount volumes from the specified container]:volume: ' \ |
|
| 202 |
+ '--volumes-from=-[Mount volumes from the specified container]:volume: ' \ |
|
| 203 | 203 |
'(-):images:__docker_images' \ |
| 204 | 204 |
'(-):command: _command_names -e' \ |
| 205 | 205 |
'*::arguments: _normal' |
| ... | ... |
@@ -1,10 +1,10 @@ |
| 1 | 1 |
package main |
| 2 | 2 |
|
| 3 | 3 |
import ( |
| 4 |
- "flag" |
|
| 5 | 4 |
"fmt" |
| 6 | 5 |
"github.com/dotcloud/docker" |
| 7 | 6 |
"github.com/dotcloud/docker/engine" |
| 7 |
+ flag "github.com/dotcloud/docker/pkg/mflag" |
|
| 8 | 8 |
"github.com/dotcloud/docker/sysinit" |
| 9 | 9 |
"github.com/dotcloud/docker/utils" |
| 10 | 10 |
"log" |
| ... | ... |
@@ -25,25 +25,25 @@ func main() {
|
| 25 | 25 |
} |
| 26 | 26 |
|
| 27 | 27 |
var ( |
| 28 |
- flVersion = flag.Bool("v", false, "Print version information and quit")
|
|
| 29 |
- flDaemon = flag.Bool("d", false, "Enable daemon mode")
|
|
| 30 |
- flDebug = flag.Bool("D", false, "Enable debug mode")
|
|
| 31 |
- flAutoRestart = flag.Bool("r", true, "Restart previously running containers")
|
|
| 32 |
- bridgeName = flag.String("b", "", "Attach containers to a pre-existing network bridge; use 'none' to disable container networking")
|
|
| 33 |
- bridgeIp = flag.String("bip", "", "Use this CIDR notation address for the network bridge's IP, not compatible with -b")
|
|
| 34 |
- pidfile = flag.String("p", "/var/run/docker.pid", "Path to use for daemon PID file")
|
|
| 35 |
- flRoot = flag.String("g", "/var/lib/docker", "Path to use as the root of the docker runtime")
|
|
| 36 |
- flEnableCors = flag.Bool("api-enable-cors", false, "Enable CORS headers in the remote API")
|
|
| 28 |
+ flVersion = flag.Bool([]string{"v", "-version"}, false, "Print version information and quit")
|
|
| 29 |
+ flDaemon = flag.Bool([]string{"d", "-daemon"}, false, "Enable daemon mode")
|
|
| 30 |
+ flDebug = flag.Bool([]string{"D", "-debug"}, false, "Enable debug mode")
|
|
| 31 |
+ flAutoRestart = flag.Bool([]string{"r", "-restart"}, true, "Restart previously running containers")
|
|
| 32 |
+ bridgeName = flag.String([]string{"b", "-bridge"}, "", "Attach containers to a pre-existing network bridge; use 'none' to disable container networking")
|
|
| 33 |
+ bridgeIp = flag.String([]string{"#bip", "-bip"}, "", "Use this CIDR notation address for the network bridge's IP, not compatible with -b")
|
|
| 34 |
+ pidfile = flag.String([]string{"p", "-pidfile"}, "/var/run/docker.pid", "Path to use for daemon PID file")
|
|
| 35 |
+ flRoot = flag.String([]string{"g", "-graph"}, "/var/lib/docker", "Path to use as the root of the docker runtime")
|
|
| 36 |
+ flEnableCors = flag.Bool([]string{"#api-enable-cors", "-api-enable-cors"}, false, "Enable CORS headers in the remote API")
|
|
| 37 | 37 |
flDns = docker.NewListOpts(docker.ValidateIp4Address) |
| 38 |
- flEnableIptables = flag.Bool("iptables", true, "Disable docker's addition of iptables rules")
|
|
| 39 |
- flDefaultIp = flag.String("ip", "0.0.0.0", "Default IP address to use when binding container ports")
|
|
| 40 |
- flInterContainerComm = flag.Bool("icc", true, "Enable inter-container communication")
|
|
| 41 |
- flGraphDriver = flag.String("s", "", "Force the docker runtime to use a specific storage driver")
|
|
| 38 |
+ flEnableIptables = flag.Bool([]string{"#iptables", "-iptables"}, true, "Disable docker's addition of iptables rules")
|
|
| 39 |
+ flDefaultIp = flag.String([]string{"#ip", "-ip"}, "0.0.0.0", "Default IP address to use when binding container ports")
|
|
| 40 |
+ flInterContainerComm = flag.Bool([]string{"#icc", "-icc"}, true, "Enable inter-container communication")
|
|
| 41 |
+ flGraphDriver = flag.String([]string{"s", "-storage-driver"}, "", "Force the docker runtime to use a specific storage driver")
|
|
| 42 | 42 |
flHosts = docker.NewListOpts(docker.ValidateHost) |
| 43 |
- flMtu = flag.Int("mtu", docker.DefaultNetworkMtu, "Set the containers network mtu")
|
|
| 43 |
+ flMtu = flag.Int([]string{"#mtu", "-mtu"}, docker.DefaultNetworkMtu, "Set the containers network mtu")
|
|
| 44 | 44 |
) |
| 45 |
- flag.Var(&flDns, "dns", "Force docker to use specific DNS servers") |
|
| 46 |
- flag.Var(&flHosts, "H", "Multiple tcp://host:port or unix://path/to/socket to bind in daemon mode, single connection otherwise") |
|
| 45 |
+ flag.Var(&flDns, []string{"#dns", "-dns"}, "Force docker to use specific DNS servers")
|
|
| 46 |
+ flag.Var(&flHosts, []string{"H", "-host"}, "Multiple tcp://host:port or unix://path/to/socket to bind in daemon mode, single connection otherwise")
|
|
| 47 | 47 |
|
| 48 | 48 |
flag.Parse() |
| 49 | 49 |
|
| ... | ... |
@@ -62,7 +62,7 @@ func main() {
|
| 62 | 62 |
} |
| 63 | 63 |
|
| 64 | 64 |
if *bridgeName != "" && *bridgeIp != "" {
|
| 65 |
- log.Fatal("You specified -b & -bip, mutually exclusive options. Please specify only one.")
|
|
| 65 |
+ log.Fatal("You specified -b & --bip, mutually exclusive options. Please specify only one.")
|
|
| 66 | 66 |
} |
| 67 | 67 |
|
| 68 | 68 |
if *flDebug {
|
| ... | ... |
@@ -41,7 +41,7 @@ This time, we're requesting shared access to ``$COUCH1``'s volumes. |
| 41 | 41 |
|
| 42 | 42 |
.. code-block:: bash |
| 43 | 43 |
|
| 44 |
- COUCH2=$(sudo docker run -d -p 5984 -volumes-from $COUCH1 shykes/couchdb:2013-05-03) |
|
| 44 |
+ COUCH2=$(sudo docker run -d -p 5984 --volumes-from $COUCH1 shykes/couchdb:2013-05-03) |
|
| 45 | 45 |
|
| 46 | 46 |
Browse data on the second database |
| 47 | 47 |
---------------------------------- |
| ... | ... |
@@ -43,7 +43,7 @@ container. The ``BUILD_JOB`` environment variable will be set with the new conta |
| 43 | 43 |
[...] |
| 44 | 44 |
|
| 45 | 45 |
While this container is running, we can attach to the new container to |
| 46 |
-see what is going on. The flag ``-sig-proxy`` set as ``false`` allows you to connect and |
|
| 46 |
+see what is going on. The flag ``--sig-proxy`` set as ``false`` allows you to connect and |
|
| 47 | 47 |
disconnect (Ctrl-C) to it without stopping the container. |
| 48 | 48 |
|
| 49 | 49 |
.. code-block:: bash |
| ... | ... |
@@ -44,7 +44,7 @@ use a container link to provide access to our Redis database. |
| 44 | 44 |
|
| 45 | 45 |
.. code-block:: bash |
| 46 | 46 |
|
| 47 |
- sudo docker run -name redis -d <your username>/redis |
|
| 47 |
+ sudo docker run --name redis -d <your username>/redis |
|
| 48 | 48 |
|
| 49 | 49 |
Create your web application container |
| 50 | 50 |
------------------------------------- |
| ... | ... |
@@ -56,7 +56,7 @@ Redis instance running inside that container to only this container. |
| 56 | 56 |
|
| 57 | 57 |
.. code-block:: bash |
| 58 | 58 |
|
| 59 |
- sudo docker run -link redis:db -i -t ubuntu:12.10 /bin/bash |
|
| 59 |
+ sudo docker run --link redis:db -i -t ubuntu:12.10 /bin/bash |
|
| 60 | 60 |
|
| 61 | 61 |
Once inside our freshly created container we need to install Redis to get the |
| 62 | 62 |
``redis-cli`` binary to test our connection. |
| ... | ... |
@@ -26,22 +26,21 @@ To list available commands, either run ``docker`` with no parameters or execute |
| 26 | 26 |
:: |
| 27 | 27 |
|
| 28 | 28 |
Usage of docker: |
| 29 |
- -D=false: Enable debug mode |
|
| 30 |
- -H=[unix:///var/run/docker.sock]: tcp://[host[:port]] to bind or unix://[/path/to/socket] to use. When host=[0.0.0.0], port=[4243] or path=[/var/run/docker.sock] is omitted, default values are used. |
|
| 31 |
- -api-enable-cors=false: Enable CORS headers in the remote API |
|
| 32 |
- -b="": Attach containers to a pre-existing network bridge; use 'none' to disable container networking |
|
| 33 |
- -bip="": Use the provided CIDR notation address for the dynamically created bridge (docker0); Mutually exclusive of -b |
|
| 34 |
- -d=false: Enable daemon mode |
|
| 35 |
- -dns="": Force docker to use specific DNS servers |
|
| 36 |
- -g="/var/lib/docker": Path to use as the root of the docker runtime |
|
| 37 |
- -icc=true: Enable inter-container communication |
|
| 38 |
- -ip="0.0.0.0": Default IP address to use when binding container ports |
|
| 39 |
- -iptables=true: Disable docker's addition of iptables rules |
|
| 40 |
- -mtu=1500: Set the containers network mtu |
|
| 41 |
- -p="/var/run/docker.pid": Path to use for daemon PID file |
|
| 42 |
- -r=true: Restart previously running containers |
|
| 43 |
- -s="": Force the docker runtime to use a specific storage driver |
|
| 44 |
- -v=false: Print version information and quit |
|
| 29 |
+ -D, --debug=false: Enable debug mode |
|
| 30 |
+ -H, --host=[]: Multiple tcp://host:port or unix://path/to/socket to bind in daemon mode, single connection otherwise |
|
| 31 |
+ --api-enable-cors=false: Enable CORS headers in the remote API |
|
| 32 |
+ -b, --bridge="": Attach containers to a pre-existing network bridge; use 'none' to disable container networking |
|
| 33 |
+ --bip="": Use this CIDR notation address for the network bridge's IP, not compatible with -b |
|
| 34 |
+ -d, --daemon=false: Enable daemon mode |
|
| 35 |
+ --dns=[]: Force docker to use specific DNS servers |
|
| 36 |
+ -g, --graph="/var/lib/docker": Path to use as the root of the docker runtime |
|
| 37 |
+ --icc=true: Enable inter-container communication |
|
| 38 |
+ --ip="0.0.0.0": Default IP address to use when binding container ports |
|
| 39 |
+ --iptables=true: Disable docker's addition of iptables rules |
|
| 40 |
+ -p, --pidfile="/var/run/docker.pid": Path to use for daemon PID file |
|
| 41 |
+ -r, --restart=true: Restart previously running containers |
|
| 42 |
+ -s, --storage-driver="": Force the docker runtime to use a specific storage driver |
|
| 43 |
+ -v, --version=false: Print version information and quit |
|
| 45 | 44 |
|
| 46 | 45 |
The Docker daemon is the persistent process that manages containers. Docker uses the same binary for both the |
| 47 | 46 |
daemon and client. To run the daemon you provide the ``-d`` flag. |
| ... | ... |
@@ -75,8 +74,8 @@ the ``-H`` flag for the client. |
| 75 | 75 |
|
| 76 | 76 |
Attach to a running container. |
| 77 | 77 |
|
| 78 |
- -nostdin=false: Do not attach stdin |
|
| 79 |
- -sig-proxy=true: Proxify all received signal to the process (even in non-tty mode) |
|
| 78 |
+ --no-stdin=false: Do not attach stdin |
|
| 79 |
+ --sig-proxy=true: Proxify all received signal to the process (even in non-tty mode) |
|
| 80 | 80 |
|
| 81 | 81 |
You can detach from the container again (and leave it running) with |
| 82 | 82 |
``CTRL-c`` (for a quiet exit) or ``CTRL-\`` to get a stacktrace of |
| ... | ... |
@@ -135,11 +134,11 @@ Examples: |
| 135 | 135 |
|
| 136 | 136 |
Usage: docker build [OPTIONS] PATH | URL | - |
| 137 | 137 |
Build a new container image from the source code at PATH |
| 138 |
- -t="": Repository name (and optionally a tag) to be applied |
|
| 138 |
+ -t, --time="": Repository name (and optionally a tag) to be applied |
|
| 139 | 139 |
to the resulting image in case of success. |
| 140 |
- -q=false: Suppress verbose build output. |
|
| 141 |
- -no-cache: Do not use the cache when building the image. |
|
| 142 |
- -rm: Remove intermediate containers after a successful build |
|
| 140 |
+ -q, --quiet=false: Suppress verbose build output. |
|
| 141 |
+ --no-cache: Do not use the cache when building the image. |
|
| 142 |
+ --rm: Remove intermediate containers after a successful build |
|
| 143 | 143 |
|
| 144 | 144 |
The files at ``PATH`` or ``URL`` are called the "context" of the build. The |
| 145 | 145 |
build process may refer to any of the files in the context, for example when |
| ... | ... |
@@ -233,9 +232,9 @@ by using the ``git://`` schema. |
| 233 | 233 |
|
| 234 | 234 |
Create a new image from a container's changes |
| 235 | 235 |
|
| 236 |
- -m="": Commit message |
|
| 237 |
- -author="": Author (eg. "John Hannibal Smith <hannibal@a-team.com>" |
|
| 238 |
- -run="": Configuration to be applied when the image is launched with `docker run`. |
|
| 236 |
+ -m, --message="": Commit message |
|
| 237 |
+ -a, --author="": Author (eg. "John Hannibal Smith <hannibal@a-team.com>" |
|
| 238 |
+ --run="": Configuration to be applied when the image is launched with `docker run`. |
|
| 239 | 239 |
(ex: -run='{"Cmd": ["cat", "/world"], "PortSpecs": ["22"]}')
|
| 240 | 240 |
|
| 241 | 241 |
.. _cli_commit_examples: |
| ... | ... |
@@ -279,7 +278,7 @@ run ``ls /etc``. |
| 279 | 279 |
Full -run example |
| 280 | 280 |
................. |
| 281 | 281 |
|
| 282 |
-The ``-run`` JSON hash changes the ``Config`` section when running ``docker inspect CONTAINERID`` |
|
| 282 |
+The ``--run`` JSON hash changes the ``Config`` section when running ``docker inspect CONTAINERID`` |
|
| 283 | 283 |
or ``config`` when running ``docker inspect IMAGEID``. |
| 284 | 284 |
|
| 285 | 285 |
(Multiline is okay within a single quote ``'``) |
| ... | ... |
@@ -379,7 +378,7 @@ For example: |
| 379 | 379 |
|
| 380 | 380 |
Get real time events from the server |
| 381 | 381 |
|
| 382 |
- -since="": Show previously created events and then stream. |
|
| 382 |
+ --since="": Show previously created events and then stream. |
|
| 383 | 383 |
(either seconds since epoch, or date string as below) |
| 384 | 384 |
|
| 385 | 385 |
.. _cli_events_example: |
| ... | ... |
@@ -459,8 +458,8 @@ For example: |
| 459 | 459 |
|
| 460 | 460 |
Show the history of an image |
| 461 | 461 |
|
| 462 |
- -notrunc=false: Don't truncate output |
|
| 463 |
- -q=false: only show numeric IDs |
|
| 462 |
+ --no-trunc=false: Don't truncate output |
|
| 463 |
+ -q, --quiet=false: only show numeric IDs |
|
| 464 | 464 |
|
| 465 | 465 |
To see how the ``docker:latest`` image was built: |
| 466 | 466 |
|
| ... | ... |
@@ -507,11 +506,11 @@ To see how the ``docker:latest`` image was built: |
| 507 | 507 |
|
| 508 | 508 |
List images |
| 509 | 509 |
|
| 510 |
- -a=false: show all images (by default filter out the intermediate images used to build) |
|
| 511 |
- -notrunc=false: Don't truncate output |
|
| 512 |
- -q=false: only show numeric IDs |
|
| 513 |
- -tree=false: output graph in tree format |
|
| 514 |
- -viz=false: output graph in graphviz format |
|
| 510 |
+ -a, --all=false: show all images (by default filter out the intermediate images used to build) |
|
| 511 |
+ --no-trunc=false: Don't truncate output |
|
| 512 |
+ -q, --quiet=false: only show numeric IDs |
|
| 513 |
+ --tree=false: output graph in tree format |
|
| 514 |
+ --viz=false: output graph in graphviz format |
|
| 515 | 515 |
|
| 516 | 516 |
Listing the most recently created images |
| 517 | 517 |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| ... | ... |
@@ -535,7 +534,7 @@ Listing the full length image IDs |
| 535 | 535 |
|
| 536 | 536 |
.. code-block:: bash |
| 537 | 537 |
|
| 538 |
- $ sudo docker images -notrunc | head |
|
| 538 |
+ $ sudo docker images --no-trunc | head |
|
| 539 | 539 |
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE |
| 540 | 540 |
<none> <none> 77af4d6b9913e693e8d0b4b294fa62ade6054e6b2f1ffb617ac955dd63fb0182 19 hours ago 1.089 GB |
| 541 | 541 |
committest latest b6fa739cedf5ea12a620a439402b6004d057da800f91c7524b5086a5e4749c9f 19 hours ago 1.089 GB |
| ... | ... |
@@ -552,7 +551,7 @@ Displaying images visually |
| 552 | 552 |
|
| 553 | 553 |
.. code-block:: bash |
| 554 | 554 |
|
| 555 |
- $ sudo docker images -viz | dot -Tpng -o docker.png |
|
| 555 |
+ $ sudo docker images --viz | dot -Tpng -o docker.png |
|
| 556 | 556 |
|
| 557 | 557 |
.. image:: docker_images.gif |
| 558 | 558 |
:alt: Example inheritance graph of Docker images. |
| ... | ... |
@@ -563,7 +562,7 @@ Displaying image hierarchy |
| 563 | 563 |
|
| 564 | 564 |
.. code-block:: bash |
| 565 | 565 |
|
| 566 |
- $ sudo docker images -tree |
|
| 566 |
+ $ sudo docker images --tree |
|
| 567 | 567 |
|
| 568 | 568 |
├─8dbd9e392a96 Size: 131.5 MB (virtual 131.5 MB) Tags: ubuntu:12.04,ubuntu:latest,ubuntu:precise |
| 569 | 569 |
└─27cf78414709 Size: 180.1 MB (virtual 180.1 MB) |
| ... | ... |
@@ -702,7 +701,7 @@ Insert file from GitHub |
| 702 | 702 |
|
| 703 | 703 |
Return low-level information on a container/image |
| 704 | 704 |
|
| 705 |
- -format="": Format the output using the given go template. |
|
| 705 |
+ -f, --format="": Format the output using the given go template. |
|
| 706 | 706 |
|
| 707 | 707 |
By default, this will render all results in a JSON array. If a format |
| 708 | 708 |
is specified, the given template will be executed for each result. |
| ... | ... |
@@ -721,7 +720,7 @@ fairly straightforward manner. |
| 721 | 721 |
|
| 722 | 722 |
.. code-block:: bash |
| 723 | 723 |
|
| 724 |
- $ sudo docker inspect -format='{{.NetworkSettings.IPAddress}}' $INSTANCE_ID
|
|
| 724 |
+ $ sudo docker inspect --format='{{.NetworkSettings.IPAddress}}' $INSTANCE_ID
|
|
| 725 | 725 |
|
| 726 | 726 |
List All Port Bindings |
| 727 | 727 |
...................... |
| ... | ... |
@@ -790,9 +789,9 @@ Known Issues (kill) |
| 790 | 790 |
|
| 791 | 791 |
Register or Login to the docker registry server |
| 792 | 792 |
|
| 793 |
- -e="": email |
|
| 794 |
- -p="": password |
|
| 795 |
- -u="": username |
|
| 793 |
+ -e, --email="": email |
|
| 794 |
+ -p, --password="": password |
|
| 795 |
+ -u, --username="": username |
|
| 796 | 796 |
|
| 797 | 797 |
If you want to login to a private registry you can |
| 798 | 798 |
specify this by adding the server name. |
| ... | ... |
@@ -812,12 +811,14 @@ Known Issues (kill) |
| 812 | 812 |
|
| 813 | 813 |
Fetch the logs of a container |
| 814 | 814 |
|
| 815 |
+ -f, --follow=false: Follow log output |
|
| 816 |
+ |
|
| 815 | 817 |
The ``docker logs`` command is a convenience which batch-retrieves whatever |
| 816 | 818 |
logs are present at the time of execution. This does not guarantee execution |
| 817 | 819 |
order when combined with a ``docker run`` (i.e. your run may not have generated |
| 818 | 820 |
any logs at the time you execute ``docker logs``). |
| 819 | 821 |
|
| 820 |
-The ``docker logs -f`` command combines ``docker logs`` and ``docker attach``: |
|
| 822 |
+The ``docker logs --follow`` command combines ``docker logs`` and ``docker attach``: |
|
| 821 | 823 |
it will first return all logs from the beginning and then continue streaming |
| 822 | 824 |
new output from the container's stdout and stderr. |
| 823 | 825 |
|
| ... | ... |
@@ -845,9 +846,9 @@ new output from the container's stdout and stderr. |
| 845 | 845 |
|
| 846 | 846 |
List containers |
| 847 | 847 |
|
| 848 |
- -a=false: Show all containers. Only running containers are shown by default. |
|
| 849 |
- -notrunc=false: Don't truncate output |
|
| 850 |
- -q=false: Only display numeric IDs |
|
| 848 |
+ -a, --all=false: Show all containers. Only running containers are shown by default. |
|
| 849 |
+ --no-trunc=false: Don't truncate output |
|
| 850 |
+ -q, --quiet=false: Only display numeric IDs |
|
| 851 | 851 |
|
| 852 | 852 |
Running ``docker ps`` showing 2 linked containers. |
| 853 | 853 |
|
| ... | ... |
@@ -903,7 +904,7 @@ Running ``docker ps`` showing 2 linked containers. |
| 903 | 903 |
Usage: docker rm [OPTIONS] CONTAINER |
| 904 | 904 |
|
| 905 | 905 |
Remove one or more containers |
| 906 |
- -link="": Remove the link instead of the actual container |
|
| 906 |
+ --link="": Remove the link instead of the actual container |
|
| 907 | 907 |
|
| 908 | 908 |
Known Issues (rm) |
| 909 | 909 |
~~~~~~~~~~~~~~~~~ |
| ... | ... |
@@ -926,7 +927,7 @@ This will remove the container referenced under the link ``/redis``. |
| 926 | 926 |
|
| 927 | 927 |
.. code-block:: bash |
| 928 | 928 |
|
| 929 |
- $ sudo docker rm -link /webapp/redis |
|
| 929 |
+ $ sudo docker rm --link /webapp/redis |
|
| 930 | 930 |
/webapp/redis |
| 931 | 931 |
|
| 932 | 932 |
|
| ... | ... |
@@ -996,31 +997,31 @@ image is removed. |
| 996 | 996 |
|
| 997 | 997 |
Run a command in a new container |
| 998 | 998 |
|
| 999 |
- -a=map[]: Attach to stdin, stdout or stderr |
|
| 1000 |
- -c=0: CPU shares (relative weight) |
|
| 1001 |
- -cidfile="": Write the container ID to the file |
|
| 1002 |
- -d=false: Detached mode: Run container in the background, print new container id |
|
| 1003 |
- -e=[]: Set environment variables |
|
| 1004 |
- -h="": Container host name |
|
| 1005 |
- -i=false: Keep stdin open even if not attached |
|
| 1006 |
- -privileged=false: Give extended privileges to this container |
|
| 1007 |
- -m="": Memory limit (format: <number><optional unit>, where unit = b, k, m or g) |
|
| 1008 |
- -n=true: Enable networking for this container |
|
| 1009 |
- -p=[]: Map a network port to the container |
|
| 1010 |
- -rm=false: Automatically remove the container when it exits (incompatible with -d) |
|
| 1011 |
- -t=false: Allocate a pseudo-tty |
|
| 1012 |
- -u="": Username or UID |
|
| 1013 |
- -dns=[]: Set custom dns servers for the container |
|
| 1014 |
- -v=[]: Create a bind mount with: [host-dir]:[container-dir]:[rw|ro]. If "container-dir" is missing, then docker creates a new volume. |
|
| 1015 |
- -volumes-from="": Mount all volumes from the given container(s) |
|
| 1016 |
- -entrypoint="": Overwrite the default entrypoint set by the image |
|
| 1017 |
- -w="": Working directory inside the container |
|
| 1018 |
- -lxc-conf=[]: Add custom lxc options -lxc-conf="lxc.cgroup.cpuset.cpus = 0,1" |
|
| 1019 |
- -sig-proxy=true: Proxify all received signal to the process (even in non-tty mode) |
|
| 1020 |
- -expose=[]: Expose a port from the container without publishing it to your host |
|
| 1021 |
- -link="": Add link to another container (name:alias) |
|
| 1022 |
- -name="": Assign the specified name to the container. If no name is specific docker will generate a random name |
|
| 1023 |
- -P=false: Publish all exposed ports to the host interfaces |
|
| 999 |
+ -a, --attach=map[]: Attach to stdin, stdout or stderr |
|
| 1000 |
+ -c, --cpu-shares=0: CPU shares (relative weight) |
|
| 1001 |
+ --cidfile="": Write the container ID to the file |
|
| 1002 |
+ -d, --detach=false: Detached mode: Run container in the background, print new container id |
|
| 1003 |
+ -e, --env=[]: Set environment variables |
|
| 1004 |
+ -h, --host="": Container host name |
|
| 1005 |
+ -i, --interactive=false: Keep stdin open even if not attached |
|
| 1006 |
+ --privileged=false: Give extended privileges to this container |
|
| 1007 |
+ -m, --memory="": Memory limit (format: <number><optional unit>, where unit = b, k, m or g) |
|
| 1008 |
+ -n, --networking=true: Enable networking for this container |
|
| 1009 |
+ -p, --publish=[]: Map a network port to the container |
|
| 1010 |
+ --rm=false: Automatically remove the container when it exits (incompatible with -d) |
|
| 1011 |
+ -t, --tty=false: Allocate a pseudo-tty |
|
| 1012 |
+ -u, --username="": Username or UID |
|
| 1013 |
+ --dns=[]: Set custom dns servers for the container |
|
| 1014 |
+ -v, --volume=[]: Create a bind mount with: [host-dir]:[container-dir]:[rw|ro]. If "container-dir" is missing, then docker creates a new volume. |
|
| 1015 |
+ --volumes-from="": Mount all volumes from the given container(s) |
|
| 1016 |
+ --entrypoint="": Overwrite the default entrypoint set by the image |
|
| 1017 |
+ -w, --workdir="": Working directory inside the container |
|
| 1018 |
+ --lxc-conf=[]: Add custom lxc options -lxc-conf="lxc.cgroup.cpuset.cpus = 0,1" |
|
| 1019 |
+ --sig-proxy=true: Proxify all received signal to the process (even in non-tty mode) |
|
| 1020 |
+ --expose=[]: Expose a port from the container without publishing it to your host |
|
| 1021 |
+ --link="": Add link to another container (name:alias) |
|
| 1022 |
+ --name="": Assign the specified name to the container. If no name is specific docker will generate a random name |
|
| 1023 |
+ -P, --publish-all=false: Publish all exposed ports to the host interfaces |
|
| 1024 | 1024 |
|
| 1025 | 1025 |
The ``docker run`` command first ``creates`` a writeable container layer over |
| 1026 | 1026 |
the specified image, and then ``starts`` it using the specified command. That |
| ... | ... |
@@ -1042,7 +1043,7 @@ Examples: |
| 1042 | 1042 |
|
| 1043 | 1043 |
.. code-block:: bash |
| 1044 | 1044 |
|
| 1045 |
- $ sudo docker run -cidfile /tmp/docker_test.cid ubuntu echo "test" |
|
| 1045 |
+ $ sudo docker run --cidfile /tmp/docker_test.cid ubuntu echo "test" |
|
| 1046 | 1046 |
|
| 1047 | 1047 |
This will create a container and print ``test`` to the console. The |
| 1048 | 1048 |
``cidfile`` flag makes Docker attempt to create a new file and write the |
| ... | ... |
@@ -1051,7 +1052,7 @@ error. Docker will close this file when ``docker run`` exits. |
| 1051 | 1051 |
|
| 1052 | 1052 |
.. code-block:: bash |
| 1053 | 1053 |
|
| 1054 |
- $ sudo docker run -t -i -rm ubuntu bash |
|
| 1054 |
+ $ sudo docker run -t -i --rm ubuntu bash |
|
| 1055 | 1055 |
root@bc338942ef20:/# mount -t tmpfs none /mnt |
| 1056 | 1056 |
mount: permission denied |
| 1057 | 1057 |
|
| ... | ... |
@@ -1063,7 +1064,7 @@ allow it to run: |
| 1063 | 1063 |
|
| 1064 | 1064 |
.. code-block:: bash |
| 1065 | 1065 |
|
| 1066 |
- $ sudo docker run -privileged ubuntu bash |
|
| 1066 |
+ $ sudo docker run --privileged ubuntu bash |
|
| 1067 | 1067 |
root@50e3f57e16e6:/# mount -t tmpfs none /mnt |
| 1068 | 1068 |
root@50e3f57e16e6:/# df -h |
| 1069 | 1069 |
Filesystem Size Used Avail Use% Mounted on |
| ... | ... |
@@ -1104,7 +1105,7 @@ in Docker. |
| 1104 | 1104 |
|
| 1105 | 1105 |
.. code-block:: bash |
| 1106 | 1106 |
|
| 1107 |
- $ sudo docker run -expose 80 ubuntu bash |
|
| 1107 |
+ $ sudo docker run --expose 80 ubuntu bash |
|
| 1108 | 1108 |
|
| 1109 | 1109 |
This exposes port ``80`` of the container for use within a link without |
| 1110 | 1110 |
publishing the port to the host system's interfaces. :ref:`port_redirection` |
| ... | ... |
@@ -1112,28 +1113,28 @@ explains in detail how to manipulate ports in Docker. |
| 1112 | 1112 |
|
| 1113 | 1113 |
.. code-block:: bash |
| 1114 | 1114 |
|
| 1115 |
- $ sudo docker run -name console -t -i ubuntu bash |
|
| 1115 |
+ $ sudo docker run --name console -t -i ubuntu bash |
|
| 1116 | 1116 |
|
| 1117 | 1117 |
This will create and run a new container with the container name |
| 1118 | 1118 |
being ``console``. |
| 1119 | 1119 |
|
| 1120 | 1120 |
.. code-block:: bash |
| 1121 | 1121 |
|
| 1122 |
- $ sudo docker run -link /redis:redis -name console ubuntu bash |
|
| 1122 |
+ $ sudo docker run --link /redis:redis --name console ubuntu bash |
|
| 1123 | 1123 |
|
| 1124 |
-The ``-link`` flag will link the container named ``/redis`` into the |
|
| 1124 |
+The ``--link`` flag will link the container named ``/redis`` into the |
|
| 1125 | 1125 |
newly created container with the alias ``redis``. The new container |
| 1126 | 1126 |
can access the network and environment of the redis container via |
| 1127 |
-environment variables. The ``-name`` flag will assign the name ``console`` |
|
| 1127 |
+environment variables. The ``--name`` flag will assign the name ``console`` |
|
| 1128 | 1128 |
to the newly created container. |
| 1129 | 1129 |
|
| 1130 | 1130 |
.. code-block:: bash |
| 1131 | 1131 |
|
| 1132 |
- $ sudo docker run -volumes-from 777f7dc92da7,ba8c0c54f0f2:ro -i -t ubuntu pwd |
|
| 1132 |
+ $ sudo docker run --volumes-from 777f7dc92da7,ba8c0c54f0f2:ro -i -t ubuntu pwd |
|
| 1133 | 1133 |
|
| 1134 |
-The ``-volumes-from`` flag mounts all the defined volumes from the |
|
| 1134 |
+The ``--volumes-from`` flag mounts all the defined volumes from the |
|
| 1135 | 1135 |
referenced containers. Containers can be specified by a comma seperated |
| 1136 |
-list or by repetitions of the ``-volumes-from`` argument. The container |
|
| 1136 |
+list or by repetitions of the ``--volumes-from`` argument. The container |
|
| 1137 | 1137 |
ID may be optionally suffixed with ``:ro`` or ``:rw`` to mount the volumes in |
| 1138 | 1138 |
read-only or read-write mode, respectively. By default, the volumes are mounted |
| 1139 | 1139 |
in the same mode (read write or read only) as the reference container. |
| ... | ... |
@@ -1143,11 +1144,11 @@ A complete example |
| 1143 | 1143 |
|
| 1144 | 1144 |
.. code-block:: bash |
| 1145 | 1145 |
|
| 1146 |
- $ sudo docker run -d -name static static-web-files sh |
|
| 1147 |
- $ sudo docker run -d -expose=8098 -name riak riakserver |
|
| 1148 |
- $ sudo docker run -d -m 100m -e DEVELOPMENT=1 -e BRANCH=example-code -v $(pwd):/app/bin:ro -name app appserver |
|
| 1149 |
- $ sudo docker run -d -p 1443:443 -dns=dns.dev.org -v /var/log/httpd -volumes-from static -link riak -link app -h www.sven.dev.org -name web webserver |
|
| 1150 |
- $ sudo docker run -t -i -rm -volumes-from web -w /var/log/httpd busybox tail -f access.log |
|
| 1146 |
+ $ sudo docker run -d --name static static-web-files sh |
|
| 1147 |
+ $ sudo docker run -d --expose=8098 --name riak riakserver |
|
| 1148 |
+ $ sudo docker run -d -m 100m -e DEVELOPMENT=1 -e BRANCH=example-code -v $(pwd):/app/bin:ro --name app appserver |
|
| 1149 |
+ $ sudo docker run -d -p 1443:443 --dns=dns.dev.org -v /var/log/httpd --volumes-from static --link riak --link app -h www.sven.dev.org --name web webserver |
|
| 1150 |
+ $ sudo docker run -t -i --rm --volumes-from web -w /var/log/httpd busybox tail -f access.log |
|
| 1151 | 1151 |
|
| 1152 | 1152 |
This example shows 5 containers that might be set up to test a web application change: |
| 1153 | 1153 |
|
| ... | ... |
@@ -1181,9 +1182,9 @@ This example shows 5 containers that might be set up to test a web application c |
| 1181 | 1181 |
|
| 1182 | 1182 |
Search the docker index for images |
| 1183 | 1183 |
|
| 1184 |
- -notrunc=false: Don't truncate output |
|
| 1185 |
- -stars=0: Only displays with at least xxx stars |
|
| 1186 |
- -trusted=false: Only show trusted builds |
|
| 1184 |
+ --no-trunc=false: Don't truncate output |
|
| 1185 |
+ -s, --stars=0: Only displays with at least xxx stars |
|
| 1186 |
+ -t, --trusted=false: Only show trusted builds |
|
| 1187 | 1187 |
|
| 1188 | 1188 |
.. _cli_start: |
| 1189 | 1189 |
|
| ... | ... |
@@ -1196,8 +1197,8 @@ This example shows 5 containers that might be set up to test a web application c |
| 1196 | 1196 |
|
| 1197 | 1197 |
Start a stopped container |
| 1198 | 1198 |
|
| 1199 |
- -a=false: Attach container's stdout/stderr and forward all signals to the process |
|
| 1200 |
- -i=false: Attach container's stdin |
|
| 1199 |
+ -a, --attach=false: Attach container's stdout/stderr and forward all signals to the process |
|
| 1200 |
+ -i, --interactive=false: Attach container's stdin |
|
| 1201 | 1201 |
|
| 1202 | 1202 |
.. _cli_stop: |
| 1203 | 1203 |
|
| ... | ... |
@@ -1210,7 +1211,7 @@ This example shows 5 containers that might be set up to test a web application c |
| 1210 | 1210 |
|
| 1211 | 1211 |
Stop a running container (Send SIGTERM, and then SIGKILL after grace period) |
| 1212 | 1212 |
|
| 1213 |
- -t=10: Number of seconds to wait for the container to stop before killing it. |
|
| 1213 |
+ -t, --time=10: Number of seconds to wait for the container to stop before killing it. |
|
| 1214 | 1214 |
|
| 1215 | 1215 |
The main process inside the container will receive SIGTERM, and after a grace period, SIGKILL |
| 1216 | 1216 |
|
| ... | ... |
@@ -1225,7 +1226,7 @@ The main process inside the container will receive SIGTERM, and after a grace pe |
| 1225 | 1225 |
|
| 1226 | 1226 |
Tag an image into a repository |
| 1227 | 1227 |
|
| 1228 |
- -f=false: Force |
|
| 1228 |
+ -f, --force=false: Force |
|
| 1229 | 1229 |
|
| 1230 | 1230 |
.. _cli_top: |
| 1231 | 1231 |
|
| 1232 | 1232 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,27 @@ |
| 0 |
+Copyright (c) 2014 The Docker & Go Authors. All rights reserved. |
|
| 1 |
+ |
|
| 2 |
+Redistribution and use in source and binary forms, with or without |
|
| 3 |
+modification, are permitted provided that the following conditions are |
|
| 4 |
+met: |
|
| 5 |
+ |
|
| 6 |
+ * Redistributions of source code must retain the above copyright |
|
| 7 |
+notice, this list of conditions and the following disclaimer. |
|
| 8 |
+ * Redistributions in binary form must reproduce the above |
|
| 9 |
+copyright notice, this list of conditions and the following disclaimer |
|
| 10 |
+in the documentation and/or other materials provided with the |
|
| 11 |
+distribution. |
|
| 12 |
+ * Neither the name of Google Inc. nor the names of its |
|
| 13 |
+contributors may be used to endorse or promote products derived from |
|
| 14 |
+this software without specific prior written permission. |
|
| 15 |
+ |
|
| 16 |
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
|
| 17 |
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
|
| 18 |
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
|
| 19 |
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
|
| 20 |
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
|
| 21 |
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
|
| 22 |
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
|
| 23 |
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
|
| 24 |
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
|
| 25 |
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
|
| 26 |
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 0 | 27 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,40 @@ |
| 0 |
+Package mflag (aka multiple-flag) implements command-line flag parsing. |
|
| 1 |
+It's an **hacky** fork of the [official golang package](http://golang.org/pkg/flag/) |
|
| 2 |
+ |
|
| 3 |
+It adds: |
|
| 4 |
+ |
|
| 5 |
+* both short and long flag version |
|
| 6 |
+`./example -s red` `./example --string blue` |
|
| 7 |
+ |
|
| 8 |
+* multiple names for the same option |
|
| 9 |
+``` |
|
| 10 |
+$>./example -h |
|
| 11 |
+Usage of example: |
|
| 12 |
+ -s, --string="": a simple string |
|
| 13 |
+``` |
|
| 14 |
+ |
|
| 15 |
+___ |
|
| 16 |
+It is very flexible on purpose, so you can do things like: |
|
| 17 |
+``` |
|
| 18 |
+$>./example -h |
|
| 19 |
+Usage of example: |
|
| 20 |
+ -s, -string, --string="": a simple string |
|
| 21 |
+``` |
|
| 22 |
+ |
|
| 23 |
+Or: |
|
| 24 |
+``` |
|
| 25 |
+$>./example -h |
|
| 26 |
+Usage of example: |
|
| 27 |
+ -oldflag, --newflag="": a simple string |
|
| 28 |
+``` |
|
| 29 |
+ |
|
| 30 |
+You can also hide some flags from the usage, so if we want only `--newflag`: |
|
| 31 |
+``` |
|
| 32 |
+$>./example -h |
|
| 33 |
+Usage of example: |
|
| 34 |
+ --newflag="": a simple string |
|
| 35 |
+$>./example -oldflag str |
|
| 36 |
+str |
|
| 37 |
+``` |
|
| 38 |
+ |
|
| 39 |
+See [example.go](example/example.go) for more details. |
| 0 | 40 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,27 @@ |
| 0 |
+package main |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "fmt" |
|
| 4 |
+ "github.com/dotcloud/docker/pkg/flag" |
|
| 5 |
+) |
|
| 6 |
+ |
|
| 7 |
+var ( |
|
| 8 |
+ i int |
|
| 9 |
+ str string |
|
| 10 |
+ b, h bool |
|
| 11 |
+) |
|
| 12 |
+ |
|
| 13 |
+func init() {
|
|
| 14 |
+ flag.BoolVar(&b, []string{"b"}, false, "a simple bool")
|
|
| 15 |
+ flag.IntVar(&i, []string{"#integer", "-integer"}, -1, "a simple integer")
|
|
| 16 |
+ flag.StringVar(&str, []string{"s", "#hidden", "-string"}, "", "a simple string") //-s -hidden and --string will work, but -hidden won't be in the usage
|
|
| 17 |
+ flag.BoolVar(&h, []string{"h", "#help", "-help"}, false, "display the help")
|
|
| 18 |
+ flag.Parse() |
|
| 19 |
+} |
|
| 20 |
+func main() {
|
|
| 21 |
+ if h {
|
|
| 22 |
+ flag.PrintDefaults() |
|
| 23 |
+ } |
|
| 24 |
+ fmt.Printf("%s\n", str)
|
|
| 25 |
+ fmt.Printf("%s\n", flag.Lookup("s").Value.String())
|
|
| 26 |
+} |
| 0 | 27 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,17 @@ |
| 0 |
+// Copyright 2014 The Docker & Go Authors. All rights reserved. |
|
| 1 |
+// Use of this source code is governed by a BSD-style |
|
| 2 |
+// license that can be found in the LICENSE file. |
|
| 3 |
+ |
|
| 4 |
+package mflag |
|
| 5 |
+ |
|
| 6 |
+import "os" |
|
| 7 |
+ |
|
| 8 |
+// Additional routines compiled into the package only during testing. |
|
| 9 |
+ |
|
| 10 |
+// ResetForTesting clears all flag state and sets the usage function as directed. |
|
| 11 |
+// After calling ResetForTesting, parse errors in flag handling will not |
|
| 12 |
+// exit the program. |
|
| 13 |
+func ResetForTesting(usage func()) {
|
|
| 14 |
+ CommandLine = NewFlagSet(os.Args[0], ContinueOnError) |
|
| 15 |
+ Usage = usage |
|
| 16 |
+} |
| 0 | 17 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,863 @@ |
| 0 |
+// Copyright 2014 The Docker & Go Authors. All rights reserved. |
|
| 1 |
+// Use of this source code is governed by a BSD-style |
|
| 2 |
+// license that can be found in the LICENSE file. |
|
| 3 |
+ |
|
| 4 |
+/* |
|
| 5 |
+ Package flag implements command-line flag parsing. |
|
| 6 |
+ |
|
| 7 |
+ Usage: |
|
| 8 |
+ |
|
| 9 |
+ Define flags using flag.String(), Bool(), Int(), etc. |
|
| 10 |
+ |
|
| 11 |
+ This declares an integer flag, -f or --flagname, stored in the pointer ip, with type *int. |
|
| 12 |
+ import "flag" |
|
| 13 |
+ var ip = flag.Int([]string{"f", "-flagname"}, 1234, "help message for flagname")
|
|
| 14 |
+ If you like, you can bind the flag to a variable using the Var() functions. |
|
| 15 |
+ var flagvar int |
|
| 16 |
+ func init() {
|
|
| 17 |
+ // -flaghidden will work, but will be hidden from the usage |
|
| 18 |
+ flag.IntVar(&flagvar, []string{"f", "#flaghidden", "-flagname"}, 1234, "help message for flagname")
|
|
| 19 |
+ } |
|
| 20 |
+ Or you can create custom flags that satisfy the Value interface (with |
|
| 21 |
+ pointer receivers) and couple them to flag parsing by |
|
| 22 |
+ flag.Var(&flagVal, []string{"name"}, "help message for flagname")
|
|
| 23 |
+ For such flags, the default value is just the initial value of the variable. |
|
| 24 |
+ |
|
| 25 |
+ After all flags are defined, call |
|
| 26 |
+ flag.Parse() |
|
| 27 |
+ to parse the command line into the defined flags. |
|
| 28 |
+ |
|
| 29 |
+ Flags may then be used directly. If you're using the flags themselves, |
|
| 30 |
+ they are all pointers; if you bind to variables, they're values. |
|
| 31 |
+ fmt.Println("ip has value ", *ip)
|
|
| 32 |
+ fmt.Println("flagvar has value ", flagvar)
|
|
| 33 |
+ |
|
| 34 |
+ After parsing, the arguments after the flag are available as the |
|
| 35 |
+ slice flag.Args() or individually as flag.Arg(i). |
|
| 36 |
+ The arguments are indexed from 0 through flag.NArg()-1. |
|
| 37 |
+ |
|
| 38 |
+ Command line flag syntax: |
|
| 39 |
+ -flag |
|
| 40 |
+ -flag=x |
|
| 41 |
+ -flag x // non-boolean flags only |
|
| 42 |
+ One or two minus signs may be used; they are equivalent. |
|
| 43 |
+ The last form is not permitted for boolean flags because the |
|
| 44 |
+ meaning of the command |
|
| 45 |
+ cmd -x * |
|
| 46 |
+ will change if there is a file called 0, false, etc. You must |
|
| 47 |
+ use the -flag=false form to turn off a boolean flag. |
|
| 48 |
+ |
|
| 49 |
+ Flag parsing stops just before the first non-flag argument |
|
| 50 |
+ ("-" is a non-flag argument) or after the terminator "--".
|
|
| 51 |
+ |
|
| 52 |
+ Integer flags accept 1234, 0664, 0x1234 and may be negative. |
|
| 53 |
+ Boolean flags may be 1, 0, t, f, true, false, TRUE, FALSE, True, False. |
|
| 54 |
+ Duration flags accept any input valid for time.ParseDuration. |
|
| 55 |
+ |
|
| 56 |
+ The default set of command-line flags is controlled by |
|
| 57 |
+ top-level functions. The FlagSet type allows one to define |
|
| 58 |
+ independent sets of flags, such as to implement subcommands |
|
| 59 |
+ in a command-line interface. The methods of FlagSet are |
|
| 60 |
+ analogous to the top-level functions for the command-line |
|
| 61 |
+ flag set. |
|
| 62 |
+*/ |
|
| 63 |
+package mflag |
|
| 64 |
+ |
|
| 65 |
+import ( |
|
| 66 |
+ "errors" |
|
| 67 |
+ "fmt" |
|
| 68 |
+ "io" |
|
| 69 |
+ "os" |
|
| 70 |
+ "sort" |
|
| 71 |
+ "strconv" |
|
| 72 |
+ "strings" |
|
| 73 |
+ "time" |
|
| 74 |
+) |
|
| 75 |
+ |
|
| 76 |
+// ErrHelp is the error returned if the flag -help is invoked but no such flag is defined. |
|
| 77 |
+var ErrHelp = errors.New("flag: help requested")
|
|
| 78 |
+ |
|
| 79 |
+// -- bool Value |
|
| 80 |
+type boolValue bool |
|
| 81 |
+ |
|
| 82 |
+func newBoolValue(val bool, p *bool) *boolValue {
|
|
| 83 |
+ *p = val |
|
| 84 |
+ return (*boolValue)(p) |
|
| 85 |
+} |
|
| 86 |
+ |
|
| 87 |
+func (b *boolValue) Set(s string) error {
|
|
| 88 |
+ v, err := strconv.ParseBool(s) |
|
| 89 |
+ *b = boolValue(v) |
|
| 90 |
+ return err |
|
| 91 |
+} |
|
| 92 |
+ |
|
| 93 |
+func (b *boolValue) Get() interface{} { return bool(*b) }
|
|
| 94 |
+ |
|
| 95 |
+func (b *boolValue) String() string { return fmt.Sprintf("%v", *b) }
|
|
| 96 |
+ |
|
| 97 |
+func (b *boolValue) IsBoolFlag() bool { return true }
|
|
| 98 |
+ |
|
| 99 |
+// optional interface to indicate boolean flags that can be |
|
| 100 |
+// supplied without "=value" text |
|
| 101 |
+type boolFlag interface {
|
|
| 102 |
+ Value |
|
| 103 |
+ IsBoolFlag() bool |
|
| 104 |
+} |
|
| 105 |
+ |
|
| 106 |
+// -- int Value |
|
| 107 |
+type intValue int |
|
| 108 |
+ |
|
| 109 |
+func newIntValue(val int, p *int) *intValue {
|
|
| 110 |
+ *p = val |
|
| 111 |
+ return (*intValue)(p) |
|
| 112 |
+} |
|
| 113 |
+ |
|
| 114 |
+func (i *intValue) Set(s string) error {
|
|
| 115 |
+ v, err := strconv.ParseInt(s, 0, 64) |
|
| 116 |
+ *i = intValue(v) |
|
| 117 |
+ return err |
|
| 118 |
+} |
|
| 119 |
+ |
|
| 120 |
+func (i *intValue) Get() interface{} { return int(*i) }
|
|
| 121 |
+ |
|
| 122 |
+func (i *intValue) String() string { return fmt.Sprintf("%v", *i) }
|
|
| 123 |
+ |
|
| 124 |
+// -- int64 Value |
|
| 125 |
+type int64Value int64 |
|
| 126 |
+ |
|
| 127 |
+func newInt64Value(val int64, p *int64) *int64Value {
|
|
| 128 |
+ *p = val |
|
| 129 |
+ return (*int64Value)(p) |
|
| 130 |
+} |
|
| 131 |
+ |
|
| 132 |
+func (i *int64Value) Set(s string) error {
|
|
| 133 |
+ v, err := strconv.ParseInt(s, 0, 64) |
|
| 134 |
+ *i = int64Value(v) |
|
| 135 |
+ return err |
|
| 136 |
+} |
|
| 137 |
+ |
|
| 138 |
+func (i *int64Value) Get() interface{} { return int64(*i) }
|
|
| 139 |
+ |
|
| 140 |
+func (i *int64Value) String() string { return fmt.Sprintf("%v", *i) }
|
|
| 141 |
+ |
|
| 142 |
+// -- uint Value |
|
| 143 |
+type uintValue uint |
|
| 144 |
+ |
|
| 145 |
+func newUintValue(val uint, p *uint) *uintValue {
|
|
| 146 |
+ *p = val |
|
| 147 |
+ return (*uintValue)(p) |
|
| 148 |
+} |
|
| 149 |
+ |
|
| 150 |
+func (i *uintValue) Set(s string) error {
|
|
| 151 |
+ v, err := strconv.ParseUint(s, 0, 64) |
|
| 152 |
+ *i = uintValue(v) |
|
| 153 |
+ return err |
|
| 154 |
+} |
|
| 155 |
+ |
|
| 156 |
+func (i *uintValue) Get() interface{} { return uint(*i) }
|
|
| 157 |
+ |
|
| 158 |
+func (i *uintValue) String() string { return fmt.Sprintf("%v", *i) }
|
|
| 159 |
+ |
|
| 160 |
+// -- uint64 Value |
|
| 161 |
+type uint64Value uint64 |
|
| 162 |
+ |
|
| 163 |
+func newUint64Value(val uint64, p *uint64) *uint64Value {
|
|
| 164 |
+ *p = val |
|
| 165 |
+ return (*uint64Value)(p) |
|
| 166 |
+} |
|
| 167 |
+ |
|
| 168 |
+func (i *uint64Value) Set(s string) error {
|
|
| 169 |
+ v, err := strconv.ParseUint(s, 0, 64) |
|
| 170 |
+ *i = uint64Value(v) |
|
| 171 |
+ return err |
|
| 172 |
+} |
|
| 173 |
+ |
|
| 174 |
+func (i *uint64Value) Get() interface{} { return uint64(*i) }
|
|
| 175 |
+ |
|
| 176 |
+func (i *uint64Value) String() string { return fmt.Sprintf("%v", *i) }
|
|
| 177 |
+ |
|
| 178 |
+// -- string Value |
|
| 179 |
+type stringValue string |
|
| 180 |
+ |
|
| 181 |
+func newStringValue(val string, p *string) *stringValue {
|
|
| 182 |
+ *p = val |
|
| 183 |
+ return (*stringValue)(p) |
|
| 184 |
+} |
|
| 185 |
+ |
|
| 186 |
+func (s *stringValue) Set(val string) error {
|
|
| 187 |
+ *s = stringValue(val) |
|
| 188 |
+ return nil |
|
| 189 |
+} |
|
| 190 |
+ |
|
| 191 |
+func (s *stringValue) Get() interface{} { return string(*s) }
|
|
| 192 |
+ |
|
| 193 |
+func (s *stringValue) String() string { return fmt.Sprintf("%s", *s) }
|
|
| 194 |
+ |
|
| 195 |
+// -- float64 Value |
|
| 196 |
+type float64Value float64 |
|
| 197 |
+ |
|
| 198 |
+func newFloat64Value(val float64, p *float64) *float64Value {
|
|
| 199 |
+ *p = val |
|
| 200 |
+ return (*float64Value)(p) |
|
| 201 |
+} |
|
| 202 |
+ |
|
| 203 |
+func (f *float64Value) Set(s string) error {
|
|
| 204 |
+ v, err := strconv.ParseFloat(s, 64) |
|
| 205 |
+ *f = float64Value(v) |
|
| 206 |
+ return err |
|
| 207 |
+} |
|
| 208 |
+ |
|
| 209 |
+func (f *float64Value) Get() interface{} { return float64(*f) }
|
|
| 210 |
+ |
|
| 211 |
+func (f *float64Value) String() string { return fmt.Sprintf("%v", *f) }
|
|
| 212 |
+ |
|
| 213 |
+// -- time.Duration Value |
|
| 214 |
+type durationValue time.Duration |
|
| 215 |
+ |
|
| 216 |
+func newDurationValue(val time.Duration, p *time.Duration) *durationValue {
|
|
| 217 |
+ *p = val |
|
| 218 |
+ return (*durationValue)(p) |
|
| 219 |
+} |
|
| 220 |
+ |
|
| 221 |
+func (d *durationValue) Set(s string) error {
|
|
| 222 |
+ v, err := time.ParseDuration(s) |
|
| 223 |
+ *d = durationValue(v) |
|
| 224 |
+ return err |
|
| 225 |
+} |
|
| 226 |
+ |
|
| 227 |
+func (d *durationValue) Get() interface{} { return time.Duration(*d) }
|
|
| 228 |
+ |
|
| 229 |
+func (d *durationValue) String() string { return (*time.Duration)(d).String() }
|
|
| 230 |
+ |
|
| 231 |
+// Value is the interface to the dynamic value stored in a flag. |
|
| 232 |
+// (The default value is represented as a string.) |
|
| 233 |
+// |
|
| 234 |
+// If a Value has an IsBoolFlag() bool method returning true, |
|
| 235 |
+// the command-line parser makes -name equivalent to -name=true |
|
| 236 |
+// rather than using the next command-line argument. |
|
| 237 |
+type Value interface {
|
|
| 238 |
+ String() string |
|
| 239 |
+ Set(string) error |
|
| 240 |
+} |
|
| 241 |
+ |
|
| 242 |
+// Getter is an interface that allows the contents of a Value to be retrieved. |
|
| 243 |
+// It wraps the Value interface, rather than being part of it, because it |
|
| 244 |
+// appeared after Go 1 and its compatibility rules. All Value types provided |
|
| 245 |
+// by this package satisfy the Getter interface. |
|
| 246 |
+type Getter interface {
|
|
| 247 |
+ Value |
|
| 248 |
+ Get() interface{}
|
|
| 249 |
+} |
|
| 250 |
+ |
|
| 251 |
+// ErrorHandling defines how to handle flag parsing errors. |
|
| 252 |
+type ErrorHandling int |
|
| 253 |
+ |
|
| 254 |
+const ( |
|
| 255 |
+ ContinueOnError ErrorHandling = iota |
|
| 256 |
+ ExitOnError |
|
| 257 |
+ PanicOnError |
|
| 258 |
+) |
|
| 259 |
+ |
|
| 260 |
+// A FlagSet represents a set of defined flags. The zero value of a FlagSet |
|
| 261 |
+// has no name and has ContinueOnError error handling. |
|
| 262 |
+type FlagSet struct {
|
|
| 263 |
+ // Usage is the function called when an error occurs while parsing flags. |
|
| 264 |
+ // The field is a function (not a method) that may be changed to point to |
|
| 265 |
+ // a custom error handler. |
|
| 266 |
+ Usage func() |
|
| 267 |
+ |
|
| 268 |
+ name string |
|
| 269 |
+ parsed bool |
|
| 270 |
+ actual map[string]*Flag |
|
| 271 |
+ formal map[string]*Flag |
|
| 272 |
+ args []string // arguments after flags |
|
| 273 |
+ errorHandling ErrorHandling |
|
| 274 |
+ output io.Writer // nil means stderr; use out() accessor |
|
| 275 |
+} |
|
| 276 |
+ |
|
| 277 |
+// A Flag represents the state of a flag. |
|
| 278 |
+type Flag struct {
|
|
| 279 |
+ Names []string // name as it appears on command line |
|
| 280 |
+ Usage string // help message |
|
| 281 |
+ Value Value // value as set |
|
| 282 |
+ DefValue string // default value (as text); for usage message |
|
| 283 |
+} |
|
| 284 |
+ |
|
| 285 |
+// sortFlags returns the flags as a slice in lexicographical sorted order. |
|
| 286 |
+func sortFlags(flags map[string]*Flag) []*Flag {
|
|
| 287 |
+ var list sort.StringSlice |
|
| 288 |
+ for _, f := range flags {
|
|
| 289 |
+ found := false |
|
| 290 |
+ fName := strings.TrimPrefix(strings.TrimPrefix(f.Names[0], "#"), "-") |
|
| 291 |
+ for _, name := range list {
|
|
| 292 |
+ if name == fName {
|
|
| 293 |
+ found = true |
|
| 294 |
+ break |
|
| 295 |
+ } |
|
| 296 |
+ } |
|
| 297 |
+ if !found {
|
|
| 298 |
+ list = append(list, fName) |
|
| 299 |
+ } |
|
| 300 |
+ } |
|
| 301 |
+ list.Sort() |
|
| 302 |
+ result := make([]*Flag, len(list)) |
|
| 303 |
+ for i, name := range list {
|
|
| 304 |
+ result[i] = flags[name] |
|
| 305 |
+ } |
|
| 306 |
+ return result |
|
| 307 |
+} |
|
| 308 |
+ |
|
| 309 |
+func (f *FlagSet) out() io.Writer {
|
|
| 310 |
+ if f.output == nil {
|
|
| 311 |
+ return os.Stderr |
|
| 312 |
+ } |
|
| 313 |
+ return f.output |
|
| 314 |
+} |
|
| 315 |
+ |
|
| 316 |
+// SetOutput sets the destination for usage and error messages. |
|
| 317 |
+// If output is nil, os.Stderr is used. |
|
| 318 |
+func (f *FlagSet) SetOutput(output io.Writer) {
|
|
| 319 |
+ f.output = output |
|
| 320 |
+} |
|
| 321 |
+ |
|
| 322 |
+// VisitAll visits the flags in lexicographical order, calling fn for each. |
|
| 323 |
+// It visits all flags, even those not set. |
|
| 324 |
+func (f *FlagSet) VisitAll(fn func(*Flag)) {
|
|
| 325 |
+ for _, flag := range sortFlags(f.formal) {
|
|
| 326 |
+ fn(flag) |
|
| 327 |
+ } |
|
| 328 |
+} |
|
| 329 |
+ |
|
| 330 |
+// VisitAll visits the command-line flags in lexicographical order, calling |
|
| 331 |
+// fn for each. It visits all flags, even those not set. |
|
| 332 |
+func VisitAll(fn func(*Flag)) {
|
|
| 333 |
+ CommandLine.VisitAll(fn) |
|
| 334 |
+} |
|
| 335 |
+ |
|
| 336 |
+// Visit visits the flags in lexicographical order, calling fn for each. |
|
| 337 |
+// It visits only those flags that have been set. |
|
| 338 |
+func (f *FlagSet) Visit(fn func(*Flag)) {
|
|
| 339 |
+ for _, flag := range sortFlags(f.actual) {
|
|
| 340 |
+ fn(flag) |
|
| 341 |
+ } |
|
| 342 |
+} |
|
| 343 |
+ |
|
| 344 |
+// Visit visits the command-line flags in lexicographical order, calling fn |
|
| 345 |
+// for each. It visits only those flags that have been set. |
|
| 346 |
+func Visit(fn func(*Flag)) {
|
|
| 347 |
+ CommandLine.Visit(fn) |
|
| 348 |
+} |
|
| 349 |
+ |
|
| 350 |
+// Lookup returns the Flag structure of the named flag, returning nil if none exists. |
|
| 351 |
+func (f *FlagSet) Lookup(name string) *Flag {
|
|
| 352 |
+ return f.formal[name] |
|
| 353 |
+} |
|
| 354 |
+ |
|
| 355 |
+// Lookup returns the Flag structure of the named command-line flag, |
|
| 356 |
+// returning nil if none exists. |
|
| 357 |
+func Lookup(name string) *Flag {
|
|
| 358 |
+ return CommandLine.formal[name] |
|
| 359 |
+} |
|
| 360 |
+ |
|
| 361 |
+// Set sets the value of the named flag. |
|
| 362 |
+func (f *FlagSet) Set(name, value string) error {
|
|
| 363 |
+ flag, ok := f.formal[name] |
|
| 364 |
+ if !ok {
|
|
| 365 |
+ return fmt.Errorf("no such flag -%v", name)
|
|
| 366 |
+ } |
|
| 367 |
+ err := flag.Value.Set(value) |
|
| 368 |
+ if err != nil {
|
|
| 369 |
+ return err |
|
| 370 |
+ } |
|
| 371 |
+ if f.actual == nil {
|
|
| 372 |
+ f.actual = make(map[string]*Flag) |
|
| 373 |
+ } |
|
| 374 |
+ f.actual[name] = flag |
|
| 375 |
+ return nil |
|
| 376 |
+} |
|
| 377 |
+ |
|
| 378 |
+// Set sets the value of the named command-line flag. |
|
| 379 |
+func Set(name, value string) error {
|
|
| 380 |
+ return CommandLine.Set(name, value) |
|
| 381 |
+} |
|
| 382 |
+ |
|
| 383 |
+// PrintDefaults prints, to standard error unless configured |
|
| 384 |
+// otherwise, the default values of all defined flags in the set. |
|
| 385 |
+func (f *FlagSet) PrintDefaults() {
|
|
| 386 |
+ f.VisitAll(func(flag *Flag) {
|
|
| 387 |
+ format := " -%s=%s: %s\n" |
|
| 388 |
+ if _, ok := flag.Value.(*stringValue); ok {
|
|
| 389 |
+ // put quotes on the value |
|
| 390 |
+ format = " -%s=%q: %s\n" |
|
| 391 |
+ } |
|
| 392 |
+ names := []string{}
|
|
| 393 |
+ for _, name := range flag.Names {
|
|
| 394 |
+ if name[0] != '#' {
|
|
| 395 |
+ names = append(names, name) |
|
| 396 |
+ } |
|
| 397 |
+ } |
|
| 398 |
+ fmt.Fprintf(f.out(), format, strings.Join(names, ", -"), flag.DefValue, flag.Usage) |
|
| 399 |
+ }) |
|
| 400 |
+} |
|
| 401 |
+ |
|
| 402 |
+// PrintDefaults prints to standard error the default values of all defined command-line flags. |
|
| 403 |
+func PrintDefaults() {
|
|
| 404 |
+ CommandLine.PrintDefaults() |
|
| 405 |
+} |
|
| 406 |
+ |
|
| 407 |
+// defaultUsage is the default function to print a usage message. |
|
| 408 |
+func defaultUsage(f *FlagSet) {
|
|
| 409 |
+ if f.name == "" {
|
|
| 410 |
+ fmt.Fprintf(f.out(), "Usage:\n") |
|
| 411 |
+ } else {
|
|
| 412 |
+ fmt.Fprintf(f.out(), "Usage of %s:\n", f.name) |
|
| 413 |
+ } |
|
| 414 |
+ f.PrintDefaults() |
|
| 415 |
+} |
|
| 416 |
+ |
|
| 417 |
+// NOTE: Usage is not just defaultUsage(CommandLine) |
|
| 418 |
+// because it serves (via godoc flag Usage) as the example |
|
| 419 |
+// for how to write your own usage function. |
|
| 420 |
+ |
|
| 421 |
+// Usage prints to standard error a usage message documenting all defined command-line flags. |
|
| 422 |
+// The function is a variable that may be changed to point to a custom function. |
|
| 423 |
+var Usage = func() {
|
|
| 424 |
+ fmt.Fprintf(os.Stderr, "Usage of %s:\n", os.Args[0]) |
|
| 425 |
+ PrintDefaults() |
|
| 426 |
+} |
|
| 427 |
+ |
|
| 428 |
+// NFlag returns the number of flags that have been set. |
|
| 429 |
+func (f *FlagSet) NFlag() int { return len(f.actual) }
|
|
| 430 |
+ |
|
| 431 |
+// NFlag returns the number of command-line flags that have been set. |
|
| 432 |
+func NFlag() int { return len(CommandLine.actual) }
|
|
| 433 |
+ |
|
| 434 |
+// Arg returns the i'th argument. Arg(0) is the first remaining argument |
|
| 435 |
+// after flags have been processed. |
|
| 436 |
+func (f *FlagSet) Arg(i int) string {
|
|
| 437 |
+ if i < 0 || i >= len(f.args) {
|
|
| 438 |
+ return "" |
|
| 439 |
+ } |
|
| 440 |
+ return f.args[i] |
|
| 441 |
+} |
|
| 442 |
+ |
|
| 443 |
+// Arg returns the i'th command-line argument. Arg(0) is the first remaining argument |
|
| 444 |
+// after flags have been processed. |
|
| 445 |
+func Arg(i int) string {
|
|
| 446 |
+ return CommandLine.Arg(i) |
|
| 447 |
+} |
|
| 448 |
+ |
|
| 449 |
+// NArg is the number of arguments remaining after flags have been processed. |
|
| 450 |
+func (f *FlagSet) NArg() int { return len(f.args) }
|
|
| 451 |
+ |
|
| 452 |
+// NArg is the number of arguments remaining after flags have been processed. |
|
| 453 |
+func NArg() int { return len(CommandLine.args) }
|
|
| 454 |
+ |
|
| 455 |
+// Args returns the non-flag arguments. |
|
| 456 |
+func (f *FlagSet) Args() []string { return f.args }
|
|
| 457 |
+ |
|
| 458 |
+// Args returns the non-flag command-line arguments. |
|
| 459 |
+func Args() []string { return CommandLine.args }
|
|
| 460 |
+ |
|
| 461 |
+// BoolVar defines a bool flag with specified name, default value, and usage string. |
|
| 462 |
+// The argument p points to a bool variable in which to store the value of the flag. |
|
| 463 |
+func (f *FlagSet) BoolVar(p *bool, names []string, value bool, usage string) {
|
|
| 464 |
+ f.Var(newBoolValue(value, p), names, usage) |
|
| 465 |
+} |
|
| 466 |
+ |
|
| 467 |
+// BoolVar defines a bool flag with specified name, default value, and usage string. |
|
| 468 |
+// The argument p points to a bool variable in which to store the value of the flag. |
|
| 469 |
+func BoolVar(p *bool, names []string, value bool, usage string) {
|
|
| 470 |
+ CommandLine.Var(newBoolValue(value, p), names, usage) |
|
| 471 |
+} |
|
| 472 |
+ |
|
| 473 |
+// Bool defines a bool flag with specified name, default value, and usage string. |
|
| 474 |
+// The return value is the address of a bool variable that stores the value of the flag. |
|
| 475 |
+func (f *FlagSet) Bool(names []string, value bool, usage string) *bool {
|
|
| 476 |
+ p := new(bool) |
|
| 477 |
+ f.BoolVar(p, names, value, usage) |
|
| 478 |
+ return p |
|
| 479 |
+} |
|
| 480 |
+ |
|
| 481 |
+// Bool defines a bool flag with specified name, default value, and usage string. |
|
| 482 |
+// The return value is the address of a bool variable that stores the value of the flag. |
|
| 483 |
+func Bool(names []string, value bool, usage string) *bool {
|
|
| 484 |
+ return CommandLine.Bool(names, value, usage) |
|
| 485 |
+} |
|
| 486 |
+ |
|
| 487 |
+// IntVar defines an int flag with specified name, default value, and usage string. |
|
| 488 |
+// The argument p points to an int variable in which to store the value of the flag. |
|
| 489 |
+func (f *FlagSet) IntVar(p *int, names []string, value int, usage string) {
|
|
| 490 |
+ f.Var(newIntValue(value, p), names, usage) |
|
| 491 |
+} |
|
| 492 |
+ |
|
| 493 |
+// IntVar defines an int flag with specified name, default value, and usage string. |
|
| 494 |
+// The argument p points to an int variable in which to store the value of the flag. |
|
| 495 |
+func IntVar(p *int, names []string, value int, usage string) {
|
|
| 496 |
+ CommandLine.Var(newIntValue(value, p), names, usage) |
|
| 497 |
+} |
|
| 498 |
+ |
|
| 499 |
+// Int defines an int flag with specified name, default value, and usage string. |
|
| 500 |
+// The return value is the address of an int variable that stores the value of the flag. |
|
| 501 |
+func (f *FlagSet) Int(names []string, value int, usage string) *int {
|
|
| 502 |
+ p := new(int) |
|
| 503 |
+ f.IntVar(p, names, value, usage) |
|
| 504 |
+ return p |
|
| 505 |
+} |
|
| 506 |
+ |
|
| 507 |
+// Int defines an int flag with specified name, default value, and usage string. |
|
| 508 |
+// The return value is the address of an int variable that stores the value of the flag. |
|
| 509 |
+func Int(names []string, value int, usage string) *int {
|
|
| 510 |
+ return CommandLine.Int(names, value, usage) |
|
| 511 |
+} |
|
| 512 |
+ |
|
| 513 |
+// Int64Var defines an int64 flag with specified name, default value, and usage string. |
|
| 514 |
+// The argument p points to an int64 variable in which to store the value of the flag. |
|
| 515 |
+func (f *FlagSet) Int64Var(p *int64, names []string, value int64, usage string) {
|
|
| 516 |
+ f.Var(newInt64Value(value, p), names, usage) |
|
| 517 |
+} |
|
| 518 |
+ |
|
| 519 |
+// Int64Var defines an int64 flag with specified name, default value, and usage string. |
|
| 520 |
+// The argument p points to an int64 variable in which to store the value of the flag. |
|
| 521 |
+func Int64Var(p *int64, names []string, value int64, usage string) {
|
|
| 522 |
+ CommandLine.Var(newInt64Value(value, p), names, usage) |
|
| 523 |
+} |
|
| 524 |
+ |
|
| 525 |
+// Int64 defines an int64 flag with specified name, default value, and usage string. |
|
| 526 |
+// The return value is the address of an int64 variable that stores the value of the flag. |
|
| 527 |
+func (f *FlagSet) Int64(names []string, value int64, usage string) *int64 {
|
|
| 528 |
+ p := new(int64) |
|
| 529 |
+ f.Int64Var(p, names, value, usage) |
|
| 530 |
+ return p |
|
| 531 |
+} |
|
| 532 |
+ |
|
| 533 |
+// Int64 defines an int64 flag with specified name, default value, and usage string. |
|
| 534 |
+// The return value is the address of an int64 variable that stores the value of the flag. |
|
| 535 |
+func Int64(names []string, value int64, usage string) *int64 {
|
|
| 536 |
+ return CommandLine.Int64(names, value, usage) |
|
| 537 |
+} |
|
| 538 |
+ |
|
| 539 |
+// UintVar defines a uint flag with specified name, default value, and usage string. |
|
| 540 |
+// The argument p points to a uint variable in which to store the value of the flag. |
|
| 541 |
+func (f *FlagSet) UintVar(p *uint, names []string, value uint, usage string) {
|
|
| 542 |
+ f.Var(newUintValue(value, p), names, usage) |
|
| 543 |
+} |
|
| 544 |
+ |
|
| 545 |
+// UintVar defines a uint flag with specified name, default value, and usage string. |
|
| 546 |
+// The argument p points to a uint variable in which to store the value of the flag. |
|
| 547 |
+func UintVar(p *uint, names []string, value uint, usage string) {
|
|
| 548 |
+ CommandLine.Var(newUintValue(value, p), names, usage) |
|
| 549 |
+} |
|
| 550 |
+ |
|
| 551 |
+// Uint defines a uint flag with specified name, default value, and usage string. |
|
| 552 |
+// The return value is the address of a uint variable that stores the value of the flag. |
|
| 553 |
+func (f *FlagSet) Uint(names []string, value uint, usage string) *uint {
|
|
| 554 |
+ p := new(uint) |
|
| 555 |
+ f.UintVar(p, names, value, usage) |
|
| 556 |
+ return p |
|
| 557 |
+} |
|
| 558 |
+ |
|
| 559 |
+// Uint defines a uint flag with specified name, default value, and usage string. |
|
| 560 |
+// The return value is the address of a uint variable that stores the value of the flag. |
|
| 561 |
+func Uint(names []string, value uint, usage string) *uint {
|
|
| 562 |
+ return CommandLine.Uint(names, value, usage) |
|
| 563 |
+} |
|
| 564 |
+ |
|
| 565 |
+// Uint64Var defines a uint64 flag with specified name, default value, and usage string. |
|
| 566 |
+// The argument p points to a uint64 variable in which to store the value of the flag. |
|
| 567 |
+func (f *FlagSet) Uint64Var(p *uint64, names []string, value uint64, usage string) {
|
|
| 568 |
+ f.Var(newUint64Value(value, p), names, usage) |
|
| 569 |
+} |
|
| 570 |
+ |
|
| 571 |
+// Uint64Var defines a uint64 flag with specified name, default value, and usage string. |
|
| 572 |
+// The argument p points to a uint64 variable in which to store the value of the flag. |
|
| 573 |
+func Uint64Var(p *uint64, names []string, value uint64, usage string) {
|
|
| 574 |
+ CommandLine.Var(newUint64Value(value, p), names, usage) |
|
| 575 |
+} |
|
| 576 |
+ |
|
| 577 |
+// Uint64 defines a uint64 flag with specified name, default value, and usage string. |
|
| 578 |
+// The return value is the address of a uint64 variable that stores the value of the flag. |
|
| 579 |
+func (f *FlagSet) Uint64(names []string, value uint64, usage string) *uint64 {
|
|
| 580 |
+ p := new(uint64) |
|
| 581 |
+ f.Uint64Var(p, names, value, usage) |
|
| 582 |
+ return p |
|
| 583 |
+} |
|
| 584 |
+ |
|
| 585 |
+// Uint64 defines a uint64 flag with specified name, default value, and usage string. |
|
| 586 |
+// The return value is the address of a uint64 variable that stores the value of the flag. |
|
| 587 |
+func Uint64(names []string, value uint64, usage string) *uint64 {
|
|
| 588 |
+ return CommandLine.Uint64(names, value, usage) |
|
| 589 |
+} |
|
| 590 |
+ |
|
| 591 |
+// StringVar defines a string flag with specified name, default value, and usage string. |
|
| 592 |
+// The argument p points to a string variable in which to store the value of the flag. |
|
| 593 |
+func (f *FlagSet) StringVar(p *string, names []string, value string, usage string) {
|
|
| 594 |
+ f.Var(newStringValue(value, p), names, usage) |
|
| 595 |
+} |
|
| 596 |
+ |
|
| 597 |
+// StringVar defines a string flag with specified name, default value, and usage string. |
|
| 598 |
+// The argument p points to a string variable in which to store the value of the flag. |
|
| 599 |
+func StringVar(p *string, names []string, value string, usage string) {
|
|
| 600 |
+ CommandLine.Var(newStringValue(value, p), names, usage) |
|
| 601 |
+} |
|
| 602 |
+ |
|
| 603 |
+// String defines a string flag with specified name, default value, and usage string. |
|
| 604 |
+// The return value is the address of a string variable that stores the value of the flag. |
|
| 605 |
+func (f *FlagSet) String(names []string, value string, usage string) *string {
|
|
| 606 |
+ p := new(string) |
|
| 607 |
+ f.StringVar(p, names, value, usage) |
|
| 608 |
+ return p |
|
| 609 |
+} |
|
| 610 |
+ |
|
| 611 |
+// String defines a string flag with specified name, default value, and usage string. |
|
| 612 |
+// The return value is the address of a string variable that stores the value of the flag. |
|
| 613 |
+func String(names []string, value string, usage string) *string {
|
|
| 614 |
+ return CommandLine.String(names, value, usage) |
|
| 615 |
+} |
|
| 616 |
+ |
|
| 617 |
+// Float64Var defines a float64 flag with specified name, default value, and usage string. |
|
| 618 |
+// The argument p points to a float64 variable in which to store the value of the flag. |
|
| 619 |
+func (f *FlagSet) Float64Var(p *float64, names []string, value float64, usage string) {
|
|
| 620 |
+ f.Var(newFloat64Value(value, p), names, usage) |
|
| 621 |
+} |
|
| 622 |
+ |
|
| 623 |
+// Float64Var defines a float64 flag with specified name, default value, and usage string. |
|
| 624 |
+// The argument p points to a float64 variable in which to store the value of the flag. |
|
| 625 |
+func Float64Var(p *float64, names []string, value float64, usage string) {
|
|
| 626 |
+ CommandLine.Var(newFloat64Value(value, p), names, usage) |
|
| 627 |
+} |
|
| 628 |
+ |
|
| 629 |
+// Float64 defines a float64 flag with specified name, default value, and usage string. |
|
| 630 |
+// The return value is the address of a float64 variable that stores the value of the flag. |
|
| 631 |
+func (f *FlagSet) Float64(names []string, value float64, usage string) *float64 {
|
|
| 632 |
+ p := new(float64) |
|
| 633 |
+ f.Float64Var(p, names, value, usage) |
|
| 634 |
+ return p |
|
| 635 |
+} |
|
| 636 |
+ |
|
| 637 |
+// Float64 defines a float64 flag with specified name, default value, and usage string. |
|
| 638 |
+// The return value is the address of a float64 variable that stores the value of the flag. |
|
| 639 |
+func Float64(names []string, value float64, usage string) *float64 {
|
|
| 640 |
+ return CommandLine.Float64(names, value, usage) |
|
| 641 |
+} |
|
| 642 |
+ |
|
| 643 |
+// DurationVar defines a time.Duration flag with specified name, default value, and usage string. |
|
| 644 |
+// The argument p points to a time.Duration variable in which to store the value of the flag. |
|
| 645 |
+func (f *FlagSet) DurationVar(p *time.Duration, names []string, value time.Duration, usage string) {
|
|
| 646 |
+ f.Var(newDurationValue(value, p), names, usage) |
|
| 647 |
+} |
|
| 648 |
+ |
|
| 649 |
+// DurationVar defines a time.Duration flag with specified name, default value, and usage string. |
|
| 650 |
+// The argument p points to a time.Duration variable in which to store the value of the flag. |
|
| 651 |
+func DurationVar(p *time.Duration, names []string, value time.Duration, usage string) {
|
|
| 652 |
+ CommandLine.Var(newDurationValue(value, p), names, usage) |
|
| 653 |
+} |
|
| 654 |
+ |
|
| 655 |
+// Duration defines a time.Duration flag with specified name, default value, and usage string. |
|
| 656 |
+// The return value is the address of a time.Duration variable that stores the value of the flag. |
|
| 657 |
+func (f *FlagSet) Duration(names []string, value time.Duration, usage string) *time.Duration {
|
|
| 658 |
+ p := new(time.Duration) |
|
| 659 |
+ f.DurationVar(p, names, value, usage) |
|
| 660 |
+ return p |
|
| 661 |
+} |
|
| 662 |
+ |
|
| 663 |
+// Duration defines a time.Duration flag with specified name, default value, and usage string. |
|
| 664 |
+// The return value is the address of a time.Duration variable that stores the value of the flag. |
|
| 665 |
+func Duration(names []string, value time.Duration, usage string) *time.Duration {
|
|
| 666 |
+ return CommandLine.Duration(names, value, usage) |
|
| 667 |
+} |
|
| 668 |
+ |
|
| 669 |
+// Var defines a flag with the specified name and usage string. The type and |
|
| 670 |
+// value of the flag are represented by the first argument, of type Value, which |
|
| 671 |
+// typically holds a user-defined implementation of Value. For instance, the |
|
| 672 |
+// caller could create a flag that turns a comma-separated string into a slice |
|
| 673 |
+// of strings by giving the slice the methods of Value; in particular, Set would |
|
| 674 |
+// decompose the comma-separated string into the slice. |
|
| 675 |
+func (f *FlagSet) Var(value Value, names []string, usage string) {
|
|
| 676 |
+ // Remember the default value as a string; it won't change. |
|
| 677 |
+ flag := &Flag{names, usage, value, value.String()}
|
|
| 678 |
+ for _, name := range names {
|
|
| 679 |
+ name = strings.TrimPrefix(name, "#") |
|
| 680 |
+ _, alreadythere := f.formal[name] |
|
| 681 |
+ if alreadythere {
|
|
| 682 |
+ var msg string |
|
| 683 |
+ if f.name == "" {
|
|
| 684 |
+ msg = fmt.Sprintf("flag redefined: %s", name)
|
|
| 685 |
+ } else {
|
|
| 686 |
+ msg = fmt.Sprintf("%s flag redefined: %s", f.name, name)
|
|
| 687 |
+ } |
|
| 688 |
+ fmt.Fprintln(f.out(), msg) |
|
| 689 |
+ panic(msg) // Happens only if flags are declared with identical names |
|
| 690 |
+ } |
|
| 691 |
+ if f.formal == nil {
|
|
| 692 |
+ f.formal = make(map[string]*Flag) |
|
| 693 |
+ } |
|
| 694 |
+ f.formal[name] = flag |
|
| 695 |
+ } |
|
| 696 |
+} |
|
| 697 |
+ |
|
| 698 |
+// Var defines a flag with the specified name and usage string. The type and |
|
| 699 |
+// value of the flag are represented by the first argument, of type Value, which |
|
| 700 |
+// typically holds a user-defined implementation of Value. For instance, the |
|
| 701 |
+// caller could create a flag that turns a comma-separated string into a slice |
|
| 702 |
+// of strings by giving the slice the methods of Value; in particular, Set would |
|
| 703 |
+// decompose the comma-separated string into the slice. |
|
| 704 |
+func Var(value Value, names []string, usage string) {
|
|
| 705 |
+ CommandLine.Var(value, names, usage) |
|
| 706 |
+} |
|
| 707 |
+ |
|
| 708 |
+// failf prints to standard error a formatted error and usage message and |
|
| 709 |
+// returns the error. |
|
| 710 |
+func (f *FlagSet) failf(format string, a ...interface{}) error {
|
|
| 711 |
+ err := fmt.Errorf(format, a...) |
|
| 712 |
+ fmt.Fprintln(f.out(), err) |
|
| 713 |
+ f.usage() |
|
| 714 |
+ return err |
|
| 715 |
+} |
|
| 716 |
+ |
|
| 717 |
+// usage calls the Usage method for the flag set, or the usage function if |
|
| 718 |
+// the flag set is CommandLine. |
|
| 719 |
+func (f *FlagSet) usage() {
|
|
| 720 |
+ if f == CommandLine {
|
|
| 721 |
+ Usage() |
|
| 722 |
+ } else if f.Usage == nil {
|
|
| 723 |
+ defaultUsage(f) |
|
| 724 |
+ } else {
|
|
| 725 |
+ f.Usage() |
|
| 726 |
+ } |
|
| 727 |
+} |
|
| 728 |
+ |
|
| 729 |
+// parseOne parses one flag. It reports whether a flag was seen. |
|
| 730 |
+func (f *FlagSet) parseOne() (bool, error) {
|
|
| 731 |
+ if len(f.args) == 0 {
|
|
| 732 |
+ return false, nil |
|
| 733 |
+ } |
|
| 734 |
+ s := f.args[0] |
|
| 735 |
+ if len(s) == 0 || s[0] != '-' || len(s) == 1 {
|
|
| 736 |
+ return false, nil |
|
| 737 |
+ } |
|
| 738 |
+ if s[1] == '-' && len(s) == 2 { // "--" terminates the flags
|
|
| 739 |
+ f.args = f.args[1:] |
|
| 740 |
+ return false, nil |
|
| 741 |
+ } |
|
| 742 |
+ name := s[1:] |
|
| 743 |
+ if len(name) == 0 || name[0] == '=' {
|
|
| 744 |
+ return false, f.failf("bad flag syntax: %s", s)
|
|
| 745 |
+ } |
|
| 746 |
+ |
|
| 747 |
+ // it's a flag. does it have an argument? |
|
| 748 |
+ f.args = f.args[1:] |
|
| 749 |
+ has_value := false |
|
| 750 |
+ value := "" |
|
| 751 |
+ for i := 1; i < len(name); i++ { // equals cannot be first
|
|
| 752 |
+ if name[i] == '=' {
|
|
| 753 |
+ value = name[i+1:] |
|
| 754 |
+ has_value = true |
|
| 755 |
+ name = name[0:i] |
|
| 756 |
+ break |
|
| 757 |
+ } |
|
| 758 |
+ } |
|
| 759 |
+ m := f.formal |
|
| 760 |
+ flag, alreadythere := m[name] // BUG |
|
| 761 |
+ if !alreadythere {
|
|
| 762 |
+ if name == "-help" || name == "help" || name == "h" { // special case for nice help message.
|
|
| 763 |
+ f.usage() |
|
| 764 |
+ return false, ErrHelp |
|
| 765 |
+ } |
|
| 766 |
+ return false, f.failf("flag provided but not defined: -%s", name)
|
|
| 767 |
+ } |
|
| 768 |
+ if fv, ok := flag.Value.(boolFlag); ok && fv.IsBoolFlag() { // special case: doesn't need an arg
|
|
| 769 |
+ if has_value {
|
|
| 770 |
+ if err := fv.Set(value); err != nil {
|
|
| 771 |
+ return false, f.failf("invalid boolean value %q for -%s: %v", value, name, err)
|
|
| 772 |
+ } |
|
| 773 |
+ } else {
|
|
| 774 |
+ fv.Set("true")
|
|
| 775 |
+ } |
|
| 776 |
+ } else {
|
|
| 777 |
+ // It must have a value, which might be the next argument. |
|
| 778 |
+ if !has_value && len(f.args) > 0 {
|
|
| 779 |
+ // value is the next arg |
|
| 780 |
+ has_value = true |
|
| 781 |
+ value, f.args = f.args[0], f.args[1:] |
|
| 782 |
+ } |
|
| 783 |
+ if !has_value {
|
|
| 784 |
+ return false, f.failf("flag needs an argument: -%s", name)
|
|
| 785 |
+ } |
|
| 786 |
+ if err := flag.Value.Set(value); err != nil {
|
|
| 787 |
+ return false, f.failf("invalid value %q for flag -%s: %v", value, name, err)
|
|
| 788 |
+ } |
|
| 789 |
+ } |
|
| 790 |
+ if f.actual == nil {
|
|
| 791 |
+ f.actual = make(map[string]*Flag) |
|
| 792 |
+ } |
|
| 793 |
+ f.actual[name] = flag |
|
| 794 |
+ return true, nil |
|
| 795 |
+} |
|
| 796 |
+ |
|
| 797 |
+// Parse parses flag definitions from the argument list, which should not |
|
| 798 |
+// include the command name. Must be called after all flags in the FlagSet |
|
| 799 |
+// are defined and before flags are accessed by the program. |
|
| 800 |
+// The return value will be ErrHelp if -help was set but not defined. |
|
| 801 |
+func (f *FlagSet) Parse(arguments []string) error {
|
|
| 802 |
+ f.parsed = true |
|
| 803 |
+ f.args = arguments |
|
| 804 |
+ for {
|
|
| 805 |
+ seen, err := f.parseOne() |
|
| 806 |
+ if seen {
|
|
| 807 |
+ continue |
|
| 808 |
+ } |
|
| 809 |
+ if err == nil {
|
|
| 810 |
+ break |
|
| 811 |
+ } |
|
| 812 |
+ switch f.errorHandling {
|
|
| 813 |
+ case ContinueOnError: |
|
| 814 |
+ return err |
|
| 815 |
+ case ExitOnError: |
|
| 816 |
+ os.Exit(2) |
|
| 817 |
+ case PanicOnError: |
|
| 818 |
+ panic(err) |
|
| 819 |
+ } |
|
| 820 |
+ } |
|
| 821 |
+ return nil |
|
| 822 |
+} |
|
| 823 |
+ |
|
| 824 |
+// Parsed reports whether f.Parse has been called. |
|
| 825 |
+func (f *FlagSet) Parsed() bool {
|
|
| 826 |
+ return f.parsed |
|
| 827 |
+} |
|
| 828 |
+ |
|
| 829 |
+// Parse parses the command-line flags from os.Args[1:]. Must be called |
|
| 830 |
+// after all flags are defined and before flags are accessed by the program. |
|
| 831 |
+func Parse() {
|
|
| 832 |
+ // Ignore errors; CommandLine is set for ExitOnError. |
|
| 833 |
+ CommandLine.Parse(os.Args[1:]) |
|
| 834 |
+} |
|
| 835 |
+ |
|
| 836 |
+// Parsed returns true if the command-line flags have been parsed. |
|
| 837 |
+func Parsed() bool {
|
|
| 838 |
+ return CommandLine.Parsed() |
|
| 839 |
+} |
|
| 840 |
+ |
|
| 841 |
+// CommandLine is the default set of command-line flags, parsed from os.Args. |
|
| 842 |
+// The top-level functions such as BoolVar, Arg, and on are wrappers for the |
|
| 843 |
+// methods of CommandLine. |
|
| 844 |
+var CommandLine = NewFlagSet(os.Args[0], ExitOnError) |
|
| 845 |
+ |
|
| 846 |
+// NewFlagSet returns a new, empty flag set with the specified name and |
|
| 847 |
+// error handling property. |
|
| 848 |
+func NewFlagSet(name string, errorHandling ErrorHandling) *FlagSet {
|
|
| 849 |
+ f := &FlagSet{
|
|
| 850 |
+ name: name, |
|
| 851 |
+ errorHandling: errorHandling, |
|
| 852 |
+ } |
|
| 853 |
+ return f |
|
| 854 |
+} |
|
| 855 |
+ |
|
| 856 |
+// Init sets the name and error handling property for a flag set. |
|
| 857 |
+// By default, the zero FlagSet uses an empty name and the |
|
| 858 |
+// ContinueOnError error handling policy. |
|
| 859 |
+func (f *FlagSet) Init(name string, errorHandling ErrorHandling) {
|
|
| 860 |
+ f.name = name |
|
| 861 |
+ f.errorHandling = errorHandling |
|
| 862 |
+} |
| 0 | 863 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,377 @@ |
| 0 |
+// Copyright 2014 The Docker & Go Authors. All rights reserved. |
|
| 1 |
+// Use of this source code is governed by a BSD-style |
|
| 2 |
+// license that can be found in the LICENSE file. |
|
| 3 |
+ |
|
| 4 |
+package mflag_test |
|
| 5 |
+ |
|
| 6 |
+import ( |
|
| 7 |
+ "bytes" |
|
| 8 |
+ "fmt" |
|
| 9 |
+ . "github.com/dotcloud/docker/pkg/mflag" |
|
| 10 |
+ "os" |
|
| 11 |
+ "sort" |
|
| 12 |
+ "strings" |
|
| 13 |
+ "testing" |
|
| 14 |
+ "time" |
|
| 15 |
+) |
|
| 16 |
+ |
|
| 17 |
+func boolString(s string) string {
|
|
| 18 |
+ if s == "0" {
|
|
| 19 |
+ return "false" |
|
| 20 |
+ } |
|
| 21 |
+ return "true" |
|
| 22 |
+} |
|
| 23 |
+ |
|
| 24 |
+func TestEverything(t *testing.T) {
|
|
| 25 |
+ ResetForTesting(nil) |
|
| 26 |
+ Bool([]string{"test_bool"}, false, "bool value")
|
|
| 27 |
+ Int([]string{"test_int"}, 0, "int value")
|
|
| 28 |
+ Int64([]string{"test_int64"}, 0, "int64 value")
|
|
| 29 |
+ Uint([]string{"test_uint"}, 0, "uint value")
|
|
| 30 |
+ Uint64([]string{"test_uint64"}, 0, "uint64 value")
|
|
| 31 |
+ String([]string{"test_string"}, "0", "string value")
|
|
| 32 |
+ Float64([]string{"test_float64"}, 0, "float64 value")
|
|
| 33 |
+ Duration([]string{"test_duration"}, 0, "time.Duration value")
|
|
| 34 |
+ |
|
| 35 |
+ m := make(map[string]*Flag) |
|
| 36 |
+ desired := "0" |
|
| 37 |
+ visitor := func(f *Flag) {
|
|
| 38 |
+ for _, name := range f.Names {
|
|
| 39 |
+ if len(name) > 5 && name[0:5] == "test_" {
|
|
| 40 |
+ m[name] = f |
|
| 41 |
+ ok := false |
|
| 42 |
+ switch {
|
|
| 43 |
+ case f.Value.String() == desired: |
|
| 44 |
+ ok = true |
|
| 45 |
+ case name == "test_bool" && f.Value.String() == boolString(desired): |
|
| 46 |
+ ok = true |
|
| 47 |
+ case name == "test_duration" && f.Value.String() == desired+"s": |
|
| 48 |
+ ok = true |
|
| 49 |
+ } |
|
| 50 |
+ if !ok {
|
|
| 51 |
+ t.Error("Visit: bad value", f.Value.String(), "for", name)
|
|
| 52 |
+ } |
|
| 53 |
+ } |
|
| 54 |
+ } |
|
| 55 |
+ } |
|
| 56 |
+ VisitAll(visitor) |
|
| 57 |
+ if len(m) != 8 {
|
|
| 58 |
+ t.Error("VisitAll misses some flags")
|
|
| 59 |
+ for k, v := range m {
|
|
| 60 |
+ t.Log(k, *v) |
|
| 61 |
+ } |
|
| 62 |
+ } |
|
| 63 |
+ m = make(map[string]*Flag) |
|
| 64 |
+ Visit(visitor) |
|
| 65 |
+ if len(m) != 0 {
|
|
| 66 |
+ t.Errorf("Visit sees unset flags")
|
|
| 67 |
+ for k, v := range m {
|
|
| 68 |
+ t.Log(k, *v) |
|
| 69 |
+ } |
|
| 70 |
+ } |
|
| 71 |
+ // Now set all flags |
|
| 72 |
+ Set("test_bool", "true")
|
|
| 73 |
+ Set("test_int", "1")
|
|
| 74 |
+ Set("test_int64", "1")
|
|
| 75 |
+ Set("test_uint", "1")
|
|
| 76 |
+ Set("test_uint64", "1")
|
|
| 77 |
+ Set("test_string", "1")
|
|
| 78 |
+ Set("test_float64", "1")
|
|
| 79 |
+ Set("test_duration", "1s")
|
|
| 80 |
+ desired = "1" |
|
| 81 |
+ Visit(visitor) |
|
| 82 |
+ if len(m) != 8 {
|
|
| 83 |
+ t.Error("Visit fails after set")
|
|
| 84 |
+ for k, v := range m {
|
|
| 85 |
+ t.Log(k, *v) |
|
| 86 |
+ } |
|
| 87 |
+ } |
|
| 88 |
+ // Now test they're visited in sort order. |
|
| 89 |
+ var flagNames []string |
|
| 90 |
+ Visit(func(f *Flag) {
|
|
| 91 |
+ for _, name := range f.Names {
|
|
| 92 |
+ flagNames = append(flagNames, name) |
|
| 93 |
+ } |
|
| 94 |
+ }) |
|
| 95 |
+ if !sort.StringsAreSorted(flagNames) {
|
|
| 96 |
+ t.Errorf("flag names not sorted: %v", flagNames)
|
|
| 97 |
+ } |
|
| 98 |
+} |
|
| 99 |
+ |
|
| 100 |
+func TestGet(t *testing.T) {
|
|
| 101 |
+ ResetForTesting(nil) |
|
| 102 |
+ Bool([]string{"test_bool"}, true, "bool value")
|
|
| 103 |
+ Int([]string{"test_int"}, 1, "int value")
|
|
| 104 |
+ Int64([]string{"test_int64"}, 2, "int64 value")
|
|
| 105 |
+ Uint([]string{"test_uint"}, 3, "uint value")
|
|
| 106 |
+ Uint64([]string{"test_uint64"}, 4, "uint64 value")
|
|
| 107 |
+ String([]string{"test_string"}, "5", "string value")
|
|
| 108 |
+ Float64([]string{"test_float64"}, 6, "float64 value")
|
|
| 109 |
+ Duration([]string{"test_duration"}, 7, "time.Duration value")
|
|
| 110 |
+ |
|
| 111 |
+ visitor := func(f *Flag) {
|
|
| 112 |
+ for _, name := range f.Names {
|
|
| 113 |
+ if len(name) > 5 && name[0:5] == "test_" {
|
|
| 114 |
+ g, ok := f.Value.(Getter) |
|
| 115 |
+ if !ok {
|
|
| 116 |
+ t.Errorf("Visit: value does not satisfy Getter: %T", f.Value)
|
|
| 117 |
+ return |
|
| 118 |
+ } |
|
| 119 |
+ switch name {
|
|
| 120 |
+ case "test_bool": |
|
| 121 |
+ ok = g.Get() == true |
|
| 122 |
+ case "test_int": |
|
| 123 |
+ ok = g.Get() == int(1) |
|
| 124 |
+ case "test_int64": |
|
| 125 |
+ ok = g.Get() == int64(2) |
|
| 126 |
+ case "test_uint": |
|
| 127 |
+ ok = g.Get() == uint(3) |
|
| 128 |
+ case "test_uint64": |
|
| 129 |
+ ok = g.Get() == uint64(4) |
|
| 130 |
+ case "test_string": |
|
| 131 |
+ ok = g.Get() == "5" |
|
| 132 |
+ case "test_float64": |
|
| 133 |
+ ok = g.Get() == float64(6) |
|
| 134 |
+ case "test_duration": |
|
| 135 |
+ ok = g.Get() == time.Duration(7) |
|
| 136 |
+ } |
|
| 137 |
+ if !ok {
|
|
| 138 |
+ t.Errorf("Visit: bad value %T(%v) for %s", g.Get(), g.Get(), name)
|
|
| 139 |
+ } |
|
| 140 |
+ } |
|
| 141 |
+ } |
|
| 142 |
+ } |
|
| 143 |
+ VisitAll(visitor) |
|
| 144 |
+} |
|
| 145 |
+ |
|
| 146 |
+func TestUsage(t *testing.T) {
|
|
| 147 |
+ called := false |
|
| 148 |
+ ResetForTesting(func() { called = true })
|
|
| 149 |
+ if CommandLine.Parse([]string{"-x"}) == nil {
|
|
| 150 |
+ t.Error("parse did not fail for unknown flag")
|
|
| 151 |
+ } |
|
| 152 |
+ if !called {
|
|
| 153 |
+ t.Error("did not call Usage for unknown flag")
|
|
| 154 |
+ } |
|
| 155 |
+} |
|
| 156 |
+ |
|
| 157 |
+func testParse(f *FlagSet, t *testing.T) {
|
|
| 158 |
+ if f.Parsed() {
|
|
| 159 |
+ t.Error("f.Parse() = true before Parse")
|
|
| 160 |
+ } |
|
| 161 |
+ boolFlag := f.Bool([]string{"bool"}, false, "bool value")
|
|
| 162 |
+ bool2Flag := f.Bool([]string{"bool2"}, false, "bool2 value")
|
|
| 163 |
+ intFlag := f.Int([]string{"-int"}, 0, "int value")
|
|
| 164 |
+ int64Flag := f.Int64([]string{"-int64"}, 0, "int64 value")
|
|
| 165 |
+ uintFlag := f.Uint([]string{"uint"}, 0, "uint value")
|
|
| 166 |
+ uint64Flag := f.Uint64([]string{"-uint64"}, 0, "uint64 value")
|
|
| 167 |
+ stringFlag := f.String([]string{"string"}, "0", "string value")
|
|
| 168 |
+ float64Flag := f.Float64([]string{"float64"}, 0, "float64 value")
|
|
| 169 |
+ durationFlag := f.Duration([]string{"duration"}, 5*time.Second, "time.Duration value")
|
|
| 170 |
+ extra := "one-extra-argument" |
|
| 171 |
+ args := []string{
|
|
| 172 |
+ "-bool", |
|
| 173 |
+ "-bool2=true", |
|
| 174 |
+ "--int", "22", |
|
| 175 |
+ "--int64", "0x23", |
|
| 176 |
+ "-uint", "24", |
|
| 177 |
+ "--uint64", "25", |
|
| 178 |
+ "-string", "hello", |
|
| 179 |
+ "-float64", "2718e28", |
|
| 180 |
+ "-duration", "2m", |
|
| 181 |
+ extra, |
|
| 182 |
+ } |
|
| 183 |
+ if err := f.Parse(args); err != nil {
|
|
| 184 |
+ t.Fatal(err) |
|
| 185 |
+ } |
|
| 186 |
+ if !f.Parsed() {
|
|
| 187 |
+ t.Error("f.Parse() = false after Parse")
|
|
| 188 |
+ } |
|
| 189 |
+ if *boolFlag != true {
|
|
| 190 |
+ t.Error("bool flag should be true, is ", *boolFlag)
|
|
| 191 |
+ } |
|
| 192 |
+ if *bool2Flag != true {
|
|
| 193 |
+ t.Error("bool2 flag should be true, is ", *bool2Flag)
|
|
| 194 |
+ } |
|
| 195 |
+ if *intFlag != 22 {
|
|
| 196 |
+ t.Error("int flag should be 22, is ", *intFlag)
|
|
| 197 |
+ } |
|
| 198 |
+ if *int64Flag != 0x23 {
|
|
| 199 |
+ t.Error("int64 flag should be 0x23, is ", *int64Flag)
|
|
| 200 |
+ } |
|
| 201 |
+ if *uintFlag != 24 {
|
|
| 202 |
+ t.Error("uint flag should be 24, is ", *uintFlag)
|
|
| 203 |
+ } |
|
| 204 |
+ if *uint64Flag != 25 {
|
|
| 205 |
+ t.Error("uint64 flag should be 25, is ", *uint64Flag)
|
|
| 206 |
+ } |
|
| 207 |
+ if *stringFlag != "hello" {
|
|
| 208 |
+ t.Error("string flag should be `hello`, is ", *stringFlag)
|
|
| 209 |
+ } |
|
| 210 |
+ if *float64Flag != 2718e28 {
|
|
| 211 |
+ t.Error("float64 flag should be 2718e28, is ", *float64Flag)
|
|
| 212 |
+ } |
|
| 213 |
+ if *durationFlag != 2*time.Minute {
|
|
| 214 |
+ t.Error("duration flag should be 2m, is ", *durationFlag)
|
|
| 215 |
+ } |
|
| 216 |
+ if len(f.Args()) != 1 {
|
|
| 217 |
+ t.Error("expected one argument, got", len(f.Args()))
|
|
| 218 |
+ } else if f.Args()[0] != extra {
|
|
| 219 |
+ t.Errorf("expected argument %q got %q", extra, f.Args()[0])
|
|
| 220 |
+ } |
|
| 221 |
+} |
|
| 222 |
+ |
|
| 223 |
+func TestParse(t *testing.T) {
|
|
| 224 |
+ ResetForTesting(func() { t.Error("bad parse") })
|
|
| 225 |
+ testParse(CommandLine, t) |
|
| 226 |
+} |
|
| 227 |
+ |
|
| 228 |
+func TestFlagSetParse(t *testing.T) {
|
|
| 229 |
+ testParse(NewFlagSet("test", ContinueOnError), t)
|
|
| 230 |
+} |
|
| 231 |
+ |
|
| 232 |
+// Declare a user-defined flag type. |
|
| 233 |
+type flagVar []string |
|
| 234 |
+ |
|
| 235 |
+func (f *flagVar) String() string {
|
|
| 236 |
+ return fmt.Sprint([]string(*f)) |
|
| 237 |
+} |
|
| 238 |
+ |
|
| 239 |
+func (f *flagVar) Set(value string) error {
|
|
| 240 |
+ *f = append(*f, value) |
|
| 241 |
+ return nil |
|
| 242 |
+} |
|
| 243 |
+ |
|
| 244 |
+func TestUserDefined(t *testing.T) {
|
|
| 245 |
+ var flags FlagSet |
|
| 246 |
+ flags.Init("test", ContinueOnError)
|
|
| 247 |
+ var v flagVar |
|
| 248 |
+ flags.Var(&v, []string{"v"}, "usage")
|
|
| 249 |
+ if err := flags.Parse([]string{"-v", "1", "-v", "2", "-v=3"}); err != nil {
|
|
| 250 |
+ t.Error(err) |
|
| 251 |
+ } |
|
| 252 |
+ if len(v) != 3 {
|
|
| 253 |
+ t.Fatal("expected 3 args; got ", len(v))
|
|
| 254 |
+ } |
|
| 255 |
+ expect := "[1 2 3]" |
|
| 256 |
+ if v.String() != expect {
|
|
| 257 |
+ t.Errorf("expected value %q got %q", expect, v.String())
|
|
| 258 |
+ } |
|
| 259 |
+} |
|
| 260 |
+ |
|
| 261 |
+// Declare a user-defined boolean flag type. |
|
| 262 |
+type boolFlagVar struct {
|
|
| 263 |
+ count int |
|
| 264 |
+} |
|
| 265 |
+ |
|
| 266 |
+func (b *boolFlagVar) String() string {
|
|
| 267 |
+ return fmt.Sprintf("%d", b.count)
|
|
| 268 |
+} |
|
| 269 |
+ |
|
| 270 |
+func (b *boolFlagVar) Set(value string) error {
|
|
| 271 |
+ if value == "true" {
|
|
| 272 |
+ b.count++ |
|
| 273 |
+ } |
|
| 274 |
+ return nil |
|
| 275 |
+} |
|
| 276 |
+ |
|
| 277 |
+func (b *boolFlagVar) IsBoolFlag() bool {
|
|
| 278 |
+ return b.count < 4 |
|
| 279 |
+} |
|
| 280 |
+ |
|
| 281 |
+func TestUserDefinedBool(t *testing.T) {
|
|
| 282 |
+ var flags FlagSet |
|
| 283 |
+ flags.Init("test", ContinueOnError)
|
|
| 284 |
+ var b boolFlagVar |
|
| 285 |
+ var err error |
|
| 286 |
+ flags.Var(&b, []string{"b"}, "usage")
|
|
| 287 |
+ if err = flags.Parse([]string{"-b", "-b", "-b", "-b=true", "-b=false", "-b", "barg", "-b"}); err != nil {
|
|
| 288 |
+ if b.count < 4 {
|
|
| 289 |
+ t.Error(err) |
|
| 290 |
+ } |
|
| 291 |
+ } |
|
| 292 |
+ |
|
| 293 |
+ if b.count != 4 {
|
|
| 294 |
+ t.Errorf("want: %d; got: %d", 4, b.count)
|
|
| 295 |
+ } |
|
| 296 |
+ |
|
| 297 |
+ if err == nil {
|
|
| 298 |
+ t.Error("expected error; got none")
|
|
| 299 |
+ } |
|
| 300 |
+} |
|
| 301 |
+ |
|
| 302 |
+func TestSetOutput(t *testing.T) {
|
|
| 303 |
+ var flags FlagSet |
|
| 304 |
+ var buf bytes.Buffer |
|
| 305 |
+ flags.SetOutput(&buf) |
|
| 306 |
+ flags.Init("test", ContinueOnError)
|
|
| 307 |
+ flags.Parse([]string{"-unknown"})
|
|
| 308 |
+ if out := buf.String(); !strings.Contains(out, "-unknown") {
|
|
| 309 |
+ t.Logf("expected output mentioning unknown; got %q", out)
|
|
| 310 |
+ } |
|
| 311 |
+} |
|
| 312 |
+ |
|
| 313 |
+// This tests that one can reset the flags. This still works but not well, and is |
|
| 314 |
+// superseded by FlagSet. |
|
| 315 |
+func TestChangingArgs(t *testing.T) {
|
|
| 316 |
+ ResetForTesting(func() { t.Fatal("bad parse") })
|
|
| 317 |
+ oldArgs := os.Args |
|
| 318 |
+ defer func() { os.Args = oldArgs }()
|
|
| 319 |
+ os.Args = []string{"cmd", "-before", "subcmd", "-after", "args"}
|
|
| 320 |
+ before := Bool([]string{"before"}, false, "")
|
|
| 321 |
+ if err := CommandLine.Parse(os.Args[1:]); err != nil {
|
|
| 322 |
+ t.Fatal(err) |
|
| 323 |
+ } |
|
| 324 |
+ cmd := Arg(0) |
|
| 325 |
+ os.Args = Args() |
|
| 326 |
+ after := Bool([]string{"after"}, false, "")
|
|
| 327 |
+ Parse() |
|
| 328 |
+ args := Args() |
|
| 329 |
+ |
|
| 330 |
+ if !*before || cmd != "subcmd" || !*after || len(args) != 1 || args[0] != "args" {
|
|
| 331 |
+ t.Fatalf("expected true subcmd true [args] got %v %v %v %v", *before, cmd, *after, args)
|
|
| 332 |
+ } |
|
| 333 |
+} |
|
| 334 |
+ |
|
| 335 |
+// Test that -help invokes the usage message and returns ErrHelp. |
|
| 336 |
+func TestHelp(t *testing.T) {
|
|
| 337 |
+ var helpCalled = false |
|
| 338 |
+ fs := NewFlagSet("help test", ContinueOnError)
|
|
| 339 |
+ fs.Usage = func() { helpCalled = true }
|
|
| 340 |
+ var flag bool |
|
| 341 |
+ fs.BoolVar(&flag, []string{"flag"}, false, "regular flag")
|
|
| 342 |
+ // Regular flag invocation should work |
|
| 343 |
+ err := fs.Parse([]string{"-flag=true"})
|
|
| 344 |
+ if err != nil {
|
|
| 345 |
+ t.Fatal("expected no error; got ", err)
|
|
| 346 |
+ } |
|
| 347 |
+ if !flag {
|
|
| 348 |
+ t.Error("flag was not set by -flag")
|
|
| 349 |
+ } |
|
| 350 |
+ if helpCalled {
|
|
| 351 |
+ t.Error("help called for regular flag")
|
|
| 352 |
+ helpCalled = false // reset for next test |
|
| 353 |
+ } |
|
| 354 |
+ // Help flag should work as expected. |
|
| 355 |
+ err = fs.Parse([]string{"-help"})
|
|
| 356 |
+ if err == nil {
|
|
| 357 |
+ t.Fatal("error expected")
|
|
| 358 |
+ } |
|
| 359 |
+ if err != ErrHelp {
|
|
| 360 |
+ t.Fatal("expected ErrHelp; got ", err)
|
|
| 361 |
+ } |
|
| 362 |
+ if !helpCalled {
|
|
| 363 |
+ t.Fatal("help was not called")
|
|
| 364 |
+ } |
|
| 365 |
+ // If we define a help flag, that should override. |
|
| 366 |
+ var help bool |
|
| 367 |
+ fs.BoolVar(&help, []string{"help"}, false, "help flag")
|
|
| 368 |
+ helpCalled = false |
|
| 369 |
+ err = fs.Parse([]string{"-help"})
|
|
| 370 |
+ if err != nil {
|
|
| 371 |
+ t.Fatal("expected no error for defined -help; got ", err)
|
|
| 372 |
+ } |
|
| 373 |
+ if helpCalled {
|
|
| 374 |
+ t.Fatal("help was called; should not have been for defined help flag")
|
|
| 375 |
+ } |
|
| 376 |
+} |