coral_core 0.1.2

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.rdoc ADDED
@@ -0,0 +1,33 @@
1
+ = coral_core
2
+
3
+ This library provides core data elements and utilities used in other Coral gems.
4
+
5
+ The Coral core library contains functionality that is utilized by other
6
+ Coral gems by providing basic utilities like Git, Shell, Disk, and Data
7
+ manipulation libraries, a UI system, and a core data model that supports
8
+ Events, Commands, Repositories, and Memory (version controlled JSON
9
+ objects). This library is only used as a starting point for other systems.
10
+
11
+ Note: This library is still very early in development!
12
+
13
+ == Contributing to coral_core
14
+
15
+ * Check out the latest master to make sure the feature hasn't been implemented
16
+ or the bug hasn't been fixed yet.
17
+ * Check out the issue tracker to make sure someone already hasn't requested
18
+ it and/or contributed it.
19
+ * Fork the project.
20
+ * Start a feature/bugfix branch.
21
+ * Commit and push until you are happy with your contribution.
22
+ * Make sure to add tests for it. This is important so I don't break it in a
23
+ future version unintentionally.
24
+ * Please try not to mess with the Rakefile, version, or history. If you want
25
+ to have your own version, or is otherwise necessary, that is fine, but
26
+ please isolate to its own commit so I can cherry-pick around it.
27
+
28
+ == Copyright
29
+
30
+ Licensed under GPLv3. See LICENSE.txt for further details.
31
+
32
+ Copyright (c) 2013 Adrian Webb <adrian.webb@coraltech.net>
33
+ Coral Technology Group LLC
data/Rakefile ADDED
@@ -0,0 +1,77 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'rake'
5
+ require 'bundler'
6
+ require 'jeweler'
7
+ require 'rspec/core/rake_task'
8
+ require 'rdoc/task'
9
+ require 'yard'
10
+
11
+ require './lib/coral_core.rb'
12
+
13
+ #-------------------------------------------------------------------------------
14
+ # Dependencies
15
+
16
+ begin
17
+ Bundler.setup(:default, :development)
18
+ rescue Bundler::BundlerError => e
19
+ $stderr.puts e.message
20
+ $stderr.puts "Run `bundle install` to install missing gems"
21
+ exit e.status_code
22
+ end
23
+
24
+ #-------------------------------------------------------------------------------
25
+ # Gem specification
26
+
27
+ Jeweler::Tasks.new do |gem|
28
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
29
+ gem.name = "coral_core"
30
+ gem.homepage = "http://github.com/coraltech/ruby-coral_core"
31
+ gem.rubyforge_project = 'coral_core'
32
+ gem.license = "GPLv3"
33
+ gem.email = "adrian.webb@coraltech.net"
34
+ gem.authors = ["Adrian Webb"]
35
+ gem.summary = %Q{Provides core data elements and utilities used in other Coral gems}
36
+ gem.description = File.read('README.rdoc')
37
+ gem.required_ruby_version = '>= 1.8.1'
38
+ gem.has_rdoc = true
39
+ gem.rdoc_options << '--title' << 'Coral Core library' <<
40
+ '--main' << 'README.rdoc' <<
41
+ '--line-numbers'
42
+
43
+ # Dependencies defined in Gemfile
44
+ end
45
+
46
+ Jeweler::RubygemsDotOrgTasks.new
47
+
48
+ #-------------------------------------------------------------------------------
49
+ # Testing
50
+
51
+ RSpec::Core::RakeTask.new(:spec, :tag) do |spec, task_args|
52
+ options = []
53
+ options << "--tag #{task_args[:tag]}" if task_args.is_a?(Array) && ! task_args[:tag].to_s.empty?
54
+ spec.rspec_opts = options.join(' ')
55
+ end
56
+
57
+ task :default => :spec
58
+
59
+ #-------------------------------------------------------------------------------
60
+ # Documentation
61
+
62
+ version = Coral::VERSION
63
+ doc_title = "coral_core #{version}"
64
+
65
+ Rake::RDocTask.new do |rdoc|
66
+ rdoc.rdoc_dir = 'rdoc'
67
+ rdoc.title = doc_title
68
+ rdoc.rdoc_files.include('README*')
69
+ rdoc.rdoc_files.include('lib/**/*.rb')
70
+ end
71
+
72
+ #---
73
+
74
+ YARD::Rake::YardocTask.new do |ydoc|
75
+ ydoc.files = [ 'README*', 'lib/**/*.rb' ]
76
+ ydoc.options = [ "--output-dir yardoc", "--title '#{doc_title}'" ]
77
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.2
@@ -0,0 +1,236 @@
1
+
2
+ module Coral
3
+ class Command < Core
4
+
5
+ #-----------------------------------------------------------------------------
6
+ # Properties
7
+
8
+ attr_accessor :name
9
+ attr_reader :subcommand
10
+
11
+ #-----------------------------------------------------------------------------
12
+ # Constructor / Destructor
13
+
14
+ def initialize(options = {})
15
+
16
+ if options.is_a?(String) || options.is_a?(Symbol)
17
+ options = string(options)
18
+ options = { :name => options, :command => options }
19
+ end
20
+
21
+ super(options)
22
+
23
+ @properties = {}
24
+
25
+ self.subcommand = options[:subcommand] if options.has_key?(:subcommand)
26
+
27
+ @name = ( options.has_key?(:name) ? string(options[:name]) : '' )
28
+
29
+ @properties = options
30
+ @properties[:command] = executable(options)
31
+ end
32
+
33
+ #-----------------------------------------------------------------------------
34
+ # Property accessors / modifiers
35
+
36
+ def command_base
37
+ return @properties[:command]
38
+ end
39
+
40
+ #---
41
+
42
+ def command=command
43
+ @properties[:command] = executable({ :command => command })
44
+ end
45
+
46
+ #---
47
+
48
+ def vagrant=command
49
+ @properties[:command] = executable({ :vagrant => command })
50
+ end
51
+
52
+ #---
53
+
54
+ def coral=command
55
+ @properties[:command] = executable({ :coral => command })
56
+ end
57
+
58
+ #---
59
+
60
+ def args
61
+ return array(@properties[:args])
62
+ end
63
+
64
+ #---
65
+
66
+ def args=args
67
+ @properties[:args] = array(args)
68
+ end
69
+
70
+ #---
71
+
72
+ def flags
73
+ return array(@properties[:flags])
74
+ end
75
+
76
+ #---
77
+
78
+ def flags=flags
79
+ @properties[:flags] = array(flags)
80
+ end
81
+
82
+ #---
83
+
84
+ def data
85
+ return hash(@properties[:data])
86
+ end
87
+
88
+ #---
89
+
90
+ def data=data
91
+ @properties[:data] = hash(data)
92
+ end
93
+
94
+ #---
95
+
96
+ def subcommand=subcommand
97
+ @properties[:subcommand] = hash(subcommand)
98
+ @subcommand = Module.const_get("Coral").const_get(self.class).new(@properties[:subcommand])
99
+ end
100
+
101
+ #-----------------------------------------------------------------------------
102
+ # Import / Export
103
+
104
+ def export
105
+ return symbol_map(@properties)
106
+ end
107
+
108
+ #-----------------------------------------------------------------------------
109
+ # Command functions
110
+
111
+ def build(components = {}, overrides = nil, override_key = false)
112
+
113
+ command = string(components[:command])
114
+ flags = array( components.has_key?(:flags) ? components[:flags] : [] )
115
+ data = string_map(hash( components.has_key?(:data) ? components[:data] : {} ))
116
+ args = array( components.has_key?(:args) ? components[:args] : [] )
117
+ subcommand = hash( components.has_key?(:subcommand) ? components[:subcommand] : {} )
118
+
119
+ override_key = command unless override_key
120
+ override_key = override_key.to_sym
121
+
122
+ command_string = command.dup
123
+ subcommand_string = ''
124
+
125
+ escape_characters = /[\'\"]+/
126
+ escape_replacement = '\"'
127
+
128
+ dash_pattern = /^([\-]+)/
129
+ assignment_pattern = /\=$/
130
+
131
+ # Flags
132
+ if overrides && overrides.has_key?(:flags)
133
+ if overrides[:flags].is_a?(Hash)
134
+ if overrides[:flags].has_key?(override_key)
135
+ flags = array(overrides[:flags][override_key])
136
+ end
137
+ else
138
+ flags = array(overrides[:flags])
139
+ end
140
+ end
141
+ flags.each do |flag|
142
+ if flag && ! flag.empty?
143
+ flag = string(flag)
144
+
145
+ if flag.match(dash_pattern)
146
+ dashes = $1
147
+ else
148
+ dashes = ( flag.size == 1 ? '-' : '--' )
149
+ end
150
+ command_string << " #{dashes}#{flag}"
151
+ end
152
+ end
153
+
154
+ # Data
155
+ if overrides && overrides.has_key?(:data)
156
+ if overrides[:data].has_key?(override_key)
157
+ data = hash(overrides[:data][override_key])
158
+ else
159
+ override = true
160
+ overrides[:data].each do |key, value|
161
+ if ! value.is_a?(String)
162
+ override = false
163
+ end
164
+ end
165
+ data = hash(overrides[:data]) if override
166
+ end
167
+ end
168
+ data.each do |key, value|
169
+ key = string(key)
170
+ value = string(value).strip.sub(escape_characters, escape_replacement)
171
+
172
+ if key.match(dash_pattern)
173
+ dashes = $1
174
+ else
175
+ dashes = ( key.size == 1 ? '-' : '--' )
176
+ end
177
+ space = ( key.match(assignment_pattern) ? '' : ' ' )
178
+
179
+ command_string << " #{dashes}#{key}#{space}'#{value}'"
180
+ end
181
+
182
+ # Arguments
183
+ if overrides && overrides.has_key?(:args)
184
+ if overrides[:args].is_a?(Hash)
185
+ if overrides[:args].has_key?(override_key)
186
+ args = array(overrides[:args][override_key])
187
+ end
188
+ else
189
+ args = array(overrides[:args])
190
+ end
191
+ end
192
+ args.each do |arg|
193
+ arg = string(arg).sub(escape_characters, escape_replacement)
194
+ command_string << " '#{arg}'"
195
+ end
196
+
197
+ # Subcommand
198
+ subcommand_overrides = ( overrides ? overrides[:subcommand] : nil )
199
+ if subcommand && subcommand.is_a?(Hash) && ! subcommand.empty?
200
+ subcommand_string = build(subcommand, subcommand_overrides)
201
+ end
202
+
203
+ return (command_string + ' ' + subcommand_string).strip
204
+ end
205
+
206
+ #-----------------------------------------------------------------------------
207
+
208
+ def exec!(options = {}, overrides = nil)
209
+ success = Coral::Util::Shell.exec!(build(export, overrides), options) do |line|
210
+ block_given? ? yield(line) : true
211
+ end
212
+ return success
213
+ end
214
+
215
+ #---
216
+
217
+ def exec(options = {}, overrides = nil)
218
+ return exec!(options, overrides)
219
+ end
220
+
221
+ #-----------------------------------------------------------------------------
222
+ # Utilities
223
+
224
+ def executable(options)
225
+ if options.has_key?(:coral)
226
+ return 'vagrant coral ' + options[:coral]
227
+
228
+ elsif options.has_key?(:vagrant)
229
+ return 'vagrant ' + options[:vagrant]
230
+
231
+ elsif options.has_key?(:command)
232
+ return options[:command]
233
+ end
234
+ end
235
+ end
236
+ end
@@ -0,0 +1,200 @@
1
+
2
+ module Coral
3
+ class Core
4
+
5
+ #-----------------------------------------------------------------------------
6
+ # Constructor / Destructor
7
+
8
+ def initialize(options = {})
9
+ @ui = Coral::Interface.new(options)
10
+ end
11
+
12
+ #-----------------------------------------------------------------------------
13
+ # Accessor / Modifiers
14
+
15
+ attr_accessor :ui
16
+
17
+ #-----------------------------------------------------------------------------
18
+
19
+ def self.logger
20
+ return @ui.class.logger
21
+ end
22
+
23
+ #---
24
+
25
+ def logger
26
+ return @ui.logger
27
+ end
28
+
29
+ #---
30
+
31
+ def logger=logger
32
+ @ui.logger = logger
33
+ end
34
+
35
+ #-----------------------------------------------------------------------------
36
+ # General utilities
37
+
38
+ def self.symbol_map(data)
39
+ results = {}
40
+ return data unless data
41
+
42
+ case data
43
+ when Hash
44
+ data.each do |key, value|
45
+ results[key.to_sym] = symbol_map(value)
46
+ end
47
+ else
48
+ results = data
49
+ end
50
+ return results
51
+ end
52
+
53
+ #---
54
+
55
+ def symbol_map(data)
56
+ return self.class.symbol_map(data)
57
+ end
58
+
59
+ #---
60
+
61
+ def self.string_map(data)
62
+ results = {}
63
+ return data unless data
64
+
65
+ case data
66
+ when Hash
67
+ data.each do |key, value|
68
+ results[key.to_s] = string_map(value)
69
+ end
70
+ else
71
+ results = data
72
+ end
73
+ return results
74
+ end
75
+
76
+ #---
77
+
78
+ def string_map(data)
79
+ return self.class.string_map(data)
80
+ end
81
+
82
+ #-----------------------------------------------------------------------------
83
+
84
+ def self.filter(data, method = false)
85
+ if method && method.is_a?(Symbol) &&
86
+ [ :array, :hash, :string, :symbol, :test ].include?(method.to_sym)
87
+ return send(method, data)
88
+ end
89
+ return data
90
+ end
91
+
92
+ #---
93
+
94
+ def filter(data, method = false)
95
+ return self.class.filter(data, method)
96
+ end
97
+
98
+ #-----------------------------------------------------------------------------
99
+
100
+ def self.array(data, default = [], split_string = false)
101
+ result = default
102
+ if data && ! data.empty?
103
+ case data
104
+ when Array
105
+ result = data
106
+ when String
107
+ result = [ ( split_string ? data.split(/\s*,\s*/) : data ) ]
108
+ else
109
+ result = [ data ]
110
+ end
111
+ end
112
+ return result
113
+ end
114
+
115
+ #---
116
+
117
+ def array(data, default = [], split_string = false)
118
+ return self.class.array(data, default, split_string)
119
+ end
120
+
121
+ #---
122
+
123
+ def self.hash(data, default = {})
124
+ result = default
125
+ if data && ! data.empty?
126
+ case data
127
+ when Hash
128
+ result = data
129
+ else
130
+ result = {}
131
+ end
132
+ end
133
+ return result
134
+ end
135
+
136
+ #---
137
+
138
+ def hash(data, default = {})
139
+ return self.class.hash(data, default)
140
+ end
141
+
142
+ #---
143
+
144
+ def self.string(data, default = '')
145
+ result = default
146
+ if data && ! data.empty?
147
+ case data
148
+ when String
149
+ result = data
150
+ else
151
+ result = data.to_s
152
+ end
153
+ end
154
+ return result
155
+ end
156
+
157
+ #---
158
+
159
+ def string(data, default = '')
160
+ return self.class.string(data, default)
161
+ end
162
+
163
+ #---
164
+
165
+ def self.symbol(data, default = :undefined)
166
+ result = default
167
+ if data && ! data.empty?
168
+ case data
169
+ when Symbol
170
+ result = data
171
+ when String
172
+ result = data.to_sym
173
+ else
174
+ result = data.class.to_sym
175
+ end
176
+ end
177
+ return result
178
+ end
179
+
180
+ #---
181
+
182
+ def symbol(data, default = '')
183
+ return self.class.symbol(data, default)
184
+ end
185
+
186
+ #---
187
+
188
+ def self.test(data)
189
+ return false if ! data || data.empty?
190
+ return false if data.is_a?(String) && data =~ /^(FALSE|false|False|No|no|N|n)$/
191
+ return true
192
+ end
193
+
194
+ #---
195
+
196
+ def test(data)
197
+ return self.class.test(data)
198
+ end
199
+ end
200
+ end
@@ -0,0 +1,55 @@
1
+
2
+ module Coral
3
+ class RegexpEvent < Event
4
+
5
+ #-----------------------------------------------------------------------------
6
+ # Properties
7
+
8
+ TYPE = :regexp
9
+
10
+ #-----------------------------------------------------------------------------
11
+ # Constructor / Destructor
12
+
13
+ def initialize(options = {})
14
+ options[:type] = TYPE
15
+
16
+ super(options)
17
+
18
+ if options.has_key?(:string)
19
+ self.pattern = options[:string]
20
+ end
21
+ end
22
+
23
+ #-----------------------------------------------------------------------------
24
+ # Property accessors / modifiers
25
+
26
+ def pattern
27
+ return property(:pattern, '', :string)
28
+ end
29
+
30
+ #---
31
+
32
+ def pattern=pattern
33
+ set_property(:pattern, string(pattern))
34
+ end
35
+
36
+ #-----------------------------------------------------------------------------
37
+ # Import / Export
38
+
39
+ def export
40
+ return "#{type}:#{pattern}"
41
+ end
42
+
43
+ #-----------------------------------------------------------------------------
44
+ # Event handling
45
+
46
+ def check(source)
47
+ if source.match(/#{pattern}/)
48
+ logger.debug("MATCH! -> #{pattern} matched #{source}")
49
+ return true
50
+ end
51
+ logger.debug("nothing -> #{pattern} - #{source}")
52
+ return false
53
+ end
54
+ end
55
+ end