boof-grit 1.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. data/API.txt +101 -0
  2. data/History.txt +53 -0
  3. data/LICENSE +22 -0
  4. data/README.md +210 -0
  5. data/VERSION.yml +4 -0
  6. data/examples/ex_add_commit.rb +13 -0
  7. data/examples/ex_index.rb +14 -0
  8. data/lib/grit.rb +68 -0
  9. data/lib/grit/actor.rb +36 -0
  10. data/lib/grit/blame.rb +61 -0
  11. data/lib/grit/blob.rb +126 -0
  12. data/lib/grit/commit.rb +246 -0
  13. data/lib/grit/commit_stats.rb +128 -0
  14. data/lib/grit/config.rb +44 -0
  15. data/lib/grit/diff.rb +70 -0
  16. data/lib/grit/errors.rb +7 -0
  17. data/lib/grit/git-ruby.rb +186 -0
  18. data/lib/grit/git-ruby/commit_db.rb +52 -0
  19. data/lib/grit/git-ruby/file_index.rb +193 -0
  20. data/lib/grit/git-ruby/git_object.rb +350 -0
  21. data/lib/grit/git-ruby/internal/file_window.rb +58 -0
  22. data/lib/grit/git-ruby/internal/loose.rb +137 -0
  23. data/lib/grit/git-ruby/internal/pack.rb +382 -0
  24. data/lib/grit/git-ruby/internal/raw_object.rb +37 -0
  25. data/lib/grit/git-ruby/object.rb +325 -0
  26. data/lib/grit/git-ruby/repository.rb +740 -0
  27. data/lib/grit/git.rb +141 -0
  28. data/lib/grit/index.rb +122 -0
  29. data/lib/grit/lazy.rb +33 -0
  30. data/lib/grit/merge.rb +45 -0
  31. data/lib/grit/ref.rb +177 -0
  32. data/lib/grit/repo.rb +452 -0
  33. data/lib/grit/ruby1.9.rb +7 -0
  34. data/lib/grit/status.rb +151 -0
  35. data/lib/grit/submodule.rb +88 -0
  36. data/lib/grit/tag.rb +66 -0
  37. data/lib/grit/tree.rb +123 -0
  38. data/lib/open3_detach.rb +46 -0
  39. data/test/bench/benchmarks.rb +126 -0
  40. data/test/helper.rb +18 -0
  41. data/test/profile.rb +21 -0
  42. data/test/suite.rb +6 -0
  43. data/test/test_actor.rb +35 -0
  44. data/test/test_blame.rb +32 -0
  45. data/test/test_blame_tree.rb +33 -0
  46. data/test/test_blob.rb +83 -0
  47. data/test/test_commit.rb +207 -0
  48. data/test/test_commit_stats.rb +33 -0
  49. data/test/test_commit_write.rb +20 -0
  50. data/test/test_config.rb +58 -0
  51. data/test/test_diff.rb +18 -0
  52. data/test/test_file_index.rb +56 -0
  53. data/test/test_git.rb +94 -0
  54. data/test/test_grit.rb +32 -0
  55. data/test/test_head.rb +72 -0
  56. data/test/test_index_status.rb +40 -0
  57. data/test/test_merge.rb +17 -0
  58. data/test/test_raw.rb +16 -0
  59. data/test/test_real.rb +19 -0
  60. data/test/test_reality.rb +17 -0
  61. data/test/test_remote.rb +14 -0
  62. data/test/test_repo.rb +381 -0
  63. data/test/test_rubygit.rb +192 -0
  64. data/test/test_rubygit_alt.rb +40 -0
  65. data/test/test_rubygit_index.rb +76 -0
  66. data/test/test_rubygit_iv2.rb +28 -0
  67. data/test/test_submodule.rb +69 -0
  68. data/test/test_tag.rb +103 -0
  69. data/test/test_tree.rb +101 -0
  70. metadata +143 -0
data/lib/grit/repo.rb ADDED
@@ -0,0 +1,452 @@
1
+ module Grit
2
+
3
+ class Repo
4
+ DAEMON_EXPORT_FILE = 'git-daemon-export-ok'
5
+
6
+ # The path of the git repo as a String
7
+ attr_accessor :path
8
+ attr_accessor :working_dir
9
+ attr_reader :bare
10
+
11
+ # The git command line interface object
12
+ attr_accessor :git
13
+
14
+ def initialize(work_tree, git_dir, options)
15
+ @bare = work_tree == git_dir
16
+ @working_dir, @path = work_tree, git_dir
17
+ @git = Git.new @path, @working_dir
18
+
19
+ if options[:init]
20
+ Dir.mkdir @working_dir unless File.exist? @working_dir
21
+ # this could possibly more simple if mocha wouldn't mess with...
22
+ git.run '', :init, '', {}, [] unless File.exist? @path
23
+ else
24
+ raise NoSuchPathError unless File.exist? @working_dir
25
+ raise InvalidGitRepositoryError unless File.exist? @path
26
+ end
27
+ end
28
+
29
+ # Creates new repository if it does not exist and returns it.
30
+ def self.init(path, options = {})
31
+ new path, options.merge(:init => true)
32
+ end
33
+ # Create a new Repo instance
34
+ # +path+ is the path to either the root git directory or the bare git repo
35
+ # +options+ :is_bare force to load a bare repo
36
+ #
37
+ # Examples
38
+ # g = Repo.new("/Users/tom/dev/grit")
39
+ # g = Repo.new("/Users/tom/public/grit.git")
40
+ #
41
+ # Returns Grit::Repo
42
+ def self.new(path, options = {})
43
+ work_tree = File.expand_path path
44
+ git_dir = if options[:is_bare] or work_tree[/\.git$/]
45
+ work_tree
46
+ else
47
+ File.join work_tree, '.git'
48
+ end
49
+
50
+ super work_tree, git_dir, options
51
+ end
52
+
53
+ # The project's description. Taken verbatim from GIT_REPO/description
54
+ #
55
+ # Returns String
56
+ def description
57
+ File.open(File.join(self.path, 'description')).read.chomp
58
+ end
59
+
60
+ def blame(file, commit = nil)
61
+ Blame.new(self, file, commit)
62
+ end
63
+
64
+
65
+ # Create tag with <tt>name</tt> from <tt>startpoint</tt> if it does not
66
+ # exist. The default <tt>startpoint</tt> is the current HEAD.
67
+ def add_tag(name, startpoint = nil)
68
+ Tag.create self, name, startpoint
69
+ end
70
+ # Returns branch with <tt>name</tt>. This will be created if it does not
71
+ # exist. The default <tt>startpoint</tt> is the current HEAD.
72
+ def branch(name, startpoint = nil)
73
+ head = get_head(name) || Head.create(self, name, startpoint)
74
+ end
75
+
76
+ # An array of Head objects representing the branch heads in
77
+ # this repo
78
+ #
79
+ # Returns array of Grit::Head[] (baked)
80
+ def heads
81
+ Head.find_all(self)
82
+ end
83
+ alias_method :branches, :heads
84
+
85
+ # Searches heads for <tt>head_name</tt> and returns the result.
86
+ def get_head(head_name)
87
+ heads.find { |h| h.name == head_name }
88
+ end
89
+
90
+ # Check if head with <tt>head_name</tt> exists.
91
+ def is_head?(head_name)
92
+ get_head(head_name)
93
+ end
94
+
95
+ # Object reprsenting the current repo head.
96
+ #
97
+ # Returns Grit::Head (baked)
98
+ def head
99
+ Head.current(self)
100
+ end
101
+
102
+
103
+ # Commits current index
104
+ #
105
+ # Returns true/false if commit worked
106
+ def commit_index(message)
107
+ self.git.commit({}, '-m', message)
108
+ end
109
+
110
+ # Commits all tracked and modified files
111
+ #
112
+ # Returns true/false if commit worked
113
+ def commit_all(message)
114
+ self.git.commit({}, '-a', '-m', message)
115
+ end
116
+
117
+ # Adds files to the index
118
+ def add(*files)
119
+ self.git.add({}, *files.flatten)
120
+ end
121
+
122
+ # Remove files from the index
123
+ def remove(*files)
124
+ self.git.rm({}, *files.flatten)
125
+ end
126
+
127
+
128
+ def blame_tree(commit, path = nil)
129
+ commit_array = self.git.blame_tree(commit, path)
130
+
131
+ final_array = {}
132
+ commit_array.each do |file, sha|
133
+ final_array[file] = commit(sha)
134
+ end
135
+ final_array
136
+ end
137
+
138
+ def status
139
+ Status.new(self)
140
+ end
141
+
142
+
143
+ # An array of Tag objects that are available in this repo
144
+ #
145
+ # Returns Grit::Tag[] (baked)
146
+ def tags
147
+ Tag.find_all(self)
148
+ end
149
+
150
+ # An array of Remote objects representing the remote branches in
151
+ # this repo
152
+ #
153
+ # Returns Grit::Remote[] (baked)
154
+ def remotes
155
+ Remote.find_all(self)
156
+ end
157
+
158
+ # An array of Ref objects representing the refs in
159
+ # this repo
160
+ #
161
+ # Returns Grit::Ref[] (baked)
162
+ def refs
163
+ [ Head.find_all(self), Tag.find_all(self), Remote.find_all(self) ].flatten
164
+ end
165
+
166
+ def commit_stats(start = 'master', max_count = 10, skip = 0)
167
+ options = {:max_count => max_count,
168
+ :skip => skip}
169
+
170
+ CommitStats.find_all(self, start, options)
171
+ end
172
+
173
+ # An array of Commit objects representing the history of a given ref/commit
174
+ # +start+ is the branch/commit name (default 'master')
175
+ # +max_count+ is the maximum number of commits to return (default 10, use +false+ for all)
176
+ # +skip+ is the number of commits to skip (default 0)
177
+ #
178
+ # Returns Grit::Commit[] (baked)
179
+ def commits(start = 'master', max_count = 10, skip = 0)
180
+ options = {:max_count => max_count,
181
+ :skip => skip}
182
+
183
+ Commit.find_all(self, start, options)
184
+ end
185
+
186
+ # The Commits objects that are reachable via +to+ but not via +from+
187
+ # Commits are returned in chronological order.
188
+ # +from+ is the branch/commit name of the younger item
189
+ # +to+ is the branch/commit name of the older item
190
+ #
191
+ # Returns Grit::Commit[] (baked)
192
+ def commits_between(from, to)
193
+ Commit.find_all(self, "#{from}..#{to}").reverse
194
+ end
195
+
196
+ # The Commits objects that are newer than the specified date.
197
+ # Commits are returned in chronological order.
198
+ # +start+ is the branch/commit name (default 'master')
199
+ # +since+ is a string represeting a date/time
200
+ # +extra_options+ is a hash of extra options
201
+ #
202
+ # Returns Grit::Commit[] (baked)
203
+ def commits_since(start = 'master', since = '1970-01-01', extra_options = {})
204
+ options = {:since => since}.merge(extra_options)
205
+
206
+ Commit.find_all(self, start, options)
207
+ end
208
+
209
+ # The number of commits reachable by the given branch/commit
210
+ # +start+ is the branch/commit name (default 'master')
211
+ #
212
+ # Returns Integer
213
+ def commit_count(start = 'master')
214
+ Commit.count(self, start)
215
+ end
216
+
217
+ # The Commit object for the specified id
218
+ # +id+ is the SHA1 identifier of the commit
219
+ #
220
+ # Returns Grit::Commit (baked)
221
+ def commit(id)
222
+ options = {:max_count => 1}
223
+
224
+ Commit.find_all(self, id, options).first
225
+ end
226
+
227
+ # Returns a list of commits that is in +other_repo+ but not in self
228
+ #
229
+ # Returns Grit::Commit[]
230
+ def commit_deltas_from(other_repo, ref = "master", other_ref = "master")
231
+ # TODO: we should be able to figure out the branch point, rather than
232
+ # rev-list'ing the whole thing
233
+ repo_refs = self.git.rev_list({}, ref).strip.split("\n")
234
+ other_repo_refs = other_repo.git.rev_list({}, other_ref).strip.split("\n")
235
+
236
+ (other_repo_refs - repo_refs).map do |ref|
237
+ Commit.find_all(other_repo, ref, {:max_count => 1}).first
238
+ end
239
+ end
240
+
241
+ # The Tree object for the given treeish reference
242
+ # +treeish+ is the reference (default 'master')
243
+ # +paths+ is an optional Array of directory paths to restrict the tree (deafult [])
244
+ #
245
+ # Examples
246
+ # repo.tree('master', ['lib/'])
247
+ #
248
+ # Returns Grit::Tree (baked)
249
+ def tree(treeish = 'master', paths = [])
250
+ Tree.construct(self, treeish, paths)
251
+ end
252
+
253
+ # The Blob object for the given id
254
+ # +id+ is the SHA1 id of the blob
255
+ #
256
+ # Returns Grit::Blob (unbaked)
257
+ def blob(id)
258
+ Blob.create(self, :id => id)
259
+ end
260
+
261
+ # The commit log for a treeish
262
+ #
263
+ # Returns Grit::Commit[]
264
+ def log(commit = 'master', path = nil, options = {})
265
+ default_options = {:pretty => "raw"}
266
+ actual_options = default_options.merge(options)
267
+ arg = path ? [commit, '--', path] : [commit]
268
+ commits = self.git.log(actual_options, *arg)
269
+ Commit.list_from_string(self, commits)
270
+ end
271
+
272
+ # The diff from commit +a+ to commit +b+, optionally restricted to the given file(s)
273
+ # +a+ is the base commit
274
+ # +b+ is the other commit
275
+ # +paths+ is an optional list of file paths on which to restrict the diff
276
+ def diff(a, b, *paths)
277
+ self.git.diff({}, a, b, '--', *paths)
278
+ end
279
+
280
+ # The commit diff for the given commit
281
+ # +commit+ is the commit name/id
282
+ #
283
+ # Returns Grit::Diff[]
284
+ def commit_diff(commit)
285
+ Commit.diff(self, commit)
286
+ end
287
+
288
+ # Initialize a bare git repository at the given path
289
+ # +path+ is the full path to the repo (traditionally ends with /<name>.git)
290
+ # +options+ is any additional options to the git init command
291
+ #
292
+ # Examples
293
+ # Grit::Repo.init_bare('/var/git/myrepo.git')
294
+ #
295
+ # Returns Grit::Repo (the newly created repo)
296
+ def self.init_bare(path, git_options = {}, repo_options = {})
297
+ git = Git.new(path)
298
+ git.init(git_options)
299
+ self.new(path, repo_options)
300
+ end
301
+
302
+ # Fork a bare git repository from this repo
303
+ # +path+ is the full path of the new repo (traditionally ends with /<name>.git)
304
+ # +options+ is any additional options to the git clone command (:bare and :shared are true by default)
305
+ #
306
+ # Returns Grit::Repo (the newly forked repo)
307
+ def fork_bare(path, options = {})
308
+ default_options = {:bare => true, :shared => true}
309
+ real_options = default_options.merge(options)
310
+ self.git.clone(real_options, self.path, path)
311
+ Repo.new(path)
312
+ end
313
+
314
+ # Archive the given treeish
315
+ # +treeish+ is the treeish name/id (default 'master')
316
+ # +prefix+ is the optional prefix
317
+ #
318
+ # Examples
319
+ # repo.archive_tar
320
+ # # => <String containing tar archive>
321
+ #
322
+ # repo.archive_tar('a87ff14')
323
+ # # => <String containing tar archive for commit a87ff14>
324
+ #
325
+ # repo.archive_tar('master', 'myproject/')
326
+ # # => <String containing tar archive and prefixed with 'myproject/'>
327
+ #
328
+ # Returns String (containing tar archive)
329
+ def archive_tar(treeish = 'master', prefix = nil)
330
+ options = {}
331
+ options[:prefix] = prefix if prefix
332
+ self.git.archive(options, treeish)
333
+ end
334
+
335
+ # Archive and gzip the given treeish
336
+ # +treeish+ is the treeish name/id (default 'master')
337
+ # +prefix+ is the optional prefix
338
+ #
339
+ # Examples
340
+ # repo.archive_tar_gz
341
+ # # => <String containing tar.gz archive>
342
+ #
343
+ # repo.archive_tar_gz('a87ff14')
344
+ # # => <String containing tar.gz archive for commit a87ff14>
345
+ #
346
+ # repo.archive_tar_gz('master', 'myproject/')
347
+ # # => <String containing tar.gz archive and prefixed with 'myproject/'>
348
+ #
349
+ # Returns String (containing tar.gz archive)
350
+ def archive_tar_gz(treeish = 'master', prefix = nil)
351
+ options = {}
352
+ options[:prefix] = prefix if prefix
353
+ self.git.archive(options, treeish, "| gzip")
354
+ end
355
+
356
+ # Write an archive directly to a file
357
+ # +treeish+ is the treeish name/id (default 'master')
358
+ # +prefix+ is the optional prefix (default nil)
359
+ # +filename+ is the name of the file (default 'archive.tar.gz')
360
+ # +format+ is the optional format (default nil)
361
+ # +pipe+ is the command to run the output through (default 'gzip')
362
+ #
363
+ # Returns nothing
364
+ def archive_to_file(treeish = 'master', prefix = nil, filename = 'archive.tar.gz', format = nil, pipe = "gzip")
365
+ options = {}
366
+ options[:prefix] = prefix if prefix
367
+ options[:format] = format if format
368
+ self.git.archive(options, treeish, "| #{pipe} > #{filename}")
369
+ end
370
+
371
+ # Enable git-daemon serving of this repository by writing the
372
+ # git-daemon-export-ok file to its git directory
373
+ #
374
+ # Returns nothing
375
+ def enable_daemon_serve
376
+ FileUtils.touch(File.join(self.path, DAEMON_EXPORT_FILE))
377
+ end
378
+
379
+ # Disable git-daemon serving of this repository by ensuring there is no
380
+ # git-daemon-export-ok file in its git directory
381
+ #
382
+ # Returns nothing
383
+ def disable_daemon_serve
384
+ FileUtils.rm_f(File.join(self.path, DAEMON_EXPORT_FILE))
385
+ end
386
+
387
+ def gc_auto
388
+ self.git.gc({:auto => true})
389
+ end
390
+
391
+ # The list of alternates for this repo
392
+ #
393
+ # Returns Array[String] (pathnames of alternates)
394
+ def alternates
395
+ alternates_path = File.join(self.path, *%w{objects info alternates})
396
+
397
+ if File.exist?(alternates_path)
398
+ File.read(alternates_path).strip.split("\n")
399
+ else
400
+ []
401
+ end
402
+ end
403
+
404
+ # Sets the alternates
405
+ # +alts+ is the Array of String paths representing the alternates
406
+ #
407
+ # Returns nothing
408
+ def alternates=(alts)
409
+ alts.each do |alt|
410
+ unless File.exist?(alt)
411
+ raise "Could not set alternates. Alternate path #{alt} must exist"
412
+ end
413
+ end
414
+
415
+ if alts.empty?
416
+ File.open(File.join(self.path, *%w{objects info alternates}), 'w') do |f|
417
+ f.write ''
418
+ end
419
+ else
420
+ File.open(File.join(self.path, *%w{objects info alternates}), 'w') do |f|
421
+ f.write alts.join("\n")
422
+ end
423
+ end
424
+ end
425
+
426
+ def config
427
+ @config ||= Config.new(self)
428
+ end
429
+
430
+ def index
431
+ Index.new(self)
432
+ end
433
+
434
+ def update_ref(head, commit_sha)
435
+ return nil if !commit_sha || (commit_sha.size != 40)
436
+
437
+ ref_heads = File.join(self.path, 'refs', 'heads')
438
+ FileUtils.mkdir_p(ref_heads)
439
+ File.open(File.join(ref_heads, head), 'w') do |f|
440
+ f.write(commit_sha)
441
+ end
442
+ commit_sha
443
+
444
+ end
445
+
446
+ # Pretty object inspection
447
+ def inspect
448
+ %Q{#<Grit::Repo "#{@path}">}
449
+ end
450
+ end # Repo
451
+
452
+ end # Grit
@@ -0,0 +1,7 @@
1
+ class String
2
+ if ((defined? RUBY_VERSION) && (RUBY_VERSION[0..2] == "1.9"))
3
+ def getord(offset); self[offset].ord; end
4
+ else
5
+ alias :getord :[]
6
+ end
7
+ end