docker_brick 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.
- checksums.yaml +7 -0
- data/.gitignore +22 -0
- data/.project +17 -0
- data/Gemfile +11 -0
- data/LICENSE.txt +24 -0
- data/README.md +29 -0
- data/Rakefile +2 -0
- data/bin/brick +11 -0
- data/docker_brick.gemspec +29 -0
- data/lib/brick/application.rb +35 -0
- data/lib/brick/cli/build.rb +28 -0
- data/lib/brick/cli/core/subcommand_loader.rb +39 -0
- data/lib/brick/cli/help.rb +16 -0
- data/lib/brick/cli/project_new.rb +29 -0
- data/lib/brick/cli/run.rb +113 -0
- data/lib/brick/cli/service_new.rb +44 -0
- data/lib/brick/cli/up.rb +46 -0
- data/lib/brick/cli.rb +230 -0
- data/lib/brick/cli__validator.rb +28 -0
- data/lib/brick/config.rb +9 -0
- data/lib/brick/docker/docker_client.rb +160 -0
- data/lib/brick/generators/new_project_generator/templates/fig.yml +0 -0
- data/lib/brick/generators/new_project_generator.rb +51 -0
- data/lib/brick/generators/new_service_generator.rb +24 -0
- data/lib/brick/generators.rb +10 -0
- data/lib/brick/mixin/aliasing.rb +24 -0
- data/lib/brick/mixin/colors.rb +24 -0
- data/lib/brick/mixin/convert_to_class_name.rb +52 -0
- data/lib/brick/mixin/docker_support.rb +253 -0
- data/lib/brick/mixin/yaml_helper.rb +18 -0
- data/lib/brick/mixin.rb +8 -0
- data/lib/brick/models/project.rb +139 -0
- data/lib/brick/models/service.rb +276 -0
- data/lib/brick/models.rb +13 -0
- data/lib/brick/monkey_patches/cli.rb +24 -0
- data/lib/brick/monkey_patches/connection.rb +15 -0
- data/lib/brick/monkey_patches/docker_container.rb +28 -0
- data/lib/brick/monkey_patches/hash.rb +16 -0
- data/lib/brick/monkey_patches.rb +5 -0
- data/lib/brick/version.rb +4 -0
- data/lib/brick.rb +34 -0
- data/spec/brick_update.sh +7 -0
- data/spec/integration/brick/models/project_spec.rb +70 -0
- data/spec/projects/nc_test/fig.yml +14 -0
- data/spec/projects/nc_test/ncserver/Dockerfile +7 -0
- data/spec/projects/rails/myapp/Dockerfile +7 -0
- data/spec/projects/rails/myapp/Gemfile +2 -0
- data/spec/projects/rails/myapp/fig.yml +13 -0
- data/spec/shell/brick_update.sh +7 -0
- data/spec/spec_helper.rb +19 -0
- data/spec/unit/brick/mixin/docker_support.yml +33 -0
- data/spec/unit/brick/mixin/docker_support_spec.rb +66 -0
- data/spec/unit/brick/models/dockerfile/Dockerfile +7 -0
- data/spec/unit/brick/models/fig_build.yml +3 -0
- data/spec/unit/brick/models/fig_completed.yml +41 -0
- data/spec/unit/brick/models/fig_dependency.yml +19 -0
- data/spec/unit/brick/models/fig_single.yml +6 -0
- data/spec/unit/brick/models/fig_volumes.yml +10 -0
- data/spec/unit/brick/models/fig_volumes_from.yml +19 -0
- data/spec/unit/brick/models/project_spec.rb +70 -0
- data/spec/unit/brick/models/service_spec.rb +80 -0
- metadata +231 -0
data/lib/brick/cli.rb
ADDED
@@ -0,0 +1,230 @@
|
|
1
|
+
require 'mixlib/cli'
|
2
|
+
require 'brick/application'
|
3
|
+
require 'brick/monkey_patches/cli'
|
4
|
+
module Brick
|
5
|
+
class CLI
|
6
|
+
|
7
|
+
extend Brick::Mixin::ConvertToClassName
|
8
|
+
include Mixlib::CLI
|
9
|
+
#include Application
|
10
|
+
|
11
|
+
|
12
|
+
def self.logger
|
13
|
+
@@logger ||= Logger.new(STDOUT)
|
14
|
+
@@logger.level = Logger::INFO
|
15
|
+
@@logger.formatter = proc do |severity, datetime, progname, msg|
|
16
|
+
"#{msg}\n"
|
17
|
+
end
|
18
|
+
@@logger
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
def self.inherited(subclass)
|
23
|
+
unless subclass.unnamed?
|
24
|
+
subcommands[subclass.snake_case_name] = subclass
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.unnamed?
|
29
|
+
name.nil? || name.empty?
|
30
|
+
end
|
31
|
+
|
32
|
+
# Run command line for the given +args+ (ARGV), adding +options+ to the list of
|
33
|
+
# CLI options that the subcommand knows how to handle.
|
34
|
+
# ===Arguments
|
35
|
+
# args::: usually ARGV
|
36
|
+
# options::: A Mixlib::CLI option parser hash. These +options+ are how
|
37
|
+
# subcommands know about global knife CLI options
|
38
|
+
def self.run(args, options={})
|
39
|
+
#configure brick for common attributes
|
40
|
+
#common_optparser.configure_brick
|
41
|
+
common_optparser.opt_parser.banner="Usage: brick SUBCOMMAND (options)"
|
42
|
+
CLI_Validator::validate
|
43
|
+
#logger.info "begin to run the comand #{args}"
|
44
|
+
load_commands
|
45
|
+
subcommand_class = subcommand_class_from(args)
|
46
|
+
subcommand_class.options = common_optparser.class.options.merge!(subcommand_class.options)
|
47
|
+
subcommand_class.load_deps
|
48
|
+
instance = subcommand_class.new(args)
|
49
|
+
#instance.configure_brick
|
50
|
+
instance.run_with_pretty_exceptions
|
51
|
+
end
|
52
|
+
|
53
|
+
def self.common_optparser
|
54
|
+
@@common_optparser ||= Application.new
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.subcommand_class_from(args)
|
58
|
+
command_words = args.select {|arg| arg =~ /^(([[:alnum:]])[[:alnum:]\_\-]+)$/ }
|
59
|
+
|
60
|
+
subcommand_class = nil
|
61
|
+
|
62
|
+
while ( !subcommand_class ) && ( !command_words.empty? )
|
63
|
+
snake_case_class_name = command_words.join("_")
|
64
|
+
unless subcommand_class = subcommands[snake_case_class_name]
|
65
|
+
command_words.pop
|
66
|
+
end
|
67
|
+
end
|
68
|
+
# see if we got the command as e.g., brick model create
|
69
|
+
subcommand_class ||= subcommands[args.first.gsub('-', '_')]
|
70
|
+
subcommand_class || subcommand_not_found!(args)
|
71
|
+
end
|
72
|
+
|
73
|
+
def self.subcommands
|
74
|
+
@@subcommands ||= {}
|
75
|
+
end
|
76
|
+
|
77
|
+
def self.subcommand_not_found!(args)
|
78
|
+
logger.fatal("Cannot find sub command for: '#{args.join(' ')}'")
|
79
|
+
|
80
|
+
|
81
|
+
list_commands
|
82
|
+
|
83
|
+
|
84
|
+
exit 10
|
85
|
+
end
|
86
|
+
|
87
|
+
def self.list_parameters
|
88
|
+
puts common_optparser.opt_parser.to_s
|
89
|
+
puts ""
|
90
|
+
end
|
91
|
+
|
92
|
+
# is given, only subcommands in that category are shown
|
93
|
+
def self.list_commands(preferred_category=nil)
|
94
|
+
load_commands
|
95
|
+
|
96
|
+
category_desc = preferred_category ? preferred_category + " " : ''
|
97
|
+
logger.info "Available #{category_desc}subcommands: (for details, brick SUB-COMMAND --help)\n\n"
|
98
|
+
|
99
|
+
if preferred_category && subcommands_by_category.key?(preferred_category)
|
100
|
+
commands_to_show = {preferred_category => subcommands_by_category[preferred_category]}
|
101
|
+
else
|
102
|
+
commands_to_show = subcommands_by_category
|
103
|
+
end
|
104
|
+
|
105
|
+
commands_to_show.sort.each do |category, commands|
|
106
|
+
next if category =~ /deprecated/i
|
107
|
+
logger.info "** #{category.upcase} COMMANDS **"
|
108
|
+
commands.sort.each do |command|
|
109
|
+
logger.info subcommands[command].banner if subcommands[command]
|
110
|
+
end
|
111
|
+
logger.info
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def self.subcommands_by_category
|
116
|
+
unless @subcommands_by_category
|
117
|
+
@subcommands_by_category = Hash.new { |hash, key| hash[key] = [] }
|
118
|
+
subcommands.each do |snake_cased, klass|
|
119
|
+
@subcommands_by_category[klass.subcommand_category] << snake_cased
|
120
|
+
end
|
121
|
+
end
|
122
|
+
@subcommands_by_category
|
123
|
+
end
|
124
|
+
|
125
|
+
def self.snake_case_name
|
126
|
+
convert_to_snake_case(name.split('::').last) unless unnamed?
|
127
|
+
end
|
128
|
+
|
129
|
+
def self.load_commands
|
130
|
+
@commands_loaded ||= subcommand_loader.load_commands
|
131
|
+
end
|
132
|
+
|
133
|
+
|
134
|
+
def self.subcommand_loader
|
135
|
+
@subcommand_loader ||= CLI::SubcommandLoader.new
|
136
|
+
end
|
137
|
+
|
138
|
+
#Add catergory
|
139
|
+
def self.category(new_category)
|
140
|
+
@category = new_category
|
141
|
+
end
|
142
|
+
|
143
|
+
def self.subcommand_category
|
144
|
+
@category || snake_case_name.split('_').first unless unnamed?
|
145
|
+
end
|
146
|
+
|
147
|
+
def self.dependency_loaders
|
148
|
+
@dependency_loaders ||= []
|
149
|
+
end
|
150
|
+
|
151
|
+
def self.deps(&block)
|
152
|
+
dependency_loaders << block
|
153
|
+
end
|
154
|
+
|
155
|
+
def self.load_deps
|
156
|
+
dependency_loaders.each do |dep_loader|
|
157
|
+
dep_loader.call
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
def initialize(argv=[])
|
162
|
+
|
163
|
+
super()
|
164
|
+
command_name_words = self.class.snake_case_name.split('_')
|
165
|
+
|
166
|
+
# Mixlib::CLI ignores the embedded name_args
|
167
|
+
@cmd_args = ARGV.dup - command_name_words
|
168
|
+
|
169
|
+
@cmd_args = parse_options @cmd_args
|
170
|
+
@cmd_args.delete(command_name_words.join('-'))
|
171
|
+
#@name_args.reject! { |name_arg| command_name_words.delete(name_arg) }
|
172
|
+
|
173
|
+
|
174
|
+
Brick::Config.merge!(config)
|
175
|
+
|
176
|
+
project_name = ::Brick::Config[:project]
|
177
|
+
|
178
|
+
config_file = ::Brick::Config[:config_file]
|
179
|
+
|
180
|
+
project_dir = File.dirname(config_file)
|
181
|
+
|
182
|
+
::Brick::Config[:project_dir] = project_dir
|
183
|
+
=begin
|
184
|
+
if config[:help]
|
185
|
+
logger.info opt_parser
|
186
|
+
exit 1
|
187
|
+
end
|
188
|
+
=end
|
189
|
+
|
190
|
+
end
|
191
|
+
|
192
|
+
|
193
|
+
def run_with_pretty_exceptions
|
194
|
+
unless self.respond_to?(:run)
|
195
|
+
logger.error "You need to add a #run method to your brick command before you can use it"
|
196
|
+
end
|
197
|
+
run
|
198
|
+
rescue Exception => e
|
199
|
+
raise
|
200
|
+
humanize_exception(e)
|
201
|
+
exit 100
|
202
|
+
end
|
203
|
+
|
204
|
+
def humanize_exception(e)
|
205
|
+
case e
|
206
|
+
when SystemExit
|
207
|
+
raise # make sure exit passes through.
|
208
|
+
when Errno::ECONNREFUSED, Timeout::Error, Errno::ETIMEDOUT, SocketError
|
209
|
+
logger.error "Network Error: #{e.message}"
|
210
|
+
logger.info "Check your network settings"
|
211
|
+
else
|
212
|
+
logger.error "#{e.class.name}: #{e.message}"
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
def show_usage
|
217
|
+
puts( self.opt_parser.to_s)
|
218
|
+
end
|
219
|
+
|
220
|
+
# def configure_brick
|
221
|
+
# begin
|
222
|
+
# parse_options
|
223
|
+
# rescue => e
|
224
|
+
# ::Brick::CLI::logger.error e.message
|
225
|
+
# exit 1
|
226
|
+
# end
|
227
|
+
# Brick::Config.merge!(config)
|
228
|
+
# end
|
229
|
+
end
|
230
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Brick
|
2
|
+
class CLI_Validator
|
3
|
+
NO_COMMAND_GIVEN = "You need to pass a sub-command (e.g., brick SUB-COMMAND)\n"
|
4
|
+
|
5
|
+
def self.validate
|
6
|
+
if no_command_given?
|
7
|
+
print_help_and_exit(1, NO_COMMAND_GIVEN)
|
8
|
+
end
|
9
|
+
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.no_subcommand_given?
|
13
|
+
ARGV[0] =~ /^-/
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.no_command_given?
|
17
|
+
ARGV.empty?
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.print_help_and_exit(exitcode=1, fatal_message=nil)
|
21
|
+
Brick::CLI::logger.error(fatal_message) if fatal_message
|
22
|
+
Brick::CLI.list_parameters
|
23
|
+
Brick::CLI.list_commands
|
24
|
+
exit exitcode
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
data/lib/brick/config.rb
ADDED
@@ -0,0 +1,160 @@
|
|
1
|
+
require 'monitor'
|
2
|
+
require "docker"
|
3
|
+
require 'json'
|
4
|
+
require 'uri'
|
5
|
+
#require 'byebug'
|
6
|
+
module Brick
|
7
|
+
module Docker
|
8
|
+
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
module Brick
|
13
|
+
module Docker
|
14
|
+
class DockerClient
|
15
|
+
include Brick::Mixin::DockerSupport
|
16
|
+
|
17
|
+
@@default_client = nil
|
18
|
+
|
19
|
+
@@lock = Monitor.new
|
20
|
+
|
21
|
+
to_aliase_methods = [:run]
|
22
|
+
|
23
|
+
attr_accessor :base_url, :connection
|
24
|
+
|
25
|
+
@@connection_pool = Hash.new
|
26
|
+
|
27
|
+
@base_url = ENV['DOCKER_URL']
|
28
|
+
|
29
|
+
def self.connection base_url
|
30
|
+
|
31
|
+
conn = nil
|
32
|
+
|
33
|
+
@@lock.synchronize do
|
34
|
+
conn ||= @@connection_pool[base_url.to_sym]
|
35
|
+
|
36
|
+
if(conn.nil?)
|
37
|
+
conn = ::Docker::Connection.new(base_url, {})
|
38
|
+
@@connection_pool[base_url.to_sym] = @connection
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
conn
|
43
|
+
end
|
44
|
+
|
45
|
+
def initialize(options={})
|
46
|
+
|
47
|
+
unless(options[:base_url].nil?)
|
48
|
+
@base_url = options[:base_url]
|
49
|
+
end
|
50
|
+
|
51
|
+
|
52
|
+
@base_url ||= 'unix:///var/run/docker.sock'
|
53
|
+
|
54
|
+
|
55
|
+
@connection= self.class.connection @base_url
|
56
|
+
|
57
|
+
puts "#{__method__} #{__LINE__} @connection=#{@connection}"
|
58
|
+
end
|
59
|
+
|
60
|
+
def self.default
|
61
|
+
@@default_client ||= DockerClient.new
|
62
|
+
#puts "client=#{@@default_client}"
|
63
|
+
return @@default_client
|
64
|
+
end
|
65
|
+
|
66
|
+
def create config_hash, name=nil
|
67
|
+
|
68
|
+
docker_hash= create_config(config_hash)
|
69
|
+
|
70
|
+
docker_hash['name'] = name unless name.nil?
|
71
|
+
|
72
|
+
begin
|
73
|
+
container = ::Docker::Container.create(docker_hash.dup, connection)
|
74
|
+
#get full information of the container
|
75
|
+
container = ::Docker::Container.get(container.id,connection)
|
76
|
+
rescue ::Docker::Error::NotFoundError => exception
|
77
|
+
if exception.message.include? 'No such image'
|
78
|
+
::Docker::Image.create({'fromImage'=> config_hash['image']},{}, connection)
|
79
|
+
container = ::Docker::Container.create(docker_hash.dup, connection)
|
80
|
+
#get full information of the container
|
81
|
+
container = ::Docker::Container.get(container.id,connection)
|
82
|
+
else
|
83
|
+
raise exception
|
84
|
+
end
|
85
|
+
return container
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
|
90
|
+
#if the container is already existed, reuse it
|
91
|
+
#if the container is not started, start it
|
92
|
+
def run config_hash, name=nil
|
93
|
+
#byebug
|
94
|
+
container = get_container_by_name name
|
95
|
+
|
96
|
+
|
97
|
+
if container.nil?
|
98
|
+
container = create config_hash, name
|
99
|
+
else
|
100
|
+
Brick::CLI::logger.info "container #{name} has already existed."
|
101
|
+
end
|
102
|
+
|
103
|
+
Brick::CLI::logger.debug "container #{container}."
|
104
|
+
|
105
|
+
|
106
|
+
unless container.is_running?
|
107
|
+
container.start(start_config(config_hash))
|
108
|
+
else
|
109
|
+
Brick::CLI::logger.info "container #{name} is #{container.info["Status"]}"
|
110
|
+
end
|
111
|
+
|
112
|
+
container
|
113
|
+
end
|
114
|
+
|
115
|
+
def get_container_by_name name=nil
|
116
|
+
|
117
|
+
container = nil
|
118
|
+
|
119
|
+
unless name.nil?
|
120
|
+
container = ::Docker::Container.search_by_name name, connection
|
121
|
+
end
|
122
|
+
|
123
|
+
container.first
|
124
|
+
|
125
|
+
end
|
126
|
+
|
127
|
+
def get_container_by_id id
|
128
|
+
::Docker::Container.get(id,connection)
|
129
|
+
end
|
130
|
+
|
131
|
+
|
132
|
+
def build_from_dir options={}
|
133
|
+
|
134
|
+
image_name = options[:image_name]
|
135
|
+
|
136
|
+
dockerfile_path = options[:build_dir]
|
137
|
+
|
138
|
+
project_dir = options[:project_dir]
|
139
|
+
|
140
|
+
no_cache = options[:no_cache]
|
141
|
+
|
142
|
+
dockerfile_path = determine_dockerfile_path(dockerfile_path, project_dir)
|
143
|
+
|
144
|
+
|
145
|
+
image = ::Docker::Image.build_from_dir(dockerfile_path, {"t"=>image_name, "nocache" =>no_cache }) {
|
146
|
+
|chunk| h1 = ::JSON.parse(chunk);
|
147
|
+
|
148
|
+
value = h1.values[0].to_s;
|
149
|
+
|
150
|
+
puts(::URI.unescape(value))
|
151
|
+
|
152
|
+
}
|
153
|
+
|
154
|
+
|
155
|
+
image
|
156
|
+
end
|
157
|
+
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
File without changes
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require "thor/group"
|
2
|
+
require "fileutils"
|
3
|
+
|
4
|
+
module Brick::Generators
|
5
|
+
class NewProjectGenerator < Thor::Group
|
6
|
+
include Thor::Actions
|
7
|
+
|
8
|
+
argument :working_dir
|
9
|
+
argument :project_name
|
10
|
+
|
11
|
+
attr_accessor :project_root
|
12
|
+
|
13
|
+
def self.source_root
|
14
|
+
File.join(File.dirname(__FILE__), "new_project_generator", "templates")
|
15
|
+
end
|
16
|
+
|
17
|
+
def create_root
|
18
|
+
self.destination_root = File.expand_path(working_dir)
|
19
|
+
empty_directory(project_name)
|
20
|
+
self.project_root=File.join(working_dir,project_name)
|
21
|
+
FileUtils.cd(project_root)
|
22
|
+
end
|
23
|
+
|
24
|
+
def fig_file
|
25
|
+
copy_file("fig.yml","#{project_name}/fig.yml")
|
26
|
+
puts "the project is created at #{project_root}"
|
27
|
+
end
|
28
|
+
|
29
|
+
def init_git
|
30
|
+
puts "Initializing git repo in #{project_root}"
|
31
|
+
FileUtils.cd(project_root)
|
32
|
+
git :init
|
33
|
+
git :add => "."
|
34
|
+
git :commit => "-m 'Initial commit'"
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def git(commands={})
|
41
|
+
if commands.is_a?(Symbol)
|
42
|
+
`git #{commands}`
|
43
|
+
else
|
44
|
+
commands.each do |cmd, options|
|
45
|
+
`git #{cmd} #{options}`
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require "thor/group"
|
2
|
+
|
3
|
+
module Brick::Generators
|
4
|
+
class NewServiceGenerator < Thor::Group
|
5
|
+
argument :working_dir
|
6
|
+
|
7
|
+
|
8
|
+
|
9
|
+
def create_a
|
10
|
+
puts "a"
|
11
|
+
'a'
|
12
|
+
end
|
13
|
+
|
14
|
+
def create_b
|
15
|
+
puts "b"
|
16
|
+
'b'
|
17
|
+
end
|
18
|
+
|
19
|
+
def create_c
|
20
|
+
puts "c"
|
21
|
+
'c'
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Brick::Mixin::Aliasing
|
2
|
+
|
3
|
+
def alias_method_chain(target, feature)
|
4
|
+
# Strip out punctuation on predicates or bang methods since
|
5
|
+
# e.g. target?_without_feature is not a valid method name.
|
6
|
+
aliased_target, punctuation = target.to_s.sub(/([?!=])$/, ''), $1
|
7
|
+
yield(aliased_target, punctuation) if block_given?
|
8
|
+
|
9
|
+
with_method = "#{aliased_target}_with_#{feature}#{punctuation}"
|
10
|
+
without_method = "#{aliased_target}_without_#{feature}#{punctuation}"
|
11
|
+
|
12
|
+
alias_method without_method, target
|
13
|
+
alias_method target, with_method
|
14
|
+
|
15
|
+
case
|
16
|
+
when public_method_defined?(without_method)
|
17
|
+
public target
|
18
|
+
when protected_method_defined?(without_method)
|
19
|
+
protected target
|
20
|
+
when private_method_defined?(without_method)
|
21
|
+
private target
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'set'
|
2
|
+
require 'colorize'
|
3
|
+
|
4
|
+
module Brick::Mixin::Colors
|
5
|
+
COLORS = [:blue, :red, :yellow, :light_red, :green, :light_green, :light_yellow, :black, :light_black, :light_blue, :magenta, :light_magenta, :cyan, :light_cyan, :white, :light_white]
|
6
|
+
|
7
|
+
@@current = -1
|
8
|
+
|
9
|
+
def determine_color
|
10
|
+
if $stdout.isatty
|
11
|
+
@@current = (@@current+1)%COLORS.size
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def color_generator str
|
16
|
+
|
17
|
+
if $stdout.isatty
|
18
|
+
|
19
|
+
str=str.colorize(COLORS[@@current])
|
20
|
+
end
|
21
|
+
|
22
|
+
str
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module Brick
|
2
|
+
module Mixin
|
3
|
+
end
|
4
|
+
end
|
5
|
+
|
6
|
+
|
7
|
+
module Brick
|
8
|
+
module Mixin
|
9
|
+
module ConvertToClassName
|
10
|
+
extend self
|
11
|
+
|
12
|
+
def convert_to_class_name(str)
|
13
|
+
str = str.dup
|
14
|
+
str.gsub!(/[^A-Za-z0-9_]/,'_')
|
15
|
+
rname = nil
|
16
|
+
regexp = %r{^(.+?)(_(.+))?$}
|
17
|
+
|
18
|
+
mn = str.match(regexp)
|
19
|
+
if mn
|
20
|
+
rname = mn[1].capitalize
|
21
|
+
|
22
|
+
while mn && mn[3]
|
23
|
+
mn = mn[3].match(regexp)
|
24
|
+
rname << mn[1].capitalize if mn
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
rname
|
29
|
+
end
|
30
|
+
|
31
|
+
def convert_to_snake_case(str, namespace=nil)
|
32
|
+
str = str.dup
|
33
|
+
str.sub!(/^#{namespace}(\:\:)?/, '') if namespace
|
34
|
+
str.gsub!(/[A-Z]/) {|s| "_" + s}
|
35
|
+
str.downcase!
|
36
|
+
str.sub!(/^\_/, "")
|
37
|
+
str
|
38
|
+
end
|
39
|
+
|
40
|
+
def snake_case_basename(str)
|
41
|
+
with_namespace = convert_to_snake_case(str)
|
42
|
+
with_namespace.split("::").last.sub(/^_/, '')
|
43
|
+
end
|
44
|
+
|
45
|
+
def filename_to_qualified_string(base, filename)
|
46
|
+
file_base = File.basename(filename, ".rb")
|
47
|
+
base.to_s + (file_base == 'default' ? '' : "_#{file_base}")
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|