func multisnapshotCmd(mysqld *mysqlctl.Mysqld, subFlags *flag.FlagSet, args []string) { concurrency := subFlags.Int("concurrency", 8, "how many compression jobs to run simultaneously") spec := subFlags.String("spec", "-", "shard specification") tablesString := subFlags.String("tables", "", "dump only this comma separated list of tables") skipSlaveRestart := subFlags.Bool("skip-slave-restart", false, "after the snapshot is done, do not restart slave replication") maximumFilesize := subFlags.Uint64("maximum-file-size", 128*1024*1024, "the maximum size for an uncompressed data file") subFlags.Parse(args) if subFlags.NArg() != 2 { relog.Fatal("action multisnapshot requires <db name> <key name>") } shards, err := key.ParseShardingSpec(*spec) if err != nil { relog.Fatal("multisnapshot failed: %v", err) } var tables []string if *tablesString != "" { tables = strings.Split(*tablesString, ",") } filenames, err := mysqld.CreateMultiSnapshot(shards, subFlags.Arg(0), subFlags.Arg(1), tabletAddr, false, *concurrency, tables, *skipSlaveRestart, *maximumFilesize, nil) if err != nil { relog.Fatal("multisnapshot failed: %v", err) } else { relog.Info("manifest locations: %v", filenames) } }
// ApplyWithError populates the flag given the flag set and environment func (f BoolTFlag) ApplyWithError(set *flag.FlagSet) error { val := true if f.EnvVar != "" { for _, envVar := range strings.Split(f.EnvVar, ",") { envVar = strings.TrimSpace(envVar) if envVal, ok := syscall.Getenv(envVar); ok { if envVal == "" { val = false break } envValBool, err := strconv.ParseBool(envVal) if err != nil { return fmt.Errorf("could not parse %s as bool value for flag %s: %s", envVal, f.Name, err) } val = envValBool break } } } eachName(f.Name, func(name string) { if f.Destination != nil { set.BoolVar(f.Destination, name, val, f.Usage) return } set.Bool(name, val, f.Usage) }) return nil }
// newCommandPub creates and returns a pub command. func newCommandPub(args []string, cli *client.Client) (command, error) { // Create a flag set. var flg flag.FlagSet // Define the flags. qos := flg.Uint("q", uint(mqtt.QoS0), "QoS") retain := flg.Bool("r", false, "Retain") topicName := flg.String("t", "", "Topic Name") message := flg.String("m", "", "Application Message") // Parse the flag. if err := flg.Parse(args); err != nil { return nil, errCmdArgsParse } // Create a pub command. cmd := &commandPub{ cli: cli, publishOpts: &client.PublishOptions{ QoS: byte(*qos), Retain: *retain, TopicName: []byte(*topicName), Message: []byte(*message), }, } // Return the command. return cmd, nil }
func TestLoadConfig(t *testing.T) { var flagSet flag.FlagSet a := flagSet.Int("a", -1, "for test") b := flagSet.Bool("b", true, "for test") c := flagSet.String("c", "-1", "for test") da := flagSet.Int("d.a", -1, "for test") dd := flagSet.Bool("d.d", false, "for test") dc := flagSet.String("d.c", "-1", "for test") e := loadConfig("config_test.txt", &flagSet, false) if nil != e { t.Error(e) return } if *a != 1 { t.Error("a != 1") } if !*b { t.Error("b != true") } if "abc" != *c { t.Error("c != \"abc\"") } if *da != 1323 { t.Error("d.a != 1323") } if !*dd { t.Error("db != true") } if "67" != *dc { t.Errorf("dc != \"67\", actual is %s", *dc) } }
func commandSplitClone(wi *Instance, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) (Worker, error) { online := subFlags.Bool("online", defaultOnline, "do online copy (optional approximate copy, source and destination tablets will not be put out of serving, minimizes downtime during offline copy)") offline := subFlags.Bool("offline", defaultOffline, "do offline copy (exact copy at a specific GTID, required before shard migration, source and destination tablets will be put out of serving during copy)") excludeTables := subFlags.String("exclude_tables", "", "comma separated list of tables to exclude") strategy := subFlags.String("strategy", "", "which strategy to use for restore, use 'vtworker SplitClone --strategy=-help k/s' for more info") sourceReaderCount := subFlags.Int("source_reader_count", defaultSourceReaderCount, "number of concurrent streaming queries to use on the source") writeQueryMaxRows := subFlags.Int("write_query_max_rows", defaultWriteQueryMaxRows, "maximum number of rows per write query") writeQueryMaxSize := subFlags.Int("write_query_max_size", defaultWriteQueryMaxSize, "maximum size (in bytes) per write query") writeQueryMaxRowsDelete := subFlags.Int("write_query_max_rows_delete", defaultWriteQueryMaxRows, "maximum number of rows per DELETE FROM write query") minTableSizeForSplit := subFlags.Int("min_table_size_for_split", defaultMinTableSizeForSplit, "tables bigger than this size on disk in bytes will be split into source_reader_count chunks if possible") destinationWriterCount := subFlags.Int("destination_writer_count", defaultDestinationWriterCount, "number of concurrent RPCs to execute on the destination") minHealthyRdonlyTablets := subFlags.Int("min_healthy_rdonly_tablets", defaultMinHealthyRdonlyTablets, "minimum number of healthy RDONLY tablets in the source and destination shard at start") maxTPS := subFlags.Int64("max_tps", defaultMaxTPS, "if non-zero, limit copy to maximum number of (write) transactions/second on the destination (unlimited by default)") if err := subFlags.Parse(args); err != nil { return nil, err } if subFlags.NArg() != 1 { subFlags.Usage() return nil, fmt.Errorf("command SplitClone requires <keyspace/shard>") } keyspace, shard, err := topoproto.ParseKeyspaceShard(subFlags.Arg(0)) if err != nil { return nil, err } var excludeTableArray []string if *excludeTables != "" { excludeTableArray = strings.Split(*excludeTables, ",") } worker, err := NewSplitCloneWorker(wr, wi.cell, keyspace, shard, *online, *offline, excludeTableArray, *strategy, *sourceReaderCount, *writeQueryMaxRows, *writeQueryMaxSize, *writeQueryMaxRowsDelete, uint64(*minTableSizeForSplit), *destinationWriterCount, *minHealthyRdonlyTablets, *maxTPS) if err != nil { return nil, fmt.Errorf("cannot create split clone worker: %v", err) } return worker, nil }
func commandWorkflowCreate(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { if WorkflowManager == nil { return fmt.Errorf("no workflow.Manager registered") } skipStart := subFlags.Bool("skip_start", false, "If set, the workflow will not be started.") if err := subFlags.Parse(args); err != nil { return err } if subFlags.NArg() < 1 { return fmt.Errorf("the <factoryName> argument is required for the WorkflowCreate command") } factoryName := subFlags.Arg(0) uuid, err := WorkflowManager.Create(ctx, factoryName, subFlags.Args()[1:]) if err != nil { return err } wr.Logger().Printf("uuid: %v\n", uuid) if !*skipStart { return WorkflowManager.Start(ctx, uuid) } return nil }
func commandVtGateExecute(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { server := subFlags.String("server", "", "VtGate server to connect to") bindVariables := newBindvars(subFlags) connectTimeout := subFlags.Duration("connect_timeout", 30*time.Second, "Connection timeout for vtgate client") tabletType := subFlags.String("tablet_type", "master", "tablet type to query") json := subFlags.Bool("json", false, "Output JSON instead of human-readable table") if err := subFlags.Parse(args); err != nil { return err } if subFlags.NArg() != 1 { return fmt.Errorf("the <sql> argument is required for the VtGateExecute command") } t, err := parseTabletType(*tabletType, []topodatapb.TabletType{topodatapb.TabletType_MASTER, topodatapb.TabletType_REPLICA, topodatapb.TabletType_RDONLY}) if err != nil { return err } vtgateConn, err := vtgateconn.Dial(ctx, *server, *connectTimeout) if err != nil { return fmt.Errorf("error connecting to vtgate '%v': %v", *server, err) } defer vtgateConn.Close() qr, err := vtgateConn.Execute(ctx, subFlags.Arg(0), *bindVariables, t) if err != nil { return fmt.Errorf("Execute failed: %v", err) } if *json { return printJSON(wr.Logger(), qr) } printQueryResult(loggerWriter{wr.Logger()}, qr) return nil }
func (cmd *editDescriptionCmd) Flags(fs *flag.FlagSet) *flag.FlagSet { cmd.ById = fs.Bool(drive.CLIOptionId, false, "open by id instead of path") cmd.Description = fs.String(drive.CLIOptionDescription, "", drive.DescDescription) cmd.Piped = fs.Bool(drive.CLIOptionPiped, false, drive.DescPiped) return fs }
func (gc *GetCommand) Flags(fs *flag.FlagSet) *flag.FlagSet { gc.header = fs.Bool("H", false, "Display record header") gc.test = fs.Bool("t", false, "Test that the record can be retrieved") gc.separator = fs.String("s", "====", "Record separator") return fs }
func (c *DaemonCmd) Flags(fs *flag.FlagSet) { c.dbfile = fs.String("o", "ci.db", "override the default local file name") c.port = fs.Int("p", 2020, "override the default local port") c.hookport = fs.Int("hp", 2121, "override the default hook port ") c.hook = fs.Bool("hook", false, "also start an http Hook server (Get returns a status, Post fire a build)") }
// NewGoCmdWithFlags like NewGoCmd, but wl also parse flags configured i flagset func NewGoCmdWithFlags(flagset *flag.FlagSet, workdir string, args ...string) (*GoCmd, error) { if len(args) < 2 { return nil, errors.New("GoCmd must have at least two arguments (e.g. go build)") } if sort.SearchStrings([]string{"build", "run", "test"}, args[1]) > -1 { flagset.Int("p", runtime.NumCPU(), "number or parallel builds") for _, f := range []string{"x", "v", "n", "a", "work"} { flagset.Bool(f, false, "") } for _, f := range []string{"compiler", "gccgoflags", "gcflags", "ldflags", "tags"} { flagset.String(f, "", "") } } switch args[1] { case "run": case "build": flagset.String("o", "", "output: output file") case "test": for _, f := range []string{"i", "c"} { flagset.Bool(f, false, "") } for _, testflag := range TestFlags { flagset.String(testflag, "", "") flagset.String("test."+testflag, "", "") } flagset.Bool("short", false, "") flagset.Bool("test.short", false, "") flagset.Bool("test.v", false, "") default: return nil, errors.New("Currently only build run and test commands supported. Sorry.") } if err := flagset.Parse(args[2:]); err != nil { return nil, err } var params, extra []string switch args[1] { case "build": params = flagset.Args() case "run": for i, param := range flagset.Args() { if !strings.HasSuffix(param, ".go") { extra = flagset.Args()[i:] break } params = append(params, param) } case "test": for i, param := range flagset.Args() { if strings.HasPrefix(param, "-") { extra = flagset.Args()[i:] break } params = append(params, param) } default: return nil, errors.New("Currently only build run and test commands supported") } return &GoCmd{make(map[string]string), workdir, args[0], args[1], FromFlagSet(flagset), params, extra}, nil }
func (cmd *touchCmd) Flags(fs *flag.FlagSet) *flag.FlagSet { cmd.hidden = fs.Bool(drive.HiddenKey, false, "allows pushing of hidden paths") cmd.recursive = fs.Bool("r", false, "toggles recursive touching") cmd.matches = fs.Bool(drive.MatchesKey, false, "search by prefix and touch") cmd.quiet = fs.Bool(drive.QuietKey, false, "if set, do not log anything but errors") cmd.byId = fs.Bool(drive.CLIOptionId, false, "share by id instead of path") return fs }
func (cmd *diffCmd) Flags(fs *flag.FlagSet) *flag.FlagSet { cmd.hidden = fs.Bool(drive.HiddenKey, false, "allows pulling of hidden paths") cmd.ignoreChecksum = fs.Bool(drive.CLIOptionIgnoreChecksum, true, drive.DescIgnoreChecksum) cmd.ignoreConflict = fs.Bool(drive.CLIOptionIgnoreConflict, false, drive.DescIgnoreConflict) cmd.ignoreNameClashes = fs.Bool(drive.CLIOptionIgnoreNameClashes, false, drive.DescIgnoreNameClashes) cmd.quiet = fs.Bool(drive.QuietKey, false, "if set, do not log anything but errors") return fs }
func teardownCmd(mysqld *mysqlctl.Mysqld, subFlags *flag.FlagSet, args []string) { force := subFlags.Bool("force", false, "will remove the root directory even if mysqld shutdown fails") subFlags.Parse(args) if err := mysqlctl.Teardown(mysqld, *force); err != nil { relog.Fatal("failed teardown mysql (forced? %v): %v", *force, err) } }
func init() { var fs flag.FlagSet goimport := fs.Bool("goimport", false, "use goimport instead of gofmt") commands["fmt"] = &Command{ fs: &fs, do: func(ctx *Context) { doFormat(ctx, *goimport) }, } }
func init() { var fs flag.FlagSet all := fs.Bool("all", false, "show unexported identifiers") commands["doc"] = &Command{ fs: &fs, do: func(ctx *Context) { os.Exit(doDoc(ctx, *all)) }, } }
func (cmd *deleteCmd) Flags(fs *flag.FlagSet) *flag.FlagSet { cmd.Hidden = fs.Bool(drive.HiddenKey, false, "allows trashing hidden paths") cmd.Matches = fs.Bool(drive.MatchesKey, false, "search by prefix and delete") cmd.Quiet = fs.Bool(drive.QuietKey, false, "if set, do not log anything but errors") cmd.ById = fs.Bool(drive.CLIOptionId, false, "delete by id instead of path") cmd.NoPrompt = fs.Bool(drive.NoPromptKey, false, "disables the prompt") return fs }
func (c *ExecCmd) Flags(fs *flag.FlagSet) { // output selection c.cat = fs.Bool("cat", false, "concatenate outputs, and print it") c.sum = fs.Bool("sum", false, "parse each output as a number and print out the total") c.count = fs.Bool("count", false, "count different outputs, and prints the resulting histogram") c.digest = fs.Bool("digest", false, "compute the sha1 digest of all outputs") c.local = fs.Bool("l", false, "start in the current working dir. Default is to start in the sbr workspace") }
func (cmd *statCmd) Flags(fs *flag.FlagSet) *flag.FlagSet { cmd.depth = fs.Int(drive.DepthKey, 1, "maximum recursion depth") cmd.hidden = fs.Bool(drive.HiddenKey, false, "discover hidden paths") cmd.recursive = fs.Bool("r", false, "recursively discover folders") cmd.quiet = fs.Bool(drive.QuietKey, false, "if set, do not log anything but errors") cmd.byId = fs.Bool(drive.CLIOptionId, false, "stat by id instead of path") cmd.md5sum = fs.Bool(drive.Md5sumKey, false, "produce output compatible with md5sum(1)") return fs }
func cmdEdit(subFlags *flag.FlagSet, args []string) error { var ( force = subFlags.Bool("f", false, "no warning on nonexistent node") ) subFlags.Parse(args) if subFlags.NArg() == 0 { return fmt.Errorf("edit: no path specified") } arg := subFlags.Arg(0) zkPath := fixZkPath(arg) data, stat, err := zconn.Get(zkPath) if err != nil { if !*force || !zookeeper.IsError(err, zookeeper.ZNONODE) { log.Warningf("edit: cannot access %v: %v", zkPath, err) } return fmt.Errorf("edit: cannot access %v: %v", zkPath, err) } name := path.Base(zkPath) tmpPath := fmt.Sprintf("/tmp/zk-edit-%v-%v", name, time.Now().UnixNano()) f, err := os.Create(tmpPath) if err == nil { _, err = f.WriteString(data) f.Close() } if err != nil { return fmt.Errorf("edit: cannot write file %v", err) } cmd := exec.Command(os.Getenv("EDITOR"), tmpPath) cmd.Stdin = os.Stdin cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr err = cmd.Run() if err != nil { os.Remove(tmpPath) return fmt.Errorf("edit: cannot start $EDITOR: %v", err) } fileData, err := ioutil.ReadFile(tmpPath) if err != nil { os.Remove(tmpPath) return fmt.Errorf("edit: cannot read file %v", err) } if string(fileData) != data { // data changed - update if we can _, err = zconn.Set(zkPath, string(fileData), stat.Version()) if err != nil { os.Remove(tmpPath) return fmt.Errorf("edit: cannot write zk file %v", err) } } os.Remove(tmpPath) return nil }
func snapshotSourceEndCmd(mysqld *mysqlctl.Mysqld, subFlags *flag.FlagSet, args []string) { slaveStartRequired := subFlags.Bool("slave-start", false, "will restart replication") readWrite := subFlags.Bool("read-write", false, "will make the server read-write") subFlags.Parse(args) err := mysqld.SnapshotSourceEnd(*slaveStartRequired, !(*readWrite), true) if err != nil { relog.Fatal("snapshotsourceend failed: %v", err) } }
func initCmd(mysqld *mysqlctl.Mysqld, subFlags *flag.FlagSet, args []string) { waitTime := subFlags.Duration("wait_time", mysqlctl.MysqlWaitTime, "how long to wait for startup") bootstrapArchive := subFlags.String("bootstrap_archive", "mysql-db-dir.tbz", "name of bootstrap archive within vitess/data/bootstrap directory") skipSchema := subFlags.Bool("skip_schema", false, "don't apply initial schema") subFlags.Parse(args) if err := mysqld.Init(*waitTime, *bootstrapArchive, *skipSchema); err != nil { log.Fatalf("failed init mysql: %v", err) } }
// Startup flags func (sc *CompareCommand) Flags(fs *flag.FlagSet) *flag.FlagSet { sc.setName = fs.String("s", "", "Select records from this set") sc.beforeDate = fs.String("B", "", "Select records that were updated before date (YYYY-MM-DD)") sc.afterDate = fs.String("A", "", "Select records that were updated after date (YYYY-MM-DD)") sc.firstResult = fs.Int("f", 0, "Index of first record to retrieve") sc.fromFile = fs.String("F", "", "Read identifiers from a file") sc.maxResults = fs.Int("c", 100000, "Maximum number of records to retrieve") sc.compareContent = fs.Bool("C", false, "Compares the metadata content of common metadata records") return fs }
func addGlobalOpts(set *flag.FlagSet) { for _, flg := range GlobalOptions { lName := longName(flg) switch f := flg.(type) { case cli.BoolFlag: set.Bool(lName, false, f.Usage) case cli.StringFlag: set.String(lName, f.Value, f.Usage) } } }
func commandReparentShard(wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) (string, error) { leaveMasterReadOnly := subFlags.Bool("leave-master-read-only", false, "leaves the master read-only after reparenting") force := subFlags.Bool("force", false, "will force the reparent even if the master is already correct") subFlags.Parse(args) if subFlags.NArg() != 2 { log.Fatalf("action ReparentShard requires <keyspace/shard|zk shard path> <tablet alias|zk tablet path>") } keyspace, shard := shardParamToKeyspaceShard(subFlags.Arg(0)) tabletAlias := tabletParamToTabletAlias(subFlags.Arg(1)) return "", wr.ReparentShard(keyspace, shard, tabletAlias, *leaveMasterReadOnly, *force) }
func teardownCmd(mysqld *mysqlctl.Mysqld, subFlags *flag.FlagSet, args []string) error { waitTime := subFlags.Duration("wait_time", 2*time.Minute, "how long to wait for shutdown") force := subFlags.Bool("force", false, "will remove the root directory even if mysqld shutdown fails") subFlags.Parse(args) ctx, cancel := context.WithTimeout(context.Background(), *waitTime) defer cancel() if err := mysqld.Teardown(ctx, *force); err != nil { return fmt.Errorf("failed teardown mysql (forced? %v): %v", *force, err) } return nil }
func commandVtGateExecuteKeyspaceIds(ctx context.Context, wr *wrangler.Wrangler, subFlags *flag.FlagSet, args []string) error { server := subFlags.String("server", "", "VtGate server to connect to") bindVariables := newBindvars(subFlags) connectTimeout := subFlags.Duration("connect_timeout", 30*time.Second, "Connection timeout for vtgate client") tabletType := subFlags.String("tablet_type", "master", "tablet type to query") keyspace := subFlags.String("keyspace", "", "keyspace to send query to") keyspaceIDsStr := subFlags.String("keyspace_ids", "", "comma-separated list of keyspace ids (in hex) that will map into shards to send query to") options := subFlags.String("options", "", "execute options values as a text encoded proto of the ExecuteOptions structure") json := subFlags.Bool("json", false, "Output JSON instead of human-readable table") if err := subFlags.Parse(args); err != nil { return err } if subFlags.NArg() != 1 { return fmt.Errorf("the <sql> argument is required for the VtGateExecuteKeyspaceIds command") } t, err := parseTabletType(*tabletType, []topodatapb.TabletType{topodatapb.TabletType_MASTER, topodatapb.TabletType_REPLICA, topodatapb.TabletType_RDONLY}) if err != nil { return err } var keyspaceIDs [][]byte if *keyspaceIDsStr != "" { keyspaceIDHexs := strings.Split(*keyspaceIDsStr, ",") keyspaceIDs = make([][]byte, len(keyspaceIDHexs)) for i, keyspaceIDHex := range keyspaceIDHexs { keyspaceIDs[i], err = hex.DecodeString(keyspaceIDHex) if err != nil { return fmt.Errorf("cannot hex-decode value %v '%v': %v", i, keyspaceIDHex, err) } } } executeOptions, err := parseExecuteOptions(*options) if err != nil { return err } vtgateConn, err := vtgateconn.Dial(ctx, *server, *connectTimeout, "") if err != nil { return fmt.Errorf("error connecting to vtgate '%v': %v", *server, err) } defer vtgateConn.Close() qr, err := vtgateConn.ExecuteKeyspaceIds(ctx, subFlags.Arg(0), *keyspace, keyspaceIDs, *bindVariables, t, executeOptions) if err != nil { return fmt.Errorf("Execute failed: %v", err) } if *json { return printJSON(wr.Logger(), qr) } printQueryResult(loggerWriter{wr.Logger()}, qr) return nil }
func (cmd *untrashCmd) Flags(fs *flag.FlagSet) *flag.FlagSet { cmd.hidden = fs.Bool(drive.HiddenKey, false, "allows untrashing hidden paths") cmd.matches = fs.Bool(drive.MatchesKey, false, "search by prefix and untrash") cmd.quiet = fs.Bool(drive.QuietKey, false, "if set, do not log anything but errors") cmd.byId = fs.Bool(drive.CLIOptionId, false, "untrash by id instead of path") return fs }
func (cmd *aboutCmd) Flags(fs *flag.FlagSet) *flag.FlagSet { cmd.features = fs.Bool("features", false, "gives information on features present on this drive") cmd.quota = fs.Bool("quota", false, "prints out quota information for this drive") cmd.filesize = fs.Bool("filesize", false, "prints out information about file sizes e.g the max upload size for a specific file size") cmd.quiet = fs.Bool(drive.QuietKey, false, "if set, do not log anything but errors") return fs }
func cmdStat(subFlags *flag.FlagSet, args []string) error { var ( force = subFlags.Bool("f", false, "no warning on nonexistent node") ) subFlags.Parse(args) if subFlags.NArg() == 0 { return fmt.Errorf("stat: no path specified") } resolved, err := zk.ResolveWildcards(zconn, subFlags.Args()) if err != nil { return fmt.Errorf("stat: invalid wildcards: %v", err) } if len(resolved) == 0 { // the wildcards didn't result in anything, we're done return nil } hasError := false for _, arg := range resolved { zkPath := fixZkPath(arg) acls, stat, err := zconn.ACL(zkPath) if stat == nil { err = fmt.Errorf("no such node") } if err != nil { hasError = true if !*force || !zookeeper.IsError(err, zookeeper.ZNONODE) { log.Warningf("stat: cannot access %v: %v", zkPath, err) } continue } fmt.Printf("Path: %s\n", zkPath) fmt.Printf("Created: %s\n", stat.CTime().Format(timeFmtMicro)) fmt.Printf("Modified: %s\n", stat.MTime().Format(timeFmtMicro)) fmt.Printf("Size: %v\n", stat.DataLength()) fmt.Printf("Children: %v\n", stat.NumChildren()) fmt.Printf("Version: %v\n", stat.Version()) fmt.Printf("Ephemeral: %v\n", stat.EphemeralOwner()) fmt.Printf("ACL:\n") for _, acl := range acls { fmt.Printf(" %v:%v %v\n", acl.Scheme, acl.Id, fmtAcl(acl)) } } if hasError { return fmt.Errorf("stat: some paths had errors") } return nil }