func mainInfo(args []string) int { f := flag.NewFlagSet("info", flag.ExitOnError) opt_check := f.Bool("c", false, "Run integrity check") f.Usage = func() { fmt.Print(infoUsage) f.PrintDefaults() } f.Parse(args) dir := f.Arg(0) if dir == "" { dir = "." } rep := repo.GetRepo(dir) status := 0 first := true err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error { if err != nil { fmt.Fprintf(os.Stderr, "%s: %v\n", path, err.Error()) status = 1 return err } // Skip .dirstore/ at root if filepath.Base(path) == attrs.DirStoreName && filepath.Dir(path) == dir && info.IsDir() { return filepath.SkipDir } else if !info.Mode().IsRegular() { return nil } if first { first = false } else { fmt.Println() } fmt.Printf("File: %s\n", path) if conflict := repo.ConflictFile(path); conflict != "" { fmt.Printf("Conflict With: %s\n", conflict) } for _, alt := range repo.ConflictFileAlternatives(path) { fmt.Printf("Conflict Alternatives: %s\n", alt) } var realHash mh.Multihash if *opt_check { realHash, err = repo.HashFile(path, info) if err != nil { fmt.Fprintf(os.Stderr, "%s: %v\n", path, err) return nil } } hashTime, err := repo.GetHashTime(path) if repo.IsNoData(err) { if *opt_check { fmt.Printf("Actual Hash: %s\n", base58.Encode(realHash)) } fmt.Printf("Status: New\n") } else { if err != nil { fmt.Fprintf(os.Stderr, "%s: %v\n", path, err.Error()) return nil } fmt.Printf("Hash Time: %v\n", hashTime.Format(time.RFC3339Nano)) hash, err := attrs.Get(path, repo.XattrHash) if err != nil { fmt.Fprintf(os.Stderr, "%s: %v\n", path, err) return nil } var par2exists = false if rep != nil { par2exists, _ = rep.Par2Exists(hash) } fmt.Printf("Recorded Hash: %s (reduncency %s)\n", base58.Encode(hash), boolToAvailableStr(par2exists)) if *opt_check { par2exists = false if rep != nil { par2exists, _ = rep.Par2Exists(realHash) } fmt.Printf("Actual Hash: %s (redundency %s)\n", base58.Encode(realHash), boolToAvailableStr(par2exists)) } if hashTime != info.ModTime() { fmt.Printf("Status: Dirty\n") } else { if *opt_check && !bytes.Equal(realHash, hash) { fmt.Printf("Status: Corrupted\n") } else { fmt.Printf("Status: Clean\n") } } } return nil }) if err != nil { fmt.Fprintf(os.Stderr, "%v", err) os.Exit(1) } return status }
func mainStatus(args []string) int { f := flag.NewFlagSet("status", flag.ExitOnError) opt_no_par2 := f.Bool("n", false, "Do not show files missing PAR2 redundency data") opt_show_only_hash := f.Bool("c", false, "Show only unchanged committed files with their hash") opt_no_docignore := f.Bool("no-docignore", false, "Don't treat .docignore files specially") f.Usage = func() { fmt.Print(usageStatus) f.PrintDefaults() } f.Parse(args) dir := f.Arg(0) if dir == "" { dir = "." } rep := repo.GetRepo(dir) status := 0 err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error { if err != nil { fmt.Fprintf(os.Stderr, "%s: %v\n", path, err.Error()) status = 1 return err } // Skip directories containing an empty .docignore file if !*opt_no_docignore && ignore.IsIgnored(path) { return filepath.SkipDir } // Skip .dirstore/ at root if filepath.Base(path) == attrs.DirStoreName && filepath.Dir(path) == dir && info.IsDir() { return filepath.SkipDir } else if !info.Mode().IsRegular() { return nil } if *opt_show_only_hash { hash, err := repo.GetHash(path, info, false) if err != nil { fmt.Fprintf(os.Stderr, "%s: %v\n", path, err.Error()) return nil } if hash != nil { fmt.Printf("%s\t%s\n", base58.Encode(hash), path) } } else { var conflict string = "" if repo.ConflictFile(path) != "" { conflict = " c" } else if len(repo.ConflictFileAlternatives(path)) > 0 { conflict = " C" } hashTime, err := repo.GetHashTime(path) if repo.IsNoData(err) { if info.Mode()&os.FileMode(0200) == 0 { fmt.Printf("?%s (ro)\t%s\n", conflict, path) } else { fmt.Printf("?%s\t%s\n", conflict, path) } return nil } else if err != nil { fmt.Fprintf(os.Stderr, "%s: %v\n", path, err.Error()) return nil } var redundency string = "*" if rep != nil { digest, err := repo.GetHash(path, info, true) if err != nil { fmt.Fprintf(os.Stderr, "%s: %v\n", path, err.Error()) return nil } if par2exists, _ := rep.Par2Exists(digest); par2exists { redundency = "" } } if hashTime != info.ModTime() { fmt.Printf("+%s%s\t%s\n", conflict, redundency, path) } else if conflict != "" || (redundency != "" && !*opt_no_par2) { fmt.Printf("%s%s\t%s\n", conflict, redundency, path) } } return nil }) if err != nil { fmt.Fprintf(os.Stderr, "%v", err) os.Exit(1) } return status }
func mainSave(args []string) int { f := flag.NewFlagSet("save", flag.ExitOnError) opt_force := f.Bool("force", false, "Force writing xattrs on read only files") opt_nodocignore := f.Bool("no-docignore", false, "Don't respect .docignore") f.Usage = func() { fmt.Print(saveUsage) f.PrintDefaults() } f.Parse(args) dir := f.Arg(0) if dir == "" { dir = "." } dirstore := repo.GetRepo(dir) if dirstore == nil { fmt.Fprintf(os.Stderr, "%s: Could not find repository, please run doc init\n", dir) os.Exit(1) } status := 0 err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error { if err != nil { fmt.Fprintf(os.Stderr, "%s: %v\n", path, err.Error()) status = 1 return err } if !*opt_nodocignore && ignore.IsIgnored(path) { return filepath.SkipDir } // Skip .dirstore/ at root if filepath.Base(path) == attrs.DirStoreName && filepath.Dir(path) == dir && info.IsDir() { return filepath.SkipDir } else if info.IsDir() || !info.Mode().IsRegular() { return nil } hashTime, err := repo.GetHashTime(path) if err != nil && !repo.IsNoData(err) { fmt.Fprintf(os.Stderr, "%s: %v\n", path, err.Error()) return nil } var digest []byte if err != nil || hashTime != info.ModTime() { digest, err = commitFile(path, info, *opt_force) if err != nil { status = 1 fmt.Fprintf(os.Stderr, "%s: %v\n", path, err.Error()) } else if digest != nil { fmt.Printf("%s %s\n", base58.Encode(digest), path) } } else { digest, err = attrs.Get(path, repo.XattrHash) if err != nil { fmt.Fprintf(os.Stderr, "%s: %v\n", path, err) return nil } } err = dirstore.Create(path, digest) if err != nil { fmt.Fprintf(os.Stderr, "%s: %v\n", path, err) return nil } return nil }) if err != nil { fmt.Fprintf(os.Stderr, "%v", err) os.Exit(1) } return status }