smc-get 0.2.0.beta1 → 0.3.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- data/COPYING +674 -674
- data/HISTORY.rdoc +53 -31
- data/README.rdoc +162 -162
- data/VERSION.txt +1 -1
- data/bin/smc-checksum +44 -44
- data/bin/smc-checksum~ +2 -0
- data/bin/smc-get +31 -31
- data/bin/smc-repo-conv +205 -0
- data/bin/smc-repo-conv~ +155 -0
- data/config/smc-get.yml +32 -32
- data/config/smc-get.yml~ +32 -0
- data/lib/smc_get.rb +22 -22
- data/lib/smc_get/cui.rb +325 -325
- data/lib/smc_get/cui_commands/build.rb +297 -329
- data/lib/smc_get/cui_commands/command.rb +181 -117
- data/lib/smc_get/cui_commands/getinfo.rb +91 -91
- data/lib/smc_get/cui_commands/help.rb +64 -64
- data/lib/smc_get/cui_commands/install.rb +101 -101
- data/lib/smc_get/cui_commands/list.rb +101 -101
- data/lib/smc_get/cui_commands/search.rb +106 -106
- data/lib/smc_get/cui_commands/server.rb +76 -0
- data/lib/smc_get/cui_commands/uninstall.rb +77 -80
- data/lib/smc_get/cui_commands/update.rb +107 -119
- data/lib/smc_get/cui_commands/version.rb +57 -57
- data/lib/smc_get/errors.rb +166 -140
- data/lib/smc_get/gui.rb +19 -19
- data/lib/smc_get/local_repository.rb +290 -277
- data/lib/smc_get/package.rb +240 -260
- data/lib/smc_get/package_archive.rb +186 -80
- data/lib/smc_get/package_specification.rb +257 -253
- data/lib/smc_get/remote_repository.rb +272 -272
- data/lib/smc_get/repository.rb +9 -9
- data/lib/smc_get/smc_get.rb +118 -117
- data/smcpak.rdoc +331 -331
- data/test/test_smc-get-cui.rb +122 -122
- data/test/test_smc-get-lib.rb +171 -171
- metadata +25 -22
@@ -1,272 +1,272 @@
|
|
1
|
-
#Encoding: UTF-8
|
2
|
-
################################################################################
|
3
|
-
# This file is part of smc-get.
|
4
|
-
# Copyright (C) 2010-2011 Entertaining Software, Inc.
|
5
|
-
# Copyright (C) 2011 Marvin Gülker
|
6
|
-
#
|
7
|
-
# This program is free software: you can redistribute it and/or modify
|
8
|
-
# it under the terms of the GNU General Public License as published by
|
9
|
-
# the Free Software Foundation, either version 3 of the License, or
|
10
|
-
# (at your option) any later version.
|
11
|
-
#
|
12
|
-
# This program 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 General Public License for more details.
|
16
|
-
#
|
17
|
-
# You should have received a copy of the GNU General Public License
|
18
|
-
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
19
|
-
################################################################################
|
20
|
-
|
21
|
-
module SmcGet
|
22
|
-
|
23
|
-
#A RemoteRepository represents a web location from which <tt>smc-get</tt>
|
24
|
-
#is able to download packages. The structure of those repositories is
|
25
|
-
#explained in the smcpak.rdoc file in the <i>Repostories</i> section.
|
26
|
-
class RemoteRepository < Repository
|
27
|
-
|
28
|
-
#Name of the remote directory containing the <tt>.smcpak</tt> files.
|
29
|
-
PACKAGES_DIR = "packages"
|
30
|
-
#Name of the remote directory containing the packages specifications.
|
31
|
-
SPECS_DIR = "specs"
|
32
|
-
#Name of the file containg the names of all packages in this repository.
|
33
|
-
LIST_FILE = "packages.lst"
|
34
|
-
#Number of bytes to read while downloading a file.
|
35
|
-
CHUNK_SIZE = 1024
|
36
|
-
|
37
|
-
##
|
38
|
-
# :attr_reader: packages
|
39
|
-
#Returns an array of remote Packages that contains all packages
|
40
|
-
#in this repository. This is a very time-intensive operation, depending
|
41
|
-
#on how many packages the repository contains, because it downloads all
|
42
|
-
#the package specifications of all the packages. It’s not a good idea
|
43
|
-
#to call this.
|
44
|
-
|
45
|
-
#An URI object representing the repository’s URI.
|
46
|
-
attr_reader :uri
|
47
|
-
#A list of all package names (without an extension).
|
48
|
-
attr_reader :packages_list
|
49
|
-
|
50
|
-
#Creates a "new" Repository.
|
51
|
-
#==Parameters
|
52
|
-
#[uri] The URI of the repository, something like
|
53
|
-
# "\http://my-host.org/smc-repo".
|
54
|
-
#==Raises
|
55
|
-
#[InvalidRepository] The repository is either nonexistant or doesn’t obey
|
56
|
-
# the repository structure format.
|
57
|
-
#==Return value
|
58
|
-
#The newly created repository.
|
59
|
-
#==Usage
|
60
|
-
# r = Repository.new("http://myrepo.org")
|
61
|
-
# r = Repository.new("https://my-host.org/smc-repo")
|
62
|
-
# r = Repository.new("ftp://ftp.my-host.org/smc")
|
63
|
-
def initialize(uri)
|
64
|
-
@uri = URI.parse(uri)
|
65
|
-
#Download the packages list. Usually it’s small enough to fit into RAM.
|
66
|
-
begin
|
67
|
-
@packages_list = open(@uri
|
68
|
-
rescue SocketError, Errno::ECONNREFUSED, OpenURI::HTTPError => e #open-uri raises HTTPError even in case of other protocols
|
69
|
-
raise(Errors::InvalidRepository.new(@uri), e.message)
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
#Downloads the given package specification from this repository and
|
74
|
-
#places it in +directory+.
|
75
|
-
#
|
76
|
-
#If the file already exists, it’s overwritten.
|
77
|
-
#==Parameters
|
78
|
-
#[spec_file] The package specification file you want to download. It must
|
79
|
-
# end with the <tt>.yml</tt> extension.
|
80
|
-
#[directory] (".") The directory where you want to download the file to.
|
81
|
-
# Created if it doesn’t exist.
|
82
|
-
#==Raises
|
83
|
-
#[NoSuchResourceError] The package name for this specification couldn’t be
|
84
|
-
# found in the repository. Note that the spec may be
|
85
|
-
# there despite of this, but packages not listed
|
86
|
-
# in the repository’s contents file are treated as if
|
87
|
-
# they weren’t there.
|
88
|
-
#==Return value
|
89
|
-
#The path to the downloaded file as a Pathname object.
|
90
|
-
#==Usage
|
91
|
-
# my_repo.fetch_spec("mypackage.yml", "/home/freak/Downloads")
|
92
|
-
#
|
93
|
-
# my_repo.fetch_spec("mypackage.yml")
|
94
|
-
def fetch_spec(spec_file, directory = ".")
|
95
|
-
directory = Pathname.new(directory)
|
96
|
-
pkg_name = spec_file.sub(/\.yml$/, "")
|
97
|
-
goal_file = directory + spec_file
|
98
|
-
|
99
|
-
unless @packages_list.include?(pkg_name)
|
100
|
-
raise(Errors::NoSuchResourceError.new(:spec, spec_file), "Package '#{pkg_name}' not found in the repository!")
|
101
|
-
end
|
102
|
-
|
103
|
-
directory.mktree unless directory.directory?
|
104
|
-
|
105
|
-
#I am quite sure that URI#merge has a bug. Example:
|
106
|
-
# uri = URI.parse("http://www.ruby-lang.org")
|
107
|
-
#Now try to append the path test/test2:
|
108
|
-
# uri2 = uri + "test" + "test2"
|
109
|
-
#What do you think contains uri2? This:
|
110
|
-
# http://www.ruby-lang.org/test2
|
111
|
-
#Something missing, eh? Even more surprising, this one works as
|
112
|
-
#expected:
|
113
|
-
# uri + "test/test2"
|
114
|
-
#The second one is the workaround I use in the following line.
|
115
|
-
open(
|
116
|
-
File.open(goal_file, "w") do |file|
|
117
|
-
file.write(tempfile.read) #Specs almost ever are small enough to fit in RAM
|
118
|
-
end
|
119
|
-
end
|
120
|
-
goal_file
|
121
|
-
end
|
122
|
-
|
123
|
-
#Downloads the given package from this repository and places it in
|
124
|
-
#+directory+. Yields the package’s total size in bytes and how many
|
125
|
-
#bytes have already been downloaded. If the size is unknown for some
|
126
|
-
#reason, +bytes_total+ is nil. For the last block call, +bytes_total+
|
127
|
-
#and +bytes_done+ are guaranteed to be equal, except if +bytes_total+
|
128
|
-
#couldn’t be determined in which case it’s still nil.
|
129
|
-
#
|
130
|
-
#If the file does already exist in +directory+, it is overwritten.
|
131
|
-
#==Parameters
|
132
|
-
#[pkg_file] The package file you want to download. It must end in
|
133
|
-
# the <tt>.smcpak</tt> extension.
|
134
|
-
#[directory] (".") The directory where you want to download the file to.
|
135
|
-
# Created if it doesn’t exist.
|
136
|
-
#==Raises
|
137
|
-
#[NoSuchPackageError] The package name for this package couldn’t be
|
138
|
-
# found in the repository. Note that the package may be
|
139
|
-
# there despite of this, but packages not listed
|
140
|
-
# in the repository’s contents file are treated as if
|
141
|
-
# they weren’t there.
|
142
|
-
#[OpenURI::HTTPError] Connection error.
|
143
|
-
#==Return value
|
144
|
-
#The path to the downloaded file as a Pathname object.
|
145
|
-
#==Usage
|
146
|
-
# my_repo.fetch_package("mypackage.smcpak", "/home/freak/downloads")
|
147
|
-
#
|
148
|
-
# my_repo.fetch_package("mypackage.smcpak") do |bytes_total, bytes_done|
|
149
|
-
# print("\rDownloaded #{bytes_done} bytes of #{bytes_total}.") if bytes_total
|
150
|
-
# end
|
151
|
-
def fetch_package(pkg_file, directory = ".")
|
152
|
-
directory = Pathname.new(directory)
|
153
|
-
pkg_name = pkg_file.sub(/\.smcpak$/, "")
|
154
|
-
goal_file = directory + pkg_file
|
155
|
-
|
156
|
-
unless @packages_list.include?(pkg_name)
|
157
|
-
raise(Errors::NoSuchPackageError.new(pkg_name), "ERROR: Package '#{pkg_name}' not found in the repository!")
|
158
|
-
end
|
159
|
-
|
160
|
-
directory.mktree unless directory.directory?
|
161
|
-
|
162
|
-
bytes_total = nil
|
163
|
-
size_proc = lambda{|content_length| bytes_total = content_length}
|
164
|
-
prog_proc = lambda{|bytes_done| yield(bytes_total, bytes_done)}
|
165
|
-
|
166
|
-
#See the source of #fetch_spec for an explanation on the obscure
|
167
|
-
#URI concatenation.
|
168
|
-
open(
|
169
|
-
#The packages may be too big for fitting into RAM, therefore we’re going
|
170
|
-
#to read and write the packages chunk by chunk. Btw. please notice me
|
171
|
-
#if you find a SMC package that’s larger than 4 GiB! I’d be curious
|
172
|
-
#about what it contains!
|
173
|
-
File.open(goal_file, "wb") do |file|
|
174
|
-
while chunk = tempfile.read(CHUNK_SIZE)
|
175
|
-
file.write(chunk)
|
176
|
-
end
|
177
|
-
end
|
178
|
-
end
|
179
|
-
|
180
|
-
goal_file
|
181
|
-
end
|
182
|
-
|
183
|
-
#Not implemented yet.
|
184
|
-
def install(package, &block)
|
185
|
-
raise(NotImplementedError, "Can't automatically upload to remote repositories yet!")
|
186
|
-
end
|
187
|
-
|
188
|
-
#Not implemented yet.
|
189
|
-
def uninstall(pkg_name)
|
190
|
-
raise(NotImplementedError, "Can't automatically remove from remote repositories yet!")
|
191
|
-
end
|
192
|
-
|
193
|
-
#Returns the URI of the remote repository.
|
194
|
-
def to_s
|
195
|
-
@uri.to_s
|
196
|
-
end
|
197
|
-
|
198
|
-
#See attribute.
|
199
|
-
# def packages # :nodoc:
|
200
|
-
# @packages_list.map do |pkg_name|
|
201
|
-
# Package.from_repository(self, "#{pkg_name}.yml")
|
202
|
-
# end
|
203
|
-
# end
|
204
|
-
|
205
|
-
#True if a package with the given name (without the .smcpak extension)
|
206
|
-
#exists in the repository.
|
207
|
-
def contain?(pkg)
|
208
|
-
if pkg.kind_of? Package
|
209
|
-
@packages_list.include?(pkg.spec.name)
|
210
|
-
else
|
211
|
-
@packages_list.include?(pkg_name)
|
212
|
-
end
|
213
|
-
end
|
214
|
-
alias contains? contain?
|
215
|
-
|
216
|
-
#call-seq:
|
217
|
-
# search(regexp [, *attributes ]){|pkgname|...}
|
218
|
-
#
|
219
|
-
#Searches for a specific package and yields each candidate to the
|
220
|
-
#given block.
|
221
|
-
#==Parameters
|
222
|
-
#[regexp] The Regular Expression to use as the search pattern.
|
223
|
-
#[*attributes] (<tt>[:name]</tt>) A list of all attributes to match
|
224
|
-
# the Regular Expression against (note that only
|
225
|
-
# passing :name is siginificantly faster, because
|
226
|
-
# there’s no need to download the specs).
|
227
|
-
# Possible attributes:
|
228
|
-
# * name
|
229
|
-
# * title
|
230
|
-
# * authors
|
231
|
-
# * difficulty
|
232
|
-
# * description
|
233
|
-
# * levels
|
234
|
-
# * music
|
235
|
-
# * sounds
|
236
|
-
# * graphics
|
237
|
-
# * worlds
|
238
|
-
#[pkgname] *Blockargument*. The package name (not title!) of
|
239
|
-
# a package matching the search criteria.
|
240
|
-
#==Examples
|
241
|
-
# rp.search(/cool/){|pkgname| p pkgname} #=> "cool_levels"
|
242
|
-
# rp.search(/Luiji/i, :authors){|pkgname| p pkgname} #=> All packages created by Luiji or luiji...
|
243
|
-
def search(regexp, *attributes)
|
244
|
-
attributes << :name if attributes.empty? #Default value
|
245
|
-
if attributes == [:name] #Good, no need to download all the specs
|
246
|
-
@packages_list.each{|name| yield(name) if name =~ regexp}
|
247
|
-
else #OK, so we need to download one spec after the other...
|
248
|
-
@packages_list.each do |pkgname|
|
249
|
-
spec = PackageSpecification.from_file(fetch_spec("#{pkgname}.yml", SmcGet.temp_dir))
|
250
|
-
attributes.each do |att|
|
251
|
-
case att
|
252
|
-
when :name then yield(pkgname) if spec.name =~ regexp
|
253
|
-
when :title then yield(pkgname) if spec.title =~ regexp
|
254
|
-
when :authors then yield(pkgname) if spec.authors.any?{|a| a =~ regexp}
|
255
|
-
when :difficulty then yield(pkgname) if spec.difficulty =~ regexp
|
256
|
-
when :description then yield(pkgname) if spec.description =~ regexp
|
257
|
-
when :levels then yield(pkgname) if spec.levels.any?{|l| l =~ regexp}
|
258
|
-
when :music then yield(pkgname) if spec.music.any?{|m| m =~ regexp}
|
259
|
-
when :sounds then yield(pkgname) if spec.sound.any?{|s| s =~ regexp}
|
260
|
-
when :graphics then yield(pkgname) if spec.graphics.any?{|g| g =~ regexp}
|
261
|
-
when :worlds then yield(pkgname) if spec.worlds.any?{|w| w =~ regexp}
|
262
|
-
else
|
263
|
-
$stderr.puts("Warning: Unknown attribute #{att}, ignoring it.")
|
264
|
-
end #case
|
265
|
-
end #attributes.each
|
266
|
-
end # @packages.each
|
267
|
-
end #if only :name
|
268
|
-
end #search
|
269
|
-
|
270
|
-
end #RemoteRepository
|
271
|
-
|
272
|
-
end #SmcGet
|
1
|
+
#Encoding: UTF-8
|
2
|
+
################################################################################
|
3
|
+
# This file is part of smc-get.
|
4
|
+
# Copyright (C) 2010-2011 Entertaining Software, Inc.
|
5
|
+
# Copyright (C) 2011 Marvin Gülker
|
6
|
+
#
|
7
|
+
# This program is free software: you can redistribute it and/or modify
|
8
|
+
# it under the terms of the GNU General Public License as published by
|
9
|
+
# the Free Software Foundation, either version 3 of the License, or
|
10
|
+
# (at your option) any later version.
|
11
|
+
#
|
12
|
+
# This program 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 General Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU General Public License
|
18
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
19
|
+
################################################################################
|
20
|
+
|
21
|
+
module SmcGet
|
22
|
+
|
23
|
+
#A RemoteRepository represents a web location from which <tt>smc-get</tt>
|
24
|
+
#is able to download packages. The structure of those repositories is
|
25
|
+
#explained in the smcpak.rdoc file in the <i>Repostories</i> section.
|
26
|
+
class RemoteRepository < Repository
|
27
|
+
|
28
|
+
#Name of the remote directory containing the <tt>.smcpak</tt> files.
|
29
|
+
PACKAGES_DIR = "packages"
|
30
|
+
#Name of the remote directory containing the packages specifications.
|
31
|
+
SPECS_DIR = "specs"
|
32
|
+
#Name of the file containg the names of all packages in this repository.
|
33
|
+
LIST_FILE = "packages.lst"
|
34
|
+
#Number of bytes to read while downloading a file.
|
35
|
+
CHUNK_SIZE = 1024
|
36
|
+
|
37
|
+
##
|
38
|
+
# :attr_reader: packages
|
39
|
+
#Returns an array of remote Packages that contains all packages
|
40
|
+
#in this repository. This is a very time-intensive operation, depending
|
41
|
+
#on how many packages the repository contains, because it downloads all
|
42
|
+
#the package specifications of all the packages. It’s not a good idea
|
43
|
+
#to call this.
|
44
|
+
|
45
|
+
#An URI object representing the repository’s URI.
|
46
|
+
attr_reader :uri
|
47
|
+
#A list of all package names (without an extension).
|
48
|
+
attr_reader :packages_list
|
49
|
+
|
50
|
+
#Creates a "new" Repository.
|
51
|
+
#==Parameters
|
52
|
+
#[uri] The URI of the repository, something like
|
53
|
+
# "\http://my-host.org/smc-repo".
|
54
|
+
#==Raises
|
55
|
+
#[InvalidRepository] The repository is either nonexistant or doesn’t obey
|
56
|
+
# the repository structure format.
|
57
|
+
#==Return value
|
58
|
+
#The newly created repository.
|
59
|
+
#==Usage
|
60
|
+
# r = Repository.new("http://myrepo.org")
|
61
|
+
# r = Repository.new("https://my-host.org/smc-repo")
|
62
|
+
# r = Repository.new("ftp://ftp.my-host.org/smc")
|
63
|
+
def initialize(uri)
|
64
|
+
@uri = URI.parse(uri)
|
65
|
+
#Download the packages list. Usually it’s small enough to fit into RAM.
|
66
|
+
begin
|
67
|
+
@packages_list = open("#{@uri}/#{LIST_FILE}"){|tmpfile| tmpfile.read}.split
|
68
|
+
rescue SocketError, Errno::ECONNREFUSED, OpenURI::HTTPError => e #open-uri raises HTTPError even in case of other protocols
|
69
|
+
raise(Errors::InvalidRepository.new(@uri), e.message)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
#Downloads the given package specification from this repository and
|
74
|
+
#places it in +directory+.
|
75
|
+
#
|
76
|
+
#If the file already exists, it’s overwritten.
|
77
|
+
#==Parameters
|
78
|
+
#[spec_file] The package specification file you want to download. It must
|
79
|
+
# end with the <tt>.yml</tt> extension.
|
80
|
+
#[directory] (".") The directory where you want to download the file to.
|
81
|
+
# Created if it doesn’t exist.
|
82
|
+
#==Raises
|
83
|
+
#[NoSuchResourceError] The package name for this specification couldn’t be
|
84
|
+
# found in the repository. Note that the spec may be
|
85
|
+
# there despite of this, but packages not listed
|
86
|
+
# in the repository’s contents file are treated as if
|
87
|
+
# they weren’t there.
|
88
|
+
#==Return value
|
89
|
+
#The path to the downloaded file as a Pathname object.
|
90
|
+
#==Usage
|
91
|
+
# my_repo.fetch_spec("mypackage.yml", "/home/freak/Downloads")
|
92
|
+
#
|
93
|
+
# my_repo.fetch_spec("mypackage.yml")
|
94
|
+
def fetch_spec(spec_file, directory = ".")
|
95
|
+
directory = Pathname.new(directory)
|
96
|
+
pkg_name = spec_file.sub(/\.yml$/, "")
|
97
|
+
goal_file = directory + spec_file
|
98
|
+
|
99
|
+
unless @packages_list.include?(pkg_name)
|
100
|
+
raise(Errors::NoSuchResourceError.new(:spec, spec_file), "Package '#{pkg_name}' not found in the repository!")
|
101
|
+
end
|
102
|
+
|
103
|
+
directory.mktree unless directory.directory?
|
104
|
+
|
105
|
+
#I am quite sure that URI#merge has a bug. Example:
|
106
|
+
# uri = URI.parse("http://www.ruby-lang.org")
|
107
|
+
#Now try to append the path test/test2:
|
108
|
+
# uri2 = uri + "test" + "test2"
|
109
|
+
#What do you think contains uri2? This:
|
110
|
+
# http://www.ruby-lang.org/test2
|
111
|
+
#Something missing, eh? Even more surprising, this one works as
|
112
|
+
#expected:
|
113
|
+
# uri + "test/test2"
|
114
|
+
#The second one is the workaround I use in the following line.
|
115
|
+
open("#{@uri}/#{SPECS_DIR}/#{spec_file}") do |tempfile|
|
116
|
+
File.open(goal_file, "w") do |file|
|
117
|
+
file.write(tempfile.read) #Specs almost ever are small enough to fit in RAM
|
118
|
+
end
|
119
|
+
end
|
120
|
+
goal_file
|
121
|
+
end
|
122
|
+
|
123
|
+
#Downloads the given package from this repository and places it in
|
124
|
+
#+directory+. Yields the package’s total size in bytes and how many
|
125
|
+
#bytes have already been downloaded. If the size is unknown for some
|
126
|
+
#reason, +bytes_total+ is nil. For the last block call, +bytes_total+
|
127
|
+
#and +bytes_done+ are guaranteed to be equal, except if +bytes_total+
|
128
|
+
#couldn’t be determined in which case it’s still nil.
|
129
|
+
#
|
130
|
+
#If the file does already exist in +directory+, it is overwritten.
|
131
|
+
#==Parameters
|
132
|
+
#[pkg_file] The package file you want to download. It must end in
|
133
|
+
# the <tt>.smcpak</tt> extension.
|
134
|
+
#[directory] (".") The directory where you want to download the file to.
|
135
|
+
# Created if it doesn’t exist.
|
136
|
+
#==Raises
|
137
|
+
#[NoSuchPackageError] The package name for this package couldn’t be
|
138
|
+
# found in the repository. Note that the package may be
|
139
|
+
# there despite of this, but packages not listed
|
140
|
+
# in the repository’s contents file are treated as if
|
141
|
+
# they weren’t there.
|
142
|
+
#[OpenURI::HTTPError] Connection error.
|
143
|
+
#==Return value
|
144
|
+
#The path to the downloaded file as a Pathname object.
|
145
|
+
#==Usage
|
146
|
+
# my_repo.fetch_package("mypackage.smcpak", "/home/freak/downloads")
|
147
|
+
#
|
148
|
+
# my_repo.fetch_package("mypackage.smcpak") do |bytes_total, bytes_done|
|
149
|
+
# print("\rDownloaded #{bytes_done} bytes of #{bytes_total}.") if bytes_total
|
150
|
+
# end
|
151
|
+
def fetch_package(pkg_file, directory = ".")
|
152
|
+
directory = Pathname.new(directory)
|
153
|
+
pkg_name = pkg_file.sub(/\.smcpak$/, "")
|
154
|
+
goal_file = directory + pkg_file
|
155
|
+
|
156
|
+
unless @packages_list.include?(pkg_name)
|
157
|
+
raise(Errors::NoSuchPackageError.new(pkg_name), "ERROR: Package '#{pkg_name}' not found in the repository!")
|
158
|
+
end
|
159
|
+
|
160
|
+
directory.mktree unless directory.directory?
|
161
|
+
|
162
|
+
bytes_total = nil
|
163
|
+
size_proc = lambda{|content_length| bytes_total = content_length}
|
164
|
+
prog_proc = lambda{|bytes_done| yield(bytes_total, bytes_done)}
|
165
|
+
|
166
|
+
#See the source of #fetch_spec for an explanation on the obscure
|
167
|
+
#URI concatenation.
|
168
|
+
open("#{@uri}/#{PACKAGES_DIR}/#{pkg_file}", "rb", content_length_proc: size_proc, progress_proc: prog_proc) do |tempfile|
|
169
|
+
#The packages may be too big for fitting into RAM, therefore we’re going
|
170
|
+
#to read and write the packages chunk by chunk. Btw. please notice me
|
171
|
+
#if you find a SMC package that’s larger than 4 GiB! I’d be curious
|
172
|
+
#about what it contains!
|
173
|
+
File.open(goal_file, "wb") do |file|
|
174
|
+
while chunk = tempfile.read(CHUNK_SIZE)
|
175
|
+
file.write(chunk)
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
goal_file
|
181
|
+
end
|
182
|
+
|
183
|
+
#Not implemented yet.
|
184
|
+
def install(package, &block)
|
185
|
+
raise(NotImplementedError, "Can't automatically upload to remote repositories yet!")
|
186
|
+
end
|
187
|
+
|
188
|
+
#Not implemented yet.
|
189
|
+
def uninstall(pkg_name)
|
190
|
+
raise(NotImplementedError, "Can't automatically remove from remote repositories yet!")
|
191
|
+
end
|
192
|
+
|
193
|
+
#Returns the URI of the remote repository.
|
194
|
+
def to_s
|
195
|
+
@uri.to_s
|
196
|
+
end
|
197
|
+
|
198
|
+
#See attribute.
|
199
|
+
# def packages # :nodoc:
|
200
|
+
# @packages_list.map do |pkg_name|
|
201
|
+
# Package.from_repository(self, "#{pkg_name}.yml")
|
202
|
+
# end
|
203
|
+
# end
|
204
|
+
|
205
|
+
#True if a package with the given name (without the .smcpak extension)
|
206
|
+
#exists in the repository.
|
207
|
+
def contain?(pkg)
|
208
|
+
if pkg.kind_of? Package
|
209
|
+
@packages_list.include?(pkg.spec.name)
|
210
|
+
else
|
211
|
+
@packages_list.include?(pkg_name)
|
212
|
+
end
|
213
|
+
end
|
214
|
+
alias contains? contain?
|
215
|
+
|
216
|
+
#call-seq:
|
217
|
+
# search(regexp [, *attributes ]){|pkgname|...}
|
218
|
+
#
|
219
|
+
#Searches for a specific package and yields each candidate to the
|
220
|
+
#given block.
|
221
|
+
#==Parameters
|
222
|
+
#[regexp] The Regular Expression to use as the search pattern.
|
223
|
+
#[*attributes] (<tt>[:name]</tt>) A list of all attributes to match
|
224
|
+
# the Regular Expression against (note that only
|
225
|
+
# passing :name is siginificantly faster, because
|
226
|
+
# there’s no need to download the specs).
|
227
|
+
# Possible attributes:
|
228
|
+
# * name
|
229
|
+
# * title
|
230
|
+
# * authors
|
231
|
+
# * difficulty
|
232
|
+
# * description
|
233
|
+
# * levels
|
234
|
+
# * music
|
235
|
+
# * sounds
|
236
|
+
# * graphics
|
237
|
+
# * worlds
|
238
|
+
#[pkgname] *Blockargument*. The package name (not title!) of
|
239
|
+
# a package matching the search criteria.
|
240
|
+
#==Examples
|
241
|
+
# rp.search(/cool/){|pkgname| p pkgname} #=> "cool_levels"
|
242
|
+
# rp.search(/Luiji/i, :authors){|pkgname| p pkgname} #=> All packages created by Luiji or luiji...
|
243
|
+
def search(regexp, *attributes)
|
244
|
+
attributes << :name if attributes.empty? #Default value
|
245
|
+
if attributes == [:name] #Good, no need to download all the specs
|
246
|
+
@packages_list.each{|name| yield(name) if name =~ regexp}
|
247
|
+
else #OK, so we need to download one spec after the other...
|
248
|
+
@packages_list.each do |pkgname|
|
249
|
+
spec = PackageSpecification.from_file(fetch_spec("#{pkgname}.yml", SmcGet.temp_dir))
|
250
|
+
attributes.each do |att|
|
251
|
+
case att
|
252
|
+
when :name then yield(pkgname) if spec.name =~ regexp
|
253
|
+
when :title then yield(pkgname) if spec.title =~ regexp
|
254
|
+
when :authors then yield(pkgname) if spec.authors.any?{|a| a =~ regexp}
|
255
|
+
when :difficulty then yield(pkgname) if spec.difficulty =~ regexp
|
256
|
+
when :description then yield(pkgname) if spec.description =~ regexp
|
257
|
+
when :levels then yield(pkgname) if spec.levels.any?{|l| l =~ regexp}
|
258
|
+
when :music then yield(pkgname) if spec.music.any?{|m| m =~ regexp}
|
259
|
+
when :sounds then yield(pkgname) if spec.sound.any?{|s| s =~ regexp}
|
260
|
+
when :graphics then yield(pkgname) if spec.graphics.any?{|g| g =~ regexp}
|
261
|
+
when :worlds then yield(pkgname) if spec.worlds.any?{|w| w =~ regexp}
|
262
|
+
else
|
263
|
+
$stderr.puts("Warning: Unknown attribute #{att}, ignoring it.")
|
264
|
+
end #case
|
265
|
+
end #attributes.each
|
266
|
+
end # @packages.each
|
267
|
+
end #if only :name
|
268
|
+
end #search
|
269
|
+
|
270
|
+
end #RemoteRepository
|
271
|
+
|
272
|
+
end #SmcGet
|