1// depstool is a command-line tool for manipulating QUICHE WORKSPACE.bazel file. 2package main 3 4import ( 5 "flag" 6 "fmt" 7 "io/ioutil" 8 "log" 9 "os" 10 "time" 11 12 "github.com/bazelbuild/buildtools/build" 13 "quiche.googlesource.com/quiche/depstool/deps" 14) 15 16func list(path string, contents []byte) { 17 flags, err := deps.ParseHTTPArchiveRules(contents) 18 if err != nil { 19 log.Fatalf("Failed to parse %s: %v", path, err) 20 } 21 22 fmt.Println("+------------------------------+--------------------------+") 23 fmt.Println("| Dependency | Last updated |") 24 fmt.Println("+------------------------------+--------------------------+") 25 for _, flag := range flags { 26 lastUpdated, err := time.Parse("2006-01-02", flag.LastUpdated) 27 if err != nil { 28 log.Fatalf("Failed to parse date %s: %v", flag.LastUpdated, err) 29 } 30 delta := time.Since(lastUpdated) 31 days := int(delta.Hours() / 24) 32 fmt.Printf("| %28s | %s, %3d days ago |\n", flag.Name, flag.LastUpdated, days) 33 } 34 fmt.Println("+------------------------------+--------------------------+") 35} 36 37func validate(path string, contents []byte) { 38 file, err := build.ParseWorkspace(path, contents) 39 if err != nil { 40 log.Fatalf("Failed to parse the WORKSPACE.bazel file: %v", err) 41 } 42 43 success := true 44 for _, stmt := range file.Stmt { 45 rule, ok := deps.HTTPArchiveRule(stmt) 46 if !ok { 47 // Skip unrelated rules 48 continue 49 } 50 if _, err := deps.ParseHTTPArchiveRule(rule); err != nil { 51 log.Printf("Failed to parse http_archive in %s on the line %d, issue: %v", path, rule.Pos.Line, err) 52 success = false 53 } 54 } 55 if !success { 56 os.Exit(1) 57 } 58 log.Printf("All http_archive rules have been validated successfully") 59 os.Exit(0) 60} 61 62func usage() { 63 fmt.Fprintf(flag.CommandLine.Output(), ` 64usage: depstool [WORKSPACE file] [subcommand] 65 66Available subcommands: 67 list Lists all of the rules in the file 68 validate Validates that the WORKSPACE file is parsable 69 70If no subcommand is specified, "list" is assumed. 71`) 72 flag.PrintDefaults() 73} 74 75func main() { 76 flag.Usage = usage 77 flag.Parse() 78 path := flag.Arg(0) 79 if path == "" { 80 usage() 81 os.Exit(1) 82 } 83 contents, err := ioutil.ReadFile(path) 84 if err != nil { 85 log.Fatalf("Failed to read WORKSPACE.bazel file: %v", err) 86 } 87 88 subcommand := flag.Arg(1) 89 switch subcommand { 90 case "": 91 fallthrough // list is the default action 92 case "list": 93 list(path, contents) 94 case "validate": 95 validate(path, contents) 96 default: 97 log.Fatalf("Unknown command: %s", subcommand) 98 } 99} 100