From a1237671ba3ec38f5b123ee6600e4352dc03196b Mon Sep 17 00:00:00 2001 From: scott Chacon Date: Sun, 11 Nov 2007 10:04:26 -0800 Subject: git add working, git status object working --- lib/git.rb | 1 + lib/git/base.rb | 12 ++++++- lib/git/lib.rb | 97 ++++++++++++++++++++++++++++++++++++++------------ lib/git/status.rb | 103 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 189 insertions(+), 24 deletions(-) create mode 100644 lib/git/status.rb (limited to 'lib') diff --git a/lib/git.rb b/lib/git.rb index bb68388..cfcbc8c 100644 --- a/lib/git.rb +++ b/lib/git.rb @@ -20,6 +20,7 @@ require 'git/branch' require 'git/remote' require 'git/diff' +require 'git/status' =begin require 'git/author' require 'git/file' diff --git a/lib/git/base.rb b/lib/git/base.rb index 00495c7..eded12d 100644 --- a/lib/git/base.rb +++ b/lib/git/base.rb @@ -92,6 +92,7 @@ module Git def config(name = nil, value = nil) if(name && value) # set value + lib.config_set(name, value) elsif (name) # return value lib.config_get(name) @@ -114,7 +115,11 @@ module Git def log(count = 30) Git::Log.new(self, count) end - + + def status + Git::Status.new(self) + end + def branches Git::Branches.new(self) end @@ -131,6 +136,11 @@ module Git Git::Diff.new(self, objectish, obj2) end + # adds files from the working directory to the git repository + def add(path = '.') + self.lib.add(path) + end + # convenience methods def revparse(objectish) diff --git a/lib/git/lib.rb b/lib/git/lib.rb index 9fa3986..ec65e55 100644 --- a/lib/git/lib.rb +++ b/lib/git/lib.rb @@ -52,6 +52,10 @@ module Git opts[:bare] ? {:repository => clone_dir} : {:working_directory => clone_dir} end + + ## READ COMMANDS ## + + def log_commits(opts = {}) arr_opts = ['--pretty=oneline'] arr_opts << "-#{opts[:count]}" if opts[:count] @@ -89,28 +93,6 @@ module Git 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| - (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]] @@ -161,10 +143,78 @@ module Git hsh end + + # compares the index and the working directory + def diff_files + hsh = {} + command_lines('diff-files').each do |line| + (info, file) = line.split("\t") + (mode_src, mode_dest, sha_src, sha_dest, type) = info.split + hsh[file] = {:path => file, :mode_file => mode_src, :mode_index => mode_dest, + :sha_file => sha_src, :sha_index => sha_dest, :type => type} + end + hsh + end + + # compares the index and the repository + def diff_index(treeish) + hsh = {} + command_lines('diff-index', treeish).each do |line| + (info, file) = line.split("\t") + (mode_src, mode_dest, sha_src, sha_dest, type) = info.split + hsh[file] = {:path => file, :mode_repo => mode_src, :mode_index => mode_dest, + :sha_repo => sha_src, :sha_index => sha_dest, :type => type} + end + hsh + end + + def ls_files + hsh = {} + command_lines('ls-files', '--stage').each do |line| + (info, file) = line.split("\t") + (mode, sha, stage) = info.split + hsh[file] = {:path => file, :mode_index => mode, :sha_index => sha, :stage => stage} + end + hsh + 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 + + 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 + + ## WRITE COMMANDS ## + + def config_set(name, value) + command('config', [name, "'#{value}'"]) + end + + def add(path = '.') + command('add', path) + end + private - def command_lines(cmd, opts) + def command_lines(cmd, opts = {}) command(cmd, opts).split("\n") end @@ -177,6 +227,7 @@ module Git #puts "git #{cmd} #{opts}" out = `git #{cmd} #{opts} 2>&1`.chomp #puts out + #puts if $?.exitstatus > 1 raise Git::GitExecuteError.new(out) end diff --git a/lib/git/status.rb b/lib/git/status.rb new file mode 100644 index 0000000..24fd98d --- /dev/null +++ b/lib/git/status.rb @@ -0,0 +1,103 @@ +module Git + + class Status + include Enumerable + + @base = nil + @files = nil + + def initialize(base) + @base = base + construct_status + end + + def changed + @files.select { |k, f| f.type == 'M' } + end + + def added + @files.select { |k, f| f.type == 'A' } + end + + def untracked + @files.select { |k, f| f.untracked } + end + + def pretty + out = '' + self.each do |file| + out << file.path + out << "\n\tsha(r) " + file.sha_repo.to_s + out << "\n\tsha(i) " + file.sha_index.to_s + out << "\n\ttype " + file.type.to_s + out << "\n\tstage " + file.stage.to_s + out << "\n\tuntrac " + file.untracked.to_s + out << "\n" + end + out << "\n" + out + end + + # enumerable method + + def [](file) + @files[file] + end + + def each + @files.each do |k, file| + yield file + end + end + + class StatusFile + attr_accessor :path, :type, :stage, :untracked + attr_accessor :mode_index, :mode_repo + attr_accessor :sha_index, :sha_repo + + def initialize(hash) + @path = hash[:path] + @type = hash[:type] + @stage = hash[:stage] + @mode_index = hash[:mode_index] + @mode_repo = hash[:mode_repo] + @sha_index = hash[:sha_index] + @sha_repo = hash[:sha_repo] + @untracked = hash[:untracked] + end + + + end + + private + + def construct_status + @files = @base.lib.ls_files + + # find untracked in working dir + Dir.chdir(@base.dir.path) do + Dir.glob('**/*') do |file| + if !@files[file] + @files[file] = {:path => file, :untracked => true} if !File.directory?(file) + end + end + end + + # find modified in tree + @base.lib.diff_files.each do |path, data| + @files[path].merge!(data) + end + + # find added but not committed - new files + @base.lib.diff_index('HEAD').each do |path, data| + @files[path].merge!(data) + end + + @files.each do |k, file_hash| + @files[k] = StatusFile.new(file_hash) + end + end + + end + +end \ No newline at end of file -- cgit