xezat 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +14 -0
  3. data/.gitmodules +3 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE.txt +22 -0
  6. data/README.md +207 -0
  7. data/Rakefile +2 -0
  8. data/bin/xezat +14 -0
  9. data/lib/xezat.rb +6 -0
  10. data/lib/xezat/command/bump.rb +174 -0
  11. data/lib/xezat/command/create.rb +105 -0
  12. data/lib/xezat/command/debug.rb +30 -0
  13. data/lib/xezat/command/doctor.rb +45 -0
  14. data/lib/xezat/command/generate.rb +50 -0
  15. data/lib/xezat/command/validate.rb +43 -0
  16. data/lib/xezat/commands.rb +32 -0
  17. data/lib/xezat/cygchangelog.rb +53 -0
  18. data/lib/xezat/cygclasses.rb +33 -0
  19. data/lib/xezat/detector/autoconf.rb +16 -0
  20. data/lib/xezat/detector/automake.rb +16 -0
  21. data/lib/xezat/detector/boost.m4.rb +20 -0
  22. data/lib/xezat/detector/cmake.rb +16 -0
  23. data/lib/xezat/detector/gengetopt.rb +16 -0
  24. data/lib/xezat/detector/libtool.rb +16 -0
  25. data/lib/xezat/detector/make.rb +19 -0
  26. data/lib/xezat/detectors.rb +36 -0
  27. data/lib/xezat/main.rb +13 -0
  28. data/lib/xezat/packages.rb +21 -0
  29. data/lib/xezat/refine/linguist/file_blob.rb +14 -0
  30. data/lib/xezat/validator/m4.rb +30 -0
  31. data/lib/xezat/validator/pkgconfig.rb +23 -0
  32. data/lib/xezat/validators.rb +38 -0
  33. data/lib/xezat/variables.rb +48 -0
  34. data/lib/xezat/version.rb +3 -0
  35. data/share/xezat/compilers.json +39 -0
  36. data/share/xezat/invoke_cygport_dep.sh +5 -0
  37. data/share/xezat/repository/bitbucket.json +5 -0
  38. data/share/xezat/repository/github.json +5 -0
  39. data/share/xezat/repository/google.json +7 -0
  40. data/share/xezat/repository/sourceforge.json +6 -0
  41. data/share/xezat/show_cygport_description.sh +8 -0
  42. data/share/xezat/show_cygport_variable.sh +30 -0
  43. data/share/xezat/template/README.erb +60 -0
  44. data/share/xezat/template/cygport.erb +19 -0
  45. data/share/xezat/template/pkgconfig.erb +10 -0
  46. data/share/xezat/template/setup.erb +17 -0
  47. data/test/test.rb +18 -0
  48. data/test/xezat/command/fixture/doctor/a.lst.gz +0 -0
  49. data/test/xezat/command/fixture/doctor/b1.lst.gz +0 -0
  50. data/test/xezat/command/fixture/doctor/b2.lst.gz +0 -0
  51. data/test/xezat/command/test_create.rb +47 -0
  52. data/test/xezat/command/test_doctor.rb +16 -0
  53. data/test/xezat/detector/fixture/autoconf/no/configure.scan +1 -0
  54. data/test/xezat/detector/fixture/autoconf/yes_root/configure.ac +1 -0
  55. data/test/xezat/detector/fixture/autoconf/yes_subdir/subdir/configure.ac +1 -0
  56. data/test/xezat/detector/fixture/automake/no/Makefile.in +1 -0
  57. data/test/xezat/detector/fixture/automake/yes_root/Makefile.am +1 -0
  58. data/test/xezat/detector/fixture/automake/yes_subdir/subdir/Makefile.am +1 -0
  59. data/test/xezat/detector/fixture/boost.m4/no/configure.ac +1 -0
  60. data/test/xezat/detector/fixture/boost.m4/yes/configure.ac +1 -0
  61. data/test/xezat/detector/fixture/cmake/no/CMakeList.txt +1 -0
  62. data/test/xezat/detector/fixture/cmake/yes_root/CMakeLists.txt +1 -0
  63. data/test/xezat/detector/fixture/cmake/yes_subdir/subdir/CMakeLists.txt +1 -0
  64. data/test/xezat/detector/fixture/gengetopt/no/xezat.log +1 -0
  65. data/test/xezat/detector/fixture/gengetopt/yes_root/xezat.ggo +1 -0
  66. data/test/xezat/detector/fixture/gengetopt/yes_subdir/subdir/xezat.ggo +1 -0
  67. data/test/xezat/detector/test_autoconf.rb +23 -0
  68. data/test/xezat/detector/test_automake.rb +23 -0
  69. data/test/xezat/detector/test_boost.m4.rb +19 -0
  70. data/test/xezat/detector/test_cmake.rb +23 -0
  71. data/test/xezat/detector/test_gengetopt.rb +23 -0
  72. data/test/xezat/test_cygchangelog.rb +25 -0
  73. data/test/xezat/test_cygclasses.rb +31 -0
  74. data/test/xezat/test_variables.rb +15 -0
  75. data/test/xezat/validator/fixture/m4/no/usr/share/aclocal/.gitkeep +0 -0
  76. data/test/xezat/validator/fixture/m4/skip/usr/share/aclocal/.gitkeep +0 -0
  77. data/test/xezat/validator/fixture/m4/yes/usr/share/aclocal/test.m4 +1 -0
  78. data/test/xezat/validator/test_m4.rb +23 -0
  79. data/xezat.gemspec +28 -0
  80. metadata +239 -0
@@ -0,0 +1,105 @@
1
+ require 'erb'
2
+ require 'facets/file/atomic_write'
3
+ require 'json'
4
+ require 'xezat/commands'
5
+ require 'xezat/cygclasses'
6
+
7
+ module Xezat
8
+ # 指定された repository が存在しない場合に投げられる例外
9
+ class NoSuchRepositoryError < StandardError
10
+ end
11
+
12
+ # cygport を上書き許可なしで上書きしようとした場合に投げられる例外
13
+ class UnoverwritableConfigurationError < StandardError
14
+ end
15
+
16
+ # 指定された cygclass が存在しない場合に投げられる例外
17
+ class NoSuchCygclassError < StandardError
18
+ end
19
+
20
+ # VCS が複数指定された場合に投げられる例外
21
+ class CygclassConflictError < StandardError
22
+ end
23
+
24
+ module Command
25
+ # 新しい cygport ファイルを生成する
26
+ class Create
27
+ def initialize(program)
28
+ program.command(:create) do |c|
29
+ c.syntax 'create [options] cygport'
30
+ c.description 'create new cygport'
31
+ c.option 'apponly', '-a', '--app-only', 'application only'
32
+ c.option 'category', '-c', '--category category', String, 'specify category'
33
+ c.option 'description', '--description description', String, 'specify description'
34
+ c.option 'inherit', '-i', '--inherit cygclass', Array, 'inherit cygclasses'
35
+ c.option 'overwrite', '-o', '--overwrite', 'overwrite cygport'
36
+ c.option 'repository', '--repository repository', String, 'specify repository (github, google, sourceforge)'
37
+ c.option 'summary', '-s', '--summary summary', String, 'specify summary'
38
+ c.action do |args, options|
39
+ execute(c, args, options)
40
+ end
41
+ end
42
+ end
43
+
44
+ CommandManager::register(:create, self)
45
+
46
+ def execute(c, args, options)
47
+ cygport = args.shift
48
+ raise ArgumentError, 'wrong number of arguments (0 for 1)' unless cygport
49
+ c.logger.info "ignore extra arguments: #{args.to_s}" unless args.empty?
50
+
51
+ repository_variables = self.get_repository_variables(options['repository'])
52
+
53
+ raise UnoverwritableConfigurationError, "#{cygport} already exists" if File::exist?(cygport) && !options['overwrite']
54
+
55
+ cygclasses = options['inherit'] || []
56
+ template_variables = get_template_variables(repository_variables, CygclassManager.new, cygclasses)
57
+ File::atomic_write(cygport) do |f|
58
+ f.write(get_cygport(template_variables, options['category'], options['summary'], options['description'], options['apponly'], cygclasses, cygport))
59
+ end
60
+ end
61
+
62
+ # repository からデフォルトのシェル変数群を取得する
63
+ def get_repository_variables(repository)
64
+ if repository
65
+ repository_file = File::expand_path(File::join(REPOSITORY_DIR, "#{repository}.json"))
66
+ if FileTest::exists?(repository_file) && FileTest::readable?(repository_file)
67
+ repository_variables = JSON.parse(File::read(repository_file), {:symbolize_names => true})
68
+ else
69
+ raise NoSuchRepositoryError, "No such repository: #{template}"
70
+ end
71
+ else
72
+ {
73
+ :HOMEPAGE => '',
74
+ :SRC_URI => ''
75
+ }
76
+ end
77
+ end
78
+
79
+ # 他のパラメータからテンプレートに埋め込むシェル変数群を取得する
80
+ def get_template_variables(original_template_variables, cygclass_manager, cygclasses)
81
+ vcs_class = nil
82
+ vcs_prefix = 'SRC'
83
+ cygclasses.each do |cygclass|
84
+ raise NoSuchCygclassError, "No such cygclass: #{cygclass}" unless cygclass_manager.include?(cygclass.intern)
85
+ if cygclass_manager.vcs?(cygclass.intern)
86
+ raise CygclassConflictError, "#{cygclass} conflict with #{vcs_class}" if vcs_class
87
+ vcs_class = cygclass
88
+ end
89
+ end
90
+ vcs_prefix = vcs_class.to_s.upcase if vcs_class
91
+ vcs_uri = "#{vcs_prefix}_URI".intern
92
+ {
93
+ :HOMEPAGE => original_template_variables[:HOMEPAGE],
94
+ vcs_uri => original_template_variables[vcs_uri]
95
+ }
96
+ end
97
+
98
+ # シェル変数群を埋め込まれたテンプレート文字列を返す
99
+ def get_cygport(template_variables, category, summary, description, apponly, cygclasses, cygport)
100
+ erb = File::expand_path(File::join(TEMPLATE_DIR, 'cygport.erb'))
101
+ ERB.new(File::readlines(erb).join(nil), nil, '%-').result(binding)
102
+ end
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,30 @@
1
+ require 'pp'
2
+ require 'xezat/commands'
3
+ require 'xezat/variables'
4
+
5
+ module Xezat
6
+ module Command
7
+ # 変数を表示する
8
+ class Debug
9
+ def initialize(program)
10
+ program.command(:debug) do |c|
11
+ c.syntax 'debug cygport'
12
+ c.description 'show cygport variables'
13
+ c.action do |args, options|
14
+ execute(c, args, options)
15
+ end
16
+ end
17
+ end
18
+
19
+ CommandManager::register(:debug, self)
20
+
21
+ def execute(c, args, options)
22
+ cygport = args.shift
23
+ raise ArgumentError, 'wrong number of arguments (0 for 1)' unless cygport
24
+ c.logger.info "ignore extra arguments: #{args.to_s}" unless args.empty?
25
+
26
+ pp VariableManager::get_default_variables(cygport)
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,45 @@
1
+ require 'xezat/commands'
2
+ require 'zlib'
3
+
4
+ module Xezat
5
+ module Command
6
+ # package tree が健全であるかどうかを診断する
7
+ class Doctor
8
+ def initialize(program)
9
+ program.command(:doctor) do |c|
10
+ c.syntax 'doctor'
11
+ c.description 'diagnose installed packages'
12
+ c.action do |args, options|
13
+ execute(c, args, options)
14
+ end
15
+ end
16
+ end
17
+
18
+ CommandManager::register(:doctor, self)
19
+
20
+ def execute(c, args, options)
21
+ get_contents_uniqueness.each do |path, pkg|
22
+ c.logger.warn "#{path} is in multiple packages: #{pkg}" if pkg.length > 1
23
+ end
24
+ end
25
+
26
+ def get_contents_uniqueness(path = '/etc/setup')
27
+ content2pkg = {}
28
+ Dir.glob(File.join(path, '*.lst.gz')) do |lst|
29
+ pkg = File.basename(lst, '.lst.gz').intern
30
+ Zlib::GzipReader.open(lst) do |gz|
31
+ gz.each_line do |line|
32
+ line.strip!
33
+ unless line.end_with?('/')
34
+ path = line.intern
35
+ content2pkg[path] = [] unless content2pkg.key?(path)
36
+ content2pkg[path] << pkg
37
+ end
38
+ end
39
+ end
40
+ end
41
+ content2pkg
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,50 @@
1
+ require 'xezat/commands'
2
+ require 'xezat/variables'
3
+
4
+ module Xezat
5
+ # 生成するファイルを上書き許可なしで上書きしようとした場合に投げられる例外
6
+ class UnregeneratableConfigurationError < StandardError
7
+ end
8
+
9
+ module Command
10
+ # 追加のファイルを生成する
11
+ class Generate
12
+ def initialize(program)
13
+ program.command(:generate) do |c|
14
+ c.syntax 'generate [options] cygport'
15
+ c.description 'generate additional files'
16
+ c.option 'cmake', '-c', '--cmake', 'generate *.cmake'
17
+ c.option 'overwrite', '-o', '--overwrite', 'overwrite file'
18
+ c.option 'pc', '-p', '--pkg-config', 'generate *.pc'
19
+ c.action do |args, options|
20
+ execute(c, args, options)
21
+ end
22
+ end
23
+ end
24
+
25
+ CommandManager::register(:generate, self)
26
+
27
+ def execute(c, args, options)
28
+ cygport = args.shift
29
+ raise ArgumentError, 'wrong number of arguments (0 for 1)' unless cygport
30
+ c.logger.info "ignore extra arguments: #{args.to_s}" unless args.empty?
31
+
32
+ variables = VariableManager::get_default_variables(cygport)
33
+
34
+ if options['pc']
35
+ pc = File::expand_path(File::join(variables[:S], "#{variables[:PN]}.pc.in"))
36
+ raise UnregeneratableConfigurationError, "#{variables[:PN]}.pc.in already exists" if File::exist?(pc) && !options['overwrite']
37
+ File::atomic_write(pc) do |f|
38
+ f.write(get_package_config(variables))
39
+ end
40
+ end
41
+ end
42
+
43
+ # シェル変数群を埋め込まれたテンプレート文字列を返す
44
+ def get_package_config(variables)
45
+ erb = File::expand_path(File::join(TEMPLATE_DIR, 'pkgconfig.erb'))
46
+ ERB.new(File::readlines(erb).join(nil), nil, '%-').result(binding)
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,43 @@
1
+ require 'xezat/commands'
2
+ require 'xezat/validators'
3
+ require 'xezat/variables'
4
+
5
+ module Xezat
6
+ module Command
7
+ # package が妥当であるかを検証する
8
+ class Validate
9
+ def initialize(program)
10
+ program.command(:validate) do |c|
11
+ c.syntax 'validate [options] cygport'
12
+ c.description 'validate package contents'
13
+ c.action do |args, options|
14
+ execute(c, args, options)
15
+ end
16
+ end
17
+ end
18
+
19
+ CommandManager::register(:validate, self)
20
+
21
+ def execute(c, args, options)
22
+ cygport = args.shift
23
+ raise ArgumentError, 'wrong number of arguments (0 for 1)' unless cygport
24
+ c.logger.info "ignore extra arguments: #{args.to_s}" unless args.empty?
25
+ variables = VariableManager::get_default_variables(cygport)
26
+ ValidatorManager::load_default_validators
27
+ ValidatorManager::validate(variables).each do |name, result|
28
+ if result[:result].nil?
29
+ c.logger.info "Validate #{name} ... skip"
30
+ else
31
+ if result[:result]
32
+ c.logger.info "Validate #{name} ... OK"
33
+ else
34
+ c.logger.warn "Validate #{name} ... NG"
35
+ c.logger.warn result[:detail]
36
+ end
37
+ end
38
+ end
39
+
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,32 @@
1
+ module Xezat
2
+ # command が多重定義された場合に投げられる例外
3
+ class MultipleCommandDefinitionError < StandardError
4
+ end
5
+
6
+ # command を管理するクラス
7
+ class CommandManager
8
+ @@commands = {}
9
+
10
+ # command を登録する
11
+ def self.register(name, klass)
12
+ raise MultipleCommandDefinitionError, "'#{name}' already defined" if @@commands.key?(name)
13
+ @@commands[name] = klass.new(@@program)
14
+ end
15
+
16
+ # command をロードする
17
+ def self.load_default_commands(path = File::expand_path(File::join(File::dirname(__FILE__), 'command')))
18
+ Dir::glob(File::join(path, '*.rb')) do |rb|
19
+ require rb
20
+ end
21
+ end
22
+
23
+ def self.program=(program)
24
+ @@program = program
25
+ end
26
+
27
+ def self.[](name)
28
+ @@commands[name]
29
+ end
30
+
31
+ end
32
+ end
@@ -0,0 +1,53 @@
1
+ require 'rubygems'
2
+
3
+ module Xezat
4
+ # package の changelog を管理するクラス
5
+ class Cygchangelog
6
+ def initialize(str = '')
7
+ @changelogs = str.empty? ? {} : nil
8
+ version = nil
9
+ str.each_line do |line|
10
+ line.rstrip!
11
+ if /^Port Notes:$/ === line
12
+ @changelogs = {}
13
+ else
14
+ unless @changelogs.nil?
15
+ if match_data = /^----- version (.+) -----$/.match(line)
16
+ version = match_data[1].intern
17
+ else
18
+ if match_data = /^(.+)$/.match(line)
19
+ raise ReadmeSyntaxException, "Version missing" if version.nil?
20
+ if @changelogs.key?(version)
21
+ @changelogs[version] << $/ << match_data[1]
22
+ else
23
+ @changelogs[version] = match_data[1]
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+
32
+ def [](key)
33
+ @changelogs[key]
34
+ end
35
+
36
+ def []=(key, value)
37
+ @changelogs[key] = value
38
+ end
39
+
40
+ def key?(key)
41
+ @changelogs.key?(key)
42
+ end
43
+
44
+ def each(&block)
45
+ @changelogs.sort do |a, b|
46
+ - (Gem::Version.new(a[0]) <=> Gem::Version.new(b[0]))
47
+ end.each do |k, v|
48
+ block.call(k, v)
49
+ end
50
+ end
51
+
52
+ end
53
+ end
@@ -0,0 +1,33 @@
1
+ require 'xezat'
2
+
3
+ module Xezat
4
+ # cygclass を管理するクラス
5
+ class CygclassManager
6
+ def initialize(cygclass_dir = '/usr/share/cygport/cygclass')
7
+ @cygclasses = []
8
+ @vcs_cygclassess = []
9
+ if Dir.exists?(cygclass_dir)
10
+ Dir.glob(File.join(cygclass_dir, '*.cygclass')) do |filename|
11
+ cygclass = File::basename(filename, '.cygclass')
12
+ @cygclasses << cygclass.intern
13
+ File::foreach(filename) do |line|
14
+ @vcs_cygclassess << cygclass.intern if "readonly -f #{cygclass}_fetch" == line.strip
15
+ end
16
+ end
17
+ end
18
+ end
19
+
20
+ def include?(cygclass)
21
+ @cygclasses.include?(cygclass)
22
+ end
23
+
24
+ def vcs?(cygclass)
25
+ @vcs_cygclassess.include?(cygclass)
26
+ end
27
+
28
+ def vcs()
29
+ @vcs_cygclassess
30
+ end
31
+
32
+ end
33
+ end
@@ -0,0 +1,16 @@
1
+ require 'find'
2
+ require 'xezat/detectors'
3
+
4
+ module Xezat
5
+ module Detector
6
+ class Autoconf
7
+ DetectorManager::register(:autoconf, self)
8
+ def detect(variables)
9
+ Find::find(variables[:S]) do |file|
10
+ return true if file.end_with?(File::SEPARATOR + 'configure.ac') || file.end_with?(File::SEPARATOR + 'configure.in')
11
+ end
12
+ false
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,16 @@
1
+ require 'find'
2
+ require 'xezat/detectors'
3
+
4
+ module Xezat
5
+ module Detector
6
+ class Automake
7
+ DetectorManager::register(:automake, self)
8
+ def detect(variables)
9
+ Find::find(variables[:S]) do |file|
10
+ return true if file.end_with?(File::SEPARATOR + 'Makefile.am')
11
+ end
12
+ false
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,20 @@
1
+ require 'find'
2
+ require 'xezat/detectors'
3
+
4
+ module Xezat
5
+ module Detector
6
+ class BoostM4
7
+ DetectorManager::register(:'boost.m4', self)
8
+ def detect(variables)
9
+ Find::find(variables[:S]) do |file|
10
+ if file.end_with?(File::SEPARATOR + 'configure.ac') || file.end_with?(File::SEPARATOR + 'configure.in')
11
+ File::foreach(file) do |line|
12
+ return true if line.lstrip.start_with?('BOOST_REQUIRE')
13
+ end
14
+ end
15
+ end
16
+ false
17
+ end
18
+ end
19
+ end
20
+ end