smc-get 0.2.0.beta1 → 0.3.0.beta1

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.
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env ruby
2
+ #Encoding: UTF-8
@@ -1,31 +1,31 @@
1
- #!/usr/bin/env ruby
2
- #Encoding: UTF-8
3
- ################################################################################
4
- # This file is part of smc-get.
5
- # Copyright (C) 2010-2011 Entertaining Software, Inc.
6
- # Copyright (C) 2011 Marvin Gülker
7
- #
8
- # This program is free software: you can redistribute it and/or modify
9
- # it under the terms of the GNU General Public License as published by
10
- # the Free Software Foundation, either version 3 of the License, or
11
- # (at your option) any later version.
12
- #
13
- # This program is distributed in the hope that it will be useful,
14
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
15
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
- # GNU General Public License for more details.
17
- #
18
- # You should have received a copy of the GNU General Public License
19
- # along with this program. If not, see <http://www.gnu.org/licenses/>.
20
- ################################################################################
21
-
22
- if RUBY_VERSION =~ /^1.8/ #1.8 doesn't have require_relative
23
- require File.join(File.expand_path(File.dirname(__FILE__)), "..", "lib", "smc_get", "smc_get")
24
- require File.join(File.expand_path(File.dirname(__FILE__)), "..", "lib", "smc_get", "cui")
25
- else
26
- require_relative "../lib/smc_get/smc_get"
27
- require_relative "../lib/smc_get/cui"
28
- end
29
-
30
- cui = SmcGet::CUI.new(ARGV)
31
- cui.start
1
+ #!/usr/bin/env ruby
2
+ #Encoding: UTF-8
3
+ ################################################################################
4
+ # This file is part of smc-get.
5
+ # Copyright (C) 2010-2011 Entertaining Software, Inc.
6
+ # Copyright (C) 2011 Marvin Gülker
7
+ #
8
+ # This program is free software: you can redistribute it and/or modify
9
+ # it under the terms of the GNU General Public License as published by
10
+ # the Free Software Foundation, either version 3 of the License, or
11
+ # (at your option) any later version.
12
+ #
13
+ # This program is distributed in the hope that it will be useful,
14
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ # GNU General Public License for more details.
17
+ #
18
+ # You should have received a copy of the GNU General Public License
19
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
20
+ ################################################################################
21
+
22
+ if RUBY_VERSION =~ /^1.8/ #1.8 doesn't have require_relative
23
+ require File.join(File.expand_path(File.dirname(__FILE__)), "..", "lib", "smc_get", "smc_get")
24
+ require File.join(File.expand_path(File.dirname(__FILE__)), "..", "lib", "smc_get", "cui")
25
+ else
26
+ require_relative "../lib/smc_get/smc_get"
27
+ require_relative "../lib/smc_get/cui"
28
+ end
29
+
30
+ cui = SmcGet::CUI.new(ARGV)
31
+ cui.start
@@ -0,0 +1,205 @@
1
+ # -*- coding: utf-8 -*-
2
+ #!/usr/bin/env ruby
3
+ #Note the user of string hash keys throughout this file. This is
4
+ #due to the package specifications being serialized using YAML,
5
+ #which shouldn't be used with symbols. To prevent the necessity
6
+ #of converting between symbols and strings everywhere a spec needs
7
+ #to be accessed, I just use strings as the hash keys.
8
+
9
+ require "open-uri"
10
+ require "fileutils"
11
+ require "pathname"
12
+ require "tempfile"
13
+ require "psych"
14
+ require "yaml"
15
+ require_relative "../lib/smc_get"
16
+
17
+ PROGNAME = File.basename($0)
18
+
19
+ if ARGV.empty? or ARGV.include?("-h") or ARGV.include?("--help")
20
+ puts(<<HELP)
21
+ USAGE:
22
+ #{PROGNAME} OUTPUT_DIRECTORY
23
+
24
+ Skims through the GitHub SMC repository that contains all source
25
+ files for the SMCPAK files in the main repository and converts
26
+ them all to SMCPAKs. A complete SMC repository is created inside
27
+ OUTPUT_DIRECTORY.
28
+ HELP
29
+ exit
30
+ end
31
+
32
+ Thread.abort_on_exception = true
33
+
34
+ OUTPUT_DIRECTORY = Pathname.new(ARGV.pop)
35
+ SPECS_DIRECTORY = OUTPUT_DIRECTORY + "specs"
36
+ PACKAGES_DIRECTORY = OUTPUT_DIRECTORY + "packages"
37
+ REPO_LIST_FILE = OUTPUT_DIRECTORY + "packages.lst"
38
+
39
+ SOURCE_REPO_BASE_URL = "https://raw.github.com/Luiji/Secret-Maryo-Chronicles-Contributed-Levels/master"
40
+ SPECS_BASE_URL = SOURCE_REPO_BASE_URL + "/packages/"
41
+ PACKAGE_LIST_URL = SPECS_BASE_URL + "packages.lst"
42
+ ELEMENT_BASE_URLS = {
43
+ "levels" => SOURCE_REPO_BASE_URL + "/levels/",
44
+ "graphics" => SOURCE_REPO_BASE_URL + "/graphics/",
45
+ "music" => SOURCE_REPO_BASE_URL + "/music/",
46
+ "sounds" => SOURCE_REPO_BASE_URL + "/sounds/",
47
+ "worlds" => SOURCE_REPO_BASE_URL + "/worlds/"
48
+ }
49
+
50
+ ELEMENT_TEMP_DIRS = {
51
+ "levels" => "levels",
52
+ "graphics" => "pixmaps",
53
+ "music" => "music",
54
+ "sounds" => "sounds",
55
+ "worlds" => "worlds"
56
+ }
57
+
58
+ ########################################
59
+ # Start of code
60
+ ########################################
61
+
62
+ @output_mutex = Mutex.new
63
+ @threads = []
64
+ Thread.abort_on_exception = true
65
+
66
+ def info(str)
67
+ @output_mutex.synchronize do
68
+ puts(str) #TODO: Handling the --quiet option!
69
+ end
70
+ end
71
+
72
+ def error(str)
73
+ @output_mutex.synchronize do
74
+ $stderr.puts(str)
75
+ end
76
+ end
77
+
78
+ def make_spec(name, old_spec, directory)
79
+ new_spec = old_spec.dup
80
+ new_spec["checksums"] = Hash.new{|hsh, k| hsh[k] = Hash.new(&hsh.default_proc)} #Recursive hash
81
+
82
+ #This is a dirty workaround for the fact that the GitHub specs don't obey
83
+ #the specification structure and use a field "last-updated" instead of
84
+ #the correct "last_update" (note the missing 'd' at the end).
85
+ if new_spec["last-updated"]
86
+ $stderr.puts("**WARNING** Invalid field `last-updated' autocorrected to `last_update' for #{name}!")
87
+ new_spec["last_update"] = new_spec.delete("last-updated")
88
+ end
89
+
90
+ #First, go for the similar-structured spec elements
91
+ %w[levels graphics music sounds].each do |str|
92
+ next unless old_spec[str] #May be missing if not needed
93
+
94
+ old_spec[str].each do |file|
95
+ file = Pathname.new(file)
96
+ #Recursively grab the second-to-last item (the last item is the
97
+ #file to check itself which we need to assign a value, the checksum,
98
+ #to). If a file’s parent is "." there’s no need to iterate through the
99
+ #hash as the file is _directly_ inside an element’s toplevel directory
100
+ #(where element is one of "levels", "graphics", etc.).
101
+ hsh = new_spec["checksums"][str]
102
+ file.parent.each_filename{|part| hsh = hsh[part]} unless file.parent.to_s == "."
103
+
104
+ checksum = Digest::SHA1.file(directory + ELEMENT_TEMP_DIRS[str] + file).hexdigest
105
+ hsh[file.basename.to_s] = checksum
106
+ end
107
+ end
108
+
109
+ #Then go for the worlds.
110
+ if old_spec["worlds"] #May be missing if not needed
111
+ old_spec["worlds"].each do |worldname|
112
+ %w[description.xml layer.xml world.xml].each do |filename|
113
+ checksum = Digest::SHA1.file(directory + worldname + filename).hexdigest
114
+ new_spec["checksums"]["worlds"][worldname][filename] = checksum
115
+ end
116
+ end
117
+ end
118
+
119
+ File.open(directory + "#{name}.yml", "w"){|f| YAML.dump(new_spec, f)}
120
+ end
121
+
122
+ #include FileUtils::Verbose #We want to see what’s going on
123
+ include FileUtils
124
+
125
+ #Initialize smc-get
126
+ SmcGet.setup
127
+
128
+ #Setup the bare repository directory structure
129
+ rm_rf OUTPUT_DIRECTORY
130
+ mkdir_p OUTPUT_DIRECTORY
131
+ mkdir PACKAGES_DIRECTORY
132
+ mkdir SPECS_DIRECTORY
133
+
134
+ #Get the list of all available packages
135
+ info("Reading remote package list")
136
+ package_names = open(PACKAGE_LIST_URL){|page| page.readlines.map(&:chomp)}
137
+ skipped = []
138
+
139
+ #Iterate through all the packages
140
+ package_names.each do |pkgname|
141
+ #To speed up the whole thing, do each package in it’s own thread
142
+ @threads << Thread.new do
143
+ #Get the remote package spec
144
+ info("Reading remote package specification for '#{pkgname}'")
145
+ spec_url = SPECS_BASE_URL + "#{pkgname}.yml"
146
+ spec = open(spec_url){|page| YAML.load(page)}
147
+
148
+ #Create a temporary directory just for this sole package
149
+ Dir.mktmpdir do |tmpdir|
150
+ tmpdir = Pathname.new(tmpdir) + pkgname #Package directory must be named the same as the spec file
151
+ mkdir_p tmpdir
152
+
153
+ begin
154
+ #Download all the package’s files into the appropriate directories
155
+ %w[levels graphics music sounds].each do |str|
156
+ next unless spec[str] #Not all specs contain everything
157
+ info("Downloading #{str} for '#{pkgname}'")
158
+
159
+ spec[str].each do |file|
160
+ file = Pathname.new(file)
161
+ downloaded_file = tmpdir + ELEMENT_TEMP_DIRS[str] + file
162
+ mkdir_p downloaded_file.dirname #Subdirectories usually allowed
163
+
164
+ open(ELEMENT_BASE_URLS[str] + URI.escape(file.to_s)) do |page|
165
+ File.open(downloaded_file, "w"){|f| f.write(page.read)}
166
+ end #open URI
167
+ end #each file
168
+ end #each string
169
+
170
+ info("Computing checksums for '#{pkgname}'")
171
+ make_spec(pkgname, spec, tmpdir)
172
+ info("Copying '#{pkgname}' to '#{OUTPUT_DIRECTORY}'")
173
+ pkg = SmcGet::Package.create(tmpdir)
174
+ cp pkg.path, PACKAGES_DIRECTORY
175
+ pkg.spec.save(SPECS_DIRECTORY)
176
+ rescue => e
177
+ skipped << pkgname
178
+ error("**WARNING** Skipping package '#{pkgname}', original error was: #{e.class}: #{e.message}")
179
+ end
180
+ end #mktmpdir
181
+
182
+ end #Thread.new
183
+ end #package_names.each
184
+
185
+ #Wait for all the threads to finish
186
+ @threads.map(&:join)
187
+
188
+ #Write the package list
189
+ converted_packages = package_names - skipped
190
+ File.open(REPO_LIST_FILE, "w"){|f| f.write(converted_packages.join("\n"))}
191
+
192
+ #Print out a summary... Hey, waiting makes curious! ;-)
193
+ puts
194
+ puts "SUMMARY".center(80, "=")
195
+ puts "Packages found in the GitHub repository: #{package_names.count}"
196
+ sleep 2
197
+ puts "Packages converted into .smcpak files: #{converted_packages.count}"
198
+ sleep 2
199
+ puts "Packages skipped due to packaging errors: #{skipped.count}"
200
+ sleep 2
201
+ puts
202
+ print "That is... "
203
+ sleep 3
204
+ percent = ((converted_packages.count.to_f / package_names.count.to_f) * 100).round(2)
205
+ puts "#{percent}% converted correctly! Have fun!"
@@ -0,0 +1,155 @@
1
+ # -*- coding: utf-8 -*-
2
+ #!/usr/bin/env ruby
3
+
4
+ require "open-uri"
5
+ require "fileutils"
6
+ require "pathname"
7
+ require "tempfile"
8
+ require "psych"
9
+ require "yaml"
10
+ require_relative "../lib/smc_get"
11
+
12
+ PROGNAME = File.basename($0)
13
+
14
+
15
+ if ARGV.empty? or ARGV.include?("-h") or ARGV.include?("--help")
16
+ puts(<<HELP)
17
+ USAGE:
18
+ #{PROGNAME} OUTPUT_DIRECTORY
19
+
20
+ Skims through the GitHub SMC repository that contains all source
21
+ files for the SMCPAK files in the main repository and converts
22
+ them all to SMCPAKs. A complete SMC repository is created inside
23
+ OUTPUT_DIRECTORY.
24
+ HELP
25
+ exit
26
+ end
27
+
28
+ OUTPUT_DIRECTORY = Pathname.new(ARGV.pop)
29
+ SPECS_DIRECTORY = OUTPUT_DIRECTORY + "specs"
30
+ PACKAGES_DIRECTORY = OUTPUT_DIRECTORY + "packages"
31
+
32
+ SOURCE_REPO_BASE_URL = "https://raw.github.com/Luiji/Secret-Maryo-Chronicles-Contributed-Levels/master"
33
+ SPECS_BASE_URL = SOURCE_REPO_BASE_URL + "/packages/"
34
+ PACKAGE_LIST_URL = SPECS_BASE_URL + "packages.lst"
35
+ ELEMENT_BASE_URLS = {
36
+ :levels => SOURCE_REPO_BASE_URL + "/levels/",
37
+ :graphics => SOURCE_REPO_BASE_URL + "/graphics/",
38
+ :music => SOURCE_REPO_BASE_URL + "/music/",
39
+ :sounds => SOURCE_REPO_BASE_URL + "/sounds/",
40
+ :worlds => SOURCE_REPO_BASE_URL + "/worlds/"
41
+ }
42
+
43
+ ELEMENT_TEMP_DIRS = {
44
+ :levels => "levels",
45
+ :graphics => "pixmaps",
46
+ :music => "music",
47
+ :sounds => "sounds",
48
+ :worlds => "worlds"
49
+ }
50
+
51
+ ########################################
52
+ # Start of code
53
+ ########################################
54
+
55
+ @output_mutex = Mutex.new
56
+ @threads = []
57
+ Thread.abort_on_exception = true
58
+
59
+ def info(str)
60
+ @output_mutex.synchronize do
61
+ puts(str) #TODO: Handling the --quiet option!
62
+ end
63
+ end
64
+
65
+ def error(str)
66
+ @output_mutex.synchronize do
67
+ $stderr.puts(str)
68
+ end
69
+ end
70
+
71
+ def make_spec(name, old_spec, directory)
72
+ new_spec = old_spec.dup
73
+ new_spec["checksums"] = Hash.new{|hsh, k| hsh[k] = Hash.new(&hsh.default_proc)} #Recursive hash
74
+
75
+ %w[levels graphics music sounds].each do |str|
76
+ old_spec[str].each do |file|
77
+ file = Pathname.new(file)
78
+ hsh = new_spec["checksums"][str]
79
+ file.parent.each_filename{|part| hsh = hsh[part]} #Recursively grabbing second-to-last item
80
+ checksum = Digest::SHA1.file(directory + ELEMENT_TEMP_DIRS[str] + file).hexdigest
81
+ hsh[file.basename.to_s] = checksum
82
+ end
83
+ end
84
+
85
+ old_spec["worlds"].each do |worldname|
86
+ %w[description.xml layer.xml world.xml].each do |filename|
87
+ checksum = Digest::SHA1.file(directory + worldname + filename).hexdigest
88
+ new_spec["checksums"]["worlds"][worldname][filename] = checksum
89
+ end
90
+ end
91
+
92
+ File.open(directory + "#{name}.yml", "w"){|f| YAML.dump(new_spec, f)}
93
+ end
94
+
95
+ def makepkg(directory)
96
+
97
+ end
98
+
99
+ include FileUtils::Verbose #We want to see what’s going on
100
+
101
+ rm_rf OUTPUT_DIRECTORY
102
+ mkdir_p OUTPUT_DIRECTORY
103
+ mkdir PACKAGES_DIRECTORY
104
+ mkdir SPECS_DIRECTORY
105
+
106
+ #Get the list of all available packages
107
+ info("Reading remote package list")
108
+ package_names = open(PACKAGE_LIST_URL){|page| page.readlines.map(&:chomp)}
109
+
110
+ #Iterate through all the packages
111
+ package_names.each do |pkgname|
112
+ #To speed up the whole thing, do each package in it’s own thread
113
+ @threads << Thread.new do
114
+ #Get the remote package spec
115
+ info("Reading remote package specification for '#{pkgname}'")
116
+ spec_url = SPECS_BASE_URL + "#{pkgname}.yml"
117
+ spec = open(spec_url){|page| YAML.load(page)}
118
+
119
+ #Create a temporary directory just for this sole package
120
+ Dir.mktmpdir do |tmpdir|
121
+ tmpdir = Pathname.new(tmpdir)
122
+
123
+ begin
124
+ #Download all the package’s files into the appropriate directories
125
+ [:levels, :graphics, :music, :sounds].each do |sym|
126
+ next unless spec[sym.to_s] #Not all specs contain everything
127
+ info("Downloading #{sym} for '#{pkgname}'")
128
+
129
+ spec[sym.to_s].each do |file|
130
+ file = Pathname.new(file)
131
+ downloaded_file = tmpdir + ELEMENT_TEMP_DIRS[sym] + file
132
+ mkdir_p downloaded_file.dirname #Subdirectories usually allowed
133
+
134
+ open(ELEMENT_BASE_URLS[sym] + URI.escape(file.to_s)) do |page|
135
+ File.open(downloaded_file, "w"){|f| f.write(page.read)}
136
+ end #open URI
137
+ end #each file
138
+ end #each symbol
139
+
140
+ info("Computing checksums for '#{pkgname}'")
141
+ make_spec(pkgname, spec, tmpdir)
142
+ info("Copying '#{pkgname}' to '#{OUTPUT_DIRECTORY}'")
143
+ pkg = SmcGet::Package.create(tmpdir)
144
+ cp pkg.path, PACKAGES_DIRECTORY
145
+ pkg.spec.save(SPECS_DIRECTORY)
146
+ rescue => e
147
+ error("Skipping package '#{pkgname}', original error was: #{e.message}")
148
+ end
149
+ end #mktmpdir
150
+
151
+ end #Thread.new
152
+ end #package_names.each
153
+ info("MAIN PROGRAM FINISHED") #DEBUG
154
+ @threads.map(&:join)
155
+ sleep #DEBUG
@@ -1,32 +1,32 @@
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
- #This is the configuration file for smc-get.
22
- ---
23
- #This is the directory where everything gets installed into.
24
- #Set this to the installation directory of SMC, e.g.
25
- #/usr/share/smc.
26
- data_directory: "/usr/share/smc"
27
- #This is the URL of the repository where packages are downloaded from.
28
- repo_url: "https://raw.github.com/Luiji/Secret-Maryo-Chronicles-Contributed-Levels/master/packages"
29
- #This is the maximum number of tries smc-get makes in order to
30
- #download a package.
31
- max_tries: 3
32
-
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
+ #This is the configuration file for smc-get.
22
+ ---
23
+ #This is the directory where everything gets installed into.
24
+ #Set this to the installation directory of SMC, e.g.
25
+ #/usr/share/smc.
26
+ data_directory: "/usr/share/smc"
27
+ #This is the URL of the repository where packages are downloaded from.
28
+ repo_url: "https://raw.github.com/Quintus/smc-contributed-packages/master"
29
+ #This is the maximum number of tries smc-get makes in order to
30
+ #download a package.
31
+ max_tries: 3
32
+