Add rpm spec file linter (rpmlint) (#486)
* Initial attempt at an rpmlint linter. * Add some basic documentation. * Play with indentation in the test file. * Another attempt to fix the rpmlint test. * Hopefully this does it.
This commit is contained in:
parent
d8dcc56af5
commit
4eeb4783d3
@ -95,6 +95,7 @@ name. That seems to be the fairest way to arrange this table.
|
|||||||
| Puppet | [puppet](https://puppet.com), [puppet-lint](https://puppet-lint.com) |
|
| Puppet | [puppet](https://puppet.com), [puppet-lint](https://puppet-lint.com) |
|
||||||
| Python | [flake8](http://flake8.pycqa.org/en/latest/), [mypy](http://mypy-lang.org/), [pylint](https://www.pylint.org/) |
|
| Python | [flake8](http://flake8.pycqa.org/en/latest/), [mypy](http://mypy-lang.org/), [pylint](https://www.pylint.org/) |
|
||||||
| reStructuredText | [proselint](http://proselint.com/)|
|
| reStructuredText | [proselint](http://proselint.com/)|
|
||||||
|
| RPM spec | [rpmlint](https://github.com/rpm-software-management/rpmlint) |
|
||||||
| Ruby | [rubocop](https://github.com/bbatsov/rubocop), [ruby](https://www.ruby-lang.org) |
|
| Ruby | [rubocop](https://github.com/bbatsov/rubocop), [ruby](https://www.ruby-lang.org) |
|
||||||
| Rust | [rustc](https://www.rust-lang.org/), cargo (see `:help ale-integration-rust` for configuration instructions) |
|
| Rust | [rustc](https://www.rust-lang.org/), cargo (see `:help ale-integration-rust` for configuration instructions) |
|
||||||
| SASS | [sass-lint](https://www.npmjs.com/package/sass-lint), [stylelint](https://github.com/stylelint/stylelint) |
|
| SASS | [sass-lint](https://www.npmjs.com/package/sass-lint), [stylelint](https://github.com/stylelint/stylelint) |
|
||||||
|
85
ale_linters/spec/rpmlint.vim
Normal file
85
ale_linters/spec/rpmlint.vim
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
" Author: Jason Tibbitts <tibbs@math.uh.edu>
|
||||||
|
" Description: Adds support for checking RPM spec files with rpmlint
|
||||||
|
|
||||||
|
" rpmlint will produce varions types of output:
|
||||||
|
"
|
||||||
|
" Lines like the following are output when the file is simply not able to be
|
||||||
|
" parsed by rpmspec -P:
|
||||||
|
" apcupsd.spec: E: specfile-error warning: bogus date in %changelog: Mon Oct 1 2005 - Foo
|
||||||
|
" apcupsd.spec: E: specfile-error error: %changelog not in descending chronological order
|
||||||
|
" They do not contain a line number, and there's not a whole lot that can be
|
||||||
|
" done to locate them besides grep for them. rpmlint is just passing the
|
||||||
|
" output from rpm along with the filename, an error indicator, and an error
|
||||||
|
" type.
|
||||||
|
"
|
||||||
|
" Lines like the following:
|
||||||
|
" cyrus-imapd.spec:23: W: macro-in-comment %version
|
||||||
|
" cyrus-imapd.spec:18: E: hardcoded-library-path in %_prefix/lib/%name
|
||||||
|
" indicate warnings and errors, respectively. No column numbers are provided
|
||||||
|
"
|
||||||
|
" Lines like:
|
||||||
|
" apcupsd.spec: I: checking
|
||||||
|
" apcupsd.spec: I: checking-url https://downloads.sourceforge.net/apcupsd/apcupsd-3.14.14.tar.gz (timeout 10 seconds)
|
||||||
|
" are merely informational and are only output when -v is passed. But they
|
||||||
|
" may be useful in a log to know why things are taking so long.
|
||||||
|
"
|
||||||
|
" And this is always output at the end and should just be ignored:
|
||||||
|
" 0 packages and 1 specfiles checked; 4 errors, 0 warnings.
|
||||||
|
|
||||||
|
let g:ale_spec_rpmlint_executable =
|
||||||
|
\ get(g:, 'ale_spec_rpmlint_executable', 'rpmlint')
|
||||||
|
|
||||||
|
let g:ale_spec_rpmlint_options =
|
||||||
|
\ get(g:, 'ale_spec_rpmlint_options', '')
|
||||||
|
|
||||||
|
function! ale_linters#spec#rpmlint#GetExecutable(buffer) abort
|
||||||
|
return ale#Var(a:buffer, 'spec_rpmlint_executable')
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! ale_linters#spec#rpmlint#GetCommand(buffer) abort
|
||||||
|
return ale_linters#spec#rpmlint#GetExecutable(a:buffer)
|
||||||
|
\ . ' ' . ale#Var(a:buffer, 'spec_rpmlint_options')
|
||||||
|
\ . ' -o "NetworkEnabled False"'
|
||||||
|
\ . ' -v'
|
||||||
|
\ . ' %t'
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
function! ale_linters#spec#rpmlint#Handle(buffer, lines) abort
|
||||||
|
" let l:pat_inform = '^.\+: I: \(.+\)'
|
||||||
|
let l:pat_errwarn = '^.\+:\(\d\+\): \([EW]\): \(.\+\)'
|
||||||
|
let l:pat_baderr = '^.\+: E: \(.\+\)'
|
||||||
|
let l:output = []
|
||||||
|
|
||||||
|
for l:line in a:lines
|
||||||
|
let l:match_errwarn = matchlist(l:line, l:pat_errwarn)
|
||||||
|
let l:match_baderr = matchlist(l:line, l:pat_baderr)
|
||||||
|
|
||||||
|
if len(l:match_errwarn) > 0
|
||||||
|
let l:text = l:match_errwarn[3]
|
||||||
|
let l:type = l:match_errwarn[2]
|
||||||
|
let l:lnum = l:match_errwarn[1] + 0
|
||||||
|
elseif len(l:match_baderr) > 0
|
||||||
|
let l:text = l:match_baderr[1]
|
||||||
|
let l:type = 'E'
|
||||||
|
let l:lnum = 1
|
||||||
|
else
|
||||||
|
continue
|
||||||
|
endif
|
||||||
|
|
||||||
|
call add(l:output, {
|
||||||
|
\ 'bufnr': a:buffer,
|
||||||
|
\ 'lnum': l:lnum,
|
||||||
|
\ 'text': l:text,
|
||||||
|
\ 'type': l:type,
|
||||||
|
\})
|
||||||
|
endfor
|
||||||
|
|
||||||
|
return l:output
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
call ale#linter#Define('spec', {
|
||||||
|
\ 'name': 'rpmlint',
|
||||||
|
\ 'executable_callback': 'ale_linters#spec#rpmlint#GetExecutable',
|
||||||
|
\ 'command_callback': 'ale_linters#spec#rpmlint#GetCommand',
|
||||||
|
\ 'callback': 'ale_linters#spec#rpmlint#Handle',
|
||||||
|
\})
|
28
doc/ale-spec.txt
Normal file
28
doc/ale-spec.txt
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
===============================================================================
|
||||||
|
ALE RPM Spec Integration *ale-spec-options*
|
||||||
|
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
rpmlint *ale-spec-rpmlint*
|
||||||
|
|
||||||
|
g:ale_spec_rpmlint_executable *g:ale_spec_rpmlint_executable*
|
||||||
|
|
||||||
|
Type: |String|
|
||||||
|
Default: `'rpmlint'`
|
||||||
|
|
||||||
|
This variable sets executable used for rpmlint.
|
||||||
|
|
||||||
|
|
||||||
|
g:ale_spec_rpmlint_options *g:ale_spec_rpmlint_options*
|
||||||
|
|
||||||
|
Type: |String|
|
||||||
|
Default: `''`
|
||||||
|
|
||||||
|
Set this to pass extra arguments to rpmlint.
|
||||||
|
|
||||||
|
For example, to instruct rpmlint to use a specific configuration file:
|
||||||
|
|
||||||
|
let g:ale_spec_rpmlint_options = '-f custom.cf'
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
vim:tw=78:ts=2:sts=2:sw=2:ft=help:norl:
|
@ -71,6 +71,8 @@ CONTENTS *ale-contents*
|
|||||||
sh....................................|ale-sh-options|
|
sh....................................|ale-sh-options|
|
||||||
shell...............................|ale-sh-shell|
|
shell...............................|ale-sh-shell|
|
||||||
shellcheck..........................|ale-sh-shellcheck|
|
shellcheck..........................|ale-sh-shellcheck|
|
||||||
|
spec..................................|ale-spec-options|
|
||||||
|
rpmlint.............................|ale-spec-rpmlint|
|
||||||
tex...................................|ale-tex-options|
|
tex...................................|ale-tex-options|
|
||||||
chktex..............................|ale-tex-chktex|
|
chktex..............................|ale-tex-chktex|
|
||||||
lacheck.............................|ale-tex-lacheck|
|
lacheck.............................|ale-tex-lacheck|
|
||||||
@ -151,6 +153,7 @@ The following languages and tools are supported.
|
|||||||
* Puppet: 'puppet', 'puppet-lint'
|
* Puppet: 'puppet', 'puppet-lint'
|
||||||
* Python: 'flake8', 'mypy', 'pylint'
|
* Python: 'flake8', 'mypy', 'pylint'
|
||||||
* reStructuredText: 'proselint'
|
* reStructuredText: 'proselint'
|
||||||
|
* RPM spec: 'spec'
|
||||||
* Rust: 'rustc' (see |ale-integration-rust|)
|
* Rust: 'rustc' (see |ale-integration-rust|)
|
||||||
* Ruby: 'rubocop'
|
* Ruby: 'rubocop'
|
||||||
* SASS: 'sasslint', 'stylelint'
|
* SASS: 'sasslint', 'stylelint'
|
||||||
|
29
test/handler/test_rpmlint_handler.vader
Normal file
29
test/handler/test_rpmlint_handler.vader
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
Execute(The rpmlint handler should parse error messages correctly):
|
||||||
|
runtime ale_linters/spec/rpmlint.vim
|
||||||
|
|
||||||
|
AssertEqual
|
||||||
|
\ [
|
||||||
|
\ {
|
||||||
|
\ 'bufnr': 42,
|
||||||
|
\ 'lnum': 23,
|
||||||
|
\ 'text': 'macro-in-comment %version',
|
||||||
|
\ 'type': 'W',
|
||||||
|
\ },
|
||||||
|
\ {
|
||||||
|
\ 'bufnr': 42,
|
||||||
|
\ 'lnum': 17,
|
||||||
|
\ 'text': 'hardcoded-library-path in %_prefix/lib/%name',
|
||||||
|
\ 'type': 'E',
|
||||||
|
\ },
|
||||||
|
\ {
|
||||||
|
\ 'bufnr': 42,
|
||||||
|
\ 'lnum': 1,
|
||||||
|
\ 'text': 'specfile-error warning: bogus date in %changelog: Mon Oct 1 2005 - Foo',
|
||||||
|
\ 'type': 'E',
|
||||||
|
\ },
|
||||||
|
\ ],
|
||||||
|
\ ale_linters#spec#rpmlint#Handle(42, [
|
||||||
|
\ 'cyrus-imapd.spec:23: W: macro-in-comment %version',
|
||||||
|
\ 'cyrus-imapd.spec:17: E: hardcoded-library-path in %_prefix/lib/%name',
|
||||||
|
\ 'apcupsd.spec: E: specfile-error warning: bogus date in %changelog: Mon Oct 1 2005 - Foo',
|
||||||
|
\ ])
|
Loading…
Reference in New Issue
Block a user