packo 0.0.1.alpha.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.
- data/bin/packo +78 -0
- data/bin/packo-base +24 -0
- data/bin/packo-build +24 -0
- data/bin/packo-db +24 -0
- data/bin/packo-env +24 -0
- data/bin/packo-files +24 -0
- data/bin/packo-profile +24 -0
- data/bin/packo-repository +24 -0
- data/bin/packo-select +24 -0
- data/lib/packo.rb +186 -0
- data/lib/packo/cli.rb +79 -0
- data/lib/packo/cli/base.rb +554 -0
- data/lib/packo/cli/build.rb +488 -0
- data/lib/packo/cli/database.rb +55 -0
- data/lib/packo/cli/database/definition.rb +65 -0
- data/lib/packo/cli/database/helpers.rb +20 -0
- data/lib/packo/cli/environment.rb +45 -0
- data/lib/packo/cli/files.rb +153 -0
- data/lib/packo/cli/profile.rb +31 -0
- data/lib/packo/cli/repository.rb +561 -0
- data/lib/packo/cli/repository/binary.rb +74 -0
- data/lib/packo/cli/repository/helpers.rb +20 -0
- data/lib/packo/cli/repository/repository.rb +48 -0
- data/lib/packo/cli/repository/source.rb +91 -0
- data/lib/packo/cli/repository/virtual.rb +53 -0
- data/lib/packo/cli/select.rb +61 -0
- data/lib/packo/do.rb +249 -0
- data/lib/packo/environment.rb +269 -0
- data/lib/packo/extensions.rb +70 -0
- data/lib/packo/flags.rb +64 -0
- data/lib/packo/host.rb +121 -0
- data/lib/packo/models.rb +171 -0
- data/lib/packo/models/installed_package.rb +190 -0
- data/lib/packo/models/installed_package/content.rb +50 -0
- data/lib/packo/models/installed_package/dependency.rb +39 -0
- data/lib/packo/models/repository.rb +209 -0
- data/lib/packo/models/repository/binary.rb +32 -0
- data/lib/packo/models/repository/binary/mirror.rb +35 -0
- data/lib/packo/models/repository/package.rb +73 -0
- data/lib/packo/models/repository/package/binary.rb +34 -0
- data/lib/packo/models/repository/package/binary/build.rb +36 -0
- data/lib/packo/models/repository/package/source.rb +36 -0
- data/lib/packo/models/repository/package/source/feature.rb +36 -0
- data/lib/packo/models/repository/package/source/flavor.rb +36 -0
- data/lib/packo/models/repository/package/virtual.rb +32 -0
- data/lib/packo/models/repository/source.rb +30 -0
- data/lib/packo/models/repository/virtual.rb +30 -0
- data/lib/packo/models/selector.rb +34 -0
- data/lib/packo/models/tag.rb +30 -0
- data/lib/packo/package.rb +239 -0
- data/lib/packo/package/blocker.rb +100 -0
- data/lib/packo/package/blockers.rb +40 -0
- data/lib/packo/package/dependencies.rb +40 -0
- data/lib/packo/package/dependency.rb +100 -0
- data/lib/packo/package/feature.rb +55 -0
- data/lib/packo/package/features.rb +105 -0
- data/lib/packo/package/flavor.rb +101 -0
- data/lib/packo/package/tags.rb +60 -0
- data/lib/packo/package/tags/expression.rb +130 -0
- data/lib/packo/package/tags/expression/group.rb +28 -0
- data/lib/packo/package/tags/expression/logic.rb +48 -0
- data/lib/packo/package/tags/expression/name.rb +28 -0
- data/lib/packo/profile.rb +174 -0
- data/lib/packo/rbuild.rb +22 -0
- data/lib/packo/rbuild/behaviors.rb +20 -0
- data/lib/packo/rbuild/behaviors/default.rb +27 -0
- data/lib/packo/rbuild/feature.rb +64 -0
- data/lib/packo/rbuild/features.rb +65 -0
- data/lib/packo/rbuild/flavor.rb +67 -0
- data/lib/packo/rbuild/module.rb +40 -0
- data/lib/packo/rbuild/modules.rb +27 -0
- data/lib/packo/rbuild/modules/building.rb +24 -0
- data/lib/packo/rbuild/modules/building/autotools.rb +315 -0
- data/lib/packo/rbuild/modules/building/cmake.rb +38 -0
- data/lib/packo/rbuild/modules/building/patch.rb +84 -0
- data/lib/packo/rbuild/modules/building/rake.rb +74 -0
- data/lib/packo/rbuild/modules/building/strip.rb +41 -0
- data/lib/packo/rbuild/modules/misc.rb +26 -0
- data/lib/packo/rbuild/modules/misc/fetcher.rb +177 -0
- data/lib/packo/rbuild/modules/misc/fetching.rb +22 -0
- data/lib/packo/rbuild/modules/misc/fetching/git.rb +57 -0
- data/lib/packo/rbuild/modules/misc/fetching/github.rb +31 -0
- data/lib/packo/rbuild/modules/misc/fetching/gnu.rb +59 -0
- data/lib/packo/rbuild/modules/misc/fetching/mercurial.rb +51 -0
- data/lib/packo/rbuild/modules/misc/fetching/sourceforge.rb +47 -0
- data/lib/packo/rbuild/modules/misc/fetching/subversion.rb +51 -0
- data/lib/packo/rbuild/modules/misc/fetching/wget.rb +57 -0
- data/lib/packo/rbuild/modules/misc/unpacker.rb +70 -0
- data/lib/packo/rbuild/modules/misc/unpacking.rb +23 -0
- data/lib/packo/rbuild/modules/misc/unpacking/lzma.rb +34 -0
- data/lib/packo/rbuild/modules/misc/unpacking/tar.rb +35 -0
- data/lib/packo/rbuild/modules/misc/unpacking/xz.rb +34 -0
- data/lib/packo/rbuild/modules/misc/unpacking/zip.rb +26 -0
- data/lib/packo/rbuild/modules/packaging.rb +20 -0
- data/lib/packo/rbuild/modules/packaging/pko.rb +78 -0
- data/lib/packo/rbuild/package.rb +281 -0
- data/lib/packo/rbuild/package/manifest.rb +169 -0
- data/lib/packo/rbuild/stages.rb +171 -0
- data/lib/packo/rbuild/stages/callbacks.rb +96 -0
- data/lib/packo/rbuild/stages/stage.rb +50 -0
- data/lib/packo/repository.rb +95 -0
- data/lib/packo/repository/binary.rb +116 -0
- data/lib/packo/repository/source.rb +77 -0
- data/lib/packo/repository/virtual.rb +66 -0
- data/lib/packo/system.rb +53 -0
- data/lib/packo/version.rb +26 -0
- metadata +276 -0
data/lib/packo/cli.rb
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
#--
|
|
2
|
+
# Copyleft meh. [http://meh.doesntexist.org | meh@paranoici.org]
|
|
3
|
+
#
|
|
4
|
+
# This file is part of packo.
|
|
5
|
+
#
|
|
6
|
+
# packo is free software: you can redistribute it and/or modify
|
|
7
|
+
# it under the terms of the GNU Affero General Public License as published
|
|
8
|
+
# by the Free Software Foundation, either version 3 of the License, or
|
|
9
|
+
# (at your option) any later version.
|
|
10
|
+
#
|
|
11
|
+
# packo is distributed in the hope that it will be useful,
|
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
14
|
+
# GNU Affero General Public License for more details.
|
|
15
|
+
#
|
|
16
|
+
# You should have received a copy of the GNU Affero General Public License
|
|
17
|
+
# along with packo. If not, see <http://www.gnu.org/licenses/>.
|
|
18
|
+
#++
|
|
19
|
+
|
|
20
|
+
require 'thor'
|
|
21
|
+
require 'colorb'
|
|
22
|
+
|
|
23
|
+
class Thor
|
|
24
|
+
class << self
|
|
25
|
+
def help(shell, subcommand = false)
|
|
26
|
+
list = printable_tasks(true, subcommand)
|
|
27
|
+
Thor::Util.thor_classes_in(self).each do |klass|
|
|
28
|
+
list += klass.printable_tasks(false)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
shell.say 'Commands:'
|
|
32
|
+
shell.print_table(list, ident: 2, truncate: true)
|
|
33
|
+
shell.say
|
|
34
|
+
class_options_help(shell)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
module Base
|
|
39
|
+
module ClassMethods
|
|
40
|
+
def handle_no_task_error(task) #:nodoc:
|
|
41
|
+
if $thor_runner
|
|
42
|
+
raise UndefinedTaskError, "Could not find command #{task.inspect} in #{namespace.inspect} namespace."
|
|
43
|
+
else
|
|
44
|
+
raise UndefinedTaskError, "Could not find command #{task.inspect}."
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
module Packo
|
|
52
|
+
|
|
53
|
+
module CLI
|
|
54
|
+
def self.info (text)
|
|
55
|
+
puts "#{'*'.green.bold} #{text}"
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def self.warn (text)
|
|
59
|
+
puts "#{'*'.yellow.bold} #{text}"
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def self.fatal (text)
|
|
63
|
+
puts "#{'*'.red} #{text}"
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
['INT', 'QUIT', 'ABRT', 'TERM', 'TSTP'].each {|sig|
|
|
70
|
+
trap sig do
|
|
71
|
+
if defined?(Packo::Models)
|
|
72
|
+
Packo::Models.transactions.each {|t| t.rollback}
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
puts 'Aborting.'
|
|
76
|
+
|
|
77
|
+
Process.exit! 0
|
|
78
|
+
end
|
|
79
|
+
}
|
|
@@ -0,0 +1,554 @@
|
|
|
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 'packo'
|
|
22
|
+
require 'packo/models'
|
|
23
|
+
require 'packo/rbuild'
|
|
24
|
+
|
|
25
|
+
module Packo; module CLI
|
|
26
|
+
|
|
27
|
+
class Base < Thor
|
|
28
|
+
include Thor::Actions
|
|
29
|
+
|
|
30
|
+
class_option :help, type: :boolean, desc: 'Show help usage'
|
|
31
|
+
|
|
32
|
+
desc 'install PACKAGE... [OPTIONS]', 'Install packages'
|
|
33
|
+
map '-i' => :install, '--install' => :install
|
|
34
|
+
method_option :destination, type: :string, default: System.env[:INSTALL_PATH], aliases: '-d', desc: 'Set the destination where to install the package'
|
|
35
|
+
method_option :inherit, type: :boolean, default: false, aliases: '-I', desc: 'Apply the passed flags to the eventual dependencies'
|
|
36
|
+
method_option :force, type: :boolean, default: false, aliases: '-f', desc: 'Force installation when something minor goes wrong'
|
|
37
|
+
method_option :ignore, type: :boolean, default: false, aliases: '-x', desc: 'Ignore the installation and do not add the package to the database'
|
|
38
|
+
method_option :nodeps, type: :boolean, default: false, aliases: '-N', desc: 'Ignore blockers and dependencies'
|
|
39
|
+
method_option :depsonly, type: :boolean, default: false, aliases: '-D', desc: 'Install only dependencies'
|
|
40
|
+
method_option :repository, type: :string, aliases: '-r', desc: 'Set a specific repository'
|
|
41
|
+
def install (*names)
|
|
42
|
+
type = names.last.is_a?(Symbol) ? names.pop : :both
|
|
43
|
+
|
|
44
|
+
FileUtils.mkpath options[:destination] rescue nil
|
|
45
|
+
FileUtils.mkpath System.env[:SELECTORS] rescue nil
|
|
46
|
+
|
|
47
|
+
binary = false
|
|
48
|
+
|
|
49
|
+
if names.last === true
|
|
50
|
+
manual = names.shift ? 0 : 1
|
|
51
|
+
else
|
|
52
|
+
manual = 1
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
names.each {|name|
|
|
56
|
+
CLI.info "Installing #{name}"
|
|
57
|
+
|
|
58
|
+
if File.extname(name).empty?
|
|
59
|
+
packages = nil
|
|
60
|
+
|
|
61
|
+
if System.env[:FLAVOR].include?('binary')
|
|
62
|
+
packages = Models.search(name, options[:repository], :binary)
|
|
63
|
+
|
|
64
|
+
if packages.empty?
|
|
65
|
+
CLI.warn "#{name} could not be found in the binary repositories, looking in source repositories"
|
|
66
|
+
packages = nil
|
|
67
|
+
else
|
|
68
|
+
binary = true
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
begin
|
|
73
|
+
if !packages
|
|
74
|
+
packages = Models.search(name, options[:repository], :source)
|
|
75
|
+
|
|
76
|
+
binary = false
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
names = packages.group_by {|package|
|
|
80
|
+
"#{package.tags}/#{package.name}"
|
|
81
|
+
}.map {|(name, package)| name}.uniq
|
|
82
|
+
|
|
83
|
+
if names.length > 1
|
|
84
|
+
CLI.fatal "More than one package matches: #{name}"
|
|
85
|
+
names.each {|name|
|
|
86
|
+
puts " #{name}"
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
exit 10
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
package = packages.sort {|a, b|
|
|
93
|
+
a.version <=> b.version
|
|
94
|
+
}.last
|
|
95
|
+
|
|
96
|
+
if !package
|
|
97
|
+
CLI.fatal "#{name} not found"
|
|
98
|
+
exit 11
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
env = Environment.new(package)
|
|
102
|
+
|
|
103
|
+
if package.repository.type == :binary && !_has(package, env)
|
|
104
|
+
CLI.warn 'The binary package is not available with the features you asked for, trying to build from source'
|
|
105
|
+
packages = nil
|
|
106
|
+
raise ArgumentError
|
|
107
|
+
end
|
|
108
|
+
rescue ArgumentError
|
|
109
|
+
retry
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
case package.repository.type
|
|
113
|
+
when :binary
|
|
114
|
+
name = "#{package.tags.to_s(true)}/#{package.name}-#{package.version}"
|
|
115
|
+
|
|
116
|
+
flavor = ''
|
|
117
|
+
env[:FLAVOR].split(/\s+/).reject {|f| f == 'binary'}.each {|f|
|
|
118
|
+
flavor << ".#{f}"
|
|
119
|
+
}
|
|
120
|
+
flavor[0, 1] = ''
|
|
121
|
+
|
|
122
|
+
features = ''
|
|
123
|
+
env[:FEATURES].split(/\s+/).each {|f|
|
|
124
|
+
features << "-#{f}"
|
|
125
|
+
}
|
|
126
|
+
features[0, 1] = ''
|
|
127
|
+
|
|
128
|
+
name << "%#{package.slot}"
|
|
129
|
+
name << "+#{flavor}"
|
|
130
|
+
name << "-#{features}"
|
|
131
|
+
name << ".pko"
|
|
132
|
+
|
|
133
|
+
FileUtils.mkpath(File.dirname("#{env[:TMP]}/#{name}")) rescue nil
|
|
134
|
+
|
|
135
|
+
begin
|
|
136
|
+
Packo.sh 'wget', '-c', '-O', "#{env[:TMP]}/#{name}", "#{_uri(package.repository)}/#{name}"
|
|
137
|
+
rescue RuntimeError
|
|
138
|
+
FileUtils.rm "#{env[:TMP]}/#{name}"
|
|
139
|
+
CLI.fatal "Failed to download #{name}"
|
|
140
|
+
exit 12
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
name = "#{env[:TMP]}/#{name}"
|
|
144
|
+
|
|
145
|
+
if (digest = _digest(package, env)) && (result = Do.digest(name)) != digest
|
|
146
|
+
CLI.fatal "Digest mismatch (got #{result} expected #{digest}), install this package from source, the mirror could be compromised"
|
|
147
|
+
exit 13
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
path = "#{env[:TMP]}/.__packo_unpacked/#{name[env[:TMP].length, name.length]}"
|
|
151
|
+
|
|
152
|
+
when :source
|
|
153
|
+
manifest = RBuild::Package::Manifest.parse(_manifest(package, env))
|
|
154
|
+
|
|
155
|
+
unless options[:nodeps] || System.env[:NODEPS]
|
|
156
|
+
manifest.blockers {|blocker|
|
|
157
|
+
if blocker.build? && System.has?(blocker)
|
|
158
|
+
CLI.fatal "#{blocker} can't be installed with #{package}"
|
|
159
|
+
exit 16
|
|
160
|
+
end
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
manifest.dependencies.each {|dependency|
|
|
164
|
+
if dependency.build? && !System.has?(dependency)
|
|
165
|
+
install(dependency.to_s, dependency.type)
|
|
166
|
+
end
|
|
167
|
+
}
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
if options[:depsonly]
|
|
171
|
+
exit 0
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
name = _build(package, env)
|
|
175
|
+
|
|
176
|
+
if !name
|
|
177
|
+
CLI.fatal "Something went wrong while trying to build #{package.to_s(:whole)}"
|
|
178
|
+
exit 14
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
path = "#{env[:TMP]}/.__packo_unpacked/#{package.tags.to_s(true)}/#{name[env[:TMP].length + '.__packo_build/'.length, name.length]}"
|
|
182
|
+
end
|
|
183
|
+
else
|
|
184
|
+
path = "#{System.env[:TMP]}/.__packo_unpacked/#{File.basename(name)}"
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
FileUtils.rm_rf path, secure: true
|
|
188
|
+
|
|
189
|
+
case File.extname(name)
|
|
190
|
+
when '.pko'
|
|
191
|
+
RBuild::Modules::Packaging::PKO.unpack(File.realpath(name), path)
|
|
192
|
+
|
|
193
|
+
manifest = RBuild::Package::Manifest.open("#{path}/manifest.xml")
|
|
194
|
+
|
|
195
|
+
else
|
|
196
|
+
CLI.fatal 'Unknown package type'
|
|
197
|
+
exit 15
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
package = Packo::Package.new(manifest.package.to_hash)
|
|
201
|
+
|
|
202
|
+
if !options[:inherit]
|
|
203
|
+
Environment[:FLAVOR] = Environment[:FEATURES] = ''
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
unless options[:nodeps] || System.env[:NODEPS]
|
|
207
|
+
manifest.blockers {|blocker|
|
|
208
|
+
if blocker.runtime? && System.has?(blocker)
|
|
209
|
+
CLI.fatal "#{blocker} can't be installed with #{package}"
|
|
210
|
+
exit 16
|
|
211
|
+
end
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
manifest.dependencies.each {|dependency|
|
|
215
|
+
if !System.has?(dependency) && dependency.runtime?
|
|
216
|
+
install(dependency.to_s, dependency.type)
|
|
217
|
+
end
|
|
218
|
+
}
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
if options[:depsonly]
|
|
222
|
+
exit 0
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
if System.has?(package)
|
|
226
|
+
uninstall(package.to_s(:whole)) rescue nil
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
manifest.selectors.each {|selector|
|
|
230
|
+
FileUtils.mkpath System.env[:SELECTORS]
|
|
231
|
+
FileUtils.cp_r "#{path}/selectors/#{selector.path}", System.env[:SELECTORS], preserve: true, remove_destination: true
|
|
232
|
+
Packo.sh 'packo-select', 'add', selector.name, selector.description, "#{System.env[:SELECTORS]}/#{selector.path}", silent: true
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
Models.transaction {|t|
|
|
236
|
+
pkg = Models::InstalledPackage.first_or_new(
|
|
237
|
+
tags_hashed: manifest.package.tags.hashed,
|
|
238
|
+
name: manifest.package.name,
|
|
239
|
+
slot: manifest.package.slot
|
|
240
|
+
)
|
|
241
|
+
|
|
242
|
+
pkg.attributes = {
|
|
243
|
+
repo: options[:repository],
|
|
244
|
+
|
|
245
|
+
version: manifest.package.version,
|
|
246
|
+
revision: manifest.package.revision,
|
|
247
|
+
|
|
248
|
+
flavor: manifest.package.flavor,
|
|
249
|
+
features: manifest.package.features,
|
|
250
|
+
|
|
251
|
+
description: manifest.package.description,
|
|
252
|
+
homepage: manifest.package.homepage,
|
|
253
|
+
license: manifest.package.license,
|
|
254
|
+
|
|
255
|
+
manual: manual,
|
|
256
|
+
type: type
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
pkg.save
|
|
260
|
+
|
|
261
|
+
manifest.package.tags.each {|tag|
|
|
262
|
+
pkg.tags.first_or_create(name: tag.to_s)
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
length = "#{path}/dist/".length
|
|
266
|
+
old = path
|
|
267
|
+
|
|
268
|
+
begin
|
|
269
|
+
Find.find("#{path}/dist") {|file|
|
|
270
|
+
next unless file[length, file.length]
|
|
271
|
+
|
|
272
|
+
type = nil
|
|
273
|
+
path = (options[:destination] + file[length, file.length]).cleanpath.to_s
|
|
274
|
+
fake = path[options[:destination].cleanpath.to_s.length, path.length] || ''
|
|
275
|
+
meta = nil
|
|
276
|
+
|
|
277
|
+
if !options[:force] && File.exists?(path) && !File.directory?(path)
|
|
278
|
+
if (tmp = _exists?(fake))
|
|
279
|
+
CLI.fatal "#{path} belongs to #{tmp}, use --force to overwrite"
|
|
280
|
+
else
|
|
281
|
+
CLI.fatal "#{path} doesn't belong to any package, use --force to overwrite"
|
|
282
|
+
end
|
|
283
|
+
|
|
284
|
+
raise RuntimeError.new 'File collision'
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
if File.directory?(file)
|
|
288
|
+
type = :dir
|
|
289
|
+
|
|
290
|
+
begin
|
|
291
|
+
FileUtils.mkpath(path)
|
|
292
|
+
puts "--- #{path if path != '/'}/"
|
|
293
|
+
rescue
|
|
294
|
+
puts "--- #{path if path != '/'}/".red
|
|
295
|
+
end
|
|
296
|
+
elsif File.symlink?(file)
|
|
297
|
+
type = :sym
|
|
298
|
+
meta = File.readlink(file)
|
|
299
|
+
|
|
300
|
+
begin
|
|
301
|
+
FileUtils.ln_sf meta, path
|
|
302
|
+
puts ">>> #{path} -> #{meta}".cyan.bold
|
|
303
|
+
rescue
|
|
304
|
+
puts ">>> #{path} -> #{meta}".red
|
|
305
|
+
end
|
|
306
|
+
elsif File.file?(file)
|
|
307
|
+
type = :obj
|
|
308
|
+
meta = Do.digest(file)
|
|
309
|
+
|
|
310
|
+
begin
|
|
311
|
+
FileUtils.cp file, path, preserve: true
|
|
312
|
+
puts ">>> #{path}".bold
|
|
313
|
+
rescue
|
|
314
|
+
puts ">>> #{path}".red
|
|
315
|
+
end
|
|
316
|
+
else
|
|
317
|
+
next
|
|
318
|
+
end
|
|
319
|
+
|
|
320
|
+
content = pkg.contents.first_or_create(
|
|
321
|
+
type: type,
|
|
322
|
+
path: fake
|
|
323
|
+
)
|
|
324
|
+
|
|
325
|
+
content.update(
|
|
326
|
+
meta: meta
|
|
327
|
+
)
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
pkg.save
|
|
331
|
+
rescue Exception => e
|
|
332
|
+
CLI.fatal 'Something went deeply wrong while installing package contents'
|
|
333
|
+
Packo.debug e
|
|
334
|
+
|
|
335
|
+
pkg.contents.each {|content| content.check!
|
|
336
|
+
path = "#{installed.model.destination}/#{content.path}".gsub(%r{/*/}, '/')
|
|
337
|
+
|
|
338
|
+
case content.type
|
|
339
|
+
when :obj
|
|
340
|
+
if File.exists?(path) && (options[:force] || content.meta == Do.digest(path))
|
|
341
|
+
puts "<<< #{path}".bold
|
|
342
|
+
FileUtils.rm_f(path) rescue nil
|
|
343
|
+
else
|
|
344
|
+
puts "=== #{path}".red
|
|
345
|
+
end
|
|
346
|
+
|
|
347
|
+
when :sym
|
|
348
|
+
if File.exists?(path) && (options[:force] || !File.exists?(path) || content.meta == File.readlink(path))
|
|
349
|
+
puts "<<< #{path} -> #{content.meta}".cyan.bold
|
|
350
|
+
FileUtils.rm_f(path) rescue nil
|
|
351
|
+
else
|
|
352
|
+
puts "=== #{path} -> #{File.readlink(path)}".red
|
|
353
|
+
end
|
|
354
|
+
|
|
355
|
+
when :dir
|
|
356
|
+
puts "--- #{path if path != '/'}/"
|
|
357
|
+
end
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
pkg.contents.all(type: :dir, order: [:path.desc]).each {|content|
|
|
361
|
+
path = "#{options[:destination]}/#{content.path}".gsub(%r{/*/}, '/')
|
|
362
|
+
|
|
363
|
+
Dir.delete(path) rescue nil
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
t.rollback
|
|
367
|
+
|
|
368
|
+
exit 17
|
|
369
|
+
end
|
|
370
|
+
|
|
371
|
+
if options[:ignore]
|
|
372
|
+
t.rollback
|
|
373
|
+
else
|
|
374
|
+
pkg.update(destination: options[:destination].cleanpath)
|
|
375
|
+
end
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
end
|
|
379
|
+
|
|
380
|
+
desc 'uninstall PACKAGE... [OPTIONS]', 'Uninstall packages'
|
|
381
|
+
map '-C' => :uninstall, '-R' => :uninstall, 'remove' => :uninstall
|
|
382
|
+
method_option :force, type: :boolean, default: false, aliases: '-f', desc: 'Force installation when something minor goes wrong'
|
|
383
|
+
def uninstall (*names)
|
|
384
|
+
names.each {|name|
|
|
385
|
+
packages = Models.search_installed(name)
|
|
386
|
+
|
|
387
|
+
if packages.empty?
|
|
388
|
+
CLI.fatal "No installed packages match #{name}"
|
|
389
|
+
exit 20
|
|
390
|
+
end
|
|
391
|
+
|
|
392
|
+
packages.each {|installed|
|
|
393
|
+
Models.transaction {
|
|
394
|
+
installed.model.contents.each {|content| content.check!
|
|
395
|
+
path = "#{installed.model.destination}/#{content.path}".gsub(%r{/*/}, '/')
|
|
396
|
+
|
|
397
|
+
case content.type
|
|
398
|
+
when :obj
|
|
399
|
+
if File.exists?(path) && (options[:force] || content.meta == Do.digest(path))
|
|
400
|
+
puts "<<< #{path}".bold
|
|
401
|
+
FileUtils.rm_f(path) rescue nil
|
|
402
|
+
else
|
|
403
|
+
puts "=== #{path}".red
|
|
404
|
+
end
|
|
405
|
+
|
|
406
|
+
when :sym
|
|
407
|
+
if File.exists?(path) && (options[:force] || !File.exists?(path) || content.meta == File.readlink(path))
|
|
408
|
+
puts "<<< #{path} -> #{content.meta}".cyan.bold
|
|
409
|
+
FileUtils.rm_f(path) rescue nil
|
|
410
|
+
else
|
|
411
|
+
puts "=== #{path} -> #{File.readlink(path)}".red
|
|
412
|
+
end
|
|
413
|
+
|
|
414
|
+
when :dir
|
|
415
|
+
puts "--- #{path if path != '/'}/"
|
|
416
|
+
end
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
installed.model.contents.all(type: :dir, order: [:path.desc]).each {|content|
|
|
420
|
+
path = "#{options[:destination]}/#{content.path}".gsub(%r{/*/}, '/')
|
|
421
|
+
|
|
422
|
+
Dir.delete(path) rescue nil
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
installed.model.destroy
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
end
|
|
430
|
+
|
|
431
|
+
desc 'search [EXPRESSION] [OPTIONS]', 'Search through installed packages'
|
|
432
|
+
map '--search' => :search, '-Ss' => :search
|
|
433
|
+
method_option :type, type: :string, aliases: '-t', desc: 'The repository type (binary, source, virtual)'
|
|
434
|
+
method_option :repository, type: :string, aliases: '-r', desc: 'Set a specific repository'
|
|
435
|
+
method_option :full, type: :boolean, default: false, aliases: '-F', desc: 'Include the repository that owns the package, features and flavor'
|
|
436
|
+
def search (expression='')
|
|
437
|
+
Models.search_installed(expression, options[:repository], options[:type]).group_by {|package|
|
|
438
|
+
"#{package.tags}/#{package.name}"
|
|
439
|
+
}.sort.each {|(name, packages)|
|
|
440
|
+
if options[:full]
|
|
441
|
+
packages.group_by {|package|
|
|
442
|
+
"#{package.repository.type}/#{package.repository.name}" rescue nil
|
|
443
|
+
}.each {|name, packages|
|
|
444
|
+
packages.group_by {|package|
|
|
445
|
+
"#{package.features} #{package.flavor}"
|
|
446
|
+
}.each {|name, packages|
|
|
447
|
+
print "#{"#{packages.first.tags}/" unless packages.first.tags.empty?}#{packages.first.name.bold}"
|
|
448
|
+
|
|
449
|
+
print ' ('
|
|
450
|
+
print packages.map {|package|
|
|
451
|
+
"#{package.version.to_s.red}" + (package.slot ? "%#{package.slot.to_s.blue.bold}" : '')
|
|
452
|
+
}.join(', ')
|
|
453
|
+
print ')'
|
|
454
|
+
|
|
455
|
+
print " [#{packages.first.features}]" unless packages.first.features.empty?
|
|
456
|
+
print " {#{packages.first.flavor}}" unless packages.first.flavor.empty?
|
|
457
|
+
|
|
458
|
+
print " <#{"#{packages.first.repository.type}/#{packages.first.repository.name}".black.bold}>" if packages.first.repository
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
else
|
|
462
|
+
print "#{packages.first.tags}/#{packages.first.name.bold} ("
|
|
463
|
+
|
|
464
|
+
print packages.map {|package|
|
|
465
|
+
"#{package.version.to_s.red}" + (package.slot ? "%#{package.slot.to_s.blue.bold}" : '')
|
|
466
|
+
}.join(', ')
|
|
467
|
+
|
|
468
|
+
print ")"
|
|
469
|
+
end
|
|
470
|
+
|
|
471
|
+
print "\n"
|
|
472
|
+
}
|
|
473
|
+
end
|
|
474
|
+
|
|
475
|
+
desc 'info [EXPRESSION] [OPTIONS]', 'Search through installed packages and returns detailed informations about them'
|
|
476
|
+
map '--info' => :info
|
|
477
|
+
method_option :type, type: :string, aliases: '-t', desc: 'The repository type (binary, source, virtual)'
|
|
478
|
+
method_option :repository, type: :string, aliases: '-r', desc: 'Set a specific repository'
|
|
479
|
+
def info (expression='')
|
|
480
|
+
Models.search_installed(expression, options[:repository], options[:type]).each {|package|
|
|
481
|
+
print package.name.bold
|
|
482
|
+
print "-#{package.version.to_s.red}"
|
|
483
|
+
print " {#{package.revision.yellow.bold}}" if package.revision > 0
|
|
484
|
+
print " (#{package.slot.to_s.blue.bold})" if package.slot
|
|
485
|
+
print " [#{package.tags.join(' ').magenta}]" if !package.tags.empty?
|
|
486
|
+
print "\n"
|
|
487
|
+
|
|
488
|
+
puts " #{'Description'.green}: #{package.description}" if package.description
|
|
489
|
+
puts " #{'Homepage'.green}: #{package.homepage}" if package.homepage
|
|
490
|
+
puts " #{'License'.green}: #{package.license}" if package.license
|
|
491
|
+
puts " #{'Maintainer'.green}: #{package.model.maintainer}" if package.maintainer
|
|
492
|
+
puts " #{'Flavor'.green}: #{package.flavor}" if package.flavor
|
|
493
|
+
puts " #{'Features'.green}: #{package.features}" if package.features
|
|
494
|
+
|
|
495
|
+
print "\n"
|
|
496
|
+
}
|
|
497
|
+
end
|
|
498
|
+
|
|
499
|
+
private
|
|
500
|
+
|
|
501
|
+
def _uri (repository)
|
|
502
|
+
Repository.first(Packo::Repository.parse(name).to_hash).URI rescue nil
|
|
503
|
+
end
|
|
504
|
+
|
|
505
|
+
def _build (package, env)
|
|
506
|
+
Do.cd {
|
|
507
|
+
FileUtils.rm_rf "#{System.env[:TMP]}/.__packo_build", secure: true rescue nil
|
|
508
|
+
FileUtils.mkpath "#{System.env[:TMP]}/.__packo_build" rescue nil
|
|
509
|
+
|
|
510
|
+
require 'packo/cli/build'
|
|
511
|
+
|
|
512
|
+
begin
|
|
513
|
+
System.env.sandbox(env) {
|
|
514
|
+
Packo::CLI::Build.start(['package', package.to_s(:whole), "--output=#{System.env[:TMP]}/.__packo_build", "--repository=#{package.repository}"])
|
|
515
|
+
}
|
|
516
|
+
rescue
|
|
517
|
+
end
|
|
518
|
+
|
|
519
|
+
Dir.glob("#{System.env[:TMP]}/.__packo_build/#{package.name}-#{package.version}*.pko").first
|
|
520
|
+
}
|
|
521
|
+
end
|
|
522
|
+
|
|
523
|
+
def _manifest (package, env)
|
|
524
|
+
tmp = Models.search(package.to_s, options[:repository])
|
|
525
|
+
|
|
526
|
+
RBuild::Package::Manifest.new(
|
|
527
|
+
Packo.loadPackage("#{tmp.last.repository.path}/#{tmp.last.model.data.path}", tmp.last)
|
|
528
|
+
).to_s
|
|
529
|
+
end
|
|
530
|
+
|
|
531
|
+
def _has (package, env)
|
|
532
|
+
!!Models.search(package.to_s(:whole), package.repository.name, package.repository.type).find {|package|
|
|
533
|
+
!!package.model.data.builds.to_a.find {|build|
|
|
534
|
+
build.features.split(/\s+/).sort == env[:FEATURES].split(/\s+/).sort && \
|
|
535
|
+
build.flavor.split(/\s+/).sort == env[:FLAVOR].split(/\s+/).sort
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
end
|
|
539
|
+
|
|
540
|
+
def _digest (package, env)
|
|
541
|
+
Models.search(package, package.repository.name, :binary).find {|package|
|
|
542
|
+
package.model.data.builds.to_a.find {|build|
|
|
543
|
+
build.features.split(/\s+/).sort == env[:FEATURES].split(/\s+/).sort && \
|
|
544
|
+
build.flavor.split(/\s+/).sort == env[:FLAVOR].split(/\s+/).sort
|
|
545
|
+
}
|
|
546
|
+
}.model.data.digest
|
|
547
|
+
end
|
|
548
|
+
|
|
549
|
+
def _exists? (path)
|
|
550
|
+
Models::InstalledPackage::Content.first(path: path, :type.not => :dir).package rescue false
|
|
551
|
+
end
|
|
552
|
+
end
|
|
553
|
+
|
|
554
|
+
end; end
|