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.
@@ -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
+