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.
@@ -0,0 +1,168 @@
1
+
2
+ module Coral
3
+ class Event < Core
4
+
5
+ #-----------------------------------------------------------------------------
6
+ # Constructor / Destructor
7
+
8
+ def self.instance!(options = {}, build_hash = false, keep_array = false)
9
+ group = ( build_hash ? {} : [] )
10
+ events = build_info(options)
11
+
12
+ index = 1
13
+ events.each do |info|
14
+ type = info[:type]
15
+
16
+ if type && ! type.empty?
17
+ event = ( block_given? ? yield(type, info) : create(type, info) )
18
+
19
+ if event
20
+ if build_hash
21
+ group[index] = event
22
+ else
23
+ group << event
24
+ end
25
+ end
26
+ end
27
+ index += 1
28
+ end
29
+ if ! build_hash && events.length == 1 && ! keep_array
30
+ return group.shift
31
+ end
32
+ return group
33
+ end
34
+
35
+ #---
36
+
37
+ def self.instance(options = {}, build_hash = false, keep_array = false)
38
+ return instance!(options, build_hash, keep_array)
39
+ end
40
+
41
+ #---
42
+
43
+ def initialize(options = {})
44
+ super(options)
45
+
46
+ @name = ( options.has_key?(:name) ? options[:name] : '' )
47
+ @delegate = ( options.has_key?(:delegate) ? options[:delegate] : nil )
48
+ @properties = options
49
+ end
50
+
51
+ #-----------------------------------------------------------------------------
52
+ # Property accessors / modifiers
53
+
54
+ attr_accessor :name
55
+
56
+ #---
57
+
58
+ def type
59
+ return string(@properties[:type])
60
+ end
61
+
62
+ #---
63
+
64
+ def set_properties(data)
65
+ return @delegate.set_properties(data) if @delegate
66
+
67
+ @properties = hash(data)
68
+ return self
69
+ end
70
+
71
+ #---
72
+
73
+ def property(name, default = '', format = false)
74
+ name = name.to_sym
75
+
76
+ property = default
77
+ property = filter(@properties[name], format) if @properties.has_key?(name)
78
+ return property
79
+ end
80
+
81
+ #---
82
+
83
+ def set_property(name, value)
84
+ return @delegate.set_property(name, value) if @delegate
85
+
86
+ @properties[name] = value
87
+ return self
88
+ end
89
+
90
+ #-----------------------------------------------------------------------------
91
+ # Import / Export
92
+
93
+ def export
94
+ return type
95
+ end
96
+
97
+ #-----------------------------------------------------------------------------
98
+ # Event handling
99
+
100
+ def check(source)
101
+ return false
102
+ end
103
+
104
+ #-----------------------------------------------------------------------------
105
+ # Utilities
106
+
107
+ def self.build_info!(data = {})
108
+ events = []
109
+
110
+ if data.is_a?(String)
111
+ data = data.split(/\s*,\s*/)
112
+ elsif data.is_a?(Hash)
113
+ data = [ data ]
114
+ end
115
+
116
+ if data.is_a?(Array)
117
+ data.each do |element|
118
+ event = {}
119
+
120
+ if block_given?
121
+ event = yield(element)
122
+ else
123
+ case element
124
+ when String
125
+ event = split_event_string(element)
126
+
127
+ when Hash
128
+ event = element
129
+ end
130
+ end
131
+
132
+ unless event.empty?
133
+ events << event
134
+ end
135
+ end
136
+ end
137
+ return events
138
+ end
139
+
140
+ #---
141
+
142
+ def self.build_info(data = {})
143
+ return build_info!(data)
144
+ end
145
+
146
+ #-----------------------------------------------------------------------------
147
+
148
+ def self.create(type, info)
149
+ event = nil
150
+ begin
151
+ event = Module.const_get("Coral").const_get("#{type.capitalize}Event").new(info)
152
+ rescue
153
+ end
154
+ return event
155
+ end
156
+
157
+ #-----------------------------------------------------------------------------
158
+
159
+ def self.split_event_string(data)
160
+ info = {}
161
+ components = data.split(':')
162
+ info[:type] = components.shift
163
+ info[:string] = components.join(':')
164
+
165
+ return info
166
+ end
167
+ end
168
+ end
@@ -0,0 +1,179 @@
1
+
2
+ require "log4r"
3
+
4
+ module Coral
5
+ class Interface
6
+
7
+ #-----------------------------------------------------------------------------
8
+ # Properties
9
+
10
+ @@logger = Log4r::Logger.new("coral::interface")
11
+
12
+ #---
13
+
14
+ COLORS = {
15
+ :clear => "\e[0m",
16
+ :red => "\e[31m",
17
+ :green => "\e[32m",
18
+ :yellow => "\e[33m"
19
+ }
20
+
21
+ COLOR_MAP = {
22
+ :warn => COLORS[:yellow],
23
+ :error => COLORS[:red],
24
+ :success => COLORS[:green]
25
+ }
26
+
27
+ #-----------------------------------------------------------------------------
28
+ # Constructor
29
+
30
+ def initialize(options = {})
31
+ class_name = self.class.to_s.downcase
32
+
33
+ if options.is_a?(String)
34
+ options = { :resource => options, :logger => options }
35
+ end
36
+
37
+ if options.has_key?(:logger)
38
+ if options[:logger].is_a?(String)
39
+ @logger = Log4r::Logger.new(options[:logger])
40
+ else
41
+ @logger = options[:logger]
42
+ end
43
+ else
44
+ @logger = Log4r::Logger.new("coral::#{class_name}")
45
+ end
46
+
47
+ @resource = ( options.has_key?(:resource) ? options[:resource] : '' )
48
+ @color = ( options.has_key?(:color) ? options[:color] : true )
49
+
50
+ @printer = ( options.has_key?(:printer) ? options[:printer] : :puts )
51
+
52
+ @input = ( options.has_key?(:input) ? options[:input] : $stdin )
53
+ @output = ( options.has_key?(:output) ? options[:output] : $stdout )
54
+ @error = ( options.has_key?(:error) ? options[:error] : $stderr )
55
+
56
+ @delegate = ( options.has_key?(:ui_delegate) ? options[:ui_delegate] : nil )
57
+ end
58
+
59
+ #-----------------------------------------------------------------------------
60
+ # Accessors / Modifiers
61
+
62
+ attr_accessor :logger, :resource, :color, :input, :output, :error, :delegate
63
+
64
+ #-----------------------------------------------------------------------------
65
+
66
+ def self.logger
67
+ return @@logger
68
+ end
69
+
70
+ #-----------------------------------------------------------------------------
71
+ # UI functionality
72
+
73
+ def say(type, message, options = {})
74
+ return @delegate.say(type, message, options) if check_delegate('say')
75
+
76
+ defaults = { :new_line => true, :prefix => true }
77
+ options = defaults.merge(options)
78
+ printer = options[:new_line] ? :puts : :print
79
+ channel = type == :error || options[:channel] == :error ? @error : @output
80
+
81
+ safe_puts(format_message(type, message, options),
82
+ :channel => channel, :printer => printer)
83
+ end
84
+
85
+ #---
86
+
87
+ def ask(message, options = {})
88
+ return @delegate.ask(message, options) if check_delegate('ask')
89
+
90
+ options[:new_line] = false if ! options.has_key?(:new_line)
91
+ options[:prefix] = false if ! options.has_key?(:prefix)
92
+
93
+ say(:info, message, options)
94
+ return @input.gets.chomp
95
+ end
96
+
97
+ #-----------------------------------------------------------------------------
98
+
99
+ def info(message, *args)
100
+ @logger.info("info: #{message}")
101
+
102
+ return @delegate.info(message, *args) if check_delegate('info')
103
+ say(:info, message, *args)
104
+ end
105
+
106
+ #---
107
+
108
+ def warn(message, *args)
109
+ @logger.info("warn: #{message}")
110
+
111
+ return @delegate.warn(message, *args) if check_delegate('warn')
112
+ say(:warn, message, *args)
113
+ end
114
+
115
+ #---
116
+
117
+ def error(message, *args)
118
+ @logger.info("error: #{message}")
119
+
120
+ return @delegate.error(message, *args) if check_delegate('error')
121
+ say(:error, message, *args)
122
+ end
123
+
124
+ #---
125
+
126
+ def success(message, *args)
127
+ @logger.info("success: #{message}")
128
+
129
+ return @delegate.success(message, *args) if check_delegate('success')
130
+ say(:success, message, *args)
131
+ end
132
+
133
+ #-----------------------------------------------------------------------------
134
+ # Utilities
135
+
136
+ def format_message(type, message, options = {})
137
+ return @delegate.format_message(type, message, options) if check_delegate('format_message')
138
+
139
+ if @resource && ! @resource.empty? && options[:prefix]
140
+ prefix = "[#{@resource}]"
141
+ end
142
+ message = "#{prefix} #{message}".strip
143
+
144
+ if @color
145
+ if options.has_key?(:color)
146
+ color = COLORS[options[:color]]
147
+ message = "#{color}#{message}#{COLORS[:clear]}"
148
+ else
149
+ message = "#{COLOR_MAP[type]}#{message}#{COLORS[:clear]}" if COLOR_MAP[type]
150
+ end
151
+ end
152
+ return message
153
+ end
154
+
155
+ #---
156
+
157
+ def safe_puts(message = nil, options = {})
158
+ return @delegate.safe_puts(message, options) if check_delegate('safe_puts')
159
+
160
+ message ||= ""
161
+ options = {
162
+ :channel => @output,
163
+ :printer => @printer,
164
+ }.merge(options)
165
+
166
+ begin
167
+ options[:channel].send(options[:printer], message)
168
+ rescue Errno::EPIPE
169
+ return
170
+ end
171
+ end
172
+
173
+ #-----------------------------------------------------------------------------
174
+
175
+ def check_delegate(method)
176
+ return ( @delegate && @delegate.respond_to?(method.to_s) )
177
+ end
178
+ end
179
+ end
@@ -0,0 +1,222 @@
1
+
2
+ require 'json'
3
+
4
+ module Coral
5
+ class Memory < Repository
6
+
7
+ #-----------------------------------------------------------------------------
8
+ # Constructor / Destructor
9
+
10
+ def initialize(options = {})
11
+ super(options)
12
+
13
+ @absolute_config_file = ''
14
+
15
+ @properties = ( options.has_key?(:properties) ? hash(options[:properties]) : {} )
16
+ @config_file = ( options.has_key?(:config_file) ? string(options[:config_file]) : '' )
17
+ @autoload = ( options.has_key?(:autoload) ? options[:autoload] : true )
18
+ @autosave = ( options.has_key?(:autosave) ? options[:autosave] : true )
19
+ @autocommit = ( options.has_key?(:autocommit) ? options[:autocommit] : true )
20
+ @commit_message = ( options.has_key?(:commit_message) ? string(options[:commit_message]) : 'Saving state' )
21
+
22
+ set_absolute_config_file
23
+ load if @autoload
24
+ end
25
+
26
+ #---
27
+
28
+ def self.finalize(file_name)
29
+ proc do
30
+ Coral::Util::Disk.close(file_name)
31
+ end
32
+ end
33
+
34
+ #-----------------------------------------------------------------------------
35
+ # Property accessors / modifiers
36
+
37
+ attr_accessor :autoload, :autosave, :autocommit, :commit_message
38
+ attr_reader :config_file, :absolute_config_file
39
+
40
+ #---
41
+
42
+ def set_absolute_config_file
43
+ if @directory.empty? || @config_file.empty?
44
+ @absolute_config_file = ''
45
+ else
46
+ @absolute_config_file = ( ! @submodule.empty? ? File.join(@directory, @submodule, @config_file) : File.join(@directory, @config_file) )
47
+ ObjectSpace.define_finalizer(self, self.class.finalize(@absolute_config_file))
48
+ end
49
+ return self
50
+ end
51
+
52
+ #---
53
+
54
+ def config_file=config_file
55
+ @config_file = string(config_file)
56
+
57
+ set_absolute_config_file
58
+ load if @autoload
59
+ end
60
+
61
+ #-----------------------------------------------------------------------------
62
+
63
+ def get(key, default = '', format = false)
64
+ value = default
65
+ key = string(key)
66
+
67
+ if ! @properties || ! @properties.is_a?(Hash)
68
+ @properties = {}
69
+ end
70
+ if @properties.has_key?(key)
71
+ value = @properties[key]
72
+ end
73
+ return filter(value, format)
74
+ end
75
+
76
+ #---
77
+
78
+ def set(key, value = '')
79
+ key = string(key)
80
+
81
+ if ! @properties || ! @properties.is_a?(Hash)
82
+ @properties = {}
83
+ end
84
+ @properties[key] = value
85
+ save if @autosave
86
+ return self
87
+ end
88
+
89
+ #---
90
+
91
+ def delete(key)
92
+ key = string(key)
93
+
94
+ if ! @properties || ! @properties.is_a?(Hash)
95
+ @properties = {}
96
+ end
97
+ @properties.delete(key)
98
+ save if @autosave
99
+ return self
100
+ end
101
+
102
+ #---
103
+
104
+ def get_group(group, name = '', key = nil, default = {}, format = false)
105
+ info = get(group, {})
106
+ value = info
107
+
108
+ if name
109
+ name = string(name)
110
+ if info.has_key?(name) && info[name].is_a?(Hash)
111
+ if key && ! key.empty?
112
+ key = string(key)
113
+ if info[name].has_key?(key)
114
+ value = info[name][key]
115
+ else
116
+ value = default
117
+ end
118
+ else
119
+ value = info[name]
120
+ end
121
+ else
122
+ value = default
123
+ end
124
+ end
125
+ return filter(value, format)
126
+ end
127
+
128
+ #---
129
+
130
+ def set_group(group, name, key = nil, value = {})
131
+ group = string(group)
132
+ name = string(name)
133
+
134
+ if ! @properties || ! @properties.is_a?(Hash)
135
+ @properties = {}
136
+ end
137
+ if ! @properties[group] || ! @properties[group].is_a?(Hash)
138
+ @properties[group] = {}
139
+ end
140
+
141
+ if key && ! key.empty?
142
+ key = string(key)
143
+ if ! @properties[group][name] || ! @properties[group][name].is_a?(Hash)
144
+ @properties[group][name] = {}
145
+ end
146
+ @properties[group][name][key] = value
147
+
148
+ else
149
+ @properties[group][name] = value
150
+ end
151
+ save if @autosave
152
+ return self
153
+ end
154
+
155
+ #---
156
+
157
+ def delete_group(group, name, key = nil)
158
+ group = string(group)
159
+ name = string(name)
160
+
161
+ if ! @properties || ! @properties.is_a?(Hash)
162
+ @properties = {}
163
+ end
164
+ if ! @properties[group] || ! @properties[group].is_a?(Hash)
165
+ @properties[group] = {}
166
+ end
167
+
168
+ if key && ! key.empty?
169
+ key = string(key)
170
+ if @properties[group][name] && @properties[group][name].is_a?(Hash)
171
+ @properties[group][name].delete(key)
172
+ end
173
+ else
174
+ @properties[group].delete(name)
175
+ end
176
+ save if @autosave
177
+ return self
178
+ end
179
+
180
+ #-----------------------------------------------------------------------------
181
+ # Import / Export
182
+
183
+ def export
184
+ return @properties
185
+ end
186
+
187
+ #-----------------------------------------------------------------------------
188
+ # Configuration loading / saving
189
+
190
+ def load
191
+ if can_persist?
192
+ config = Coral::Util::Disk.read(@absolute_config_file)
193
+ if config && ! config.empty?
194
+ @properties = JSON.parse(config)
195
+ end
196
+ end
197
+ return self
198
+ end
199
+
200
+ #---
201
+
202
+ def save(options = {})
203
+ if can_persist?
204
+ config = JSON.generate(@properties)
205
+ if config && ! config.empty?
206
+ Coral::Util::Disk.write(@absolute_config_file, config)
207
+ commit(@absolute_config_file, options) if @autocommit
208
+ end
209
+ end
210
+ return self
211
+ end
212
+
213
+ #-----------------------------------------------------------------------------
214
+ # Checks
215
+
216
+ def can_persist?
217
+ success = super
218
+ success = false if success && @absolute_config_file.empty?
219
+ return success
220
+ end
221
+ end
222
+ end
@@ -0,0 +1,156 @@
1
+
2
+ module Coral
3
+ class Repository < Core
4
+
5
+ #-----------------------------------------------------------------------------
6
+ # Constructor / Destructor
7
+
8
+ def initialize(options = {})
9
+ super(options)
10
+
11
+ @name = ( options.has_key?(:name) ? string(options[:name]) : '' )
12
+ @directory = ( options.has_key?(:directory) ? string(options[:directory]) : '' )
13
+ @submodule = ( options.has_key?(:submodule) ? string(options[:submodule]) : '' )
14
+ @remote_dir = ( options.has_key?(:remote_dir) ? string(options[:remote_dir]) : '' )
15
+
16
+ ensure_git(true)
17
+ end
18
+
19
+ #-----------------------------------------------------------------------------
20
+ # Property accessors / modifiers
21
+
22
+ attr_accessor :name, :remote_dir
23
+ attr_reader :directory, :submodule, :git
24
+
25
+ #---
26
+
27
+ def ensure_git(reset = false)
28
+ if reset || ! @git
29
+ if @directory.empty?
30
+ @git = nil
31
+ else
32
+ directory = @directory
33
+ if ! @submodule.empty?
34
+ directory = File.join(@directory, @submodule)
35
+ end
36
+ @git = Git.open(directory, {
37
+ :log => logger,
38
+ })
39
+ end
40
+ end
41
+ return self
42
+ end
43
+
44
+ #---
45
+
46
+ def set_repository(directory = '', submodule = '')
47
+ @directory = string(directory)
48
+ @submodule = string(submodule)
49
+ ensure_git(true)
50
+ return self
51
+ end
52
+
53
+ #-----------------------------------------------------------------------------
54
+
55
+ def set_remote(name, hosts, options = {})
56
+ if can_persist?
57
+ hosts = array(hosts)
58
+
59
+ delete_remote(name)
60
+ return self if hosts.empty?
61
+
62
+ if @remote_dir && ! options.has_key?(:repo)
63
+ options[:repo] = @remote_dir
64
+ end
65
+
66
+ git.add_remote(name, Git.url(hosts.shift, options[:repo], options))
67
+
68
+ if ! hosts.empty?
69
+ remote = git.remote(name)
70
+
71
+ options[:add] = true
72
+
73
+ hosts.each do |host|
74
+ git_url = Git.url(host, options[:repo], options)
75
+ remote.set_url(git_url, options)
76
+ end
77
+ end
78
+ end
79
+ return self
80
+ end
81
+
82
+ #---
83
+
84
+ def delete_remote(name)
85
+ if can_persist?
86
+ remote = @git.remote(name)
87
+ if remote && remote.url && ! remote.url.empty?
88
+ remote.remove
89
+ end
90
+ end
91
+ return self
92
+ end
93
+
94
+ #-----------------------------------------------------------------------------
95
+ # Git operations
96
+
97
+ def commit(files = '.', options = {})
98
+ if can_persist?
99
+ time = Time.new.strftime("%Y-%m-%d %H:%M:%S")
100
+ user = ENV['USER']
101
+ message = ( options[:message] ? options[:message] : 'Saving state' )
102
+
103
+ options[:author] = ( ! options[:author].empty? ? options[:author] : '' )
104
+ options[:allow_empty] = ( options[:allow_empty] ? options[:allow_empty] : false )
105
+
106
+ unless user && ! user.empty?
107
+ user = 'UNKNOWN'
108
+ end
109
+
110
+ array(files).each do |file|
111
+ @git.add(file) # Get all added and updated files
112
+ @git.add(file, { :update => true }) # Get all deleted files
113
+ end
114
+
115
+ @git.commit("#{time} by <#{user}> - #{message}", options)
116
+ end
117
+ return self
118
+ end
119
+
120
+ #-----------------------------------------------------------------------------
121
+
122
+ def push!(remote = 'origin', options = {})
123
+ if can_persist?
124
+ branch = ( options[:branch] && ! options[:branch].empty? ? options[:branch] : 'master' )
125
+ tags = ( options[:tags] ? options[:tags] : false )
126
+
127
+ return Coral::Command.new({
128
+ :command => :git,
129
+ :data => { 'git-dir=' => @git.repo.to_s },
130
+ :subcommand => {
131
+ :command => :push,
132
+ :flags => ( tags ? :tags : '' ),
133
+ :args => [ remote, branch ]
134
+ }
135
+ }).exec!(options) do |line|
136
+ block_given? ? yield(line) : true
137
+ end
138
+ end
139
+ end
140
+
141
+ #---
142
+
143
+ def push(remote = 'origin', options = {})
144
+ return push!(remote, options)
145
+ end
146
+
147
+ #-----------------------------------------------------------------------------
148
+ # Checks
149
+
150
+ def can_persist?
151
+ ensure_git
152
+ return true if @git
153
+ return false
154
+ end
155
+ end
156
+ end