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