podman
162 строки · 3.6 Кб
1// Copyright 2015 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package objabi6
7import (8"flag"9"fmt"10"io"11"io/ioutil"12"log"13"os"14"strconv"15"strings"16)
17
18func Flagcount(name, usage string, val *int) {19flag.Var((*count)(val), name, usage)20}
21
22func Flagfn1(name, usage string, f func(string)) {23flag.Var(fn1(f), name, usage)24}
25
26func Flagprint(w io.Writer) {27flag.CommandLine.SetOutput(w)28flag.PrintDefaults()29}
30
31func Flagparse(usage func()) {32flag.Usage = usage33os.Args = expandArgs(os.Args)34flag.Parse()35}
36
37// expandArgs expands "response files" arguments in the provided slice.
38//
39// A "response file" argument starts with '@' and the rest of that
40// argument is a filename with CR-or-CRLF-separated arguments. Each
41// argument in the named files can also contain response file
42// arguments. See Issue 18468.
43//
44// The returned slice 'out' aliases 'in' iff the input did not contain
45// any response file arguments.
46//
47// TODO: handle relative paths of recursive expansions in different directories?
48// Is there a spec for this? Are relative paths allowed?
49func expandArgs(in []string) (out []string) {50// out is nil until we see a "@" argument.51for i, s := range in {52if strings.HasPrefix(s, "@") {53if out == nil {54out = make([]string, 0, len(in)*2)55out = append(out, in[:i]...)56}57slurp, err := ioutil.ReadFile(s[1:])58if err != nil {59log.Fatal(err)60}61args := strings.Split(strings.TrimSpace(strings.Replace(string(slurp), "\r", "", -1)), "\n")62out = append(out, expandArgs(args)...)63} else if out != nil {64out = append(out, s)65}66}67if out == nil {68return in69}70return71}
72
73func AddVersionFlag() {74flag.Var(versionFlag{}, "V", "print version and exit")75}
76
77var buildID string // filled in by linker78
79type versionFlag struct{}80
81func (versionFlag) IsBoolFlag() bool { return true }82func (versionFlag) Get() interface{} { return nil }83func (versionFlag) String() string { return "" }84func (versionFlag) Set(s string) error {85name := os.Args[0]86name = name[strings.LastIndex(name, `/`)+1:]87name = name[strings.LastIndex(name, `\`)+1:]88name = strings.TrimSuffix(name, ".exe")89
90// If there's an active experiment, include that,91// to distinguish go1.10.2 with an experiment92// from go1.10.2 without an experiment.93p := Expstring()94if p == DefaultExpstring() {95p = ""96}97sep := ""98if p != "" {99sep = " "100}101
102// The go command invokes -V=full to get a unique identifier103// for this tool. It is assumed that the release version is sufficient104// for releases, but during development we include the full105// build ID of the binary, so that if the compiler is changed and106// rebuilt, we notice and rebuild all packages.107if s == "full" {108if strings.HasPrefix(Version, "devel") {109p += " buildID=" + buildID110}111}112
113fmt.Printf("%s version %s%s%s\n", name, Version, sep, p)114os.Exit(0)115return nil116}
117
118// count is a flag.Value that is like a flag.Bool and a flag.Int.
119// If used as -name, it increments the count, but -name=x sets the count.
120// Used for verbose flag -v.
121type count int122
123func (c *count) String() string {124return fmt.Sprint(int(*c))125}
126
127func (c *count) Set(s string) error {128switch s {129case "true":130*c++131case "false":132*c = 0133default:134n, err := strconv.Atoi(s)135if err != nil {136return fmt.Errorf("invalid count %q", s)137}138*c = count(n)139}140return nil141}
142
143func (c *count) Get() interface{} {144return int(*c)145}
146
147func (c *count) IsBoolFlag() bool {148return true149}
150
151func (c *count) IsCountFlag() bool {152return true153}
154
155type fn1 func(string)156
157func (f fn1) Set(s string) error {158f(s)159return nil160}
161
162func (f fn1) String() string { return "" }163