git-hack 0.0.3 → 0.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README.md CHANGED
@@ -1,9 +1,9 @@
1
1
  # git-hack
2
2
 
3
- I don't known why logic of git is sooooo horrible!! And I make this tools for people to say "WOW,This is git !!!"
3
+ 目标是制作一个简单易用的git 工具
4
4
 
5
- 0. git-save git-redo git-undo git-backto They look easy to understand? Wow,This is git.
6
- 1.
5
+ 0. git-save git-redo git-undo git-backto They look easy to understand?
6
+ 1. remote comming son..
7
7
 
8
8
 
9
9
  ## Installing
@@ -14,12 +14,16 @@ All you need to do is grab the gem:
14
14
 
15
15
 
16
16
  ### save
17
+ git save "msg"
17
18
 
18
19
  ### undo
20
+ git undo # 回到上一个提交
19
21
 
20
22
  ### redo
23
+ git redo # 前进到下一个提交
21
24
 
22
25
  ### backto
26
+ git backto [number] # 跳到指定的提交
23
27
 
24
28
  ## Copyright
25
29
 
@@ -2,4 +2,4 @@
2
2
 
3
3
  require (File.expand_path('../../lib/git-hack', __FILE__))
4
4
 
5
- GitHack::GitRepo.new(".").git_goto(ARGV.first)
5
+ GitHack::GitRepo.new(".").goto(ARGV.first.to_i)
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require (File.expand_path('../../lib/git-hack', __FILE__))
4
+ require 'awesome_print'
5
+
6
+ GitHack::GitRepo.new(".").show_commits
@@ -6,7 +6,7 @@
6
6
  module Git
7
7
  class Lib
8
8
  def full_log_commits(opts = {})
9
- arr_opts = ['--pretty=raw']
9
+ arr_opts = ['--no-color --pretty=raw']
10
10
  arr_opts << "-#{opts[:count]}" if opts[:count]
11
11
  arr_opts << "--skip=#{opts[:skip]}" if opts[:skip]
12
12
  arr_opts << "--since=#{opts[:since]}" if opts[:since].is_a? String
@@ -1,15 +1,23 @@
1
- #
2
- # 把文本转化成对象的Build模式
3
- #
1
+ # Copyright @ weizhao 2012
2
+ # 把线性数据转化成对象的线性构造器
3
+ # 给定@data,@index就可以从 #object #all_object 方法中得到构造到的对象
4
+ # 一般需要重写 #process_line 行处理函数
5
+ # #out? 退出条件处理函数
4
6
  #
5
7
  class LineBuilder
6
- attr_accessor :data,:index,:object
8
+ attr_accessor :data,:index
7
9
  def initialize(data,index=0)
8
- @data = data
9
- @index = index
10
- @object = nil
11
- @is_parse = false
10
+ @data = data # 要处理的array数据
11
+ @index = index # 处理数据的位置,从0起
12
+ @data_size = data.size # 这个会经常调用
13
+ @object = nil # 保存要构造的对象,调用#parse后可以使用
14
+ @all_objects = nil # 保存所有能构造的对象, 调用#find_all后使用
15
+ @is_parse = false # 是否解析过的标志
12
16
  end
17
+
18
+ #
19
+ # parse 分析函数,最好不要重写,一般这可就可以了
20
+ #
13
21
  def parse
14
22
  @is_parse = true
15
23
  return nil if is_over?
@@ -19,37 +27,53 @@ class LineBuilder
19
27
  end until ( out? || is_over?)
20
28
  self
21
29
  end
30
+ #
22
31
  # 行处理函数,必须被重写
32
+ # 默认是读一行,把数据做为对象传给object
33
+ #
23
34
  def process_line
24
35
  line = @data[@index]
25
36
  @object = line
26
37
  end
38
+ def object
39
+ @object ||= parse.object
40
+ end
41
+ def all_objects
42
+ @all_objects ||= find_all.collect { |b| b.object }
43
+ end
44
+ #
27
45
  # 进入条件,默认直接进入
46
+ #
28
47
  def in?
29
48
  true
30
49
  end
50
+ #
31
51
  # 退出条件,默认为读完本行直接退出,重写要设置@index的新值
52
+ # 即线性构造器每次只取一行
53
+ #
32
54
  def out?
33
55
  @index += 1
34
56
  end
35
- # 是否数据结构
57
+ # 是否数据已经遍历结束
36
58
  def is_over?
37
- @index >= @data.size
59
+ @index >= @data_size
38
60
  end
61
+ # 得到下一个数据
62
+ # 运行两次不会得到下一个的下一个数据
39
63
  def get_next
40
64
  return nil if is_over?
41
65
  return self.class.new(@data,@index).parse
42
66
  end
43
- # 得出剩下的
67
+ # 得到剩下的数据
44
68
  def rest
45
69
  return [] if is_over?
46
70
  next_b = get_next
47
- return [next_b] + ( next_b.is_over? ? [] : next_b.rest)
71
+ return [next_b] + next_b.rest #( next_b.is_over? ? [] : next_b.rest)
48
72
  end
49
- # 找出全部的
73
+ # 为@data结构全部的数据
50
74
  def find_all
51
- return [] if is_over? && @object == nil
75
+ return [] if is_over? && @object == nil # 给定的index已经超出data
52
76
  parse unless @is_parse
53
- [self] + rest
77
+ @all_objects = [self] + rest
54
78
  end
55
79
  end
@@ -0,0 +1,13 @@
1
+ # 标记方法安全运行的模块
2
+ #
3
+ module SaveExecute
4
+ def ready_to_execute
5
+ @is_success = false
6
+ end
7
+ def execute_success
8
+ @is_success = true
9
+ end
10
+ def success?
11
+ @is_success
12
+ end
13
+ end
@@ -3,6 +3,8 @@ require "git"
3
3
  Dir["#{File.dirname(__FILE__)}/**/*.rb"].each { |f| require f }
4
4
 
5
5
  module GitHack
6
+ include PathCommon
7
+ include SaveExecute
6
8
  def self.current
7
9
  @current || get_dir('.')
8
10
  end
@@ -1,10 +1,18 @@
1
-
1
+ # Commit类对应git当中的提交对象
2
2
  require_relative "../git-hack"
3
3
 
4
4
 
5
5
  module GitHack
6
6
  class Commit
7
- attr_accessor :message,:sha
7
+ attr_accessor :message,:sha,:parent,:tree,:author,:committer
8
+ def initialize(hash)
9
+ @sha = hash['sha']
10
+ @message = hash['message']
11
+ @parent = hash['parent']
12
+ @tree = hash['tree']
13
+ @author = hash['author']
14
+ @committer = hash['committer']
15
+ end
8
16
  end
9
17
  end
10
18
 
@@ -0,0 +1,50 @@
1
+ # CommitFacade 类提供一个对外的git commit的接口
2
+ #
3
+ require_relative "commit_line_builder"
4
+ require_relative "simple_line_builder"
5
+
6
+ module GitHack
7
+ class CommitFacade
8
+ def initialize(dir)
9
+ @dir = dir
10
+ @commits = []
11
+ end
12
+ # 从log中取得当前commit之前的Commits
13
+ #
14
+ def get_log_commits
15
+ git = Git.open(@dir ,:log => Logger.new(STDOUT))
16
+ l = Git::Lib.new(git)
17
+ opts = ["--pretty=raw"]
18
+ data = l.command_lines_patch('log',opts)
19
+ return @commits = CommitLineBuilder.new(data,0).all_objects
20
+ end
21
+ def get_next_commit
22
+ file = File.open("#{@dir}/.git/logs/HEAD")
23
+ data = []
24
+ file.each { |line|
25
+ data << line
26
+ }
27
+ commit_data = SimpleLineBuilder.new(data,0).find_all
28
+ commit = commit_data.find do |c|
29
+ c.object == current_commit
30
+ end
31
+ commit_sha = commit ? commit.value : nil
32
+ end
33
+ def current_commit
34
+ @current_commit if @current_commit
35
+ data = data_from_file("#{@dir}/.git/HEAD")
36
+ commit_file_data = SimpleLineBuilder.new(data,0).parse
37
+ commit_file = commit_file_data.value
38
+ @current_commit = data_from_file("#{@dir}/.git/#{commit_file}")
39
+ @current_commit = @current_commit[0].chomp
40
+ end
41
+ def data_from_file(path)
42
+ file = File.open(path)
43
+ data = []
44
+ file.each { |line|
45
+ data << line
46
+ }
47
+ data
48
+ end
49
+ end
50
+ end
@@ -1,11 +1,19 @@
1
-
1
+ # CommitLineBuilder类用于得到库内的提交信息
2
+ # 现阶段从git log命令得到主数据
2
3
  require_relative "../core_ext/line_builder"
4
+
5
+ # git log 数据可能被加色,本补丁删除加色信息
3
6
  class String
4
7
  def uncolorize
5
- self.gsub(/\e\[(\d+)*m/,"")
8
+ # BUG: 在bin/git* 下运行可以去掉,但是安装gem 后就不能了????
9
+ self.gsub(/\e\[(\d+)*m/,"") # 以除 \e[30e] 颜色标记
10
+ end
11
+ end
12
+ class Hash
13
+ def to_class(new_class)
14
+ return new_class.new(self)
6
15
  end
7
16
  end
8
-
9
17
 
10
18
  module GitHack
11
19
  class CommitLineBuilder < LineBuilder
@@ -16,40 +24,40 @@ module GitHack
16
24
  @commit = { 'sha'=>nil, 'message' => '', 'parent' => [] }
17
25
  @is_next_commit = false
18
26
  end
27
+ # 重写#process_line
19
28
  def process_line
20
- @is_message
21
- line = @data[@index]
22
- line = line.chomp.uncolorize
23
- if line == ""
29
+ line = @data[@index].chomp.uncolorize
30
+ if line == "" # msg信息以上下两个"" 分隔
24
31
  @is_message = !@is_message
25
32
  elsif @is_message
26
33
  @commit['message'] << line+"\n"
27
34
  else
28
- data = line.split
29
- @key = key = data.shift
30
- @value = data.join(" ")
35
+ line_to_commit(line)
36
+ end
37
+ @object = @commit.to_class(Commit)
38
+ end
39
+ # 将每行的数据信息转换成Commit的信息
40
+ def line_to_commit(line)
41
+ data = line.split
42
+ key = data.shift
43
+ value = data.join(" ")
31
44
 
32
- if @key == "commit"
33
- if @commit['sha']
34
- @is_next_commit = true
35
- else
36
- @commit['sha'] = @value
37
- end
38
- elsif @key == 'parent'
39
- @commit[@key] << @value
45
+ if key == "commit"
46
+ if @commit['sha'] # key第二次是commit时 设置是否下条信息的标志,见 #out?
47
+ @is_next_commit = true
40
48
  else
41
- @commit[@key] = @value
49
+ @commit['sha'] = value
42
50
  end
51
+ elsif key == 'parent'
52
+ @commit[key] << value
53
+ else
54
+ @commit[key] = value
43
55
  end
44
- @object = @commit
45
56
  end
46
57
  def out?
47
- if @is_next_commit
48
- return true
49
- else
50
- @index += 1
51
- return false
52
- end
58
+ # 如果已经到下一条commit,则为结束标志,并指针并不再移动
59
+ @index += 1 unless @is_next_commit
60
+ return @is_next_commit
53
61
  end
54
62
  end
55
63
  end
@@ -3,7 +3,9 @@ require 'logger'
3
3
  require 'colorize'
4
4
  require "ap"
5
5
 
6
+ require_relative "../git-hack"
6
7
  require_relative "../core_ext/path"
8
+ require_relative "../core_ext/save_execute"
7
9
 
8
10
  module GitHack
9
11
  # GitRepo类拥有git的所有
@@ -11,34 +13,38 @@ module GitHack
11
13
  # work,即工作目录及文件 GitHack::WorkingDirectory类
12
14
  # remote,对应远程库信息 GitHack::Remote类
13
15
  #
16
+ # 对外操作的函数:
17
+ # # init(dir)
18
+ # # goto(number)
19
+ # # redo
20
+ # # undo
21
+ #
14
22
  class GitRepo < Git::Path
15
23
  include PathCommon
24
+ include SaveExecute
25
+
16
26
  attr_accessor :git,:commits,:work,:remote,:current_commit
27
+
17
28
  def initialize(path)
18
29
  @workingdirectory = get_gitdir(path)
19
- @commits = []
30
+ @git = nil
31
+ @commits = nil
32
+ @commit_facade = nil
20
33
  end
34
+
35
+ # 属性函数
21
36
  def git
22
37
  @git ||= Git.open(@workingdirectory ,:log => Logger.new(STDOUT))
23
38
  end
24
- def commits
25
- return @commits if !@commits.empty?
26
- l = Git::Lib.new(git)
27
- opts = ["--pretty=raw"]
28
- @data = l.command_lines_patch('log',opts)
29
- return @commits = CommitLineBuilder.new(@data,0).find_all
30
- end
31
- # 得到本身或是上层目录中.git文件的路经
32
- def get_gitdir(path)
33
- git_path = absolute_path(path)
34
- return nil if git_path == "/"
35
- return git_path if is_gitdir?(git_path)
36
- return get_gitdir(join(git_path,"/../"))
39
+ def commit_facade
40
+ @commit_facade ||= CommitFacade.new(@workingdirectory)
37
41
  end
38
- def is_gitdir?(path)
39
- File.directory?(join(path,".git")) ? true : false
42
+ def commits
43
+ @commits ||= commit_facade.get_log_commits
40
44
  end
45
+ #
41
46
  # 把工作目录的文件添加到git仓库并提交
47
+ #
42
48
  def git_save(msg,options={})
43
49
  ready_to_execute
44
50
  return self if not_git_directory?
@@ -47,61 +53,50 @@ module GitHack
47
53
  execute_success
48
54
  self
49
55
  end
50
- def ready_to_execute
51
- @is_success = false
52
- end
53
- def execute_success
54
- @is_success = true
55
- end
56
- def success?
57
- @is_success
58
- end
59
- def add_workingdirectory
60
- git.add(@workingdirectory)
61
- end
62
- def commit(msg)
63
- msg ||= auto_commit_msg
64
- begin
65
- git.commit(msg,:add_all=>true)
66
- rescue Git::GitExecuteError => e
67
- puts e.to_s.colorize(:green)
68
- end
69
- end
70
- def auto_commit_msg
71
- "auto commit" # TODO: 需要完成
72
- end
56
+
73
57
  # undo 回到上一次提交
74
58
  def undo
75
- git_goto(1)
59
+ goto(1)
76
60
  end
77
61
  # redo 到当前提交的下一个提交
78
62
  def redo
79
63
  ready_to_execute
80
64
  return self if not_git_directory?
81
- next_commit = get_next_commit
65
+ next_commit = commit_facade.get_next_commit
82
66
  return self if !next_commit
83
67
  git.reset_hard(next_commit)
84
68
  execute_success
85
69
  self
86
70
  end
87
- def git_goto(number,options={})
88
- number = number.to_i
89
- goto(number,options)
90
-
91
- end
92
71
  # 回到前第number个保存
93
72
  #
94
73
  def goto(number,options={})
95
74
  ready_to_execute
96
75
  return self if not_git_directory?
97
- git.reset_hard(commits[number].commit['sha'])
76
+ ap commits
77
+ git.reset_hard(commits[number].sha)
98
78
  execute_success
99
79
  self
100
80
  end
81
+ # 初始化空文件夹成为git库
101
82
  def init(dir)
102
83
  @git = Git.init(dir)
103
84
  @workingdirectory = dir
104
85
  end
86
+ def show_commits
87
+ ap commits
88
+ end
89
+ #
90
+ # 得到本身或是上层目录中.git文件的路经
91
+ #
92
+ def get_gitdir(path)
93
+ git_path = absolute_path(path)
94
+ return nil if git_path == "/"
95
+ return git_path if is_gitdir?(git_path)
96
+ return get_gitdir(join(git_path,"/../"))
97
+ end
98
+
99
+ private
105
100
  def not_git_directory?
106
101
  if @workingdirectory == nil
107
102
  puts "Not a git directory ,run `git init` first"
@@ -109,33 +104,23 @@ module GitHack
109
104
  end
110
105
  return false
111
106
  end
112
- def get_next_commit
113
- file = File.open("#{@workingdirectory}/.git/logs/HEAD")
114
- data = []
115
- file.each { |line|
116
- data << line
117
- }
118
- commit_data = SimpleLineBuilder.new(data,0).find_all
119
- commit = commit_data.find do |c|
120
- c.object == current_commit
107
+ def is_gitdir?(path)
108
+ File.directory?(join(path,".git")) ? true : false
109
+ end
110
+
111
+ def add_workingdirectory
112
+ git.add(@workingdirectory)
113
+ end
114
+ def commit(msg)
115
+ msg ||= auto_commit_msg
116
+ begin
117
+ git.commit(msg,:add_all=>true)
118
+ rescue Git::GitExecuteError => e
119
+ puts e.to_s.colorize(:green)
121
120
  end
122
- commit_sha = commit ? commit.value : nil
123
- end
124
- def current_commit
125
- @current_commit if @current_commit
126
- data = data_from_file("#{@workingdirectory}/.git/HEAD")
127
- commit_file_data = SimpleLineBuilder.new(data,0).parse
128
- commit_file = commit_file_data.value
129
- @current_commit = data_from_file("#{@workingdirectory}/.git/#{commit_file}")
130
- @current_commit = @current_commit[0].chomp
131
- end
132
- def data_from_file(path)
133
- file = File.open(path)
134
- data = []
135
- file.each { |line|
136
- data << line
137
- }
138
- data
121
+ end
122
+ def auto_commit_msg
123
+ "auto commit" # TODO: 需要完成
139
124
  end
140
125
  end
141
126
  end
@@ -8,8 +8,7 @@ module GitHack
8
8
  super(data,index)
9
9
  end
10
10
  def process_line
11
- line = @data[@index]
12
- line = line.chomp.split
11
+ line = @data[@index].chomp.split
13
12
  @object = line.shift
14
13
  @value = line.shift
15
14
  end
@@ -1,3 +1,3 @@
1
1
  module GitHack
2
- VERSION = "0.0.3"
2
+ VERSION = "0.0.5"
3
3
  end
@@ -0,0 +1,31 @@
1
+ require "spec_helper"
2
+
3
+ describe CommitFacade do
4
+ before do
5
+ @dir = dir_under_git
6
+ refresh_dir(@dir)
7
+ Git.init(@dir)
8
+ @gitrepo = GitRepo.new(@dir)
9
+ @gitrepo.get_gitdir(@dir)
10
+ @msg = "test commit "
11
+ add_for_commit("#{@dir}/test")
12
+ @gitrepo.git_save(@msg)
13
+ add_for_commit("#{@dir}/test2")
14
+ @gitrepo.git_save(@msg)
15
+ @cf = CommitFacade.new(@dir)
16
+ end
17
+ describe "# get_log_commits " do
18
+ context "When given dir " do
19
+ it "Should return commits frome log. " do
20
+ @cf.get_log_commits.length.should be 2
21
+ end
22
+ it "Show data" do
23
+ #ap @cf.get_log_commits
24
+ #ap @cf.get_log_commits[0]
25
+ end
26
+
27
+ end
28
+
29
+ end
30
+ after { del_dir(@dir) }
31
+ end
@@ -5,11 +5,6 @@ require "spec_helper"
5
5
 
6
6
 
7
7
  describe GitRepo do
8
- # test data
9
- let(:dir_with_git) { project_dir }
10
- let(:dir_under_git) { join(project_dir,"tmp_git_hack_test") }
11
- let(:dir_no_git) { "#{ENV["HOME"]}/tmp_git_hack_test" }
12
-
13
8
  describe "#get_gitdir " do
14
9
  context "When given a .git directory" do
15
10
  specify { GitRepo.new(dir_with_git).get_gitdir(dir_with_git).should == dir_with_git }
@@ -12,14 +12,16 @@ describe LineBuilder do
12
12
  end
13
13
  specify { @data.size.should be > 1 }
14
14
  specify { @linebuilder.object.should_not be nil }
15
+ specify { @linebuilder.all_objects.size.should be > 0 }
15
16
  specify { @linebuilder.is_over?.should_not be true }
16
17
  specify { @linebuilder.get_next.should_not be nil }
17
18
  specify { @linebuilder.rest.size.should be > 0 }
18
19
  specify { @linebuilder.find_all.size.should be > 0 }
20
+ specify { @linebuilder.data.should be @linebuilder.get_next.data }
21
+ # 用于查看内部数据的查看spec
19
22
  it "Show Some data" do
20
23
  puts @linebuilder.index
21
24
  puts @data.size
22
-
23
25
  end
24
26
  context "When is come to the last" do
25
27
  before do
@@ -1,7 +1,9 @@
1
1
  require_relative "../lib/git-hack"
2
+ require_relative "test_env"
2
3
 
3
4
  include GitHack
4
5
  include PathCommon
6
+ include TestENV
5
7
  require "fileutils"
6
8
  require "colorize"
7
9
 
@@ -0,0 +1,15 @@
1
+ # 为测试准备环境用的一些方法
2
+ module TestENV
3
+ def dir_with_git
4
+ project_dir
5
+ end
6
+ def dir_under_git
7
+ join(project_dir,"tmp_git_hack_test")
8
+ end
9
+ def dir_no_git
10
+ "#{ENV["HOME"]}/tmp_git_hack_test"
11
+ end
12
+ end
13
+
14
+
15
+
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: git-hack
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.5
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-02-24 00:00:00.000000000 Z
12
+ date: 2012-02-27 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: colorize
16
- requirement: &22140160 !ruby/object:Gem::Requirement
16
+ requirement: &10189420 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *22140160
24
+ version_requirements: *10189420
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: git
27
- requirement: &22139340 !ruby/object:Gem::Requirement
27
+ requirement: &10188960 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,12 +32,13 @@ dependencies:
32
32
  version: '0'
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *22139340
35
+ version_requirements: *10188960
36
36
  description: A more smart tools of git. Come from git-smart
37
37
  email:
38
38
  - azhao.1981@gmail.com
39
39
  executables:
40
40
  - git-goto
41
+ - git-minilog
41
42
  - git-redo
42
43
  - git-save
43
44
  - git-undo
@@ -50,6 +51,7 @@ files:
50
51
  - README.md
51
52
  - Rakefile
52
53
  - bin/git-goto
54
+ - bin/git-minilog
53
55
  - bin/git-redo
54
56
  - bin/git-save
55
57
  - bin/git-undo
@@ -58,16 +60,20 @@ files:
58
60
  - lib/core_ext/git_patch.rb
59
61
  - lib/core_ext/line_builder.rb
60
62
  - lib/core_ext/path.rb
63
+ - lib/core_ext/save_execute.rb
61
64
  - lib/git-hack.rb
62
65
  - lib/git-hack/commit.rb
66
+ - lib/git-hack/commit_facade.rb
63
67
  - lib/git-hack/commit_line_builder.rb
64
68
  - lib/git-hack/git_repo.rb
65
69
  - lib/git-hack/simple_line_builder.rb
66
70
  - lib/git-hack/version.rb
71
+ - spec/commit_facade_spec.rb
67
72
  - spec/commit_line_builder_spec.rb
68
73
  - spec/git_repo_spec.rb
69
74
  - spec/line_builder_spec.rb
70
75
  - spec/spec_helper.rb
76
+ - spec/test_env.rb
71
77
  - spec/tmp/hello_for_rspec
72
78
  - tmp/classtest.rb
73
79
  - tmp/cli.rb