OLD | NEW |
---|---|
(Empty) | |
1 #!/usr/bin/env python | |
2 # Copyright 2015 The Chromium Authors. All rights reserved. | |
3 # Use of this source code is governed by a BSD-style license that can be | |
4 # found in the LICENSE file. | |
5 | |
6 """Suggests what Goop file entries can be removed. | |
7 | |
8 Horribly slow, but simple. Evaluates recursive dependencies of all packages | |
9 in infra/go/... (including github ones) and compares them against Goopfile.lock | |
10 entries. | |
11 | |
12 Supposed to be called under activated go environment. | |
13 """ | |
14 | |
15 import os | |
16 import subprocess | |
17 import sys | |
18 | |
19 # For VENDORED_TOOLS. | |
20 import bootstrap | |
21 | |
22 | |
23 GO_DIR = os.path.dirname(os.path.abspath(__file__)) | |
nodir
2015/09/29 16:46:05
You can check that $GOROOT equals this and suggest
Vadim Sh.
2015/09/29 19:49:34
GOROOT points to goland SDK. GOPATH have multiple
| |
24 | |
25 | |
26 # List of Goopfile.lock entries we want to keep because they are imported only | |
27 # when building on Windows (and thus detected as unused when script is used | |
28 # on Linux). | |
29 EXCEPTIONS = [ | |
30 'github.com/mattn/go-isatty', | |
31 'github.com/olekukonko/ts', | |
32 ] | |
33 | |
34 | |
35 def get_deps(pkg_glob): | |
tandrii(chromium)
2015/09/29 10:17:27
Add caching of the result, and it'll be so much fa
Vadim Sh.
2015/09/29 19:49:34
Added cache, it doesn't make much difference.
| |
36 """Returns a set of imported dependencies.""" | |
37 cmd = ['go', 'list', '-f', '{{ join .Deps "\\n" }}', pkg_glob] | |
nodir
2015/09/29 16:46:05
this must be ran with GO_DIR as current dir, becau
Vadim Sh.
2015/09/29 19:49:34
relpath(...) below builds correct path regardless
nodir
2015/09/29 20:39:13
I just ran go/clean_goop.py from root and it error
| |
38 print 'Running ', cmd | |
39 deps = subprocess.check_output(cmd).strip() | |
40 return sorted(set(deps.splitlines())) | |
41 | |
42 | |
43 def get_all_goop(): | |
tandrii(chromium)
2015/09/29 10:17:27
and maybe cache this too?
Vadim Sh.
2015/09/29 19:49:33
Done.
| |
44 """Returns a list of packages specified in Goopfile.lock.""" | |
45 with open(os.path.join(GO_DIR, 'Goopfile.lock'), 'rt') as f: | |
nodir
2015/09/29 16:46:05
't' mode is unnecessary to specify since it is def
Vadim Sh.
2015/09/29 19:49:34
r is too for that matter
| |
46 goop = f.read() | |
tandrii(chromium)
2015/09/29 10:17:27
nit: return [l.split()[0] for l in f]
Vadim Sh.
2015/09/29 19:49:34
Done.
| |
47 return [line.split()[0] for line in goop.splitlines()] | |
48 | |
49 | |
50 def get_used_goop(deps): | |
51 """Returns set of packages in Goopfile.lock that cover a dependency list.""" | |
52 used = set() | |
53 for pkg in get_all_goop(): | |
54 for dep in deps: | |
55 # If goop pkg covers at least one dependency, it is used. | |
56 if dep.startswith(pkg): | |
nodir
2015/09/29 16:46:05
if dep == pkg or dep.startswith(pkg+'/'):
Vadim Sh.
2015/09/29 19:49:34
Done.
| |
57 used.add(pkg) | |
58 break | |
59 return used | |
60 | |
61 | |
62 def main(): | |
63 all_deps = set(EXCEPTIONS) | |
64 | |
65 # We want to enumerate packages in infra/go/src/... and only them (not all | |
66 # packages in GOPAHT, since we don't want to enumerate vendored packages). | |
nodir
2015/09/29 16:46:05
GOPATH
| |
67 # A package glob needs to start with '.' or '..' to be interpreted as file | |
68 # system path. See 'go help packages'. | |
69 go_dir_rel = os.path.relpath(os.path.join(GO_DIR)) | |
nodir
2015/09/29 16:46:05
os.path.join(GO_DIR) == GO_DIR ? Am I missing some
Vadim Sh.
2015/09/29 19:49:34
There used to be something else there.
| |
70 assert go_dir_rel.startswith('.') | |
71 all_deps.update(get_deps(os.path.join(go_dir_rel, 'src', '...'))) | |
72 | |
73 # Tools build by bootstrap script may not be directly referenced by src/ code. | |
74 for tool in bootstrap.VENDORED_TOOLS: | |
75 all_deps.add(tool) | |
76 all_deps.update(get_deps(tool)) | |
77 | |
78 # all_deps is all direct dependencies of infra/go/src code. Find what part of | |
79 # Goopfile.lock covers them. Then recurse into them. Note that Goopfile | |
80 # may specify a parent package of a package used in actual code. So recursing | |
81 # into deps of that parent package may reveal more dependencies. | |
82 goop_deps = set() | |
83 while True: | |
84 for pkg in goop_deps: | |
nodir
2015/09/29 16:46:05
goop_deps is set() in the first iteration. Then it
Vadim Sh.
2015/09/29 19:49:33
Done.
| |
85 all_deps.update(get_deps(pkg + '/...')) | |
86 new_goop_deps = get_used_goop(all_deps) | |
87 if new_goop_deps == goop_deps: | |
88 break | |
89 goop_deps = new_goop_deps | |
90 | |
91 # Find what is not used. | |
92 unused = [p for p in get_all_goop() if p not in goop_deps] | |
93 if unused: | |
94 print '-' * 80 | |
95 print 'Consider removing from Goopfile following packages:' | |
tandrii(chromium)
2015/09/29 10:17:27
nit: s/following/the following
Vadim Sh.
2015/09/29 19:49:34
Done.
| |
96 print '\n'.join(unused) | |
97 else: | |
98 print 'Hooray! All Goopfile packages seems to be in use.' | |
tandrii(chromium)
2015/09/29 10:17:28
s/seems/seem
Vadim Sh.
2015/09/29 19:49:34
Done.
| |
99 | |
100 return 0 | |
101 | |
102 | |
103 if __name__ == '__main__': | |
104 sys.exit(main()) | |
OLD | NEW |