blob: fa125be52c1e85bbf1b1b59883f51e5943746502 [file] [log] [blame]
Bram Moolenaar071d4272004-06-13 20:20:40 +00001" Plugin to update the %changelog section of RPM spec files
2" Filename: spec.vim
Bram Moolenaar08589172014-03-08 18:38:28 +01003" Maintainer: Igor Gnatenko i.gnatenko.brain@gmail.com
4" Former Maintainer: Gustavo Niemeyer <niemeyer@conectiva.com> (until March 2014)
fundawange4015762024-09-10 21:43:05 +02005" Last Change: 2015 Jun 01
6" Update by Zdenek Dohnal, 2022 May 17
7" 2024 Sep 10 by Vim Project: add epoch support for spec changelog, #15537
Bram Moolenaar071d4272004-06-13 20:20:40 +00008
9if exists("b:did_ftplugin")
10 finish
11endif
12let b:did_ftplugin = 1
13
Bram Moolenaarb6b046b2011-12-30 13:11:27 +010014let s:cpo_save = &cpo
15set cpo&vim
16
Bram Moolenaar071d4272004-06-13 20:20:40 +000017if !exists("no_plugin_maps") && !exists("no_spec_maps")
18 if !hasmapto("<Plug>SpecChangelog")
19 map <buffer> <LocalLeader>c <Plug>SpecChangelog
20 endif
21endif
22
Bram Moolenaar113cb512021-11-07 20:27:04 +000023if !hasmapto("call <SID>SpecChangelog(\"\")<CR>")
24 noremap <buffer> <unique> <script> <Plug>SpecChangelog :call <SID>SpecChangelog("")<CR>
Bram Moolenaar2b8388b2015-02-28 13:11:45 +010025endif
Bram Moolenaar071d4272004-06-13 20:20:40 +000026
Bram Moolenaarf2571c62015-06-09 19:44:55 +020027if !exists("*s:GetRelVer")
28 function! s:GetRelVer()
29 if has('python')
30python << PYEND
31import sys, datetime, shutil, tempfile
32import vim
33
34try:
35 import rpm
36except ImportError:
37 pass
38else:
39 specfile = vim.current.buffer.name
40 if specfile:
Bram Moolenaar82af8712016-06-04 20:20:29 +020041 rpm.delMacro("dist")
Bram Moolenaarf2571c62015-06-09 19:44:55 +020042 spec = rpm.spec(specfile)
Bram Moolenaar82af8712016-06-04 20:20:29 +020043 headers = spec.sourceHeader
44 version = headers["Version"]
45 release = headers["Release"]
Bram Moolenaar2d8ed022022-05-21 13:08:16 +010046 vim.command("let ver = '" + version + "'")
47 vim.command("let rel = '" + release + "'")
Bram Moolenaarf2571c62015-06-09 19:44:55 +020048PYEND
49 endif
50 endfunction
51endif
52
Bram Moolenaar071d4272004-06-13 20:20:40 +000053if !exists("*s:SpecChangelog")
54 function s:SpecChangelog(format)
55 if strlen(a:format) == 0
56 if !exists("g:spec_chglog_format")
Bram Moolenaarf2571c62015-06-09 19:44:55 +020057 let email = input("Name <email address>: ")
Bram Moolenaar071d4272004-06-13 20:20:40 +000058 let g:spec_chglog_format = "%a %b %d %Y " . l:email
59 echo "\r"
60 endif
61 let format = g:spec_chglog_format
62 else
63 if !exists("g:spec_chglog_format")
64 let g:spec_chglog_format = a:format
65 endif
66 let format = a:format
67 endif
68 let line = 0
69 let name = ""
fundawange4015762024-09-10 21:43:05 +020070 let epoch = ""
Bram Moolenaar071d4272004-06-13 20:20:40 +000071 let ver = ""
72 let rel = ""
73 let nameline = -1
fundawange4015762024-09-10 21:43:05 +020074 let epochline = -1
Bram Moolenaar071d4272004-06-13 20:20:40 +000075 let verline = -1
76 let relline = -1
77 let chgline = -1
78 while (line <= line("$"))
79 let linestr = getline(line)
Bram Moolenaar4072ba52020-12-23 13:56:35 +010080 if name == "" && linestr =~? '^Name:'
Bram Moolenaar071d4272004-06-13 20:20:40 +000081 let nameline = line
82 let name = substitute(strpart(linestr,5), '^[ ]*\([^ ]\+\)[ ]*$','\1','')
fundawange4015762024-09-10 21:43:05 +020083 elseif epoch == "" && linestr =~? '^Epoch:'
84 let epochline = line
85 let epoch = substitute(strpart(linestr,6), '^[ ]*\([^ ]\+\)[ ]*$','\1','')
Bram Moolenaar4072ba52020-12-23 13:56:35 +010086 elseif ver == "" && linestr =~? '^Version:'
Bram Moolenaar071d4272004-06-13 20:20:40 +000087 let verline = line
88 let ver = substitute(strpart(linestr,8), '^[ ]*\([^ ]\+\)[ ]*$','\1','')
Bram Moolenaar4072ba52020-12-23 13:56:35 +010089 elseif rel == "" && linestr =~? '^Release:'
Bram Moolenaar071d4272004-06-13 20:20:40 +000090 let relline = line
91 let rel = substitute(strpart(linestr,8), '^[ ]*\([^ ]\+\)[ ]*$','\1','')
Bram Moolenaar4072ba52020-12-23 13:56:35 +010092 elseif linestr =~? '^%changelog'
Bram Moolenaar071d4272004-06-13 20:20:40 +000093 let chgline = line
94 execute line
95 break
96 endif
97 let line = line+1
98 endwhile
Bram Moolenaar4072ba52020-12-23 13:56:35 +010099 if nameline != -1 && verline != -1 && relline != -1
Bram Moolenaar071d4272004-06-13 20:20:40 +0000100 let include_release_info = exists("g:spec_chglog_release_info")
101 let name = s:ParseRpmVars(name, nameline)
fundawange4015762024-09-10 21:43:05 +0200102 let epoch = s:ParseRpmVars(epoch, epochline)
Bram Moolenaar071d4272004-06-13 20:20:40 +0000103 let ver = s:ParseRpmVars(ver, verline)
104 let rel = s:ParseRpmVars(rel, relline)
105 else
106 let include_release_info = 0
107 endif
Bram Moolenaarf2571c62015-06-09 19:44:55 +0200108
109 call s:GetRelVer()
110
Bram Moolenaar4072ba52020-12-23 13:56:35 +0100111 if chgline == -1
Bram Moolenaar071d4272004-06-13 20:20:40 +0000112 let option = confirm("Can't find %changelog. Create one? ","&End of file\n&Here\n&Cancel",3)
Bram Moolenaar4072ba52020-12-23 13:56:35 +0100113 if option == 1
Bram Moolenaar071d4272004-06-13 20:20:40 +0000114 call append(line("$"),"")
115 call append(line("$"),"%changelog")
116 execute line("$")
117 let chgline = line(".")
Bram Moolenaar4072ba52020-12-23 13:56:35 +0100118 elseif option == 2
Bram Moolenaar071d4272004-06-13 20:20:40 +0000119 call append(line("."),"%changelog")
120 normal j
Bram Moolenaar4072ba52020-12-23 13:56:35 +0100121 let chgline = line(".")
Bram Moolenaar071d4272004-06-13 20:20:40 +0000122 endif
123 endif
Bram Moolenaar4072ba52020-12-23 13:56:35 +0100124 if chgline != -1
Bram Moolenaar82af8712016-06-04 20:20:29 +0200125 let tmptime = v:lc_time
126 language time C
fundawange4015762024-09-10 21:43:05 +0200127 if strlen(epoch)
128 let ver = epoch.":".ver
129 endif
Bram Moolenaarf2571c62015-06-09 19:44:55 +0200130 let parsed_format = "* ".strftime(format)." - ".ver."-".rel
Bram Moolenaar82af8712016-06-04 20:20:29 +0200131 execute "language time" tmptime
Bram Moolenaar071d4272004-06-13 20:20:40 +0000132 let release_info = "+ ".name."-".ver."-".rel
133 let wrong_format = 0
134 let wrong_release = 0
135 let insert_line = 0
Bram Moolenaar4072ba52020-12-23 13:56:35 +0100136 if getline(chgline+1) != parsed_format
Bram Moolenaar071d4272004-06-13 20:20:40 +0000137 let wrong_format = 1
138 endif
Bram Moolenaar4072ba52020-12-23 13:56:35 +0100139 if include_release_info && getline(chgline+2) != release_info
Bram Moolenaar071d4272004-06-13 20:20:40 +0000140 let wrong_release = 1
141 endif
Bram Moolenaar4072ba52020-12-23 13:56:35 +0100142 if wrong_format || wrong_release
143 if include_release_info && !wrong_release && !exists("g:spec_chglog_never_increase_release")
Bram Moolenaar071d4272004-06-13 20:20:40 +0000144 let option = confirm("Increase release? ","&Yes\n&No",1)
Bram Moolenaar4072ba52020-12-23 13:56:35 +0100145 if option == 1
Bram Moolenaar071d4272004-06-13 20:20:40 +0000146 execute relline
147 normal 
148 let rel = substitute(strpart(getline(relline),8), '^[ ]*\([^ ]\+\)[ ]*$','\1','')
149 let release_info = "+ ".name."-".ver."-".rel
150 endif
151 endif
152 let n = 0
153 call append(chgline+n, parsed_format)
154 if include_release_info
155 let n = n + 1
156 call append(chgline+n, release_info)
157 endif
158 let n = n + 1
159 call append(chgline+n,"- ")
160 let n = n + 1
161 call append(chgline+n,"")
162 let insert_line = chgline+n
163 else
164 let line = chgline
165 if !exists("g:spec_chglog_prepend")
166 while !(getline(line+2) =~ '^\( *\|\*.*\)$')
167 let line = line+1
168 endwhile
169 endif
170 call append(line+1,"- ")
171 let insert_line = line+2
172 endif
173 execute insert_line
174 startinsert!
175 endif
176 endfunction
177endif
178
179if !exists("*s:ParseRpmVars")
180 function s:ParseRpmVars(str, strline)
181 let end = -1
182 let ret = ""
183 while (1)
184 let start = match(a:str, "\%{", end+1)
Bram Moolenaar4072ba52020-12-23 13:56:35 +0100185 if start == -1
Bram Moolenaar071d4272004-06-13 20:20:40 +0000186 let ret = ret . strpart(a:str, end+1)
187 break
188 endif
189 let ret = ret . strpart(a:str, end+1, start-(end+1))
190 let end = match(a:str, "}", start)
Bram Moolenaar4072ba52020-12-23 13:56:35 +0100191 if end == -1
Bram Moolenaar071d4272004-06-13 20:20:40 +0000192 let ret = ret . strpart(a:str, start)
193 break
194 endif
195 let varname = strpart(a:str, start+2, end-(start+2))
196 execute a:strline
Bram Moolenaar1c6737b2020-09-07 22:18:52 +0200197 let definestr = "^[ \t]*%\\(define\\|global\\)[ \t]\\+".varname."[ \t]\\+\\(.*\\)$"
Bram Moolenaar071d4272004-06-13 20:20:40 +0000198 let linenum = search(definestr, "bW")
Bram Moolenaar4072ba52020-12-23 13:56:35 +0100199 if linenum != 0
Bram Moolenaar1c6737b2020-09-07 22:18:52 +0200200 let ret = ret . substitute(getline(linenum), definestr, "\\2", "")
Bram Moolenaar071d4272004-06-13 20:20:40 +0000201 endif
202 endwhile
203 return ret
204 endfunction
205endif
206
207" The following lines, along with the macros/matchit.vim plugin,
208" make it easy to navigate the different sections of a spec file
209" with the % key (thanks to Max Ischenko).
210
211let b:match_ignorecase = 0
212let b:match_words =
Bram Moolenaar82af8712016-06-04 20:20:29 +0200213 \ '^Name:^%description:^%clean:^%(?:auto)?setup:^%build:^%install:^%files:' .
Bram Moolenaar071d4272004-06-13 20:20:40 +0000214 \ '^%package:^%preun:^%postun:^%changelog'
215
Bram Moolenaarb6b046b2011-12-30 13:11:27 +0100216let &cpo = s:cpo_save
217unlet s:cpo_save
218
Bram Moolenaar84f72352012-03-11 15:57:40 +0100219let b:undo_ftplugin = "unlet! b:match_ignorecase b:match_words"