six-updater 0.10.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
|