grit 1.1.1 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of grit might be problematic. Click here for more details.

Files changed (66) hide show
  1. data/History.txt +9 -0
  2. data/README.md +37 -11
  3. data/VERSION.yml +3 -3
  4. data/examples/ex_add_commit.rb +13 -0
  5. data/examples/ex_index.rb +14 -0
  6. data/lib/grit.rb +10 -3
  7. data/lib/grit/actor.rb +5 -5
  8. data/lib/grit/blob.rb +12 -12
  9. data/lib/grit/commit.rb +3 -3
  10. data/lib/grit/commit_stats.rb +26 -26
  11. data/lib/grit/config.rb +9 -9
  12. data/lib/grit/diff.rb +16 -16
  13. data/lib/grit/errors.rb +1 -1
  14. data/lib/grit/git-ruby.rb +108 -27
  15. data/lib/grit/git-ruby/commit_db.rb +11 -11
  16. data/lib/grit/git-ruby/file_index.rb +28 -28
  17. data/lib/grit/git-ruby/git_object.rb +14 -14
  18. data/lib/grit/git-ruby/internal/file_window.rb +4 -4
  19. data/lib/grit/git-ruby/internal/loose.rb +10 -10
  20. data/lib/grit/git-ruby/internal/pack.rb +29 -29
  21. data/lib/grit/git-ruby/internal/raw_object.rb +4 -4
  22. data/lib/grit/git-ruby/object.rb +9 -9
  23. data/lib/grit/git-ruby/repository.rb +111 -107
  24. data/lib/grit/git.rb +191 -14
  25. data/lib/grit/index.rb +21 -21
  26. data/lib/grit/lazy.rb +1 -1
  27. data/lib/grit/merge.rb +9 -9
  28. data/lib/grit/ref.rb +6 -31
  29. data/lib/grit/repo.rb +110 -65
  30. data/lib/grit/ruby1.9.rb +1 -1
  31. data/lib/grit/status.rb +24 -24
  32. data/lib/grit/submodule.rb +15 -15
  33. data/lib/grit/tag.rb +7 -57
  34. data/lib/grit/tree.rb +12 -12
  35. data/test/bench/benchmarks.rb +126 -0
  36. data/test/helper.rb +18 -0
  37. data/test/profile.rb +21 -0
  38. data/test/suite.rb +6 -0
  39. data/test/test_actor.rb +35 -0
  40. data/test/test_blame.rb +32 -0
  41. data/test/test_blame_tree.rb +33 -0
  42. data/test/test_blob.rb +83 -0
  43. data/test/test_commit.rb +207 -0
  44. data/test/test_commit_stats.rb +33 -0
  45. data/test/test_commit_write.rb +20 -0
  46. data/test/test_config.rb +58 -0
  47. data/test/test_diff.rb +18 -0
  48. data/test/test_file_index.rb +56 -0
  49. data/test/test_git.rb +105 -0
  50. data/test/test_grit.rb +32 -0
  51. data/test/test_head.rb +47 -0
  52. data/test/test_index_status.rb +40 -0
  53. data/test/test_merge.rb +17 -0
  54. data/test/test_raw.rb +16 -0
  55. data/test/test_real.rb +19 -0
  56. data/test/test_reality.rb +17 -0
  57. data/test/test_remote.rb +14 -0
  58. data/test/test_repo.rb +349 -0
  59. data/test/test_rubygit.rb +192 -0
  60. data/test/test_rubygit_alt.rb +40 -0
  61. data/test/test_rubygit_index.rb +76 -0
  62. data/test/test_rubygit_iv2.rb +28 -0
  63. data/test/test_submodule.rb +69 -0
  64. data/test/test_tag.rb +67 -0
  65. data/test/test_tree.rb +101 -0
  66. metadata +43 -13
@@ -1,16 +1,16 @@
1
1
  module Grit
2
-
2
+
3
3
  class Repo
4
4
  DAEMON_EXPORT_FILE = 'git-daemon-export-ok'
5
-
5
+
6
6
  # The path of the git repo as a String
7
7
  attr_accessor :path
8
8
  attr_accessor :working_dir
9
9
  attr_reader :bare
10
-
10
+
11
11
  # The git command line interface object
12
12
  attr_accessor :git
13
-
13
+
14
14
  # Create a new Repo instance
15
15
  # +path+ is the path to either the root git directory or the bare git repo
16
16
  # +options+ :is_bare force to load a bare repo
@@ -22,7 +22,7 @@ module Grit
22
22
  # Returns Grit::Repo
23
23
  def initialize(path, options = {})
24
24
  epath = File.expand_path(path)
25
-
25
+
26
26
  if File.exist?(File.join(epath, '.git'))
27
27
  self.working_dir = epath
28
28
  self.path = File.join(epath, '.git')
@@ -35,10 +35,10 @@ module Grit
35
35
  else
36
36
  raise NoSuchPathError.new(epath)
37
37
  end
38
-
38
+
39
39
  self.git = Git.new(self.path)
40
40
  end
41
-
41
+
42
42
  # Does nothing yet...
43
43
  def self.init(path)
44
44
  # !! TODO !!
@@ -46,19 +46,19 @@ module Grit
46
46
  # generate initial git directory
47
47
  # create new Grit::Repo on that dir, return it
48
48
  end
49
-
49
+
50
50
  # The project's description. Taken verbatim from GIT_REPO/description
51
51
  #
52
52
  # Returns String
53
53
  def description
54
- File.open(File.join(self.path, 'description')).read.chomp
54
+ self.git.fs_read('description').chomp
55
55
  end
56
56
 
57
57
  def blame(file, commit = nil)
58
58
  Blame.new(self, file, commit)
59
59
  end
60
60
 
61
-
61
+
62
62
  # An array of Head objects representing the branch heads in
63
63
  # this repo
64
64
  #
@@ -66,17 +66,17 @@ module Grit
66
66
  def heads
67
67
  Head.find_all(self)
68
68
  end
69
-
69
+
70
70
  alias_method :branches, :heads
71
71
 
72
72
  def get_head(head_name)
73
73
  heads.find { |h| h.name == head_name }
74
74
  end
75
-
75
+
76
76
  def is_head?(head_name)
77
77
  get_head(head_name)
78
78
  end
79
-
79
+
80
80
  # Object reprsenting the current repo head.
81
81
  #
82
82
  # Returns Grit::Head (baked)
@@ -108,18 +108,18 @@ module Grit
108
108
  def remove(*files)
109
109
  self.git.rm({}, *files.flatten)
110
110
  end
111
-
111
+
112
112
 
113
113
  def blame_tree(commit, path = nil)
114
114
  commit_array = self.git.blame_tree(commit, path)
115
-
115
+
116
116
  final_array = {}
117
117
  commit_array.each do |file, sha|
118
118
  final_array[file] = commit(sha)
119
119
  end
120
120
  final_array
121
121
  end
122
-
122
+
123
123
  def status
124
124
  Status.new(self)
125
125
  end
@@ -131,7 +131,7 @@ module Grit
131
131
  def tags
132
132
  Tag.find_all(self)
133
133
  end
134
-
134
+
135
135
  # An array of Remote objects representing the remote branches in
136
136
  # this repo
137
137
  #
@@ -140,6 +140,34 @@ module Grit
140
140
  Remote.find_all(self)
141
141
  end
142
142
 
143
+ def remote_list
144
+ self.git.list_remotes
145
+ end
146
+
147
+ def remote_add(name, url)
148
+ self.git.remote({}, 'add', name, url)
149
+ end
150
+
151
+ def remote_fetch(name)
152
+ self.git.fetch({}, name)
153
+ end
154
+
155
+ # takes an array of remote names and last pushed dates
156
+ # fetches from all of the remotes where the local fetch
157
+ # date is earlier than the passed date, then records the
158
+ # last fetched date
159
+ #
160
+ # { 'origin' => date,
161
+ # 'peter => date,
162
+ # }
163
+ def remotes_fetch_needed(remotes)
164
+ remotes.each do |remote, date|
165
+ # TODO: check against date
166
+ self.remote_fetch(remote)
167
+ end
168
+ end
169
+
170
+
143
171
  # An array of Ref objects representing the refs in
144
172
  # this repo
145
173
  #
@@ -151,10 +179,10 @@ module Grit
151
179
  def commit_stats(start = 'master', max_count = 10, skip = 0)
152
180
  options = {:max_count => max_count,
153
181
  :skip => skip}
154
-
182
+
155
183
  CommitStats.find_all(self, start, options)
156
184
  end
157
-
185
+
158
186
  # An array of Commit objects representing the history of a given ref/commit
159
187
  # +start+ is the branch/commit name (default 'master')
160
188
  # +max_count+ is the maximum number of commits to return (default 10, use +false+ for all)
@@ -164,10 +192,10 @@ module Grit
164
192
  def commits(start = 'master', max_count = 10, skip = 0)
165
193
  options = {:max_count => max_count,
166
194
  :skip => skip}
167
-
195
+
168
196
  Commit.find_all(self, start, options)
169
197
  end
170
-
198
+
171
199
  # The Commits objects that are reachable via +to+ but not via +from+
172
200
  # Commits are returned in chronological order.
173
201
  # +from+ is the branch/commit name of the younger item
@@ -177,7 +205,7 @@ module Grit
177
205
  def commits_between(from, to)
178
206
  Commit.find_all(self, "#{from}..#{to}").reverse
179
207
  end
180
-
208
+
181
209
  # The Commits objects that are newer than the specified date.
182
210
  # Commits are returned in chronological order.
183
211
  # +start+ is the branch/commit name (default 'master')
@@ -187,10 +215,10 @@ module Grit
187
215
  # Returns Grit::Commit[] (baked)
188
216
  def commits_since(start = 'master', since = '1970-01-01', extra_options = {})
189
217
  options = {:since => since}.merge(extra_options)
190
-
218
+
191
219
  Commit.find_all(self, start, options)
192
220
  end
193
-
221
+
194
222
  # The number of commits reachable by the given branch/commit
195
223
  # +start+ is the branch/commit name (default 'master')
196
224
  #
@@ -198,17 +226,17 @@ module Grit
198
226
  def commit_count(start = 'master')
199
227
  Commit.count(self, start)
200
228
  end
201
-
229
+
202
230
  # The Commit object for the specified id
203
231
  # +id+ is the SHA1 identifier of the commit
204
232
  #
205
233
  # Returns Grit::Commit (baked)
206
234
  def commit(id)
207
235
  options = {:max_count => 1}
208
-
236
+
209
237
  Commit.find_all(self, id, options).first
210
238
  end
211
-
239
+
212
240
  # Returns a list of commits that is in +other_repo+ but not in self
213
241
  #
214
242
  # Returns Grit::Commit[]
@@ -217,12 +245,12 @@ module Grit
217
245
  # rev-list'ing the whole thing
218
246
  repo_refs = self.git.rev_list({}, ref).strip.split("\n")
219
247
  other_repo_refs = other_repo.git.rev_list({}, other_ref).strip.split("\n")
220
-
248
+
221
249
  (other_repo_refs - repo_refs).map do |ref|
222
250
  Commit.find_all(other_repo, ref, {:max_count => 1}).first
223
251
  end
224
252
  end
225
-
253
+
226
254
  # The Tree object for the given treeish reference
227
255
  # +treeish+ is the reference (default 'master')
228
256
  # +paths+ is an optional Array of directory paths to restrict the tree (deafult [])
@@ -234,7 +262,7 @@ module Grit
234
262
  def tree(treeish = 'master', paths = [])
235
263
  Tree.construct(self, treeish, paths)
236
264
  end
237
-
265
+
238
266
  # The Blob object for the given id
239
267
  # +id+ is the SHA1 id of the blob
240
268
  #
@@ -253,7 +281,7 @@ module Grit
253
281
  commits = self.git.log(actual_options, *arg)
254
282
  Commit.list_from_string(self, commits)
255
283
  end
256
-
284
+
257
285
  # The diff from commit +a+ to commit +b+, optionally restricted to the given file(s)
258
286
  # +a+ is the base commit
259
287
  # +b+ is the other commit
@@ -261,7 +289,7 @@ module Grit
261
289
  def diff(a, b, *paths)
262
290
  self.git.diff({}, a, b, '--', *paths)
263
291
  end
264
-
292
+
265
293
  # The commit diff for the given commit
266
294
  # +commit+ is the commit name/id
267
295
  #
@@ -269,7 +297,7 @@ module Grit
269
297
  def commit_diff(commit)
270
298
  Commit.diff(self, commit)
271
299
  end
272
-
300
+
273
301
  # Initialize a bare git repository at the given path
274
302
  # +path+ is the full path to the repo (traditionally ends with /<name>.git)
275
303
  # +options+ is any additional options to the git init command
@@ -279,11 +307,13 @@ module Grit
279
307
  #
280
308
  # Returns Grit::Repo (the newly created repo)
281
309
  def self.init_bare(path, git_options = {}, repo_options = {})
310
+ git_options = {:bare => true}.merge(git_options)
282
311
  git = Git.new(path)
312
+ git.fs_mkdir('..')
283
313
  git.init(git_options)
284
314
  self.new(path, repo_options)
285
315
  end
286
-
316
+
287
317
  # Fork a bare git repository from this repo
288
318
  # +path+ is the full path of the new repo (traditionally ends with /<name>.git)
289
319
  # +options+ is any additional options to the git clone command (:bare and :shared are true by default)
@@ -292,10 +322,24 @@ module Grit
292
322
  def fork_bare(path, options = {})
293
323
  default_options = {:bare => true, :shared => true}
294
324
  real_options = default_options.merge(options)
325
+ Git.new(path).fs_mkdir('..')
295
326
  self.git.clone(real_options, self.path, path)
296
327
  Repo.new(path)
297
328
  end
298
-
329
+
330
+ # Fork a bare git repository from another repo
331
+ # +path+ is the full path of the new repo (traditionally ends with /<name>.git)
332
+ # +options+ is any additional options to the git clone command (:bare and :shared are true by default)
333
+ #
334
+ # Returns Grit::Repo (the newly forked repo)
335
+ def fork_bare_from(path, options = {})
336
+ default_options = {:bare => true, :shared => true}
337
+ real_options = default_options.merge(options)
338
+ Git.new(self.path).fs_mkdir('..')
339
+ self.git.clone(real_options, path, self.path)
340
+ Repo.new(self.path)
341
+ end
342
+
299
343
  # Archive the given treeish
300
344
  # +treeish+ is the treeish name/id (default 'master')
301
345
  # +prefix+ is the optional prefix
@@ -316,7 +360,7 @@ module Grit
316
360
  options[:prefix] = prefix if prefix
317
361
  self.git.archive(options, treeish)
318
362
  end
319
-
363
+
320
364
  # Archive and gzip the given treeish
321
365
  # +treeish+ is the treeish name/id (default 'master')
322
366
  # +prefix+ is the optional prefix
@@ -335,7 +379,7 @@ module Grit
335
379
  def archive_tar_gz(treeish = 'master', prefix = nil)
336
380
  options = {}
337
381
  options[:prefix] = prefix if prefix
338
- self.git.archive(options, treeish, "| gzip")
382
+ self.git.archive(options, treeish, "| gzip -n")
339
383
  end
340
384
 
341
385
  # Write an archive directly to a file
@@ -358,34 +402,33 @@ module Grit
358
402
  #
359
403
  # Returns nothing
360
404
  def enable_daemon_serve
361
- FileUtils.touch(File.join(self.path, DAEMON_EXPORT_FILE))
405
+ self.git.fs_write(DAEMON_EXPORT_FILE, '')
362
406
  end
363
-
407
+
364
408
  # Disable git-daemon serving of this repository by ensuring there is no
365
409
  # git-daemon-export-ok file in its git directory
366
410
  #
367
411
  # Returns nothing
368
412
  def disable_daemon_serve
369
- FileUtils.rm_f(File.join(self.path, DAEMON_EXPORT_FILE))
413
+ self.git.fs_delete(DAEMON_EXPORT_FILE)
370
414
  end
371
-
415
+
372
416
  def gc_auto
373
417
  self.git.gc({:auto => true})
374
418
  end
375
-
419
+
376
420
  # The list of alternates for this repo
377
421
  #
378
422
  # Returns Array[String] (pathnames of alternates)
379
423
  def alternates
380
- alternates_path = File.join(self.path, *%w{objects info alternates})
381
-
382
- if File.exist?(alternates_path)
383
- File.read(alternates_path).strip.split("\n")
424
+ alternates_path = "objects/info/alternates"
425
+ if self.git.fs_exist?(alternates_path)
426
+ self.git.fs_read(alternates_path).strip.split("\n")
384
427
  else
385
428
  []
386
429
  end
387
430
  end
388
-
431
+
389
432
  # Sets the alternates
390
433
  # +alts+ is the Array of String paths representing the alternates
391
434
  #
@@ -396,42 +439,44 @@ module Grit
396
439
  raise "Could not set alternates. Alternate path #{alt} must exist"
397
440
  end
398
441
  end
399
-
442
+
400
443
  if alts.empty?
401
- File.open(File.join(self.path, *%w{objects info alternates}), 'w') do |f|
402
- f.write ''
403
- end
444
+ self.git.fs_write('objects/info/alternates', '')
404
445
  else
405
- File.open(File.join(self.path, *%w{objects info alternates}), 'w') do |f|
406
- f.write alts.join("\n")
407
- end
446
+ self.git.fs_write('objects/info/alternates', alts.join("\n"))
408
447
  end
409
448
  end
410
-
449
+
411
450
  def config
412
451
  @config ||= Config.new(self)
413
452
  end
414
-
453
+
415
454
  def index
416
455
  Index.new(self)
417
456
  end
418
-
457
+
419
458
  def update_ref(head, commit_sha)
420
459
  return nil if !commit_sha || (commit_sha.size != 40)
421
-
422
- ref_heads = File.join(self.path, 'refs', 'heads')
423
- FileUtils.mkdir_p(ref_heads)
424
- File.open(File.join(ref_heads, head), 'w') do |f|
425
- f.write(commit_sha)
426
- end
460
+ self.git.fs_write("refs/heads/#{head}", commit_sha)
427
461
  commit_sha
462
+ end
428
463
 
464
+ # Rename the current repository directory.
465
+ # +name+ is the new name
466
+ #
467
+ # Returns nothing
468
+ def rename(name)
469
+ if @bare
470
+ self.git.fs_move('/', "../#{name}")
471
+ else
472
+ self.git.fs_move('/', "../../#{name}")
473
+ end
429
474
  end
430
-
475
+
431
476
  # Pretty object inspection
432
477
  def inspect
433
478
  %Q{#<Grit::Repo "#{@path}">}
434
479
  end
435
480
  end # Repo
436
-
481
+
437
482
  end # Grit
@@ -1,4 +1,4 @@
1
- class String
1
+ class String
2
2
  if ((defined? RUBY_VERSION) && (RUBY_VERSION[0..2] == "1.9"))
3
3
  def getord(offset); self[offset].ord; end
4
4
  else
@@ -1,20 +1,20 @@
1
1
  module Grit
2
-
2
+
3
3
  class Status
4
4
  include Enumerable
5
-
5
+
6
6
  @base = nil
7
7
  @files = nil
8
-
8
+
9
9
  def initialize(base)
10
10
  @base = base
11
11
  construct_status
12
12
  end
13
-
13
+
14
14
  def changed
15
15
  @files.select { |k, f| f.type == 'M' }
16
16
  end
17
-
17
+
18
18
  def added
19
19
  @files.select { |k, f| f.type == 'A' }
20
20
  end
@@ -22,11 +22,11 @@ module Grit
22
22
  def deleted
23
23
  @files.select { |k, f| f.type == 'D' }
24
24
  end
25
-
25
+
26
26
  def untracked
27
27
  @files.select { |k, f| f.untracked }
28
28
  end
29
-
29
+
30
30
  def pretty
31
31
  out = ''
32
32
  self.each do |file|
@@ -41,26 +41,26 @@ module Grit
41
41
  out << "\n"
42
42
  out
43
43
  end
44
-
44
+
45
45
  # enumerable method
46
-
46
+
47
47
  def [](file)
48
48
  @files[file]
49
49
  end
50
-
50
+
51
51
  def each
52
52
  @files.each do |k, file|
53
53
  yield file
54
54
  end
55
55
  end
56
-
56
+
57
57
  class StatusFile
58
58
  attr_accessor :path, :type, :stage, :untracked
59
59
  attr_accessor :mode_index, :mode_repo
60
60
  attr_accessor :sha_index, :sha_repo
61
-
61
+
62
62
  @base = nil
63
-
63
+
64
64
  def initialize(base, hash)
65
65
  @base = base
66
66
  @path = hash[:path]
@@ -72,7 +72,7 @@ module Grit
72
72
  @sha_repo = hash[:sha_repo]
73
73
  @untracked = hash[:untracked]
74
74
  end
75
-
75
+
76
76
  def blob(type = :index)
77
77
  if type == :repo
78
78
  @base.object(@sha_repo)
@@ -80,15 +80,15 @@ module Grit
80
80
  @base.object(@sha_index) rescue @base.object(@sha_repo)
81
81
  end
82
82
  end
83
-
83
+
84
84
  end
85
-
85
+
86
86
  private
87
-
87
+
88
88
  def construct_status
89
89
  @files = ls_files
90
-
91
- Dir.chdir(@base.working_dir) do
90
+
91
+ Dir.chdir(@base.working_dir) do
92
92
  # find untracked in working dir
93
93
  Dir.glob('**/*') do |file|
94
94
  if !@files[file]
@@ -100,12 +100,12 @@ module Grit
100
100
  diff_files.each do |path, data|
101
101
  @files[path] ? @files[path].merge!(data) : @files[path] = data
102
102
  end
103
-
103
+
104
104
  # find added but not committed - new files
105
105
  diff_index('HEAD').each do |path, data|
106
106
  @files[path] ? @files[path].merge!(data) : @files[path] = data
107
107
  end
108
-
108
+
109
109
  @files.each do |k, file_hash|
110
110
  @files[k] = StatusFile.new(@base, file_hash)
111
111
  end
@@ -118,7 +118,7 @@ module Grit
118
118
  @base.git.diff_files.split("\n").each do |line|
119
119
  (info, file) = line.split("\t")
120
120
  (mode_src, mode_dest, sha_src, sha_dest, type) = info.split
121
- hsh[file] = {:path => file, :mode_file => mode_src.to_s[1, 7], :mode_index => mode_dest,
121
+ hsh[file] = {:path => file, :mode_file => mode_src.to_s[1, 7], :mode_index => mode_dest,
122
122
  :sha_file => sha_src, :sha_index => sha_dest, :type => type}
123
123
  end
124
124
  hsh
@@ -130,7 +130,7 @@ module Grit
130
130
  @base.git.diff_index({}, treeish).split("\n").each do |line|
131
131
  (info, file) = line.split("\t")
132
132
  (mode_src, mode_dest, sha_src, sha_dest, type) = info.split
133
- hsh[file] = {:path => file, :mode_repo => mode_src.to_s[1, 7], :mode_index => mode_dest,
133
+ hsh[file] = {:path => file, :mode_repo => mode_src.to_s[1, 7], :mode_index => mode_dest,
134
134
  :sha_repo => sha_src, :sha_index => sha_dest, :type => type}
135
135
  end
136
136
  hsh
@@ -147,5 +147,5 @@ module Grit
147
147
  hsh
148
148
  end
149
149
  end
150
-
150
+
151
151
  end