six-updater 0.17.1-x86-mswin32

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,112 @@
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
+ log.debug "#{$!}"
45
+ end
46
+ end
47
+ log.warn "WARNING: Failed, was unable to clone!" unless done
48
+ done
49
+ end
50
+
51
+ def version
52
+ repository.log.first.to_s
53
+ end
54
+
55
+ def update(opts = {})
56
+ done = false
57
+ repositories = @repositories.clone
58
+ while repositories.size > 0 && !done
59
+ cfg = nil
60
+ File.open(File.join(@path, '.git/config')) { |file| cfg = file.readlines }
61
+ rep = ''
62
+ cfg.map! do |entry|
63
+ if entry[/(\t*)url \=/]
64
+ rep = repositories.sample
65
+ repositories -= [rep]
66
+ "#{$1}url = #{rep}"
67
+ else
68
+ entry
69
+ end
70
+ end
71
+ log.info "Trying #{rep}"
72
+ File.open(File.join(@path, '.git/config'), 'w') { |file| file.puts cfg }
73
+ begin
74
+ repository.config("core.autocrlf", "false")
75
+ repository.pull_legacy
76
+ done = true
77
+ rescue
78
+ log.debug "WARNING: Failed, trying other mirrors if available"
79
+ log.debug "#{$!}"
80
+ end
81
+ end
82
+ log.warn "WARNING: Failed, was unable to update!" unless done
83
+ done
84
+ end
85
+
86
+ def status(force = false)
87
+ if force || !@status
88
+ @status = status_update
89
+ end
90
+ @status
91
+ end
92
+
93
+ def check_status(type, array, msg)
94
+ str = []
95
+ if array.size > 0
96
+ str << "#{type}:"
97
+ array.each { |item| str << item[0] }
98
+ msg << str.join("\n")
99
+ end
100
+ end
101
+
102
+ def status_update
103
+ msg = []
104
+ [
105
+ ['Added', repository.status.added], ['Changed', repository.status.changed],
106
+ ['Deleted', repository.status.deleted], ['Untracked', repository.status.untracked]
107
+ ].each { |entry| check_status(entry[0], entry[1], msg) }
108
+ msg
109
+ end
110
+ end
111
+ end
112
+ end
@@ -0,0 +1,348 @@
1
+ # encoding: UTF-8
2
+
3
+ module Six
4
+ module Updater
5
+ class Mod
6
+ attr_reader :changed
7
+ DEFAULT_PRIORITY = 9999
8
+ def initialize(modconfig, config)
9
+ @modconfig = modconfig
10
+ @config = config
11
+ @stat = Hash.new
12
+ @stat[:changelog] = []
13
+ @stat[:current], @stat[:previous] = "A", "B"
14
+ @path = File.join(self.apppath, @modconfig[:folder])
15
+ get_repositories
16
+
17
+ @modconfig[:folder].gsub!('\\', '/')
18
+ @folder_str = @modconfig[:folder].clone
19
+ @folder_str.gsub!('/', '-')
20
+
21
+ if @modconfig[:versionfile]
22
+ @modconfig[:versionfile] = File.join(@config[:app_modpath], @modconfig[:folder], @modconfig[:versionfile])
23
+ else
24
+ @modconfig[:versionfile] = File.join(@config[:app_modpath], @modconfig[:folder], '.version.txt')
25
+ end
26
+
27
+ unless @modconfig[:depth]
28
+ @modconfig[:depth] = @config[:depth]
29
+ end
30
+
31
+ @changed = false
32
+
33
+ @installed = if FileTest.exists?(File.join(@path, '.rsync'))
34
+ @repository = RsyncRepo.new(@modconfig[:repository], @path, :log => log)
35
+ true
36
+ else
37
+ false
38
+ end
39
+ end
40
+
41
+ # TODO: Custom paths need more consideration, especially re the -mod= line
42
+ def apppath; @modconfig[:path] ? @modconfig[:path] : @config[:app_modpath]; end
43
+ def priority; @modconfig[:priority] ? @modconfig[:priority] : DEFAULT_PRIORITY; end
44
+ def esc(val); "\"#{val}\""; end
45
+ def log; Six::Updater.log; end
46
+ def sure?; Six::Updater.sure?; end
47
+ def log_status; log.warn "Status: #{@repository.status.join("\n")}" if @repository.status.size > 0; end
48
+ def not_a_repository; log.warn "Does not seem to be a repository!"; end
49
+
50
+ def disabled?
51
+ log.info "Mod is tagged 'disabled' in the configuration file. Skipping..." if @modconfig[:disabled]
52
+ @modconfig[:disabled]
53
+ end
54
+
55
+ def installed?
56
+ not_a_repository unless @installed
57
+ @installed
58
+ end
59
+
60
+ def skip?
61
+ log.info "Mod is tagged 'skip' in the configuration file. Skipping..." if @modconfig[:skip]
62
+ @modconfig[:skip]
63
+ end
64
+
65
+ def get_repositories
66
+ cfg = File.join(@path, '.repositories.yml')
67
+ @repositories = if FileTest.exist?(cfg)
68
+ File.open(cfg) { |file| YAML::load(file) }
69
+ elsif @modconfig[:repository].class == Array
70
+ @modconfig[:repository]
71
+ else
72
+ [@modconfig[:repository]]
73
+ end
74
+ end
75
+
76
+ def write_version
77
+ @modconfig[:versionfile][/(.*)\/(.*)/]
78
+ folder = $1
79
+ FileUtils.mkdir_p folder unless FileTest.exists? folder
80
+ begin
81
+ File.open(@modconfig[:versionfile], 'w') { |file| file.puts @stat[:current] }
82
+ true
83
+ rescue
84
+ log.warn "WARNING: Unable to write version.txt file, please make sure everything arma is closed, etc"
85
+ log.debug "#{$!}"
86
+ false
87
+ end
88
+ end
89
+
90
+ def changelog
91
+ return if self.disabled?
92
+ return unless self.installed?
93
+
94
+ unless @stat[:previous] == @stat[:current]
95
+ log.info 'Playing log...'
96
+ @stat[:changelog].each do |msg|
97
+ log.debug msg # TODO: Necessary?
98
+ puts msg
99
+ end
100
+ end
101
+ end
102
+
103
+ # RESET process (incase everything FOOKED :D)
104
+ def reset
105
+ return if self.disabled?
106
+ return unless self.installed?
107
+
108
+ log.warn "###########"
109
+ log.warn "# WARNING #"
110
+ log.warn "###########"
111
+ log.warn "You are about to reset and loose all local changes in the specified repository"
112
+ log_status
113
+ sure?
114
+ log.info 'Resetting...'
115
+ @repository.repository.reset(nil, {:hard => true})
116
+ end
117
+
118
+ # UPDATE Process
119
+ def update
120
+ if self.skip?
121
+ begin
122
+ userconfig(false)
123
+ rescue
124
+ log.warn 'WARNING: Userconfig processing is unable to complete.'
125
+ log.debug "#{$!}"
126
+ end
127
+ return
128
+ else
129
+ return if self.disabled?
130
+ end
131
+
132
+ return unless self.installed?
133
+
134
+ @stat[:previous] = @repository.version
135
+ log.info "Current Version: #{@stat[:previous]}, checking for updates..."
136
+ done = @repository.update
137
+ @stat[:current] = @repository.version
138
+
139
+ begin
140
+ @repository.status(true)
141
+ rescue
142
+ log.warn 'WARNING: Update seems to have completed but there was a status error..'
143
+ log.debug "#{$!}"
144
+ log_status
145
+ end
146
+
147
+ if @stat[:previous] == @stat[:current]
148
+ log.info "No updates found"
149
+ write_version # DO this always incase previous version.txt failed for whatever reason!
150
+ else
151
+ log.info "Applied version: #{@stat[:current]}"
152
+ @changed = true
153
+ if write_version
154
+ #write_changelog
155
+ else
156
+ @repository.reset(@stat[:previous], {:hard => true})
157
+ @changed = false
158
+ @stat[:current] = @stat[:previous]
159
+ end
160
+ end
161
+
162
+ # TODO: Detect missing / out of date config files, and notify user
163
+ begin
164
+ userconfig(false)
165
+ rescue
166
+ log.warn 'WARNING: Userconfig processing is unable to complete.'
167
+ log.debug "#{$!}"
168
+ end
169
+
170
+ unless done
171
+ 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'
172
+ log_status
173
+ # TODO: Add display of stats for changed files etc
174
+ end
175
+ end
176
+
177
+ # INSTALL process
178
+ def install
179
+ log.debug "Path: #{@path}"
180
+ return if self.disabled?
181
+ if self.installed?
182
+ log.info "Already installed, trying to update..."
183
+ update
184
+ else
185
+ if FileTest.exist?(@path)
186
+ log.warn "WARNING: Folder already exists but seems incompatible. Not installing."
187
+ log.info "If you want the software to install this mod, please delete the modfolder"
188
+ else
189
+ log.info "Installing... This might take a while, please wait."
190
+ folder = ''
191
+ if @modconfig[:folder][/(.*)\/(.*)/]
192
+ basepath, subfolder = $1, $2
193
+ basepath = File.join(@config[:app_modpath], basepath)
194
+ FileUtils.mkdir_p basepath unless FileTest.exist?(basepath)
195
+ end
196
+
197
+ file = File.join(DATA_PATH, "#{@folder_str}.7z")
198
+ file = File.join(BASE_PATH, "#{@folder_str}.7z") unless File.exists?(file)
199
+ if File.exists?(file)
200
+ log.info "Found #{@folder_str}.7z, using it"
201
+ #Six::Updater.zipcheck
202
+ FileUtils.mkdir_p @path
203
+ cmd = "7z x -o#{esc(@path)} #{esc(file)}"
204
+ log.debug cmd
205
+ output = %x[#{cmd}]
206
+ log.debug output
207
+
208
+ if File.exists?(File.join(@path, ".rsync", "config.yml"))
209
+ begin
210
+ @repository = RsyncRepo.new(@modconfig[:repository], @path, :log => log)
211
+ @installed = true
212
+ get_repositories
213
+ update
214
+ rescue
215
+ @installed = false
216
+ FileUtils::rm_rf(@path) if FileTest.exist?(@path)
217
+ end
218
+ else
219
+ log.warn "WARNING: Failed to open the repository, the #{@folder_str}.7z does not seem to be correct"
220
+ log.warn "Installing from rsync network instead"
221
+ log.debug "#{$!}"
222
+ FileUtils::rm_rf(@path) if FileTest.exist?(@path)
223
+ end
224
+ end
225
+
226
+ unless @installed
227
+ @repository = RsyncRepo.new(@repositories, @path)
228
+ opts = {}
229
+ opts.merge!({:log => log}) if @config[:verbose]
230
+ @installed = @repository.clone(opts)
231
+ unless @installed
232
+ log.warn "WARNING: Failed to download the repository! This could be due to a server / connection problem. Please try again later"
233
+ end
234
+ end
235
+
236
+ if @installed
237
+ @changed = true
238
+ @stat[:previous] = nil
239
+ begin
240
+ @stat[:current] = @repository.version
241
+ write_version
242
+ rescue
243
+ log.warn 'WARNING: Post installation was unable to complete. This could be due to a server / connection problem. Please try again later'
244
+ log.debug "#{$!}"
245
+ FileUtils::rm_rf(@path) if FileTest.exist?(@path)
246
+ end
247
+ begin
248
+ userconfig
249
+ rescue
250
+ log.warn 'WARNING: Userconfig processing is unable to complete.'
251
+ log.debug "#{$!}"
252
+ end
253
+ else
254
+ FileUtils::rm_rf(@path) if FileTest.exist?(@path)
255
+ end
256
+ end
257
+ end
258
+ end
259
+
260
+ def cleanup
261
+ log.warn "CLEANUP Action unimplemented atm, please pick different action"
262
+ end
263
+
264
+ # UNINSTALL process
265
+ def uninstall
266
+ return if self.disabled?
267
+
268
+ if FileTest.exist?(@path)
269
+ log.warn "###########"
270
+ log.warn "# WARNING #"
271
+ log.warn "###########"
272
+ log.warn "You are about to uninstall the specified repository"
273
+ sure?
274
+ log.warn 'Uninstalling...'
275
+ FileUtils.rm_rf @path
276
+ end
277
+ # TODO: Cleanup Userconfig ?
278
+ end
279
+
280
+ # Process keys
281
+ def keys(force = true)
282
+ return if self.disabled?
283
+ return unless self.installed?
284
+
285
+ path = File.join(@path, 'store', 'keys.tar')
286
+ path = File.join(@path, 'store', 'keys') unless File.exists?(path)
287
+ path = File.join(@path, 'keys') unless File.directory?(path)
288
+ if File.exists?(path)
289
+ log.info "Found keys, processing..."
290
+ k_path = File.join(@config[:app_path], 'keys')
291
+ if File.directory? path
292
+ Dir[File.join(path, '*.bikey')].each do |key|
293
+ key[/(.*)\/(.*)/]
294
+ path, file = $1, $2
295
+ file[/(.*)_(.*)\.bikey/]
296
+ prefix, suffix = $1, $2
297
+ if suffix && prefix
298
+ if suffix[/(\D*)\d*/]
299
+ suf = $1
300
+ Dir[File.join(k_path, "#{prefix}_#{suf}*.bikey")].each { |delkey| FileUtils.rm_f(delkey) } if suf
301
+ end
302
+ end
303
+ FileUtils.cp(key, k_path)
304
+ end
305
+ else
306
+ # TODO: Cleanup old keys, Ruby Tar library, examine content? - tarruby doesn't build on 1.9.1. mingw
307
+ cmd = "7z x #{esc(path)} -o #{esc(@config[:app_path])}"
308
+ cmd.gsub!("/", "\\")
309
+ system cmd
310
+ end
311
+ end
312
+ end
313
+
314
+ # Process userconfigs
315
+ # TODO: Add this processing to update, aka; IF userconfig has changed THEN update it
316
+ def userconfig(force = true)
317
+ return if self.disabled?
318
+ return unless self.installed?
319
+
320
+ # TODO: Process this on file level instead of folder level?
321
+ time = Time.now.to_i
322
+ f = @modconfig[:folder].clone
323
+ f.gsub!('@', '')
324
+ path = File.join(@path, 'store', 'userconfig.tar')
325
+ path = File.join(@path, 'store', 'userconfig') unless File.exists?(path)
326
+ path = File.join(@path, 'userconfig') unless File.exists?(path)
327
+ if File.exists?(path)
328
+ uconfig = File.join(@config[:app_path], 'userconfig')
329
+ uconfigpath = File.join(uconfig, f)
330
+ if !force && FileTest.exist?(uconfigpath)
331
+ log.debug "Userconfig folder already found, skipping"
332
+ return
333
+ end
334
+ log.info "Found userconfig, processing..."
335
+ FileUtils::mv(uconfigpath, "#{uconfigpath}_#{time}") if File.exists?(uconfigpath)
336
+ if File.directory? path
337
+ FileUtils::mkdir_p uconfig unless File.exists?(uconfig)
338
+ FileUtils::cp_r(path, uconfigpath)
339
+ else
340
+ cmd = "7z x #{esc(path)} -o#{esc(@config[:app_path])} -y"
341
+ cmd.gsub!("/", "\\")
342
+ system cmd
343
+ end
344
+ end
345
+ end
346
+ end
347
+ end
348
+ end