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
@@ -0,0 +1,19 @@
|
|
1
|
+
components:
|
2
|
+
utils:
|
3
|
+
lua_modules: [util, timer]
|
4
|
+
tag: utils
|
5
|
+
LiveObject:
|
6
|
+
tag: ui.base
|
7
|
+
Panel:
|
8
|
+
lua_modules: [Panel<LiveObject]
|
9
|
+
tag: ui.full
|
10
|
+
|
11
|
+
tags:
|
12
|
+
_default: {shape: record, style: filled, fillcolor: beige}
|
13
|
+
utils: {fillcolor: bisque3}
|
14
|
+
ui: {shape: Mrecord}
|
15
|
+
ui.base: {fillcolor: bisque3}
|
16
|
+
ui.full: {fillcolor: cornflowerblue}
|
17
|
+
|
18
|
+
# relations: -- for erd
|
19
|
+
|
data/lib/cbt.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require "cbt/girc"
|
2
|
+
require "cbt/component"
|
3
|
+
require "cbt/digester"
|
4
|
+
require "cbt/app"
|
5
|
+
require "cbt/creator"
|
6
|
+
require "cbt/checkout"
|
7
|
+
require "cbt/cleanup"
|
8
|
+
require "cbt/diagram"
|
9
|
+
|
10
|
+
require "luobo/cbt"
|
11
|
+
require "luobo/lua"
|
12
|
+
require "luobo/spec"
|
13
|
+
require "luobo/settings"
|
data/lib/cbt/app.rb
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
require 'find'
|
2
|
+
require 'logger'
|
3
|
+
require 'yaml'
|
4
|
+
|
5
|
+
module Cbt
|
6
|
+
class App
|
7
|
+
attr_accessor :options, :git, :components
|
8
|
+
def initialize options = {}
|
9
|
+
@options = options
|
10
|
+
@git = Girc.new('git', @options[:verbose])
|
11
|
+
|
12
|
+
# initialize logger
|
13
|
+
@logger = Logger.new(STDOUT)
|
14
|
+
@logger.level = @options[:verbose] ? Logger::INFO : Logger::WARN
|
15
|
+
@logger.formatter = proc {|severity, datetime, progname, msg| "#{msg.to_s}\n"}
|
16
|
+
|
17
|
+
@config = YAML.load(File.open(@options[:config_file]).read)
|
18
|
+
# parse a components name=>object list
|
19
|
+
@components = Hash.new
|
20
|
+
@config["components"].each do |name, conf|
|
21
|
+
@components[name] = Component.new(name, conf)
|
22
|
+
end
|
23
|
+
|
24
|
+
# merge tag attributes recursively
|
25
|
+
@config["tags"].each do |t,v|
|
26
|
+
tv = @config["tags"]["_default"].clone || {}
|
27
|
+
p = nil
|
28
|
+
t.split('.').each do |pt|
|
29
|
+
p = p ? [p, pt].join('.') : pt # merge in order: tv < a < a.b < a.b.c, ...
|
30
|
+
# puts "merge from #{p} to #{t}"
|
31
|
+
tv.merge! @config["tags"][p] if @config["tags"][p]
|
32
|
+
end
|
33
|
+
@config["tags"][t] = tv
|
34
|
+
end
|
35
|
+
|
36
|
+
# check uniqueness for assets and lua module
|
37
|
+
luam, assets = Hash.new, Hash.new
|
38
|
+
@components.each do |cname, comp|
|
39
|
+
comp.assets.each do |aname, asset|
|
40
|
+
error "asset #{aname} defined in both components #{cname} and #{assets[aname]}" if assets[aname]
|
41
|
+
assets[aname] = cname
|
42
|
+
end
|
43
|
+
|
44
|
+
comp.modules.each do |mname, lua|
|
45
|
+
error "lua module #{mname} defined in both components #{cname} and #{luam[mname]}" if luam[mname]
|
46
|
+
luam[mname] = cname
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# log message handler
|
52
|
+
# ------------------------------
|
53
|
+
def error msg
|
54
|
+
@logger.fatal ("[ERROR] " + msg).bold.red
|
55
|
+
exit
|
56
|
+
end
|
57
|
+
|
58
|
+
def warn msg
|
59
|
+
@logger.warn ("[WARN] " + msg).yellow
|
60
|
+
end
|
61
|
+
|
62
|
+
def info msg
|
63
|
+
@logger.info "[INFO] " + msg
|
64
|
+
end
|
65
|
+
|
66
|
+
# find current components from the command line option
|
67
|
+
# or from the git branch name
|
68
|
+
def current_component_names
|
69
|
+
component_list = Array.new
|
70
|
+
error "you can not specify component name with '--all' option" if @options[:component] and @options[:all]
|
71
|
+
|
72
|
+
if @options[:component]
|
73
|
+
component_list = @options[:component].split(",")
|
74
|
+
elsif @options[:all]
|
75
|
+
component_list = @components.keys
|
76
|
+
else
|
77
|
+
if @git.in_git_dir? and /^(comp|component|ct)\/.+/.match(@git.current_branch)
|
78
|
+
info "parse component names from git branch (#{@git.current_branch})"
|
79
|
+
component_list << @git.current_branch.gsub(/^(comp|component|ct)\//, '')
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
component_list.each { |n| error "unknown component name '#{n}'" unless @components[n] }
|
84
|
+
component_list
|
85
|
+
end
|
86
|
+
|
87
|
+
# return the tag definition from config file.
|
88
|
+
def tags tag
|
89
|
+
@config["tags"][tag.to_s] || {}
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
93
|
+
end
|
data/lib/cbt/checkout.rb
ADDED
@@ -0,0 +1,155 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
module Cbt
|
4
|
+
class Checkout < App
|
5
|
+
|
6
|
+
# copy file from s to t, use luobo if convert class defined
|
7
|
+
def cp_file s, t
|
8
|
+
converted = false
|
9
|
+
if /\.(?<ext_>\w+)$/ =~ s
|
10
|
+
if ext_
|
11
|
+
begin
|
12
|
+
klass = Module.const_get(ext_.capitalize + 'Luobo')
|
13
|
+
rescue Exception => e
|
14
|
+
end
|
15
|
+
|
16
|
+
if klass and klass.is_a?(Class)
|
17
|
+
info "Use #{klass} to convert #{s}"
|
18
|
+
klass.cp! s, t, @options[:platform]
|
19
|
+
converted = true
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# if no any luobo class converted the file, copy as it is
|
25
|
+
FileUtils.cp s, t unless converted
|
26
|
+
|
27
|
+
# add to consistency list
|
28
|
+
@digester.add_history s
|
29
|
+
@digester.add_history t
|
30
|
+
end
|
31
|
+
|
32
|
+
def add_copy_list sfile, tfile
|
33
|
+
# only add source file that has changed unless no_consistency_check
|
34
|
+
@file_list[sfile] = tfile if @options[:no_consistency_check] or @digester.changed?(sfile)
|
35
|
+
if @file_list[sfile] and @digester.changed?(tfile) and File.exists? tfile
|
36
|
+
error "target file #{tfile} changed. use --force to force overwrite" unless @options[:force]
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# copy asset files for all components
|
41
|
+
def copy_assets! comp, ws_dir
|
42
|
+
comp.assets.each do |aname, asset|
|
43
|
+
comp_dir = comp.dir(@options[:components_dir])
|
44
|
+
|
45
|
+
# detect if an asset file saved both in global and component space
|
46
|
+
sfile = asset.path([comp_dir], @options[:platform])
|
47
|
+
global_file = asset.path([@options[:assets_dir]], @options[:platform])
|
48
|
+
warn "#{sfile} will overwrite #{global_file}" if sfile and global_file
|
49
|
+
|
50
|
+
sfile = global_file unless sfile
|
51
|
+
error "asset file for #{aname}, component #{comp.name} not found" unless sfile
|
52
|
+
|
53
|
+
tfile = m.target(ws_dir)
|
54
|
+
add_copy_list sfile, tfile
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# copy required component assets and files
|
59
|
+
def copy_require! comp, ws_dir
|
60
|
+
comp.modules.each do |mname, m|
|
61
|
+
next if mname == 'main' # skip main file from the application core component
|
62
|
+
comp_dir = comp.dir(@options[:components_dir])
|
63
|
+
|
64
|
+
sfile = m.path([comp_dir], @options[:require_platform])
|
65
|
+
tfile = m.target(ws_dir)
|
66
|
+
error "no file find for module lua file #{mname}, component #{comp.name}" unless sfile
|
67
|
+
|
68
|
+
# add lua module file int copy waiting list
|
69
|
+
add_copy_list sfile, tfile
|
70
|
+
end
|
71
|
+
# copy all
|
72
|
+
end
|
73
|
+
|
74
|
+
# copy lua/spec files for a component
|
75
|
+
def process_component! comp
|
76
|
+
info "checkout component #{comp.name}"
|
77
|
+
|
78
|
+
# the copy candidate files list
|
79
|
+
@file_list = Hash.new
|
80
|
+
|
81
|
+
comp_dir = comp.dir(@options[:components_dir])
|
82
|
+
ws_dir = comp.ws_dir(@options[:workspace_dir], @options[:platform])
|
83
|
+
unless File.directory? ws_dir
|
84
|
+
info "create workspace directory #{ws_dir}"
|
85
|
+
FileUtils.mkdir_p ws_dir
|
86
|
+
end
|
87
|
+
|
88
|
+
@digester = Digester.new(ws_dir + ".yml")
|
89
|
+
|
90
|
+
# copy assets files for all components
|
91
|
+
@components.each do |cname, c|
|
92
|
+
copy_assets! c, ws_dir unless cname == comp.name
|
93
|
+
end
|
94
|
+
copy_assets! comp, ws_dir # copy the current component at last
|
95
|
+
|
96
|
+
# copy require files for all components other than current component
|
97
|
+
@components.each do |cname, c|
|
98
|
+
copy_require! c, ws_dir unless cname == comp.name
|
99
|
+
end
|
100
|
+
|
101
|
+
# for each lua module, error if no file
|
102
|
+
comp.modules['main'] = LuaModule.new(comp.name, 'main') unless comp.modules['main']
|
103
|
+
comp.modules.each do |mname, m|
|
104
|
+
sfile = m.path([comp_dir], @options[:platform])
|
105
|
+
tfile = m.target(ws_dir)
|
106
|
+
error "no file find for module lua file #{mname}, component #{comp.name}" unless sfile
|
107
|
+
|
108
|
+
# add lua module file int copy waiting list
|
109
|
+
add_copy_list sfile, tfile
|
110
|
+
end
|
111
|
+
|
112
|
+
# for all spec files
|
113
|
+
spec_dir = comp_dir
|
114
|
+
spec_dir = @options[:components_dir] if @options[:all_spec]
|
115
|
+
Dir[spec_dir + "/*_spec.lua"].each do |lua|
|
116
|
+
add_copy_list lua, File.join(ws_dir, File.basename(lua))
|
117
|
+
end
|
118
|
+
|
119
|
+
# check if t registered twice
|
120
|
+
tlist = Hash.new
|
121
|
+
@file_list.each do |s,t|
|
122
|
+
warn "#{s} will overwrite #{tlist[t]} (for #{t})" if tlist[t]
|
123
|
+
tlist[t] = s
|
124
|
+
|
125
|
+
if @options[:simulation]
|
126
|
+
puts "#{s} -> #{t}"
|
127
|
+
else
|
128
|
+
info "copy #{s} -> #{t}"
|
129
|
+
cp_file s, t
|
130
|
+
@digester.add_history s
|
131
|
+
@digester.add_history t
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
# wrap for all components
|
137
|
+
def process!
|
138
|
+
unless File.directory? @options[:workspace_dir]
|
139
|
+
info "create workspace directory #{@options[:workspace_dir]}"
|
140
|
+
FileUtils.mkdir_p @options[:workspace_dir]
|
141
|
+
end
|
142
|
+
|
143
|
+
if @options[:build] == true
|
144
|
+
warn "set require platform to #{@options[:platform]}" unless @options[:require_platform] == @options[:platform]
|
145
|
+
@options[:require_platform] = @options[:platform]
|
146
|
+
end
|
147
|
+
|
148
|
+
# process for all component
|
149
|
+
current_component_names.each do |cname|
|
150
|
+
comp = @components[cname]
|
151
|
+
process_component! comp
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
data/lib/cbt/cleanup.rb
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
module Cbt
|
2
|
+
|
3
|
+
# handle file platform versinn and copy
|
4
|
+
class SrcFile
|
5
|
+
attr_accessor :component_name
|
6
|
+
def initialize component_name, basename, ext=nil
|
7
|
+
unless ext
|
8
|
+
if /^(?<basename_>.+?)\.(?<ext_>\w+)$/ =~ basename
|
9
|
+
basename, ext = basename_, ext_
|
10
|
+
end
|
11
|
+
end
|
12
|
+
@component_name, @basename, @ext = component_name, basename, ext
|
13
|
+
end
|
14
|
+
|
15
|
+
# search up for the source file for the current file object
|
16
|
+
# with @name as the basename
|
17
|
+
def path dir = [], platform = 'debug'
|
18
|
+
# search up for each dir in row
|
19
|
+
dir.each do |d|
|
20
|
+
[".#{platform}.", "."].each do |filename|
|
21
|
+
file_path = File.join(d, @basename + filename + @ext)
|
22
|
+
# end search and return the file first found in the given directories
|
23
|
+
# return File.expand_path(file_path) if File.exists? file_path
|
24
|
+
return file_path if File.exists? file_path
|
25
|
+
end
|
26
|
+
end
|
27
|
+
nil
|
28
|
+
end
|
29
|
+
|
30
|
+
# file copy to under workspace
|
31
|
+
def target workspace_dir
|
32
|
+
File.join(workspace_dir, @basename + '.' + @ext)
|
33
|
+
end
|
34
|
+
|
35
|
+
end # class file
|
36
|
+
|
37
|
+
# module lua file object holds file contents digest to
|
38
|
+
# prevent accedental over-write
|
39
|
+
class LuaModule < SrcFile
|
40
|
+
attr_accessor :name, :super_class
|
41
|
+
|
42
|
+
def initialize component_name, name
|
43
|
+
@name, @super_class = name.split("<")
|
44
|
+
super(component_name, @name, 'lua')
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# assets files
|
49
|
+
class AssetFile < SrcFile
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
class Component
|
54
|
+
attr_accessor :name, :modules, :assets
|
55
|
+
|
56
|
+
def initialize name, conf
|
57
|
+
@name, @conf = name, conf
|
58
|
+
|
59
|
+
# if no modules defined, use the name as default
|
60
|
+
@conf["lua_modules"] = Array.new unless @conf["lua_modules"]
|
61
|
+
@conf["lua_modules"] << @name if @conf["lua_modules"].size == 0
|
62
|
+
|
63
|
+
@conf["assets"] = Array.new unless @conf["assets"]
|
64
|
+
|
65
|
+
# parse module definitions, convert to objects
|
66
|
+
@modules, @assets = {}, {} # name => object pair
|
67
|
+
@conf["lua_modules"].each do |lname|
|
68
|
+
raise "invalid lua module name '#{lname}'" unless /^[a-zA-Z][\<a-zA-Z_0-9]+$/.match(lname)
|
69
|
+
@modules[lname] = LuaModule.new(@name, lname)
|
70
|
+
end
|
71
|
+
|
72
|
+
@conf["assets"].each do |asset|
|
73
|
+
@assets[asset] = AssetFile.new(@name, asset)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def tag
|
78
|
+
@conf["tag"]
|
79
|
+
end
|
80
|
+
|
81
|
+
# where the module/asset files are located
|
82
|
+
def dir base_dir
|
83
|
+
File.join(base_dir, @name).gsub(/\/$/, '')
|
84
|
+
end
|
85
|
+
|
86
|
+
# target working space directory
|
87
|
+
def ws_dir base_dir, platform
|
88
|
+
File.join(base_dir, @name + '_' + platform).gsub(/\/$/, '')
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
data/lib/cbt/creator.rb
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
require "fileutils"
|
2
|
+
require "erubis"
|
3
|
+
|
4
|
+
module Cbt
|
5
|
+
class Creator < App
|
6
|
+
|
7
|
+
# find the template file from local or gem folders
|
8
|
+
def find_tpl_file tt
|
9
|
+
# first find the template under the current folder
|
10
|
+
tpl = File.join("template", tt)
|
11
|
+
|
12
|
+
# if not find there, use the default template come from the gem
|
13
|
+
unless File.exists? tpl
|
14
|
+
tpl = File.expand_path(File.dirname(__FILE__)) + "/../../templates/" + tt
|
15
|
+
end
|
16
|
+
File.expand_path(tpl)
|
17
|
+
end
|
18
|
+
|
19
|
+
# find template file name
|
20
|
+
def find_tpl luamod, mock = false
|
21
|
+
tt = ""
|
22
|
+
if luamod.name =~ /^[A-Z]/
|
23
|
+
tt = luamod.super_class ? "Class_with_super" : "Class"
|
24
|
+
else
|
25
|
+
tt = luamod.super_class ? "part_with_super" : "part"
|
26
|
+
end
|
27
|
+
|
28
|
+
tt = mock ? tt + ".mock.lua.erb" : tt + ".lua.erb"
|
29
|
+
find_tpl_file(tt)
|
30
|
+
end
|
31
|
+
|
32
|
+
# create skeleton files based on filename, module objects and template filename
|
33
|
+
def create! filename, luamod, template
|
34
|
+
if (not File.exists?(filename)) or @options[:force]
|
35
|
+
info "create file #{filename}"
|
36
|
+
fh = File.open(filename, 'w:utf-8')
|
37
|
+
fh.puts Erubis::Eruby.new(File.open(template, 'r:utf-8').read).result({
|
38
|
+
"super_class" => luamod.super_class, "name" => luamod.name,
|
39
|
+
"label" => sprintf("(component: %s)", luamod.component_name)
|
40
|
+
})
|
41
|
+
fh.close
|
42
|
+
else
|
43
|
+
info "skip existing file #{filename}"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# create initial lua files based on templates
|
48
|
+
def process!
|
49
|
+
comps = current_component_names
|
50
|
+
warn "no component specified." unless comps.size > 0
|
51
|
+
comps.each do |cname|
|
52
|
+
comp = @components[cname]
|
53
|
+
raise "undefined components #{cname}" unless comp
|
54
|
+
|
55
|
+
# create each module lua files
|
56
|
+
rep_dir = comp.dir(@options[:components_dir])
|
57
|
+
comp.modules.each do |name, mod|
|
58
|
+
unless File.directory? rep_dir
|
59
|
+
info "create directory #{rep_dir}"
|
60
|
+
FileUtils.mkdir_p rep_dir
|
61
|
+
end
|
62
|
+
|
63
|
+
# create file:
|
64
|
+
create!(File.join(rep_dir, mod.name + ".mock.lua"), mod, find_tpl(mod, true))
|
65
|
+
create!(File.join(rep_dir, mod.name + ".lua"), mod, find_tpl(mod, false))
|
66
|
+
create!(File.join(rep_dir, mod.name + "_spec.lua"), mod, find_tpl_file('spec.lua.erb')) unless name == 'main'
|
67
|
+
end
|
68
|
+
|
69
|
+
create!(File.join(rep_dir, "main.lua"), LuaModule.new(cname, 'main'), find_tpl_file('main.lua.erb')) unless comp.modules['main']
|
70
|
+
end # component names
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|