cbt 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +221 -0
- data/ROADMAP +33 -0
- data/Rakefile +3 -0
- data/bin/cbt +130 -0
- data/cbt.gemspec +19 -0
- data/config/components.yml +20 -0
- data/config/members.yml +16 -0
- data/docs/css/jsgantt.css +53 -0
- data/docs/gantt.html +330 -0
- data/docs/js/jsgantt.js +1681 -0
- data/examples/config/components.yml +19 -0
- data/lib/cbt.rb +13 -0
- data/lib/cbt/app.rb +93 -0
- data/lib/cbt/checkout.rb +155 -0
- data/lib/cbt/cleanup.rb +7 -0
- data/lib/cbt/component.rb +91 -0
- data/lib/cbt/creator.rb +75 -0
- data/lib/cbt/diagram.rb +50 -0
- data/lib/cbt/digester.rb +59 -0
- data/lib/cbt/girc.rb +169 -0
- data/lib/cbt/version.rb +3 -0
- data/lib/luobo/cbt.rb +25 -0
- data/lib/luobo/lua.rb +3 -0
- data/lib/luobo/settings.rb +4 -0
- data/lib/luobo/spec.rb +4 -0
- data/spec/app_spec.rb +49 -0
- data/spec/creator_spec.rb +39 -0
- data/spec/digester_spec.rb +55 -0
- data/spec/spec_helper.rb +8 -0
- data/templates/Class.lua.erb +18 -0
- data/templates/Class.mock.lua.erb +20 -0
- data/templates/Class_with_super.lua.erb +22 -0
- data/templates/Class_with_super.mock.lua.erb +23 -0
- data/templates/main.lua.erb +2 -0
- data/templates/part.lua.erb +9 -0
- data/templates/part.mock.lua.erb +11 -0
- data/templates/part_with_super.lua.erb +13 -0
- data/templates/part_with_super.mock.lua.erb +13 -0
- data/templates/spec.lua.erb +3 -0
- metadata +143 -0
data/lib/cbt/diagram.rb
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'rviz'
|
2
|
+
|
3
|
+
module Cbt
|
4
|
+
class Diagram < App
|
5
|
+
|
6
|
+
def process!
|
7
|
+
g = Rviz::Graph.new
|
8
|
+
g.set('dpi', '300')
|
9
|
+
g.set('rankdir', 'LR')
|
10
|
+
|
11
|
+
# for each components, create a node of graphviz
|
12
|
+
@components.each do |cname, c|
|
13
|
+
if @options[:tag] and @options[:tag].size > 0
|
14
|
+
next unless @options[:tag].include? c.tag
|
15
|
+
end
|
16
|
+
|
17
|
+
# parse source file, add relationship
|
18
|
+
c.modules.each do |mname, m|
|
19
|
+
rec_name = m.name
|
20
|
+
attrs = self.tags(c.tag)
|
21
|
+
g.add_record(rec_name, attrs)
|
22
|
+
g.node(rec_name).add_row(cname + '/' + m.name, true)
|
23
|
+
g.add_edge(rec_name, 'f1', m.super_class, nil, {label: 'inherit', arrowhead: "odiamond"}) if m.super_class
|
24
|
+
|
25
|
+
# parse the file
|
26
|
+
comp_dir = c.dir(@options[:components_dir])
|
27
|
+
lua_file = m.path([comp_dir], 'debug')
|
28
|
+
File.open(lua_file).each do |line|
|
29
|
+
next if line =~ /no_erd/
|
30
|
+
line.chomp!
|
31
|
+
if /function\s#{m.name}\:/ =~ line
|
32
|
+
func = line.gsub(/^.*function\s#{m.name}\:/, '')
|
33
|
+
func.gsub!(/#.*$/, '')
|
34
|
+
g.node(rec_name).add_row('+' + func, false)
|
35
|
+
end
|
36
|
+
|
37
|
+
if /diagram\s*\-\>\s*/ =~ line
|
38
|
+
link_to = line.gsub(/^.*diagram\s*\-\>\s*/, '')
|
39
|
+
tgt, label = link_to.split(/\s+/, 2)
|
40
|
+
g.add_edge(rec_name, 'f1', tgt, nil, {label: label})
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
g.output
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
end
|
data/lib/cbt/digester.rb
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require 'yaml/store'
|
3
|
+
require 'digest/md5'
|
4
|
+
|
5
|
+
module Cbt
|
6
|
+
class Digester
|
7
|
+
|
8
|
+
# initialize from the configuration
|
9
|
+
def initialize store_file
|
10
|
+
@store_file = store_file
|
11
|
+
@store = YAML::Store.new @store_file
|
12
|
+
end
|
13
|
+
|
14
|
+
def file_digest file
|
15
|
+
return "" unless File.exists? file
|
16
|
+
d = Digest::MD5.hexdigest(File.read(file))
|
17
|
+
end
|
18
|
+
|
19
|
+
# add file copy history
|
20
|
+
def add_history file, digest = nil
|
21
|
+
digest = file_digest file unless digest
|
22
|
+
@store.transaction do
|
23
|
+
@store[file] = Array.new unless @store[file]
|
24
|
+
@store[file] << {
|
25
|
+
'datetime' => DateTime.now.strftime("%F %T"),
|
26
|
+
'digest' => digest
|
27
|
+
}
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# return 'datetime' => '', 'digest' => '' or nil for no store
|
32
|
+
def last_change file
|
33
|
+
@store.transaction do
|
34
|
+
@store[file][-1] if @store[file]
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# if the digest is different from last time
|
39
|
+
def changed? file, digest = nil
|
40
|
+
digest = file_digest file unless digest
|
41
|
+
@store.transaction do
|
42
|
+
not (@store[file] and @store[file][-1] and @store[file][-1]['digest'] == digest)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# if the current digest exists in file store
|
47
|
+
def known? file, digest = nil
|
48
|
+
digest = file_digest file unless digest
|
49
|
+
@store.transaction do
|
50
|
+
return false unless @store[file]
|
51
|
+
@store[file].each do |h|
|
52
|
+
return true if h['digest'] == digest
|
53
|
+
end
|
54
|
+
end
|
55
|
+
false
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
end
|
data/lib/cbt/girc.rb
ADDED
@@ -0,0 +1,169 @@
|
|
1
|
+
module Cbt
|
2
|
+
class Girc
|
3
|
+
attr_accessor :git
|
4
|
+
|
5
|
+
def initialize cmd = 'git', v = true
|
6
|
+
@git = cmd
|
7
|
+
@v = v
|
8
|
+
end
|
9
|
+
|
10
|
+
def info msg
|
11
|
+
return unless @v
|
12
|
+
puts "[GITC] #{msg}" if msg.size > 0
|
13
|
+
end
|
14
|
+
|
15
|
+
# general informations
|
16
|
+
# -----------------------
|
17
|
+
# return modified files (without additions/deletions)
|
18
|
+
def modified_files
|
19
|
+
files = Array.new
|
20
|
+
`#{@git} status`.split("\n").each do |line|
|
21
|
+
if /modified\:\s+(?<file_>.+)/ =~ line
|
22
|
+
files << File.expand_path(file_)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
files
|
26
|
+
end
|
27
|
+
|
28
|
+
# return config list as a hash
|
29
|
+
def config
|
30
|
+
h = Hash.new
|
31
|
+
`#{@git} config --list`.split("\n").each do |line|
|
32
|
+
key, value = line.split("=")
|
33
|
+
h[key] = value
|
34
|
+
end
|
35
|
+
h
|
36
|
+
end
|
37
|
+
|
38
|
+
# return the value of user.name in configuration
|
39
|
+
def me
|
40
|
+
config["user.name"] || "?"
|
41
|
+
end
|
42
|
+
|
43
|
+
# all branches include remote branches
|
44
|
+
def branches
|
45
|
+
branch_list = Array.new
|
46
|
+
`#{@git} branch -a`.split("\n").each do |line|
|
47
|
+
line.gsub!('* ', '')
|
48
|
+
line.gsub!(/\s/, '')
|
49
|
+
branch_list << line unless branch_list.include? line
|
50
|
+
end
|
51
|
+
branch_list
|
52
|
+
end
|
53
|
+
|
54
|
+
# the branch currently working on
|
55
|
+
def current_branch
|
56
|
+
`#{@git} branch`.split("\n").each do |line|
|
57
|
+
if /\*/.match line
|
58
|
+
return line.gsub('* ', '')
|
59
|
+
end
|
60
|
+
end
|
61
|
+
nil
|
62
|
+
end
|
63
|
+
|
64
|
+
def remote_list
|
65
|
+
lst = Array.new
|
66
|
+
`#{@git} remote -v`.split("\n").each do |line|
|
67
|
+
rn = line.split(/\s+/)[0]
|
68
|
+
lst << rn unless lst.include? rn
|
69
|
+
end
|
70
|
+
lst
|
71
|
+
end
|
72
|
+
|
73
|
+
# is the working directory has modified file
|
74
|
+
def wd_clean?
|
75
|
+
clean = true
|
76
|
+
`#{@git} status`.split("\n").each do |line|
|
77
|
+
clean = false if /Changes/.match line
|
78
|
+
end
|
79
|
+
clean
|
80
|
+
end
|
81
|
+
|
82
|
+
# whether the current directory is a git working directory
|
83
|
+
def in_git_dir?
|
84
|
+
`#{@git} status` =~ /fatal/ ? false : true
|
85
|
+
end
|
86
|
+
|
87
|
+
# modifications
|
88
|
+
# --------------------
|
89
|
+
|
90
|
+
# pull from the remote use fetch/merge
|
91
|
+
def pull! remote = 'origin'
|
92
|
+
cb = self.current_branch
|
93
|
+
info "Fetch from #{remote}"
|
94
|
+
rslt = `#{@git} fetch #{remote}`
|
95
|
+
raise "fetch failed with message: #{rslt}" unless $?.success?
|
96
|
+
info rslt
|
97
|
+
info `#{@git} merge #{remote}/#{cb}`
|
98
|
+
end
|
99
|
+
|
100
|
+
# create a new branch, if remote set, push it to remote too
|
101
|
+
# then switch to that branch
|
102
|
+
def new_branch! branch, remote=nil
|
103
|
+
raise "You need clean up you working directory" unless wd_clean?
|
104
|
+
raise "Branch #{branch} already exists" if self.branches.include? branch
|
105
|
+
`#{@git} checkout -b #{branch}`
|
106
|
+
`#{@git} push #{remote} #{branch}` if remote
|
107
|
+
end
|
108
|
+
|
109
|
+
# delete a branch
|
110
|
+
def del_branch! branch, remote=nil
|
111
|
+
rslt = `#{@git} branch -d #{branch}`
|
112
|
+
raise "Cat not delete branch #{branch}: #{rslt}" unless $?.success?
|
113
|
+
`#{@git} push #{remote} :#{branch}` if remote
|
114
|
+
end
|
115
|
+
|
116
|
+
def stash!
|
117
|
+
unless wd_clean?
|
118
|
+
info "Stash your local changes"
|
119
|
+
`#{@git} add .`
|
120
|
+
`#{@git} stash`
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
def stash_pop!
|
125
|
+
raise "You may clean up you work directroy first before pop out from the stash" unless wd_clean?
|
126
|
+
info "Pop out from you last stash"
|
127
|
+
`#{@git} stash pop`
|
128
|
+
end
|
129
|
+
|
130
|
+
# remote from a specified remote ref
|
131
|
+
def rebase! remote = 'origin', branch = 'develop'
|
132
|
+
cb = self.current_branch
|
133
|
+
stashed = false
|
134
|
+
|
135
|
+
unless self.wd_clean?
|
136
|
+
self.stash!
|
137
|
+
stashed = true
|
138
|
+
end
|
139
|
+
|
140
|
+
if branch == self.current_branch
|
141
|
+
info "Pull from remote"
|
142
|
+
# `#{@git} pull --rebase #{remote} #{branch}`
|
143
|
+
`#{@git} pull #{remote} #{branch}`
|
144
|
+
else
|
145
|
+
info "Switch to branch #{branch}"
|
146
|
+
`#{@git} fetch #{remote}`
|
147
|
+
rslt = `#{@git} checkout #{branch}`
|
148
|
+
raise "Checkout failed: #{rslt}" unless $?.success?
|
149
|
+
|
150
|
+
info "Update branch from remote"
|
151
|
+
# rslt = `#{@git} pull --rebase #{remote} #{branch}`
|
152
|
+
rslt = `#{@git} pull #{remote} #{branch}`
|
153
|
+
raise "Pull for #{branch} failed: #{rslt}" unless $?.success?
|
154
|
+
|
155
|
+
info "Switch back to branch #{cb}"
|
156
|
+
`#{@git} checkout #{cb}`
|
157
|
+
info "Merge from #{branch}"
|
158
|
+
rslt = `#{@git} merge #{branch}`
|
159
|
+
raise "Merge with #{branch} failed: #{rslt}" unless $?.success?
|
160
|
+
|
161
|
+
info "pull branch #{self.current_branch} from remote"
|
162
|
+
`#{@git} pull #{remote} #{self.current_branch}`
|
163
|
+
end
|
164
|
+
|
165
|
+
self.stash_pop! if stashed
|
166
|
+
end
|
167
|
+
|
168
|
+
end
|
169
|
+
end
|
data/lib/cbt/version.rb
ADDED
data/lib/luobo/cbt.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'luobo'
|
2
|
+
|
3
|
+
class CbtLuobo < Luobo
|
4
|
+
attr_accessor :platform
|
5
|
+
|
6
|
+
def self.cp! s, t, p
|
7
|
+
k = self.new s, t
|
8
|
+
k.platform = p
|
9
|
+
k.process!
|
10
|
+
end
|
11
|
+
|
12
|
+
def do__platform token
|
13
|
+
str = ''
|
14
|
+
token.blocks.each do |line|
|
15
|
+
line.gsub!(/^\s\s?/, '')
|
16
|
+
str += token.indent + line + "\n"
|
17
|
+
end
|
18
|
+
str
|
19
|
+
end
|
20
|
+
|
21
|
+
def do_ios token
|
22
|
+
do__platform token if @platform == 'ios'
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
data/lib/luobo/lua.rb
ADDED
data/lib/luobo/spec.rb
ADDED
data/spec/app_spec.rb
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
class GircMock
|
4
|
+
attr_accessor :current_branch
|
5
|
+
def in_git_dir?; true end
|
6
|
+
end
|
7
|
+
|
8
|
+
describe Cbt::App do
|
9
|
+
|
10
|
+
describe "#initialize" do
|
11
|
+
subject(:app) do
|
12
|
+
Cbt::App.new(config_file: "examples/config/components.yml")
|
13
|
+
end
|
14
|
+
|
15
|
+
it "parses two components in the list" do
|
16
|
+
app.components.keys.size.should eq(3)
|
17
|
+
app.components.each { |k,v| v.is_a?(Cbt::Component).should be_true }
|
18
|
+
end
|
19
|
+
|
20
|
+
it "parses module files for component utils" do
|
21
|
+
app.components["utils"].modules.size.should eq(2)
|
22
|
+
app.components["utils"].modules.each {|k,v| v.is_a?(Cbt::LuaModule).should be_true}
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "#current_component_names" do
|
27
|
+
subject(:app) do
|
28
|
+
app = Cbt::App.new(config_file: "examples/config/components.yml")
|
29
|
+
app.git = GircMock.new
|
30
|
+
app
|
31
|
+
end
|
32
|
+
|
33
|
+
it "return component for full format current branch" do
|
34
|
+
app.git.current_branch = 'component/utils'
|
35
|
+
app.current_component_names[0].should eq('utils')
|
36
|
+
end
|
37
|
+
|
38
|
+
it "return component for shorter format current branch" do
|
39
|
+
app.git.current_branch = 'comp/utils'
|
40
|
+
app.current_component_names[0].should eq('utils')
|
41
|
+
end
|
42
|
+
|
43
|
+
it "return component for short format current branch" do
|
44
|
+
app.git.current_branch = 'ct/utils'
|
45
|
+
app.current_component_names[0].should eq('utils')
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Cbt::Creator do
|
4
|
+
describe "#find_tpl" do
|
5
|
+
subject(:crt) { Cbt::Creator.new(config_file: "examples/config/components.yml") }
|
6
|
+
|
7
|
+
it "find tpl for simple module" do
|
8
|
+
crt.find_tpl(Cbt::LuaModule.new('utils', 'util')).should eq(File.expand_path("templates/part.lua.erb"))
|
9
|
+
end
|
10
|
+
|
11
|
+
it "find tpl for simple Class" do
|
12
|
+
crt.find_tpl(Cbt::LuaModule.new('utils', 'Util')).should eq(File.expand_path("templates/Class.lua.erb"))
|
13
|
+
end
|
14
|
+
|
15
|
+
it "find tpl for simple module with super class" do
|
16
|
+
crt.find_tpl(Cbt::LuaModule.new('utils', 'util<Sp')).should eq(File.expand_path("templates/part_with_super.lua.erb"))
|
17
|
+
end
|
18
|
+
|
19
|
+
it "find tpl for simple Class with super class" do
|
20
|
+
crt.find_tpl(Cbt::LuaModule.new('utils', 'Util<Sp')).should eq(File.expand_path("templates/Class_with_super.lua.erb"))
|
21
|
+
end
|
22
|
+
it "find tpl for mock module" do
|
23
|
+
crt.find_tpl(Cbt::LuaModule.new('utils', 'util'), true).should eq(File.expand_path("templates/part.mock.lua.erb"))
|
24
|
+
end
|
25
|
+
|
26
|
+
it "find tpl for mock Class" do
|
27
|
+
crt.find_tpl(Cbt::LuaModule.new('utils', 'Util'), true).should eq(File.expand_path("templates/Class.mock.lua.erb"))
|
28
|
+
end
|
29
|
+
|
30
|
+
it "find tpl for mock module" do
|
31
|
+
crt.find_tpl(Cbt::LuaModule.new('utils', 'util<Sp'), true).should eq(File.expand_path("templates/part_with_super.mock.lua.erb"))
|
32
|
+
end
|
33
|
+
|
34
|
+
it "find tpl for mock Class" do
|
35
|
+
crt.find_tpl(Cbt::LuaModule.new('utils', 'Util<Sp'), true).should eq(File.expand_path("templates/Class_with_super.mock.lua.erb"))
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
require 'fileutils'
|
4
|
+
|
5
|
+
describe Cbt::Digester do
|
6
|
+
TEMP_FILE = 'history.yml'
|
7
|
+
subject(:dst) { Cbt::Digester.new(TEMP_FILE) }
|
8
|
+
|
9
|
+
describe '#add_history' do
|
10
|
+
it "can add history" do
|
11
|
+
dst.add_history('filename', 'digeststringverylong')
|
12
|
+
dst.last_change('filename').should_not be_nil
|
13
|
+
end
|
14
|
+
|
15
|
+
it "can get last history" do
|
16
|
+
dst.last_change('filename')['digest'].should eq('digeststringverylong')
|
17
|
+
end
|
18
|
+
|
19
|
+
it "can handle more than one file" do
|
20
|
+
dst.add_history('filename2', 'lfgjhowtqerpfdfflou4o8rywo')
|
21
|
+
dst.last_change('filename')['digest'].should eq('digeststringverylong')
|
22
|
+
end
|
23
|
+
|
24
|
+
it "can test file change" do
|
25
|
+
dst.changed?('filename', 'digeststringverylong').should be_false
|
26
|
+
dst.changed?('filename', 'digeststringverylongzz').should be_true
|
27
|
+
end
|
28
|
+
|
29
|
+
it "can test file version in history" do
|
30
|
+
dst.add_history('filename', '34dofy8yeroerhfdofsdf')
|
31
|
+
dst.known?('filename', 'digeststringverylong').should be_true
|
32
|
+
dst.known?('filename', 'digeststringverylozng').should be_false
|
33
|
+
end
|
34
|
+
|
35
|
+
it "compare file change only for the last version" do
|
36
|
+
dst.changed?('filename', '34dofy8yeroerhfdofsdf').should be_false
|
37
|
+
dst.changed?('filename', 'digeststringverylong').should be_true
|
38
|
+
end
|
39
|
+
|
40
|
+
it "compare file change without digest" do
|
41
|
+
FileUtils.cp 'examples/config/components.yml', 'history_test'
|
42
|
+
dst.add_history('history_test')
|
43
|
+
dst.changed?('history_test').should be_false
|
44
|
+
#wfh = File.open('history_test', 'w')
|
45
|
+
#wfh.puts "history file test"
|
46
|
+
#wfh.close
|
47
|
+
#dst.changed?('history_test').should be_true
|
48
|
+
end
|
49
|
+
|
50
|
+
after(:all) do
|
51
|
+
FileUtils.rm TEMP_FILE
|
52
|
+
FileUtils.rm 'history_test'
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|