5 @working_directory = nil
11 # opens a bare Git Repository - no working directory options
12 def self.bare(git_dir)
13 self.new :repository => git_dir
16 # opens a new Git Project from a working directory
17 # you can specify non-standard git_dir and index file in the options
18 def self.open(working_dir, opts={})
19 default = {:working_directory => working_dir}
20 git_options = default.merge(opts)
25 # initializes a git repository
31 def self.init(working_dir, opts = {})
32 default = {:working_directory => working_dir,
33 :repository => File.join(working_dir, '.git')}
34 git_options = default.merge(opts)
36 if git_options[:working_directory]
37 # if !working_dir, make it
38 FileUtils.mkdir_p(git_options[:working_directory]) if !File.directory?(git_options[:working_directory])
42 Git::Lib.new(git_options).init
47 # clones a git repository locally
49 # repository - http://repo.or.cz/w/sinatra.git
60 def self.clone(repository, name, opts = {})
62 self.new(Git::Lib.new.clone(repository, name, opts))
65 def initialize(options = {})
66 if working_dir = options[:working_directory]
67 options[:repository] = File.join(working_dir, '.git') if !options[:repository]
68 options[:index] = File.join(working_dir, '.git', 'index') if !options[:index]
71 @working_directory = Git::WorkingDirectory.new(options[:working_directory]) if options[:working_directory]
72 @repository = Git::Repository.new(options[:repository]) if options[:repository]
73 @index = Git::Index.new(options[:index], false) if options[:index]
77 # returns a reference to the working directory
84 # returns reference to the git repository directory
90 # returns reference to the git index file
96 def set_working(work_dir, check = true)
98 @working_directory = Git::WorkingDirectory.new(work_dir.to_s, check)
101 def set_index(index_file, check = true)
103 @index = Git::Index.new(index_file.to_s, check)
106 # changes current working directory for a block
107 # to the git working directory
113 # @git.commit('message')
116 Dir.chdir(dir.path) do
121 # returns the repository size in bytes
124 Dir.chdir(repo.path) do
125 (size, dot) = `du -d0`.chomp.split
130 #g.config('user.name', 'Scott Chacon') # sets value
131 #g.config('user.email', 'email@email.com') # sets value
132 #g.config('user.name') # returns 'Scott Chacon'
133 #g.config # returns whole config hash
134 def config(name = nil, value = nil)
137 lib.config_set(name, value)
149 # returns a Git::Object of the appropriate type
150 # you can also call @git.gtree('tree'), but that's
151 # just for readability. If you call @git.gtree('HEAD') it will
152 # still return a Git::Object::Commit object.
154 # @git.object calls a factory method that will run a rev-parse
155 # on the objectish and determine the type of the object and return
156 # an appropriate object for that type
157 def object(objectish)
158 Git::Object.new(self, objectish)
162 Git::Object.new(self, objectish, 'tree')
165 def gcommit(objectish)
166 Git::Object.new(self, objectish, 'commit')
170 Git::Object.new(self, objectish, 'blob')
173 # returns a Git::Log object with count commits
175 Git::Log.new(self, count)
178 # returns a Git::Status object
180 Git::Status.new(self)
183 # returns a Git::Branches object of all the Git::Branch objects for this repo
185 Git::Branches.new(self)
188 # returns a Git::Branch object for branch_name
189 def branch(branch_name = 'master')
190 Git::Branch.new(self, branch_name)
193 # returns a Git::Remote object
194 def remote(remote_name = 'origin')
195 Git::Remote.new(self, remote_name)
198 # this is a convenience method for accessing the class that wraps all the
199 # actual 'git' forked system calls. At some point I hope to replace the Git::Lib
200 # class with one that uses native methods or libgit C bindings
202 @lib ||= Git::Lib.new(self)
205 # will run a grep for 'string' on the HEAD of the git repository
207 # to be more surgical in your grep, you can call grep() off a specific
208 # git object. for example:
210 # @git.object("v2.3").grep('TODO')
212 # in any case, it returns a hash of arrays of the type:
213 # hsh[tree-ish] = [[line_no, match], [line_no, match2]]
214 # hsh[tree-ish] = [[line_no, match], [line_no, match2]]
216 # so you might use it like this:
218 # @git.grep("TODO").each do |sha, arr|
219 # puts "in blob #{sha}:"
220 # arr.each do |match|
221 # puts "\t line #{match[0]}: '#{match[1]}'"
225 self.object('HEAD').grep(string)
228 # returns a Git::Diff object
229 def diff(objectish = 'HEAD', obj2 = nil)
230 Git::Diff.new(self, objectish, obj2)
233 # adds files from the working directory to the git repository
238 # removes file(s) from the git repository
239 def remove(path = '.', opts = {})
240 self.lib.remove(path, opts)
243 # resets the working directory to the provided commitish
244 def reset(commitish = nil, opts = {})
245 self.lib.reset(commitish, opts)
248 # resets the working directory to the commitish with '--hard'
249 def reset_hard(commitish = nil, opts = {})
250 opts = {:hard => true}.merge(opts)
251 self.lib.reset(commitish, opts)
254 # commits all pending changes in the index file to the git repository
255 def commit(message, opts = {})
256 self.lib.commit(message, opts)
259 # commits all pending changes in the index file to the git repository,
260 # but automatically adds all modified files without having to explicitly
261 # calling @git.add() on them.
262 def commit_all(message, opts = {})
263 opts = {:add_all => true}.merge(opts)
264 self.lib.commit(message, opts)
267 # checks out a branch as the new git working directory
268 def checkout(branch = 'master', opts = {})
269 self.lib.checkout(branch, opts)
272 # fetches changes from a remote branch - this does not modify the working directory,
273 # it just gets the changes from the remote if there are any
274 def fetch(remote = 'origin')
275 self.lib.fetch(remote)
278 # pushes changes to a remote repository - easiest if this is a cloned repository,
279 # otherwise you may have to run something like this first to setup the push parameters:
281 # @git.config('remote.remote-name.push', 'refs/heads/master:refs/heads/master')
283 def push(remote = 'origin', branch = 'master')
284 self.lib.push(remote, branch)
287 # merges one or more branches into the current working branch
289 # you can specify more than one branch to merge by passing an array of branches
290 def merge(branch, message = 'merge')
291 self.lib.merge(branch, message)
294 # fetches a branch from a remote and merges it into the current working branch
295 def pull(remote = 'origin', branch = 'master', message = 'origin pull')
297 merge(branch, message)
300 # returns an array of Git:Remote objects
302 self.lib.remotes.map { |r| Git::Remote.new(self, r) }
305 # adds a new remote to this repository
306 # url can be a git url or a Git::Base object if it's a local reference
308 # @git.add_remote('scotts_git', 'git://repo.or.cz/rubygit.git')
309 # @git.fetch('scotts_git')
310 # @git.merge('scotts_git/master')
312 def add_remote(name, url, opts = {})
313 if url.is_a?(Git::Base)
316 self.lib.remote_add(name, url, opts)
317 Git::Remote.new(self, name)
320 # returns an array of all Git::Tag objects for this repository
322 self.lib.tags.map { |r| tag(r) }
325 # returns a Git::Tag object
327 Git::Object.new(self, tag_name, 'tag', true)
330 # creates a new git tag (Git::Tag)
331 def add_tag(tag_name)
332 self.lib.tag(tag_name)
336 # creates an archive file of the given tree-ish
337 def archive(treeish, file = nil, opts = {})
338 self.object(treeish).archive(file, opts)
341 # repacks the repository
347 ## LOWER LEVEL INDEX OPERATIONS ##
349 def with_index(new_index)
351 set_index(new_index, false)
352 return_value = yield @index
357 def with_temp_index &blk
358 tempfile = Tempfile.new('temp-index')
359 temp_path = tempfile.path
361 with_index(temp_path, &blk)
364 def checkout_index(opts = {})
365 self.lib.checkout_index(opts)
368 def read_tree(treeish, opts = {})
369 self.lib.read_tree(treeish, opts)
376 def commit_tree(tree = nil, opts = {})
377 Git::Object::Commit.new(self, self.lib.commit_tree(tree, opts))
380 def write_and_commit_tree(opts = {})
382 commit_tree(tree, opts)
385 def update_ref(branch, commit)
386 branch(branch).update_ref(commit)
394 def with_working(work_dir)
396 old_working = @working_directory
397 set_working(work_dir)
398 Dir.chdir work_dir do
399 return_value = yield @working_directory
401 set_working(old_working)
405 def with_temp_working &blk
406 tempfile = Tempfile.new("temp-workdir")
407 temp_dir = tempfile.path
409 Dir.mkdir(temp_dir, 0700)
410 with_working(temp_dir, &blk)
414 # runs git rev-parse to convert the objectish to a full sha
416 # @git.revparse("HEAD^^")
417 # @git.revparse('v2.4^{tree}')
418 # @git.revparse('v2.4:/doc/index.html')
420 def revparse(objectish)
421 self.lib.revparse(objectish)
424 # returns the name of the branch the working directory is currently on
426 self.lib.branch_current