schacon-grit 0.9.4 → 1.1.1

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.
data/lib/grit/index.rb CHANGED
@@ -29,12 +29,20 @@ module Grit
29
29
  current[filename] = data
30
30
  end
31
31
 
32
+ # Sets the current tree
33
+ # +tree+ the branch/tag/sha... to use - a string
34
+ #
35
+ # Returns index (self)
32
36
  def read_tree(tree)
33
37
  self.current_tree = self.repo.tree(tree)
34
38
  end
35
39
 
36
40
  # Commit the contents of the index
37
- # +message+ is the commit message
41
+ # +message+ is the commit message [nil]
42
+ # +parents+ is one or more commits to attach this commit to to form a new head [nil]
43
+ # +actor+ is the details of the user making the commit [nil]
44
+ # +last_tree+ is a tree to compare with - to avoid making empty commits [nil]
45
+ # +head+ is the branch to write this head to [master]
38
46
  #
39
47
  # Returns a String of the SHA1 of the commit
40
48
  def commit(message, parents = nil, actor = nil, last_tree = nil, head = 'master')
@@ -62,16 +70,9 @@ module Grit
62
70
  contents << ''
63
71
  contents << message
64
72
 
65
- commit_sha1 = self.repo.git.ruby_git.put_raw_object(contents.join("\n"), 'commit')
66
-
67
- # self.repo.git.update_ref({}, 'HEAD', commit_sha1)
68
- ref_heads = File.join(self.repo.path, 'refs', 'heads')
69
- FileUtils.mkdir_p(ref_heads)
70
- File.open(File.join(ref_heads, head), 'w') do |f|
71
- f.write(commit_sha1)
72
- end if commit_sha1
73
+ commit_sha1 = self.repo.git.put_raw_object(contents.join("\n"), 'commit')
73
74
 
74
- commit_sha1
75
+ self.repo.update_ref(head, commit_sha1)
75
76
  end
76
77
 
77
78
  # Recursively write a tree to the index
@@ -92,12 +93,12 @@ module Grit
92
93
  # overwrite with new tree contents
93
94
  tree.each do |k, v|
94
95
  case v
95
- when String:
96
+ when String
96
97
  sha = write_blob(v)
97
98
  sha = [sha].pack("H*")
98
99
  str = "%s %s\0%s" % ['100644', k, sha]
99
100
  tree_contents[k] = str
100
- when Hash:
101
+ when Hash
101
102
  ctree = now_tree/k if now_tree
102
103
  sha = write_tree(v, ctree)
103
104
  sha = [sha].pack("H*")
@@ -106,7 +107,7 @@ module Grit
106
107
  end
107
108
  end
108
109
  tr = tree_contents.sort.map { |k, v| v }.join('')
109
- self.repo.git.ruby_git.put_raw_object(tr, 'tree')
110
+ self.repo.git.put_raw_object(tr, 'tree')
110
111
  end
111
112
 
112
113
  # Write the blob to the index
@@ -114,7 +115,7 @@ module Grit
114
115
  #
115
116
  # Returns the SHA1 String of the blob
116
117
  def write_blob(data)
117
- self.repo.git.ruby_git.put_raw_object(data, 'blob')
118
+ self.repo.git.put_raw_object(data, 'blob')
118
119
  end
119
120
  end # Index
120
121
 
data/lib/grit/merge.rb ADDED
@@ -0,0 +1,45 @@
1
+ module Grit
2
+
3
+ class Merge
4
+
5
+ STATUS_BOTH = 'both'
6
+ STATUS_OURS = 'ours'
7
+ STATUS_THEIRS = 'theirs'
8
+
9
+ attr_reader :conflicts, :text, :sections
10
+
11
+ def initialize(str)
12
+ status = STATUS_BOTH
13
+
14
+ section = 1
15
+ @conflicts = 0
16
+ @text = {}
17
+
18
+ lines = str.split("\n")
19
+ lines.each do |line|
20
+ if /^<<<<<<< (.*?)/.match(line)
21
+ status = STATUS_OURS
22
+ @conflicts += 1
23
+ section += 1
24
+ elsif line == '======='
25
+ status = STATUS_THEIRS
26
+ elsif /^>>>>>>> (.*?)/.match(line)
27
+ status = STATUS_BOTH
28
+ section += 1
29
+ else
30
+ @text[section] ||= {}
31
+ @text[section][status] ||= []
32
+ @text[section][status] << line
33
+ end
34
+ end
35
+ @text = @text.values
36
+ @sections = @text.size
37
+ end
38
+
39
+ # Pretty object inspection
40
+ def inspect
41
+ %Q{#<Grit::Merge}
42
+ end
43
+ end # Merge
44
+
45
+ end # Grit
data/lib/grit/ref.rb CHANGED
@@ -9,32 +9,13 @@ module Grit
9
9
  # +options+ is a Hash of options
10
10
  #
11
11
  # Returns Grit::Ref[] (baked)
12
- def find_all(repo, options = {})
13
- refs = []
14
-
15
- Dir.chdir(repo.path) do
16
- if File.file?('packed-refs')
17
- File.readlines('packed-refs').each do |line|
18
- if m = /^(\w{40}) (.*?)$/.match(line)
19
- next if !Regexp.new('^' + prefix).match(m[2])
20
- name = m[2].sub("#{prefix}/", '')
21
- commit = Commit.create(repo, :id => m[1])
22
- refs << self.new(name, commit)
23
- end
24
- end
25
- end
26
-
27
- files = Dir.glob(prefix + '/**/*')
28
- files.each do |ref|
29
- next if !File.file?(ref)
30
- id = File.read(ref).chomp
31
- name = ref.sub("#{prefix}/", '')
32
- commit = Commit.create(repo, :id => id)
33
- refs << self.new(name, commit)
34
- end
12
+ def find_all(repo, options = {})
13
+ refs = repo.git.refs(options, prefix)
14
+ refs.split("\n").map do |ref|
15
+ name, id = *ref.split(' ')
16
+ commit = Commit.create(repo, :id => id)
17
+ self.new(name, commit)
35
18
  end
36
-
37
- refs
38
19
  end
39
20
 
40
21
  protected
@@ -80,7 +61,7 @@ module Grit
80
61
  #
81
62
  # Returns Grit::Head (baked)
82
63
  def self.current(repo, options = {})
83
- head = File.open(File.join(repo.path, 'HEAD')).read.chomp
64
+ head = repo.git.fs_read('HEAD').chomp
84
65
  if /ref: refs\/heads\/(.*)/.match(head)
85
66
  self.new($1, repo.git.rev_parse(options, 'HEAD'))
86
67
  end
@@ -88,8 +69,6 @@ module Grit
88
69
 
89
70
  end # Head
90
71
 
91
- class Tag < Ref ; end
92
-
93
72
  class Remote < Ref; end
94
-
73
+
95
74
  end # Grit
data/lib/grit/repo.rb CHANGED
@@ -13,6 +13,7 @@ module Grit
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
+ # +options+ :is_bare force to load a bare repo
16
17
  #
17
18
  # Examples
18
19
  # g = Repo.new("/Users/tom/dev/grit")
@@ -37,7 +38,8 @@ module Grit
37
38
 
38
39
  self.git = Git.new(self.path)
39
40
  end
40
-
41
+
42
+ # Does nothing yet...
41
43
  def self.init(path)
42
44
  # !! TODO !!
43
45
  # create directory
@@ -49,8 +51,13 @@ module Grit
49
51
  #
50
52
  # Returns String
51
53
  def description
52
- File.open(File.join(self.path, 'description')).read.chomp
54
+ self.git.fs_read('description').chomp
55
+ end
56
+
57
+ def blame(file, commit = nil)
58
+ Blame.new(self, file, commit)
53
59
  end
60
+
54
61
 
55
62
  # An array of Head objects representing the branch heads in
56
63
  # this repo
@@ -62,10 +69,14 @@ module Grit
62
69
 
63
70
  alias_method :branches, :heads
64
71
 
65
- def is_head?(head_name)
72
+ def get_head(head_name)
66
73
  heads.find { |h| h.name == head_name }
67
74
  end
68
75
 
76
+ def is_head?(head_name)
77
+ get_head(head_name)
78
+ end
79
+
69
80
  # Object reprsenting the current repo head.
70
81
  #
71
82
  # Returns Grit::Head (baked)
@@ -93,7 +104,7 @@ module Grit
93
104
  self.git.add({}, *files.flatten)
94
105
  end
95
106
 
96
- # Adds files to the index
107
+ # Remove files from the index
97
108
  def remove(*files)
98
109
  self.git.rm({}, *files.flatten)
99
110
  end
@@ -128,6 +139,34 @@ module Grit
128
139
  def remotes
129
140
  Remote.find_all(self)
130
141
  end
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
+
131
170
 
132
171
  # An array of Ref objects representing the refs in
133
172
  # this repo
@@ -198,6 +237,53 @@ module Grit
198
237
  Commit.find_all(self, id, options).first
199
238
  end
200
239
 
240
+ # Returns a list of commits that is in +other_repo+ but not in self
241
+ #
242
+ # Returns Grit::Commit[]
243
+ def commit_deltas_from(other_repo, ref = "master", other_ref = "master")
244
+ # TODO: we should be able to figure out the branch point, rather than
245
+ # rev-list'ing the whole thing
246
+ repo_refs = self.git.rev_list({}, ref).strip.split("\n")
247
+ other_repo_refs = other_repo.git.rev_list({}, other_ref).strip.split("\n")
248
+
249
+ (other_repo_refs - repo_refs).map do |ref|
250
+ Commit.find_all(other_repo, ref, {:max_count => 1}).first
251
+ end
252
+ end
253
+
254
+ def objects(refs)
255
+ Grit.no_quote = true
256
+ obj = self.git.rev_list({:objects => true}, refs).split("\n").map { |a| a[0, 40] }
257
+ Grit.no_quote = false
258
+ obj
259
+ end
260
+
261
+ def objects_between(ref1, ref2 = nil)
262
+ if ref2
263
+ refs = "#{ref2}..#{ref1}"
264
+ else
265
+ refs = ref1
266
+ end
267
+ self.objects(refs)
268
+ end
269
+
270
+ def diff_objects(commit_sha, parents = true)
271
+ revs = []
272
+ Grit.no_quote = true
273
+ if parents
274
+ # PARENTS:
275
+ cmd = "-r -t -m #{commit_sha}"
276
+ revs = self.git.diff_tree({}, cmd).strip.split("\n").map{ |a| r = a.split(' '); r[3] if r[1] != '160000' }
277
+ else
278
+ # NO PARENTS:
279
+ cmd = "-r -t #{commit_sha}"
280
+ revs = self.git.method_missing('ls-tree', {}, "-r -t #{commit_sha}").split("\n").map{ |a| a.split("\t").first.split(' ')[2] }
281
+ end
282
+ revs << self.commit(commit_sha).tree.id
283
+ Grit.no_quote = false
284
+ return revs.uniq.compact
285
+ end
286
+
201
287
  # The Tree object for the given treeish reference
202
288
  # +treeish+ is the reference (default 'master')
203
289
  # +paths+ is an optional Array of directory paths to restrict the tree (deafult [])
@@ -255,20 +341,31 @@ module Grit
255
341
  # Returns Grit::Repo (the newly created repo)
256
342
  def self.init_bare(path, git_options = {}, repo_options = {})
257
343
  git = Git.new(path)
344
+ git.fs_mkdir('..')
258
345
  git.init(git_options)
259
346
  self.new(path, repo_options)
260
347
  end
348
+
349
+ def self.init_bare_or_open(path, git_options = {}, repo_options = {})
350
+ git = Git.new(path)
351
+ if !git.exist?
352
+ git.fs_mkdir(path)
353
+ git.init(git_options)
354
+ end
355
+ self.new(path, repo_options)
356
+ end
261
357
 
262
358
  # Fork a bare git repository from this repo
263
359
  # +path+ is the full path of the new repo (traditionally ends with /<name>.git)
264
- # +options+ is any additional options to the git clone command
360
+ # +options+ is any additional options to the git clone command (:bare and :shared are true by default)
265
361
  #
266
362
  # Returns Grit::Repo (the newly forked repo)
267
363
  def fork_bare(path, options = {})
268
364
  default_options = {:bare => true, :shared => true}
269
365
  real_options = default_options.merge(options)
366
+ Git.new(path).fs_mkdir('..')
270
367
  self.git.clone(real_options, self.path, path)
271
- Repo.new(path)
368
+ self.new(path)
272
369
  end
273
370
 
274
371
  # Archive the given treeish
@@ -310,23 +407,30 @@ module Grit
310
407
  def archive_tar_gz(treeish = 'master', prefix = nil)
311
408
  options = {}
312
409
  options[:prefix] = prefix if prefix
313
- self.git.archive(options, treeish, "| gzip")
410
+ self.git.archive(options, treeish, "| gzip -n")
314
411
  end
315
412
 
316
- # run archive directly to a file
317
- def archive_to_file(treeish = 'master', prefix = nil, filename = 'archive.tar.gz')
413
+ # Write an archive directly to a file
414
+ # +treeish+ is the treeish name/id (default 'master')
415
+ # +prefix+ is the optional prefix (default nil)
416
+ # +filename+ is the name of the file (default 'archive.tar.gz')
417
+ # +format+ is the optional format (default nil)
418
+ # +pipe+ is the command to run the output through (default 'gzip')
419
+ #
420
+ # Returns nothing
421
+ def archive_to_file(treeish = 'master', prefix = nil, filename = 'archive.tar.gz', format = nil, pipe = "gzip")
318
422
  options = {}
319
423
  options[:prefix] = prefix if prefix
320
- self.git.archive(options, treeish, "| gzip > #{filename}")
424
+ options[:format] = format if format
425
+ self.git.archive(options, treeish, "| #{pipe} > #{filename}")
321
426
  end
322
427
 
323
-
324
428
  # Enable git-daemon serving of this repository by writing the
325
429
  # git-daemon-export-ok file to its git directory
326
430
  #
327
431
  # Returns nothing
328
432
  def enable_daemon_serve
329
- FileUtils.touch(File.join(self.path, DAEMON_EXPORT_FILE))
433
+ self.git.fs_write(DAEMON_EXPORT_FILE, '')
330
434
  end
331
435
 
332
436
  # Disable git-daemon serving of this repository by ensuring there is no
@@ -334,17 +438,20 @@ module Grit
334
438
  #
335
439
  # Returns nothing
336
440
  def disable_daemon_serve
337
- FileUtils.rm_f(File.join(self.path, DAEMON_EXPORT_FILE))
441
+ self.git.fs_delete(DAEMON_EXPORT_FILE)
442
+ end
443
+
444
+ def gc_auto
445
+ self.git.gc({:auto => true})
338
446
  end
339
447
 
340
448
  # The list of alternates for this repo
341
449
  #
342
450
  # Returns Array[String] (pathnames of alternates)
343
451
  def alternates
344
- alternates_path = File.join(self.path, *%w{objects info alternates})
345
-
346
- if File.exist?(alternates_path)
347
- File.read(alternates_path).strip.split("\n")
452
+ alternates_path = "objects/info/alternates"
453
+ if self.git.fs_exist?(alternates_path)
454
+ self.git.fs_read(alternates_path).strip.split("\n")
348
455
  else
349
456
  []
350
457
  end
@@ -362,11 +469,9 @@ module Grit
362
469
  end
363
470
 
364
471
  if alts.empty?
365
- File.delete(File.join(self.path, *%w{objects info alternates}))
472
+ self.git.fs_write('objects/info/alternates', '')
366
473
  else
367
- File.open(File.join(self.path, *%w{objects info alternates}), 'w') do |f|
368
- f.write alts.join("\n")
369
- end
474
+ self.git.fs_write('objects/info/alternates', alts.join("\n"))
370
475
  end
371
476
  end
372
477
 
@@ -378,6 +483,24 @@ module Grit
378
483
  Index.new(self)
379
484
  end
380
485
 
486
+ def update_ref(head, commit_sha)
487
+ return nil if !commit_sha || (commit_sha.size != 40)
488
+ self.git.fs_write("refs/heads/#{head}", commit_sha)
489
+ commit_sha
490
+ end
491
+
492
+ # Rename the current repository directory.
493
+ # +name+ is the new name
494
+ #
495
+ # Returns nothing
496
+ def rename(name)
497
+ if @bare
498
+ self.git.fs_move('/', "../#{name}")
499
+ else
500
+ self.git.fs_move('/', "../../#{name}")
501
+ end
502
+ end
503
+
381
504
  # Pretty object inspection
382
505
  def inspect
383
506
  %Q{#<Grit::Repo "#{@path}">}