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 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) } }
// 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) }