cbt 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
@@ -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
@@ -0,0 +1,7 @@
1
+ module Cbt
2
+ class Cleanup < App
3
+ def process!
4
+
5
+ end
6
+ end
7
+ end
@@ -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
@@ -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
+