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,59 @@
1
+
2
+ module Coral
3
+ module Util
4
+ class Data < Core
5
+
6
+ #-----------------------------------------------------------------------------
7
+ # Utilities
8
+
9
+ def self.merge(objects, merge_arrays = false)
10
+ value = nil
11
+ return value unless objects
12
+
13
+ unless objects.is_a?(Array)
14
+ objects = [ objects ]
15
+ end
16
+
17
+ objects.each do |object|
18
+ value = recursive_merge(value, object, merge_arrays)
19
+ end
20
+ return value
21
+ end
22
+
23
+ #---
24
+
25
+ def self.recursive_merge(overrides, data, merge_arrays = false)
26
+ return data unless overrides
27
+ return overrides unless data
28
+
29
+ if overrides.is_a?(Hash)
30
+ overrides.each do |name, override|
31
+ if data.is_a?(Hash)
32
+ if data[name]
33
+ data[name] = recursive_merge(override, data[name])
34
+ else
35
+ begin
36
+ item = override.dup
37
+ rescue TypeError
38
+ item = override
39
+ end
40
+ data[name] = recursive_merge(override, item)
41
+ end
42
+ else
43
+ data = overrides
44
+ end
45
+ end
46
+ elsif merge_arrays && overrides.is_a?(Array)
47
+ if data.is_a?(Array)
48
+ data = data | overrides
49
+ else
50
+ data = overrides
51
+ end
52
+ else
53
+ data = overrides
54
+ end
55
+ return data
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,82 @@
1
+
2
+ module Coral
3
+ module Util
4
+ class Disk < Core
5
+
6
+ #-----------------------------------------------------------------------------
7
+ # Properties
8
+
9
+ @@files = {}
10
+
11
+ #-----------------------------------------------------------------------------
12
+ # Utilities
13
+
14
+ def self.open(file_name, options = {}, reset = false)
15
+ mode = string(options[:mode])
16
+ separator = ( options[:separator] ? options[:separator] : false )
17
+ description = ( options[:description] ? options[:description] : '' )
18
+
19
+ if @@files.has_key?(file_name) && ! reset
20
+ reset = true if ! mode.empty? && mode != @@files[file_name][:mode]
21
+ end
22
+
23
+ if ! @@files.has_key?(file_name) || ! @@files[file_name][:file] || reset
24
+ @@files[file_name][:file].close if @@files[file_name][:file]
25
+ unless mode.empty?
26
+ @@files[file_name] = {
27
+ :file => File.open(file_name, mode),
28
+ :mode => mode,
29
+ }
30
+ end
31
+ end
32
+ return @@files[file_name][:file]
33
+ end
34
+
35
+ #---
36
+
37
+ def self.read(file_name, options = {})
38
+ options[:mode] = ( options[:mode] ? options[:mode] : 'r' )
39
+ file = open(file_name, options)
40
+
41
+ if file
42
+ return file.read
43
+ end
44
+ return nil
45
+ end
46
+
47
+ #---
48
+
49
+ def self.write(file_name, data, options = {})
50
+ options[:mode] = ( options[:mode] ? options[:mode] : 'w' )
51
+ file = open(file_name, options)
52
+
53
+ if file
54
+ return file.write(data)
55
+ end
56
+ return nil
57
+ end
58
+
59
+ #---
60
+
61
+ def self.log(data, options = {})
62
+ reset = ( options[:file_name] || options[:mode] )
63
+ file = open(( options[:file_name] ? options[:file_name] : 'log.txt' ), options, reset)
64
+ if file
65
+ file.write("--------------------------------------\n") if separator
66
+ file.write("#{description}\n") if description
67
+ file.write("#{data}\n")
68
+ end
69
+ end
70
+
71
+ #---
72
+
73
+ def self.close(file_names = [])
74
+ file_names = @@files.keys unless file_names && ! file_names.empty?
75
+ array(file_names).each do |file_name|
76
+ @@files[file_name][:file].close if @@files[file_name][:file]
77
+ @@files.delete(file_name)
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,58 @@
1
+
2
+ module Git
3
+
4
+ #*******************************************************************************
5
+ # Errors
6
+
7
+ class GitDirectoryError < StandardError
8
+ end
9
+
10
+ #*******************************************************************************
11
+ # Base Git definition
12
+
13
+ class Base
14
+
15
+ #-----------------------------------------------------------------------------
16
+ # Constructor / Destructor
17
+
18
+ def initialize(options = {})
19
+ if working_dir = options[:working_directory]
20
+ options[:repository] ||= File.join(working_dir, '.git')
21
+
22
+ if File.file?(options[:repository])
23
+ File.read(options[:repository]).each_line do |line|
24
+ matches = line.match(/^\s*gitdir:\s*(.+)\s*/)
25
+ if matches.length && matches[1]
26
+ options[:repository] = matches[1]
27
+ break
28
+ end
29
+ end
30
+ end
31
+
32
+ if File.directory?(options[:repository])
33
+ options[:index] ||= File.join(options[:repository], 'index')
34
+ else
35
+ raise GitDirectoryError.new("Git repository directory #{options[:repository]} not found for #{working_dir}")
36
+ end
37
+ end
38
+
39
+ if options[:log]
40
+ @logger = options[:log]
41
+ @logger.info("Starting Git")
42
+ else
43
+ @logger = nil
44
+ end
45
+
46
+ @working_directory = options[:working_directory] ? Git::WorkingDirectory.new(options[:working_directory]) : nil
47
+ @repository = options[:repository] ? Git::Repository.new(options[:repository]) : nil
48
+ @index = options[:index] ? Git::Index.new(options[:index], false) : nil
49
+ end
50
+
51
+ #-----------------------------------------------------------------------------
52
+ # Commit extensions
53
+
54
+ def add(path = '.', opts = {})
55
+ self.lib.add(path, opts)
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,82 @@
1
+
2
+ module Git
3
+ class Lib
4
+
5
+ #-----------------------------------------------------------------------------
6
+ # Commit extensions
7
+
8
+ def add(path = '.', opts = {})
9
+ arr_opts = []
10
+ arr_opts << '-u' if opts[:update]
11
+ if path.is_a?(Array)
12
+ arr_opts += path
13
+ else
14
+ arr_opts << path
15
+ end
16
+ command('add', arr_opts)
17
+ end
18
+
19
+ #---
20
+
21
+ def commit(message, opts = {})
22
+ arr_opts = ['-m', message]
23
+ arr_opts << "--author=\'#{opts[:author]}\'" unless opts[:author] && opts[:author].empty?
24
+ arr_opts << '-a' if opts[:add_all]
25
+ arr_opts << '--allow-empty' if opts[:allow_empty]
26
+ command('commit', arr_opts)
27
+ end
28
+
29
+ #-----------------------------------------------------------------------------
30
+ # Remote extensions
31
+
32
+ def remote_add(name, url, opts = {})
33
+ arr_opts = ['add']
34
+ arr_opts << '-f' if opts[:with_fetch]
35
+ arr_opts << name
36
+ arr_opts << url
37
+
38
+ command('remote', arr_opts)
39
+ end
40
+
41
+ #---
42
+
43
+ def remote_set_url(name, url, opts = {})
44
+ arr_opts = ['set-url']
45
+
46
+ if opts[:add]
47
+ arr_opts << '--add' if opts[:add]
48
+ end
49
+
50
+ if opts[:delete]
51
+ arr_opts << '--delete' if opts[:delete]
52
+ end
53
+
54
+ if opts[:push]
55
+ arr_opts << '--push' if opts[:push]
56
+ end
57
+
58
+ arr_opts << name
59
+ arr_opts << url
60
+
61
+ command('remote', arr_opts)
62
+ end
63
+
64
+ #---
65
+
66
+ def remote_remove(name)
67
+ command('remote', ['rm', name])
68
+ end
69
+
70
+ #-----------------------------------------------------------------------------
71
+ # Utilities
72
+
73
+ def escape(s)
74
+ escaped = s.to_s.gsub('"', '\'')
75
+ if escaped =~ /^\-+/
76
+ escaped
77
+ else
78
+ %Q{"#{escaped}"}
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,12 @@
1
+
2
+ module Git
3
+ class Remote
4
+
5
+ #-----------------------------------------------------------------------------
6
+ # Remote endpoints
7
+
8
+ def set_url(url, opts = {})
9
+ @base.lib.remote_set_url(@name, url, opts)
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,15 @@
1
+
2
+ require 'git'
3
+
4
+ module Git
5
+
6
+ #-----------------------------------------------------------------------------
7
+ # Utilities
8
+
9
+ def self.url(host, repo, options = {})
10
+ options[:user] = ( options[:user] ? options[:user] : 'git' )
11
+ options[:auth] = ( options[:auth] ? options[:auth] : true )
12
+
13
+ return options[:user] + ( options[:auth] ? '@' : '://' ) + host + ( options[:auth] ? ':' : '/' ) + repo
14
+ end
15
+ end
@@ -0,0 +1,178 @@
1
+
2
+ module Coral
3
+ module Util
4
+ class Shell < Core
5
+
6
+ #-----------------------------------------------------------------------------
7
+ # Utilities
8
+
9
+ def self.exec!(command, options = {})
10
+ min = ( options[:min] ? options[:min].to_i : 1 )
11
+ tries = ( options[:tries] ? options[:tries].to_i : min )
12
+ tries = ( min > tries ? min : tries )
13
+
14
+ info_prefix = ( options[:info_prefix] ? options[:info_prefix] : '' )
15
+ info_suffix = ( options[:info_suffix] ? options[:info_suffix] : '' )
16
+ error_prefix = ( options[:error_prefix] ? options[:error_prefix] : '' )
17
+ error_suffix = ( options[:error_suffix] ? options[:error_suffix] : '' )
18
+
19
+ conditions = Coral::Event.instance(options[:exit], true)
20
+
21
+ $stdout.sync = true
22
+ $stderr.sync = true
23
+
24
+ for i in tries.downto(1)
25
+ ui.info(">> running: #{command}")
26
+
27
+ begin
28
+ t1, output_new, output_orig = pipe_exec_stream!($stdout, conditions, {
29
+ :prefix => info_prefix,
30
+ :suffix => info_suffix,
31
+ }) do |line|
32
+ block_given? ? yield(line) : true
33
+ end
34
+
35
+ t2, error_new, error_orig = pipe_exec_stream!($stderr, conditions, {
36
+ :prefix => error_prefix,
37
+ :suffix => error_suffix,
38
+ }) do |line|
39
+ block_given? ? yield(line) : true
40
+ end
41
+
42
+ system_success = system(command)
43
+
44
+ ensure
45
+ output_success = close_exec_pipe(t1, $stdout, output_orig, output_new)
46
+ error_success = close_exec_pipe(t2, $stderr, error_orig, error_new)
47
+ end
48
+ ui.info('')
49
+
50
+ success = ( system_success && output_success && error_success )
51
+
52
+ min -= 1
53
+ break if success && min <= 0 && conditions.empty?
54
+ end
55
+ unless conditions.empty?
56
+ success = false
57
+ end
58
+
59
+ return success
60
+ end
61
+
62
+ #---
63
+
64
+ def self.exec(command, options = {})
65
+ return exec!(command, options)
66
+ end
67
+
68
+ #---
69
+
70
+ def self.pipe_exec_stream!(output, conditions, options)
71
+ original = output.dup
72
+ read, write = IO.pipe
73
+
74
+ match_prefix = ( options[:match_prefix] ? options[:match_prefix] : 'EXIT' )
75
+
76
+ thread = process_stream!(read, original, options) do |line|
77
+ check_conditions!(line, conditions, match_prefix) do
78
+ block_given? ? yield(line) : true
79
+ end
80
+ end
81
+
82
+ thread.abort_on_exception = false
83
+
84
+ output.reopen(write)
85
+ return thread, write, original
86
+ end
87
+
88
+ #---
89
+
90
+ def self.close_exec_pipe(thread, output, original, write)
91
+ output.reopen(original)
92
+
93
+ write.close
94
+ success = thread.value
95
+ Thread.kill(thread) # Die bastard, die!
96
+
97
+ original.close
98
+ return success
99
+ end
100
+
101
+ #---
102
+
103
+ def self.check_conditions!(line, conditions, match_prefix = '')
104
+ prefix = ''
105
+
106
+ unless ! conditions || conditions.empty?
107
+ conditions.each do |key, event|
108
+ if event.check(line)
109
+ prefix = match_prefix
110
+ conditions.delete(key)
111
+ end
112
+ end
113
+ end
114
+
115
+ result = true
116
+ if block_given?
117
+ result = yield
118
+
119
+ unless prefix.empty?
120
+ case result
121
+ when Hash
122
+ result[:prefix] = prefix
123
+ else
124
+ result = { :success => result, :prefix => prefix }
125
+ end
126
+ end
127
+ end
128
+ return result
129
+ end
130
+
131
+ #---
132
+
133
+ def self.process_stream!(input, output, options)
134
+ return Thread.new do
135
+ success = true
136
+ default_prefix = ( options[:prefix] ? options[:prefix] : '' )
137
+ default_suffix = ( options[:suffix] ? options[:suffix] : '' )
138
+
139
+ begin
140
+ while ( data = input.readpartial(1024) )
141
+ message = data.strip
142
+ newline = ( data[-1,1].match(/\n/) ? true : false )
143
+
144
+ unless message.empty?
145
+ lines = message.split(/\n/)
146
+ lines.each_with_index do |line, index|
147
+ prefix = default_prefix
148
+ suffix = default_suffix
149
+
150
+ if block_given?
151
+ result = yield(line)
152
+
153
+ if result && result.is_a?(Hash)
154
+ prefix = result[:prefix]
155
+ suffix = result[:suffix]
156
+ result = result[:success]
157
+ end
158
+ success = result if success
159
+ end
160
+
161
+ prefix = ( prefix && ! prefix.empty? ? "#{prefix}: " : '' )
162
+ suffix = ( suffix && ! suffix.empty? ? suffix : '' )
163
+ eol = ( index < lines.length - 1 || newline ? "\n" : ' ' )
164
+
165
+ output.write(prefix.lstrip + line + suffix.rstrip + eol)
166
+ end
167
+ end
168
+ end
169
+ rescue EOFError
170
+ end
171
+
172
+ input.close
173
+ success
174
+ end
175
+ end
176
+ end
177
+ end
178
+ end
data/lib/coral_core.rb ADDED
@@ -0,0 +1,49 @@
1
+
2
+ home = File.dirname(__FILE__)
3
+
4
+ $:.unshift(home) unless
5
+ $:.include?(home) || $:.include?(File.expand_path(home))
6
+
7
+ #-------------------------------------------------------------------------------
8
+
9
+ require 'rubygems'
10
+
11
+ #---
12
+
13
+ # Include core
14
+ [ :interface, :core ].each do |name|
15
+ require File.join('coral_core', name.to_s + ".rb")
16
+ end
17
+
18
+ # Include utilities
19
+ [ :git, :data, :disk, :shell ].each do |name|
20
+ require File.join('coral_core', 'util', name.to_s + ".rb")
21
+ end
22
+
23
+ # Include Git overrides
24
+ Dir.glob(File.join(home, 'coral_core', 'util', 'git', '*.rb')).each do |file|
25
+ require file
26
+ end
27
+
28
+ # Include data model
29
+ [ :event, :command, :repository, :memory ].each do |name|
30
+ require File.join('coral_core', name.to_s + ".rb")
31
+ end
32
+
33
+ # Include specialized events
34
+ Dir.glob(File.join(home, 'coral_core', 'event', '*.rb')).each do |file|
35
+ require file
36
+ end
37
+
38
+ #*******************************************************************************
39
+ # Coral Core Library
40
+ #
41
+ # This provides core data elements and utilities used in the Coral gems.
42
+ #
43
+ # Author:: Adrian Webb (mailto:adrian.webb@coraltech.net)
44
+ # License:: GPLv3
45
+ module Coral
46
+
47
+ VERSION = File.read(File.join(File.dirname(__FILE__), '..', 'VERSION'))
48
+
49
+ end