git-hack 0.0.3 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
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