packo 0.0.1.alpha.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (107) hide show
  1. data/bin/packo +78 -0
  2. data/bin/packo-base +24 -0
  3. data/bin/packo-build +24 -0
  4. data/bin/packo-db +24 -0
  5. data/bin/packo-env +24 -0
  6. data/bin/packo-files +24 -0
  7. data/bin/packo-profile +24 -0
  8. data/bin/packo-repository +24 -0
  9. data/bin/packo-select +24 -0
  10. data/lib/packo.rb +186 -0
  11. data/lib/packo/cli.rb +79 -0
  12. data/lib/packo/cli/base.rb +554 -0
  13. data/lib/packo/cli/build.rb +488 -0
  14. data/lib/packo/cli/database.rb +55 -0
  15. data/lib/packo/cli/database/definition.rb +65 -0
  16. data/lib/packo/cli/database/helpers.rb +20 -0
  17. data/lib/packo/cli/environment.rb +45 -0
  18. data/lib/packo/cli/files.rb +153 -0
  19. data/lib/packo/cli/profile.rb +31 -0
  20. data/lib/packo/cli/repository.rb +561 -0
  21. data/lib/packo/cli/repository/binary.rb +74 -0
  22. data/lib/packo/cli/repository/helpers.rb +20 -0
  23. data/lib/packo/cli/repository/repository.rb +48 -0
  24. data/lib/packo/cli/repository/source.rb +91 -0
  25. data/lib/packo/cli/repository/virtual.rb +53 -0
  26. data/lib/packo/cli/select.rb +61 -0
  27. data/lib/packo/do.rb +249 -0
  28. data/lib/packo/environment.rb +269 -0
  29. data/lib/packo/extensions.rb +70 -0
  30. data/lib/packo/flags.rb +64 -0
  31. data/lib/packo/host.rb +121 -0
  32. data/lib/packo/models.rb +171 -0
  33. data/lib/packo/models/installed_package.rb +190 -0
  34. data/lib/packo/models/installed_package/content.rb +50 -0
  35. data/lib/packo/models/installed_package/dependency.rb +39 -0
  36. data/lib/packo/models/repository.rb +209 -0
  37. data/lib/packo/models/repository/binary.rb +32 -0
  38. data/lib/packo/models/repository/binary/mirror.rb +35 -0
  39. data/lib/packo/models/repository/package.rb +73 -0
  40. data/lib/packo/models/repository/package/binary.rb +34 -0
  41. data/lib/packo/models/repository/package/binary/build.rb +36 -0
  42. data/lib/packo/models/repository/package/source.rb +36 -0
  43. data/lib/packo/models/repository/package/source/feature.rb +36 -0
  44. data/lib/packo/models/repository/package/source/flavor.rb +36 -0
  45. data/lib/packo/models/repository/package/virtual.rb +32 -0
  46. data/lib/packo/models/repository/source.rb +30 -0
  47. data/lib/packo/models/repository/virtual.rb +30 -0
  48. data/lib/packo/models/selector.rb +34 -0
  49. data/lib/packo/models/tag.rb +30 -0
  50. data/lib/packo/package.rb +239 -0
  51. data/lib/packo/package/blocker.rb +100 -0
  52. data/lib/packo/package/blockers.rb +40 -0
  53. data/lib/packo/package/dependencies.rb +40 -0
  54. data/lib/packo/package/dependency.rb +100 -0
  55. data/lib/packo/package/feature.rb +55 -0
  56. data/lib/packo/package/features.rb +105 -0
  57. data/lib/packo/package/flavor.rb +101 -0
  58. data/lib/packo/package/tags.rb +60 -0
  59. data/lib/packo/package/tags/expression.rb +130 -0
  60. data/lib/packo/package/tags/expression/group.rb +28 -0
  61. data/lib/packo/package/tags/expression/logic.rb +48 -0
  62. data/lib/packo/package/tags/expression/name.rb +28 -0
  63. data/lib/packo/profile.rb +174 -0
  64. data/lib/packo/rbuild.rb +22 -0
  65. data/lib/packo/rbuild/behaviors.rb +20 -0
  66. data/lib/packo/rbuild/behaviors/default.rb +27 -0
  67. data/lib/packo/rbuild/feature.rb +64 -0
  68. data/lib/packo/rbuild/features.rb +65 -0
  69. data/lib/packo/rbuild/flavor.rb +67 -0
  70. data/lib/packo/rbuild/module.rb +40 -0
  71. data/lib/packo/rbuild/modules.rb +27 -0
  72. data/lib/packo/rbuild/modules/building.rb +24 -0
  73. data/lib/packo/rbuild/modules/building/autotools.rb +315 -0
  74. data/lib/packo/rbuild/modules/building/cmake.rb +38 -0
  75. data/lib/packo/rbuild/modules/building/patch.rb +84 -0
  76. data/lib/packo/rbuild/modules/building/rake.rb +74 -0
  77. data/lib/packo/rbuild/modules/building/strip.rb +41 -0
  78. data/lib/packo/rbuild/modules/misc.rb +26 -0
  79. data/lib/packo/rbuild/modules/misc/fetcher.rb +177 -0
  80. data/lib/packo/rbuild/modules/misc/fetching.rb +22 -0
  81. data/lib/packo/rbuild/modules/misc/fetching/git.rb +57 -0
  82. data/lib/packo/rbuild/modules/misc/fetching/github.rb +31 -0
  83. data/lib/packo/rbuild/modules/misc/fetching/gnu.rb +59 -0
  84. data/lib/packo/rbuild/modules/misc/fetching/mercurial.rb +51 -0
  85. data/lib/packo/rbuild/modules/misc/fetching/sourceforge.rb +47 -0
  86. data/lib/packo/rbuild/modules/misc/fetching/subversion.rb +51 -0
  87. data/lib/packo/rbuild/modules/misc/fetching/wget.rb +57 -0
  88. data/lib/packo/rbuild/modules/misc/unpacker.rb +70 -0
  89. data/lib/packo/rbuild/modules/misc/unpacking.rb +23 -0
  90. data/lib/packo/rbuild/modules/misc/unpacking/lzma.rb +34 -0
  91. data/lib/packo/rbuild/modules/misc/unpacking/tar.rb +35 -0
  92. data/lib/packo/rbuild/modules/misc/unpacking/xz.rb +34 -0
  93. data/lib/packo/rbuild/modules/misc/unpacking/zip.rb +26 -0
  94. data/lib/packo/rbuild/modules/packaging.rb +20 -0
  95. data/lib/packo/rbuild/modules/packaging/pko.rb +78 -0
  96. data/lib/packo/rbuild/package.rb +281 -0
  97. data/lib/packo/rbuild/package/manifest.rb +169 -0
  98. data/lib/packo/rbuild/stages.rb +171 -0
  99. data/lib/packo/rbuild/stages/callbacks.rb +96 -0
  100. data/lib/packo/rbuild/stages/stage.rb +50 -0
  101. data/lib/packo/repository.rb +95 -0
  102. data/lib/packo/repository/binary.rb +116 -0
  103. data/lib/packo/repository/source.rb +77 -0
  104. data/lib/packo/repository/virtual.rb +66 -0
  105. data/lib/packo/system.rb +53 -0
  106. data/lib/packo/version.rb +26 -0
  107. metadata +276 -0
@@ -0,0 +1,488 @@
1
+ # encoding: utf-8
2
+ #--
3
+ # Copyleft meh. [http://meh.doesntexist.org | meh@paranoici.org]
4
+ #
5
+ # This file is part of packo.
6
+ #
7
+ # packo is free software: you can redistribute it and/or modify
8
+ # it under the terms of the GNU Affero General Public License as published
9
+ # by the Free Software Foundation, either version 3 of the License, or
10
+ # (at your option) any later version.
11
+ #
12
+ # packo is distributed in the hope that it will be useful,
13
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ # GNU Affero General Public License for more details.
16
+ #
17
+ # You should have received a copy of the GNU Affero General Public License
18
+ # along with packo. If not, see <http://www.gnu.org/licenses/>.
19
+ #++
20
+
21
+ require 'nokogiri'
22
+ require 'digest/sha1'
23
+
24
+ require 'packo'
25
+ require 'packo/rbuild'
26
+
27
+ module Packo; module CLI
28
+
29
+ class Build < Thor
30
+ include Thor::Actions
31
+
32
+ class_option :help, type: :boolean, desc: 'Show help usage'
33
+
34
+ desc 'package PACKAGE... [OPTIONS]', 'Create packages of the matching names'
35
+ method_option :output, type: :string, default: System.env[:TMP], aliases: '-o', desc: 'The directory where to save packages'
36
+ method_option :wipe, type: :boolean, default: false, aliases: '-w', desc: 'Wipes the package directory before building it'
37
+ method_option :ask, type: :boolean, default: false, aliases: '-a', desc: 'Prompt the user if he want to continue building or not'
38
+ method_option :repository, type: :string, aliases: '-r', desc: 'Set a specific source repository'
39
+ method_option :execute, type: :string, aliases: '-x', desc: 'Create a package from an executed command instead of from an RBuild'
40
+ method_option :bump, type: :boolean, default: true, aliases: '-b', desc: 'Bump revision when creating a package from command if package is installed'
41
+ method_option :inspect, type: :boolean, default: false, aliases: '-i', desc: 'Inspect the list of files that will be included in the package in EDITOR'
42
+ def package (*packages)
43
+ if command = options[:execute]
44
+ if System.env[:SANDBOX_ACTIVE] || System.env[:FAKED_MODE]
45
+ CLI.warn "`packo build -x` may not work properly, try with `packo-build -x` if it fails.\n\n"
46
+ end
47
+
48
+ package = Package.parse(packages.first)
49
+
50
+ unless package.name && package.version
51
+ CLI.fatal 'You have to pass a valid package name and version, like package-0.2'
52
+ exit 1
53
+ end
54
+
55
+ package = RBuild::Package.define(package.name, package.version) {
56
+ tags *package.tags
57
+
58
+ description "Built in: `#{Dir.pwd}` with `#{command}`"
59
+ maintainer ENV['USER']
60
+ }
61
+
62
+ package.avoid RBuild::Behaviors::Default
63
+
64
+ package.clean!
65
+ package.create!
66
+
67
+ tmp = Tempfile.new('packo')
68
+ dir = "#{System.env[:TMP]}/#{Process.pid}"
69
+
70
+ tmp.write %{
71
+ #! /bin/sh
72
+
73
+ cd "#{Dir.pwd}"
74
+
75
+ #{command}
76
+
77
+ exit $?
78
+ }
79
+
80
+ tmp.chmod 0700
81
+ tmp.close
82
+
83
+ Packo.sh 'installwatch', "--logfile=#{package.tempdir}/newfiles.log", "--exclude=#{Dir.pwd}",
84
+ "--root=#{package.workdir}", '--transl=yes', '--backup=no', tmp.path
85
+
86
+ inspect = options[:inspect]
87
+
88
+ package.before :pack, priority: -42 do
89
+ files = File.new("#{tempdir}/newfiles", 'w')
90
+
91
+ files.print File.new("#{tempdir}/newfiles.log", 'r').lines.map {|line| line.strip!
92
+ whole, type = line.match(/^.*?\t(.*?)\t/).to_a
93
+
94
+ case type
95
+ when 'chmod', 'open'
96
+ whole, file = line.match(/.*?\t.*?\t(.*?)(\t|$)/).to_a
97
+
98
+ next if file.match(%r[^(/dev|#{Regexp.escape(Dir.pwd)}|/tmp)(/|$)])
99
+
100
+ file
101
+
102
+ when 'symlink'
103
+ whole, to, file = line.match(/.*?\t.*?\t(.*?)\t(.*?)(\t|$)/).to_a
104
+
105
+ "#{file} -> #{to}"
106
+ end
107
+ }.compact.uniq.sort.join("\n")
108
+
109
+ files.close
110
+
111
+ if inspect
112
+ Packo.sh System.env[:EDITOR] || 'vi', files.path
113
+ end
114
+
115
+ links = []
116
+
117
+ File.new("#{tempdir}/newfiles", 'r').lines.each {|line|
118
+ whole, file, link = line.match(/^(.*?)(?: -> (.*?))?$/).to_a
119
+
120
+ FileUtils.mkpath "#{distdir}/#{File.dirname(file)}"
121
+
122
+ if link
123
+ links << [link, file]
124
+ else
125
+ FileUtils.cp "#{workdir}/TRANSL/#{file}", "#{distdir}/#{file}"
126
+ end
127
+ }
128
+
129
+ links.each {|(link, file)|
130
+ FileUtils.ln_sf link, "#{distdir}/#{file}" rescue nil
131
+ }
132
+ end
133
+
134
+ package.before :pack! do
135
+ if inspect
136
+ Packo.sh System.env[:EDITOR] || 'vi', "#{directory}/manifest.xml"
137
+ end
138
+ end
139
+
140
+ if options[:bump]
141
+ require 'packo/models'
142
+
143
+ if !Models.search_installed(package.to_s).empty?
144
+ package.revision = Models.search_installed(package.to_s).first.revision + 1
145
+ end
146
+ end
147
+
148
+ begin
149
+ package.build {|stage|
150
+ CLI.info "Executing #{stage.name}"
151
+ }
152
+
153
+ CLI.info "Succesfully built #{package}"
154
+ rescue Exception => e
155
+ CLI.fatal "Failed to build #{package}"
156
+ CLI.fatal e.message
157
+ Packo.debug e
158
+ end
159
+
160
+ exit 0
161
+ end
162
+
163
+ Environment.new {|env|
164
+ if !env[:ARCH] || !env[:KERNEL] || !env[:LIBC] || !env[:COMPILER]
165
+ CLI.fatal 'You have to set ARCH, KERNEL, LIBC and COMPILER to build packages.'
166
+ exit 1
167
+ end
168
+ }
169
+
170
+ packages.map {|package|
171
+ if package.end_with?('.rbuild')
172
+ package
173
+ else
174
+ require 'packo/models'
175
+
176
+ packages = Models.search(package, options[:repository])
177
+
178
+ names = packages.group_by {|package|
179
+ "#{package.tags}/#{package.name}"
180
+ }.map {|(name, package)| name}.uniq
181
+
182
+ if names.length == 0
183
+ CLI.fatal "No package matches #{package}"
184
+
185
+ exit 10
186
+ elsif names.length > 1
187
+ CLI.fatal "More than one package matches: #{package}"
188
+
189
+ names.each {|name|
190
+ puts " #{name}"
191
+ }
192
+
193
+ exit 11
194
+ end
195
+
196
+ packages.sort {|a, b|
197
+ a.version <=> b.version
198
+ }.last
199
+ end
200
+ }.each {|package|
201
+ if package.is_a?(String)
202
+ path = File.dirname(File.realpath(package))
203
+ package = Package.parse(package.sub(/\.rbuild$/, ''))
204
+ else
205
+ path = "#{package.repository.path}/#{package.model.data.path}"
206
+ end
207
+
208
+ manifest = Nokogiri::XML.parse(File.read("#{path}/digest.xml"))
209
+
210
+ files = {}
211
+ manifest.xpath('//files/file').each {|e|
212
+ files[e['name']] = e.text
213
+ }
214
+
215
+ begin; package = Packo.loadPackage(path, package); rescue LoadError; end
216
+
217
+ if !package
218
+ CLI.fatal 'The package could not be instantiated'
219
+ exit 12
220
+ end
221
+
222
+ if package.parent.nil?
223
+ CLI.warn 'The package does not have a parent'
224
+ end
225
+
226
+ package.path = path
227
+
228
+ CLI.info "Building #{package}"
229
+
230
+ output = File.realpath(options[:output])
231
+
232
+ package.after :pack do |path|
233
+ FileUtils.cp path, output, preserve: true
234
+ end
235
+
236
+ if (File.read("#{package.directory}/.build") rescue nil) != package.to_s(:everything) || options[:wipe]
237
+ CLI.info "Cleaning #{package} because something changed."
238
+
239
+ clean("#{path}/#{package.name}-#{package.version}.rbuild")
240
+
241
+ package.create!
242
+
243
+ begin
244
+ File.write("#{package.directory}/.build", package.to_s(:everything))
245
+ rescue; end
246
+ end
247
+
248
+ begin
249
+ package.build {|stage|
250
+ CLI.info "Executing #{stage.name}"
251
+ }
252
+
253
+ CLI.info "Succesfully built #{package}"
254
+ rescue Exception => e
255
+ CLI.fatal "Failed to build #{package}"
256
+ CLI.fatal e.message
257
+ Packo.debug e
258
+ end
259
+ }
260
+ end
261
+
262
+ desc 'clean PACKAGE... [OPTIONS]', 'Clean packages'
263
+ method_option :repository, type: :string, aliases: '-r', desc: 'Set a specific source repository'
264
+ def clean (*packages)
265
+ packages.map {|package|
266
+ if package.end_with?('.rbuild')
267
+ package
268
+ else
269
+ require 'packo/models'
270
+
271
+ packages = Models.search(package, options[:repository])
272
+
273
+ if (multiple = packages.uniq).length > 1
274
+ CLI.fatal 'Multiple packages with the same name, be more precise.'
275
+ exit 2
276
+ end
277
+
278
+ packages.last
279
+ end
280
+ }.compact.each {|package|
281
+ if package.is_a?(String)
282
+ path = File.dirname(File.realpath(package))
283
+ package = Package.parse(package.sub(/\.rbuild$/, ''))
284
+ else
285
+ path = "#{package.repository.path}/#{package.model.data.path}"
286
+ end
287
+
288
+ begin
289
+ package = Packo.loadPackage(path, package)
290
+ package.clean!
291
+
292
+ CLI.info "Cleaned #{package.to_s(:name)}"
293
+ rescue Exception => e
294
+ CLI.fatal "Failed cleaning of #{package.to_s(:name)}"
295
+ Packo.debug e
296
+ end
297
+ }
298
+ end
299
+
300
+ desc 'digest RBUILD...', 'Digest the given rbuilds'
301
+ def digest (*files)
302
+ files.each {|file|
303
+ if !File.exists?(file)
304
+ CLI.fatal "#{file} does not exist"
305
+ exit 40
306
+ end
307
+
308
+ Dir.chdir(File.dirname(file))
309
+
310
+ begin
311
+ if File.basename(file).match(/.*?-\d/)
312
+ package = Packo.loadPackage(File.dirname(file), Package.parse(File.basename(file).sub(/\.rbuild$/, '')))
313
+ else
314
+ package = Packo.loadPackage(file)
315
+ end
316
+ rescue LoadError
317
+ CLI.fatal 'Failed to load the rbuild'
318
+ exit 41
319
+ end
320
+
321
+ if !package
322
+ CLI.fatal "Couldn't instantiate the package."
323
+ exit 42
324
+ end
325
+
326
+ package.digests = {}
327
+
328
+ package.after :fetch do |result|
329
+ package.stages.stop!
330
+
331
+ throw :halt
332
+ end
333
+
334
+ Do.cd {
335
+ package.build
336
+ }
337
+
338
+ original = Nokogiri::XML.parse(File.read('digest.xml')) {|config|
339
+ config.default_xml.noblanks
340
+ } rescue nil
341
+
342
+ builder = Nokogiri::XML::Builder.new {|xml|
343
+ xml.digest(version: '1.0') {
344
+ xml.build(version: package.version, slot: package.slot) {
345
+ xml.features package.features.to_a.map {|f| f.name}.join(' ')
346
+
347
+ xml.files {
348
+ package.distfiles.to_a.each {|(name, file)|
349
+ file ||= name
350
+
351
+ xml.file({ name: File.basename(file.path), url: file.url }, Do.digest(file.path))
352
+ } if package.distfiles
353
+ }
354
+ }
355
+
356
+ if original
357
+ original.xpath('//build').each {|build|
358
+ if build['version'] != package.version.to_s && ((build['slot'].empty? && !package.slot) || build['slot'] != package.slot.to_s)
359
+ xml.doc.root.add_child(build)
360
+ end
361
+ }
362
+ end
363
+ }
364
+ }
365
+
366
+ File.write('digest.xml', builder.to_xml(indent: 4))
367
+ }
368
+ rescue Errno::EACCES
369
+ CLI.fatal 'Try to use packo-build instead.'
370
+ end
371
+
372
+ desc 'manifest PACKAGE [OPTIONS]', 'Output the manifest of the given package'
373
+ method_option :repository, type: :string, aliases: '-r', desc: 'Set a specific source repository'
374
+ def manifest (package)
375
+ if package.end_with?('.rbuild')
376
+ if File.basename(package).match(/.*?-\d/)
377
+ package = Packo.loadPackage(File.dirname(package), Package.parse(File.basename(package).sub(/\.rbuild$/, '')))
378
+ else
379
+ package = Packo.loadPackage(package)
380
+ end
381
+ else
382
+ require 'packo/models'
383
+
384
+ tmp = Models.search(package, options[:repository])
385
+
386
+ if tmp.empty?
387
+ CLI.fatal 'Package not found'
388
+ exit 21
389
+ end
390
+
391
+ if (multiple = tmp.uniq).length > 1
392
+ CLI.fatal 'Multiple packages with the same name, be more precise.'
393
+ exit 22
394
+ end
395
+
396
+ package = Packo.loadPackage("#{tmp.last.repository.path}/#{tmp.last.model.data.path}", tmp.last)
397
+ end
398
+
399
+ if package
400
+ puts RBuild::Package::Manifest.new(package).to_s
401
+ else
402
+ CLI.fatal 'Package could not be instantiated'
403
+ exit 23
404
+ end
405
+ end
406
+
407
+ desc 'info FILE', 'Get informations about an rbuild'
408
+ def info (file)
409
+ if File.basename(file).match(/.*?-\d/)
410
+ package = Packo.loadPackage(File.dirname(file), Package.parse(File.basename(file).sub(/\.rbuild$/, '')))
411
+ else
412
+ package = Packo.loadPackage(file)
413
+ end
414
+
415
+ print package.name.bold
416
+ print "-#{package.version.to_s.red}"
417
+ print " {#{package.revision.yellow.bold}}" if package.revision > 0
418
+ print " (#{package.slot.blue.bold})" if package.slot
419
+ print " [#{package.tags.join(' ').magenta}]"
420
+ print "\n"
421
+
422
+ puts " #{'Description'.green}: #{package.description}"
423
+ puts " #{'Homepage'.green}: #{package.homepage}"
424
+ puts " #{'License'.green}: #{package.license}"
425
+ puts " #{'Maintainer'.green}: #{package.maintainer || 'nobody'}"
426
+
427
+ flavor = []
428
+ package.flavor.each {|f|
429
+ next if [:vanilla, :documentation, :headers, :debug].member?(f.name)
430
+
431
+ flavor << f
432
+ }
433
+
434
+ features = []
435
+ package.features.each {|f|
436
+ features << f
437
+ }
438
+
439
+ length = (flavor + features).map {|f|
440
+ f.name.length
441
+ }.max
442
+
443
+ if flavor.length > 0
444
+ print " #{'Flavor'.green}: "
445
+
446
+ flavor.each {|element|
447
+ if element.enabled
448
+ print "#{element.name.to_s.white.bold}#{System.env[:NO_COLORS] ? '!' : ''}"
449
+ else
450
+ print element.name.to_s.black.bold
451
+ end
452
+
453
+ print "#{' ' * (4 + length - element.name.length + (System.env[:NO_COLORS] && !element.enabled? ? 1 : 0))}#{element.description || '...'}"
454
+
455
+ print "\n "
456
+ }
457
+
458
+ print "\r" if features.length > 0
459
+ end
460
+
461
+ if features.length > 0
462
+ print " #{'Features'.green}: "
463
+
464
+ features.each {|feature|
465
+ if feature.enabled
466
+ print "#{feature.name.to_s.white.bold}#{System.env[:NO_COLORS] ? '!' : ''}"
467
+ else
468
+ print feature.name.to_s.black.bold
469
+ end
470
+
471
+ print "#{' ' * (4 + length - feature.name.length + (System.env[:NO_COLORS] && !feature.enabled? ? 1 : 0))}#{feature.description || '...'}"
472
+
473
+ print "\n "
474
+ }
475
+ end
476
+
477
+ print "\n"
478
+ end
479
+
480
+ def initialize (*args)
481
+ FileUtils.mkpath(System.env[:TMP])
482
+ File.umask 022
483
+
484
+ super(*args)
485
+ end
486
+ end
487
+
488
+ end; end