qi_libs.rb helper, force git version tag when tag requested
[software/sisu] / setup / qi_libs.rb
1 require_relative 'sisu_version'
2 module Project_details
3 include SiSUversion
4 def self.name
5 'SiSU'
6 end
7 def self.summary
8 'documents - structuring, publishing in multiple formats & search'
9 end
10 def self.description
11 'documents - structuring, publishing in multiple formats & search'
12 end
13 def self.homepage
14 'http://www.sisudoc.org'
15 end
16 def self.thor
17 "ruby-thor files for the installation/setup of #{name}"
18 end
19 def self.platform_notice
20 "[#{name} is for Linux/Unix Platforms]"
21 end
22 def self.env
23 RbConfig::CONFIG
24 end
25 def self.host
26 env['host']
27 end
28 def self.dir
29 def self.proj
30 Project_details.name.downcase
31 end
32 def self.arch
33 env['archdir']
34 end
35 def self.sitearch
36 env['sitearchdir']
37 end
38 def self.bin
39 env['bindir']
40 end
41 def self.lib
42 env['sitelibdir']
43 end
44 def self.data
45 env['datadir']
46 end
47 def self.share
48 "#{env['datadir']}/sisu"
49 end
50 def self.conf
51 env['sysconfdir']
52 end
53 def self.man
54 env['mandir']
55 end
56 def self.vim
57 "#{env['datadir']}/sisu/vim"
58 end
59 def self.out
60 "#{env['localstatedir']}/#{proj}"
61 end
62 def self.rubylib
63 env['LIBRUBYARG_SHARED']
64 end
65 def self.pwd
66 Dir.pwd #ENV['PWD']
67 end
68 self
69 end
70 def self.version
71 stamp={}
72 v="#{dir.pwd}/data/sisu/version.yml"
73 if File.exist?(v)
74 stamp=YAML::load(File::open(v))
75 stamp[:version]
76 else ''
77 end
78 end
79 def self.system_info
80 ##{Project_details.platform_notice}
81 puts <<-WOK
82 Host
83 host: #{Project_details.host}
84 arch: #{Project_details.dir.arch}
85 sitearch: #{Project_details.dir.sitearch}
86 Directories for installation
87 bin: #{Project_details.dir.bin}
88 lib (site-ruby): #{Project_details.dir.lib}/#{Project_details.dir.proj}/v*
89 conf [etc]: #{Project_details.dir.conf}/#{Project_details.dir.proj}
90 data (odf, shared images): #{Project_details.dir.share}
91 vim (vim syntax, highlighting, ftplugin): #{Project_details.dir.data}/sisu/vim
92 data (README, version_manifest): #{Project_details.dir.data}/doc/#{Project_details.dir.proj}
93 man (manual pages): #{Project_details.dir.man}
94 output: #{Project_details.dir.out}
95 processing: #{Project_details.dir.out}/processing
96 www: #{Project_details.dir.out}/www
97 rubylib: #{Project_details.dir.rubylib}
98
99 WOK
100 end
101 def self.gem_env
102 system("gem env")
103 end
104 end
105 module Utils
106 def self.answer?(ask)
107 resp='redo'
108 print ask + " ['yes', 'no' or 'quit']: "
109 resp=File.new('/dev/tty').gets.strip #resp=gets.strip
110 if resp == 'yes' then true
111 elsif resp == 'no' then false
112 elsif resp =~/^quit|exit$/ then exit
113 else puts "[please type: 'yes', 'no' or 'quit']"
114 answer?(ask)
115 end
116 end
117 def self.default_notice # local help not implemented description incorrect
118 ans= %{#{Project_details.thor}
119 Information on alternative actions is available using:
120 [if ruby-thor is installed:]
121 "#{$called_as} help")
122 Default action selected - "install #{Project_details.name}" proceed? }
123 resp=answer?(ans)
124 exit unless resp
125 end
126 def self.chmod_file(place)
127 if place =~/\/bin/; File.chmod(0755,place)
128 else File.chmod(0644,place)
129 end
130 end
131 def self.chmod_util(place)
132 if place =~/\/bin/; chmod(0755,place)
133 else chmod(0644,place)
134 end
135 end
136 def self.system_date
137 `date "+%Y-%m-%d"`.strip
138 end
139 def self.system_date_stamp
140 `date "+%Yw%W/%u"`.strip
141 end
142 def self.program_found?(prog)
143 found=`which #{prog}` #`whereis #{make}`
144 (found =~/bin\/#{prog}\b/) ? :true : :false
145 end
146 end
147 module Install
148 #%% using a directory and its mapping
149 def self.setup_find_create(dir_get,dir_put,exclude_files=['\*'],act) #primary,
150 begin
151 Find.find("#{Project_details.dir.pwd}/#{dir_get}") do |f|
152 stub=f.scan(/#{Project_details.dir.pwd}\/#{dir_get}\/(\S+)/).join
153 place="#{dir_put}/#{stub}"
154 action=case
155 when File.file?(f)
156 unless f =~/#{exclude_files.join("|")}/
157 unless act==:dryrun
158 cp(f,place)
159 Utils.chmod_file(place)
160 end
161 "-> #{dir_put}/"
162 end
163 when File.directory?(f)
164 if not FileTest.directory?(place) \
165 and not act==:dryrun
166 FileUtils.mkpath(place)
167 end
168 "./#{dir_get}/"
169 else '?'
170 end
171 puts "#{action}#{stub}"
172 end
173 rescue
174 puts "\n\n[ are you root? required for install ]"
175 end
176 end
177 def self.setup_find_cp_r(dir_get,dir_put,act) #secondary, using recursive copy
178 begin
179 Find.find("#{Project_details.dir.pwd}/#{dir_get}") do |f|
180 stub=f.scan(/#{Project_details.dir.pwd}\/#{dir_get}\/(\S+)/).join
181 place="#{dir_put}/#{stub}"
182 case
183 when File.file?(f)
184 unless act==:dryrun
185 cp_r(f,place)
186 Utils.chmod_util(place)
187 else
188 puts "--> #{place}"
189 end
190 when File.directory?(f)
191 unless FileTest.directory?(place)
192 unless act==:dryrun
193 mkdir(place)
194 else
195 puts "mkdir -p #{place}"
196 end
197 end
198 end
199 end
200 rescue
201 puts "\n\n[ are you root? required for install ]"
202 end
203 end
204 end
205 module Version_info
206 def self.contents(vi,rel=:release)
207 release=rel ==:pre_release \
208 ? '_pre_rel'
209 : ''
210 <<-WOK
211 ---
212 :project: #{vi[:project]}
213 :version: #{vi[:version]}#{release}
214 :date_stamp: #{vi[:date_stamp]}
215 :date: "#{vi[:date]}"
216 WOK
217 end
218 def self.git_version_extract
219 if FileTest.file?('/usr/bin/git')
220 x=`git describe --long --tags 2>&1`.strip.
221 gsub(/^[a-z_-]*([0-9.]+)/,'\1').
222 gsub(/([^-]*-g)/,'r\1').
223 gsub(/-/,'.')
224 x=(x=~/^[0-9]+\.[0-9]+\.[0-9]+\.r[0-9]+\.g[0-9a-f]{7}/) \
225 ? x
226 : nil
227 else nil
228 end
229 end
230 def self.version_number(vi)
231 vi[:version]
232 end
233 def self.version_number_use(vi)
234 (git_version_extract.nil?) \
235 ? (vi[:version])
236 : git_version_extract
237 end
238 def self.version_number_info(vi)
239 (Version_info.version_number_use(vi) != vi[:version_number]) \
240 ? (%{#{vi[:version_number]} from git #{Version_info.version_number_use(vi)}})
241 : vi[:version_number]
242 end
243 def self.version_number_info_stable
244 vi=Version_info::Current.setting_stable
245 (Version_info.version_number_use(vi) != vi[:version_number]) \
246 ? (%{#{vi[:version_number]} from git #{Version_info.version_number_use(vi)}})
247 : vi[:version_number]
248 end
249 module Current
250 def self.yml_file_path
251 'data/sisu/version.yml'
252 end
253 def self.settings(file)
254 v="#{Dir.pwd}/#{file}"
255 if File.exist?(v)
256 YAML::load(File::open(v))
257 else ''
258 end
259 end
260 def self.changelog_file_stable
261 'data/doc/sisu/CHANGELOG_v7'
262 end
263 def self.file_stable
264 yml_file_path
265 end
266 def self.setting_stable
267 hsh=settings(file_stable)
268 hsh[:version_number]=/([0-9]+\.[0-9]+\.[0-9]+)/.
269 match(hsh[:version])[1]
270 hsh
271 end
272 def self.version_number
273 Version_info::Current.setting_stable[:version_number]
274 end
275 def self.content_stable
276 Version_info.contents(setting_stable)
277 end
278 end
279 module Next
280 def self.settings(v)
281 {
282 project: "#{Project_details.name}",
283 version: "#{v}",
284 date: "#{Utils.system_date}",
285 date_stamp: "#{Utils.system_date_stamp}",
286 }
287 end
288 def self.setting_stable
289 settings(SiSU_version)
290 end
291 def self.content_stable(rel)
292 Version_info.contents(setting_stable,rel)
293 end
294 end
295 module Update
296 def self.version_number(vi)
297 /([0-9]+\.[0-9]+\.[0-9]+)/.match(vi[:version])[1]
298 end
299 def self.version_number_stable
300 vi=Version_info::Current.setting_stable
301 /([0-9]+\.[0-9]+\.[0-9]+)/.match(vi[:version])[1]
302 end
303 def self.version_info_update_commit(filename,vi_hash_current,vi_content_current,vi_hash_next,vi_content_next)
304 ans=%{update #{Project_details.name.downcase} version info replacing:
305 #{vi_hash_current.sort}
306 with:
307 #{vi_hash_next.sort}
308
309 #{vi_content_current}
310 becoming:
311 #{vi_content_next}
312 proceed? }
313 resp=Utils.answer?(ans)
314 if resp
315 fn="#{Dir.pwd}/#{filename}"
316 if File.writable?("#{Dir.pwd}/.")
317 file_version=File.new(fn,'w+')
318 file_version << vi_content_next
319 file_version.close
320 else
321 puts %{*WARN* is the file or directory writable? could not create #{filename}}
322 end
323 end
324 end
325 def self.update_documentation
326 fn="#{Dir.pwd}/data/doc/sisu/markup-samples/manual/_sisu/sisu_document_make"
327 if File.file?(fn) \
328 and File.writable?(fn)
329 ver_no_stable=Version_info::Current.setting_stable[:version_number]
330 debian_stable='Jessie'
331 debian_testing='Stretch'
332 sisu_doc_make = IO.readlines(fn)
333 sisu_doc_make_next=sisu_doc_make.each.map do |line|
334 line=line.gsub(/(\/$\{sisu_stable\}\/,)'[0-9]+\.[0-9]+\.[0-9]+'/,"\\1'#{ver_no_stable}'").
335 gsub(/(\/$\{debian_stable\}\/,)'\*\{[A-Z][a-z]+\}\*'/,
336 "\\1'*{#{debian_stable}}*'").
337 gsub(/(\/$\{debian_testing\}\/,)'\*\{[A-Z][a-z]+\}\*'/,
338 "\\1'*{#{debian_testing}}*'")
339 line
340 end
341 if sisu_doc_make_next.length == sisu_doc_make.length
342 sisu_doc_make_file=File.new(fn,'w+')
343 sisu_doc_make_next.flatten.each do |line|
344 sisu_doc_make_file << line
345 end
346 sisu_doc_make_file.close
347 else puts "expected changelog arrays to have same length, in: #{pkgbuild.length}, out: #{pkgbuild_next.length}"
348 end
349 end
350 end
351 def self.update_stable(rel=:release)
352 version_info_update_commit(
353 Version_info::Current.file_stable,
354 Version_info::Current.setting_stable,
355 Version_info::Current.content_stable,
356 Version_info::Next.setting_stable,
357 Version_info::Next.content_stable(rel),
358 )
359 end
360 def self.update_pkgbuild_stable(rel=:release)
361 vn=version_number_stable
362 ans=%{update PKGBUILD version info:
363 pkgver=#{vn}
364
365 proceed? }
366 resp=Utils.answer?(ans)
367 if resp
368 filename='PKGBUILD_tar_xz'
369 fn="#{Dir.pwd}/setup/#{filename}"
370 if File.writable?(fn)
371 pkgbuild = IO.readlines(fn)
372 pkgbuild_next=pkgbuild.each.map do |line|
373 if line =~/^\s*pkgver=/
374 line=line.gsub(/^\s*(pkgver=)[0-9.]+/,"\\1#{vn}")
375 else line
376 end
377 end
378 if pkgbuild.length == pkgbuild_next.length
379 pkgbuild_file=File.new(fn,'w+')
380 pkgbuild_next.flatten.each do |line|
381 pkgbuild_file << line
382 end
383 pkgbuild_file.close
384 else puts "expected changelog arrays to have same length, in: #{pkgbuild.length}, out: #{pkgbuild_next.length}"
385 end
386 end
387 end
388 end
389 def self.changelog_header(vi)
390 vn=version_number(vi)
391 <<-WOK
392 * sisu_#{vn}.orig.tar.xz (#{vi[:date]}:#{vi[:date_stamp].gsub(/20\d\dw/,'')})
393 http://git.sisudoc.org/gitweb/?p=code/sisu.git;a=log;h=refs/tags/sisu_#{vn}
394 WOK
395 end
396 def self.changelog_header_release(filename,ch,vi)
397 ans=%{update #{Project_details.name.downcase} changelog header, open version:
398
399 #{ch}
400 proceed? }
401 resp=Utils.answer?(ans)
402 if resp
403 fn="#{Dir.pwd}/#{filename}"
404 if File.writable?(fn)
405 changelog_arr_current = IO.readlines(fn)
406 changelog_arr_next=changelog_arr_current.each.map do |line|
407 if line =~/^\*\s+sisu_[0-9]+\.[0-9]+\.[0-9]+(?:_pre_rel)?\.orig\.tar\.xz \(Open commit window: [0-9]{4}-[0-9]{2}-[0-9]{2}; Pre-Release\)$/
408 "* sisu_#{vi[:version]}.orig.tar.xz " \
409 + "(#{vi[:date]}:#{vi[:date_stamp].gsub(/20\d\dw/,'')})\n"
410 else line
411 end
412 end
413 if changelog_arr_current.length == changelog_arr_next.length
414 changelog_file=File.new(fn,'w+')
415 changelog_arr_next.flatten.each do |line|
416 changelog_file << line
417 end
418 changelog_file.close
419 else puts "expected changelog arrays to have same length, in: #{changelog_arr_current.length}, out: #{changelog_arr_next.length}"
420 end
421 else
422 puts %{*WARN* is the file or directory writable? could not create #{filename}}
423 end
424 end
425 end
426 def self.changelog_header_stable_filename
427 Version_info::Current.changelog_file_stable
428 end
429 def self.changelog_header_stable
430 ch=changelog_header(Version_info::Current.setting_stable)
431 changelog_header_release(
432 changelog_header_stable_filename,
433 ch,
434 Version_info::Current.setting_stable
435 )
436 end
437 def self.changelog_header_pre_release(vi)
438 vn=version_number(vi)
439 <<-WOK
440 * sisu_#{vn}.orig.tar.xz (Open commit window: #{vi[:date]}; Pre-Release)
441 http://git.sisudoc.org/gitweb/?p=code/sisu.git;a=log;h=refs/tags/sisu_#{vn}
442 WOK
443 end
444 def self.changelog_header_pre_release_write(filename,ch)
445 ans=%{update #{Project_details.name.downcase} changelog header, open version:
446
447 #{ch}
448 proceed? }
449 resp=Utils.answer?(ans)
450 if resp
451 fn="#{Dir.pwd}/#{filename}"
452 if File.writable?(fn)
453 changelog_arr_current = IO.readlines(fn)
454 changelog_arr_next=changelog_arr_current.each.map do |line|
455 if line =~/^--- HEAD ---$/
456 line << ("\n" + ch)
457 else line
458 end
459 end
460 if changelog_arr_current.length == changelog_arr_next.length
461 changelog_file=File.new(fn,'w+')
462 changelog_arr_next.flatten.each do |line|
463 changelog_file << line
464 end
465 changelog_file.close
466 else puts "expected changelog arrays to have same length, in: #{changelog_arr_current.length}, out: #{changelog_arr_next.length}"
467 end
468 else
469 puts %{*WARN* is the file or directory writable? could not create #{filename}}
470 end
471 end
472 end
473 def self.changelog_header_stable_pre_release
474 ch=changelog_header_pre_release(Version_info::Current.setting_stable)
475 changelog_header_pre_release_write(changelog_header_stable_filename,ch)
476 end
477 def self.commit_changelog(rel=:release,msg)
478 system(%{
479 git commit -a -m"#{msg}"
480 git commit --amend
481 })
482 end
483 def self.tag_upstream
484 system(%{
485 git tag -af sisu_#{SiSU_version} -m"SiSU #{SiSU_version}"
486 })
487 end
488 def self.changelog_header_commit(rel=:release)
489 msg=(rel == :pre_release) \
490 ? "version & changelog, open commit window"
491 : "version & changelog, tag for release"
492 ans=%{commit #{msg}:\n\nproceed? }
493 resp=Utils.answer?(ans)
494 if resp
495 commit_changelog(rel,msg)
496 end
497 end
498 def self.changelog_header_commit_tag_upstream(rel=:release)
499 msg=(rel == :pre_release) \
500 ? "version & changelog, open commit window"
501 : "version & changelog, tag for release"
502 ans=%{commit #{msg}:\n\nproceed? }
503 resp=Utils.answer?(ans)
504 if resp
505 commit_changelog(rel,msg)
506 tag_upstream
507 end
508 end
509 end
510 self
511 end
512 module GitExtractTaggedVersionBuild
513 def upstream
514 system(%{ git checkout upstream })
515 end
516 def self.git_tagged_versions(tag=nil)
517 if tag
518 v=if tag =~/sisu_[0-9](?:\.[0-9]){0,2}$/ then tag
519 elsif tag =~/^[0-9](?:\.[0-9]){0,2}$/ then 'sisu_' + tag
520 else 'sisu_'
521 end
522 system(%{ git tag -l | ag --nocolor '^#{v}' })
523 end
524 end
525 def self.git_checkout_and_build_and_install_version(tag,options)
526 begin
527 ver=if tag =~/sisu_[0-9]\.[0-9]+\.[0-9]+/ then tag
528 elsif tag =~/^[0-9]\.[0-9]+\.[0-9]+/ then 'sisu_' + tag
529 else branch
530 end
531 create=options[:create] ? '--create ' : ''
532 build=options[:build] ? '--build ' : ''
533 install=options[:install] ? '--install ' : ''
534 commands =<<-WOK
535 git checkout #{ver} &&
536 #{$called_as} gem #{ver} #{create}#{build}#{install};
537 WOK
538 puts commands
539 begin
540 system(commands)
541 rescue
542 end
543 rescue
544 ensure
545 system(%{
546 git checkout upstream
547 })
548 end
549 end
550 end
551 module Gemspecs
552 def self.info(vi)
553 puts <<-WOK
554 --
555 name: #{vi[:project].downcase}
556 version: #{vi[:version_number]}
557 date: #{vi[:date]}
558 summary: #{vi[:project]}
559 WOK
560 end
561 def self.contents(vi)
562 <<-WOK
563 Gem::Specification.new do |s|
564 s.name = '#{vi[:project].downcase}'
565 s.version = '#{vi[:version_number]}'
566 s.date = '#{vi[:date]}'
567 s.summary = '#{Project_details.summary} (linux calls)'
568 s.description = '#{Project_details.description} [#{Version_info.version_number_info(vi)}] (linux calls & without external dependencies)'
569 s.homepage = '#{Project_details.homepage}'
570 s.authors = ["Ralph Amissah"]
571 s.email = 'ralph.amissah@gmail.com'
572 s.license = 'GPL3'
573 s.files = Dir['lib/#{Project_details.name.downcase}.rb'] +
574 Dir['lib/#{Project_details.name.downcase}/*.rb'] +
575 Dir['data/#{Project_details.name.downcase}/version.yml'] +
576 Dir['data/#{Project_details.name.downcase}/image/*'] +
577 Dir['bin/#{Project_details.name.downcase}gem'] +
578 Dir['bin/#{Project_details.name.downcase}']
579 s.executables << '#{Project_details.name.downcase}gem' << '#{Project_details.name.downcase}'
580 s.has_rdoc = false
581 end
582 WOK
583 end
584 def self.contents_git(vi)
585 <<-WOK
586 Gem::Specification.new do |s|
587 s.name = '#{vi[:project].downcase}'
588 s.version = '#{Version_info.version_number_use(vi)}'
589 s.date = '#{vi[:date]}'
590 s.summary = '#{Project_details.summary} (linux calls)'
591 s.description = '#{Project_details.description} [#{Version_info.version_number_info(vi)}] (linux calls & without external dependencies)'
592 s.homepage = '#{Project_details.homepage}'
593 s.authors = ["Ralph Amissah"]
594 s.email = 'ralph.amissah@gmail.com'
595 s.license = 'GPL3'
596 s.files = `git ls-files -z lib`.split("\x0") +
597 Dir['data/#{Project_details.name.downcase}/version.yml'] +
598 Dir['data/#{Project_details.name.downcase}/image/*'] +
599 Dir['bin/#{Project_details.name.downcase}gem'] +
600 Dir['bin/#{Project_details.name.downcase}']
601 s.executables << '#{Project_details.name.downcase}gem' << '#{Project_details.name.downcase}'
602 s.has_rdoc = false
603 end
604 WOK
605 end
606 def self.create(filename,gemspec)
607 fn="#{Dir.pwd}/#{filename}.gemspec"
608 if File.writable?("#{Dir.pwd}/.")
609 file_sisu_gemspec=File.new(fn,'w+')
610 file_sisu_gemspec << gemspec
611 file_sisu_gemspec.close
612 else
613 puts %{*WARN* is the file or directory writable? could not create #{filename}}
614 end
615 end
616 def self.build(fn)
617 system(%{ gem build #{fn}.gemspec })
618 end
619 def self.install(vn)
620 system(%{
621 sudo gem install --local --no-document --verbose sisu-#{vn}.gem
622 })
623 end
624 module Current
625 def self.filename
626 Project_details.name.downcase
627 end
628 def self.filename_stable
629 Project_details.name.downcase \
630 + '-' \
631 + Version_info::Current.setting_stable[:version_number]
632 end
633 def self.info_stable
634 Gemspecs.info(Version_info::Current.setting_stable)
635 end
636 def self.current_stable
637 Gemspecs.contents(
638 Version_info::Current.setting_stable,
639 )
640 end
641 def self.current_git_version
642 Gemspecs.contents_git(
643 Version_info::Current.setting_stable,
644 )
645 end
646 def self.create_stable(version=:version_standard)
647 (version==:version_git) \
648 ? (Gemspecs.create(filename,current_git_version))
649 : (Gemspecs.create(filename,current_stable))
650 end
651 def self.build_stable
652 Gemspecs.build(filename)
653 end
654 def self.install_stable(version=:version_standard)
655 vi=Version_info::Current.setting_stable
656 vn=((version==:version_git) \
657 && (Version_info.version_number_use(vi) != vi[:version_number])) \
658 ? (Version_info.version_number_use(vi))
659 : (vi[:version_number])
660 Gemspecs.install(vn)
661 end
662 end
663 end
664 module Package
665 def self.sequence
666 puts <<-WOK
667 --open-version # update package version
668 --version-and-tag-for-release # git tags upstream version
669 # not included:
670 # --merge # git merge upstream tag into debian/sid
671 # --dch # dch create and edit
672 # --dch-commit # dch commit
673 # --build # git-buildpackage
674 # --git_push # git push changes
675 # --dput # dput package
676 # --reprepro_update # reprepro update
677 # --reprepro_push # reprepro rsync changes
678 WOK
679 end
680 end
681 __END__