github.com/npaton/distribution@v2.3.1-rc.0+incompatible/cmd/digest/main.go (about) 1 package main 2 3 import ( 4 "flag" 5 "fmt" 6 "io" 7 "log" 8 "os" 9 10 "github.com/docker/distribution/digest" 11 "github.com/docker/distribution/version" 12 ) 13 14 var ( 15 algorithm = digest.Canonical 16 showVersion bool 17 ) 18 19 type job struct { 20 name string 21 reader io.Reader 22 } 23 24 func init() { 25 flag.Var(&algorithm, "a", "select the digest algorithm (shorthand)") 26 flag.Var(&algorithm, "algorithm", "select the digest algorithm") 27 flag.BoolVar(&showVersion, "version", false, "show the version and exit") 28 29 log.SetFlags(0) 30 log.SetPrefix(os.Args[0] + ": ") 31 } 32 33 func usage() { 34 fmt.Fprintf(os.Stderr, "usage: %s [files...]\n", os.Args[0]) 35 fmt.Fprintf(os.Stderr, ` 36 Calculate the digest of one or more input files, emitting the result 37 to standard out. If no files are provided, the digest of stdin will 38 be calculated. 39 40 `) 41 flag.PrintDefaults() 42 } 43 44 func unsupported() { 45 log.Fatalf("unsupported digest algorithm: %v", algorithm) 46 } 47 48 func main() { 49 var jobs []job 50 51 flag.Usage = usage 52 flag.Parse() 53 if showVersion { 54 version.PrintVersion() 55 return 56 } 57 58 var fail bool // if we fail on one item, foul the exit code 59 if flag.NArg() > 0 { 60 for _, path := range flag.Args() { 61 fp, err := os.Open(path) 62 63 if err != nil { 64 log.Printf("%s: %v", path, err) 65 fail = true 66 continue 67 } 68 defer fp.Close() 69 70 jobs = append(jobs, job{name: path, reader: fp}) 71 } 72 } else { 73 // just read stdin 74 jobs = append(jobs, job{name: "-", reader: os.Stdin}) 75 } 76 77 digestFn := algorithm.FromReader 78 79 if !algorithm.Available() { 80 unsupported() 81 } 82 83 for _, job := range jobs { 84 dgst, err := digestFn(job.reader) 85 if err != nil { 86 log.Printf("%s: %v", job.name, err) 87 fail = true 88 continue 89 } 90 91 fmt.Printf("%v\t%s\n", dgst, job.name) 92 } 93 94 if fail { 95 os.Exit(1) 96 } 97 }