six-updater 0.10.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/LICENSE +3 -0
- data/README +3 -0
- data/Rakefile +49 -0
- data/lib/six/updater-app.rb +51 -0
- data/lib/six/updater.rb +459 -0
- data/lib/six/updater/gitrepo.rb +110 -0
- data/lib/six/updater/mod.rb +355 -0
- data/lib/six/updater/options.rb +130 -0
- data/lib/six/updater/rsyncrepo.rb +73 -0
- metadata +103 -0
data/LICENSE
ADDED
data/README
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
#
|
2
|
+
# To change this template, choose Tools | Templates
|
3
|
+
# and open the template in the editor.
|
4
|
+
|
5
|
+
|
6
|
+
require 'rubygems'
|
7
|
+
require 'rake'
|
8
|
+
require 'rake/clean'
|
9
|
+
require 'rake/gempackagetask'
|
10
|
+
require 'rake/rdoctask'
|
11
|
+
require 'rake/testtask'
|
12
|
+
|
13
|
+
spec = Gem::Specification.new do |s|
|
14
|
+
s.name = 'six-updater'
|
15
|
+
s.version = '0.10.1'
|
16
|
+
s.has_rdoc = true
|
17
|
+
s.extra_rdoc_files = ['README', 'LICENSE']
|
18
|
+
s.summary = 'Your summary here'
|
19
|
+
s.description = s.summary
|
20
|
+
s.author = 'Sickboy'
|
21
|
+
s.email = 'sb@dev-heaven.net'
|
22
|
+
s.add_dependency('log4r', '>= 1.1.0')
|
23
|
+
s.add_dependency('six-rsync', '>= 0.1.0')
|
24
|
+
s.add_dependency('win32-process', '>= 0.6.0')
|
25
|
+
s.add_dependency('win32-shortcut', '>= 0.2.3')
|
26
|
+
# s.executables = ['your_executable_here']
|
27
|
+
s.files = %w(LICENSE README Rakefile) + Dir.glob("{bin,spec}/**/*") + Dir.glob("lib/*/**/*.rb")
|
28
|
+
s.require_path = "lib"
|
29
|
+
s.bindir = "bin"
|
30
|
+
end
|
31
|
+
|
32
|
+
Rake::GemPackageTask.new(spec) do |p|
|
33
|
+
p.gem_spec = spec
|
34
|
+
p.need_tar = true
|
35
|
+
p.need_zip = true
|
36
|
+
end
|
37
|
+
|
38
|
+
Rake::RDocTask.new do |rdoc|
|
39
|
+
files =['README', 'LICENSE', 'lib/**/*.rb']
|
40
|
+
rdoc.rdoc_files.add(files)
|
41
|
+
rdoc.main = "README" # page to start on
|
42
|
+
rdoc.title = "six-arma-updater Docs"
|
43
|
+
rdoc.rdoc_dir = 'doc/rdoc' # rdoc output folder
|
44
|
+
rdoc.options << '--line-numbers'
|
45
|
+
end
|
46
|
+
|
47
|
+
Rake::TestTask.new do |t|
|
48
|
+
t.test_files = FileList['test/**/*.rb']
|
49
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'six/updater/options'
|
2
|
+
require 'six/updater'
|
3
|
+
|
4
|
+
# TODO: Should exec outside the module
|
5
|
+
module Six
|
6
|
+
module Updater
|
7
|
+
if not defined?(Ocra)
|
8
|
+
initialize
|
9
|
+
mods = []
|
10
|
+
puts
|
11
|
+
log.info "Processing:"
|
12
|
+
@config[:folders].each do |config|
|
13
|
+
# TODO: Only display message when there are actually todo's
|
14
|
+
puts
|
15
|
+
log.info "= #{config[:folder]}"
|
16
|
+
mod = Mod.new(config, @config)
|
17
|
+
mods << mod
|
18
|
+
@todo.each { |t| mod.send t }
|
19
|
+
#mod.install
|
20
|
+
end
|
21
|
+
|
22
|
+
puts
|
23
|
+
log.info "Postprocessing:"
|
24
|
+
@config[:folders].each_with_index do |config,index|
|
25
|
+
mod = mods[index]
|
26
|
+
if mod.changed || @config[:force]
|
27
|
+
# TODO: Only display message when there are actually todo's
|
28
|
+
puts
|
29
|
+
log.info "= #{config[:folder]}"
|
30
|
+
@second_todo.each { |t| mod.send t }
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
puts
|
35
|
+
log.info "Processing general tasks:"
|
36
|
+
@general_todo.each { |t| Six::Updater.send t }
|
37
|
+
|
38
|
+
puts
|
39
|
+
log.info "Ready!"
|
40
|
+
|
41
|
+
if @config[:wait]
|
42
|
+
puts
|
43
|
+
log.info "Please press ENTER to exit"
|
44
|
+
STDIN.gets
|
45
|
+
end
|
46
|
+
else
|
47
|
+
gem 'git'
|
48
|
+
require 'git'
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
data/lib/six/updater.rb
ADDED
@@ -0,0 +1,459 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require 'yaml'
|
4
|
+
require 'fileutils'
|
5
|
+
require 'win32/registry'
|
6
|
+
|
7
|
+
gem 'win32-shortcut'
|
8
|
+
require 'win32/shortcut'
|
9
|
+
gem 'log4r'
|
10
|
+
require 'log4r'
|
11
|
+
gem 'six-rsync'
|
12
|
+
require 'six/rsync'
|
13
|
+
gem 'win32-process'
|
14
|
+
require 'win32/process'
|
15
|
+
|
16
|
+
require 'digest/md5'
|
17
|
+
require 'six/updater/mod'
|
18
|
+
#require 'sixupdater/gitrepo'
|
19
|
+
require 'six/updater/rsyncrepo'
|
20
|
+
|
21
|
+
include Six::Repositories
|
22
|
+
|
23
|
+
# Language fix for alternative localizations
|
24
|
+
if RUBY_VERSION == "1.9.1"
|
25
|
+
if defined?(Ocra)
|
26
|
+
(Dir[File.join($:[-2], 'enc/*.so')] + Dir[File.join($:[-2], 'enc/trans/*.so')]).each do |file|
|
27
|
+
require file
|
28
|
+
end
|
29
|
+
end
|
30
|
+
#EXCLUDE = [12]
|
31
|
+
#(1..16).each { |i| require "enc/iso_8859_#{i}" unless EXCLUDE.include? i }
|
32
|
+
#require 'enc/windows_1251'
|
33
|
+
end
|
34
|
+
|
35
|
+
if RUBY_VERSION == "1.8.7"
|
36
|
+
class Array
|
37
|
+
def sample
|
38
|
+
self[rand self.size]
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
module Six
|
44
|
+
# TODO: Evaluate if this module should be a class instead?
|
45
|
+
module Updater
|
46
|
+
VERSION = '0.10.1'
|
47
|
+
COMPONENT = 'six-updater'
|
48
|
+
|
49
|
+
# Configuration
|
50
|
+
ARMA2 = ['SOFTWARE\\Bohemia Interactive Studio\\ArmA 2', 'MAIN']
|
51
|
+
ARMA2_ALT = ['SOFTWARE\\Bohemia Interactive\\ArmA 2', 'InstallPath']
|
52
|
+
ARMA2_STEAM = ['SOFTWARE\\SOFTWARE\\Valve\\Steam\\', 'InstallPath']
|
53
|
+
# Fix for WinXP
|
54
|
+
BASE_PATH = if ENV['OCRA_EXECUTABLE']
|
55
|
+
if ENV['OCRA_EXECUTABLE'][/(.*)[\/|\\].*/]
|
56
|
+
p = $1
|
57
|
+
p.gsub!('\\', '/')
|
58
|
+
p
|
59
|
+
else
|
60
|
+
p = Dir.pwd
|
61
|
+
p.gsub!('\\', '/')
|
62
|
+
p
|
63
|
+
end
|
64
|
+
elsif defined?(TAR2RUBYSCRIPT)
|
65
|
+
if oldlocation
|
66
|
+
oldlocation
|
67
|
+
else
|
68
|
+
Dir.pwd
|
69
|
+
end
|
70
|
+
else
|
71
|
+
p = Dir.pwd
|
72
|
+
p.gsub!('\\', '/')
|
73
|
+
p
|
74
|
+
end
|
75
|
+
TOOL_PATH = File.join(BASE_PATH, 'tools')
|
76
|
+
LOG_LIMIT = 9999
|
77
|
+
# TODO: Allow downloader yml instead?
|
78
|
+
# TODO: Auto update always etc? :D
|
79
|
+
|
80
|
+
@general_todo, @second_todo = [], []
|
81
|
+
|
82
|
+
bpath = BASE_PATH.clone
|
83
|
+
bpath.gsub!('/', '\\')
|
84
|
+
tpath = "#{File.join(bpath, 'tools')};#{File.join(bpath, 'tools', 'bin')}"
|
85
|
+
tpath.gsub!('/', '\\')
|
86
|
+
ENV['PATH'] = "#{ENV['PATH']};#{bpath};#{tpath}"
|
87
|
+
|
88
|
+
# Create config hash with default settings
|
89
|
+
@config = Hash.new
|
90
|
+
@config[:app_params] = '-noSplash -noFilePatching'
|
91
|
+
@config[:app_exe] = 'arma2.exe'
|
92
|
+
@config[:depth] = 1
|
93
|
+
@config[:folders] = []
|
94
|
+
@config[:server] = Hash.new
|
95
|
+
@config[:server_path] = File.join(BASE_PATH, 'servers')
|
96
|
+
@config[:verbose] = false
|
97
|
+
|
98
|
+
# FIXME: Solve this properly!
|
99
|
+
@config[:defaultactions] = [:install]
|
100
|
+
@config[:defaultgeneralactions] = [:createshortcut]
|
101
|
+
@config[:defaultsecondactions] = [:changelog, :cleanup]
|
102
|
+
|
103
|
+
# Create loggers
|
104
|
+
@@log = Log4r::Logger.new(COMPONENT)
|
105
|
+
format1 = if defined?(DEBUG)
|
106
|
+
Log4r::PatternFormatter.new(:pattern => "[%l] %d: %m", :date_pattern => '%H:%M:%S')
|
107
|
+
else
|
108
|
+
Log4r::PatternFormatter.new(:pattern => "%m")
|
109
|
+
end
|
110
|
+
format2 = Log4r::PatternFormatter.new(:pattern => "[%l] %c %d: %m", :date_pattern => '%H:%M:%S')
|
111
|
+
|
112
|
+
|
113
|
+
if not defined?(Ocra)
|
114
|
+
# Create Outputters
|
115
|
+
path = File.join(BASE_PATH, 'logs')
|
116
|
+
FileUtils::mkdir_p path
|
117
|
+
o_file = Log4r::FileOutputter.new "#{COMPONENT}-file",
|
118
|
+
'level' => 0, # All
|
119
|
+
:filename => File.join(path, "#{COMPONENT}.log"),
|
120
|
+
'formatter' => format2
|
121
|
+
#:maxsize => 1024
|
122
|
+
|
123
|
+
@@log.outputters << o_file
|
124
|
+
|
125
|
+
o_out = Log4r::StdoutOutputter.new "#{COMPONENT}-stdout",
|
126
|
+
'level' => 2, # no DEBUG
|
127
|
+
'formatter' => format1
|
128
|
+
|
129
|
+
o_err = Log4r::StderrOutputter.new "#{COMPONENT}-stderr",
|
130
|
+
'level' => 4, # Error and Up
|
131
|
+
'formatter' => format1
|
132
|
+
|
133
|
+
@@log.outputters << o_out << o_err
|
134
|
+
end
|
135
|
+
|
136
|
+
module_function
|
137
|
+
def log
|
138
|
+
@@log
|
139
|
+
end
|
140
|
+
|
141
|
+
def wait
|
142
|
+
STDIN.gets
|
143
|
+
end
|
144
|
+
|
145
|
+
def sure?
|
146
|
+
log.info "Are you really sure? Please press Enter to continue, or close the application to abort."
|
147
|
+
wait
|
148
|
+
end
|
149
|
+
|
150
|
+
def zipcheck
|
151
|
+
begin
|
152
|
+
%x[7z]
|
153
|
+
rescue
|
154
|
+
log.warn "7-zip not found, attempting download!"
|
155
|
+
system "six-downloader.exe \"#{File.join(BASE_PATH, 'six-downloader_7z.yml').gsub('/', '\\')}\" --output \"#{TOOL_PATH.gsub('/', '\\')}\""
|
156
|
+
file = File.join(TOOL_PATH, "7z.exe")
|
157
|
+
unless FileTest.exist?(file)
|
158
|
+
log.error "ERROR: #{file} not found, please download from http://7-zip.org/download.html '7-Zip Command Line Version'"
|
159
|
+
wait
|
160
|
+
Process.exit
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
# General Tasks
|
166
|
+
def joingame
|
167
|
+
cmd = ""
|
168
|
+
cmd << " -connect=#{@config[:server][:address]}" if @config[:server][:address]
|
169
|
+
cmd << " -port=#{@config[:server][:port]}" if @config[:server][:port]
|
170
|
+
cmd << " -password=#{@config[:server][:password]}" if @config[:server][:password]
|
171
|
+
log.info "Starting the game with #{@config[:app_params]} -mod=#{@mods}#{cmd}"
|
172
|
+
cwd = Dir.pwd
|
173
|
+
Dir.chdir @config[:app_path]
|
174
|
+
system "\"#{@config[:app_exe]}\" #{@config[:app_params]} -mod=#{@mods}#{cmd}"
|
175
|
+
Dir.chdir cwd
|
176
|
+
end
|
177
|
+
|
178
|
+
def startgame
|
179
|
+
log.info "Starting the game with #{@config[:app_params]} -mod=#{@mods}"
|
180
|
+
#system "\"#{@config[:app_exe]}\" #{@config[:app_params]} -mod=#{@mods}"
|
181
|
+
begin
|
182
|
+
struct = Process.create(
|
183
|
+
:app_name => File.join(@config[:app_path], @config[:app_exe]),
|
184
|
+
:command_line => "#{@config[:app_params]} -mod=#{@mods}",
|
185
|
+
:creation_flags => Process::DETACHED_PROCESS,
|
186
|
+
:process_inherit => false,
|
187
|
+
:thread_inherit => false,
|
188
|
+
:cwd => @config[:app_path],
|
189
|
+
:inherit => false
|
190
|
+
#:environment => ""
|
191
|
+
)
|
192
|
+
rescue
|
193
|
+
log.warn "WARNING: Something went wrong starting the app: #{@config[:app_exe]}"
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
def shortcut(path)
|
198
|
+
cwd = Dir.pwd
|
199
|
+
Dir.chdir path
|
200
|
+
mods = @mods.clone
|
201
|
+
mods.gsub!(/\//, '-')
|
202
|
+
mods2 = @mods.clone
|
203
|
+
mods2.gsub!('/', '\\')
|
204
|
+
name = "Play ArmA2 with #{mods}.lnk"
|
205
|
+
Win32::Shortcut.new(name) do |shortcut|
|
206
|
+
shortcut.description = "Start Arma2 with #{mods2}"
|
207
|
+
shortcut.path = File.join(@config[:app_path], @config[:app_exe])
|
208
|
+
shortcut.working_directory = @config[:app_path]
|
209
|
+
shortcut.arguments = "#{@config[:app_params]} -mod=#{mods2}"
|
210
|
+
end
|
211
|
+
str = path.clone
|
212
|
+
str.gsub!('/', '\\')
|
213
|
+
log.info "Created shortcut (in #{str}): #{name}"
|
214
|
+
Dir.chdir cwd
|
215
|
+
end
|
216
|
+
|
217
|
+
def createshortcut
|
218
|
+
shortcut @config[:app_path]
|
219
|
+
end
|
220
|
+
|
221
|
+
def createdesktopshortcut
|
222
|
+
shortcut "#{ENV['USERPROFILE']}\\Desktop"
|
223
|
+
end
|
224
|
+
|
225
|
+
def uninstall
|
226
|
+
if @config[:server]
|
227
|
+
if @config[:server][:name]
|
228
|
+
log.info "#{@config[:server][:name]} server"
|
229
|
+
path = File.join(@config[:server_path], @config[:server][:name])
|
230
|
+
if FileTest.exist?(path)
|
231
|
+
log.warn "###########"
|
232
|
+
log.warn "# WARNING #"
|
233
|
+
log.warn "###########"
|
234
|
+
log.warn "You are about to uninstall the specified repository"
|
235
|
+
sure?
|
236
|
+
log.warn 'Uninstalling...'
|
237
|
+
FileUtils.rm_rf path
|
238
|
+
#FileUtils.rm_f @modconfig[:changelog] if FileTest.exists?(@modconfig[:changelog])
|
239
|
+
#FileUtils.rm_f @modconfig[:versionfile] if FileTest.exists?(@modconfig[:versionfile])
|
240
|
+
end
|
241
|
+
end
|
242
|
+
end
|
243
|
+
=begin
|
244
|
+
@config[:folders].each do |config|
|
245
|
+
log.info "= #{config[:folder]}"
|
246
|
+
mod = Mod.new(config, @config)
|
247
|
+
mod.uninstall
|
248
|
+
end
|
249
|
+
=end
|
250
|
+
end
|
251
|
+
|
252
|
+
def setup_git
|
253
|
+
unless @setup_git
|
254
|
+
@setup_git = true
|
255
|
+
# Verify git existence / find git
|
256
|
+
unless @config[:git_path]
|
257
|
+
@config[:git_path] = File.join(TOOL_PATH, 'Git', 'Cmd')
|
258
|
+
unless FileTest.exist?(@config[:git_path])
|
259
|
+
begin
|
260
|
+
%x[git]
|
261
|
+
@config[:git_path] = 'PATH'
|
262
|
+
rescue
|
263
|
+
zipcheck
|
264
|
+
log.warn "Git not configured, nor found in path... Downloading!"
|
265
|
+
# download from http://alturl.com/hn84 into name; git.7z
|
266
|
+
pwd = Dir.pwd
|
267
|
+
Dir.chdir TOOL_PATH
|
268
|
+
file = "portablegit.7z"
|
269
|
+
FileUtils.rm_f file if FileTest.exist?(file)
|
270
|
+
system "six-downloader.exe \"#{File.join(BASE_PATH, 'six-downloader_portablegit.yml').gsub('/', '\\')}\" --output \"#{TOOL_PATH.gsub('/', '\\')}\""
|
271
|
+
dir = File.join(TOOL_PATH, 'Git')
|
272
|
+
FileUtils.rm_rf dir if FileTest.exist?(dir)
|
273
|
+
FileUtils.mkdir_p dir
|
274
|
+
log.info "Unpacking Git..."
|
275
|
+
%x[7z x -oGit \"#{file}\"]
|
276
|
+
FileUtils.rm_f file if FileTest.exist?(file)
|
277
|
+
Dir.chdir pwd
|
278
|
+
end
|
279
|
+
end
|
280
|
+
end
|
281
|
+
unless @config[:git_path] == 'PATH'
|
282
|
+
path = @config[:git_path].clone
|
283
|
+
path.gsub!('/','\\')
|
284
|
+
ENV['PATH'] = "#{ENV['PATH']};#{path}" if path.size > 0 #unless ENV['PATH'][/git/] # ??
|
285
|
+
end
|
286
|
+
|
287
|
+
log.info "Using Git at: #{@config[:git_path]}"
|
288
|
+
puts
|
289
|
+
|
290
|
+
# FIXME: This is naughty but due to portable git config setting, and this module's git version check, we must run this after initialize :/
|
291
|
+
gem 'git'
|
292
|
+
require 'git'
|
293
|
+
end
|
294
|
+
end
|
295
|
+
|
296
|
+
def initialize
|
297
|
+
# Banner
|
298
|
+
log.info "Updater (v#{VERSION}) by Sickboy <sb_at_dev-heaven.net>"
|
299
|
+
log.info 'Run with --help for help'
|
300
|
+
log.warn "WARNING: Please make sure anything ArmA related has been closed / shutdown, incl explorer windows, etc"
|
301
|
+
log.debug "BASE_PATH: #{BASE_PATH}"
|
302
|
+
log.debug "TOOL_PATH: #{TOOL_PATH}"
|
303
|
+
log.debug "@config #{@config}"
|
304
|
+
|
305
|
+
# Process the config file
|
306
|
+
config = "#{COMPONENT}.yml"
|
307
|
+
config = File.join(BASE_PATH, config)
|
308
|
+
if ARGV[0]
|
309
|
+
# FIXME: This is not a very good catch..
|
310
|
+
if ARGV[0][/.*\..*/]
|
311
|
+
if FileTest.exist?(ARGV[0])
|
312
|
+
config = ARGV[0]
|
313
|
+
else
|
314
|
+
log.warn "#{ARGV[0]} not found, trying #{config}"
|
315
|
+
end
|
316
|
+
end
|
317
|
+
end
|
318
|
+
|
319
|
+
unless FileTest.exist?(config)
|
320
|
+
log.error "ERROR: #{config} config missing!"
|
321
|
+
wait
|
322
|
+
Process.exit
|
323
|
+
end
|
324
|
+
|
325
|
+
File.open(config) { |file| @config.merge!(YAML::load(file)) }
|
326
|
+
@config[:folders] = [] unless @config[:folders]
|
327
|
+
@config[:server][:folders] = [] unless @config[:server][:folders]
|
328
|
+
|
329
|
+
# Parses CLI Parameters, merges configuration and gets todo list
|
330
|
+
parse_options
|
331
|
+
|
332
|
+
# Backwards compatibility
|
333
|
+
@config[:app_path] = @config[:armapath] if @config[:armapath]
|
334
|
+
@config[:app_exe] = @config[:armaexe] if @config[:armaexe]
|
335
|
+
@config[:app_params] = @config[:armaparams] if @config[:armaparams]
|
336
|
+
@config[:git_path] = @config[:gitpath] if @config[:gitpath]
|
337
|
+
@config[:server_path] = @config[:serverpath] if @config[:serverpath]
|
338
|
+
|
339
|
+
# Determine arma distribution and location
|
340
|
+
unless @config[:app_path]
|
341
|
+
begin
|
342
|
+
@config[:app_path] = Win32::Registry.open(Win32::Registry::HKEY_LOCAL_MACHINE, ARMA2_STEAM[0])[ARMA2_STEAM[1]]
|
343
|
+
log.info "ArmA 2 Steam Distribution detected"
|
344
|
+
rescue
|
345
|
+
begin
|
346
|
+
@config[:app_path] = Win32::Registry.open(Win32::Registry::HKEY_LOCAL_MACHINE, ARMA2_ALT[0])[ARMA2_ALT[1]]
|
347
|
+
log.info "ArmA 2 Alt Distribution detected"
|
348
|
+
rescue
|
349
|
+
begin
|
350
|
+
@config[:app_path] = Win32::Registry.open(Win32::Registry::HKEY_LOCAL_MACHINE, ARMA2[0])[ARMA2[1]]
|
351
|
+
log.info "ArmA 2 Standard Distribution detected"
|
352
|
+
rescue
|
353
|
+
log.warn "No (known) ArmA 2 Distribution detected"
|
354
|
+
end
|
355
|
+
end
|
356
|
+
end
|
357
|
+
end
|
358
|
+
|
359
|
+
# Verify installation folder
|
360
|
+
if @config[:app_path]
|
361
|
+
log.info "Installation Path: #{@config[:app_path]}"
|
362
|
+
if FileTest.exists?(@config[:app_path])
|
363
|
+
@config[:app_path].gsub!('\\', '/')
|
364
|
+
else
|
365
|
+
log.error "No valid installation folder found, please abort!"
|
366
|
+
wait
|
367
|
+
Process.exit
|
368
|
+
end
|
369
|
+
else
|
370
|
+
log.error "No valid installation folder found, please abort!"
|
371
|
+
wait
|
372
|
+
Process.exit
|
373
|
+
end
|
374
|
+
|
375
|
+
# Nasty workaround for cygwin on Vista vs XP, vs acl's
|
376
|
+
=begin
|
377
|
+
@config[:app_path][/\A(\w\:)/]
|
378
|
+
str = "#{$1}/ /six-app-root ntfs noacl 0 0"
|
379
|
+
etc = File.join(TOOL_PATH, 'etc')
|
380
|
+
FileUtils.mkdir_p etc
|
381
|
+
File.open(File.join(etc, 'fstab'), 'w') { |file| file.puts str }
|
382
|
+
ENV['six-app-root'] = '/six-app-root'
|
383
|
+
=end
|
384
|
+
puts
|
385
|
+
if @config[:server][:repository]
|
386
|
+
log.info "Checking for latest updates of #{@config[:server][:name]} server info"
|
387
|
+
path = File.join(@config[:server_path], @config[:server][:name])
|
388
|
+
|
389
|
+
opts = {}
|
390
|
+
opts.merge!({:log => log}) if @config[:verbose]
|
391
|
+
|
392
|
+
case @config[:server][:repository][0]
|
393
|
+
when /\Agit:\/\//
|
394
|
+
repo = GitRepo.new(@config[:server][:repository], path)
|
395
|
+
when /\Arsync:\/\//
|
396
|
+
repo = RsyncRepo.new(@config[:server][:repository], path)
|
397
|
+
end
|
398
|
+
|
399
|
+
if FileTest.exist?(File.join(path, '.git')) || FileTest.exist?(File.join(path, '.rsync'))
|
400
|
+
repo.reset(:hard => true)
|
401
|
+
repo.update
|
402
|
+
else
|
403
|
+
#FileUtils::mkdir_p path
|
404
|
+
repo.clone
|
405
|
+
end
|
406
|
+
|
407
|
+
begin
|
408
|
+
srv = File.join(path, 'server.yml')
|
409
|
+
File.open(srv) do |f|
|
410
|
+
cfg = YAML::load(f)
|
411
|
+
@config[:folders].each do |f|
|
412
|
+
cfg[:folders].each do |f2|
|
413
|
+
@config[:folders] -= [f] if f2[:folder] == f[:folder]
|
414
|
+
end
|
415
|
+
end
|
416
|
+
@config[:folders] = cfg[:folders] + @config[:folders]
|
417
|
+
@config[:server] = cfg.merge @config[:server]
|
418
|
+
end
|
419
|
+
rescue
|
420
|
+
log.warn "WARNING: Server configured but unable to get data from repository"
|
421
|
+
end
|
422
|
+
end
|
423
|
+
|
424
|
+
@config[:folders].uniq!
|
425
|
+
log.debug "@config #{@config}"
|
426
|
+
|
427
|
+
# PreProcess the config data
|
428
|
+
@mods = []
|
429
|
+
@mods << @config[:mods] if @config[:mods]
|
430
|
+
|
431
|
+
@config[:folders].each do |folder|
|
432
|
+
folder[:folder].gsub!('\\', '/')
|
433
|
+
if folder[:mods]
|
434
|
+
@mods << folder[:mods]
|
435
|
+
else
|
436
|
+
@mods << folder[:folder]
|
437
|
+
end
|
438
|
+
end
|
439
|
+
@mods = @mods.join(';')
|
440
|
+
|
441
|
+
# Output processed config data
|
442
|
+
log.info "Manager for: #{@mods}"
|
443
|
+
|
444
|
+
|
445
|
+
# Prepare stats
|
446
|
+
@stats = []
|
447
|
+
@config[:folders].each do |folder|
|
448
|
+
stat = Hash.new
|
449
|
+
@stats << stat
|
450
|
+
path = File.join(@config[:app_path], folder[:folder])
|
451
|
+
stat[:changelog] = []
|
452
|
+
end
|
453
|
+
end
|
454
|
+
end
|
455
|
+
end
|
456
|
+
|
457
|
+
# TODO: Evaluate position
|
458
|
+
if $0 == __FILE__
|
459
|
+
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
module Six
|
4
|
+
module Updater
|
5
|
+
class GitRepo
|
6
|
+
def initialize(repositories, path, depth = 1)
|
7
|
+
@repositories = repositories
|
8
|
+
@path = path
|
9
|
+
@depth = depth
|
10
|
+
Six::Updater.setup_git
|
11
|
+
end
|
12
|
+
|
13
|
+
def open
|
14
|
+
repository
|
15
|
+
end
|
16
|
+
|
17
|
+
def repository
|
18
|
+
@repository || Git.open(@path)
|
19
|
+
end
|
20
|
+
|
21
|
+
def log
|
22
|
+
Six::Updater.log
|
23
|
+
end
|
24
|
+
|
25
|
+
def reset(opts = {})
|
26
|
+
repository.reset(nil, opts)
|
27
|
+
end
|
28
|
+
|
29
|
+
def clone(opts = {})
|
30
|
+
repositories = @repositories.clone
|
31
|
+
done = false
|
32
|
+
opts[:depth] = @depth
|
33
|
+
while repositories.size > 0 && !done
|
34
|
+
rep = repositories.sample
|
35
|
+
repositories -= [rep]
|
36
|
+
log.info "Trying #{rep}"
|
37
|
+
|
38
|
+
begin
|
39
|
+
Git.clone(rep, @path, opts)
|
40
|
+
Git.open(@path).config("core.autocrlf", "false")
|
41
|
+
done = true
|
42
|
+
rescue
|
43
|
+
log.debug "WARNING: Failed, trying other mirrors if available"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
log.warn "WARNING: Failed, was unable to clone!" unless done
|
47
|
+
done
|
48
|
+
end
|
49
|
+
|
50
|
+
def version
|
51
|
+
repository.log.first.to_s
|
52
|
+
end
|
53
|
+
|
54
|
+
def update(opts = {})
|
55
|
+
done = false
|
56
|
+
repositories = @repositories.clone
|
57
|
+
while repositories.size > 0 && !done
|
58
|
+
cfg = nil
|
59
|
+
File.open(File.join(@path, '.git/config')) { |file| cfg = file.readlines }
|
60
|
+
rep = ''
|
61
|
+
cfg.map! do |entry|
|
62
|
+
if entry[/(\t*)url \=/]
|
63
|
+
rep = repositories.sample
|
64
|
+
repositories -= [rep]
|
65
|
+
"#{$1}url = #{rep}"
|
66
|
+
else
|
67
|
+
entry
|
68
|
+
end
|
69
|
+
end
|
70
|
+
log.info "Trying #{rep}"
|
71
|
+
File.open(File.join(@path, '.git/config'), 'w') { |file| file.puts cfg }
|
72
|
+
begin
|
73
|
+
repository.config("core.autocrlf", "false")
|
74
|
+
repository.pull_legacy
|
75
|
+
done = true
|
76
|
+
rescue
|
77
|
+
log.debug "WARNING: Failed, trying other mirrors if available"
|
78
|
+
end
|
79
|
+
end
|
80
|
+
log.warn "WARNING: Failed, was unable to update!" unless done
|
81
|
+
done
|
82
|
+
end
|
83
|
+
|
84
|
+
def status(force = false)
|
85
|
+
if force || !@status
|
86
|
+
@status = status_update
|
87
|
+
end
|
88
|
+
@status
|
89
|
+
end
|
90
|
+
|
91
|
+
def check_status(type, array, msg)
|
92
|
+
str = []
|
93
|
+
if array.size > 0
|
94
|
+
str << "#{type}:"
|
95
|
+
array.each { |item| str << item[0] }
|
96
|
+
msg << str.join("\n")
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def status_update
|
101
|
+
msg = []
|
102
|
+
[
|
103
|
+
['Added', repository.status.added], ['Changed', repository.status.changed],
|
104
|
+
['Deleted', repository.status.deleted], ['Untracked', repository.status.untracked]
|
105
|
+
].each { |entry| check_status(entry[0], entry[1], msg) }
|
106
|
+
msg
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
@@ -0,0 +1,355 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
module Six
|
4
|
+
module Updater
|
5
|
+
class Mod
|
6
|
+
def initialize(modconfig, config)
|
7
|
+
@modconfig = modconfig
|
8
|
+
@config = config
|
9
|
+
@stat = Hash.new
|
10
|
+
@stat[:changelog] = []
|
11
|
+
@stat[:current], @stat[:previous] = "A", "B"
|
12
|
+
@path = File.join(@config[:app_path], @modconfig[:folder])
|
13
|
+
get_repositories
|
14
|
+
|
15
|
+
@modconfig[:folder].gsub!('\\', '/')
|
16
|
+
@folder_str = @modconfig[:folder].clone
|
17
|
+
@folder_str.gsub!('/', '-')
|
18
|
+
|
19
|
+
# TODO: Implement this into the real modfolder so it can be verified by the server you join? - 'exclude version.txt' (.gitignore)
|
20
|
+
if @modconfig[:versionfile]
|
21
|
+
@modconfig[:versionfile] = File.join(@config[:app_path], @modconfig[:folder], @modconfig[:versionfile])
|
22
|
+
else
|
23
|
+
@modconfig[:versionfile] = File.join(@config[:app_path], @modconfig[:folder], '.version.txt')
|
24
|
+
end
|
25
|
+
if @modconfig[:changelog]
|
26
|
+
@modconfig[:changelog] = File.join(@config[:app_path], @modconfig[:folder], @modconfig[:changelog])
|
27
|
+
else
|
28
|
+
@modconfig[:changelog] = File.join(BASE_PATH, 'changelogs', "Changelog_#{@folder_str}.txt")
|
29
|
+
end
|
30
|
+
|
31
|
+
unless @modconfig[:depth]
|
32
|
+
@modconfig[:depth] = @config[:depth]
|
33
|
+
end
|
34
|
+
|
35
|
+
@changed = false
|
36
|
+
|
37
|
+
|
38
|
+
# TODO: Handle proper Git class handling for non existent repository / not a git repos
|
39
|
+
# TODO: Git.open requires git to be required, which in turn requires a git binary. Should not be required for uninstall for example.
|
40
|
+
@installed = if FileTest.exists?(File.join(@path, '.git'))
|
41
|
+
# begin
|
42
|
+
@repository = GitRepo.new(@modconfig[:repository], @path)
|
43
|
+
true
|
44
|
+
# rescue
|
45
|
+
# log.warn "WARNING: Could not open #{@path}"
|
46
|
+
# false
|
47
|
+
# end
|
48
|
+
elsif FileTest.exists?(File.join(@path, '.rsync'))
|
49
|
+
# begin
|
50
|
+
@repository = RsyncRepo.new(@modconfig[:repository], @path, :log => log)
|
51
|
+
true
|
52
|
+
# rescue
|
53
|
+
# log.warn "WARNING: Could not open #{@path}"
|
54
|
+
# false
|
55
|
+
# end
|
56
|
+
else
|
57
|
+
false
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def get_repositories
|
62
|
+
cfg = File.join(@path, '.repositories.yml')
|
63
|
+
@repositories = if FileTest.exist?(cfg)
|
64
|
+
File.open(cfg) { |file| YAML::load(file) }
|
65
|
+
elsif @modconfig[:repository].class == Array
|
66
|
+
@modconfig[:repository]
|
67
|
+
else
|
68
|
+
[@modconfig[:repository]]
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def log
|
73
|
+
Six::Updater.log
|
74
|
+
end
|
75
|
+
|
76
|
+
def changed
|
77
|
+
@changed
|
78
|
+
end
|
79
|
+
|
80
|
+
def sure?
|
81
|
+
Six::Updater.sure?
|
82
|
+
end
|
83
|
+
|
84
|
+
def log_status
|
85
|
+
log.warn "Status: #{@repository.status.join("\n")}" if @repository.status.size > 0
|
86
|
+
end
|
87
|
+
|
88
|
+
def not_a_repository
|
89
|
+
log.warn "Does not seem to be a repository!"
|
90
|
+
end
|
91
|
+
|
92
|
+
def write_version
|
93
|
+
@modconfig[:versionfile][/(.*)\/(.*)/]
|
94
|
+
folder = $1
|
95
|
+
FileUtils.mkdir_p folder unless FileTest.exists? folder
|
96
|
+
begin
|
97
|
+
File.open(@modconfig[:versionfile], 'w') { |file| file.puts @stat[:current] }
|
98
|
+
true
|
99
|
+
rescue
|
100
|
+
log.warn "WARNING: Unable to write version.txt file, please make sure everything arma is closed, etc"
|
101
|
+
false
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
# Process Comment Changelog
|
106
|
+
def write_changelog
|
107
|
+
str = "#{@stat[:current]}"
|
108
|
+
str += " - #{@stat[:previous]}" if @stat[:previous]
|
109
|
+
log.info str
|
110
|
+
|
111
|
+
history = @repository.repository.log(LOG_LIMIT)
|
112
|
+
@stat[:changelog] = []
|
113
|
+
if @stat[:previous]
|
114
|
+
history.between(@stat[:previous], @stat[:current]).each do |c|
|
115
|
+
c.message.split("\n").each { |msg| @stat[:changelog] << msg }
|
116
|
+
end
|
117
|
+
else
|
118
|
+
history.each do |c|
|
119
|
+
c.message.split("\n").each { |msg| @stat[:changelog] << msg }
|
120
|
+
end
|
121
|
+
# DONT SORT, otherwise all messed up stuff :)
|
122
|
+
#@stat[:changelog].sort!
|
123
|
+
end
|
124
|
+
|
125
|
+
# TODO: Clean empty lines etc
|
126
|
+
content = "== #{str}\n"
|
127
|
+
content += @stat[:changelog].join("\n")
|
128
|
+
content += "\n\n"
|
129
|
+
File.open(@modconfig[:changelog], 'r') { |file| content += file.read } if FileTest.exists?(@modconfig[:changelog])
|
130
|
+
@modconfig[:changelog][/(.*)\/(.*)/]
|
131
|
+
folder = $1
|
132
|
+
FileUtils.mkdir_p folder unless FileTest.exists? folder
|
133
|
+
File.open(@modconfig[:changelog], 'w') { |file| file.write content }
|
134
|
+
end
|
135
|
+
|
136
|
+
def changelog
|
137
|
+
unless @installed
|
138
|
+
not_a_repository
|
139
|
+
return
|
140
|
+
end
|
141
|
+
|
142
|
+
unless @stat[:previous] == @stat[:current]
|
143
|
+
log.info 'Playing log...'
|
144
|
+
@stat[:changelog].each do |msg|
|
145
|
+
log.debug msg # TODO: Necessary?
|
146
|
+
puts msg
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
def process(command)
|
152
|
+
# TODO: Exception handling, incase working folder was modified
|
153
|
+
log.info "Processing: #{@modconfig[:folder]} (#{command})"
|
154
|
+
cwd = Dir.pwd
|
155
|
+
if FileTest.exist?(@path)
|
156
|
+
Dir.chdir @path
|
157
|
+
system "git #{command}"
|
158
|
+
Dir.chdir cwd
|
159
|
+
else
|
160
|
+
log.warn "WARNING: Can't find folder. Folder does not seem to exist"
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
# CLEANUP Process (repack -ad / gc --agressive / --auto)
|
165
|
+
# TODO: run with --aggressive every 100 commits or so :O | Evaluate repack -adf f being more aggressive?
|
166
|
+
# Is aggressive usable yet? http://metalinguist.wordpress.com/2007/12/06/the-woes-of-git-gc-aggressive-and-how-git-deltas-work/
|
167
|
+
def cleanup
|
168
|
+
unless @installed
|
169
|
+
not_a_repository
|
170
|
+
return
|
171
|
+
end
|
172
|
+
unless @stat[:previous] == @stat[:current]
|
173
|
+
log.info 'Cleaning...'
|
174
|
+
if @modconfig[:repository][0][/\Agit:\/\//]
|
175
|
+
@repository.repository.gc_legacy
|
176
|
+
@repository.repository.repack
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
# RESET process (incase everything FOOKED :D)
|
182
|
+
def reset
|
183
|
+
unless @installed
|
184
|
+
not_a_repository
|
185
|
+
return
|
186
|
+
end
|
187
|
+
log.warn "###########"
|
188
|
+
log.warn "# WARNING #"
|
189
|
+
log.warn "###########"
|
190
|
+
log.warn "You are about to reset and loose all local changes in the specified repository"
|
191
|
+
log_status
|
192
|
+
sure?
|
193
|
+
log.info 'Resetting...'
|
194
|
+
@repository.repository.reset(nil, {:hard => true})
|
195
|
+
end
|
196
|
+
|
197
|
+
# UPDATE Process
|
198
|
+
def update
|
199
|
+
unless @installed
|
200
|
+
not_a_repository
|
201
|
+
return
|
202
|
+
end
|
203
|
+
|
204
|
+
log.info 'Updating... This might take a while, please wait.'
|
205
|
+
@stat[:previous] = @repository.version
|
206
|
+
done = @repository.update
|
207
|
+
@stat[:current] = @repository.version
|
208
|
+
|
209
|
+
begin
|
210
|
+
@repository.status(true)
|
211
|
+
rescue
|
212
|
+
log.warn 'WARNING: Update seems to have completed but there was a status error..'
|
213
|
+
log_status
|
214
|
+
end
|
215
|
+
|
216
|
+
if @stat[:previous] == @stat[:current]
|
217
|
+
log.info "No updates found"
|
218
|
+
write_version # DO this always incase previous version.txt failed for whatever reason!
|
219
|
+
else
|
220
|
+
@changed = true
|
221
|
+
if write_version
|
222
|
+
#write_changelog
|
223
|
+
else
|
224
|
+
@repository.reset(@stat[:previous], {:hard => true})
|
225
|
+
@changed = false
|
226
|
+
@stat[:current] = @stat[:previous]
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
unless done
|
231
|
+
log.warn 'WARNING: Update was unable to complete. This could be due to a server / connection problem, or due to files in use or out of synch repositories. Please make sure ArmA is closed, retry, otherwise reset and retry'
|
232
|
+
log_status
|
233
|
+
# TODO: Add display of stats for changed files etc
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
# INSTALL process
|
238
|
+
def install
|
239
|
+
log.debug "Path: #{@path}"
|
240
|
+
if @installed
|
241
|
+
log.info "Already installed, trying to update..."
|
242
|
+
update
|
243
|
+
else
|
244
|
+
if FileTest.exist?(@path)
|
245
|
+
log.info "WARNING: Folder already exists but does not seem to be a repository. Not installing"
|
246
|
+
else
|
247
|
+
log.info "Installing (depth: #{@modconfig[:depth]})... This might take a while, please wait."
|
248
|
+
folder = ''
|
249
|
+
if @modconfig[:folder][/(.*)\/(.*)/]
|
250
|
+
basepath, subfolder = $1, $2
|
251
|
+
basepath = File.join(@config[:app_path], basepath)
|
252
|
+
FileUtils.mkdir_p basepath unless FileTest.exist?(basepath)
|
253
|
+
#Dir.chdir basepath
|
254
|
+
#folder = File.join(basepath, subfolder)
|
255
|
+
end
|
256
|
+
|
257
|
+
file = File.join(BASE_PATH, "#{@folder_str}.7z")
|
258
|
+
if FileTest.exist?(file)
|
259
|
+
log.info "Found #{@folder_str}.7z, using it"
|
260
|
+
Six::Updater.zipcheck
|
261
|
+
FileUtils.mkdir_p @path
|
262
|
+
cmd = "7z x -o\"#{@path}\" \"#{file}\""
|
263
|
+
log.debug cmd
|
264
|
+
output = %x[#{cmd}]
|
265
|
+
log.debug output
|
266
|
+
begin
|
267
|
+
open
|
268
|
+
@repository.reset(nil, {:hard => true})
|
269
|
+
@installed = true
|
270
|
+
get_repositories
|
271
|
+
update
|
272
|
+
rescue
|
273
|
+
log.warn "WARNING: Failed to open the repository, not installed!"
|
274
|
+
end
|
275
|
+
else
|
276
|
+
@repository = if @repositories[0][/\Arsync:\/\//]
|
277
|
+
RsyncRepo.new(@repositories, @path, @modconfig[:depth])
|
278
|
+
else
|
279
|
+
GitRepo.new(@repositories, @path, @modconfig[:depth])
|
280
|
+
end
|
281
|
+
opts = {}
|
282
|
+
opts.merge!({:log => log}) if @config[:verbose]
|
283
|
+
@installed = @repository.clone(opts)
|
284
|
+
unless @installed
|
285
|
+
log.warn "WARNING: Failed to download the repository! This could be due to a server / connection problem. Please try again later"
|
286
|
+
end
|
287
|
+
end
|
288
|
+
|
289
|
+
if @installed
|
290
|
+
@changed = true
|
291
|
+
@stat[:previous] = nil
|
292
|
+
begin
|
293
|
+
@stat[:current] = @repository.version
|
294
|
+
if @modconfig[:repository][0][/git:\/\//]
|
295
|
+
@repository.status(true)
|
296
|
+
FileUtils.rm_f @modconfig[:changelog] if FileTest.exists?(@modconfig[:changelog])
|
297
|
+
end
|
298
|
+
write_version
|
299
|
+
#write_changelog
|
300
|
+
rescue
|
301
|
+
log.warn 'WARNING: Post installation was unable to complete. This could be due to a server / connection problem. Please try again later'
|
302
|
+
FileUtils::rm_rf(@path) if FileTest.exist?(@path)
|
303
|
+
end
|
304
|
+
begin
|
305
|
+
userconfig
|
306
|
+
rescue
|
307
|
+
log.warn 'WARNING: Userconfig processing is unable to complete.'
|
308
|
+
end
|
309
|
+
else
|
310
|
+
FileUtils::rm_rf(@path) if FileTest.exist?(@path)
|
311
|
+
end
|
312
|
+
end
|
313
|
+
end
|
314
|
+
end
|
315
|
+
|
316
|
+
# UNINSTALL process
|
317
|
+
def uninstall
|
318
|
+
if FileTest.exist?(@path)
|
319
|
+
log.warn "###########"
|
320
|
+
log.warn "# WARNING #"
|
321
|
+
log.warn "###########"
|
322
|
+
log.warn "You are about to uninstall the specified repository"
|
323
|
+
sure?
|
324
|
+
log.warn 'Uninstalling...'
|
325
|
+
FileUtils.rm_rf @path
|
326
|
+
FileUtils.rm_f @modconfig[:changelog] if FileTest.exists?(@modconfig[:changelog])
|
327
|
+
FileUtils.rm_f @modconfig[:versionfile] if FileTest.exists?(@modconfig[:versionfile])
|
328
|
+
end
|
329
|
+
# TODO: Cleanup Userconfig ?
|
330
|
+
end
|
331
|
+
|
332
|
+
# Process userconfigs
|
333
|
+
# TODO: Add this processing to update, aka; IF userconfig has changed THEN update it
|
334
|
+
def userconfig
|
335
|
+
unless @installed
|
336
|
+
not_a_repository
|
337
|
+
return
|
338
|
+
end
|
339
|
+
# TODO: Process this on file level instead of folder level?
|
340
|
+
time = Time.now.to_i
|
341
|
+
f = @modconfig[:folder].clone
|
342
|
+
f.gsub!('@', '')
|
343
|
+
path = File.join(@path, 'userconfig')
|
344
|
+
uconfig = File.join(@config[:app_path], 'userconfig')
|
345
|
+
uconfigpath = File.join(uconfig, f)
|
346
|
+
if FileTest.exist?(path)
|
347
|
+
log.info "Found userconfig, processing..."
|
348
|
+
FileUtils::mv(uconfigpath, "#{uconfigpath}_#{time}") if FileTest.exist?(uconfigpath)
|
349
|
+
FileUtils::mkdir_p uconfig unless FileTest.exist?(uconfig)
|
350
|
+
FileUtils::cp_r(path, uconfigpath)
|
351
|
+
end
|
352
|
+
end
|
353
|
+
end
|
354
|
+
end
|
355
|
+
end
|
@@ -0,0 +1,130 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
# Docu: http://www.ruby-doc.org/stdlib/libdoc/optparse/rdoc/classes/OptionParser.html
|
4
|
+
require 'optparse'
|
5
|
+
|
6
|
+
module Six
|
7
|
+
module Updater
|
8
|
+
module_function
|
9
|
+
def parse_options
|
10
|
+
todo, general_todo, second_todo = [], [], []
|
11
|
+
|
12
|
+
options = Hash.new
|
13
|
+
OptionParser.new do |opts|
|
14
|
+
$0[/.*\/(.*)/]
|
15
|
+
opts.banner = "Usage: #{$1} [config.yml] [options]"
|
16
|
+
|
17
|
+
opts.on("-v", "--[no-]verbose", "Run verbosely") do |v|
|
18
|
+
options[:verbose] = v
|
19
|
+
end
|
20
|
+
|
21
|
+
opts.on("-i", "--install", "Installs the mods, unless already installed") do |bool|
|
22
|
+
todo << :install if bool
|
23
|
+
end
|
24
|
+
|
25
|
+
opts.on("-d", "--uninstall", "Uninstalls the mods, unless not installed") do |bool|
|
26
|
+
todo << :uninstall if bool
|
27
|
+
end
|
28
|
+
|
29
|
+
opts.on("-u", "--update", "Updates each mod to latest version") do |bool|
|
30
|
+
todo << :update if bool
|
31
|
+
end
|
32
|
+
|
33
|
+
opts.on("-r", "--reset", "Resets the modfolders to latest commit status. All modifications lost") do |bool|
|
34
|
+
todo << :reset if bool
|
35
|
+
end
|
36
|
+
|
37
|
+
opts.on("-z", "--userconfig", "Processes the userconfigs of each mod. Makes backups of previous files") do |bool|
|
38
|
+
todo << :userconfig if bool
|
39
|
+
end
|
40
|
+
|
41
|
+
opts.on("-l", "--changelog", "Display Changelog after update") do |bool|
|
42
|
+
second_todo << :changelog if bool
|
43
|
+
end
|
44
|
+
|
45
|
+
opts.on("-c", "--cleanup", "Cleans up the modfolders git repositories") do |bool|
|
46
|
+
second_todo << :cleanup if bool
|
47
|
+
end
|
48
|
+
|
49
|
+
opts.on("-s", "--createshortcut", "Creates shortcut to run the game with the mods, in installation folder") do |bool|
|
50
|
+
general_todo << :createshortcut if bool
|
51
|
+
end
|
52
|
+
|
53
|
+
opts.on("-k", "--createdesktopshortcut", "Creates shortcut to run the game with the mods, on the desktop") do |bool|
|
54
|
+
general_todo << :createdesktopshortcut if bool
|
55
|
+
end
|
56
|
+
|
57
|
+
opts.on("-j", "--join", "Starts the game with #{@config[:app_params]} -mod=#{@mods} -connect=#{@config[:server][:address]} -port=#{@config[:server][:port]}") do |bool|
|
58
|
+
general_todo << :joingame if bool
|
59
|
+
end
|
60
|
+
|
61
|
+
opts.on("-g", "--startgame", "Starts the game with #{@config[:app_params]} -mod=#{@mods}") do |bool|
|
62
|
+
general_todo << :startgame if bool
|
63
|
+
end
|
64
|
+
|
65
|
+
opts.on("-w", "--wait", "Waits at the end for user pressing ENTER") do |bool|
|
66
|
+
options[:wait] = bool
|
67
|
+
end
|
68
|
+
|
69
|
+
opts.on("-f", "--force", "Forces to run tasks even though no changes were detected") do |bool|
|
70
|
+
options[:force] = bool
|
71
|
+
end
|
72
|
+
|
73
|
+
opts.on("--depth I", Integer, "Clone depth, default: #{@config[:depth]}. Set to 0 to clone all history") do |s|
|
74
|
+
options[:depth] = s
|
75
|
+
end
|
76
|
+
|
77
|
+
opts.on("--mods S", String, "Additional Mods") do |s|
|
78
|
+
options[:mods] = s
|
79
|
+
end
|
80
|
+
|
81
|
+
opts.on("--armapath S", String, "Destination folder") do |s|
|
82
|
+
options[:armapath] = s
|
83
|
+
end
|
84
|
+
|
85
|
+
opts.on("--gitpath S", String, "Git binary") do |s|
|
86
|
+
options[:gitpath] = s
|
87
|
+
end
|
88
|
+
end.parse!
|
89
|
+
|
90
|
+
default = if (todo + second_todo + general_todo).size > 0
|
91
|
+
false
|
92
|
+
else
|
93
|
+
true
|
94
|
+
end
|
95
|
+
|
96
|
+
# TODO: Move this to Updater ?
|
97
|
+
@todo = if todo.size > 0
|
98
|
+
todo
|
99
|
+
else
|
100
|
+
log.info "No parameters given, running the default"
|
101
|
+
#options[:wait] = true
|
102
|
+
if default
|
103
|
+
@config[:defaultactions]
|
104
|
+
else
|
105
|
+
[]
|
106
|
+
end
|
107
|
+
end
|
108
|
+
@general_todo = if general_todo.size > 0
|
109
|
+
general_todo
|
110
|
+
else
|
111
|
+
if default
|
112
|
+
@config[:defaultgeneralactions]
|
113
|
+
else
|
114
|
+
[]
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
@second_todo = if second_todo.size > 0
|
119
|
+
second_todo
|
120
|
+
else
|
121
|
+
if default
|
122
|
+
@config[:defaultsecondactions]
|
123
|
+
else
|
124
|
+
[]
|
125
|
+
end
|
126
|
+
end
|
127
|
+
@config = @config.merge(options)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
module Six
|
4
|
+
module Updater
|
5
|
+
class RsyncRepo
|
6
|
+
def initialize(repositories, path, depth = 1)
|
7
|
+
@repositories = repositories
|
8
|
+
@path = path
|
9
|
+
@changed = false
|
10
|
+
@installed = false
|
11
|
+
end
|
12
|
+
|
13
|
+
def log
|
14
|
+
Six::Updater.log
|
15
|
+
end
|
16
|
+
|
17
|
+
def version
|
18
|
+
f = File.join(@path, '.rsync', '.pack', '.repository.yml')
|
19
|
+
if FileTest.exist?(f)
|
20
|
+
File.open(f) {|file| YAML::load(file)[:version] }
|
21
|
+
else
|
22
|
+
nil
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def open(opts = {})
|
27
|
+
repository(opts)
|
28
|
+
end
|
29
|
+
|
30
|
+
def reset(opts = {})
|
31
|
+
repository.reset(opts)
|
32
|
+
end
|
33
|
+
|
34
|
+
def status(force = false)
|
35
|
+
[]
|
36
|
+
end
|
37
|
+
|
38
|
+
def repository(opts = {:log => log})
|
39
|
+
@repository || Six::Repositories::Rsync.open(@path, opts)
|
40
|
+
end
|
41
|
+
|
42
|
+
def clone(opts = {})
|
43
|
+
done = false
|
44
|
+
@path[/(.*)\/(.*)/]
|
45
|
+
opts = {:path => $1, :depth => @depth, :log => log}
|
46
|
+
#begin
|
47
|
+
@repository = Rsync.clone(@repositories, $2, opts)
|
48
|
+
# FIXME: Update needs to be fixed
|
49
|
+
done = true
|
50
|
+
# rescue
|
51
|
+
# log.warn "WARNING: Failed, was unable to clone!" unless done
|
52
|
+
#log.debug "WARNING: Failed, trying other mirrors if available"
|
53
|
+
# end
|
54
|
+
done
|
55
|
+
end
|
56
|
+
|
57
|
+
def update(opts = {})
|
58
|
+
cfg = nil
|
59
|
+
File.open(File.join(@path, '.rsync/config.yml')) { |file| cfg = YAML::load(file) }
|
60
|
+
cfg[:hosts] = @repositories
|
61
|
+
File.open(File.join(@path, '.rsync/config.yml'), 'w') { |file| file.puts cfg.to_yaml }
|
62
|
+
|
63
|
+
# begin
|
64
|
+
repository.update
|
65
|
+
done = true
|
66
|
+
# rescue
|
67
|
+
# log.warn "WARNING: Failed, was unable to update!" unless done
|
68
|
+
# end
|
69
|
+
done
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
metadata
ADDED
@@ -0,0 +1,103 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: six-updater
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.10.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Sickboy
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-09-25 00:00:00 +02:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: log4r
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 1.1.0
|
24
|
+
version:
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: six-rsync
|
27
|
+
type: :runtime
|
28
|
+
version_requirement:
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.1.0
|
34
|
+
version:
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: win32-process
|
37
|
+
type: :runtime
|
38
|
+
version_requirement:
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 0.6.0
|
44
|
+
version:
|
45
|
+
- !ruby/object:Gem::Dependency
|
46
|
+
name: win32-shortcut
|
47
|
+
type: :runtime
|
48
|
+
version_requirement:
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 0.2.3
|
54
|
+
version:
|
55
|
+
description: Your summary here
|
56
|
+
email: sb@dev-heaven.net
|
57
|
+
executables: []
|
58
|
+
|
59
|
+
extensions: []
|
60
|
+
|
61
|
+
extra_rdoc_files:
|
62
|
+
- README
|
63
|
+
- LICENSE
|
64
|
+
files:
|
65
|
+
- LICENSE
|
66
|
+
- README
|
67
|
+
- Rakefile
|
68
|
+
- lib/six/updater/gitrepo.rb
|
69
|
+
- lib/six/updater/mod.rb
|
70
|
+
- lib/six/updater/options.rb
|
71
|
+
- lib/six/updater/rsyncrepo.rb
|
72
|
+
- lib/six/updater-app.rb
|
73
|
+
- lib/six/updater.rb
|
74
|
+
has_rdoc: true
|
75
|
+
homepage:
|
76
|
+
licenses: []
|
77
|
+
|
78
|
+
post_install_message:
|
79
|
+
rdoc_options: []
|
80
|
+
|
81
|
+
require_paths:
|
82
|
+
- lib
|
83
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
84
|
+
requirements:
|
85
|
+
- - ">="
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: "0"
|
88
|
+
version:
|
89
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
90
|
+
requirements:
|
91
|
+
- - ">="
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: "0"
|
94
|
+
version:
|
95
|
+
requirements: []
|
96
|
+
|
97
|
+
rubyforge_project:
|
98
|
+
rubygems_version: 1.3.5
|
99
|
+
signing_key:
|
100
|
+
specification_version: 3
|
101
|
+
summary: Your summary here
|
102
|
+
test_files: []
|
103
|
+
|