@@ -49,8 +49,14 @@ def clone(repository, name, opts = {})
49
49
50
50
arr_opts = [ ]
51
51
arr_opts << "--bare" if opts [ :bare ]
52
- arr_opts << "-o #{ opts [ :remote ] } " if opts [ :remote ]
53
- arr_opts << "--depth #{ opts [ :depth ] . to_i } " if opts [ :depth ] && opts [ :depth ] . to_i > 0
52
+ if opts [ :remote ]
53
+ arr_opts << "-o"
54
+ arr_opts << opts [ :remote ]
55
+ end
56
+ if opts [ :depth ] && opts [ :depth ] . to_i > 0
57
+ arr_opts << "--depth"
58
+ arr_opts << opts [ :depth ] . to_i
59
+ end
54
60
arr_opts << repository
55
61
arr_opts << clone_dir
56
62
@@ -66,35 +72,41 @@ def clone(repository, name, opts = {})
66
72
def log_commits ( opts = { } )
67
73
arr_opts = [ '--pretty=oneline' ]
68
74
arr_opts << "-#{ opts [ :count ] } " if opts [ :count ]
69
- arr_opts << "--since=\" #{ opts [ :since ] } \" " if opts [ :since ] . is_a? String
70
- arr_opts << "--until=\" #{ opts [ :until ] } \" " if opts [ :until ] . is_a? String
71
- arr_opts << "--grep=\" #{ opts [ :grep ] } \" " if opts [ :grep ] . is_a? String
72
- arr_opts << "--author=\" #{ opts [ :author ] } \" " if opts [ :author ] . is_a? String
75
+ arr_opts << "--since=#{ opts [ :since ] } " if opts [ :since ] . is_a? String
76
+ arr_opts << "--until=#{ opts [ :until ] } " if opts [ :until ] . is_a? String
77
+ arr_opts << "--grep=#{ opts [ :grep ] } " if opts [ :grep ] . is_a? String
78
+ arr_opts << "--author=#{ opts [ :author ] } " if opts [ :author ] . is_a? String
73
79
arr_opts << "#{ opts [ :between ] [ 0 ] . to_s } ..#{ opts [ :between ] [ 1 ] . to_s } " if ( opts [ :between ] && opts [ :between ] . size == 2 )
74
80
arr_opts << opts [ :object ] if opts [ :object ] . is_a? String
75
- arr_opts << '-- ' + opts [ :path_limiter ] if opts [ :path_limiter ] . is_a? String
76
-
81
+ if opts [ :path_limiter ] . is_a? String
82
+ arr_opts << '--'
83
+ arr_opts << opts [ :path_limiter ]
84
+ end
85
+
77
86
command_lines ( 'log' , arr_opts , true ) . map { |l | l . split . first }
78
87
end
79
88
80
89
def full_log_commits ( opts = { } )
81
90
arr_opts = [ '--pretty=raw' ]
82
91
arr_opts << "-#{ opts [ :count ] } " if opts [ :count ]
83
- arr_opts << "--skip=\" #{ opts [ :skip ] } \" " if opts [ :skip ]
84
- arr_opts << "--since=\" #{ opts [ :since ] } \" " if opts [ :since ] . is_a? String
85
- arr_opts << "--until=\" #{ opts [ :until ] } \" " if opts [ :until ] . is_a? String
86
- arr_opts << "--grep=\" #{ opts [ :grep ] } \" " if opts [ :grep ] . is_a? String
87
- arr_opts << "--author=\" #{ opts [ :author ] } \" " if opts [ :author ] . is_a? String
92
+ arr_opts << "--skip=#{ opts [ :skip ] } " if opts [ :skip ]
93
+ arr_opts << "--since=#{ opts [ :since ] } " if opts [ :since ] . is_a? String
94
+ arr_opts << "--until=#{ opts [ :until ] } " if opts [ :until ] . is_a? String
95
+ arr_opts << "--grep=#{ opts [ :grep ] } " if opts [ :grep ] . is_a? String
96
+ arr_opts << "--author=#{ opts [ :author ] } " if opts [ :author ] . is_a? String
88
97
arr_opts << "#{ opts [ :between ] [ 0 ] . to_s } ..#{ opts [ :between ] [ 1 ] . to_s } " if ( opts [ :between ] && opts [ :between ] . size == 2 )
89
98
arr_opts << opts [ :object ] if opts [ :object ] . is_a? String
90
- arr_opts << '-- ' + opts [ :path_limiter ] if opts [ :path_limiter ] . is_a? String
99
+ if opts [ :path_limiter ] . is_a? String
100
+ arr_opts << '--'
101
+ arr_opts << opts [ :path_limiter ]
102
+ end
91
103
92
104
full_log = command_lines ( 'log' , arr_opts , true )
93
105
process_commit_data ( full_log )
94
106
end
95
107
96
108
def revparse ( string )
97
- return string if string =~ /\w {40}/ # passing in a sha - just no-op it
109
+ return string if string =~ /[A-Fa-f0-9] {40}/ # passing in a sha - just no-op it
98
110
rev = [ 'head' , 'remotes' , 'tags' ] . map do |d |
99
111
File . join ( @git_dir , 'refs' , d , string )
100
112
end . find do |path |
@@ -170,7 +182,7 @@ def object_contents(sha, &block)
170
182
def ls_tree ( sha )
171
183
data = { 'blob' => { } , 'tree' => { } }
172
184
173
- command_lines ( 'ls-tree' , sha . to_s ) . each do |line |
185
+ command_lines ( 'ls-tree' , sha ) . each do |line |
174
186
( info , filenm ) = line . split ( "\t " )
175
187
( mode , type , sha ) = info . split
176
188
data [ type ] [ filenm ] = { :mode => mode , :sha => sha }
@@ -184,7 +196,7 @@ def mv(file1, file2)
184
196
end
185
197
186
198
def full_tree ( sha )
187
- command_lines ( 'ls-tree' , [ '-r' , sha . to_s ] )
199
+ command_lines ( 'ls-tree' , [ '-r' , sha ] )
188
200
end
189
201
190
202
def tree_depth ( sha )
@@ -225,9 +237,15 @@ def grep(string, opts = {})
225
237
grep_opts = [ '-n' ]
226
238
grep_opts << '-i' if opts [ :ignore_case ]
227
239
grep_opts << '-v' if opts [ :invert_match ]
228
- grep_opts << "-e '#{ string } '"
240
+ grep_opts << '-e'
241
+ grep_opts << string
229
242
grep_opts << opts [ :object ] if opts [ :object ] . is_a? ( String )
230
- grep_opts << ( '-- ' + opts [ :path_limiter ] ) if opts [ :path_limiter ] . is_a? String
243
+
244
+ if opts [ :path_limiter ] . is_a? String
245
+ grep_opts << '--'
246
+ grep_opts << opts [ :path_limiter ]
247
+ end
248
+
231
249
hsh = { }
232
250
command_lines ( 'grep' , grep_opts ) . each do |line |
233
251
if m = /(.*)\: (\d +)\: (.*)/ . match ( line )
@@ -242,17 +260,25 @@ def diff_full(obj1 = 'HEAD', obj2 = nil, opts = {})
242
260
diff_opts = [ '-p' ]
243
261
diff_opts << obj1
244
262
diff_opts << obj2 if obj2 . is_a? ( String )
245
- diff_opts << ( '-- ' + opts [ :path_limiter ] ) if opts [ :path_limiter ] . is_a? String
246
-
263
+
264
+ if opts [ :path_limiter ] . is_a? String
265
+ diff_opts << '--'
266
+ diff_opts << opts [ :path_limiter ]
267
+ end
268
+
247
269
command ( 'diff' , diff_opts )
248
270
end
249
271
250
272
def diff_stats ( obj1 = 'HEAD' , obj2 = nil , opts = { } )
251
273
diff_opts = [ '--numstat' ]
252
274
diff_opts << obj1
253
275
diff_opts << obj2 if obj2 . is_a? ( String )
254
- diff_opts << ( '-- ' + opts [ :path_limiter ] ) if opts [ :path_limiter ] . is_a? String
255
-
276
+
277
+ if opts [ :path_limiter ] . is_a? String
278
+ diff_opts << '--'
279
+ diff_opts << opts [ :path_limiter ]
280
+ end
281
+
256
282
hsh = { :total => { :insertions => 0 , :deletions => 0 , :lines => 0 , :files => 0 } , :files => { } }
257
283
258
284
command_lines ( 'diff' , diff_opts ) . each do |file |
@@ -351,48 +377,52 @@ def parse_config(file)
351
377
## WRITE COMMANDS ##
352
378
353
379
def config_set ( name , value )
354
- command ( 'config' , [ name , "' #{ value } '" ] )
380
+ command ( 'config' , [ name , value ] )
355
381
end
356
382
357
383
def add ( path = '.' )
358
- path = path . join ( ' ' ) if path . is_a? ( Array )
359
384
command ( 'add' , path )
360
385
end
361
386
362
387
def remove ( path = '.' , opts = { } )
363
- path = path . join ( ' ' ) if path . is_a? ( Array )
364
-
365
388
arr_opts = [ '-f' ] # overrides the up-to-date check by default
366
389
arr_opts << [ '-r' ] if opts [ :recursive ]
367
- arr_opts << path
390
+ if path . is_a? ( Array )
391
+ arr_opts += path
392
+ else
393
+ arr_opts << path
394
+ end
368
395
369
396
command ( 'rm' , arr_opts )
370
397
end
371
398
372
399
def commit ( message , opts = { } )
373
- arr_opts = [ "-m ' #{ message } '" ]
400
+ arr_opts = [ '-m' , message ]
374
401
arr_opts << '-a' if opts [ :add_all ]
375
402
arr_opts << '--allow-empty' if opts [ :allow_empty ]
376
- arr_opts << "--author '#{ opts [ :author ] } '" if opts [ :author ]
403
+ if opts [ :author ]
404
+ arr_opts << "--author"
405
+ arr_opts << opts [ :author ]
406
+ end
377
407
command ( 'commit' , arr_opts )
378
408
end
379
409
380
410
def reset ( commit , opts = { } )
381
411
arr_opts = [ ]
382
412
arr_opts << '--hard' if opts [ :hard ]
383
- arr_opts << commit . to_s if commit
413
+ arr_opts << commit if commit
384
414
command ( 'reset' , arr_opts )
385
415
end
386
416
387
417
def apply ( patch_file )
388
418
arr_opts = [ ]
389
- arr_opts << patch_file . to_s if patch_file
419
+ arr_opts << patch_file if patch_file
390
420
command ( 'apply' , arr_opts )
391
421
end
392
422
393
423
def apply_mail ( patch_file )
394
424
arr_opts = [ ]
395
- arr_opts << patch_file . to_s if patch_file
425
+ arr_opts << patch_file if patch_file
396
426
command ( 'am' , arr_opts )
397
427
end
398
428
@@ -437,23 +467,29 @@ def branch_delete(branch)
437
467
def checkout ( branch , opts = { } )
438
468
arr_opts = [ ]
439
469
arr_opts << '-f' if opts [ :force ]
440
- arr_opts << [ "-b '#{ opts [ :new_branch ] } '" ] if opts [ :new_branch ]
441
- arr_opts << branch . to_s
470
+ if opts [ :new_branch ]
471
+ arr_opts << '-b'
472
+ arr_opts << opts [ :new_branch ]
473
+ end
474
+ arr_opts << branch
442
475
443
476
command ( 'checkout' , arr_opts )
444
477
end
445
478
446
479
def checkout_file ( version , file )
447
480
arr_opts = [ ]
448
- arr_opts << version . to_s
449
- arr_opts << file . to_s
481
+ arr_opts << version
482
+ arr_opts << file
450
483
command ( 'checkout' , arr_opts )
451
484
end
452
485
453
486
def merge ( branch , message = nil )
454
487
arr_opts = [ ]
455
- arr_opts << [ "-m '#{ message } '" ] if message
456
- arr_opts << branch . to_a . join ( ' ' )
488
+ if message
489
+ arr_opts << '-m'
490
+ arr_opts << message
491
+ end
492
+ arr_opts += branch . to_a
457
493
command ( 'merge' , arr_opts )
458
494
end
459
495
@@ -468,12 +504,10 @@ def unmerged
468
504
def conflicts # :yields: file, your, their
469
505
self . unmerged . each do |f |
470
506
your = Tempfile . new ( "YOUR-#{ File . basename ( f ) } " ) . path
471
- arr_opts = [ ":2:#{ f } " , ">#{ your } " ]
472
- command ( 'show' , arr_opts )
507
+ command ( 'show' , ":2:#{ f } " , true , "> #{ escape your } " )
473
508
474
509
their = Tempfile . new ( "THEIR-#{ File . basename ( f ) } " ) . path
475
- arr_opts = [ ":3:#{ f } " , ">#{ their } " ]
476
- command ( 'show' , arr_opts )
510
+ command ( 'show' , ":3:#{ f } " , true , "> #{ escape their } " )
477
511
yield ( f , your , their )
478
512
end
479
513
end
@@ -507,12 +541,12 @@ def tag(tag)
507
541
508
542
509
543
def fetch ( remote )
510
- command ( 'fetch' , remote . to_s )
544
+ command ( 'fetch' , remote )
511
545
end
512
546
513
547
def push ( remote , branch = 'master' , tags = false )
514
- command ( 'push' , [ remote . to_s , branch . to_s ] )
515
- command ( 'push' , [ '--tags' , remote . to_s ] ) if tags
548
+ command ( 'push' , [ remote , branch ] )
549
+ command ( 'push' , [ '--tags' , remote ] ) if tags
516
550
end
517
551
518
552
def tag_sha ( tag_name )
@@ -534,7 +568,7 @@ def gc
534
568
def read_tree ( treeish , opts = { } )
535
569
arr_opts = [ ]
536
570
arr_opts << "--prefix=#{ opts [ :prefix ] } " if opts [ :prefix ]
537
- arr_opts << treeish . to_a . join ( ' ' )
571
+ arr_opts += treeish . to_a
538
572
command ( 'read-tree' , arr_opts )
539
573
end
540
574
@@ -550,22 +584,29 @@ def commit_tree(tree, opts = {})
550
584
551
585
arr_opts = [ ]
552
586
arr_opts << tree
553
- arr_opts << "-p #{ opts [ :parent ] } " if opts [ :parent ]
554
- arr_opts += opts [ :parents ] . map { |p | "-p #{ p . to_s } " } if opts [ :parents ]
555
- arr_opts << "< #{ t . path } "
556
- command ( 'commit-tree' , arr_opts )
587
+ if opts [ :parent ]
588
+ arr_opts << '-p'
589
+ arr_opts << opts [ :parent ]
590
+ end
591
+ arr_opts += opts [ :parents ] . map { |p | [ '-p' , p ] } . flatten if opts [ :parents ]
592
+ command ( 'commit-tree' , arr_opts , true , "< #{ escape t . path } " )
557
593
end
558
594
559
595
def update_ref ( branch , commit )
560
- command ( 'update-ref' , [ branch . to_s , commit . to_s ] )
596
+ command ( 'update-ref' , [ branch , commit ] )
561
597
end
562
598
563
599
def checkout_index ( opts = { } )
564
600
arr_opts = [ ]
565
601
arr_opts << "--prefix=#{ opts [ :prefix ] } " if opts [ :prefix ]
566
602
arr_opts << "--force" if opts [ :force ]
567
603
arr_opts << "--all" if opts [ :all ]
568
- arr_opts << ( '-- ' + opts [ :path_limiter ] ) if opts [ :path_limiter ] . is_a? String
604
+
605
+ if opts [ :path_limiter ] . is_a? String
606
+ arr_opts << '--'
607
+ arr_opts << opts [ :path_limiter ]
608
+ end
609
+
569
610
command ( 'checkout-index' , arr_opts )
570
611
end
571
612
@@ -592,26 +633,24 @@ def archive(sha, file = nil, opts = {})
592
633
arr_opts << "--remote=#{ opts [ :remote ] } " if opts [ :remote ]
593
634
arr_opts << sha
594
635
arr_opts << opts [ :path ] if opts [ :path ]
595
- arr_opts << '| gzip' if opts [ :add_gzip ]
596
- arr_opts << "> #{ file . to_s } "
597
- command ( 'archive' , arr_opts )
636
+ command ( 'archive' , arr_opts , true , ( opts [ :add_gzip ] ? '| gzip' : '' ) + " > #{ escape file } " )
598
637
return file
599
638
end
600
639
601
640
private
602
641
603
- def command_lines ( cmd , opts = [ ] , chdir = true )
642
+ def command_lines ( cmd , opts = [ ] , chdir = true , redirect = '' )
604
643
command ( cmd , opts , chdir ) . split ( "\n " )
605
644
end
606
645
607
- def command ( cmd , opts = [ ] , chdir = true , &block )
646
+ def command ( cmd , opts = [ ] , chdir = true , redirect = '' , &block )
608
647
ENV [ 'GIT_DIR' ] = @git_dir
609
648
ENV [ 'GIT_INDEX_FILE' ] = @git_index_file
610
649
ENV [ 'GIT_WORK_TREE' ] = @git_work_dir
611
650
path = @git_work_dir || @git_dir || @path
612
651
613
- opts = opts . to_a . join ( ' ' )
614
- git_cmd = "git #{ cmd } #{ opts } 2>&1"
652
+ opts = opts . map { | s | escape ( s ) } . join ( ' ' )
653
+ git_cmd = "git #{ cmd } #{ opts } #{ redirect } 2>&1"
615
654
616
655
out = nil
617
656
if chdir && ( Dir . getwd != path )
@@ -641,6 +680,10 @@ def run_command(git_cmd, &block)
641
680
`#{ git_cmd } ` . chomp
642
681
end
643
682
end
644
-
683
+
684
+ def escape ( s )
685
+ "'" + s . to_s . gsub ( '\'' , '\'\\\'\'' ) + "'"
686
+ end
687
+
645
688
end
646
689
end
0 commit comments