5 @working_directory = nil
12 # opens a bare Git Repository - no working directory options
13 def self.bare(git_dir, opts = {})
14 default = {:repository => git_dir}
15 git_options = default.merge(opts)
20 # opens a new Git Project from a working directory
21 # you can specify non-standard git_dir and index file in the options
22 def self.open(working_dir, opts={})
23 default = {:working_directory => working_dir}
24 git_options = default.merge(opts)
29 # initializes a git repository
35 def self.init(working_dir, opts = {})
36 default = {:working_directory => working_dir,
37 :repository => File.join(working_dir, '.git')}
38 git_options = default.merge(opts)
40 if git_options[:working_directory]
41 # if !working_dir, make it
42 FileUtils.mkdir_p(git_options[:working_directory]) if !File.directory?(git_options[:working_directory])
46 Git::Lib.new(git_options).init
51 # clones a git repository locally
53 # repository - http://repo.or.cz/w/sinatra.git
64 def self.clone(repository, name, opts = {})
66 self.new(Git::Lib.new.clone(repository, name, opts))
69 def initialize(options = {})
70 if working_dir = options[:working_directory]
71 options[:repository] = File.join(working_dir, '.git') if !options[:repository]
72 options[:index] = File.join(working_dir, '.git', 'index') if !options[:index]
75 @logger = options[:log]
76 @logger.info("Starting Git")
79 @working_directory = Git::WorkingDirectory.new(options[:working_directory]) if options[:working_directory]
80 @repository = Git::Repository.new(options[:repository]) if options[:repository]
81 @index = Git::Index.new(options[:index], false) if options[:index]
85 # returns a reference to the working directory
92 # returns reference to the git repository directory
98 # returns reference to the git index file
104 def set_working(work_dir, check = true)
106 @working_directory = Git::WorkingDirectory.new(work_dir.to_s, check)
109 def set_index(index_file, check = true)
111 @index = Git::Index.new(index_file.to_s, check)
114 # changes current working directory for a block
115 # to the git working directory
121 # @git.commit('message')
124 Dir.chdir(dir.path) do
129 # returns the repository size in bytes
132 Dir.chdir(repo.path) do
133 (size, dot) = `du -d0`.chomp.split
138 #g.config('user.name', 'Scott Chacon') # sets value
139 #g.config('user.email', 'email@email.com') # sets value
140 #g.config('user.name') # returns 'Scott Chacon'
141 #g.config # returns whole config hash
142 def config(name = nil, value = nil)
145 lib.config_set(name, value)
157 # returns a Git::Object of the appropriate type
158 # you can also call @git.gtree('tree'), but that's
159 # just for readability. If you call @git.gtree('HEAD') it will
160 # still return a Git::Object::Commit object.
162 # @git.object calls a factory method that will run a rev-parse
163 # on the objectish and determine the type of the object and return
164 # an appropriate object for that type
165 def object(objectish)
166 Git::Object.new(self, objectish)
170 Git::Object.new(self, objectish, 'tree')
173 def gcommit(objectish)
174 Git::Object.new(self, objectish, 'commit')
178 Git::Object.new(self, objectish, 'blob')
181 # returns a Git::Log object with count commits
183 Git::Log.new(self, count)
186 # returns a Git::Status object
188 Git::Status.new(self)
191 # returns a Git::Branches object of all the Git::Branch objects for this repo
193 Git::Branches.new(self)
196 # returns a Git::Branch object for branch_name
197 def branch(branch_name = 'master')
198 Git::Branch.new(self, branch_name)
201 # returns a Git::Remote object
202 def remote(remote_name = 'origin')
203 Git::Remote.new(self, remote_name)
206 # this is a convenience method for accessing the class that wraps all the
207 # actual 'git' forked system calls. At some point I hope to replace the Git::Lib
208 # class with one that uses native methods or libgit C bindings
210 @lib ||= Git::Lib.new(self, @logger)
213 # will run a grep for 'string' on the HEAD of the git repository
215 # to be more surgical in your grep, you can call grep() off a specific
216 # git object. for example:
218 # @git.object("v2.3").grep('TODO')
220 # in any case, it returns a hash of arrays of the type:
221 # hsh[tree-ish] = [[line_no, match], [line_no, match2]]
222 # hsh[tree-ish] = [[line_no, match], [line_no, match2]]
224 # so you might use it like this:
226 # @git.grep("TODO").each do |sha, arr|
227 # puts "in blob #{sha}:"
228 # arr.each do |match|
229 # puts "\t line #{match[0]}: '#{match[1]}'"
233 self.object('HEAD').grep(string)
236 # returns a Git::Diff object
237 def diff(objectish = 'HEAD', obj2 = nil)
238 Git::Diff.new(self, objectish, obj2)
241 # adds files from the working directory to the git repository
246 # removes file(s) from the git repository
247 def remove(path = '.', opts = {})
248 self.lib.remove(path, opts)
251 # resets the working directory to the provided commitish
252 def reset(commitish = nil, opts = {})
253 self.lib.reset(commitish, opts)
256 # resets the working directory to the commitish with '--hard'
257 def reset_hard(commitish = nil, opts = {})
258 opts = {:hard => true}.merge(opts)
259 self.lib.reset(commitish, opts)
262 # commits all pending changes in the index file to the git repository
263 def commit(message, opts = {})
264 self.lib.commit(message, opts)
267 # commits all pending changes in the index file to the git repository,
268 # but automatically adds all modified files without having to explicitly
269 # calling @git.add() on them.
270 def commit_all(message, opts = {})
271 opts = {:add_all => true}.merge(opts)
272 self.lib.commit(message, opts)
275 # checks out a branch as the new git working directory
276 def checkout(branch = 'master', opts = {})
277 self.lib.checkout(branch, opts)
280 # fetches changes from a remote branch - this does not modify the working directory,
281 # it just gets the changes from the remote if there are any
282 def fetch(remote = 'origin')
283 self.lib.fetch(remote)
286 # pushes changes to a remote repository - easiest if this is a cloned repository,
287 # otherwise you may have to run something like this first to setup the push parameters:
289 # @git.config('remote.remote-name.push', 'refs/heads/master:refs/heads/master')
291 def push(remote = 'origin', branch = 'master')
292 self.lib.push(remote, branch)
295 # merges one or more branches into the current working branch
297 # you can specify more than one branch to merge by passing an array of branches
298 def merge(branch, message = 'merge')
299 self.lib.merge(branch, message)
302 # iterates over the files which are unmerged
304 # yields file, your_version, their_version
305 def each_conflict(&block)
306 self.lib.conflicts(&block)
309 # fetches a branch from a remote and merges it into the current working branch
310 def pull(remote = 'origin', branch = 'master', message = 'origin pull')
312 merge(branch, message)
315 # returns an array of Git:Remote objects
317 self.lib.remotes.map { |r| Git::Remote.new(self, r) }
320 # adds a new remote to this repository
321 # url can be a git url or a Git::Base object if it's a local reference
323 # @git.add_remote('scotts_git', 'git://repo.or.cz/rubygit.git')
324 # @git.fetch('scotts_git')
325 # @git.merge('scotts_git/master')
327 def add_remote(name, url, opts = {})
328 if url.is_a?(Git::Base)
331 self.lib.remote_add(name, url, opts)
332 Git::Remote.new(self, name)
335 # returns an array of all Git::Tag objects for this repository
337 self.lib.tags.map { |r| tag(r) }
340 # returns a Git::Tag object
342 Git::Object.new(self, tag_name, 'tag', true)
345 # creates a new git tag (Git::Tag)
346 def add_tag(tag_name)
347 self.lib.tag(tag_name)
351 # creates an archive file of the given tree-ish
352 def archive(treeish, file = nil, opts = {})
353 self.object(treeish).archive(file, opts)
356 # repacks the repository
362 ## LOWER LEVEL INDEX OPERATIONS ##
364 def with_index(new_index)
366 set_index(new_index, false)
367 return_value = yield @index
372 def with_temp_index &blk
373 tempfile = Tempfile.new('temp-index')
374 temp_path = tempfile.path
376 with_index(temp_path, &blk)
379 def checkout_index(opts = {})
380 self.lib.checkout_index(opts)
383 def read_tree(treeish, opts = {})
384 self.lib.read_tree(treeish, opts)
391 def commit_tree(tree = nil, opts = {})
392 Git::Object::Commit.new(self, self.lib.commit_tree(tree, opts))
395 def write_and_commit_tree(opts = {})
397 commit_tree(tree, opts)
400 def update_ref(branch, commit)
401 branch(branch).update_ref(commit)
409 def with_working(work_dir)
411 old_working = @working_directory
412 set_working(work_dir)
413 Dir.chdir work_dir do
414 return_value = yield @working_directory
416 set_working(old_working)
420 def with_temp_working &blk
421 tempfile = Tempfile.new("temp-workdir")
422 temp_dir = tempfile.path
424 Dir.mkdir(temp_dir, 0700)
425 with_working(temp_dir, &blk)
429 # runs git rev-parse to convert the objectish to a full sha
431 # @git.revparse("HEAD^^")
432 # @git.revparse('v2.4^{tree}')
433 # @git.revparse('v2.4:/doc/index.html')
435 def revparse(objectish)
436 self.lib.revparse(objectish)
439 def ls_tree(objectish)
440 self.lib.ls_tree(objectish)
443 def cat_file(objectish)
444 self.lib.object_contents(objectish)
447 # returns the name of the branch the working directory is currently on
449 self.lib.branch_current