boof-grit 1.1.2

Sign up to get free protection for your applications and to get access to all the features.
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