| // depstool is a command-line tool for manipulating QUICHE WORKSPACE.bazel file. | |
| package main | |
| import ( | |
| "flag" | |
| "fmt" | |
| "io/ioutil" | |
| "log" | |
| "os" | |
| "time" | |
| "github.com/bazelbuild/buildtools/build" | |
| "quiche.googlesource.com/quiche/depstool/deps" | |
| ) | |
| func list(path string, contents []byte) { | |
| flags, err := deps.ParseHTTPArchiveRules(contents) | |
| if err != nil { | |
| log.Fatalf("Failed to parse %s: %v", path, err) | |
| } | |
| fmt.Println("+------------------------------+--------------------------+") | |
| fmt.Println("| Dependency | Last updated |") | |
| fmt.Println("+------------------------------+--------------------------+") | |
| for _, flag := range flags { | |
| lastUpdated, err := time.Parse("2006-01-02", flag.LastUpdated) | |
| if err != nil { | |
| log.Fatalf("Failed to parse date %s: %v", flag.LastUpdated, err) | |
| } | |
| delta := time.Since(lastUpdated) | |
| days := int(delta.Hours() / 24) | |
| fmt.Printf("| %28s | %s, %3d days ago |\n", flag.Name, flag.LastUpdated, days) | |
| } | |
| fmt.Println("+------------------------------+--------------------------+") | |
| } | |
| func validate(path string, contents []byte) { | |
| file, err := build.ParseWorkspace(path, contents) | |
| if err != nil { | |
| log.Fatalf("Failed to parse the WORKSPACE.bazel file: %v", err) | |
| } | |
| success := true | |
| for _, stmt := range file.Stmt { | |
| rule, ok := deps.HTTPArchiveRule(stmt) | |
| if !ok { | |
| // Skip unrelated rules | |
| continue | |
| } | |
| if _, err := deps.ParseHTTPArchiveRule(rule); err != nil { | |
| log.Printf("Failed to parse http_archive in %s on the line %d, issue: %v", path, rule.Pos.Line, err) | |
| success = false | |
| } | |
| } | |
| if !success { | |
| os.Exit(1) | |
| } | |
| log.Printf("All http_archive rules have been validated successfully") | |
| os.Exit(0) | |
| } | |
| func fetch(path string, contents []byte, outdir string) { | |
| rules, err := deps.ParseHTTPArchiveRules(contents) | |
| if err != nil { | |
| log.Fatalf("Failed to parse %s: %v", path, err) | |
| } | |
| for _, rule := range rules { | |
| log.Printf("Fetching %s into %s...", rule.Name, outdir) | |
| outfile, err := deps.FetchEntry(rule, outdir) | |
| if err != nil { | |
| log.Fatalf("Failed to fetch %s: %s", rule.Name, err) | |
| } | |
| log.Printf("Successfully fetched %s into %s", rule.Name, outfile) | |
| } | |
| } | |
| func usage() { | |
| fmt.Fprintf(flag.CommandLine.Output(), ` | |
| usage: depstool [WORKSPACE file] [subcommand] | |
| Available subcommands: | |
| list Lists all of the rules in the file | |
| validate Validates that the WORKSPACE file is parsable | |
| fetch Fetches all dependencies into the specified directory | |
| If no subcommand is specified, "list" is assumed. | |
| `) | |
| flag.PrintDefaults() | |
| } | |
| func main() { | |
| flag.Usage = usage | |
| flag.Parse() | |
| path := flag.Arg(0) | |
| if path == "" { | |
| usage() | |
| os.Exit(1) | |
| } | |
| contents, err := ioutil.ReadFile(path) | |
| if err != nil { | |
| log.Fatalf("Failed to read WORKSPACE.bazel file: %v", err) | |
| } | |
| subcommand := flag.Arg(1) | |
| switch subcommand { | |
| case "": | |
| fallthrough // list is the default action | |
| case "list": | |
| list(path, contents) | |
| case "validate": | |
| validate(path, contents) | |
| case "fetch": | |
| fetch(path, contents, flag.Arg(2)) | |
| default: | |
| log.Fatalf("Unknown command: %s", subcommand) | |
| } | |
| } |