schacon-grit 0.9.4 → 1.1.1

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