1 |
commit: bad313667aa111639f9c5801d6f10420968ac2b9 |
2 |
Author: Arthur Zamarin <arthurzam <AT> gentoo <DOT> org> |
3 |
AuthorDate: Thu Nov 3 17:43:47 2022 +0000 |
4 |
Commit: Arthur Zamarin <arthurzam <AT> gentoo <DOT> org> |
5 |
CommitDate: Tue Nov 8 18:59:00 2022 +0000 |
6 |
URL: https://gitweb.gentoo.org/proj/pkgcore/pkgcheck.git/commit/?id=bad31366 |
7 |
|
8 |
NonPosixHeadTailUsage: new check |
9 |
|
10 |
New warning for non-POSIX compliant head or tail without -n. |
11 |
|
12 |
Closes: https://bugs.gentoo.org/558360 |
13 |
Signed-off-by: Arthur Zamarin <arthurzam <AT> gentoo.org> |
14 |
|
15 |
src/pkgcheck/checks/codingstyle.py | 46 ++++++++++++++++++++++ |
16 |
.../NonPosixHeadTailUsage/expected.json | 5 +++ |
17 |
.../NonPosixCheck/NonPosixHeadTailUsage/fix.patch | 26 ++++++++++++ |
18 |
.../NonPosixHeadTailUsage-0.ebuild | 10 +++++ |
19 |
.../NonPosixHeadTailUsage-1.ebuild | 11 ++++++ |
20 |
5 files changed, 98 insertions(+) |
21 |
|
22 |
diff --git a/src/pkgcheck/checks/codingstyle.py b/src/pkgcheck/checks/codingstyle.py |
23 |
index 30e7f9f9..954ef09d 100644 |
24 |
--- a/src/pkgcheck/checks/codingstyle.py |
25 |
+++ b/src/pkgcheck/checks/codingstyle.py |
26 |
@@ -1170,3 +1170,49 @@ class DoCompressedFilesCheck(Check): |
27 |
lineno, _ = arg.start_point |
28 |
if arg_name.endswith(self.compresion_extentions): |
29 |
yield self.functions[call_name](call_name, lineno=lineno+1, line=arg_name, pkg=pkg) |
30 |
+ |
31 |
+ |
32 |
+class NonPosixHeadTailUsage(results.LineResult, results.Warning): |
33 |
+ """Using of non-POSIX compliant ``head`` or ``tail``. |
34 |
+ |
35 |
+ The numeric argument to ``head`` or ``tail`` without ``-n`` (for example |
36 |
+ ``head -10``) is deprecated and not POSIX compliant. To fix, prepand ``-n`` |
37 |
+ before the number [#]_. |
38 |
+ |
39 |
+ .. [#] https://devmanual.gentoo.org/tools-reference/head-and-tail/index.html |
40 |
+ """ |
41 |
+ def __init__(self, command, **kwargs): |
42 |
+ super().__init__(**kwargs) |
43 |
+ self.command = command |
44 |
+ |
45 |
+ @property |
46 |
+ def desc(self): |
47 |
+ return f'line {self.lineno}: non-posix usage of {self.command!r}: {self.line!r}' |
48 |
+ |
49 |
+ |
50 |
+class NonPosixCheck(Check): |
51 |
+ """Scan ebuild for non-posix usage, code which might be not portable.""" |
52 |
+ |
53 |
+ _source = sources.EbuildParseRepoSource |
54 |
+ known_results = frozenset([NonPosixHeadTailUsage]) |
55 |
+ |
56 |
+ def __init__(self, options, **kwargs): |
57 |
+ super().__init__(options, **kwargs) |
58 |
+ self.re_head_tail = re.compile(r'[+-]\d+') |
59 |
+ |
60 |
+ def check_head_tail(self, pkg, call_node, call_name): |
61 |
+ prev_arg = '' |
62 |
+ for arg in map(pkg.node_str, call_node.children[1:]): |
63 |
+ if (self.re_head_tail.match(arg) and |
64 |
+ not (prev_arg.startswith('-') and prev_arg.endswith(('n', 'c')))): |
65 |
+ lineno, _ = call_node.start_point |
66 |
+ yield NonPosixHeadTailUsage(f'{call_name} {arg}', |
67 |
+ lineno=lineno+1, line=pkg.node_str(call_node), pkg=pkg) |
68 |
+ break |
69 |
+ prev_arg = arg |
70 |
+ |
71 |
+ def feed(self, pkg): |
72 |
+ for call_node, _ in bash.cmd_query.captures(pkg.tree.root_node): |
73 |
+ call_name = pkg.node_str(call_node.child_by_field_name('name')) |
74 |
+ if call_name in ('head', 'tail'): |
75 |
+ yield from self.check_head_tail(pkg, call_node, call_name) |
76 |
|
77 |
diff --git a/testdata/data/repos/standalone/NonPosixCheck/NonPosixHeadTailUsage/expected.json b/testdata/data/repos/standalone/NonPosixCheck/NonPosixHeadTailUsage/expected.json |
78 |
new file mode 100644 |
79 |
index 00000000..daed2c67 |
80 |
--- /dev/null |
81 |
+++ b/testdata/data/repos/standalone/NonPosixCheck/NonPosixHeadTailUsage/expected.json |
82 |
@@ -0,0 +1,5 @@ |
83 |
+{"__class__": "NonPosixHeadTailUsage", "category": "NonPosixCheck", "package": "NonPosixHeadTailUsage", "version": "0", "line": "head -1 file", "lineno": 7, "command": "head -1"} |
84 |
+{"__class__": "NonPosixHeadTailUsage", "category": "NonPosixCheck", "package": "NonPosixHeadTailUsage", "version": "0", "line": "head -q file -1", "lineno": 8, "command": "head -1"} |
85 |
+{"__class__": "NonPosixHeadTailUsage", "category": "NonPosixCheck", "package": "NonPosixHeadTailUsage", "version": "1", "line": "tail -1 file", "lineno": 7, "command": "tail -1"} |
86 |
+{"__class__": "NonPosixHeadTailUsage", "category": "NonPosixCheck", "package": "NonPosixHeadTailUsage", "version": "1", "line": "tail -q file -1", "lineno": 8, "command": "tail -1"} |
87 |
+{"__class__": "NonPosixHeadTailUsage", "category": "NonPosixCheck", "package": "NonPosixHeadTailUsage", "version": "1", "line": "tail -qn file +1", "lineno": 9, "command": "tail +1"} |
88 |
|
89 |
diff --git a/testdata/data/repos/standalone/NonPosixCheck/NonPosixHeadTailUsage/fix.patch b/testdata/data/repos/standalone/NonPosixCheck/NonPosixHeadTailUsage/fix.patch |
90 |
new file mode 100644 |
91 |
index 00000000..c01e9028 |
92 |
--- /dev/null |
93 |
+++ b/testdata/data/repos/standalone/NonPosixCheck/NonPosixHeadTailUsage/fix.patch |
94 |
@@ -0,0 +1,26 @@ |
95 |
+--- standalone/NonPosixCheck/NonPosixHeadTailUsage/NonPosixHeadTailUsage-0.ebuild |
96 |
++++ fixed/NonPosixCheck/NonPosixHeadTailUsage/NonPosixHeadTailUsage-0.ebuild |
97 |
+@@ -4,7 +4,7 @@ SLOT="0" |
98 |
+ LICENSE="BSD" |
99 |
+ |
100 |
+ src_prepare() { |
101 |
+- head -1 file > another || die |
102 |
+- head -q file -1 > another || die |
103 |
++ head -n -1 file > another || die |
104 |
++ head -qn 1 file > another || die |
105 |
+ default |
106 |
+ } |
107 |
+--- standalone/NonPosixCheck/NonPosixHeadTailUsage/NonPosixHeadTailUsage-1.ebuild |
108 |
++++ fixed/NonPosixCheck/NonPosixHeadTailUsage/NonPosixHeadTailUsage-1.ebuild |
109 |
+@@ -4,8 +4,8 @@ SLOT="0" |
110 |
+ LICENSE="BSD" |
111 |
+ |
112 |
+ src_prepare() { |
113 |
+- tail -1 file > another || die |
114 |
+- tail -q file -1 > another || die |
115 |
+- tail -qn file +1 > another || die |
116 |
++ tail -n 1 file > another || die |
117 |
++ tail -q file -c 1 > another || die |
118 |
++ tail file -qn +1 > another || die |
119 |
+ default |
120 |
+ } |
121 |
|
122 |
diff --git a/testdata/repos/standalone/NonPosixCheck/NonPosixHeadTailUsage/NonPosixHeadTailUsage-0.ebuild b/testdata/repos/standalone/NonPosixCheck/NonPosixHeadTailUsage/NonPosixHeadTailUsage-0.ebuild |
123 |
new file mode 100644 |
124 |
index 00000000..6ee3b8fc |
125 |
--- /dev/null |
126 |
+++ b/testdata/repos/standalone/NonPosixCheck/NonPosixHeadTailUsage/NonPosixHeadTailUsage-0.ebuild |
127 |
@@ -0,0 +1,10 @@ |
128 |
+DESCRIPTION="Ebuild with non posix head usage" |
129 |
+HOMEPAGE="https://github.com/pkgcore/pkgcheck" |
130 |
+SLOT="0" |
131 |
+LICENSE="BSD" |
132 |
+ |
133 |
+src_prepare() { |
134 |
+ head -1 file > another || die |
135 |
+ head -q file -1 > another || die |
136 |
+ default |
137 |
+} |
138 |
|
139 |
diff --git a/testdata/repos/standalone/NonPosixCheck/NonPosixHeadTailUsage/NonPosixHeadTailUsage-1.ebuild b/testdata/repos/standalone/NonPosixCheck/NonPosixHeadTailUsage/NonPosixHeadTailUsage-1.ebuild |
140 |
new file mode 100644 |
141 |
index 00000000..6e926ae8 |
142 |
--- /dev/null |
143 |
+++ b/testdata/repos/standalone/NonPosixCheck/NonPosixHeadTailUsage/NonPosixHeadTailUsage-1.ebuild |
144 |
@@ -0,0 +1,11 @@ |
145 |
+DESCRIPTION="Ebuild with non posix head usage" |
146 |
+HOMEPAGE="https://github.com/pkgcore/pkgcheck" |
147 |
+SLOT="0" |
148 |
+LICENSE="BSD" |
149 |
+ |
150 |
+src_prepare() { |
151 |
+ tail -1 file > another || die |
152 |
+ tail -q file -1 > another || die |
153 |
+ tail -qn file +1 > another || die |
154 |
+ default |
155 |
+} |