Skip to content

Commit d37fefb

Browse files
authored
In progress refactor: separate crawling from generation (#199)
1 parent 082bd87 commit d37fefb

25 files changed

+438
-641
lines changed

BUILD

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@ py_library(
1313
"src/common/*.py",
1414
"src/config/*.py",
1515
"src/common/*.py",
16-
"src/crawl/*.py"]),
16+
"src/crawl/*.py",
17+
"src/generate/*.py",
18+
"src/generate/impl/*.py"]),
1719
data = ["src/config/pom_template.xml"],
1820
visibility = ["//misc:__pkg__",],
1921
)
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# random target, unrelated to the pom template generation
2+
sh_test(
3+
name = "test",
4+
srcs = ["test.sh"],
5+
)
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
echo "example test"
2+

src/common/label.py

Lines changed: 48 additions & 202 deletions
Original file line numberDiff line numberDiff line change
@@ -7,137 +7,63 @@
77
This module has abstractions for Bazel labels.
88
"""
99

10-
1110
import os
1211

1312

14-
_BUILD_FILE_NAMES = ("BUILD", "BUILD.bazel")
15-
16-
17-
def for_package(root_dir, package_path):
18-
"""
19-
Returns a label instance for the Bazel package at the given relative path,
20-
rooted at the given root_dir. Returns None if no build file exists at that
21-
location.
22-
"""
23-
for fname in _BUILD_FILE_NAMES:
24-
rel_path = os.path.join(package_path, fname)
25-
abs_path = os.path.join(root_dir, rel_path)
26-
if os.path.isfile(abs_path):
27-
return Label(rel_path)
28-
return None
29-
30-
31-
def find_packages(root_dir, package_path=""):
32-
"""
33-
Walks the directory tree, starting at root dir, and returns a list of
34-
Label instances for all Bazel packages that exist under the given root_dir.
35-
36-
If package_path is specified, the search starts at that location.
37-
"""
38-
labels = []
39-
for path, dirs, files in os.walk(os.path.join(root_dir, package_path)):
40-
for fname in files:
41-
if fname in _BUILD_FILE_NAMES:
42-
rel_path = os.path.join(os.path.relpath(path, root_dir), fname)
43-
if rel_path.startswith("./"):
44-
# build file at root dir, remove "./" so that the package
45-
# of the Label is empty
46-
rel_path = rel_path[2:]
47-
labels.append(Label(rel_path))
48-
return labels
49-
50-
5113
class Label(object):
5214
"""
53-
Represents a Bazel Label.
15+
Represents a bazel Label.
5416
"""
5517

5618
def __init__(self, name):
5719
"""
58-
Initializes a Label with the given name, a string. name represents
59-
a path-like structure with an optional target [path:target].
60-
61-
If the last path segment is a build file (/BUILD or /BUILD.bazel),
62-
it is removed from the path.
63-
20+
Initializes a Label with the given string label representation.
6421
"""
6522
assert name is not None
6623
name = name.strip()
6724
if name.endswith("/"):
6825
name = name[:-1]
69-
fname = os.path.basename(name)
70-
if fname in ("BUILD", "BUILD.bazel"):
71-
name = os.path.dirname(name)
72-
self._build_file_name = fname
73-
else:
74-
self._build_file_name = None
7526
self._name = name
7627

77-
@property
78-
def name(self):
79-
"""
80-
The name this instance was initialized with.
81-
"""
82-
return self._name
83-
84-
@property
85-
def package(self):
86-
"""
87-
The Bazel Package of this label.
88-
For example, for "//a/b/c:foo", return "//a/b/c"
89-
"""
90-
i = self._name.find(":")
91-
if i == -1:
92-
if self._name.endswith("..."):
93-
return self._name[:-3]
94-
return self._name
95-
return self._name[0:i]
96-
9728
@property
9829
def package_path(self):
9930
"""
100-
Returns the Package of this label as a valid relative path.
31+
Returns the package of this label as a relative path.
10132
"""
102-
p = self.package
103-
if p.startswith("//"):
104-
p = p[2:]
105-
if p.endswith("/"):
106-
p = p[:-1]
107-
return p
33+
start_index = self._name.find("//")
34+
if start_index == -1:
35+
start_index = 0
36+
else:
37+
start_index += 2
38+
target_index = self._name.rfind(":")
39+
if target_index == -1:
40+
target_index = len(self._name)
41+
path = self._name[start_index:target_index]
42+
if path.endswith("..."):
43+
path = path[:-3]
44+
if path.endswith("/"):
45+
path = path[:-1]
46+
return path
10847

10948
@property
11049
def target(self):
11150
"""
112-
The Bazel Target of this label.
113-
For example, for "//a/b/c:foo", return "foo"
51+
The bazel target of this label.
52+
For example, for "//a/b/c:foo", returns "foo".
11453
"""
115-
i = self._name.find(":")
54+
i = self._name.rfind(":")
11655
if i == -1:
11756
return os.path.basename(self._name)
11857
return self._name[i+1:]
11958

120-
@property
121-
def target_name(self):
122-
"""
123-
An alias for the "target" property.
124-
"""
125-
return self.target
126-
12759
@property
12860
def is_default_target(self):
12961
"""
13062
Returns True if this label refers to the default target in the package,
13163
ie the target that has the same name as the directory the BUILD file
13264
lives in.
13365
"""
134-
package = self.package
135-
target = self.target
136-
if package is None:
137-
return False
138-
if target is None:
139-
return True
140-
return os.path.basename(package) == target
66+
return os.path.basename(self.package_path) == self.target
14167

14268
@property
14369
def is_root_target(self):
@@ -148,66 +74,26 @@ def is_root_target(self):
14874
return "//:" in self._name
14975

15076
@property
151-
def fqname(self):
152-
"""
153-
The name of this label with a default repo prefix, iff the
154-
initial name did not specify such a prefix and this is not a src ref.
155-
"""
156-
if self.is_source_ref:
157-
return self._name
158-
if self.has_repo_prefix:
159-
return self._name
160-
else:
161-
# the default prefix we use for names without repo prefix:
162-
# if name is foo, fqname will be @maven//:foo
163-
# "maven" doesn't really make sense to use anymore, but it isn't
164-
# clear what to use instead - probably defaulting the repo doesn't
165-
# make sense
166-
default_repo = "maven"
167-
return self.prefix_with(default_repo).name
168-
169-
@property
170-
def simple_name(self):
171-
"""
172-
The name of this label without the remote repo prefix.
173-
If this label does not have a remote repo prefix, returns just
174-
its name.
175-
"""
176-
if self.is_source_ref:
177-
return self._name
178-
if self.has_repo_prefix:
179-
prefix = self.repo_prefix
180-
return self._name[len(prefix)+4:] # 4 = additional chars @//:
181-
else:
182-
return self._name
183-
184-
@property
185-
def is_private(self):
186-
"""
187-
Returns True if this label refers to a private target (starts with ":")
188-
"""
189-
return self._name.startswith(":")
190-
191-
@property
192-
def has_repo_prefix(self):
77+
def has_repository_prefix(self):
19378
"""
194-
Whether this label name has a remote repo prefix.
79+
Whether this label name has a remote repository prefix.
19580
"""
196-
return self.repo_prefix is not None
81+
return self.repository_prefix != ""
19782

19883
@property
199-
def repo_prefix(self):
84+
def repository_prefix(self):
20085
"""
201-
The remote repo prefix, or workspace name of this label; None if this
202-
label name doesn't have one.
86+
The repository prefix, or workspace name of this label; empty string if
87+
this label name doesn't have one.
20388
204-
For example, for a label like "@pomgen//maven", returns "pomgen".
89+
For example, for a label like "@pomgen//maven", this method returns
90+
"@pomgen", for "//foo/path" it returns "".
20591
"""
20692
if self._name.startswith("@"):
20793
i = self._name.find("//")
20894
if i != -1:
209-
return self._name[1:i]
210-
return None
95+
return self._name[0:i]
96+
return ""
21197

21298
@property
21399
def is_source_ref(self):
@@ -217,81 +103,41 @@ def is_source_ref(self):
217103
return self._name.startswith("//")
218104

219105
@property
220-
def has_file_extension(self):
221-
ext = os.path.splitext(self._name)[1]
222-
return ext in (".jar", ".proto", ".h", ".c", ".cc", ".cpp", ".m", ".py", ".pyc", ".java", ".go")
223-
224-
@property
225-
def has_extension_suffix(self):
226-
return self._name.endswith("_extension")
227-
228-
@property
229-
def is_sources_artifact(self):
230-
return "_jar_sources" in self._name
231-
232-
@property
233-
def build_file_path(self):
106+
def canonical_form(self):
234107
"""
235-
The path to the build file of this package, if this Label instance was
236-
created with a path that pointed to a build file.
237-
None if this Label instance does not know about the build file it was
238-
created for.
239-
"""
240-
if self._build_file_name is None:
241-
return None
242-
return os.path.join(self.package_path, self._build_file_name)
108+
Returns the label as a string in its canonical form:
243109
244-
def prefix_with(self, repo_prefix):
245-
"""
246-
Returns a new Label instance that is qualified with the
247-
specified repo_prefix. This method asserts that this instance is not
248-
already fully qualified.
249-
"""
250-
assert not self.has_repo_prefix, "This label already has a repo prefix: %s" % self._name
251-
return Label("@%s//:%s" % (repo_prefix, self._name))
110+
[@repository]//<package-path>:<target>.
252111
253-
def with_target(self, target):
254-
"""
255-
Returns a new Label instance that has the specified target.
112+
References to the default target are omitted.
256113
"""
257-
return Label("%s:%s" % (self.package, target))
114+
target = "" if self.is_default_target else ":%s" % self.target
115+
return "%s//%s%s" % (self.repository_prefix, self.package_path, target)
258116

259-
def as_wildcard_label(self, wildcard):
260-
if wildcard == "...":
261-
return Label("%s/%s" % (self.package, wildcard))
262-
else:
263-
return Label("%s:%s" % (self.package, wildcard))
264-
265-
def as_alternate_default_target_syntax(self):
117+
def with_target(self, new_target_name):
266118
"""
267-
Labels may omit the target if they refer to the default target, or they
268-
may not omit it. If this Label instance refers to the default target,
269-
this method returns the other syntax.
270-
So:
271-
Given this Label instance is: //a/b/c, returns //a/b/c:c
272-
Or, given this Label instance is //a/b/c:c, returns //a/b/c
119+
Returns a new Label instance with the specified new target name.
273120
"""
274-
assert self.is_default_target, "label must refer to the default target"
275-
if ":" in self.name:
276-
return Label(self.package)
121+
if self.is_default_target:
122+
label = self.canonical_form
277123
else:
278-
return Label("%s:%s" % (self.package, self.target))
124+
label = self.canonical_form[:-(len(self.target)+1)]
125+
return Label("%s:%s" % (label, new_target_name))
279126

280127
def __hash__(self):
281-
return hash((self.package_path, self.target))
128+
return hash((self.repository_prefix, self.package_path, self.target))
282129

283130
def __eq__(self, other):
284131
if other is None:
285132
return False
286-
return self.package_path == other.package_path and self.target == other.target
133+
return (self.repository_prefix == other.repository_prefix and
134+
self.package_path == other.package_path and
135+
self.target == other.target)
287136

288137
def __ne__(self, other):
289138
return not self == other
290139

291-
def __len__(self):
292-
return len(self._name)
293-
294140
def __repr__(self):
295-
return self._name
141+
return self.canonical_form
296142

297143
__str__ = __repr__

0 commit comments

Comments
 (0)