lg_pod_plugin 1.0.8 → 1.0.10

Sign up to get free protection for your applications and to get access to all the features.
Files changed (114) hide show
  1. checksums.yaml +4 -4
  2. data/bin/lg +5 -0
  3. data/lib/command/cache.rb +22 -18
  4. data/lib/command/command.rb +27 -35
  5. data/lib/command/install.rb +52 -0
  6. data/lib/command/update.rb +39 -0
  7. data/lib/lg_pod_plugin/downloader.rb +12 -17
  8. data/lib/lg_pod_plugin/git_util.rb +150 -106
  9. data/lib/lg_pod_plugin/install.rb +74 -88
  10. data/lib/lg_pod_plugin/l_cache.rb +11 -77
  11. data/lib/lg_pod_plugin/l_util.rb +6 -2
  12. data/lib/lg_pod_plugin/request.rb +90 -82
  13. data/lib/lg_pod_plugin/version.rb +1 -1
  14. data/lib/lg_pod_plugin.rb +9 -5
  15. metadata +57 -118
  16. data/lib/git/author.rb +0 -14
  17. data/lib/git/base/factory.rb +0 -101
  18. data/lib/git/base.rb +0 -670
  19. data/lib/git/branch.rb +0 -126
  20. data/lib/git/branches.rb +0 -71
  21. data/lib/git/config.rb +0 -22
  22. data/lib/git/diff.rb +0 -155
  23. data/lib/git/encoding_utils.rb +0 -33
  24. data/lib/git/escaped_path.rb +0 -77
  25. data/lib/git/index.rb +0 -5
  26. data/lib/git/lib.rb +0 -1215
  27. data/lib/git/log.rb +0 -135
  28. data/lib/git/object.rb +0 -312
  29. data/lib/git/path.rb +0 -31
  30. data/lib/git/remote.rb +0 -36
  31. data/lib/git/repository.rb +0 -6
  32. data/lib/git/stash.rb +0 -27
  33. data/lib/git/stashes.rb +0 -55
  34. data/lib/git/status.rb +0 -199
  35. data/lib/git/url.rb +0 -127
  36. data/lib/git/version.rb +0 -5
  37. data/lib/git/working_directory.rb +0 -4
  38. data/lib/git/worktree.rb +0 -38
  39. data/lib/git/worktrees.rb +0 -47
  40. data/lib/git.rb +0 -326
  41. data/lib/rchardet/big5freq.rb +0 -927
  42. data/lib/rchardet/big5prober.rb +0 -42
  43. data/lib/rchardet/chardistribution.rb +0 -250
  44. data/lib/rchardet/charsetgroupprober.rb +0 -110
  45. data/lib/rchardet/charsetprober.rb +0 -70
  46. data/lib/rchardet/codingstatemachine.rb +0 -67
  47. data/lib/rchardet/constants.rb +0 -42
  48. data/lib/rchardet/escprober.rb +0 -90
  49. data/lib/rchardet/escsm.rb +0 -245
  50. data/lib/rchardet/eucjpprober.rb +0 -88
  51. data/lib/rchardet/euckrfreq.rb +0 -597
  52. data/lib/rchardet/euckrprober.rb +0 -42
  53. data/lib/rchardet/euctwfreq.rb +0 -431
  54. data/lib/rchardet/euctwprober.rb +0 -42
  55. data/lib/rchardet/gb18030freq.rb +0 -474
  56. data/lib/rchardet/gb18030prober.rb +0 -42
  57. data/lib/rchardet/hebrewprober.rb +0 -289
  58. data/lib/rchardet/jisfreq.rb +0 -571
  59. data/lib/rchardet/jpcntx.rb +0 -229
  60. data/lib/rchardet/langbulgarianmodel.rb +0 -229
  61. data/lib/rchardet/langcyrillicmodel.rb +0 -330
  62. data/lib/rchardet/langgreekmodel.rb +0 -227
  63. data/lib/rchardet/langhebrewmodel.rb +0 -202
  64. data/lib/rchardet/langhungarianmodel.rb +0 -226
  65. data/lib/rchardet/langthaimodel.rb +0 -201
  66. data/lib/rchardet/latin1prober.rb +0 -147
  67. data/lib/rchardet/mbcharsetprober.rb +0 -89
  68. data/lib/rchardet/mbcsgroupprober.rb +0 -47
  69. data/lib/rchardet/mbcssm.rb +0 -542
  70. data/lib/rchardet/sbcharsetprober.rb +0 -122
  71. data/lib/rchardet/sbcsgroupprober.rb +0 -58
  72. data/lib/rchardet/sjisprober.rb +0 -88
  73. data/lib/rchardet/universaldetector.rb +0 -179
  74. data/lib/rchardet/utf8prober.rb +0 -87
  75. data/lib/rchardet/version.rb +0 -3
  76. data/lib/rchardet.rb +0 -67
  77. data/lib/zip/central_directory.rb +0 -212
  78. data/lib/zip/compressor.rb +0 -9
  79. data/lib/zip/constants.rb +0 -115
  80. data/lib/zip/crypto/decrypted_io.rb +0 -40
  81. data/lib/zip/crypto/encryption.rb +0 -11
  82. data/lib/zip/crypto/null_encryption.rb +0 -43
  83. data/lib/zip/crypto/traditional_encryption.rb +0 -99
  84. data/lib/zip/decompressor.rb +0 -31
  85. data/lib/zip/deflater.rb +0 -34
  86. data/lib/zip/dos_time.rb +0 -53
  87. data/lib/zip/entry.rb +0 -719
  88. data/lib/zip/entry_set.rb +0 -88
  89. data/lib/zip/errors.rb +0 -19
  90. data/lib/zip/extra_field/generic.rb +0 -44
  91. data/lib/zip/extra_field/ntfs.rb +0 -94
  92. data/lib/zip/extra_field/old_unix.rb +0 -46
  93. data/lib/zip/extra_field/universal_time.rb +0 -77
  94. data/lib/zip/extra_field/unix.rb +0 -39
  95. data/lib/zip/extra_field/zip64.rb +0 -70
  96. data/lib/zip/extra_field/zip64_placeholder.rb +0 -15
  97. data/lib/zip/extra_field.rb +0 -103
  98. data/lib/zip/file.rb +0 -468
  99. data/lib/zip/filesystem.rb +0 -643
  100. data/lib/zip/inflater.rb +0 -54
  101. data/lib/zip/input_stream.rb +0 -180
  102. data/lib/zip/ioextras/abstract_input_stream.rb +0 -122
  103. data/lib/zip/ioextras/abstract_output_stream.rb +0 -43
  104. data/lib/zip/ioextras.rb +0 -36
  105. data/lib/zip/null_compressor.rb +0 -15
  106. data/lib/zip/null_decompressor.rb +0 -19
  107. data/lib/zip/null_input_stream.rb +0 -10
  108. data/lib/zip/output_stream.rb +0 -198
  109. data/lib/zip/pass_thru_compressor.rb +0 -23
  110. data/lib/zip/pass_thru_decompressor.rb +0 -31
  111. data/lib/zip/streamable_directory.rb +0 -15
  112. data/lib/zip/streamable_stream.rb +0 -52
  113. data/lib/zip/version.rb +0 -3
  114. data/lib/zip.rb +0 -72
data/lib/git/lib.rb DELETED
@@ -1,1215 +0,0 @@
1
- require 'tempfile'
2
- require 'zlib'
3
-
4
- module Git
5
-
6
- class GitExecuteError < StandardError
7
- end
8
-
9
- class Lib
10
-
11
- @@semaphore = Mutex.new
12
-
13
- # The path to the Git working copy. The default is '"./.git"'.
14
- #
15
- # @return [Pathname] the path to the Git working copy.
16
- #
17
- # @see [Git working tree](https://git-scm.com/docs/gitglossary#Documentation/gitglossary.txt-aiddefworkingtreeaworkingtree)
18
- #
19
- attr_reader :git_work_dir
20
-
21
- # The path to the Git repository directory. The default is
22
- # `"#{git_work_dir}/.git"`.
23
- #
24
- # @return [Pathname] the Git repository directory.
25
- #
26
- # @see [Git repository](https://git-scm.com/docs/gitglossary#Documentation/gitglossary.txt-aiddefrepositoryarepository)
27
- #
28
- attr_reader :git_dir
29
-
30
- # The Git index file used to stage changes (using `git add`) before they
31
- # are committed.
32
- #
33
- # @return [Pathname] the Git index file
34
- #
35
- # @see [Git index file](https://git-scm.com/docs/gitglossary#Documentation/gitglossary.txt-aiddefindexaindex)
36
- #
37
- attr_reader :git_index_file
38
-
39
- # Create a new Git::Lib object
40
- #
41
- # @param [Git::Base, Hash] base An object that passes in values for
42
- # @git_work_dir, @git_dir, and @git_index_file
43
- #
44
- # @param [Logger] logger
45
- #
46
- # @option base [Pathname] :working_directory
47
- # @option base [Pathname] :repository
48
- # @option base [Pathname] :index
49
- #
50
- def initialize(base = nil, logger = nil)
51
- @git_dir = nil
52
- @git_index_file = nil
53
- @git_work_dir = nil
54
- @path = nil
55
-
56
- if base.is_a?(Git::Base)
57
- @git_dir = base.repo.path
58
- @git_index_file = base.index.path if base.index
59
- @git_work_dir = base.dir.path if base.dir
60
- elsif base.is_a?(Hash)
61
- @git_dir = base[:repository]
62
- @git_index_file = base[:index]
63
- @git_work_dir = base[:working_directory]
64
- end
65
- @logger = logger
66
- end
67
-
68
- # creates or reinitializes the repository
69
- #
70
- # options:
71
- # :bare
72
- # :working_directory
73
- # :initial_branch
74
- #
75
- def init(opts={})
76
- arr_opts = []
77
- arr_opts << '--bare' if opts[:bare]
78
- arr_opts << "--initial-branch=#{opts[:initial_branch]}" if opts[:initial_branch]
79
-
80
- command('init', arr_opts)
81
- end
82
-
83
- # tries to clone the given repo
84
- #
85
- # accepts options:
86
- # :bare:: no working directory
87
- # :branch:: name of branch to track (rather than 'master')
88
- # :depth:: the number of commits back to pull
89
- # :origin:: name of remote (same as remote)
90
- # :path:: directory where the repo will be cloned
91
- # :remote:: name of remote (rather than 'origin')
92
- # :recursive:: after the clone is created, initialize all submodules within, using their default settings.
93
- #
94
- # TODO - make this work with SSH password or auth_key
95
- #
96
- # @return [Hash] the options to pass to {Git::Base.new}
97
- #
98
- def clone(repository_url, directory, opts = {})
99
- @path = opts[:path] || '.'
100
- clone_dir = opts[:path] ? File.join(@path, directory) : directory
101
-
102
- arr_opts = []
103
- arr_opts << '--bare' if opts[:bare]
104
- arr_opts << '--branch' << opts[:branch] if opts[:branch]
105
- arr_opts << '--depth' << opts[:depth].to_i if opts[:depth] && opts[:depth].to_i > 0
106
- arr_opts << '--config' << opts[:config] if opts[:config]
107
- arr_opts << '--origin' << opts[:remote] || opts[:origin] if opts[:remote] || opts[:origin]
108
- arr_opts << '--recursive' if opts[:recursive]
109
- arr_opts << '--mirror' if opts[:mirror]
110
-
111
- arr_opts << '--'
112
-
113
- arr_opts << repository_url
114
- arr_opts << clone_dir
115
-
116
- command('clone', arr_opts)
117
-
118
- return_base_opts_from_clone(clone_dir, opts)
119
- end
120
-
121
- def return_base_opts_from_clone(clone_dir, opts)
122
- base_opts = {}
123
- base_opts[:repository] = clone_dir if (opts[:bare] || opts[:mirror])
124
- base_opts[:working_directory] = clone_dir unless (opts[:bare] || opts[:mirror])
125
- base_opts[:log] = opts[:log] if opts[:log]
126
- base_opts
127
- end
128
-
129
- ## READ COMMANDS ##
130
-
131
- #
132
- # Returns most recent tag that is reachable from a commit
133
- #
134
- # accepts options:
135
- # :all
136
- # :tags
137
- # :contains
138
- # :debug
139
- # :exact_match
140
- # :dirty
141
- # :abbrev
142
- # :candidates
143
- # :long
144
- # :always
145
- # :math
146
- #
147
- # @param [String|NilClass] committish target commit sha or object name
148
- # @param [{Symbol=>Object}] opts the given options
149
- # @return [String] the tag name
150
- #
151
- def describe(committish=nil, opts={})
152
- arr_opts = []
153
-
154
- arr_opts << '--all' if opts[:all]
155
- arr_opts << '--tags' if opts[:tags]
156
- arr_opts << '--contains' if opts[:contains]
157
- arr_opts << '--debug' if opts[:debug]
158
- arr_opts << '--long' if opts[:long]
159
- arr_opts << '--always' if opts[:always]
160
- arr_opts << '--exact-match' if opts[:exact_match] || opts[:"exact-match"]
161
-
162
- arr_opts << '--dirty' if opts[:dirty] == true
163
- arr_opts << "--dirty=#{opts[:dirty]}" if opts[:dirty].is_a?(String)
164
-
165
- arr_opts << "--abbrev=#{opts[:abbrev]}" if opts[:abbrev]
166
- arr_opts << "--candidates=#{opts[:candidates]}" if opts[:candidates]
167
- arr_opts << "--match=#{opts[:match]}" if opts[:match]
168
-
169
- arr_opts << committish if committish
170
-
171
- return command('describe', arr_opts)
172
- end
173
-
174
- def log_commits(opts={})
175
- arr_opts = log_common_options(opts)
176
-
177
- arr_opts << '--pretty=oneline'
178
-
179
- arr_opts += log_path_options(opts)
180
-
181
- command_lines('log', arr_opts).map { |l| l.split.first }
182
- end
183
-
184
- def full_log_commits(opts={})
185
- arr_opts = log_common_options(opts)
186
-
187
- arr_opts << '--pretty=raw'
188
- arr_opts << "--skip=#{opts[:skip]}" if opts[:skip]
189
-
190
- arr_opts += log_path_options(opts)
191
-
192
- full_log = command_lines('log', arr_opts)
193
-
194
- process_commit_log_data(full_log)
195
- end
196
-
197
- def revparse(string)
198
- return string if string =~ /^[A-Fa-f0-9]{40}$/ # passing in a sha - just no-op it
199
- rev = ['head', 'remotes', 'tags'].map do |d|
200
- File.join(@git_dir, 'refs', d, string)
201
- end.find do |path|
202
- File.file?(path)
203
- end
204
- return File.read(rev).chomp if rev
205
- command('rev-parse', string)
206
- end
207
-
208
- def namerev(string)
209
- command('name-rev', string).split[1]
210
- end
211
-
212
- def object_type(sha)
213
- command('cat-file', '-t', sha)
214
- end
215
-
216
- def object_size(sha)
217
- command('cat-file', '-s', sha).to_i
218
- end
219
-
220
- # returns useful array of raw commit object data
221
- def commit_data(sha)
222
- sha = sha.to_s
223
- cdata = command_lines('cat-file', 'commit', sha)
224
- process_commit_data(cdata, sha, 0)
225
- end
226
-
227
- def process_commit_data(data, sha = nil, indent = 4)
228
- hsh = {
229
- 'sha' => sha,
230
- 'message' => '',
231
- 'parent' => []
232
- }
233
-
234
- loop do
235
- key, *value = data.shift.split
236
-
237
- break if key.nil?
238
-
239
- if key == 'parent'
240
- hsh['parent'] << value.join(' ')
241
- else
242
- hsh[key] = value.join(' ')
243
- end
244
- end
245
-
246
- hsh['message'] = data.collect {|line| line[indent..-1]}.join("\n") + "\n"
247
-
248
- return hsh
249
- end
250
-
251
- def tag_data(name)
252
- sha = sha.to_s
253
- tdata = command_lines('cat-file', 'tag', name)
254
- process_tag_data(tdata, name, 0)
255
- end
256
-
257
- def process_tag_data(data, name, indent=4)
258
- hsh = {
259
- 'name' => name,
260
- 'message' => ''
261
- }
262
-
263
- loop do
264
- key, *value = data.shift.split
265
-
266
- break if key.nil?
267
-
268
- hsh[key] = value.join(' ')
269
- end
270
-
271
- hsh['message'] = data.collect {|line| line[indent..-1]}.join("\n") + "\n"
272
-
273
- return hsh
274
- end
275
-
276
- def process_commit_log_data(data)
277
- in_message = false
278
-
279
- hsh_array = []
280
-
281
- hsh = nil
282
-
283
- data.each do |line|
284
- line = line.chomp
285
-
286
- if line[0].nil?
287
- in_message = !in_message
288
- next
289
- end
290
-
291
- in_message = false if in_message && line[0..3] != " "
292
-
293
- if in_message
294
- hsh['message'] << "#{line[4..-1]}\n"
295
- next
296
- end
297
-
298
- key, *value = line.split
299
- value = value.join(' ')
300
-
301
- case key
302
- when 'commit'
303
- hsh_array << hsh if hsh
304
- hsh = {'sha' => value, 'message' => '', 'parent' => []}
305
- when 'parent'
306
- hsh['parent'] << value
307
- else
308
- hsh[key] = value
309
- end
310
- end
311
-
312
- hsh_array << hsh if hsh
313
-
314
- return hsh_array
315
- end
316
-
317
- def object_contents(sha, &block)
318
- command('cat-file', '-p', sha, &block)
319
- end
320
-
321
- def ls_tree(sha)
322
- data = {'blob' => {}, 'tree' => {}}
323
-
324
- command_lines('ls-tree', sha).each do |line|
325
- (info, filenm) = line.split("\t")
326
- (mode, type, sha) = info.split
327
- data[type][filenm] = {:mode => mode, :sha => sha}
328
- end
329
-
330
- data
331
- end
332
-
333
- def mv(file1, file2)
334
- command_lines('mv', '--', file1, file2)
335
- end
336
-
337
- def full_tree(sha)
338
- command_lines('ls-tree', '-r', sha)
339
- end
340
-
341
- def tree_depth(sha)
342
- full_tree(sha).size
343
- end
344
-
345
- def change_head_branch(branch_name)
346
- command('symbolic-ref', 'HEAD', "refs/heads/#{branch_name}")
347
- end
348
-
349
- def branches_all
350
- arr = []
351
- command_lines('branch', '-a').each do |b|
352
- current = (b[0, 2] == '* ')
353
- arr << [b.gsub('* ', '').strip, current]
354
- end
355
- arr
356
- end
357
-
358
- def worktrees_all
359
- arr = []
360
- directory = ''
361
- # Output example for `worktree list --porcelain`:
362
- # worktree /code/public/ruby-git
363
- # HEAD 4bef5abbba073c77b4d0ccc1ffcd0ed7d48be5d4
364
- # branch refs/heads/master
365
- #
366
- # worktree /tmp/worktree-1
367
- # HEAD b8c63206f8d10f57892060375a86ae911fad356e
368
- # detached
369
- #
370
- command_lines('worktree',['list', '--porcelain']).each do |w|
371
- s = w.split("\s")
372
- directory = s[1] if s[0] == 'worktree'
373
- arr << [directory, s[1]] if s[0] == 'HEAD'
374
- end
375
- arr
376
- end
377
-
378
- def worktree_add(dir, commitish = nil)
379
- return command('worktree', ['add', dir, commitish]) if !commitish.nil?
380
- command('worktree', ['add', dir])
381
- end
382
-
383
- def worktree_remove(dir)
384
- command('worktree', ['remove', dir])
385
- end
386
-
387
- def worktree_prune
388
- command('worktree', ['prune'])
389
- end
390
-
391
- def list_files(ref_dir)
392
- dir = File.join(@git_dir, 'refs', ref_dir)
393
- files = []
394
- Dir.chdir(dir) { files = Dir.glob('**/*').select { |f| File.file?(f) } } rescue nil
395
- files
396
- end
397
-
398
- def branch_current
399
- branches_all.select { |b| b[1] }.first[0] rescue nil
400
- end
401
-
402
- def branch_contains(commit, branch_name="")
403
- command("branch", [branch_name, "--contains", commit])
404
- end
405
-
406
- # returns hash
407
- # [tree-ish] = [[line_no, match], [line_no, match2]]
408
- # [tree-ish] = [[line_no, match], [line_no, match2]]
409
- def grep(string, opts = {})
410
- opts[:object] ||= 'HEAD'
411
-
412
- grep_opts = ['-n']
413
- grep_opts << '-i' if opts[:ignore_case]
414
- grep_opts << '-v' if opts[:invert_match]
415
- grep_opts << '-e'
416
- grep_opts << string
417
- grep_opts << opts[:object] if opts[:object].is_a?(String)
418
- grep_opts << '--' << opts[:path_limiter] if opts[:path_limiter].is_a? String
419
-
420
- hsh = {}
421
- command_lines('grep', grep_opts).each do |line|
422
- if m = /(.*?)\:(\d+)\:(.*)/.match(line)
423
- hsh[m[1]] ||= []
424
- hsh[m[1]] << [m[2].to_i, m[3]]
425
- end
426
- end
427
- hsh
428
- end
429
-
430
- def diff_full(obj1 = 'HEAD', obj2 = nil, opts = {})
431
- diff_opts = ['-p']
432
- diff_opts << obj1
433
- diff_opts << obj2 if obj2.is_a?(String)
434
- diff_opts << '--' << opts[:path_limiter] if opts[:path_limiter].is_a? String
435
-
436
- command('diff', diff_opts)
437
- end
438
-
439
- def diff_stats(obj1 = 'HEAD', obj2 = nil, opts = {})
440
- diff_opts = ['--numstat']
441
- diff_opts << obj1
442
- diff_opts << obj2 if obj2.is_a?(String)
443
- diff_opts << '--' << opts[:path_limiter] if opts[:path_limiter].is_a? String
444
-
445
- hsh = {:total => {:insertions => 0, :deletions => 0, :lines => 0, :files => 0}, :files => {}}
446
-
447
- command_lines('diff', diff_opts).each do |file|
448
- (insertions, deletions, filename) = file.split("\t")
449
- hsh[:total][:insertions] += insertions.to_i
450
- hsh[:total][:deletions] += deletions.to_i
451
- hsh[:total][:lines] = (hsh[:total][:deletions] + hsh[:total][:insertions])
452
- hsh[:total][:files] += 1
453
- hsh[:files][filename] = {:insertions => insertions.to_i, :deletions => deletions.to_i}
454
- end
455
-
456
- hsh
457
- end
458
-
459
- def diff_name_status(reference1 = nil, reference2 = nil, opts = {})
460
- opts_arr = ['--name-status']
461
- opts_arr << reference1 if reference1
462
- opts_arr << reference2 if reference2
463
-
464
- opts_arr << '--' << opts[:path] if opts[:path]
465
-
466
- command_lines('diff', opts_arr).inject({}) do |memo, line|
467
- status, path = line.split("\t")
468
- memo[path] = status
469
- memo
470
- end
471
- end
472
-
473
- # compares the index and the working directory
474
- def diff_files
475
- diff_as_hash('diff-files')
476
- end
477
-
478
- # compares the index and the repository
479
- def diff_index(treeish)
480
- diff_as_hash('diff-index', treeish)
481
- end
482
-
483
- def ls_files(location=nil)
484
- location ||= '.'
485
- hsh = {}
486
- command_lines('ls-files', '--stage', location).each do |line|
487
- (info, file) = line.split("\t")
488
- (mode, sha, stage) = info.split
489
- file = eval(file) if file =~ /^\".*\"$/ # This takes care of quoted strings returned from git
490
- hsh[file] = {:path => file, :mode_index => mode, :sha_index => sha, :stage => stage}
491
- end
492
- hsh
493
- end
494
-
495
- def ls_remote(location=nil, opts={})
496
- arr_opts = []
497
- arr_opts << ['--refs'] if opts[:refs]
498
- arr_opts << (location || '.')
499
-
500
- Hash.new{ |h,k| h[k] = {} }.tap do |hsh|
501
- command_lines('ls-remote', arr_opts).each do |line|
502
- (sha, info) = line.split("\t")
503
- (ref, type, name) = info.split('/', 3)
504
- type ||= 'head'
505
- type = 'branches' if type == 'heads'
506
- value = {:ref => ref, :sha => sha}
507
- hsh[type].update( name.nil? ? value : { name => value })
508
- end
509
- end
510
- end
511
-
512
- def ignored_files
513
- command_lines('ls-files', '--others', '-i', '--exclude-standard')
514
- end
515
-
516
-
517
- def config_remote(name)
518
- hsh = {}
519
- config_list.each do |key, value|
520
- if /remote.#{name}/.match(key)
521
- hsh[key.gsub("remote.#{name}.", '')] = value
522
- end
523
- end
524
- hsh
525
- end
526
-
527
- def config_get(name)
528
- do_get = Proc.new do |path|
529
- command('config', '--get', name)
530
- end
531
-
532
- if @git_dir
533
- Dir.chdir(@git_dir, &do_get)
534
- else
535
- do_get.call
536
- end
537
- end
538
-
539
- def global_config_get(name)
540
- command('config', '--global', '--get', name)
541
- end
542
-
543
- def config_list
544
- build_list = Proc.new do |path|
545
- parse_config_list command_lines('config', '--list')
546
- end
547
-
548
- if @git_dir
549
- Dir.chdir(@git_dir, &build_list)
550
- else
551
- build_list.call
552
- end
553
- end
554
-
555
- def global_config_list
556
- parse_config_list command_lines('config', '--global', '--list')
557
- end
558
-
559
- def parse_config_list(lines)
560
- hsh = {}
561
- lines.each do |line|
562
- (key, *values) = line.split('=')
563
- hsh[key] = values.join('=')
564
- end
565
- hsh
566
- end
567
-
568
- def parse_config(file)
569
- parse_config_list command_lines('config', '--list', '--file', file)
570
- end
571
-
572
- # Shows objects
573
- #
574
- # @param [String|NilClass] objectish the target object reference (nil == HEAD)
575
- # @param [String|NilClass] path the path of the file to be shown
576
- # @return [String] the object information
577
- def show(objectish=nil, path=nil)
578
- arr_opts = []
579
-
580
- arr_opts << (path ? "#{objectish}:#{path}" : objectish)
581
-
582
- command('show', arr_opts.compact, chomp: false)
583
- end
584
-
585
- ## WRITE COMMANDS ##
586
-
587
- def config_set(name, value, options = {})
588
- if options[:file].to_s.empty?
589
- command('config', name, value)
590
- else
591
- command('config', '--file', options[:file], name, value)
592
- end
593
- end
594
-
595
- def global_config_set(name, value)
596
- command('config', '--global', name, value)
597
- end
598
-
599
- # updates the repository index using the working directory content
600
- #
601
- # lib.add('path/to/file')
602
- # lib.add(['path/to/file1','path/to/file2'])
603
- # lib.add(:all => true)
604
- #
605
- # options:
606
- # :all => true
607
- # :force => true
608
- #
609
- # @param [String,Array] paths files paths to be added to the repository
610
- # @param [Hash] options
611
- def add(paths='.',options={})
612
- arr_opts = []
613
-
614
- arr_opts << '--all' if options[:all]
615
- arr_opts << '--force' if options[:force]
616
-
617
- arr_opts << '--'
618
-
619
- arr_opts << paths
620
-
621
- arr_opts.flatten!
622
-
623
- command('add', arr_opts)
624
- end
625
-
626
- def remove(path = '.', opts = {})
627
- arr_opts = ['-f'] # overrides the up-to-date check by default
628
- arr_opts << ['-r'] if opts[:recursive]
629
- arr_opts << ['--cached'] if opts[:cached]
630
- arr_opts << '--'
631
- if path.is_a?(Array)
632
- arr_opts += path
633
- else
634
- arr_opts << path
635
- end
636
-
637
- command('rm', arr_opts)
638
- end
639
-
640
- # Takes the commit message with the options and executes the commit command
641
- #
642
- # accepts options:
643
- # :amend
644
- # :all
645
- # :allow_empty
646
- # :author
647
- # :date
648
- # :no_verify
649
- # :allow_empty_message
650
- # :gpg_sign (accepts true or a gpg key ID as a String)
651
- # :no_gpg_sign (conflicts with :gpg_sign)
652
- #
653
- # @param [String] message the commit message to be used
654
- # @param [Hash] opts the commit options to be used
655
- def commit(message, opts = {})
656
- arr_opts = []
657
- arr_opts << "--message=#{message}" if message
658
- arr_opts << '--amend' << '--no-edit' if opts[:amend]
659
- arr_opts << '--all' if opts[:add_all] || opts[:all]
660
- arr_opts << '--allow-empty' if opts[:allow_empty]
661
- arr_opts << "--author=#{opts[:author]}" if opts[:author]
662
- arr_opts << "--date=#{opts[:date]}" if opts[:date].is_a? String
663
- arr_opts << '--no-verify' if opts[:no_verify]
664
- arr_opts << '--allow-empty-message' if opts[:allow_empty_message]
665
-
666
- if opts[:gpg_sign] && opts[:no_gpg_sign]
667
- raise ArgumentError, 'cannot specify :gpg_sign and :no_gpg_sign'
668
- elsif opts[:gpg_sign]
669
- arr_opts <<
670
- if opts[:gpg_sign] == true
671
- '--gpg-sign'
672
- else
673
- "--gpg-sign=#{opts[:gpg_sign]}"
674
- end
675
- elsif opts[:no_gpg_sign]
676
- arr_opts << '--no-gpg-sign'
677
- end
678
-
679
- command('commit', arr_opts)
680
- end
681
-
682
- def reset(commit, opts = {})
683
- arr_opts = []
684
- arr_opts << '--hard' if opts[:hard]
685
- arr_opts << commit if commit
686
- command('reset', arr_opts)
687
- end
688
-
689
- def clean(opts = {})
690
- arr_opts = []
691
- arr_opts << '--force' if opts[:force]
692
- arr_opts << '-ff' if opts[:ff]
693
- arr_opts << '-d' if opts[:d]
694
- arr_opts << '-x' if opts[:x]
695
-
696
- command('clean', arr_opts)
697
- end
698
-
699
- def revert(commitish, opts = {})
700
- # Forcing --no-edit as default since it's not an interactive session.
701
- opts = {:no_edit => true}.merge(opts)
702
-
703
- arr_opts = []
704
- arr_opts << '--no-edit' if opts[:no_edit]
705
- arr_opts << commitish
706
-
707
- command('revert', arr_opts)
708
- end
709
-
710
- def apply(patch_file)
711
- arr_opts = []
712
- arr_opts << '--' << patch_file if patch_file
713
- command('apply', arr_opts)
714
- end
715
-
716
- def apply_mail(patch_file)
717
- arr_opts = []
718
- arr_opts << '--' << patch_file if patch_file
719
- command('am', arr_opts)
720
- end
721
-
722
- def stashes_all
723
- arr = []
724
- filename = File.join(@git_dir, 'logs/refs/stash')
725
- if File.exist?(filename)
726
- File.open(filename) do |f|
727
- f.each_with_index do |line, i|
728
- m = line.match(/:(.*)$/)
729
- arr << [i, m[1].strip]
730
- end
731
- end
732
- end
733
- arr
734
- end
735
-
736
- def stash_save(message)
737
- output = command('stash save', message)
738
- output =~ /HEAD is now at/
739
- end
740
-
741
- def stash_apply(id = nil)
742
- if id
743
- command('stash apply', id)
744
- else
745
- command('stash apply')
746
- end
747
- end
748
-
749
- def stash_clear
750
- command('stash clear')
751
- end
752
-
753
- def stash_list
754
- command('stash list')
755
- end
756
-
757
- def branch_new(branch)
758
- command('branch', branch)
759
- end
760
-
761
- def branch_delete(branch)
762
- command('branch', '-D', branch)
763
- end
764
-
765
- def checkout(branch, opts = {})
766
- arr_opts = []
767
- arr_opts << '-b' if opts[:new_branch] || opts[:b]
768
- arr_opts << '--force' if opts[:force] || opts[:f]
769
- arr_opts << branch
770
-
771
- command('checkout', arr_opts)
772
- end
773
-
774
- def checkout_file(version, file)
775
- arr_opts = []
776
- arr_opts << version
777
- arr_opts << file
778
- command('checkout', arr_opts)
779
- end
780
-
781
- def merge(branch, message = nil, opts = {})
782
- arr_opts = []
783
- arr_opts << '--no-commit' if opts[:no_commit]
784
- arr_opts << '--no-ff' if opts[:no_ff]
785
- arr_opts << '-m' << message if message
786
- arr_opts += [branch]
787
- command('merge', arr_opts)
788
- end
789
-
790
- def merge_base(*args)
791
- opts = args.last.is_a?(Hash) ? args.pop : {}
792
-
793
- arg_opts = []
794
-
795
- arg_opts << '--octopus' if opts[:octopus]
796
- arg_opts << '--independent' if opts[:independent]
797
- arg_opts << '--fork-point' if opts[:fork_point]
798
- arg_opts << '--all' if opts[:all]
799
-
800
- arg_opts += args
801
-
802
- command('merge-base', arg_opts).lines.map(&:strip)
803
- end
804
-
805
- def unmerged
806
- unmerged = []
807
- command_lines('diff', "--cached").each do |line|
808
- unmerged << $1 if line =~ /^\* Unmerged path (.*)/
809
- end
810
- unmerged
811
- end
812
-
813
- def conflicts # :yields: file, your, their
814
- self.unmerged.each do |f|
815
- your_tempfile = Tempfile.new("YOUR-#{File.basename(f)}")
816
- your = your_tempfile.path
817
- your_tempfile.close # free up file for git command process
818
- command('show', ":2:#{f}", redirect: "> #{escape your}")
819
-
820
- their_tempfile = Tempfile.new("THEIR-#{File.basename(f)}")
821
- their = their_tempfile.path
822
- their_tempfile.close # free up file for git command process
823
- command('show', ":3:#{f}", redirect: "> #{escape their}")
824
- yield(f, your, their)
825
- end
826
- end
827
-
828
- def remote_add(name, url, opts = {})
829
- arr_opts = ['add']
830
- arr_opts << '-f' if opts[:with_fetch] || opts[:fetch]
831
- arr_opts << '-t' << opts[:track] if opts[:track]
832
- arr_opts << '--'
833
- arr_opts << name
834
- arr_opts << url
835
-
836
- command('remote', arr_opts)
837
- end
838
-
839
- def remote_set_url(name, url)
840
- arr_opts = ['set-url']
841
- arr_opts << name
842
- arr_opts << url
843
-
844
- command('remote', arr_opts)
845
- end
846
-
847
- def remote_remove(name)
848
- command('remote', 'rm', name)
849
- end
850
-
851
- def remotes
852
- command_lines('remote')
853
- end
854
-
855
- def tags
856
- command_lines('tag')
857
- end
858
-
859
- def tag(name, *opts)
860
- target = opts[0].instance_of?(String) ? opts[0] : nil
861
-
862
- opts = opts.last.instance_of?(Hash) ? opts.last : {}
863
-
864
- if (opts[:a] || opts[:annotate]) && !(opts[:m] || opts[:message])
865
- raise "Can not create an [:a|:annotate] tag without the precense of [:m|:message]."
866
- end
867
-
868
- arr_opts = []
869
-
870
- arr_opts << '-f' if opts[:force] || opts[:f]
871
- arr_opts << '-a' if opts[:a] || opts[:annotate]
872
- arr_opts << '-s' if opts[:s] || opts[:sign]
873
- arr_opts << '-d' if opts[:d] || opts[:delete]
874
- arr_opts << name
875
- arr_opts << target if target
876
-
877
- if opts[:m] || opts[:message]
878
- arr_opts << '-m' << (opts[:m] || opts[:message])
879
- end
880
-
881
- command('tag', arr_opts)
882
- end
883
-
884
- def fetch(remote, opts)
885
- arr_opts = []
886
- arr_opts << '--all' if opts[:all]
887
- arr_opts << '--tags' if opts[:t] || opts[:tags]
888
- arr_opts << '--prune' if opts[:p] || opts[:prune]
889
- arr_opts << '--prune-tags' if opts[:P] || opts[:'prune-tags']
890
- arr_opts << '--force' if opts[:f] || opts[:force]
891
- arr_opts << '--unshallow' if opts[:unshallow]
892
- arr_opts << '--depth' << opts[:depth] if opts[:depth]
893
- arr_opts << '--' if remote || opts[:ref]
894
- arr_opts << remote if remote
895
- arr_opts << opts[:ref] if opts[:ref]
896
-
897
- command('fetch', arr_opts)
898
- end
899
-
900
- def push(remote, branch = 'master', opts = {})
901
- # Small hack to keep backwards compatibility with the 'push(remote, branch, tags)' method signature.
902
- opts = {:tags => opts} if [true, false].include?(opts)
903
-
904
- arr_opts = []
905
- arr_opts << '--mirror' if opts[:mirror]
906
- arr_opts << '--delete' if opts[:delete]
907
- arr_opts << '--force' if opts[:force] || opts[:f]
908
- arr_opts << remote
909
-
910
- if opts[:mirror]
911
- command('push', arr_opts)
912
- else
913
- command('push', arr_opts + [branch])
914
- command('push', ['--tags'] + arr_opts) if opts[:tags]
915
- end
916
- end
917
-
918
- def pull(remote='origin', branch='master')
919
- command('pull', remote, branch)
920
- end
921
-
922
- def tag_sha(tag_name)
923
- head = File.join(@git_dir, 'refs', 'tags', tag_name)
924
- return File.read(head).chomp if File.exist?(head)
925
-
926
- command('show-ref', '--tags', '-s', tag_name)
927
- end
928
-
929
- def repack
930
- command('repack', '-a', '-d')
931
- end
932
-
933
- def gc
934
- command('gc', '--prune', '--aggressive', '--auto')
935
- end
936
-
937
- # reads a tree into the current index file
938
- def read_tree(treeish, opts = {})
939
- arr_opts = []
940
- arr_opts << "--prefix=#{opts[:prefix]}" if opts[:prefix]
941
- arr_opts += [treeish]
942
- command('read-tree', arr_opts)
943
- end
944
-
945
- def write_tree
946
- command('write-tree')
947
- end
948
-
949
- def commit_tree(tree, opts = {})
950
- opts[:message] ||= "commit tree #{tree}"
951
- t = Tempfile.new('commit-message')
952
- t.write(opts[:message])
953
- t.close
954
-
955
- arr_opts = []
956
- arr_opts << tree
957
- arr_opts << '-p' << opts[:parent] if opts[:parent]
958
- arr_opts += [opts[:parents]].map { |p| ['-p', p] }.flatten if opts[:parents]
959
- command('commit-tree', arr_opts, redirect: "< #{escape t.path}")
960
- end
961
-
962
- def update_ref(branch, commit)
963
- command('update-ref', branch, commit)
964
- end
965
-
966
- def checkout_index(opts = {})
967
- arr_opts = []
968
- arr_opts << "--prefix=#{opts[:prefix]}" if opts[:prefix]
969
- arr_opts << "--force" if opts[:force]
970
- arr_opts << "--all" if opts[:all]
971
- arr_opts << '--' << opts[:path_limiter] if opts[:path_limiter].is_a? String
972
-
973
- command('checkout-index', arr_opts)
974
- end
975
-
976
- # creates an archive file
977
- #
978
- # options
979
- # :format (zip, tar)
980
- # :prefix
981
- # :remote
982
- # :path
983
- def archive(sha, file = nil, opts = {})
984
- opts[:format] ||= 'zip'
985
-
986
- if opts[:format] == 'tgz'
987
- opts[:format] = 'tar'
988
- opts[:add_gzip] = true
989
- end
990
-
991
- if !file
992
- tempfile = Tempfile.new('archive')
993
- file = tempfile.path
994
- # delete it now, before we write to it, so that Ruby doesn't delete it
995
- # when it finalizes the Tempfile.
996
- tempfile.close!
997
- end
998
-
999
- arr_opts = []
1000
- arr_opts << "--format=#{opts[:format]}" if opts[:format]
1001
- arr_opts << "--prefix=#{opts[:prefix]}" if opts[:prefix]
1002
- arr_opts << "--remote=#{opts[:remote]}" if opts[:remote]
1003
- arr_opts << sha
1004
- arr_opts << '--' << opts[:path] if opts[:path]
1005
- command('archive', arr_opts, redirect: " > #{escape file}")
1006
- if opts[:add_gzip]
1007
- file_content = File.read(file)
1008
- Zlib::GzipWriter.open(file) do |gz|
1009
- gz.write(file_content)
1010
- end
1011
- end
1012
- return file
1013
- end
1014
-
1015
- # returns the current version of git, as an Array of Fixnums.
1016
- def current_command_version
1017
- output = command('version')
1018
- version = output[/\d+\.\d+(\.\d+)+/]
1019
- version.split('.').collect {|i| i.to_i}
1020
- end
1021
-
1022
- def required_command_version
1023
- [1, 6]
1024
- end
1025
-
1026
- def meets_required_version?
1027
- (self.current_command_version <=> self.required_command_version) >= 0
1028
- end
1029
-
1030
-
1031
- private
1032
-
1033
- # Systen ENV variables involved in the git commands.
1034
- #
1035
- # @return [<String>] the names of the EVN variables involved in the git commands
1036
- ENV_VARIABLE_NAMES = ['GIT_DIR', 'GIT_WORK_TREE', 'GIT_INDEX_FILE', 'GIT_SSH']
1037
-
1038
- def command_lines(cmd, *opts)
1039
- cmd_op = command(cmd, *opts)
1040
- if cmd_op.encoding.name != "UTF-8"
1041
- op = cmd_op.encode("UTF-8", "binary", :invalid => :replace, :undef => :replace)
1042
- else
1043
- op = cmd_op
1044
- end
1045
- op.split("\n")
1046
- end
1047
-
1048
- # Takes the current git's system ENV variables and store them.
1049
- def store_git_system_env_variables
1050
- @git_system_env_variables = {}
1051
- ENV_VARIABLE_NAMES.each do |env_variable_name|
1052
- @git_system_env_variables[env_variable_name] = ENV[env_variable_name]
1053
- end
1054
- end
1055
-
1056
- # Takes the previously stored git's ENV variables and set them again on ENV.
1057
- def restore_git_system_env_variables
1058
- ENV_VARIABLE_NAMES.each do |env_variable_name|
1059
- ENV[env_variable_name] = @git_system_env_variables[env_variable_name]
1060
- end
1061
- end
1062
-
1063
- # Sets git's ENV variables to the custom values for the current instance.
1064
- def set_custom_git_env_variables
1065
- ENV['GIT_DIR'] = @git_dir
1066
- ENV['GIT_WORK_TREE'] = @git_work_dir
1067
- ENV['GIT_INDEX_FILE'] = @git_index_file
1068
- ENV['GIT_SSH'] = Git::Base.config.git_ssh
1069
- end
1070
-
1071
- # Runs a block inside an environment with customized ENV variables.
1072
- # It restores the ENV after execution.
1073
- #
1074
- # @param [Proc] block block to be executed within the customized environment
1075
- def with_custom_env_variables(&block)
1076
- @@semaphore.synchronize do
1077
- store_git_system_env_variables()
1078
- set_custom_git_env_variables()
1079
- return block.call()
1080
- end
1081
- ensure
1082
- restore_git_system_env_variables()
1083
- end
1084
-
1085
- def command(cmd, *opts, &block)
1086
- command_opts = { chomp: true, redirect: '' }
1087
- if opts.last.is_a?(Hash)
1088
- command_opts.merge!(opts.pop)
1089
- end
1090
- command_opts.keys.each do |k|
1091
- raise ArgumentError.new("Unsupported option: #{k}") unless [:chomp, :redirect].include?(k)
1092
- end
1093
-
1094
- global_opts = []
1095
- global_opts << "--git-dir=#{@git_dir}" if !@git_dir.nil?
1096
- global_opts << "--work-tree=#{@git_work_dir}" if !@git_work_dir.nil?
1097
- global_opts << %w[-c core.quotePath=true]
1098
- global_opts << %w[-c color.ui=false]
1099
-
1100
- opts = [opts].flatten.map {|s| escape(s) }.join(' ')
1101
-
1102
- global_opts = global_opts.flatten.map {|s| escape(s) }.join(' ')
1103
-
1104
- git_cmd = "#{Git::Base.config.binary_path} #{global_opts} #{cmd} #{opts} #{command_opts[:redirect]} 2>&1"
1105
-
1106
- output = nil
1107
-
1108
- command_thread = nil;
1109
-
1110
- exitstatus = nil
1111
-
1112
- with_custom_env_variables do
1113
- command_thread = Thread.new do
1114
- output = run_command(git_cmd, &block)
1115
- exitstatus = $?.exitstatus
1116
- end
1117
- command_thread.join
1118
- end
1119
-
1120
- if @logger
1121
- @logger.info(git_cmd)
1122
- @logger.debug(output)
1123
- end
1124
-
1125
- raise Git::GitExecuteError, "#{git_cmd}:#{output}" if
1126
- exitstatus > 1 || (exitstatus == 1 && output != '')
1127
-
1128
- output.chomp! if output && command_opts[:chomp] && !block_given?
1129
-
1130
- output
1131
- end
1132
-
1133
- # Takes the diff command line output (as Array) and parse it into a Hash
1134
- #
1135
- # @param [String] diff_command the diff commadn to be used
1136
- # @param [Array] opts the diff options to be used
1137
- # @return [Hash] the diff as Hash
1138
- def diff_as_hash(diff_command, opts=[])
1139
- # update index before diffing to avoid spurious diffs
1140
- command('status')
1141
- command_lines(diff_command, opts).inject({}) do |memo, line|
1142
- info, file = line.split("\t")
1143
- mode_src, mode_dest, sha_src, sha_dest, type = info.split
1144
-
1145
- memo[file] = {
1146
- :mode_index => mode_dest,
1147
- :mode_repo => mode_src.to_s[1, 7],
1148
- :path => file,
1149
- :sha_repo => sha_src,
1150
- :sha_index => sha_dest,
1151
- :type => type
1152
- }
1153
-
1154
- memo
1155
- end
1156
- end
1157
-
1158
- # Returns an array holding the common options for the log commands
1159
- #
1160
- # @param [Hash] opts the given options
1161
- # @return [Array] the set of common options that the log command will use
1162
- def log_common_options(opts)
1163
- arr_opts = []
1164
-
1165
- arr_opts << "-#{opts[:count]}" if opts[:count]
1166
- arr_opts << "--no-color"
1167
- arr_opts << "--cherry" if opts[:cherry]
1168
- arr_opts << "--since=#{opts[:since]}" if opts[:since].is_a? String
1169
- arr_opts << "--until=#{opts[:until]}" if opts[:until].is_a? String
1170
- arr_opts << "--grep=#{opts[:grep]}" if opts[:grep].is_a? String
1171
- arr_opts << "--author=#{opts[:author]}" if opts[:author].is_a? String
1172
- arr_opts << "#{opts[:between][0].to_s}..#{opts[:between][1].to_s}" if (opts[:between] && opts[:between].size == 2)
1173
-
1174
- arr_opts
1175
- end
1176
-
1177
- # Retrurns an array holding path options for the log commands
1178
- #
1179
- # @param [Hash] opts the given options
1180
- # @return [Array] the set of path options that the log command will use
1181
- def log_path_options(opts)
1182
- arr_opts = []
1183
-
1184
- arr_opts << opts[:object] if opts[:object].is_a? String
1185
- arr_opts << '--' << opts[:path_limiter] if opts[:path_limiter]
1186
- arr_opts
1187
- end
1188
-
1189
- def run_command(git_cmd, &block)
1190
- return IO.popen(git_cmd, &block) if block_given?
1191
-
1192
- `#{git_cmd}`.lines.map { |l| Git::EncodingUtils.normalize_encoding(l) }.join
1193
- end
1194
-
1195
- def escape(s)
1196
- windows_platform? ? escape_for_windows(s) : escape_for_sh(s)
1197
- end
1198
-
1199
- def escape_for_sh(s)
1200
- "'#{s && s.to_s.gsub('\'','\'"\'"\'')}'"
1201
- end
1202
-
1203
- def escape_for_windows(s)
1204
- # Escape existing double quotes in s and then wrap the result with double quotes
1205
- escaped_string = s.to_s.gsub('"','\\"')
1206
- %Q{"#{escaped_string}"}
1207
- end
1208
-
1209
- def windows_platform?
1210
- # Check if on Windows via RUBY_PLATFORM (CRuby) and RUBY_DESCRIPTION (JRuby)
1211
- win_platform_regex = /mingw|mswin/
1212
- RUBY_PLATFORM =~ win_platform_regex || RUBY_DESCRIPTION =~ win_platform_regex
1213
- end
1214
- end
1215
- end