func main() { cmd.UnixIO("err") c := cmd.AppCtx() opts.NewFlag("D", "debug", &c.Debug) opts.NewFlag("u", "unix IO", &ux) opts.NewFlag("g", "get contents", &gflag) if cmd.Args()[0] == "gf" { gflag = true } args := opts.Parse() if ux { cmd.UnixIO() } if len(args) == 0 { args = append(args, ".,1") } var dc <-chan face{} if !gflag { dc = cmd.Dirs(args...) } else { dc = cmd.Files(args...) } out := cmd.Out("out") var err error for m := range dc { cmd.Dprintf("got %T\n", m) switch m := m.(type) { case error: err = m cmd.Warn("%s", m) if !ux { m := fmt.Errorf("%s: %s", cmd.Args()[0], m) if ok := out <- m; !ok { close(dc, cerror(out)) } } case zx.Dir: if !ux { if ok := out <- m; !ok { close(dc, cerror(out)) } } else { printf("%s\n", m.Fmt()) } case []byte: if ok := out <- m; !ok { close(dc, cerror(out)) } } } if err := cerror(dc); err != nil { if !ux { out <- fmt.Errorf("%s: %s", cmd.Args()[0], err) } cmd.Exit(err) } cmd.Exit(err) }
func main() { cmd.UnixIO("err") c := cmd.AppCtx() opts.NewFlag("D", "debug", &c.Debug) opts.NewFlag("v", "verbose", &c.Verb) opts.NewFlag("a", "all", &aflag) opts.NewFlag("b", "blind", &bflag) opts.NewFlag("n", "dry run", &nflag) opts.NewFlag("u", "don't use unix out", ¬ux) args := opts.Parse() if !notux { cmd.UnixIO("out") } if aflag && bflag { opts.Usage() } var err error switch len(args) { case 0: for _, nm := range names() { cmd.Printf("pull %s...\n", nm) if err2 := pull1(nm); err == nil { err = err2 } } case 1: err = pull1(args[0]) default: opts.Usage() } cmd.Exit(err) }
func main() { opts := opt.New("[file]") c := cmd.AppCtx() opts.NewFlag("D", "debug", &c.Debug) rdonly := false opts.NewFlag("r", "read only", &rdonly) opts.NewFlag("e", "do edits for testing", &doedits) cmd.UnixIO("err") args := opts.Parse() var t *ink.Txt inkout := cmd.Out("ink") if inkout == nil { cmd.UnixIO() } if len(args) == 0 { t = ink.NewTxt("1234", "abc") } else { dat, err := zx.GetAll(cmd.NS(), cmd.AbsPath(args[0])) if err != nil { cmd.Fatal(err) } t = ink.NewTxt(args[0]+" Del", string(dat)) } go edit(t) if rdonly { t.NoEdits() } ink.UsePort("8182") bs := ink.NewButtonSet(&ink.Button{Tag: "One", Name: "one"}, &ink.Button{Tag: "Two", Name: "two"}, &ink.Button{Tag: "B", Name: "b", Value: &bold}, &ink.Button{Tag: "I", Name: "i", Value: &italic}) rs := ink.NewRadioSet(&style, &ink.Button{Tag: "R", Name: "r"}, &ink.Button{Tag: "T", Name: "t"}) go buttons(bs, rs, t) pg := ink.NewPg("/", "Example text editing:", bs, rs, t) pg.Tag = "Clive's iedit" if doedits { go edits(t) } go ink.Serve() if inkout != nil { // TODO: ctlrs must use unique ids sytem-wide, or // controls written won't work because of their ids. inkout <- []byte(`<tt>Hi there, this is HTML</tt>`) var buf bytes.Buffer bs.WriteTo(&buf) inkout <- buf.Bytes() inkout <- []byte("https://localhost:8182") } t.Wait() for rs := range t.Get(0, -1) { cmd.Printf("%s", string(rs)) } }
// Run echo in the current app context. func main() { cmd.UnixIO("err") c := cmd.AppCtx() opts.NewFlag("D", "debug", &c.Debug) opts.NewFlag("n", "don't add a final newline", &nflag) opts.NewFlag("m", "issue one message per arg", &mflag) opts.NewFlag("u", "use unix out", &ux) opts.NewFlag("o", "chan: output to this chan (for testing other tools)", &oname) opts.NewFlag("i", "chan: echo input from this chan (for testing other tools)", &iname) args := opts.Parse() if ux { cmd.UnixIO(oname) } var b bytes.Buffer out := cmd.Out(oname) if out == nil { cmd.Fatal("no output chan '%s'", oname) } mflag = mflag || iname != "" for i, arg := range args { if mflag { ok := out <- []byte(arg) if !ok { cmd.Fatal("out: %s", cerror(out)) } } else { b.WriteString(arg) if i < len(args)-1 { b.WriteString(" ") } } } if iname != "" { for x := range cmd.In(iname) { x := x if b, ok := x.([]byte); ok { ok := out <- []byte(b) if !ok { cmd.Fatal("out: %s", cerror(out)) } } } } if mflag { cmd.Exit(nil) } if !nflag { b.WriteString("\n") } ok := out <- b.Bytes() if !ok { cmd.Fatal("out: %s", cerror(out)) } }
// Run print lines in the current app context. func main() { c := cmd.AppCtx() cmd.UnixIO("err") opts.NewFlag("D", "debug", &c.Debug) opts.NewFlag("1", "collect all files (not one msg per file)", &one) ux := false opts.NewFlag("u", "use unix out", &ux) args := opts.Parse() if ux { cmd.UnixIO("out") } if len(args) != 0 { cmd.SetIn("in", cmd.Files(args...)) } buf := &bytes.Buffer{} in := cmd.In("in") out := cmd.Out("out") for m := range in { switch m := m.(type) { case []byte: buf.Write(m) case zx.Dir: if !one && buf.Len() > 0 { if ok := out <- buf.Bytes(); !ok { close(in, cerror(out)) break } buf = &bytes.Buffer{} } if !one && !ux { if ok := out <- m; !ok { close(in, cerror(out)) break } } case error: cmd.Warn("%s", m) default: cmd.Dprintf("ignored %T\n", m) if !ux { if ok := out <- m; !ok { close(in, cerror(out)) break } } } } if buf.Len() > 0 { out <- buf.Bytes() } if err := cerror(in); err != nil { cmd.Fatal(err) } }
func main() { cmd.UnixIO("err") c := cmd.AppCtx() opts.NewFlag("D", "debug", &c.Debug) opts.NewFlag("v", "verbose", &c.Verb) opts.NewFlag("x", "exclude", &excl) opts.NewFlag("n", "print just replica names when used to list replicas", &nflag) opts.NewFlag("m", "move existing replica client/server paths to the given ones", &mflag) opts.NewFlag("u", "don't use unix out", ¬ux) args := opts.Parse() if !notux { cmd.UnixIO("out") } if mflag { if len(args) != 3 { cmd.Warn("-m needs all arguments") opts.Usage() } err := mv(args[0], args[1], args[2]) if err != nil { cmd.Fatal(err) } cmd.Exit(nil) } var err error switch len(args) { case 0: for _, nm := range names() { if nflag { cmd.Printf("%s\n", nm) continue } if err2 := list(nm); err2 != nil { cmd.Warn("%s: %s", nm, err2) if err == nil { err = err2 } } } case 1: err = list(args[0]) case 3: err = mk(args[0], args[1], args[2]) default: opts.Usage() } if err != nil { cmd.Fatal(err) } cmd.Exit(nil) }
func main() { cmd.UnixIO() dfltdir := auth.KeyDir() dir = dfltdir opts.NewFlag("d", "adir: clive auth dir", &dir) opts.NewFlag("f", "force write of key file when file already exists", &force) args := opts.Parse() if len(args) < 3 { opts.Usage() } name, user, secret := args[0], args[1], args[2] groups := args[3:] file := auth.KeyFile(dir, name) fi, _ := os.Stat(file) if fi != nil && !force { cmd.Fatal("key file already exists") } err := auth.SaveKey(dir, name, user, secret, groups...) if err != nil { cmd.Fatal("%s: %s", file, err) } ks, err := auth.LoadKey(dir, name) if err != nil { cmd.Fatal("can't load key: %s", err) } for _, k := range ks { if k.Uid == user { cmd.Warn("%s", file) return } } cmd.Fatal("bad user") }
func main() { c := cmd.AppCtx() opts.NewFlag("D", "debug", &c.Debug) cmd.UnixIO("err") args := opts.Parse() if len(args) == 1 && ismode(args[0]) { args = append([]string{"mode"}, args...) } if len(args) == 0 || len(args)%2 != 0 { cmd.Warn("wrong number of arguments") opts.Usage() } nd := chd(args...) in := cmd.In("in") var err error for m := range in { switch d := m.(type) { case zx.Dir: cmd.Dprintf("got %T %s\n", d, d["Upath"]) if cerr := ch(d, nd); cerr != nil { cmd.Warn("%s", cerr) err = cerr } default: // ignored cmd.Dprintf("got %T\n", m) } } if err != nil { cmd.Exit(err) } }
func mkrtest(t *testing.T, rtdir string, excl ...string) (*DB, func()) { cmd.UnixIO("in", "out", "err") os.Args[0] = "repl.test" os.Mkdir(rtdir+"/p", 0755) fstest.Verb = testing.Verbose() fstest.MkTree(t, rtdir+"/p") os.Remove("/tmp/clive.9988") fs, err := zux.NewZX(rtdir) if err != nil { os.RemoveAll(rtdir) os.Remove("/tmp/clive.9988") t.Fatal(err) } srv, err := rzx.NewServer("unix!local!9988", auth.TLSserver) if err != nil { os.RemoveAll(rtdir) os.Remove("/tmp/clive.9988") t.Fatal(err) } if err := srv.Serve("main", fs); err != nil { os.RemoveAll(rtdir) os.Remove("/tmp/clive.9988") t.Fatal(err) } db := mkdb(t, "unix!local!9988!/p", excl...) fn := func() { db.Close() os.RemoveAll(rtdir) os.Remove("/tmp/clive.9988") srv.Close() } return db, fn }
func main() { cmd.UnixIO("err") cmd.UnixIO("in") args := opts.Parse() if len(args) != 0 { in := cmd.Files(args...) cmd.SetIn("in", in) } out := cmd.Out("out") in := cmd.In("in") for m := range in { if ok := out <- m; !ok { close(in, cerror(out)) } } if err := cerror(in); err != nil { cmd.Fatal(err) } }
// Run path in the current app context. func main() { cmd.UnixIO("err") c := cmd.AppCtx() opts.NewFlag("D", "debug", &c.Debug) opts.NewFlag("r", "dir: print paths relative to dir", &dir) opts.NewFlag("d", "print parent directories", &dflag) opts.NewFlag("b", "print base names", &bflag) args := opts.Parse() if ux { cmd.UnixIO() } if dir != "" && (dflag || bflag) { cmd.Warn("incompatible flags") opts.Usage() } if dflag && bflag { cmd.Warn("incompatible flags") opts.Usage() } if dir != "" { dir = cmd.AbsPath(dir) } var sts error for _, n := range args { n = cmd.AbsPath(n) switch { case dir != "": r, err := filepath.Rel(dir, n) if err != nil { sts = err cmd.Warn("%s: %s", n, err) } else { n = r } case dflag: n = fpath.Dir(n) case bflag: n = fpath.Base(n) } cmd.Printf("%s\n", n) } cmd.Exit(sts) }
// Run cols in the current app context. func main() { c := cmd.AppCtx() opts.NewFlag("D", "debug", &c.Debug) opts.NewFlag("w", "wid: set max line width", &wid) opts.NewFlag("n", "ncols: set number of columns", &ncols) opts.NewFlag("u", "use unix output", &ux) cmd.UnixIO("err") args := opts.Parse() if ux { cmd.UnixIO("out") } if len(args) != 0 { cmd.SetIn("in", cmd.Files(args...)) } in := cmd.In("in") for m := range in { switch m := m.(type) { default: // ignored & forwarded cmd.Dprintf("got %T\n", m) continue case zx.Dir: cmd.Dprintf("got %T %s\n", m, m["Upath"]) add(strings.TrimSpace(m["name"])) case error: if m != nil { cmd.Warn("%s", m) } case []byte: cmd.Dprintf("got %T [%d]\n", m, len(m)) words := strings.Fields(strings.TrimSpace(string(m))) add(words...) } } col() if err := cerror(in); err != nil { cmd.Fatal("in %s", err) } }
func main() { cmd.UnixIO("err") c := cmd.AppCtx() opts.NewFlag("D", "debug", &c.Debug) opts.NewFlag("u", "don't use unix out", ¬ux) opts.NewFlag("1", "terminate after the first change", &once) args := opts.Parse() if !notux { cmd.UnixIO("out") } wcmd := "" if len(args) >= 2 { wcmd = strings.Join(args[1:], " ") args = args[:1] } if len(args) != 1 { opts.Usage() } for { kq(args[0], wcmd) } }
func main() { cmd.UnixIO() c := cmd.AppCtx() dfltdump := Path(u.Home, "dump") opts.NewFlag("s", "don't dump right now, wait until next at 5am", &Skip) opts.NewFlag("1", "dump once and exit", &Once) opts.NewFlag("v", "verbose", &c.Verb) opts.NewFlag("D", "debug", &c.Debug) opts.NewFlag("x", "expr: files excluded (.*, tmp.* if none given); tmp always excluded.", &Xcludes) Dump = dfltdump opts.NewFlag("d", "dir: where to keep the dump, ~/dump if none", &Dump) args := opts.Parse() if len(Xcludes) == 0 { Xcludes = []string{".*", "tmp.*", "*.tmp"} } Xcludes = append(Xcludes, "tmp") if len(args) == 0 { cmd.Warn("arguments missing") opts.Usage() } if Skip && Once { cmd.Fatal("can't skip the current dump and dump once now") } nt := 0 ec := make(chan bool) for i := 0; i < len(args); i++ { al := strings.SplitN(args[i], "!", 2) if len(al) == 1 { al = append(al, al[0]) al[0] = fpath.Base(al[0]) } t, err := zux.NewZX(al[1]) if err != nil { dbg.Warn("%s: %s", al[0], err) continue } t.Tag = al[0] t.Flags.Set("rdonly", true) nt++ go dump(Dump, t.Tag, t, ec) } if nt == 0 { cmd.Fatal("no trees to dump") } for nt > 0 { <-ec nt-- } }
// Run print lines in the current app context. func main() { c := cmd.AppCtx() cmd.UnixIO("err") opts.NewFlag("D", "debug", &c.Debug) opts.NewFlag("r", "range: print this range", &ranges) opts.NewFlag("n", "print line numbers", &nflag) opts.NewFlag("p", "print file names and line numbers", &pflag) ux := false opts.NewFlag("u", "use unix out", &ux) args := opts.Parse() if ux { cmd.UnixIO("out") } if len(args) != 0 { cmd.SetIn("in", cmd.Files(args...)) } if len(ranges) == 0 { ranges = append(ranges, ",") } if err := parseRanges(); err != nil { cmd.Fatal(err) } runFiles(lns) }
func mktest(t *testing.T, tdir string, excl ...string) (*DB, func()) { cmd.UnixIO("in", "out", "err") cmd.Warn("testing") os.Args[0] = "repl.test" fstest.Verb = testing.Verbose() os.RemoveAll(tdir) os.Remove(tdb) fstest.MkTree(t, tdir) fn := func() { os.RemoveAll(tdir) os.RemoveAll(tdb) } db := mkdb(t, tdir, excl...) return db, fn }
func main() { cmd.UnixIO() local := false opts.NewFlag("p", "port: port used (8080 by default)", &port) opts.NewFlag("t", "port: TLS port (8083 by default)", &tport) opts.NewFlag("l", "localhost and TLS only", &local) args := opts.Parse() switch len(args) { case 0: if local { dir = "/zx" } case 1: dir = args[0] default: cmd.Warn("too many arguments") opts.Usage() } cert := "/zx/lib/webcert.pem" key := "/zx/lib/webcert.key" addr := ":" go func() { err := http.ListenAndServeTLS(addr+tport, cert, key, http.FileServer(http.Dir(dir))) if err != nil { cmd.Fatal(err) } }() go func() { if local { return } err := http.ListenAndServe(addr+port, http.FileServer(http.Dir(dir))) if err != nil { cmd.Fatal(err) } }() c := make(chan bool) <-c }
func main() { cmd.UnixIO() nc := cmd.New(func() { cmd.Printf("hi from here\n") cmd.Fatal("oops!") println("XXX") }) args := cmd.Args() cmd.Printf("args %v\n", args) wc := nc.Waitc() cmd.Printf("Hi there!\n") cmd.Printf("Hi there!\n") cmd.Printf("Hi there!\n") if len(args) > 1 { n, _ := strconv.Atoi(args[1]) ns := time.Duration(n) time.Sleep(ns * time.Second) } else { time.Sleep(time.Second) } <-wc cmd.Printf("done\n") }
func find(dump, dpref, rel string, dc chan<- zx.Dir, ufile zx.Dir) { droot := fpath.Join(dump, dpref) years, err := cmd.GetDir(droot) if err != nil { cmd.Warn("%s", err) return } for i := len(years) - 1; i >= 0; i-- { year := years[i]["name"] if ignored(year, "") { continue } ypath := years[i]["path"] days, err := cmd.GetDir(ypath) if err != nil { cmd.Warn("%s: %s", ypath, err) continue } lastsz, lastmt, lastm := "", "", "" for j := len(days) - 1; j >= 0; j-- { day := days[j]["name"] if ignored(year, day) { continue } fpath := fpath.Join(days[j]["path"], rel) d, err := cmd.Stat(fpath) if err != nil { if !force { cmd.Dprintf("find: %s", err) return } continue } newm, newsz, newmt := d["mode"], d["size"], d["mtime"] if newsz == lastsz && newmt == lastmt && newm == lastm { continue } lastm, lastsz, lastmt = newm, newsz, newmt d["upath"] = ufile["path"] d["uupath"] = ufile["upath"] if ok := dc <- d; !ok { return } if !all { return } } } } func report(dc chan zx.Dir, donec chan bool) { last := "" for d := range dc { if last == "" { last = d["Upath"] if last == "" { last = d["path"] } } p := d["path"] cmd.Dprintf("found '%s'\n", p) var err error switch { case xcmd != "": _, err = cmd.Printf("%s %s %s\n", xcmd, p, last) case dflag: dcmd := fmt.Sprintf(`9 diff -n %s %s`, p, last) _, err = cmd.Printf("%s\n", dcmd) if err != nil { cmd.Warn("diff: %s", err) continue } case lflag: _, err = cmd.Printf("%s\n", d.Fmt()) case cflag: _, err = cmd.Printf("cp %s %s\n", p, d["Upath"]) default: _, err = cmd.Printf("%s\n", d["path"]) } if err != nil { close(dc, err) } last = p } close(donec, cerror(dc)) } func hist(in <-chan face{}) error { dc := make(chan zx.Dir) ec := make(chan bool) go report(dc, ec) var sts error for m := range in { switch m := m.(type) { case zx.Dir: cmd.Dprintf("got %T %s\n", m, m["path"]) file := m["path"] if m["upath"] == "" { m["upath"] = m["path"] } ddir := dump dpref := "" rel := "" switch { case zx.HasPrefix(file, "/zx"): if ddir == "" { ddir = "/dump" } dpref = "/zx" rel = zx.Suffix(file, "/zx") case zx.HasPrefix(file, "/u/gosrc/src/clive"): if ddir == "" { ddir = "/u/dump" } dpref = "clive" rel = zx.Suffix(file, "/u/gosrc/src/clive") case zx.HasPrefix(file, "/u"): if ddir == "" { ddir = "/u/dump" } els := zx.Elems(file) if len(els) < 3 { cmd.Warn("%s: too few path elements", m["upath"]) sts = errNoDump continue } dpref = els[1] rel = zx.Path(els[2:]...) default: cmd.Warn("%s: %s", m["upath"], errNoDump) sts = errNoDump continue } find(ddir, dpref, rel, dc, m.Dup()) default: cmd.Dprintf("got %T\n", m) } } close(dc, cerror(in)) <-ec if sts == nil { sts = cerror(ec) } if sts == nil { sts = cerror(in) } return sts } // Run cnt in the current app context. func main() { c := cmd.AppCtx() cmd.UnixIO("err") opts.NewFlag("D", "debug", &c.Debug) opts.NewFlag("f", "force search past file removals", &force) opts.NewFlag("l", "produce a long listing (or print just the name)", &lflag) opts.NewFlag("c", "copy the file from the dump", &cflag) opts.NewFlag("d", "print file differences", &dflag) opts.NewFlag("x", "cmd: print lines to execute this command between versions", &xcmd) opts.NewFlag("a", "list all copies that differ, not just the last one.", &all) opts.NewFlag("p", "dumpdir: path to dump (default is /dump or /u/dump)", &dump) t := time.Now() when := t opts.NewFlag("w", "date: backward search start time (default is now)", &when) ux := false opts.NewFlag("u", "unix IO", &ux) args := opts.Parse() if (all && cflag) || (force && !all) { cmd.Warn("incompatible flags") opts.Usage() } if ux { cmd.UnixIO("out") } lastyear = "" lastday = "" if !t.Equal(when) { y := when.Year() m := when.Month() d := when.Day() if y == 0 { y = t.Year() } lastyear = fmt.Sprintf("%04d", y) lastday = fmt.Sprintf("%02d%02d", m, d) } if len(args) != 0 { cmd.SetIn("in", cmd.Dirs(args...)) } in := cmd.In("in") if err := hist(in); err != nil { cmd.Fatal(err) } }
func main() { cmd.UnixIO() opts.AddUsage("\tspec is name | name!file | name!file!flags \n") opts.AddUsage("\tspec flags are ro | rw | ncro | ncrw \n") port = "8002" addr = "*!*!zx" opts.NewFlag("p", "port: tcp server port (8002 by default)", &port) opts.NewFlag("a", "addr: service address (*!*!zx by default)", &addr) opts.NewFlag("s", "use writesync for caches", &wsync) c := cmd.AppCtx() opts.NewFlag("D", "debug", &c.Debug) opts.NewFlag("A", "auth debug", &auth.Debug) opts.NewFlag("v", "report users logged in/out (verbose)", &c.Verb) opts.NewFlag("Z", "verbose debug", &Zdebug) opts.NewFlag("n", "no auth", &noauth) args := opts.Parse() if len(args) == 0 { cmd.Warn("missing arguments") opts.Usage() } c.Debug = c.Debug || Zdebug auth.Debug = c.Debug trs := map[string]zx.Fs{} ros := map[bool]string{false: "rw", true: "ro"} cs := map[bool]string{false: "uncached", true: "cached"} rotrs := map[string]bool{} var mainfs zx.Fs for i := 0; i < len(args); i++ { al := strings.Split(args[i], "!") if len(al) == 1 { al = append(al, al[0]) al[0] = fpath.Base(al[0]) } if _, ok := trs[al[0]]; ok { cmd.Warn("dup tree name %s", al[0]) continue } ronly := false caching := true if len(al) == 3 && strings.Contains(al[2], "ro") { ronly = true } if len(al) == 3 && strings.Contains(al[2], "nc") { caching = false } fp, _ := filepath.Abs(al[1]) t, err := zux.NewZX(fp) if err != nil { cmd.Warn("%s: %s", al[0], err) continue } t.Tag = al[0] cmd.Warn("%s %s %s", al[0], ros[ronly], cs[caching]) var x zx.Fs = t if caching { x, err = zxc.New(t) if err != nil { dbg.Warn("%s: zxc: %s", al[0], err) continue } if Zdebug { x.(*zxc.Fs).Debug = true } if wsync { x.(*zxc.Fs).Flags.Set("writesync", true) } } else if Zdebug { x.(*zux.Fs).Debug = true } trs[t.Tag] = x if i == 0 { mainfs = x } rotrs[t.Tag] = ronly } if len(trs) == 0 { cmd.Fatal("no trees to serve") } if _, ok := trs["main"]; !ok { trs["main"] = mainfs } vprintf("serve %s...", addr) srv, err := rzx.NewServer(addr, auth.TLSserver) if err != nil { cmd.Fatal("serve: %s", err) } if noauth { srv.NoAuth() } if c.Debug { srv.Debug = true } for nm, fs := range trs { if cfs, ok := fs.(*zxc.Fs); ok { cfs.Flags.Add("debug", &srv.Debug) cfs.Flags.Add("zdebug", &cfs.Debug) } else if lfs, ok := fs.(*zux.Fs); ok { lfs.Flags.Add("debug", &srv.Debug) lfs.Flags.Add("zdebug", &lfs.Debug) } if rotrs[nm] { fs = zx.MakeRO(fs) trs[nm] = fs } if err := srv.Serve(nm, fs); err != nil { cmd.Fatal("serve: %s: %s", nm, err) } } if err := srv.Wait(); err != nil { cmd.Fatal("srv: %s", err) } }
// Run rem in the current app context. func main() { c := cmd.AppCtx() cmd.UnixIO("err") opts.NewFlag("D", "debug", &c.Debug) opts.NewFlag("v", "verbose; print the calls made in the order they are made.", &c.Verb) opts.NewFlag("a", "remove all", &aflag) opts.NewFlag("f", "quiet, called 'force' in unix", &fflag) opts.NewFlag("n", "dry run; report removes but do not do them", &dry) args := opts.Parse() if len(args) != 0 { cmd.SetIn("in", cmd.Dirs(args...)) } c.Verb = c.Verb || dry in := cmd.In("in") var err error for m := range in { switch d := m.(type) { case zx.Dir: cmd.Dprintf("got %T %s\n", d, d["upath"]) dirs = append(dirs, d) case error: cmd.Warn("%s", d) default: // ignored cmd.Dprintf("ignored %T\n", m) } } if aflag { for i := 0; i < len(dirs); i++ { if dirs[i] == nil { continue } pi := dirs[i]["path"] for j := 1; j < len(dirs); j++ { if i == j || dirs[j] == nil { continue } pj := dirs[j]["path"] if zx.HasPrefix(pj, pi) { dirs[j] = nil } } } } for i := len(dirs) - 1; i >= 0; i-- { if dirs[i] == nil { continue } if cerr := rmf(dirs[i]); cerr != nil { if !fflag { cmd.Warn("%s", cerr) err = cerr } } } if err == nil { err = cerror(in) if err != nil { cmd.Fatal(err) } } cmd.Exit(err) }