xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/depstool/depstool.go (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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 fetch(path string, contents []byte, outdir string) {
63	rules, err := deps.ParseHTTPArchiveRules(contents)
64	if err != nil {
65		log.Fatalf("Failed to parse %s: %v", path, err)
66	}
67
68	for _, rule := range rules {
69		log.Printf("Fetching %s into %s...", rule.Name, outdir)
70		outfile, err := deps.FetchEntry(rule, outdir)
71		if err != nil {
72			log.Fatalf("Failed to fetch %s: %s", rule.Name, err)
73		}
74		log.Printf("Successfully fetched %s into %s", rule.Name, outfile)
75	}
76}
77
78func usage() {
79	fmt.Fprintf(flag.CommandLine.Output(), `
80usage: depstool [WORKSPACE file] [subcommand]
81
82Available subcommands:
83    list       Lists all of the rules in the file
84    validate   Validates that the WORKSPACE file is parsable
85    fetch      Fetches all dependencies into the specified directory
86
87If no subcommand is specified, "list" is assumed.
88`)
89	flag.PrintDefaults()
90}
91
92func main() {
93	flag.Usage = usage
94	flag.Parse()
95	path := flag.Arg(0)
96	if path == "" {
97		usage()
98		os.Exit(1)
99	}
100	contents, err := ioutil.ReadFile(path)
101	if err != nil {
102		log.Fatalf("Failed to read WORKSPACE.bazel file: %v", err)
103	}
104
105	subcommand := flag.Arg(1)
106	switch subcommand {
107	case "":
108		fallthrough // list is the default action
109	case "list":
110		list(path, contents)
111	case "validate":
112		validate(path, contents)
113	case "fetch":
114		fetch(path, contents, flag.Arg(2))
115	default:
116		log.Fatalf("Unknown command: %s", subcommand)
117	}
118}
119