coral_core 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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