peterwald-git 1.1.2

Sign up to get free protection for your applications and to get access to all the features.
data/README ADDED
@@ -0,0 +1,244 @@
1
+ == Git Library for Ruby
2
+
3
+ Library for using Git in Ruby. Test.
4
+
5
+ = Homepage
6
+
7
+ The Ruby/Git homepage is currently at :
8
+
9
+ http://jointheconversation.org/rubygit
10
+
11
+ Git public hosting of the project source code is at:
12
+
13
+ http://github/schacon/ruby-git
14
+
15
+ = Install
16
+
17
+ You can install Ruby/Git like this:
18
+
19
+ $ sudo gem install schacon-git --source=http://gems.github.com
20
+
21
+ = Major Objects
22
+
23
+ Git::Base - this is the object returned from a Git.open or Git.clone.
24
+ Most major actions are called from this object.
25
+
26
+ Git::Object - this is the base object for your tree, blob and commit objects,
27
+ returned from @git.gtree or @git.object calls. the Git::AbstractObject will
28
+ have most of the calls in common for all those objects.
29
+
30
+ Git::Diff - returns from a @git.diff command. It is an Enumerable that returns
31
+ Git::Diff:DiffFile objects from which you can get per file patches and insertion/deletion
32
+ statistics. You can also get total statistics from the Git::Diff object directly.
33
+
34
+ Git::Status - returns from a @git.status command. It is an Enumerable that returns
35
+ Git:Status::StatusFile objects for each object in git, which includes files in the working
36
+ directory, in the index and in the repository. Similar to running 'git status' on the command
37
+ line to determine untracked and changed files.
38
+
39
+ Git::Branches - Enumerable object that holds Git::Branch objects. You can call .local or .remote
40
+ on it to filter to just your local or remote branches.
41
+
42
+ Git::Remote - A reference to a remote repository that is tracked by this repository.
43
+
44
+ Git::Log - An Enumerable object that references all the Git::Object::Commit objects that encompass
45
+ your log query, which can be constructed through methods on the Git::Log object, like:
46
+
47
+ @git.log(20).object("some_file").since("2 weeks ago").between('v2.6', 'v2.7').each { |commit| [block] }
48
+
49
+ = Examples
50
+
51
+ Here are a bunch of examples of how to use the Ruby/Git package.
52
+
53
+ First you have to remember to require rubygems if it's not. Then include the 'git' gem.
54
+
55
+ require 'rubygems'
56
+ require 'git'
57
+
58
+ Here are the operations that need read permission only.
59
+
60
+ g = Git.open (working_dir, :log => Logger.new(STDOUT))
61
+
62
+ g.index
63
+ g.index.readable?
64
+ g.index.writable?
65
+ g.repo
66
+ g.dir
67
+
68
+ g.log # returns array of Git::Commit objects
69
+ g.log.since('2 weeks ago')
70
+ g.log.between('v2.5', 'v2.6')
71
+ g.log.each {|l| puts l.sha }
72
+ g.gblob('v2.5:Makefile').log.since('2 weeks ago')
73
+
74
+ g.object('HEAD^').to_s # git show / git rev-parse
75
+ g.object('HEAD^').contents
76
+ g.object('v2.5:Makefile').size
77
+ g.object('v2.5:Makefile').sha
78
+
79
+ g.gtree(treeish)
80
+ g.gblob(treeish)
81
+ g.gcommit(treeish)
82
+
83
+
84
+ commit = g.gcommit('1cc8667014381')
85
+ commit.gtree
86
+ commit.parent.sha
87
+ commit.parents.size
88
+ commit.author.name
89
+ commit.author.email
90
+ commit.author.date.strftime("%m-%d-%y")
91
+ commit.committer.name
92
+ commit.date.strftime("%m-%d-%y")
93
+ commit.message
94
+
95
+ tree = g.gtree("HEAD^{tree}")
96
+ tree.blobs
97
+ tree.subtrees
98
+ tree.children # blobs and subtrees
99
+
100
+ g.revparse('v2.5:Makefile')
101
+
102
+ g.branches # returns Git::Branch objects
103
+ g.branches.local
104
+ g.branches.remote
105
+ g.branches[:master].gcommit
106
+ g.branches['origin/master'].gcommit
107
+
108
+ g.grep('hello') # implies HEAD
109
+ g.blob('v2.5:Makefile').grep('hello')
110
+ g.tag('v2.5').grep('hello', 'docs/')
111
+
112
+ g.diff(commit1, commit2).size
113
+ g.diff(commit1, commit2).stats
114
+ g.gtree('v2.5').diff('v2.6').insertions
115
+ g.diff('gitsearch1', 'v2.5').path('lib/')
116
+ g.diff('gitsearch1', @git.gtree('v2.5'))
117
+ g.diff('gitsearch1', 'v2.5').path('docs/').patch
118
+ g.gtree('v2.5').diff('v2.6').patch
119
+
120
+ g.gtree('v2.5').diff('v2.6').each do |file_diff|
121
+ puts file_diff.path
122
+ puts file_diff.patch
123
+ puts file_diff.blob(:src).contents
124
+ end
125
+
126
+ g.config('user.name') # returns 'Scott Chacon'
127
+ g.config # returns whole config hash
128
+
129
+ g.tag # returns array of Git::Tag objects
130
+
131
+
132
+
133
+ And here are the operations that will need to write to your git repository.
134
+
135
+
136
+ g = Git.init
137
+ Git.init('project')
138
+ Git.init('/home/schacon/proj',
139
+ { :git_dir => '/opt/git/proj.git',
140
+ :index_file => '/tmp/index'} )
141
+
142
+ g = Git.clone(URI, :name => 'name', :path => '/tmp/checkout')
143
+ g.config('user.name', 'Scott Chacon')
144
+ g.config('user.email', 'email@email.com')
145
+
146
+ g.add('.')
147
+ g.add([file1, file2])
148
+
149
+ g.remove('file.txt')
150
+ g.remove(['file.txt', 'file2.txt'])
151
+
152
+ g.commit('message')
153
+ g.commit_all('message')
154
+
155
+ g = Git.clone(repo, 'myrepo')
156
+ g.chdir do
157
+ new_file('test-file', 'blahblahblah')
158
+ g.status.changed.each do |file|
159
+ puts file.blob(:index).contents
160
+ end
161
+ end
162
+
163
+ g.reset # defaults to HEAD
164
+ g.reset_hard(Git::Commit)
165
+
166
+ g.branch('new_branch') # creates new or fetches existing
167
+ g.branch('new_branch').checkout
168
+ g.branch('new_branch').delete
169
+ g.branch('existing_branch').checkout
170
+
171
+ g.checkout('new_branch')
172
+ g.checkout(g.branch('new_branch'))
173
+
174
+ g.branch(name).merge(branch2)
175
+ g.branch(branch2).merge # merges HEAD with branch2
176
+
177
+ g.branch(name).in_branch(message) { # add files } # auto-commits
178
+ g.merge('new_branch')
179
+ g.merge('origin/remote_branch')
180
+ g.merge(b.branch('master'))
181
+ g.merge([branch1, branch2])
182
+
183
+ r = g.add_remote(name, uri) # Git::Remote
184
+ r = g.add_remote(name, Git::Base) # Git::Remote
185
+
186
+ g.remotes # array of Git::Remotes
187
+ g.remote(name).fetch
188
+ g.remote(name).remove
189
+ g.remote(name).merge
190
+ g.remote(name).merge(branch)
191
+
192
+ g.fetch
193
+ g.fetch(g.remotes.first)
194
+
195
+ g.pull
196
+ g.pull(Git::Repo, Git::Branch) # fetch and a merge
197
+
198
+ g.add_tag('tag_name') # returns Git::Tag
199
+
200
+ g.repack
201
+
202
+ g.push
203
+ g.push(g.remote('name'))
204
+
205
+
206
+ Some examples of more low-level index and tree operations
207
+
208
+ g.with_temp_index do
209
+
210
+ g.read_tree(tree3) # calls self.index.read_tree
211
+ g.read_tree(tree1, :prefix => 'hi/')
212
+
213
+ c = g.commit_tree('message')
214
+ # or #
215
+ t = g.write_tree
216
+ c = g.commit_tree(t, :message => 'message', :parents => [sha1, sha2])
217
+
218
+ g.branch('branch_name').update_ref(c)
219
+ g.update_ref(branch, c)
220
+
221
+ g.with_temp_working do # new blank working directory
222
+ g.checkout
223
+ g.checkout(another_index)
224
+ g.commit # commits to temp_index
225
+ end
226
+ end
227
+
228
+ g.set_index('/path/to/index')
229
+
230
+
231
+ g.with_index(path) do
232
+ # calls set_index, then switches back after
233
+ end
234
+
235
+ g.with_working(dir) do
236
+ # calls set_working, then switches back after
237
+ end
238
+
239
+ g.with_temp_working(dir) do
240
+ g.checkout_index(:prefix => dir, :path_limiter => path)
241
+ # do file work
242
+ g.commit # commits to index
243
+ end
244
+
data/lib/git.rb ADDED
@@ -0,0 +1,110 @@
1
+
2
+ # Add the directory containing this file to the start of the load path if it
3
+ # isn't there already.
4
+ $:.unshift(File.dirname(__FILE__)) unless
5
+ $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
6
+
7
+ require 'git/base'
8
+ require 'git/path'
9
+ require 'git/lib'
10
+
11
+ require 'git/repository'
12
+ require 'git/index'
13
+ require 'git/working_directory'
14
+
15
+ require 'git/log'
16
+ require 'git/object'
17
+
18
+ require 'git/branches'
19
+ require 'git/branch'
20
+ require 'git/remote'
21
+
22
+ require 'git/diff'
23
+ require 'git/status'
24
+ require 'git/author'
25
+
26
+ require 'git/stashes'
27
+ require 'git/stash'
28
+
29
+
30
+ # Git/Ruby Library
31
+ #
32
+ # This provides bindings for working with git in complex
33
+ # interactions, including branching and merging, object
34
+ # inspection and manipulation, history, patch generation
35
+ # and more. You should be able to do most fundamental git
36
+ # operations with this library.
37
+ #
38
+ # This module provides the basic functions to open a git
39
+ # reference to work with. You can open a working directory,
40
+ # open a bare repository, initialize a new repo or clone an
41
+ # existing remote repository.
42
+ #
43
+ # Author:: Scott Chacon (mailto:schacon@gmail.com)
44
+ # License:: MIT License
45
+ module Git
46
+
47
+ VERSION = '1.0.4'
48
+
49
+ # open a bare repository
50
+ #
51
+ # this takes the path to a bare git repo
52
+ # it expects not to be able to use a working directory
53
+ # so you can't checkout stuff, commit things, etc.
54
+ # but you can do most read operations
55
+ def self.bare(git_dir, options = {})
56
+ Base.bare(git_dir, options)
57
+ end
58
+
59
+ # open an existing git working directory
60
+ #
61
+ # this will most likely be the most common way to create
62
+ # a git reference, referring to a working directory.
63
+ # if not provided in the options, the library will assume
64
+ # your git_dir and index are in the default place (.git/, .git/index)
65
+ #
66
+ # options
67
+ # :repository => '/path/to/alt_git_dir'
68
+ # :index => '/path/to/alt_index_file'
69
+ def self.open(working_dir, options = {})
70
+ Base.open(working_dir, options)
71
+ end
72
+
73
+ # initialize a new git repository, defaults to the current working directory
74
+ #
75
+ # options
76
+ # :repository => '/path/to/alt_git_dir'
77
+ # :index => '/path/to/alt_index_file'
78
+ def self.init(working_dir = '.', options = {})
79
+ Base.init(working_dir, options)
80
+ end
81
+
82
+ # clones a remote repository
83
+ #
84
+ # options
85
+ # :bare => true (does a bare clone)
86
+ # :repository => '/path/to/alt_git_dir'
87
+ # :index => '/path/to/alt_index_file'
88
+ #
89
+ # example
90
+ # Git.clone('git://repo.or.cz/rubygit.git', 'clone.git', :bare => true)
91
+ #
92
+ def self.clone(repository, name, options = {})
93
+ Base.clone(repository, name, options)
94
+ end
95
+
96
+ # Export the current HEAD (or a branch, if <tt>options[:branch]</tt>
97
+ # is specified) into the +name+ directory, then remove all traces of git from the
98
+ # directory.
99
+ #
100
+ # See +clone+ for options. Does not obey the <tt>:remote</tt> option,
101
+ # since the .git info will be deleted anyway; always uses the default
102
+ # remote, 'origin.'
103
+ def self.export(repository, name, options = {})
104
+ options.delete(:remote)
105
+ repo = clone(repository, name, {:depth => 1}.merge(options))
106
+ repo.checkout("origin/#{options[:branch]}") if options[:branch]
107
+ Dir.chdir(repo.dir.to_s) { FileUtils.rm_r '.git' }
108
+ end
109
+
110
+ end
data/lib/git/author.rb ADDED
@@ -0,0 +1,14 @@
1
+ module Git
2
+ class Author
3
+ attr_accessor :name, :email, :date
4
+
5
+ def initialize(author_string)
6
+ if m = /(.*?) <(.*?)> (\d+) (.*)/.match(author_string)
7
+ @name = m[1]
8
+ @email = m[2]
9
+ @date = Time.at(m[3].to_i)
10
+ end
11
+ end
12
+
13
+ end
14
+ end
data/lib/git/base.rb ADDED
@@ -0,0 +1,479 @@
1
+ module Git
2
+
3
+ class Base
4
+
5
+ # opens a bare Git Repository - no working directory options
6
+ def self.bare(git_dir, opts = {})
7
+ self.new({:repository => git_dir}.merge(opts))
8
+ end
9
+
10
+ # opens a new Git Project from a working directory
11
+ # you can specify non-standard git_dir and index file in the options
12
+ def self.open(working_dir, opts={})
13
+ self.new({:working_directory => working_dir}.merge(opts))
14
+ end
15
+
16
+ # initializes a git repository
17
+ #
18
+ # options:
19
+ # :repository
20
+ # :index_file
21
+ #
22
+ def self.init(working_dir, opts = {})
23
+ opts = {
24
+ :working_directory => working_dir,
25
+ :repository => File.join(working_dir, '.git')
26
+ }.merge(opts)
27
+
28
+ FileUtils.mkdir_p(opts[:working_directory]) if opts[:working_directory] && !File.directory?(opts[:working_directory])
29
+
30
+ # run git_init there
31
+ Git::Lib.new(opts).init
32
+
33
+ self.new(opts)
34
+ end
35
+
36
+ # clones a git repository locally
37
+ #
38
+ # repository - http://repo.or.cz/w/sinatra.git
39
+ # name - sinatra
40
+ #
41
+ # options:
42
+ # :repository
43
+ #
44
+ # :bare
45
+ # or
46
+ # :working_directory
47
+ # :index_file
48
+ #
49
+ def self.clone(repository, name, opts = {})
50
+ # run git-clone
51
+ self.new(Git::Lib.new.clone(repository, name, opts))
52
+ end
53
+
54
+ def initialize(options = {})
55
+ if working_dir = options[:working_directory]
56
+ options[:repository] ||= File.join(working_dir, '.git')
57
+ options[:index] ||= File.join(working_dir, '.git', 'index')
58
+ end
59
+ if options[:log]
60
+ @logger = options[:log]
61
+ @logger.info("Starting Git")
62
+ else
63
+ @logger = nil
64
+ end
65
+
66
+ @working_directory = options[:working_directory] ? Git::WorkingDirectory.new(options[:working_directory]) : nil
67
+ @repository = options[:repository] ? Git::Repository.new(options[:repository]) : nil
68
+ @index = options[:index] ? Git::Index.new(options[:index], false) : nil
69
+ end
70
+
71
+
72
+ # returns a reference to the working directory
73
+ # @git.dir.path
74
+ # @git.dir.writeable?
75
+ def dir
76
+ @working_directory
77
+ end
78
+
79
+ # returns reference to the git repository directory
80
+ # @git.dir.path
81
+ def repo
82
+ @repository
83
+ end
84
+
85
+ # returns reference to the git index file
86
+ def index
87
+ @index
88
+ end
89
+
90
+
91
+ def set_working(work_dir, check = true)
92
+ @lib = nil
93
+ @working_directory = Git::WorkingDirectory.new(work_dir.to_s, check)
94
+ end
95
+
96
+ def set_index(index_file, check = true)
97
+ @lib = nil
98
+ @index = Git::Index.new(index_file.to_s, check)
99
+ end
100
+
101
+ # changes current working directory for a block
102
+ # to the git working directory
103
+ #
104
+ # example
105
+ # @git.chdir do
106
+ # # write files
107
+ # @git.add
108
+ # @git.commit('message')
109
+ # end
110
+ def chdir # :yields: the Git::Path
111
+ Dir.chdir(dir.path) do
112
+ yield dir.path
113
+ end
114
+ end
115
+
116
+ # returns the repository size in bytes
117
+ def repo_size
118
+ size = 0
119
+ Dir.chdir(repo.path) do
120
+ (size, dot) = `du -s`.chomp.split
121
+ end
122
+ size.to_i
123
+ end
124
+
125
+ #g.config('user.name', 'Scott Chacon') # sets value
126
+ #g.config('user.email', 'email@email.com') # sets value
127
+ #g.config('user.name') # returns 'Scott Chacon'
128
+ #g.config # returns whole config hash
129
+ def config(name = nil, value = nil)
130
+ if(name && value)
131
+ # set value
132
+ lib.config_set(name, value)
133
+ elsif (name)
134
+ # return value
135
+ lib.config_get(name)
136
+ else
137
+ # return hash
138
+ lib.config_list
139
+ end
140
+ end
141
+
142
+ # factory methods
143
+
144
+ # returns a Git::Object of the appropriate type
145
+ # you can also call @git.gtree('tree'), but that's
146
+ # just for readability. If you call @git.gtree('HEAD') it will
147
+ # still return a Git::Object::Commit object.
148
+ #
149
+ # @git.object calls a factory method that will run a rev-parse
150
+ # on the objectish and determine the type of the object and return
151
+ # an appropriate object for that type
152
+ def object(objectish)
153
+ Git::Object.new(self, objectish)
154
+ end
155
+
156
+ def gtree(objectish)
157
+ Git::Object.new(self, objectish, 'tree')
158
+ end
159
+
160
+ def gcommit(objectish)
161
+ Git::Object.new(self, objectish, 'commit')
162
+ end
163
+
164
+ def gblob(objectish)
165
+ Git::Object.new(self, objectish, 'blob')
166
+ end
167
+
168
+ # returns a Git::Log object with count commits
169
+ def log(count = 30)
170
+ Git::Log.new(self, count)
171
+ end
172
+
173
+ # returns a Git::Status object
174
+ def status
175
+ Git::Status.new(self)
176
+ end
177
+
178
+ # returns a Git::Branches object of all the Git::Branch objects for this repo
179
+ def branches
180
+ Git::Branches.new(self)
181
+ end
182
+
183
+ # returns a Git::Branch object for branch_name
184
+ def branch(branch_name = 'master')
185
+ Git::Branch.new(self, branch_name)
186
+ end
187
+
188
+ # returns +true+ if the branch exists locally
189
+ def is_local_branch?(branch)
190
+ branch_names = self.branches.local.map {|b| b.name}
191
+ branch_names.include?(branch)
192
+ end
193
+
194
+ # returns +true+ if the branch exists remotely
195
+ def is_remote_branch?(branch)
196
+ branch_names = self.branches.local.map {|b| b.name}
197
+ branch_names.include?(branch)
198
+ end
199
+
200
+ # returns +true+ if the branch exists
201
+ def is_branch?(branch)
202
+ branch_names = self.branches.map {|b| b.name}
203
+ branch_names.include?(branch)
204
+ end
205
+
206
+ # returns a Git::Remote object
207
+ def remote(remote_name = 'origin')
208
+ Git::Remote.new(self, remote_name)
209
+ end
210
+
211
+ # this is a convenience method for accessing the class that wraps all the
212
+ # actual 'git' forked system calls. At some point I hope to replace the Git::Lib
213
+ # class with one that uses native methods or libgit C bindings
214
+ def lib
215
+ @lib ||= Git::Lib.new(self, @logger)
216
+ end
217
+
218
+ # will run a grep for 'string' on the HEAD of the git repository
219
+ #
220
+ # to be more surgical in your grep, you can call grep() off a specific
221
+ # git object. for example:
222
+ #
223
+ # @git.object("v2.3").grep('TODO')
224
+ #
225
+ # in any case, it returns a hash of arrays of the type:
226
+ # hsh[tree-ish] = [[line_no, match], [line_no, match2]]
227
+ # hsh[tree-ish] = [[line_no, match], [line_no, match2]]
228
+ #
229
+ # so you might use it like this:
230
+ #
231
+ # @git.grep("TODO").each do |sha, arr|
232
+ # puts "in blob #{sha}:"
233
+ # arr.each do |match|
234
+ # puts "\t line #{match[0]}: '#{match[1]}'"
235
+ # end
236
+ # end
237
+ def grep(string, path_limiter = nil, opts = {})
238
+ self.object('HEAD').grep(string, path_limiter, opts)
239
+ end
240
+
241
+ # returns a Git::Diff object
242
+ def diff(objectish = 'HEAD', obj2 = nil)
243
+ Git::Diff.new(self, objectish, obj2)
244
+ end
245
+
246
+ # adds files from the working directory to the git repository
247
+ def add(path = '.')
248
+ self.lib.add(path)
249
+ end
250
+
251
+ # removes file(s) from the git repository
252
+ def remove(path = '.', opts = {})
253
+ self.lib.remove(path, opts)
254
+ end
255
+
256
+ # resets the working directory to the provided commitish
257
+ def reset(commitish = nil, opts = {})
258
+ self.lib.reset(commitish, opts)
259
+ end
260
+
261
+ # resets the working directory to the commitish with '--hard'
262
+ def reset_hard(commitish = nil, opts = {})
263
+ opts = {:hard => true}.merge(opts)
264
+ self.lib.reset(commitish, opts)
265
+ end
266
+
267
+ # commits all pending changes in the index file to the git repository
268
+ #
269
+ # options:
270
+ # :add_all
271
+ # :allow_empty
272
+ # :author
273
+ def commit(message, opts = {})
274
+ self.lib.commit(message, opts)
275
+ end
276
+
277
+ # commits all pending changes in the index file to the git repository,
278
+ # but automatically adds all modified files without having to explicitly
279
+ # calling @git.add() on them.
280
+ def commit_all(message, opts = {})
281
+ opts = {:add_all => true}.merge(opts)
282
+ self.lib.commit(message, opts)
283
+ end
284
+
285
+ # checks out a branch as the new git working directory
286
+ def checkout(branch = 'master', opts = {})
287
+ self.lib.checkout(branch, opts)
288
+ end
289
+
290
+ # checks out an old version of a file
291
+ def checkout_file(version, file)
292
+ self.lib.checkout_file(version,file)
293
+ end
294
+
295
+ # fetches changes from a remote branch - this does not modify the working directory,
296
+ # it just gets the changes from the remote if there are any
297
+ def fetch(remote = 'origin')
298
+ self.lib.fetch(remote)
299
+ end
300
+
301
+ # pushes changes to a remote repository - easiest if this is a cloned repository,
302
+ # otherwise you may have to run something like this first to setup the push parameters:
303
+ #
304
+ # @git.config('remote.remote-name.push', 'refs/heads/master:refs/heads/master')
305
+ #
306
+ def push(remote = 'origin', branch = 'master', tags = false)
307
+ self.lib.push(remote, branch, tags)
308
+ end
309
+
310
+ # merges one or more branches into the current working branch
311
+ #
312
+ # you can specify more than one branch to merge by passing an array of branches
313
+ def merge(branch, message = 'merge')
314
+ self.lib.merge(branch, message)
315
+ end
316
+
317
+ # iterates over the files which are unmerged
318
+ def each_conflict(&block) # :yields: file, your_version, their_version
319
+ self.lib.conflicts(&block)
320
+ end
321
+
322
+ # fetches a branch from a remote and merges it into the current working branch
323
+ def pull(remote = 'origin', branch = 'master', message = 'origin pull')
324
+ fetch(remote)
325
+ merge(branch, message)
326
+ end
327
+
328
+ # returns an array of Git:Remote objects
329
+ def remotes
330
+ self.lib.remotes.map { |r| Git::Remote.new(self, r) }
331
+ end
332
+
333
+ # adds a new remote to this repository
334
+ # url can be a git url or a Git::Base object if it's a local reference
335
+ #
336
+ # @git.add_remote('scotts_git', 'git://repo.or.cz/rubygit.git')
337
+ # @git.fetch('scotts_git')
338
+ # @git.merge('scotts_git/master')
339
+ #
340
+ def add_remote(name, url, opts = {})
341
+ url = url.repo.path if url.is_a?(Git::Base)
342
+ self.lib.remote_add(name, url, opts)
343
+ Git::Remote.new(self, name)
344
+ end
345
+
346
+ # returns an array of all Git::Tag objects for this repository
347
+ def tags
348
+ self.lib.tags.map { |r| tag(r) }
349
+ end
350
+
351
+ # returns a Git::Tag object
352
+ def tag(tag_name)
353
+ Git::Object.new(self, tag_name, 'tag', true)
354
+ end
355
+
356
+ # creates a new git tag (Git::Tag)
357
+ def add_tag(tag_name)
358
+ self.lib.tag(tag_name)
359
+ tag(tag_name)
360
+ end
361
+
362
+ # creates an archive file of the given tree-ish
363
+ def archive(treeish, file = nil, opts = {})
364
+ self.object(treeish).archive(file, opts)
365
+ end
366
+
367
+ # repacks the repository
368
+ def repack
369
+ self.lib.repack
370
+ end
371
+
372
+ def gc
373
+ self.lib.gc
374
+ end
375
+
376
+ def apply(file)
377
+ if File.exists?(file)
378
+ self.lib.apply(file)
379
+ end
380
+ end
381
+
382
+ def apply_mail(file)
383
+ self.lib.apply_mail(file) if File.exists?(file)
384
+ end
385
+
386
+ ## LOWER LEVEL INDEX OPERATIONS ##
387
+
388
+ def with_index(new_index) # :yields: new_index
389
+ old_index = @index
390
+ set_index(new_index, false)
391
+ return_value = yield @index
392
+ set_index(old_index)
393
+ return_value
394
+ end
395
+
396
+ def with_temp_index &blk
397
+ tempfile = Tempfile.new('temp-index')
398
+ temp_path = tempfile.path
399
+ tempfile.unlink
400
+ with_index(temp_path, &blk)
401
+ end
402
+
403
+ def checkout_index(opts = {})
404
+ self.lib.checkout_index(opts)
405
+ end
406
+
407
+ def read_tree(treeish, opts = {})
408
+ self.lib.read_tree(treeish, opts)
409
+ end
410
+
411
+ def write_tree
412
+ self.lib.write_tree
413
+ end
414
+
415
+ def commit_tree(tree = nil, opts = {})
416
+ Git::Object::Commit.new(self, self.lib.commit_tree(tree, opts))
417
+ end
418
+
419
+ def write_and_commit_tree(opts = {})
420
+ tree = write_tree
421
+ commit_tree(tree, opts)
422
+ end
423
+
424
+ def update_ref(branch, commit)
425
+ branch(branch).update_ref(commit)
426
+ end
427
+
428
+
429
+ def ls_files
430
+ self.lib.ls_files
431
+ end
432
+
433
+ def with_working(work_dir) # :yields: the Git::WorkingDirectory
434
+ return_value = false
435
+ old_working = @working_directory
436
+ set_working(work_dir)
437
+ Dir.chdir work_dir do
438
+ return_value = yield @working_directory
439
+ end
440
+ set_working(old_working)
441
+ return_value
442
+ end
443
+
444
+ def with_temp_working &blk
445
+ tempfile = Tempfile.new("temp-workdir")
446
+ temp_dir = tempfile.path
447
+ tempfile.unlink
448
+ Dir.mkdir(temp_dir, 0700)
449
+ with_working(temp_dir, &blk)
450
+ end
451
+
452
+
453
+ # runs git rev-parse to convert the objectish to a full sha
454
+ #
455
+ # @git.revparse("HEAD^^")
456
+ # @git.revparse('v2.4^{tree}')
457
+ # @git.revparse('v2.4:/doc/index.html')
458
+ #
459
+ def revparse(objectish)
460
+ self.lib.revparse(objectish)
461
+ end
462
+
463
+ def ls_tree(objectish)
464
+ self.lib.ls_tree(objectish)
465
+ end
466
+
467
+ def cat_file(objectish)
468
+ self.lib.object_contents(objectish)
469
+ end
470
+
471
+ # returns the name of the branch the working directory is currently on
472
+ def current_branch
473
+ self.lib.branch_current
474
+ end
475
+
476
+
477
+ end
478
+
479
+ end