2017-04-19 22:40:58 +00:00
|
|
|
" 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.
|
|
|
|
|
2018-08-02 22:44:12 +00:00
|
|
|
call ale#Set('spec_rpmlint_executable', 'rpmlint')
|
|
|
|
call ale#Set('spec_rpmlint_options', '')
|
2017-04-19 22:40:58 +00:00
|
|
|
|
2021-07-04 12:19:00 +00:00
|
|
|
function! ale_linters#spec#rpmlint#GetCommand(buffer, version) abort
|
|
|
|
if ale#semver#GTE(a:version, [2, 0, 0])
|
|
|
|
" The -o/--option flag was removed in version 2.0.0
|
|
|
|
let l:version_dependent_args = ''
|
|
|
|
else
|
|
|
|
let l:version_dependent_args = ' -o "NetworkEnabled False"'
|
|
|
|
endif
|
|
|
|
|
2018-08-02 22:44:12 +00:00
|
|
|
return '%e'
|
|
|
|
\ . ale#Pad(ale#Var(a:buffer, 'spec_rpmlint_options'))
|
2017-04-19 22:40:58 +00:00
|
|
|
\ . ' -v'
|
2021-07-04 12:19:00 +00:00
|
|
|
\ . l:version_dependent_args
|
2017-04-19 22:40:58 +00:00
|
|
|
\ . ' %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',
|
2019-02-22 18:05:04 +00:00
|
|
|
\ 'executable': {b -> ale#Var(b, 'spec_rpmlint_executable')},
|
2021-07-04 12:19:00 +00:00
|
|
|
\ 'command': {buffer -> ale#semver#RunWithVersionCheck(
|
|
|
|
\ buffer,
|
|
|
|
\ ale#Var(buffer, 'spec_rpmlint_executable'),
|
|
|
|
\ '%e --version',
|
|
|
|
\ function('ale_linters#spec#rpmlint#GetCommand'),
|
|
|
|
\ )},
|
2017-04-19 22:40:58 +00:00
|
|
|
\ 'callback': 'ale_linters#spec#rpmlint#Handle',
|
|
|
|
\})
|