cbt 0.0.1
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 +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
|
+
|