dr 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.
- data/.gitignore +19 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +339 -0
- data/README.md +29 -0
- data/Rakefile +1 -0
- data/bin/dr +276 -0
- data/dr.spec +30 -0
- data/lib/dr.rb +6 -0
- data/lib/dr/buildroot.rb +103 -0
- data/lib/dr/config.rb +44 -0
- data/lib/dr/debpackage.rb +24 -0
- data/lib/dr/gitpackage.rb +252 -0
- data/lib/dr/gnupg.rb +74 -0
- data/lib/dr/logger.rb +80 -0
- data/lib/dr/package.rb +26 -0
- data/lib/dr/pkgversion.rb +69 -0
- data/lib/dr/repo.rb +300 -0
- data/lib/dr/shellcmd.rb +67 -0
- data/lib/dr/version.rb +3 -0
- metadata +149 -0
data/lib/dr/gnupg.rb
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
require "dr/shellcmd"
|
2
|
+
require "dr/logger"
|
3
|
+
|
4
|
+
module Dr
|
5
|
+
class GnuPG
|
6
|
+
include Logger
|
7
|
+
|
8
|
+
def initialize(keyring)
|
9
|
+
@keyring = keyring
|
10
|
+
|
11
|
+
# initialise the keyring
|
12
|
+
FileUtils.mkdir_p @keyring
|
13
|
+
FileUtils.chmod_R 0700, @keyring
|
14
|
+
end
|
15
|
+
|
16
|
+
def generate_key(name, mail, pass)
|
17
|
+
#kill_rngd = false
|
18
|
+
#unless File.exists? "/var/run/rngd.pid"
|
19
|
+
# print "Starting rngd (root permissions required) ... "
|
20
|
+
# Kernel.system "sudo rngd -p #{@keyring}/rngd.pid -r /dev/urandom"
|
21
|
+
# kill_rngd = true
|
22
|
+
# puts "[OK]"
|
23
|
+
#end
|
24
|
+
|
25
|
+
log(:info, tag("gpg", "Generating the GPG key"))
|
26
|
+
|
27
|
+
passphrase = "Passphrase: #{pass}" if pass.length > 0
|
28
|
+
cmd = <<-END
|
29
|
+
gpg --batch --gen-key --homedir #{@keyring} <<EOF
|
30
|
+
Key-Type: RSA
|
31
|
+
Key-Length: 2048
|
32
|
+
Subkey-Type: ELG-E
|
33
|
+
Subkey-Length: 2048
|
34
|
+
Name-Real: #{name}
|
35
|
+
Name-Email: #{mail}
|
36
|
+
#{passphrase}
|
37
|
+
Expire-Date: 0
|
38
|
+
%commit
|
39
|
+
EOF
|
40
|
+
END
|
41
|
+
# TODO: Add timeout to this one
|
42
|
+
gpg_cmd = ShellCmd.new cmd, :tag => "gpg"
|
43
|
+
|
44
|
+
cmd = "gpg --list-keys --with-colons --homedir #{@keyring}"
|
45
|
+
gpg_cmd = ShellCmd.new cmd, :tag => "gpg"
|
46
|
+
key_list = gpg_cmd.out.split "\n"
|
47
|
+
key_entry = key_list.grep(/^pub/).grep(/#{name}/).grep(/#{mail}/)
|
48
|
+
key = key_entry[0].split(":")[4][8..-1]
|
49
|
+
|
50
|
+
log(:info, tag("gpg", "Key done"))
|
51
|
+
|
52
|
+
#if kill_rngd
|
53
|
+
# print "Stopping rngd (root permissions required) ... "
|
54
|
+
# Kernel.system "sudo kill `cat #{@keyring}/rngd.pid`"
|
55
|
+
# Kernel.system "sudo rm -f #{@keyring}/rngd.pid"
|
56
|
+
# puts "[OK]"
|
57
|
+
#end
|
58
|
+
|
59
|
+
key
|
60
|
+
end
|
61
|
+
|
62
|
+
def get_id
|
63
|
+
end
|
64
|
+
|
65
|
+
def export_pub(key, location)
|
66
|
+
# TODO: Remove the key before exporting (so gpg doesn't ask about it)
|
67
|
+
log(:info, tag("gpg", "Exporting key"))
|
68
|
+
cmd = "gpg --armor --homedir #{@keyring} \
|
69
|
+
--output #{location} \
|
70
|
+
--export #{key}"
|
71
|
+
gpg_cmd = ShellCmd.new cmd, :tag => "gpg"
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
data/lib/dr/logger.rb
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
require "tco"
|
2
|
+
|
3
|
+
tco_conf = Tco::config
|
4
|
+
|
5
|
+
tco_conf.names["green"] = "#99ad6a"
|
6
|
+
tco_conf.names["yellow"] = "#d8ad4c"
|
7
|
+
tco_conf.names["red"] = "#cf6a4c"
|
8
|
+
tco_conf.names["light-grey"] = "#ababab"
|
9
|
+
tco_conf.names["dark-grey"] = "#2b2b2b"
|
10
|
+
tco_conf.names["purple"] = "#90559e"
|
11
|
+
tco_conf.names["blue"] = "#1b8efa"
|
12
|
+
|
13
|
+
tco_conf.styles["info"] = {
|
14
|
+
:fg => "green",
|
15
|
+
:bg => "dark-grey",
|
16
|
+
:bright => false,
|
17
|
+
:underline => false
|
18
|
+
}
|
19
|
+
tco_conf.styles["warn"] = {
|
20
|
+
:fg => "dark-grey",
|
21
|
+
:bg => "yellow",
|
22
|
+
:bright => false,
|
23
|
+
:underline => false
|
24
|
+
}
|
25
|
+
tco_conf.styles["err"] = {
|
26
|
+
:fg => "dark-grey",
|
27
|
+
:bg => "red",
|
28
|
+
:bright => false,
|
29
|
+
:underline => false
|
30
|
+
}
|
31
|
+
|
32
|
+
tco_conf.styles["debug"] = {
|
33
|
+
:fg => "light-grey",
|
34
|
+
:bg => "dark-grey",
|
35
|
+
:bright => false,
|
36
|
+
:underline => false
|
37
|
+
}
|
38
|
+
|
39
|
+
tco_conf.styles["log-head"] = {
|
40
|
+
:fg => "purple",
|
41
|
+
:bg => "dark-grey",
|
42
|
+
:bright => false,
|
43
|
+
:underline => false
|
44
|
+
}
|
45
|
+
|
46
|
+
Tco::reconfigure tco_conf
|
47
|
+
|
48
|
+
module Dr
|
49
|
+
module Logger
|
50
|
+
@@logger_options = {
|
51
|
+
:info => "info",
|
52
|
+
:warn => "warn",
|
53
|
+
:err => "err",
|
54
|
+
:debug => "debug"
|
55
|
+
}
|
56
|
+
|
57
|
+
def self.log(level, msg)
|
58
|
+
out = "dr".style("log-head") << " "
|
59
|
+
|
60
|
+
case level
|
61
|
+
when :info then out << "info".style(@@logger_options[:info])
|
62
|
+
when :warn then out << "WARN".style(@@logger_options[:warn])
|
63
|
+
when :err then out << "ERR!".style(@@logger_options[:err])
|
64
|
+
when :debug then out << "dbg?".style(@@logger_options[:debug])
|
65
|
+
end
|
66
|
+
|
67
|
+
out << " " << msg.chomp
|
68
|
+
puts out
|
69
|
+
STDOUT.flush
|
70
|
+
end
|
71
|
+
|
72
|
+
def log(level, msg)
|
73
|
+
Logger::log level, msg
|
74
|
+
end
|
75
|
+
|
76
|
+
def tag(tag, msg)
|
77
|
+
tag.fg("blue") << " " << msg
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
data/lib/dr/package.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
require "dr/logger"
|
2
|
+
|
3
|
+
module Dr
|
4
|
+
class Package
|
5
|
+
attr_reader :name
|
6
|
+
|
7
|
+
include Logger
|
8
|
+
class << self
|
9
|
+
include Logger
|
10
|
+
end
|
11
|
+
|
12
|
+
def initialize(name, repo)
|
13
|
+
@name = name
|
14
|
+
@repo = repo
|
15
|
+
end
|
16
|
+
|
17
|
+
def history
|
18
|
+
versions = []
|
19
|
+
Dir.foreach "#{@repo.location}/packages/#{name}/builds/" do |v|
|
20
|
+
versions.push v unless v =~ /^\./
|
21
|
+
end
|
22
|
+
|
23
|
+
versions.sort.reverse
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
module Dr
|
2
|
+
class PkgVersion
|
3
|
+
attr_accessor :upstream, :debian, :date, :build
|
4
|
+
|
5
|
+
def initialize(version_string)
|
6
|
+
@upstream = nil
|
7
|
+
@debian = nil
|
8
|
+
@date = nil
|
9
|
+
@build = 0
|
10
|
+
|
11
|
+
v = version_string.split "-"
|
12
|
+
@upstream = v[0] if v.length > 0
|
13
|
+
if v.length > 1
|
14
|
+
dv = v[1].split "."
|
15
|
+
|
16
|
+
@debian = dv[0] if dv.length > 0
|
17
|
+
if dv.length > 1
|
18
|
+
if dv[1] =~ /^[0-9]{8}/
|
19
|
+
@date = dv[1][0..7]
|
20
|
+
end
|
21
|
+
|
22
|
+
match = dv[1].match /build([0-9]+)$/
|
23
|
+
if match
|
24
|
+
@build = match.captures[0]
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def increment!
|
31
|
+
if @date == today
|
32
|
+
@build += 1
|
33
|
+
else
|
34
|
+
@date = today
|
35
|
+
end
|
36
|
+
|
37
|
+
self
|
38
|
+
end
|
39
|
+
|
40
|
+
def ==(o)
|
41
|
+
@upstream == o.upstream && @debian == o.debian &&
|
42
|
+
@date == o.date && @build == o.build
|
43
|
+
end
|
44
|
+
|
45
|
+
def to_s
|
46
|
+
v = @upstream.clone
|
47
|
+
if @debian
|
48
|
+
v << "-#{@debian}"
|
49
|
+
else
|
50
|
+
v << "-0"
|
51
|
+
end
|
52
|
+
|
53
|
+
if @date
|
54
|
+
v << ".#{@date}"
|
55
|
+
else
|
56
|
+
v << ".#{today}"
|
57
|
+
end
|
58
|
+
|
59
|
+
v << "build#{@build}" if @build > 0
|
60
|
+
|
61
|
+
v
|
62
|
+
end
|
63
|
+
|
64
|
+
private
|
65
|
+
def today
|
66
|
+
Time.now.strftime "%Y%m%d"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
data/lib/dr/repo.rb
ADDED
@@ -0,0 +1,300 @@
|
|
1
|
+
require "dr/gitpackage"
|
2
|
+
require "dr/debpackage"
|
3
|
+
|
4
|
+
require "dr/shellcmd"
|
5
|
+
require "dr/logger"
|
6
|
+
require "dr/gnupg"
|
7
|
+
require "dr/buildroot"
|
8
|
+
|
9
|
+
require "fileutils"
|
10
|
+
|
11
|
+
module Dr
|
12
|
+
class Repo
|
13
|
+
include Logger
|
14
|
+
|
15
|
+
attr_reader :location
|
16
|
+
|
17
|
+
def initialize(loc)
|
18
|
+
@location = File.expand_path loc
|
19
|
+
|
20
|
+
@packages_dir = "#{@location}/packages"
|
21
|
+
end
|
22
|
+
|
23
|
+
def setup(conf)
|
24
|
+
log :info, "Creating the archive directory"
|
25
|
+
|
26
|
+
begin
|
27
|
+
FileUtils.mkdir_p location
|
28
|
+
rescue Exception => e
|
29
|
+
log :err, "Unable to create a directory at '#{@location.fg("blue")}'"
|
30
|
+
raise e
|
31
|
+
end
|
32
|
+
|
33
|
+
FileUtils.mkdir_p "#{@location}/archive"
|
34
|
+
|
35
|
+
gpg = GnuPG.new "#{@location}/gnupg-keyring"
|
36
|
+
key = gpg.generate_key conf[:gpg_name], conf[:gpg_mail], conf[:gpg_pass]
|
37
|
+
gpg.export_pub key, "#{@location}/archive/repo.gpg.key"
|
38
|
+
|
39
|
+
log :info, "Writing the configuration file"
|
40
|
+
FileUtils.mkdir_p "#{@location}/archive/conf"
|
41
|
+
File.open "#{@location}/archive/conf/distributions", "w" do |f|
|
42
|
+
conf[:suites].each_with_index do |s, i|
|
43
|
+
f.puts "Suite: #{s}"
|
44
|
+
|
45
|
+
if conf[:codenames][i].length > 0
|
46
|
+
f.puts "Codename: #{conf[:codenames][i]}"
|
47
|
+
end
|
48
|
+
|
49
|
+
if conf[:name][i].length > 0
|
50
|
+
f.puts "Origin: #{conf[:name]} - #{s}"
|
51
|
+
f.puts "Label: #{conf[:name]} - #{s}"
|
52
|
+
end
|
53
|
+
|
54
|
+
if conf[:desc].length > 0
|
55
|
+
f.puts "Description: #{conf[:desc]}"
|
56
|
+
end
|
57
|
+
|
58
|
+
f.puts "Architectures: #{conf[:arches].join " "}"
|
59
|
+
f.puts "Components: #{conf[:components].join " "}"
|
60
|
+
|
61
|
+
f.puts "SignWith: #{key}"
|
62
|
+
f.puts ""
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
FileUtils.mkdir_p @packages_dir
|
67
|
+
|
68
|
+
conf[:arches].each do |arch|
|
69
|
+
BuildRoot.new arch, "#{@location}/build-root-#{arch}.tar.gz"
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def list_packages(suite=nil)
|
74
|
+
pkgs = []
|
75
|
+
if suite
|
76
|
+
a = 1
|
77
|
+
else
|
78
|
+
Dir.foreach @packages_dir do |pkg_name|
|
79
|
+
pkgs.push get_package pkg_name unless pkg_name =~ /^\./
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
pkgs
|
84
|
+
end
|
85
|
+
|
86
|
+
def buildroot(arch)
|
87
|
+
BuildRoot.new arch, "#{@location}/build-root-#{arch}.tar.gz"
|
88
|
+
end
|
89
|
+
|
90
|
+
def get_package(name)
|
91
|
+
unless File.exists? "#{@packages_dir}/#{name}"
|
92
|
+
raise "Package '#{name}' doesn't exist in the repo."
|
93
|
+
end
|
94
|
+
|
95
|
+
if File.exists? "#{@packages_dir}/#{name}/source"
|
96
|
+
GitPackage.new name, self
|
97
|
+
else
|
98
|
+
DebPackage.new name, self
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def get_suites
|
103
|
+
suites = nil
|
104
|
+
File.open "#{@location}/archive/conf/distributions", "r" do |f|
|
105
|
+
suites = f.read.split "\n\n"
|
106
|
+
end
|
107
|
+
|
108
|
+
suites.map do |s|
|
109
|
+
suite = nil
|
110
|
+
codename = nil
|
111
|
+
s.each_line do |l|
|
112
|
+
m = l.match /^Suite: (.+)/
|
113
|
+
suite = m.captures[0].chomp if m
|
114
|
+
|
115
|
+
m = l.match /^Codename: (.+)/
|
116
|
+
codename = m.captures[0].chomp if m
|
117
|
+
end
|
118
|
+
[suite, codename]
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
def get_architectures
|
123
|
+
arches = []
|
124
|
+
File.open "#{@location}/archive/conf/distributions", "r" do |f|
|
125
|
+
f.each_line do |l|
|
126
|
+
m = l.match /^Architectures: (.+)/
|
127
|
+
arches += m.captures[0].chomp.split(" ") if m
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
arches.uniq
|
132
|
+
end
|
133
|
+
|
134
|
+
def query_for_deb_version(suite, pkg_name)
|
135
|
+
reprepro_cmd = "reprepro --basedir #{location}/archive " +
|
136
|
+
"--list-format '${version}' list #{suite} " +
|
137
|
+
"#{pkg_name} 2>/dev/null"
|
138
|
+
reprepro = ShellCmd.new reprepro_cmd, :tag => "reprepro"
|
139
|
+
v = reprepro.out.chomp
|
140
|
+
v = nil unless v.length > 0
|
141
|
+
v
|
142
|
+
end
|
143
|
+
|
144
|
+
def get_subpackage_versions(pkg_name)
|
145
|
+
pkg = get_package pkg_name
|
146
|
+
suites = get_suites
|
147
|
+
|
148
|
+
versions = {}
|
149
|
+
suites.each do |suite, codename|
|
150
|
+
versions[suite] = {}
|
151
|
+
reprepro_cmd = "reprepro --basedir #{location}/archive " +
|
152
|
+
"--list-format '${package} ${version}\n' " +
|
153
|
+
"listfilter #{suite} 'Source (== raspberrypi-firmware)' " +
|
154
|
+
"2>/dev/null"
|
155
|
+
reprepro = ShellCmd.new reprepro_cmd, :tag => "reprepro"
|
156
|
+
reprepro.out.chomp.each_line do |line|
|
157
|
+
subpkg, version = line.split(" ").map(&:chomp)
|
158
|
+
versions[suite][subpkg] = version
|
159
|
+
end
|
160
|
+
end
|
161
|
+
versions
|
162
|
+
end
|
163
|
+
|
164
|
+
def push(pkg_name, version, suite, force=false)
|
165
|
+
pkg = get_package pkg_name
|
166
|
+
|
167
|
+
if version
|
168
|
+
unless pkg.build_exists? version
|
169
|
+
raise "Build version '#{version}' not found"
|
170
|
+
end
|
171
|
+
else
|
172
|
+
if pkg.history.length == 0
|
173
|
+
log :err, "Package #{pkg_name} has not been built yet"
|
174
|
+
log :err, "Please, run a build first and the push."
|
175
|
+
raise "Push failed"
|
176
|
+
end
|
177
|
+
version = pkg.history[0]
|
178
|
+
end
|
179
|
+
|
180
|
+
if suite
|
181
|
+
cmp = get_suites.map { |n, cn| suite == n || suite == cn }
|
182
|
+
suite_exists = cmp.inject(false) { |r, o| r || o }
|
183
|
+
raise "Suite '#{suite}' doesn't exist." unless suite_exists
|
184
|
+
else
|
185
|
+
# FIXME: This should be configurable
|
186
|
+
suite = "testing"
|
187
|
+
end
|
188
|
+
|
189
|
+
# FIXME: This will not work with packages that don't build a deb
|
190
|
+
# with the same name as the source package
|
191
|
+
current_version = query_for_deb_version suite, pkg.name
|
192
|
+
|
193
|
+
if current_version != nil && current_version >= version
|
194
|
+
log :warn, "Version #{version.fg("blue")} already available in #{suite}"
|
195
|
+
if force
|
196
|
+
reprepro = "reprepro -b #{@location}/archive " +
|
197
|
+
"--gnupghome #{location}/gnupg-keyring/ removesrc " +
|
198
|
+
"#{suite} #{pkg.name}"
|
199
|
+
ShellCmd.new reprepro, :tag => "reprepro", :show_out => true
|
200
|
+
else
|
201
|
+
log :err, "The same package of a higher version is already in the repo."
|
202
|
+
raise "Push failed"
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
log :info, "Pushing #{pkg_name} version #{version} to #{suite}"
|
207
|
+
debs = Dir["#{@location}/packages/#{pkg.name}/builds/#{version}/*"]
|
208
|
+
reprepro = "reprepro -b #{@location}/archive " +
|
209
|
+
"--gnupghome #{location}/gnupg-keyring/ includedeb " +
|
210
|
+
"#{suite} #{debs.join " "}"
|
211
|
+
ShellCmd.new reprepro, :tag => "reprepro", :show_out => true
|
212
|
+
end
|
213
|
+
|
214
|
+
def unpush(pkg_name, suite)
|
215
|
+
pkg = get_package pkg_name
|
216
|
+
|
217
|
+
cmp = get_suites.map { |n, cn| suite == n || suite == cn }
|
218
|
+
suite_exists = cmp.inject(false) { |r, o| r || o }
|
219
|
+
unless suite_exists
|
220
|
+
log :err, "Suite '#{suite}' doesn't exist."
|
221
|
+
raise "Unpush failed"
|
222
|
+
end
|
223
|
+
|
224
|
+
log :info, "Removing #{pkg_name} from #{suite}"
|
225
|
+
reprepro = "reprepro -b #{@location}/archive " +
|
226
|
+
"--gnupghome #{location}/gnupg-keyring/ removesrc " +
|
227
|
+
"#{suite} #{pkg.name}"
|
228
|
+
ShellCmd.new reprepro, :tag => "reprepro", :show_out => true
|
229
|
+
end
|
230
|
+
|
231
|
+
def remove(pkg_name, force=false)
|
232
|
+
pkg = get_package pkg_name
|
233
|
+
|
234
|
+
if is_used? pkg_name
|
235
|
+
log :warn, "Package #{pkg_name} is still used"
|
236
|
+
raise "The '#{pkg_name}' package is still used." unless force
|
237
|
+
|
238
|
+
log :info, "Will be force-removed anyway"
|
239
|
+
get_suites.zip(versions).each do |suite, version|
|
240
|
+
log :info, "Removing #{pkg_name} v#{version} from #{suite}"
|
241
|
+
unpush pkg_name, suite[0] if version != nil
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
if !is_used?(pkg_name) || force
|
246
|
+
log :info, "Removing #{pkg_name} from the repository"
|
247
|
+
FileUtils.rm_rf "#{location}/packages/#{pkg_name}"
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
251
|
+
def remove_build(pkg_name, version, force=false)
|
252
|
+
pkg = get_package pkg_name
|
253
|
+
|
254
|
+
if is_used?(pkg_name, version)
|
255
|
+
if force
|
256
|
+
log :info, "Force-removing #{version.fg("blue")} version of " +
|
257
|
+
"#{pkg_name.fg("blue")}"
|
258
|
+
versions_by_suite = get_subpackage_versions pkg_name
|
259
|
+
versions_by_suite.each do |suite, versions|
|
260
|
+
unpush pkg_name, suite if versions.has_value? version
|
261
|
+
end
|
262
|
+
else
|
263
|
+
log :warn, "This build of #{pkg_name} is " +
|
264
|
+
"still being used, add -f to force-remove"
|
265
|
+
return
|
266
|
+
end
|
267
|
+
else
|
268
|
+
log :info, "Removing the #{version.fg("blue")} version of " +
|
269
|
+
"#{pkg_name.fg("blue")}"
|
270
|
+
end
|
271
|
+
|
272
|
+
pkg.remove_build version
|
273
|
+
end
|
274
|
+
|
275
|
+
def get_build(pkg_name, version=nil)
|
276
|
+
pkg = get_package pkg_name
|
277
|
+
|
278
|
+
hist = pkg.history
|
279
|
+
raise "The package hasn't been built yet." unless hist.length > 0
|
280
|
+
version = hist[0] unless version
|
281
|
+
|
282
|
+
raise "Build #{version} doesn't exist" unless pkg.build_exists? version
|
283
|
+
|
284
|
+
Dir["#{@location}/packages/#{pkg.name}/builds/#{version}/*"]
|
285
|
+
end
|
286
|
+
|
287
|
+
private
|
288
|
+
def is_used?(pkg_name, version=nil)
|
289
|
+
versions_by_suite = get_subpackage_versions pkg_name
|
290
|
+
versions_by_suite.inject(false) do |rslt, hash_pair|
|
291
|
+
suite, versions = hash_pair
|
292
|
+
if version == nil
|
293
|
+
rslt || !versions.empty?
|
294
|
+
else
|
295
|
+
rslt || versions.has_value?(version)
|
296
|
+
end
|
297
|
+
end
|
298
|
+
end
|
299
|
+
end
|
300
|
+
end
|