summaryrefslogtreecommitdiffstats
path: root/lib/git
diff options
context:
space:
mode:
authorscott Chacon <schacon@agadorsparticus.(none)>2007-11-10 12:43:33 -0800
committerscott Chacon <schacon@agadorsparticus.(none)>2007-11-10 12:43:33 -0800
commitfde3263abc5c7866aa7dce7aef28eacaa33d7664 (patch)
treec9911ac92e9770c7bfea3e79269f8e7dcf7f6982 /lib/git
parent9d59d2965184964ab6662282ef5f9ceac2c58552 (diff)
downloadthird_party-ruby-git-fde3263abc5c7866aa7dce7aef28eacaa33d7664.tar.gz
third_party-ruby-git-fde3263abc5c7866aa7dce7aef28eacaa33d7664.tar.xz
third_party-ruby-git-fde3263abc5c7866aa7dce7aef28eacaa33d7664.zip
few hours work - diff is done
Diffstat (limited to 'lib/git')
-rw-r--r--lib/git/base.rb51
-rw-r--r--lib/git/branches.rb3
-rw-r--r--lib/git/diff.rb124
-rw-r--r--lib/git/lib.rb83
-rw-r--r--lib/git/object.rb10
-rw-r--r--lib/git/path.rb4
6 files changed, 238 insertions, 37 deletions
diff --git a/lib/git/base.rb b/lib/git/base.rb
index 8170065..1111887 100644
--- a/lib/git/base.rb
+++ b/lib/git/base.rb
@@ -22,19 +22,33 @@ module Git
self.new(git_options)
end
- def initialize(options = {})
- @working_directory = Git::Repository.new(options[:working_directory]) if options[:working_directory]
- @repository = Git::Repository.new(options[:repository]) if options[:repository]
- @index = Git::Index.new(options[:index]) if options[:index]
+ def self.init(working_dir, opts = {})
+ default = {:working_directory => working_dir,
+ :repository => File.join(working_dir, '.git')}
+ git_options = default.merge(opts)
+
+ if git_options[:working_directory]
+ # if !working_dir, make it
+ FileUtils.mkdir_p(git_options[:working_directory]) if !File.directory?(git_options[:working_directory])
+ end
+
+ # run git_init there
+ Git::Lib.new(git_options).init
+
+ self.new(git_options)
end
-
+
def self.clone
raise NotImplementedError
end
-
- def self.init
- raise NotImplementedError
+
+ def initialize(options = {})
+ @working_directory = Git::WorkingDirectory.new(options[:working_directory]) if options[:working_directory]
+ @repository = Git::Repository.new(options[:repository]) if options[:repository]
+ @index = Git::Index.new(options[:index]) if options[:index]
end
+
+
def dir
@@ -49,6 +63,23 @@ module Git
@index
end
+
+ #g.config('user.name', 'Scott Chacon') # sets value
+ #g.config('user.email', 'email@email.com') # sets value
+ #g.config('user.name') # returns 'Scott Chacon'
+ #g.config # returns whole config hash
+ def config(name = nil, value = nil)
+ if(name && value)
+ # set value
+ elsif (name)
+ # return value
+ lib.config_get(name)
+ else
+ # return hash
+ lib.config_list
+ end
+ end
+
# factory methods
def object(objectish)
@@ -75,6 +106,10 @@ module Git
self.object('HEAD').grep(string)
end
+ def diff(objectish = 'HEAD', obj2 = nil)
+ Git::Diff.new(self, objectish, obj2)
+ end
+
# convenience methods
def revparse(objectish)
diff --git a/lib/git/branches.rb b/lib/git/branches.rb
index 81abe22..72dff0a 100644
--- a/lib/git/branches.rb
+++ b/lib/git/branches.rb
@@ -11,8 +11,9 @@ module Git
@branches = {}
@base = base
+
@base.lib.branches_all.each do |b|
- @branches[b.full] = b
+ @branches[b[0]] = Git::Branch.new(@base, b[0], b[1])
end
end
diff --git a/lib/git/diff.rb b/lib/git/diff.rb
index 3686edb..b43ecd9 100644
--- a/lib/git/diff.rb
+++ b/lib/git/diff.rb
@@ -7,31 +7,137 @@ module Git
@base = nil
@from = nil
@to = nil
+ @path = nil
@full_diff = nil
+ @full_diff_files = nil
+ @stats = nil
def initialize(base, from = nil, to = nil)
- dirty_log
@base = base
- @from = from
- @to = to
+ @from = from.to_s
+ @to = to.to_s
end
- def
+ def path(path)
+ @path = path
+ return self
+ end
+
+ def size
+ cache_stats
+ @stats[:total][:files]
+ end
+
+ def lines
+ cache_stats
+ @stats[:total][:lines]
+ end
+
+ def deletions
+ cache_stats
+ @stats[:total][:deletions]
+ end
+
+ def insertions
+ cache_stats
+ @stats[:total][:insertions]
+ end
+
+ def stats
+ cache_stats
+ @stats
+ end
+
+ # if file is provided and is writable, it will write the patch into the file
+ def patch(file = nil)
+ cache_full
+ @full_diff
+ end
+ alias_method :to_s, :patch
+
# enumerable methods
+ def [](key)
+ process_full
+ @full_diff_files.assoc(key)[1]
+ end
+
def each
- cache_diff
- @full_diff.each do |file|
- yield file
+ process_full
+ @full_diff_files.each do |file|
+ yield file[1]
+ end
+ end
+
+ class DiffFile
+ attr_accessor :patch, :path, :mode, :src, :dst, :type
+ @base = nil
+
+ def initialize(base, hash)
+ @base = base
+ @patch = hash[:patch]
+ @path = hash[:path]
+ @mode = hash[:mode]
+ @src = hash[:src]
+ @dst = hash[:dst]
+ @type = hash[:type]
+ end
+
+ def blob(type = :dst)
+ if type == :src
+ @base.object(@src) if @src != '0000000'
+ else
+ @base.object(@dst) if @dst != '0000000'
+ end
end
end
private
- def cache_diff
+ def cache_full
if !@full_diff
- @full_diff = @base.lib.diff_files(@from, @to)
+ @full_diff = @base.lib.diff_full(@from, @to, {:path_limiter => @path})
+ end
+ end
+
+ def process_full
+ if !@full_diff_files
+ cache_full
+ @full_diff_files = process_full_diff
+ end
+ end
+
+ def cache_stats
+ if !@stats
+ @stats = @base.lib.diff_stats(@from, @to, {:path_limiter => @path})
+ end
+ end
+
+ # break up @diff_full
+ def process_full_diff
+ final = {}
+ current_file = nil
+ @full_diff.split("\n").each do |line|
+ if m = /diff --git a\/(.*?) b\/(.*?)/.match(line)
+ current_file = m[1]
+ final[current_file] = {:patch => line, :path => current_file,
+ :mode => '', :src => '', :dst => '', :type => 'modified'}
+ else
+ if m = /index (.......)\.\.(.......)( ......)*/.match(line)
+ final[current_file][:src] = m[1]
+ final[current_file][:dst] = m[2]
+ final[current_file][:mode] = m[3].strip if m[3]
+ end
+ if m = /(.*?) file mode (......)/.match(line)
+ final[current_file][:type] = m[1]
+ final[current_file][:mode] = m[2]
+ end
+ final[current_file][:patch] << "\n" + line
+ end
end
+ final.map { |e| [e[0], DiffFile.new(@base, e[1])] }
end
+
+ end
end \ No newline at end of file
diff --git a/lib/git/lib.rb b/lib/git/lib.rb
index 2937d52..8bb518b 100644
--- a/lib/git/lib.rb
+++ b/lib/git/lib.rb
@@ -3,15 +3,26 @@ module Git
class GitExecuteError < StandardError
end
- class GitNoOutput < StandardError
- end
-
class Lib
- @base = nil
-
+ @git_dir = nil
+ @git_index_file = nil
+ @git_work_dir = nil
+
def initialize(base)
- @base = base
+ if base.is_a?(Git::Base)
+ @git_dir = base.repo.path
+ @git_index_file = base.index.path
+ @git_work_dir = base.dir.path
+ elsif base.is_a?(Hash)
+ @git_dir = base[:repository]
+ @git_index_file = base[:index]
+ @git_work_dir = base[:working_directory]
+ end
+ end
+
+ def init
+ command('init')
end
def log_commits(opts = {})
@@ -42,13 +53,28 @@ module Git
end
def branches_all
- command_lines('branch', '-a').map do |b|
+ arr = []
+ command_lines('branch', '-a').each do |b|
current = false
current = true if b[0, 2] == '* '
- Git::Branch.new(@base, b.gsub('* ', '').strip, current)
+ arr << [b.gsub('* ', '').strip, current]
end
+ arr
+ end
+
+ def config_get(name)
+ command('config', ['--get', name])
end
+ def config_list
+ hsh = {}
+ command_lines('config', ['--list']).each do |line|
+ (key, value) = line.split('=')
+ hsh[key] = value
+ end
+ hsh
+ end
+
def config_remote(name)
hsh = {}
command_lines('config', ['--get-regexp', "remote.#{name}"]).each do |line|
@@ -68,7 +94,7 @@ module Git
grep_opts << '-i' if opts[:ignore_case]
grep_opts << '-v' if opts[:invert_match]
grep_opts << "-e '#{string}'"
- grep_opts << opts[:object] if opts[:object].is_a? String
+ grep_opts << opts[:object] if opts[:object].is_a?(String)
grep_opts << ('-- ' + opts[:path_limiter]) if opts[:path_limiter].is_a? String
hsh = {}
command_lines('grep', grep_opts).each do |line|
@@ -80,17 +106,46 @@ module Git
hsh
end
+ def diff_full(obj1 = 'HEAD', obj2 = nil, opts = {})
+ diff_opts = ['-p']
+ diff_opts << obj1
+ diff_opts << obj2 if obj2.is_a?(String)
+ diff_opts << ('-- ' + opts[:path_limiter]) if opts[:path_limiter].is_a? String
+
+ command('diff', diff_opts)
+ end
+
+ def diff_stats(obj1 = 'HEAD', obj2 = nil, opts = {})
+ diff_opts = ['--numstat']
+ diff_opts << obj1
+ diff_opts << obj2 if obj2.is_a?(String)
+ diff_opts << ('-- ' + opts[:path_limiter]) if opts[:path_limiter].is_a? String
+
+ hsh = {:total => {:insertions => 0, :deletions => 0, :lines => 0, :files => 0}, :files => {}}
+
+ command_lines('diff', diff_opts).each do |file|
+ (insertions, deletions, filename) = file.split("\t")
+ hsh[:total][:insertions] += insertions.to_i
+ hsh[:total][:deletions] += deletions.to_i
+ hsh[:total][:lines] = (hsh[:total][:deletions] + hsh[:total][:insertions])
+ hsh[:total][:files] += 1
+ hsh[:files][filename] = {:insertions => insertions.to_i, :deletions => deletions.to_i}
+ end
+
+ hsh
+ end
+
private
def command_lines(cmd, opts)
command(cmd, opts).split("\n")
end
- def command(cmd, opts)
- ENV['GIT_DIR'] = @base.repo.path
- ENV['GIT_INDEX_FILE'] = @base.index.path
- ENV['GIT_WORK_DIR'] = @base.dir.path
- Dir.chdir(@base.dir.path) do
+ def command(cmd, opts = {})
+ ENV['GIT_DIR'] = @git_dir
+ ENV['GIT_INDEX_FILE'] = @git_index_file if @git_index_file
+ ENV['GIT_WORK_DIR'] = @git_work_dir if @git_work_dir
+ Dir.chdir(@git_work_dir || @git_dir) do
opts = opts.to_a.join(' ')
#puts "git #{cmd} #{opts}"
out = `git #{cmd} #{opts} 2>&1`.chomp
diff --git a/lib/git/object.rb b/lib/git/object.rb
index f2d4114..f100597 100644
--- a/lib/git/object.rb
+++ b/lib/git/object.rb
@@ -2,7 +2,7 @@ module Git
class Object
class AbstractObject
- attr_accessor :sha, :size, :type
+ attr_accessor :sha, :size, :type, :mode
@base = nil
@@ -26,7 +26,7 @@ module Git
end
def to_s
- "#{@type.ljust(6)} #{@sha}"
+ @sha
end
def grep(string, path_limiter = nil, opts = {})
@@ -35,8 +35,12 @@ module Git
@base.lib.grep(string, grep_options)
end
+ def diff(objectish)
+ Git::Diff.new(@base, @sha, objectish)
+ end
+
def log(count = 30)
- Git::Log.new(self, count).object(@sha)
+ Git::Log.new(@base, count).object(@sha)
end
end
diff --git a/lib/git/path.rb b/lib/git/path.rb
index 9d6ba49..18845fa 100644
--- a/lib/git/path.rb
+++ b/lib/git/path.rb
@@ -3,8 +3,8 @@ module Git
attr_accessor :path
- def initialize(path)
- if File.exists?(path)
+ def initialize(path, check_path = true)
+ if !check_path || File.exists?(path)
@path = path
else
raise ArgumentError, "path does not exist", path