Class: Grit::Repo

Inherits:
Object
  • Object
show all
Defined in:
lib/grit/repo.rb

Constant Summary collapse

DAEMON_EXPORT_FILE =
'git-daemon-export-ok'

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(path, options = {}) ⇒ Repo

Create a new Repo instance

+path+ is the path to either the root git directory or the bare git repo
+options+ :is_bare force to load a bare repo

Examples

g = Repo.new("/Users/tom/dev/grit")
g = Repo.new("/Users/tom/public/grit.git")

Returns Grit::Repo



30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# File 'lib/grit/repo.rb', line 30

def initialize(path, options = {})
  epath = File.expand_path(path)

  if File.exist?(File.join(epath, '.git'))
    self.working_dir = epath
    self.path = File.join(epath, '.git')
    @bare = false
  elsif File.exist?(epath) && (epath =~ /\.git$/ || options[:is_bare])
    self.path = epath
    @bare = true
  elsif File.exist?(epath)
    raise InvalidGitRepositoryError.new(epath)
  else
    raise NoSuchPathError.new(epath)
  end

  self.git = Git.new(self.path, self.working_dir)
end

Instance Attribute Details

#bareObject (readonly)

Returns the value of attribute bare.



16
17
18
# File 'lib/grit/repo.rb', line 16

def bare
  @bare
end

#gitObject

The git command line interface object



19
20
21
# File 'lib/grit/repo.rb', line 19

def git
  @git
end

#pathObject

The path of the git repo as a String



14
15
16
# File 'lib/grit/repo.rb', line 14

def path
  @path
end

#working_dirObject

Returns the value of attribute working_dir.



15
16
17
# File 'lib/grit/repo.rb', line 15

def working_dir
  @working_dir
end

Class Method Details

.clone(remote_repo, path, options = {}) ⇒ Object



67
68
69
70
71
72
73
74
75
76
# File 'lib/grit/repo.rb', line 67

def self.clone(remote_repo, path, options = {})
  if path =~ /\.git$/
    options[:bare] = true
  end

  git = Git.new(nil)
  git.clone(options, remote_repo, path)

  Repo.new(path)
end

.init(path, options = {}) ⇒ Object



49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/grit/repo.rb', line 49

def self.init(path, options = {})
  epath = File.expand_path(path)

  if epath =~ /\.git$/ || options[:is_bare]
    path = epath
    working_dir = nil
  else
    path = File.join(epath, '.git')
    working_dir = epath
  end

  git = Git.new(path, working_dir)

  git.init

  Repo.new(path)
end

.init_bare(path, git_options = {}, repo_options = {}) ⇒ Object

Initialize a bare git repository at the given path

+path+ is the full path to the repo (traditionally ends with /<name>.git)
+options+ is any additional options to the git init command

Examples

Grit::Repo.init_bare('/var/git/myrepo.git')

Returns Grit::Repo (the newly created repo)



333
334
335
336
337
# File 'lib/grit/repo.rb', line 333

def self.init_bare(path, git_options = {}, repo_options = {})
  git = Git.new(path)
  git.init(git_options)
  self.new(path, repo_options)
end

Instance Method Details

#add(*files) ⇒ Object

Adds files to the index



131
132
133
# File 'lib/grit/repo.rb', line 131

def add(*files)
  self.git.add({}, *files.flatten)
end

#add_remote(name = nil, url = nil) ⇒ Object



502
503
504
505
# File 'lib/grit/repo.rb', line 502

def add_remote(name = nil, url = nil)
  self.git.remote({}, 'add', name, url)
  remote_error_or_response
end

#alternatesObject

The list of alternates for this repo

Returns Array (pathnames of alternates)



431
432
433
434
435
436
437
438
439
# File 'lib/grit/repo.rb', line 431

def alternates
  alternates_path = File.join(self.path, *%w{objects info alternates})

  if File.exist?(alternates_path)
    File.read(alternates_path).strip.split("\n")
  else
    []
  end
end

#alternates=(alts) ⇒ Object

Sets the alternates

+alts+ is the Array of String paths representing the alternates

Returns nothing



445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
# File 'lib/grit/repo.rb', line 445

def alternates=(alts)
  alts.each do |alt|
    unless File.exist?(alt)
      raise "Could not set alternates. Alternate path #{alt} must exist"
    end
  end

  if alts.empty?
    File.open(File.join(self.path, *%w{objects info alternates}), 'w') do |f|
      f.write ''
    end
  else
    File.open(File.join(self.path, *%w{objects info alternates}), 'w') do |f|
      f.write alts.join("\n")
    end
  end
end

#archive_tar(treeish = 'master', prefix = nil) ⇒ Object

Archive the given treeish

+treeish+ is the treeish name/id (default 'master')
+prefix+ is the optional prefix

Examples

repo.archive_tar
# => <String containing tar archive>

repo.archive_tar('a87ff14')
# => <String containing tar archive for commit a87ff14>

repo.archive_tar('master', 'myproject/')
# => <String containing tar archive and prefixed with 'myproject/'>

Returns String (containing tar archive)



366
367
368
369
370
# File 'lib/grit/repo.rb', line 366

def archive_tar(treeish = 'master', prefix = nil)
  options = {}
  options[:prefix] = prefix if prefix
  self.git.archive(options, treeish)
end

#archive_tar_gz(treeish = 'master', prefix = nil) ⇒ Object

Archive and gzip the given treeish

+treeish+ is the treeish name/id (default 'master')
+prefix+ is the optional prefix

Examples

repo.archive_tar_gz
# => <String containing tar.gz archive>

repo.archive_tar_gz('a87ff14')
# => <String containing tar.gz archive for commit a87ff14>

repo.archive_tar_gz('master', 'myproject/')
# => <String containing tar.gz archive and prefixed with 'myproject/'>

Returns String (containing tar.gz archive)



387
388
389
390
391
# File 'lib/grit/repo.rb', line 387

def archive_tar_gz(treeish = 'master', prefix = nil)
  options = {}
  options[:prefix] = prefix if prefix
  self.git.archive(options, treeish, "| gzip")
end

#archive_to_file(treeish = 'master', prefix = nil, filename = 'archive.tar.gz', format = nil, pipe = "gzip") ⇒ Object

Write an archive directly to a file

+treeish+ is the treeish name/id (default 'master')
+prefix+ is the optional prefix (default nil)
+filename+ is the name of the file (default 'archive.tar.gz')
+format+ is the optional format (default nil)
+pipe+ is the command to run the output through (default 'gzip')

Returns nothing



401
402
403
404
405
406
# File 'lib/grit/repo.rb', line 401

def archive_to_file(treeish = 'master', prefix = nil, filename = 'archive.tar.gz', format = nil, pipe = "gzip")
  options = {}
  options[:prefix] = prefix if prefix
  options[:format] = format if format
  self.git.archive(options, treeish, "| #{pipe} > #{filename}")
end

#blame(file, commit = nil) ⇒ Object



85
86
87
# File 'lib/grit/repo.rb', line 85

def blame(file, commit = nil)
  Blame.new(self, file, commit)
end

#blame_tree(commit, path = nil) ⇒ Object



163
164
165
166
167
168
169
170
171
# File 'lib/grit/repo.rb', line 163

def blame_tree(commit, path = nil)
  commit_array = self.git.blame_tree(commit, path)

  final_array = {}
  commit_array.each do |file, sha|
    final_array[file] = commit(sha)
  end
  final_array
end

#blob(id) ⇒ Object

The Blob object for the given id

+id+ is the SHA1 id of the blob

Returns Grit::Blob (unbaked)



294
295
296
# File 'lib/grit/repo.rb', line 294

def blob(id)
  Blob.create(self, :id => id)
end

#checkout_path_commit(commit, path) ⇒ Object



154
155
156
# File 'lib/grit/repo.rb', line 154

def checkout_path_commit(commit, path)
  self.git.checkout({}, commit, '--', path)
end

#commit(id) ⇒ Object

The Commit object for the specified id

+id+ is the SHA1 identifier of the commit

Returns Grit::Commit (baked)



258
259
260
261
262
# File 'lib/grit/repo.rb', line 258

def commit(id)
  options = {:max_count => 1}

  Commit.find_all(self, id, options).first
end

#commit_all(message) ⇒ Object

Commits all tracked and modified files

Returns true/false if commit worked



126
127
128
# File 'lib/grit/repo.rb', line 126

def commit_all(message)
  self.git.commit({}, '-a', '-m', message)
end

#commit_count(start = 'master') ⇒ Object

The number of commits reachable by the given branch/commit

+start+ is the branch/commit name (default 'master')

Returns Integer



250
251
252
# File 'lib/grit/repo.rb', line 250

def commit_count(start = 'master')
  Commit.count(self, start)
end

#commit_deltas_from(other_repo, ref = "master", other_ref = "master") ⇒ Object

Returns a list of commits that is in other_repo but not in self

Returns Grit::Commit[]



267
268
269
270
271
272
273
274
275
276
# File 'lib/grit/repo.rb', line 267

def commit_deltas_from(other_repo, ref = "master", other_ref = "master")
  # TODO: we should be able to figure out the branch point, rather than
  # rev-list'ing the whole thing
  repo_refs       = self.git.rev_list({}, ref).strip.split("\n")
  other_repo_refs = other_repo.git.rev_list({}, other_ref).strip.split("\n")

  (other_repo_refs - repo_refs).map do |ref|
    Commit.find_all(other_repo, ref, {:max_count => 1}).first
  end
end

#commit_diff(commit) ⇒ Object

The commit diff for the given commit

+commit+ is the commit name/id

Returns Grit::Diff[]



321
322
323
# File 'lib/grit/repo.rb', line 321

def commit_diff(commit)
  Commit.diff(self, commit)
end

#commit_index(message) ⇒ Object

Commits current index

Returns true/false if commit worked



119
120
121
# File 'lib/grit/repo.rb', line 119

def commit_index(message)
  self.git.commit({}, '-m', message)
end

#commit_stats(start = 'master', max_count = 10, skip = 0) ⇒ Object



201
202
203
204
205
206
# File 'lib/grit/repo.rb', line 201

def commit_stats(start = 'master', max_count = 10, skip = 0)
  options = {:max_count => max_count,
             :skip => skip}

  CommitStats.find_all(self, start, options)
end

#commits(start = 'master', max_count = 10, skip = 0) ⇒ Object

An array of Commit objects representing the history of a given ref/commit

+start+ is the branch/commit name (default 'master')
+max_count+ is the maximum number of commits to return (default 10, use +false+ for all)
+skip+ is the number of commits to skip (default 0)

Returns Grit::Commit[] (baked)



214
215
216
217
218
219
# File 'lib/grit/repo.rb', line 214

def commits(start = 'master', max_count = 10, skip = 0)
  options = {:max_count => max_count,
             :skip => skip}

  Commit.find_all(self, start, options)
end

#commits_between(from, to) ⇒ Object

The Commits objects that are reachable via to but not via from Commits are returned in chronological order.

+from+ is the branch/commit name of the younger item
+to+ is the branch/commit name of the older item

Returns Grit::Commit[] (baked)



227
228
229
230
231
# File 'lib/grit/repo.rb', line 227

def commits_between(from, to)
  result = Commit.find_all(self, "#{from}..#{to}").reverse
  remote_error
  result
end

#commits_since(start = 'master', since = '1970-01-01', extra_options = {}) ⇒ Object

The Commits objects that are newer than the specified date. Commits are returned in chronological order.

+start+ is the branch/commit name (default 'master')
+since+ is a string represeting a date/time
+extra_options+ is a hash of extra options

Returns Grit::Commit[] (baked)



240
241
242
243
244
# File 'lib/grit/repo.rb', line 240

def commits_since(start = 'master', since = '1970-01-01', extra_options = {})
  options = {:since => since}.merge(extra_options)

  Commit.find_all(self, start, options)
end

#configObject



463
464
465
# File 'lib/grit/repo.rb', line 463

def config
  @config ||= Config.new(self)
end

#descriptionObject

The project’s description. Taken verbatim from GIT_REPO/description

Returns String



81
82
83
# File 'lib/grit/repo.rb', line 81

def description
  File.open(File.join(self.path, 'description')).read.chomp
end

#diff(a, b, *paths) ⇒ Object

The diff from commit a to commit b, optionally restricted to the given file(s)

+a+ is the base commit
+b+ is the other commit
+paths+ is an optional list of file paths on which to restrict the diff


313
314
315
# File 'lib/grit/repo.rb', line 313

def diff(a, b, *paths)
  self.git.diff({}, a, b, '--', *paths)
end

#disable_daemon_serveObject

Disable git-daemon serving of this repository by ensuring there is no git-daemon-export-ok file in its git directory

Returns nothing



420
421
422
# File 'lib/grit/repo.rb', line 420

def disable_daemon_serve
  FileUtils.rm_f(File.join(self.path, DAEMON_EXPORT_FILE))
end

#enable_daemon_serveObject

Enable git-daemon serving of this repository by writing the git-daemon-export-ok file to its git directory

Returns nothing



412
413
414
# File 'lib/grit/repo.rb', line 412

def enable_daemon_serve
  FileUtils.touch(File.join(self.path, DAEMON_EXPORT_FILE))
end

#fork_bare(path, options = {}) ⇒ Object

Fork a bare git repository from this repo

+path+ is the full path of the new repo (traditionally ends with /<name>.git)
+options+ is any additional options to the git clone command (:bare and :shared are true by default)

Returns Grit::Repo (the newly forked repo)



344
345
346
347
348
349
# File 'lib/grit/repo.rb', line 344

def fork_bare(path, options = {})
  default_options = {:bare => true, :shared => true}
  real_options = default_options.merge(options)
  self.git.clone(real_options, self.path, path)
  Repo.new(path)
end

#gc_autoObject



424
425
426
# File 'lib/grit/repo.rb', line 424

def gc_auto
  self.git.gc({:auto => true})
end

#get_head(head_name) ⇒ Object



100
101
102
# File 'lib/grit/repo.rb', line 100

def get_head(head_name)
  heads.find { |h| h.name == head_name }
end

#headObject

Object reprsenting the current repo head.

Returns Grit::Head (baked)



111
112
113
# File 'lib/grit/repo.rb', line 111

def head
  Head.current(self)
end

#headsObject Also known as: branches

An array of Head objects representing the branch heads in this repo

Returns Grit::Head[] (baked)



94
95
96
# File 'lib/grit/repo.rb', line 94

def heads
  Head.find_all(self)
end

#indexObject



467
468
469
# File 'lib/grit/repo.rb', line 467

def index
  Index.new(self)
end

#inspectObject

Pretty object inspection



484
485
486
# File 'lib/grit/repo.rb', line 484

def inspect
  %Q{#<Grit::Repo "#{@path}">}
end

#is_head?(head_name) ⇒ Boolean

Returns:

  • (Boolean)


104
105
106
# File 'lib/grit/repo.rb', line 104

def is_head?(head_name)
  get_head(head_name)
end

#last_errorObject



507
508
509
# File 'lib/grit/repo.rb', line 507

def last_error
  !self.git.last_error.blank? ? self.git.last_error : nil
end

#last_responseObject



511
512
513
# File 'lib/grit/repo.rb', line 511

def last_response
  !self.git.last_response.blank? ? self.git.last_response : nil
end

#log(commit = 'master', path = nil, options = {}) ⇒ Object

The commit log for a treeish

Returns Grit::Commit[]



301
302
303
304
305
306
307
# File 'lib/grit/repo.rb', line 301

def log(commit = 'master', path = nil, options = {})
  default_options = {:pretty => "raw"}
  actual_options  = default_options.merge(options)
  arg = path ? [commit, '--', path] : [commit]
  commits = self.git.log(actual_options, *arg)
  Commit.list_from_string(self, commits)
end

#mv(source, destination) ⇒ Object Also known as: move



148
149
150
# File 'lib/grit/repo.rb', line 148

def mv(source, destination)
  self.git.mv({}, source, destination)
end

#pull(repository = nil, refspec = nil) ⇒ Object



493
494
495
496
497
498
499
500
# File 'lib/grit/repo.rb', line 493

def pull(repository = nil, refspec = nil)
  # git-pull seems to ignore the --work-tree setting and only works if you're actually in the directory
  # fatal: .../git-core/git-pull cannot be used without a working tree.
  in_working_dir do
    self.git.pull({}, repository, refspec)
    remote_error_or_response
  end
end

#push(repository = nil, refspec = nil) ⇒ Object



488
489
490
491
# File 'lib/grit/repo.rb', line 488

def push(repository = nil, refspec = nil)
  self.git.push({}, repository, refspec)
  remote_error_or_response
end

#refsObject

An array of Ref objects representing the refs in this repo

Returns Grit::Ref[] (baked)



197
198
199
# File 'lib/grit/repo.rb', line 197

def refs
  [ Head.find_all(self), Tag.find_all(self), Remote.find_all(self) ].flatten
end

#remotesObject

An array of Remote objects representing the remote branches in this repo

Returns Grit::Remote[] (baked)



189
190
191
# File 'lib/grit/repo.rb', line 189

def remotes
  Remote.find_all(self)
end

#revert(commit) ⇒ Object



158
159
160
# File 'lib/grit/repo.rb', line 158

def revert(commit)
  self.git.revert({}, commit)
end

#rm(*files) ⇒ Object Also known as: remove

Remove files from the index



136
137
138
# File 'lib/grit/repo.rb', line 136

def rm(*files)
  self.git.rm({}, *files.flatten)
end

#rm_r(*files) ⇒ Object Also known as: remove_recursively



142
143
144
# File 'lib/grit/repo.rb', line 142

def rm_r(*files)
  self.git.rm({}, '-r', *files.flatten)
end

#set_config(key, value = nil) ⇒ Object



515
516
517
518
# File 'lib/grit/repo.rb', line 515

def set_config(key, value = nil)
  self.git.config({}, key, value)
  remote_error_or_response
end

#statusObject



173
174
175
# File 'lib/grit/repo.rb', line 173

def status
  Status.new(self)
end

#tagsObject

An array of Tag objects that are available in this repo

Returns Grit::Tag[] (baked)



181
182
183
# File 'lib/grit/repo.rb', line 181

def tags
  Tag.find_all(self)
end

#tree(treeish = 'master', paths = []) ⇒ Object

The Tree object for the given treeish reference

+treeish+ is the reference (default 'master')
+paths+ is an optional Array of directory paths to restrict the tree (deafult [])

Examples

repo.tree('master', ['lib/'])

Returns Grit::Tree (baked)



286
287
288
# File 'lib/grit/repo.rb', line 286

def tree(treeish = 'master', paths = [])
  Tree.construct(self, treeish, paths)
end

#update_ref(head, commit_sha) ⇒ Object



471
472
473
474
475
476
477
478
479
480
481
# File 'lib/grit/repo.rb', line 471

def update_ref(head, commit_sha)
  return nil if !commit_sha || (commit_sha.size != 40)

  ref_heads = File.join(self.path, 'refs', 'heads')
  FileUtils.mkdir_p(ref_heads)
  File.open(File.join(ref_heads, head), 'w') do |f|
    f.write(commit_sha)
  end
  commit_sha

end