From 9d59d2965184964ab6662282ef5f9ceac2c58552 Mon Sep 17 00:00:00 2001 From: scott Chacon Date: Fri, 9 Nov 2007 13:11:22 -0800 Subject: added branches, more log stuff, better tests, changed the log api a bit added tests for Git::Lib, started Git::Diff development --- lib/git.rb | 10 +++++----- lib/git/base.rb | 8 ++++++++ lib/git/branch.rb | 16 +++++++++++++++- lib/git/branches.rb | 30 +++++++++++++++++++++++++++++- lib/git/diff.rb | 37 +++++++++++++++++++++++++++++++++++++ lib/git/lib.rb | 50 +++++++++++++++++++++++++++++++++++++++++++++----- lib/git/log.rb | 17 +++++++++++++---- lib/git/object.rb | 10 ++++++++++ lib/git/remote.rb | 21 +++++++++++++++++++++ 9 files changed, 183 insertions(+), 16 deletions(-) create mode 100644 lib/git/diff.rb create mode 100644 lib/git/remote.rb (limited to 'lib') diff --git a/lib/git.rb b/lib/git.rb index 634109e..a43aee2 100644 --- a/lib/git.rb +++ b/lib/git.rb @@ -15,19 +15,19 @@ require 'git/working_directory' require 'git/log' require 'git/object' +require 'git/branches' require 'git/branch' +require 'git/remote' =begin - - require 'git/author' -require 'git/ref' require 'git/file' -require 'git/sha' require 'git/diff' - require 'git/remote' + +require 'git/sha' +require 'git/ref' =end module Git diff --git a/lib/git/base.rb b/lib/git/base.rb index d552432..8170065 100644 --- a/lib/git/base.rb +++ b/lib/git/base.rb @@ -54,6 +54,10 @@ module Git def object(objectish) Git::Object.new(self, objectish) end + alias_method :tree, :object + alias_method :commit, :object + alias_method :blob, :object + def log(count = 30) Git::Log.new(self, count) @@ -67,6 +71,10 @@ module Git Git::Lib.new(self) end + def grep(string) + self.object('HEAD').grep(string) + end + # convenience methods def revparse(objectish) diff --git a/lib/git/branch.rb b/lib/git/branch.rb index 8f8953b..cc33970 100644 --- a/lib/git/branch.rb +++ b/lib/git/branch.rb @@ -1,10 +1,24 @@ module Git class Branch < Path + attr_accessor :full, :remote, :name, :current, :commit + @base = nil - def initialize(base, name) + def initialize(base, name, current = false) + @remote = nil + @full = name @base = base + @commit = @base.object(name) + @current = current + + parts = name.split('/') + if parts[1] + @remote = Git::Remote.new(@base, parts[0]) + @name = parts[1] + else + @name = parts[0] + end end end diff --git a/lib/git/branches.rb b/lib/git/branches.rb index d664d59..81abe22 100644 --- a/lib/git/branches.rb +++ b/lib/git/branches.rb @@ -8,8 +8,36 @@ module Git @branches = nil def initialize(base) + @branches = {} + @base = base - @branches = @base.lib.branches_all + @base.lib.branches_all.each do |b| + @branches[b.full] = b + end + end + + def local + self.select { |b| !b.remote } + end + + def remote + self.select { |b| b.remote } + end + + # array like methods + + def size + @branches.size + end + + def each + @branches.each do |k, b| + yield b + end + end + + def [](symbol) + @branches[symbol.to_s] end end diff --git a/lib/git/diff.rb b/lib/git/diff.rb new file mode 100644 index 0000000..3686edb --- /dev/null +++ b/lib/git/diff.rb @@ -0,0 +1,37 @@ +module Git + + # object that holds the last X commits on given branch + class Diff + include Enumerable + + @base = nil + @from = nil + @to = nil + + @full_diff = nil + + def initialize(base, from = nil, to = nil) + dirty_log + @base = base + @from = from + @to = to + end + + def + # enumerable methods + + def each + cache_diff + @full_diff.each do |file| + yield file + end + end + + private + + def cache_diff + if !@full_diff + @full_diff = @base.lib.diff_files(@from, @to) + end + end +end \ No newline at end of file diff --git a/lib/git/lib.rb b/lib/git/lib.rb index c83ecaa..2937d52 100644 --- a/lib/git/lib.rb +++ b/lib/git/lib.rb @@ -3,6 +3,9 @@ module Git class GitExecuteError < StandardError end + class GitNoOutput < StandardError + end + class Lib @base = nil @@ -11,14 +14,15 @@ module Git @base = base end - def log_commits(opts) + def log_commits(opts = {}) arr_opts = ['--pretty=oneline'] arr_opts << "-#{opts[:count]}" if opts[:count] arr_opts << "--since=\"#{opts[:since]}\"" if opts[:since].is_a? String arr_opts << "#{opts[:between][0]}..#{opts[:between][1].to_s}" if (opts[:between] && opts[:between].size == 2) - arr_opts << opts[:file] if opts[:file].is_a? String + arr_opts << opts[:object] if opts[:object].is_a? String + arr_opts << '-- ' + opts[:path_limiter] if opts[:path_limiter].is_a? String - command_lines('log', arr_opts).map { |l| Git::Object::Commit.new(@base, l.split.first) } + command_lines('log', arr_opts).map { |l| l.split.first } end def revparse(string) @@ -38,7 +42,42 @@ module Git end def branches_all - command_lines('branch', '-a').map { |l| Git::Branch.new(@base, l) } + command_lines('branch', '-a').map do |b| + current = false + current = true if b[0, 2] == '* ' + Git::Branch.new(@base, b.gsub('* ', '').strip, current) + end + end + + def config_remote(name) + hsh = {} + command_lines('config', ['--get-regexp', "remote.#{name}"]).each do |line| + (key, value) = line.split + hsh[key.gsub("remote.#{name}.", '')] = value + end + hsh + end + + # returns hash + # [tree-ish] = [[line_no, match], [line_no, match2]] + # [tree-ish] = [[line_no, match], [line_no, match2]] + def grep(string, opts = {}) + opts[:object] = 'HEAD' if !opts[:object] + + grep_opts = ['-n'] + 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[:path_limiter]) if opts[:path_limiter].is_a? String + hsh = {} + command_lines('grep', grep_opts).each do |line| + if m = /(.*)\:(\d+)\:(.*)/.match(line) + hsh[m[1]] ||= [] + hsh[m[1]] << [m[2].to_i, m[3]] + end + end + hsh end private @@ -55,7 +94,8 @@ module Git opts = opts.to_a.join(' ') #puts "git #{cmd} #{opts}" out = `git #{cmd} #{opts} 2>&1`.chomp - if $?.exitstatus != 0 + #puts out + if $?.exitstatus > 1 raise Git::GitExecuteError.new(out) end out diff --git a/lib/git/log.rb b/lib/git/log.rb index d11a6fa..eb625f3 100644 --- a/lib/git/log.rb +++ b/lib/git/log.rb @@ -7,7 +7,8 @@ module Git @base = nil @commits = nil - @file = nil + @object = nil + @path = nil @count = nil @since = nil @between = nil @@ -20,9 +21,15 @@ module Git @count = count end - def file(file) + def object(objectish) dirty_log - @file = file + @object = objectish + return self + end + + def path(path) + dirty_log + @path = path return self end @@ -77,7 +84,9 @@ module Git # actually run the 'git log' command def run_log - @commits = @base.lib.log_commits(:count => @count, :file => @file, :since => @since, :between => @between) + log = @base.lib.log_commits(:count => @count, :object => @object, + :path_limiter => @path, :since => @since, :between => @between) + @commits = log.map { |l| Git::Object::Commit.new(@base, l) } end end diff --git a/lib/git/object.rb b/lib/git/object.rb index 4f8e559..f2d4114 100644 --- a/lib/git/object.rb +++ b/lib/git/object.rb @@ -29,6 +29,16 @@ module Git "#{@type.ljust(6)} #{@sha}" end + def grep(string, path_limiter = nil, opts = {}) + default = {:object => @sha, :path_limiter => path_limiter} + grep_options = default.merge(opts) + @base.lib.grep(string, grep_options) + end + + def log(count = 30) + Git::Log.new(self, count).object(@sha) + end + end diff --git a/lib/git/remote.rb b/lib/git/remote.rb new file mode 100644 index 0000000..6956d47 --- /dev/null +++ b/lib/git/remote.rb @@ -0,0 +1,21 @@ +module Git + class Remote < Path + + attr_accessor :name, :url, :fetch + + @base = nil + + def initialize(base, name) + @base = base + config = @base.lib.config_remote(name) + @name = name + @url = config['url'] + @fetch = config['fetch'] + end + + def to_s + @name + end + + end +end \ No newline at end of file -- cgit