1 |
Sometimes people wrap long lines in their ebuilds to make it easier to |
2 |
read, but this causes us issues when doing line-by-line checking. So |
3 |
automatically unroll those lines before passing the full content down |
4 |
to our checkers. |
5 |
|
6 |
Signed-off-by: Mike Frysinger <vapier@g.o> |
7 |
--- |
8 |
v2 |
9 |
- re-order heredoc/multiline checking |
10 |
|
11 |
pym/repoman/checks.py | 60 +++++++++++++++++++++++++++++++++++++++--------- |
12 |
1 files changed, 48 insertions(+), 12 deletions(-) |
13 |
|
14 |
diff --git a/pym/repoman/checks.py b/pym/repoman/checks.py |
15 |
index c17a0bd..cd8d3d2 100644 |
16 |
--- a/pym/repoman/checks.py |
17 |
+++ b/pym/repoman/checks.py |
18 |
@@ -759,6 +759,7 @@ _ignore_comment_re = re.compile(r'^\s*#') |
19 |
def run_checks(contents, pkg): |
20 |
checks = _constant_checks |
21 |
here_doc_delim = None |
22 |
+ multiline = None |
23 |
|
24 |
for lc in checks: |
25 |
lc.new(pkg) |
26 |
@@ -772,19 +773,54 @@ def run_checks(contents, pkg): |
27 |
here_doc = _here_doc_re.match(line) |
28 |
if here_doc is not None: |
29 |
here_doc_delim = re.compile(r'^\s*%s$' % here_doc.group(1)) |
30 |
+ if here_doc_delim is not None: |
31 |
+ continue |
32 |
+ |
33 |
+ # Unroll multiline escaped strings so that we can check things: |
34 |
+ # inherit foo bar \ |
35 |
+ # moo \ |
36 |
+ # cow |
37 |
+ # This will merge these lines like so: |
38 |
+ # inherit foo bar moo cow |
39 |
+ try: |
40 |
+ # A normal line will end in the two bytes: <\> <\n>. So decoding |
41 |
+ # that will result in python thinking the <\n> is being escaped |
42 |
+ # and eat the single <\> which makes it hard for us to detect. |
43 |
+ # Instead, strip the newline (which we know all lines have), and |
44 |
+ # append a <0>. Then when python escapes it, if the line ended |
45 |
+ # in a <\>, we'll end up with a <\0> marker to key off of. This |
46 |
+ # shouldn't be a problem with any valid ebuild ... |
47 |
+ line_escaped = (line.rstrip('\n') + '0').decode('string_escape') |
48 |
+ except: |
49 |
+ # Who knows what kind of crazy crap an ebuild will have |
50 |
+ # in it -- don't allow it to kill us. |
51 |
+ line_escaped = line |
52 |
+ if multiline: |
53 |
+ # Chop off the \ and \n bytes from the previous line. |
54 |
+ multiline = multiline[:-2] + line |
55 |
+ if not line_escaped.endswith('\0'): |
56 |
+ line = multiline |
57 |
+ num = multinum |
58 |
+ multiline = None |
59 |
+ else: |
60 |
+ continue |
61 |
+ else: |
62 |
+ if line_escaped.endswith('\0'): |
63 |
+ multinum = num |
64 |
+ multiline = line |
65 |
+ continue |
66 |
|
67 |
- if here_doc_delim is None: |
68 |
- # We're not in a here-document. |
69 |
- is_comment = _ignore_comment_re.match(line) is not None |
70 |
- for lc in checks: |
71 |
- if is_comment and lc.ignore_comment: |
72 |
- continue |
73 |
- if lc.check_eapi(pkg.metadata['EAPI']): |
74 |
- ignore = lc.ignore_line |
75 |
- if not ignore or not ignore.match(line): |
76 |
- e = lc.check(num, line) |
77 |
- if e: |
78 |
- yield lc.repoman_check_name, e % (num + 1) |
79 |
+ # Finally we have a full line to parse. |
80 |
+ is_comment = _ignore_comment_re.match(line) is not None |
81 |
+ for lc in checks: |
82 |
+ if is_comment and lc.ignore_comment: |
83 |
+ continue |
84 |
+ if lc.check_eapi(pkg.metadata['EAPI']): |
85 |
+ ignore = lc.ignore_line |
86 |
+ if not ignore or not ignore.match(line): |
87 |
+ e = lc.check(num, line) |
88 |
+ if e: |
89 |
+ yield lc.repoman_check_name, e % (num + 1) |
90 |
|
91 |
for lc in checks: |
92 |
i = lc.end() |
93 |
-- |
94 |
1.7.8.6 |