summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorscott Chacon <schacon@agadorsparticus.(none)>2007-11-11 16:01:23 -0800
committerscott Chacon <schacon@agadorsparticus.(none)>2007-11-11 16:01:23 -0800
commit907b03949bab53e2f7d55094100a71abd22f23e7 (patch)
tree51b7fca355ac7007957d966cbebbcbf331c57d7d
parentb81ee9305f418209ba0d77fbb7b47b23d4b121ca (diff)
downloadthird_party-ruby-git-907b03949bab53e2f7d55094100a71abd22f23e7.tar.gz
third_party-ruby-git-907b03949bab53e2f7d55094100a71abd22f23e7.tar.xz
third_party-ruby-git-907b03949bab53e2f7d55094100a71abd22f23e7.zip
added tagging
-rw-r--r--EXAMPLES19
-rw-r--r--TODO8
-rw-r--r--lib/git/base.rb44
-rw-r--r--lib/git/branch.rb2
-rw-r--r--lib/git/lib.rb42
-rw-r--r--lib/git/object.rb34
-rw-r--r--lib/git/remote.rb25
-rw-r--r--tests/units/test_remotes.rb45
-rw-r--r--tests/units/test_tags.rb35
9 files changed, 235 insertions, 19 deletions
diff --git a/EXAMPLES b/EXAMPLES
index 233cc7c..936a213 100644
--- a/EXAMPLES
+++ b/EXAMPLES
@@ -55,13 +55,10 @@ end
g.config('user.name') # returns 'Scott Chacon'
g.config # returns whole config hash
-***** IMPLEMENTED *****
-
g.tag # returns array of Git::Tag objects
-
# needs write permission
@@ -114,21 +111,25 @@ g.merge('origin/remote_branch')
g.merge(b.branch('master'))
g.merge([branch1, branch2])
+r = g.add_remote(name, uri) # Git::Remote
+r = g.add_remote(name, Git::Base) # Git::Remote
-***** IMPLEMENTED *****
-
-g.add_remote(uri, name) # Git::Remote
-g.remotes
+g.remotes # array of Git::Remotes
g.remote(name).fetch
+g.remote(name).remove
g.remote(name).merge
g.remote(name).merge(branch)
g.fetch
-g.fetch(Git::Remote)
+g.fetch(g.remotes.first)
g.pull
g.pull(Git::Repo, Git::Branch) # fetch and a merge
-g.tag('tag_name') # returns Git::Tag
+g.add_tag('tag_name') # returns Git::Tag
+
+
+***** IMPLEMENTED *****
+
g.pack
diff --git a/TODO b/TODO
new file mode 100644
index 0000000..af82535
--- /dev/null
+++ b/TODO
@@ -0,0 +1,8 @@
+
+* More Error Examples
+
+* More Git::Status methods
+
+* Speed up through pure ruby
+
+* Speed up through C bindings to libgit-thin \ No newline at end of file
diff --git a/lib/git/base.rb b/lib/git/base.rb
index 0b837cb..ffd8a2b 100644
--- a/lib/git/base.rb
+++ b/lib/git/base.rb
@@ -84,6 +84,11 @@ module Git
@index
end
+ def chdir
+ Dir.chdir(dir.path) do
+ yield dir.path
+ end
+ end
#g.config('user.name', 'Scott Chacon') # sets value
#g.config('user.email', 'email@email.com') # sets value
@@ -128,6 +133,10 @@ module Git
Git::Branch.new(self, branch_name)
end
+ def remote(remote_name = 'origin')
+ Git::Remote.new(self, remote_name)
+ end
+
def lib
Git::Lib.new(self)
@@ -172,11 +181,46 @@ module Git
self.lib.checkout(branch, opts)
end
+ def fetch(remote = 'origin')
+ self.lib.fetch(remote)
+ end
+
def merge(branch, message = 'merge')
self.lib.merge(branch, message)
end
+ def pull(remote = 'origin', branch = 'master', message = 'origin pull')
+ fetch(remote)
+ merge(branch, message)
+ end
+
+ def remotes
+ self.lib.remotes.map { |r| Git::Remote.new(self, r) }
+ end
+
+ def add_remote(name, url, opts = {})
+ if url.is_a?(Git::Base)
+ url = url.repo.path
+ end
+ self.lib.remote_add(name, url, opts)
+ Git::Remote.new(self, name)
+ end
+
+ def tags
+ self.lib.tags.map { |r| tag(r) }
+ end
+
+ def tag(tag_name)
+ Git::Object.new(self, tag_name, true)
+ end
+
+ def add_tag(tag_name)
+ self.lib.tag(tag_name)
+ tag(tag_name)
+ end
+
# convenience methods
+
def revparse(objectish)
self.lib.revparse(objectish)
diff --git a/lib/git/branch.rb b/lib/git/branch.rb
index 1d4b64c..4b4ecfc 100644
--- a/lib/git/branch.rb
+++ b/lib/git/branch.rb
@@ -73,7 +73,7 @@ module Git
end
def to_s
- @name
+ @full
end
private
diff --git a/lib/git/lib.rb b/lib/git/lib.rb
index 9b3922e..93490db 100644
--- a/lib/git/lib.rb
+++ b/lib/git/lib.rb
@@ -264,6 +264,43 @@ module Git
command('merge', arr_opts)
end
+ def remote_add(name, url, opts = {})
+ arr_opts = ['add']
+ arr_opts << '-f' if opts[:with_fetch]
+ arr_opts << name
+ arr_opts << url
+
+ command('remote', arr_opts)
+ end
+
+ # this is documented as such, but seems broken for some reason
+ # i'll try to get around it some other way later
+ def remote_remove(name)
+ command('remote', ['rm', name])
+ end
+
+ def remotes
+ command_lines('remote')
+ end
+
+ def tags
+ command_lines('tag')
+ end
+
+ def tag(tag)
+ command('tag', tag)
+ end
+
+
+ def fetch(remote)
+ command('fetch', remote.to_s)
+ end
+
+ def tag_sha(tag_name)
+ command('show-ref', ['--tags', '-s', tag_name])
+ end
+
+
private
@@ -278,19 +315,20 @@ module Git
path = @git_work_dir || @git_dir || @path
Dir.chdir(path) do
opts = opts.to_a.join(' ')
+ git_cmd = "git #{cmd} #{opts}"
out = `git #{cmd} #{opts} 2>&1`.chomp
#puts path
#puts "gd: #{@git_work_dir}"
#puts "gi: #{@git_index_file}"
#puts "pp: #{@path}"
- #puts "git #{cmd} #{opts}"
+ #puts git_cmd
#puts out
#puts
if $?.exitstatus > 0
if $?.exitstatus == 1 && out == ''
return ''
end
- raise Git::GitExecuteError.new(out)
+ raise Git::GitExecuteError.new(git_cmd + out.to_s)
end
out
end
diff --git a/lib/git/object.rb b/lib/git/object.rb
index f100597..a7d7c17 100644
--- a/lib/git/object.rb
+++ b/lib/git/object.rb
@@ -1,4 +1,8 @@
module Git
+
+ class GitTagNameDoesNotExist< StandardError
+ end
+
class Object
class AbstractObject
@@ -64,14 +68,34 @@ module Git
end
end
-
+ class Tag < AbstractObject
+ attr_accessor :name
+
+ def initialize(base, sha, name)
+ super(base, sha)
+ @name = name
+ end
+
+ def setup
+ @type = 'tag'
+ end
+ end
+
class << self
# if we're calling this, we don't know what type it is yet
# so this is our little factory method
- def new(base, objectish)
- sha = base.lib.revparse(objectish)
- type = base.lib.object_type(sha)
-
+ def new(base, objectish, is_tag = false)
+ if is_tag
+ sha = base.lib.tag_sha(objectish)
+ if sha == ''
+ raise Git::GitTagNameDoesNotExist.new(objectish)
+ end
+ return Tag.new(base, sha, objectish)
+ else
+ sha = base.lib.revparse(objectish)
+ type = base.lib.object_type(sha)
+ end
+
klass =
case type
when /blob/: Blob
diff --git a/lib/git/remote.rb b/lib/git/remote.rb
index 6956d47..e72a7f6 100644
--- a/lib/git/remote.rb
+++ b/lib/git/remote.rb
@@ -1,7 +1,7 @@
module Git
class Remote < Path
- attr_accessor :name, :url, :fetch
+ attr_accessor :name, :url, :fetch_opts
@base = nil
@@ -10,7 +10,28 @@ module Git
config = @base.lib.config_remote(name)
@name = name
@url = config['url']
- @fetch = config['fetch']
+ @fetch_opts = config['fetch']
+ end
+
+ def remove
+ @base.remote_remove(@name)
+ end
+
+ def fetch
+ @base.fetch(@name)
+ end
+
+ # merge this remote locally
+ def merge(branch = 'master')
+ @base.merge("#{@name}/#{branch}")
+ end
+
+ def branch(branch = 'master')
+ Git::Branch.new(@base, "#{@name}/#{branch}")
+ end
+
+ def remove
+ @base.lib.remote_remove(@name)
end
def to_s
diff --git a/tests/units/test_remotes.rb b/tests/units/test_remotes.rb
new file mode 100644
index 0000000..ddb066e
--- /dev/null
+++ b/tests/units/test_remotes.rb
@@ -0,0 +1,45 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../test_helper'
+
+class TestRemotes < Test::Unit::TestCase
+ def setup
+ set_file_paths
+ end
+
+ def test_remote_fun
+ in_temp_dir do |path|
+ loc = Git.clone(@wbare, 'local')
+ rem = Git.clone(@wbare, 'remote')
+
+ r = loc.add_remote('testrem', rem)
+
+ Dir.chdir('remote') do
+ new_file('test-file1', 'blahblahblah1')
+ rem.add
+ rem.commit('master commit')
+
+ rem.branch('testbranch').in_branch('tb commit') do
+ new_file('test-file3', 'blahblahblah3')
+ rem.add
+ true
+ end
+ end
+ assert(!loc.status['test-file1'])
+ assert(!loc.status['test-file3'])
+
+ r.fetch
+ r.merge
+ assert(loc.status['test-file1'])
+
+ loc.merge(loc.remote('testrem').branch('testbranch'))
+ assert(loc.status['test-file3'])
+
+ #puts loc.remotes.map { |r| r.to_s }.inspect
+
+ #r.remove
+ #puts loc.remotes.inspect
+ end
+ end
+
+end \ No newline at end of file
diff --git a/tests/units/test_tags.rb b/tests/units/test_tags.rb
new file mode 100644
index 0000000..7d6f279
--- /dev/null
+++ b/tests/units/test_tags.rb
@@ -0,0 +1,35 @@
+#!/usr/bin/env ruby
+
+require File.dirname(__FILE__) + '/../test_helper'
+
+class TestTags < Test::Unit::TestCase
+ def setup
+ set_file_paths
+ end
+
+ def test_tags
+ in_temp_dir do |path|
+ r1 = Git.clone(@wbare, 'repo1')
+ r2 = Git.clone(@wbare, 'repo2')
+
+ assert_raise Git::GitTagNameDoesNotExist do
+ r1.tag('first')
+ end
+
+ r1.add_tag('first')
+ r1.chdir do
+ new_file('new_file', 'new content')
+ end
+ r1.add
+ r1.commit('my commit')
+ r1.add_tag('second')
+
+ assert(r1.tags.map{|t| t.name}.include?('first'))
+
+ r2.add_tag('third')
+
+ assert(r2.tags.map{|t| t.name}.include?('third'))
+ assert(!r2.tags.map{|t| t.name}.include?('second'))
+ end
+ end
+end \ No newline at end of file