kit 0.0.6 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENCE.txt +21 -0
- data/README.rdoc +54 -0
- data/lib/kit.rb +85 -44
- data/lib/kit/bit.rb +110 -23
- data/lib/kit/db_sqlite3.rb +56 -17
- metadata +6 -14
- data/README +0 -60
- data/kits/my_kit/bit.rb +0 -54
- data/kits/my_kit/clones/my_project.rb +0 -8
- data/kits/my_kit/commits/my_project.rb +0 -7
- data/kits/my_kit/config.yml +0 -36
- data/kits/my_kit/sqlite3_actions.sql +0 -16
- data/kits/my_kit/sqlite3_info.sql +0 -15
- data/kits/my_kit/upgrades/my_project.rb +0 -7
- data/spec/my_kit/my_kit.yml +0 -17
- data/spec/my_kit_spec.rb +0 -66
data/LICENCE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2011 Evan Boyd Sosenko
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
= Kit
|
2
|
+
|
3
|
+
== What is Kit?
|
4
|
+
|
5
|
+
Kit is a framework for making simple management tools called kits. Each kit keeps track of a set of objects (the bits) and info about them. Actions of different types can be queued as tasks and run separately. Bits are put into groups so that code for each action type can be different for each group. The tasks are stored in a seperate database, so the permissions for adding tasks and managing bit meta information can be set separately.
|
6
|
+
|
7
|
+
== Using Kit
|
8
|
+
|
9
|
+
To use Kit, you fist need a kit. You can download a {pre-build kit}[https://github.com/razor-x/kit/wiki/Pre-built-kits] or {build your own kit}[https://github.com/razor-x/kit/wiki/Building-your-own-kit]. Once you have a kit, create a new kit object with
|
10
|
+
|
11
|
+
k = Kit.new "/path_to/config.yml"
|
12
|
+
|
13
|
+
where the config file is either the default config file included with the kit, or your own that may override some of the defaults. Now you can start adding bits and queuing and running tasks:
|
14
|
+
|
15
|
+
bit = { :name => "foo", :group_name => "bar" }
|
16
|
+
k.add_bit bit
|
17
|
+
|
18
|
+
{ :baz => { :bit => 1 } }.each do |action, options|
|
19
|
+
k.add_task action, options
|
20
|
+
end
|
21
|
+
|
22
|
+
k.run_tasks
|
23
|
+
|
24
|
+
For more information on what methods are available see the {YARD documentation}[https://rubygems.org/gems/kit] which is hosted at RubyGems.org. For more detailed information on how to use Kit, check out the wiki[https://github.com/razor-x/kit/wiki].
|
25
|
+
|
26
|
+
== Installation
|
27
|
+
|
28
|
+
=== Gem Installation
|
29
|
+
|
30
|
+
Download and install Kit with
|
31
|
+
|
32
|
+
gem install kit
|
33
|
+
|
34
|
+
== Development
|
35
|
+
|
36
|
+
=== Source Repository
|
37
|
+
|
38
|
+
Kit is currently hosted at github. The github web page is
|
39
|
+
https://github.com/razor-x/kit. To clone the project run
|
40
|
+
|
41
|
+
git clone git://github.com/razor-x/kit.git
|
42
|
+
|
43
|
+
After cloning, you should run yard to generate documentation for the source.
|
44
|
+
|
45
|
+
== License
|
46
|
+
|
47
|
+
Kit is licensed under the MIT license.
|
48
|
+
|
49
|
+
== Warranty
|
50
|
+
|
51
|
+
This software is provided "as is" and without any express or
|
52
|
+
implied warranties, including, without limitation, the implied
|
53
|
+
warranties of merchantibility and fitness for a particular
|
54
|
+
purpose.
|
data/lib/kit.rb
CHANGED
@@ -1,58 +1,71 @@
|
|
1
1
|
require 'yaml'
|
2
2
|
|
3
|
+
# Primary class for Kit.
|
3
4
|
class Kit
|
5
|
+
|
6
|
+
require 'kit/bit'
|
7
|
+
|
8
|
+
# Exceptions.
|
9
|
+
|
10
|
+
# Raised when an action is specified that is not in the defined actions for the kit.
|
11
|
+
class NoAction < RuntimeError
|
12
|
+
end
|
13
|
+
|
4
14
|
# Loads the settings for the kit.
|
5
15
|
# @param [String, Hash] config path to kit config file or hash of kit settings
|
6
16
|
def initialize config
|
7
|
-
|
17
|
+
# Load the config and merge with the default config.
|
8
18
|
config = load_config_file config if File.exists? config
|
9
19
|
|
10
20
|
fail "No path to kit set" unless config[:kits_path]
|
11
21
|
|
12
22
|
@@kit_path = config[:kits_path]
|
13
|
-
|
14
23
|
defaults = YAML.load File.read @@kit_path + "/config.yml"
|
15
24
|
config = defaults.merge config
|
16
25
|
|
26
|
+
# Load backend for selected database type.
|
17
27
|
load 'kit/db_sqlite3.rb' if config[:db_backend] == :sqlite3
|
18
28
|
|
19
|
-
|
29
|
+
# Load class files for the kit
|
30
|
+
begin
|
31
|
+
load @@kit_path + "/bit.rb"
|
32
|
+
load @@kit_path + "/kit.rb"
|
33
|
+
rescue LoadError
|
34
|
+
end
|
20
35
|
|
21
|
-
|
36
|
+
# Set the class variables.
|
22
37
|
@@info = config[:info]
|
38
|
+
@@unique = config[:unique]
|
23
39
|
@@actions = config[:actions]
|
40
|
+
@@status_types = [ :pending, :completed, :queued ]
|
41
|
+
@@db = Backend.new config[:db_config]
|
42
|
+
|
43
|
+
# Run initialization specific to the kit.
|
44
|
+
begin
|
45
|
+
self.kit_initialize
|
46
|
+
rescue NoMethodError
|
47
|
+
end
|
24
48
|
end
|
25
49
|
|
50
|
+
# Kit related methods.
|
51
|
+
|
52
|
+
# @return [Hash] names of actions defined for this kit
|
26
53
|
def action_types
|
27
54
|
@@actions.keys
|
28
55
|
end
|
29
56
|
|
30
|
-
#
|
31
|
-
|
32
|
-
|
33
|
-
def load_config_file file
|
34
|
-
|
35
|
-
config = YAML.load File.read file
|
36
|
-
@@config_path = File.absolute_path File.dirname file
|
37
|
-
|
38
|
-
dir = config[:kits_path]
|
39
|
-
dir = if config[:kits_path].nil?
|
40
|
-
@@config_path
|
41
|
-
else
|
42
|
-
File.absolute_path @@config_path + config[:kits_path] unless [ "/", "~" ].include? config[:kits_path][0]
|
43
|
-
end
|
44
|
-
|
45
|
-
config[:kits_path] = dir
|
46
|
-
return config
|
57
|
+
# @return [Array] names of task status types defined for this kit
|
58
|
+
def status_types
|
59
|
+
@@status_types
|
47
60
|
end
|
48
61
|
|
49
|
-
# Deletes the kit's databases
|
62
|
+
# Deletes the kit's databases.
|
50
63
|
def delete_dbs
|
51
|
-
@@db.
|
52
|
-
File.delete f
|
53
|
-
end
|
64
|
+
@@db.delete
|
54
65
|
end
|
55
66
|
|
67
|
+
# Bit related methods.
|
68
|
+
|
56
69
|
# Creates bit object if it is unique enough.
|
57
70
|
# @param [Hash] info requested initial properties of the bit
|
58
71
|
# @return [Bit, nil] the new bit or nil if too similar to a bit that already exists
|
@@ -64,35 +77,52 @@ class Kit
|
|
64
77
|
end
|
65
78
|
end
|
66
79
|
|
80
|
+
# Gets a bit that matches id or info.
|
81
|
+
# @param [Integer, Hash] bit id or hash of info unique enough to identify a bit
|
82
|
+
# @return [Bit, nil] the Bit or nil if no unique bit could be found
|
67
83
|
def get_bit info
|
68
84
|
begin
|
69
85
|
if info.is_a? Integer
|
70
86
|
Bit.new info
|
71
|
-
elsif
|
87
|
+
elsif info.is_a? Hash
|
72
88
|
Bit.new Bit::lookup_id info
|
73
89
|
end
|
74
|
-
rescue NoElement
|
90
|
+
rescue Bit::NoElement
|
75
91
|
nil
|
76
92
|
end
|
77
93
|
end
|
78
94
|
|
95
|
+
# Task related methods.
|
96
|
+
|
97
|
+
# Gets all tasks with requested status for one action type.
|
98
|
+
# @param [Symbol] name of action type to get tasks for
|
99
|
+
# @param [Symbol] task status
|
100
|
+
# @return [Array] tasks for given action type with requested status
|
101
|
+
def get_tasks_by_status action, status
|
102
|
+
@@db.select_all_actions_by_status action, @@actions[action], status
|
103
|
+
end
|
104
|
+
|
79
105
|
# Adds a new task to the corresponding action table.
|
80
106
|
# @param [Symbol] action name of the action type
|
81
107
|
# @param [Hash] options options for the corresponding action type
|
82
108
|
def add_task action, options
|
83
|
-
|
84
|
-
|
109
|
+
begin
|
110
|
+
fail NoAction, "#{action}" unless @@actions.include? action
|
111
|
+
@@db.insert_action action, options
|
112
|
+
rescue NoAction => ex
|
113
|
+
puts "Could not add task: no such action: '#{ex.message}'."
|
114
|
+
end
|
85
115
|
end
|
86
116
|
|
87
117
|
# Runs all pending tasks.
|
88
118
|
def run_tasks
|
89
119
|
collect_tasks_by_bit.each do |bit, tasks|
|
90
|
-
b =
|
120
|
+
b = get_bit bit
|
121
|
+
next if b.nil?
|
91
122
|
|
92
123
|
actions = tasks.group_by { |t| t[:action] } . keys
|
93
|
-
|
94
124
|
actions.each do |a|
|
95
|
-
load @@kit_path + "/#{
|
125
|
+
load @@kit_path + "/actions/#{b.group_name}/#{a}.rb"
|
96
126
|
b.extend Actions
|
97
127
|
end
|
98
128
|
|
@@ -101,31 +131,42 @@ class Kit
|
|
101
131
|
end
|
102
132
|
|
103
133
|
b.run_all
|
104
|
-
# TODO try and use
|
134
|
+
# TODO try and use blocks here to set status to running and then complete / failed as each task runs and finishes
|
105
135
|
end
|
106
136
|
end
|
107
137
|
|
108
|
-
def get_tasks_by_status action, status
|
109
|
-
@@db.select_all_actions_by_status action, @@actions[action], status
|
110
|
-
end
|
111
|
-
|
112
138
|
private
|
113
|
-
# Gets all tasks and groups them by bit.
|
139
|
+
# Gets all pending tasks with requested status and groups them by bit.
|
114
140
|
# @return [Hash{Integer => Hash}] tasks grouped by bit id
|
115
141
|
def collect_tasks_by_bit
|
116
|
-
|
117
142
|
tasks = []
|
118
143
|
@@actions.each_key do |action|
|
119
144
|
tasks.push get_tasks_by_status action, :pending
|
120
145
|
end
|
121
146
|
tasks.flatten!
|
122
|
-
|
123
147
|
tasks.group_by { |t| t[:bit] }
|
124
148
|
end
|
125
149
|
|
126
|
-
|
127
|
-
|
150
|
+
# Converts a kit config file into a hash of kit settings.
|
151
|
+
# @param [String] file path to a kit config file in YAML format
|
152
|
+
# @return [Hash] kit settings
|
153
|
+
def load_config_file file
|
154
|
+
|
155
|
+
# Load the file using YAML.
|
156
|
+
config = YAML.load File.read file
|
157
|
+
@@config_path = File.absolute_path File.dirname file
|
158
|
+
|
159
|
+
# Determine the path to the kit.
|
160
|
+
config[:kits_path] = \
|
161
|
+
if config[:kits_path].nil?
|
162
|
+
@@config_path
|
163
|
+
elsif ! [ "/", "~" ].include? config[:kits_path][0]
|
164
|
+
File.absolute_path @@config_path + config[:kits_path]
|
165
|
+
else
|
166
|
+
config[:kits_path]
|
167
|
+
end
|
128
168
|
|
129
|
-
|
169
|
+
return config
|
170
|
+
end
|
130
171
|
|
131
|
-
|
172
|
+
end
|
data/lib/kit/bit.rb
CHANGED
@@ -1,45 +1,133 @@
|
|
1
|
+
# Class to manage individual bits.
|
1
2
|
class Bit < Kit
|
2
3
|
|
4
|
+
# Exceptions.
|
5
|
+
|
6
|
+
# Raised when element exists but was not expected.
|
7
|
+
class DuplicateElement < RuntimeError
|
8
|
+
end
|
9
|
+
|
10
|
+
# Raised when no element exists.
|
11
|
+
class NoElement < RuntimeError
|
12
|
+
end
|
13
|
+
|
14
|
+
# Raised when not enough info is given to perform the operation.
|
15
|
+
class MissingValues < RuntimeError
|
16
|
+
end
|
17
|
+
|
3
18
|
attr_reader :id
|
4
19
|
|
5
|
-
# Loads all bit info from database, or attempts to add new bit to database
|
20
|
+
# Loads all bit info from database, or attempts to add new bit to database.
|
21
|
+
# Raises a TypeError if not given an integer or hash.
|
6
22
|
# @param [Integer, Hash] info id of bit or info for new bit
|
7
23
|
def initialize info
|
24
|
+
@id = \
|
25
|
+
if info.is_a? Integer
|
26
|
+
info
|
27
|
+
elsif info.is_a? Hash
|
28
|
+
info.each do |key, value|
|
29
|
+
instance_variable_set "@#{key}", value
|
30
|
+
end
|
31
|
+
g = @group_name if @group_name
|
32
|
+
g = @group_id if @group_id
|
33
|
+
self.group = g, info
|
34
|
+
insert_new
|
35
|
+
else
|
36
|
+
fail TypeError
|
37
|
+
end
|
38
|
+
load_info
|
39
|
+
end
|
8
40
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
41
|
+
private
|
42
|
+
|
43
|
+
# Add support fot the dynamic instance variables.
|
44
|
+
class ::Array
|
45
|
+
# Makes a hash that maps symbols in the array to instance variable values.
|
46
|
+
# @param [Object] obj the object with the instance variables to use
|
47
|
+
# @param [Array] exclude instance variables named in this array as symbols are excluded from the hash
|
48
|
+
# @return [Hash] mapping of symbols in the array to instance variable values
|
49
|
+
def hash_ivars obj, exclude = []
|
50
|
+
h = {}
|
51
|
+
self.each do |x|
|
52
|
+
h[x] = obj.instance_variable_get "@#{x}" unless exclude.include? x
|
53
|
+
end
|
54
|
+
return h
|
55
|
+
end
|
56
|
+
end
|
15
57
|
|
16
|
-
|
58
|
+
# Set group by name or id.
|
59
|
+
# @param [Integer, String] group id or info for group
|
60
|
+
def group= group
|
61
|
+
@group_id = group if group.is_a? Integer
|
62
|
+
@group_name = group if group.is_a? String
|
17
63
|
|
64
|
+
if @group_id.nil?
|
65
|
+
g = @@db.select_info_by_name :groups, [ :rowid ], @group_name
|
66
|
+
@group_id = if g.nil? then insert_new_group else g[:rowid] end
|
67
|
+
end
|
18
68
|
end
|
19
69
|
|
20
|
-
#
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
70
|
+
# Inserts a new bit into the database using the availible instance variables.
|
71
|
+
# Raises a MissingValues if required values are not given.
|
72
|
+
# Raises a DuplicateElement if a bit with unique values already exists.
|
73
|
+
def insert_new
|
74
|
+
uniq = @@unique[:bits].hash_ivars self
|
75
|
+
uniq.each { |x| fail MissingValues if x.nil? }
|
76
|
+
|
77
|
+
fail DuplicateElement if lookup_id uniq
|
78
|
+
|
79
|
+
data = @@info[:bits].hash_ivars self, [ :rowid ]
|
80
|
+
@@db.insert_info :bits, data
|
81
|
+
end
|
82
|
+
|
83
|
+
# (see #insert_new)
|
84
|
+
def insert_new_group
|
85
|
+
fail MissingValues if @group_name.nil?
|
86
|
+
fail DuplicateElement if @@db.select_info_by_name :groups, @@unique[:groups], @group_name
|
87
|
+
|
88
|
+
data = @@info[:groups].hash_ivars self, [ :rowid, :name ]
|
89
|
+
data[:name] = @group_name
|
90
|
+
|
91
|
+
@@db.insert_info :groups, data
|
92
|
+
end
|
93
|
+
|
94
|
+
# Loads all bit info from the database into instance variables.
|
95
|
+
def load_info
|
96
|
+
fail MissingValues if @id.nil?
|
97
|
+
info = @@db.select_info_by_id :bits, @@info[:bits], @id
|
98
|
+
fail NoElement unless info
|
99
|
+
|
100
|
+
group_info = @@db.select_info_by_id :groups, @@info[:groups], info[:group_id]
|
101
|
+
info[:group_name] = group_info[:name]
|
102
|
+
group_info.delete :rowid
|
103
|
+
group_info.delete :name
|
104
|
+
|
105
|
+
info.merge! group_info
|
106
|
+
info.delete :rowid
|
107
|
+
|
108
|
+
info.each do |key, value|
|
109
|
+
instance_variable_set "@#{key}", value
|
110
|
+
self.class.send :attr_reader, key
|
111
|
+
self.class.send :public, key
|
25
112
|
end
|
26
113
|
end
|
27
114
|
|
28
|
-
|
115
|
+
public
|
116
|
+
# Add a task to the array of pending tasks.
|
29
117
|
# @param [Hash] task info for task
|
30
118
|
def queue_task task
|
31
119
|
@tasks = [] unless @tasks
|
32
120
|
@tasks << task
|
33
121
|
end
|
34
122
|
|
35
|
-
|
123
|
+
# def clear_task task
|
36
124
|
# action = task[:action]
|
37
125
|
# id = task[:rowid]
|
38
126
|
#
|
39
127
|
# @@db.delete_action_by_id action, id
|
40
|
-
|
128
|
+
# end
|
41
129
|
|
42
|
-
# Runs all tasks in the list of pending tasks
|
130
|
+
# Runs all tasks in the list of pending tasks and returns the status of each run task.
|
43
131
|
# @return [Hash] key is task id
|
44
132
|
def run_all
|
45
133
|
tasks = @tasks
|
@@ -55,14 +143,13 @@ class Bit < Kit
|
|
55
143
|
end
|
56
144
|
status
|
57
145
|
end
|
58
|
-
|
59
|
-
|
60
146
|
end
|
61
147
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
148
|
+
# Finds bit ids that match given criteria.
|
149
|
+
# @param [Hash] criteria field / value pairs that will be matched against
|
150
|
+
# @return [Array] bit ids that match criteria
|
151
|
+
def lookup_id criteria
|
152
|
+
@@db.select_info_by_criteria :bits, [:rowid], criteria
|
66
153
|
end
|
67
154
|
|
68
155
|
end
|
data/lib/kit/db_sqlite3.rb
CHANGED
@@ -1,7 +1,9 @@
|
|
1
1
|
require 'sqlite3'
|
2
2
|
|
3
|
-
# Methods to make sqlite3 interation more
|
3
|
+
# Methods to make sqlite3 interation more concise.
|
4
4
|
module SQLite3Tools
|
5
|
+
|
6
|
+
# Array methods.
|
5
7
|
class ::Array
|
6
8
|
# Converts an array of symbols to a string of backquoted strings for use in SELECT statement
|
7
9
|
# @return [String]
|
@@ -24,6 +26,7 @@ module SQLite3Tools
|
|
24
26
|
end
|
25
27
|
end
|
26
28
|
|
29
|
+
# Integer methods.
|
27
30
|
class ::Integer
|
28
31
|
# Generates placeholder string for INSERT statements.
|
29
32
|
# @return String placeholder
|
@@ -37,6 +40,7 @@ module SQLite3Tools
|
|
37
40
|
end
|
38
41
|
end
|
39
42
|
|
43
|
+
# SQLite3 database methods.
|
40
44
|
class SQLite3::Database
|
41
45
|
# Selects given columns using given query and converts results to to hashes.
|
42
46
|
# @param [Array<Symbol>] columns names of columns to select
|
@@ -52,6 +56,7 @@ module SQLite3Tools
|
|
52
56
|
end
|
53
57
|
end
|
54
58
|
|
59
|
+
# Backend abstracts database interactions.
|
55
60
|
class Backend < Kit
|
56
61
|
|
57
62
|
include SQLite3Tools
|
@@ -114,36 +119,40 @@ class Backend < Kit
|
|
114
119
|
end
|
115
120
|
|
116
121
|
public
|
117
|
-
def select_all_actions_by_status action, fields, status
|
118
|
-
query = "FROM `#{action}` WHERE `status` = '#{status}'"
|
119
|
-
rows = @action_db.select fields, query
|
120
|
-
|
121
|
-
h = { :action => action }
|
122
|
-
rows.map { |t| t.merge h }
|
123
|
-
end
|
124
122
|
|
125
|
-
|
126
|
-
|
127
|
-
@
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
def delete_action_by_id action, id
|
132
|
-
# puts "DELETE FROM `#{action}` WHERE `rowid` = #{id}"
|
123
|
+
# Deletes database files.
|
124
|
+
def delete
|
125
|
+
@db_paths.each do |key, f|
|
126
|
+
File.delete f
|
127
|
+
end
|
133
128
|
end
|
134
129
|
|
130
|
+
# Gets the row from an info table with the given id.
|
131
|
+
# @param [Symbol] table what database table to query
|
132
|
+
# @param [Array] fields list of column names to return
|
133
|
+
# @param [Integer] id rowid of record to return
|
134
|
+
# @return [Array] hash for each returned row with a key for each requested field
|
135
135
|
def select_info_by_id table, fields, id
|
136
136
|
info = @info_db.select fields, "FROM `#{table}` WHERE `rowid` = '#{id}'"
|
137
137
|
info.first
|
138
138
|
end
|
139
139
|
|
140
|
+
# Gets the rows from an info table with the given name.
|
141
|
+
# @param table (see #select_info_by_id)
|
142
|
+
# @param fields (see #select_info_by_id)
|
143
|
+
# @param [String] name of records to return
|
144
|
+
# @return (see #select_info_by_id)
|
140
145
|
def select_info_by_name table, fields, name
|
141
146
|
info = @info_db.select fields, "FROM `#{table}` WHERE `name` = '#{name}'"
|
142
147
|
info.first
|
143
148
|
end
|
144
149
|
|
150
|
+
# Gets the rows from an info table with the given criteria.
|
151
|
+
# @param table (see #select_info_by_id)
|
152
|
+
# @param fields (see #select_info_by_id)
|
153
|
+
# @param [Hash] criteria key / value pairs required to match
|
154
|
+
# @return (see #select_info_by_id)
|
145
155
|
def select_info_by_criteria table, fields, criteria
|
146
|
-
|
147
156
|
q = []
|
148
157
|
criteria.each do |key, value|
|
149
158
|
q << "`#{key}` = '#{value}'"
|
@@ -153,8 +162,38 @@ class Backend < Kit
|
|
153
162
|
info.first
|
154
163
|
end
|
155
164
|
|
165
|
+
# Inserts a new row into an info table.
|
166
|
+
# @param table (see #select_info_by_id)
|
167
|
+
# @param [Hash] data key / value pairs for new row
|
168
|
+
# @return [Integer] rowid of new row
|
156
169
|
def insert_info table, data
|
157
170
|
@info_db.execute "INSERT INTO #{table} ( `#{data.keys.join "`, `"}` ) VALUES ( #{data.length.make_placeholders} )", data.values
|
158
171
|
@info_db.last_insert_row_id
|
159
172
|
end
|
173
|
+
|
174
|
+
# Gets the rows from the action table with given status.
|
175
|
+
# @param table (see #select_info_by_id)
|
176
|
+
# @param fields (see #select_info_by_id)
|
177
|
+
# @param [Symbol] status name of status to match
|
178
|
+
# @return (see #select_info_by_id)
|
179
|
+
def select_all_actions_by_status table, fields, status
|
180
|
+
query = "FROM `#{table}` WHERE `status` = '#{status}'"
|
181
|
+
rows = @action_db.select fields, query
|
182
|
+
|
183
|
+
rows.map { |t| t.merge ( { :action => table, :status => t[:status].to_sym } ) }
|
184
|
+
end
|
185
|
+
|
186
|
+
# Inserts a new row into an action table.
|
187
|
+
# @param (see #insert_info)
|
188
|
+
# @return (see #insert_info)
|
189
|
+
def insert_action table, data
|
190
|
+
data.merge! ( { :status => :pending.to_s, :time => Time.now.to_i } )
|
191
|
+
@action_db.execute "INSERT INTO #{table} ( `#{data.keys.join "`, `"}` ) VALUES ( #{data.length.make_placeholders} )", data.values
|
192
|
+
@action_db.last_insert_row_id
|
193
|
+
end
|
194
|
+
|
195
|
+
# def delete_action_by_id action, id
|
196
|
+
# puts "DELETE FROM `#{action}` WHERE `rowid` = #{id}"
|
197
|
+
# end
|
198
|
+
|
160
199
|
end
|
metadata
CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
|
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
6
|
- 0
|
7
|
+
- 1
|
7
8
|
- 0
|
8
|
-
|
9
|
-
version: 0.0.6
|
9
|
+
version: 0.1.0
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Evan Boyd Sosenko
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2011-05-
|
17
|
+
date: 2011-05-13 00:00:00 -07:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -32,7 +32,7 @@ dependencies:
|
|
32
32
|
version: 1.3.3
|
33
33
|
type: :runtime
|
34
34
|
version_requirements: *id001
|
35
|
-
description: "\t\tKit is a framework for making simple management tools called kits
|
35
|
+
description: "\t\tKit is a framework for making simple management tools called kits.\n"
|
36
36
|
email:
|
37
37
|
executables: []
|
38
38
|
|
@@ -44,16 +44,8 @@ files:
|
|
44
44
|
- lib/kit.rb
|
45
45
|
- lib/kit/bit.rb
|
46
46
|
- lib/kit/db_sqlite3.rb
|
47
|
-
-
|
48
|
-
-
|
49
|
-
- kits/my_kit/upgrades/my_project.rb
|
50
|
-
- kits/my_kit/sqlite3_actions.sql
|
51
|
-
- kits/my_kit/bit.rb
|
52
|
-
- kits/my_kit/config.yml
|
53
|
-
- kits/my_kit/commits/my_project.rb
|
54
|
-
- kits/my_kit/clones/my_project.rb
|
55
|
-
- spec/my_kit/my_kit.yml
|
56
|
-
- spec/my_kit_spec.rb
|
47
|
+
- LICENCE.txt
|
48
|
+
- README.rdoc
|
57
49
|
has_rdoc: true
|
58
50
|
homepage:
|
59
51
|
licenses:
|
data/README
DELETED
@@ -1,60 +0,0 @@
|
|
1
|
-
= Kit
|
2
|
-
|
3
|
-
Kit is a framework for making simple management tools called kits. Read about why I wrote kit below for an idea of what Kit can do for you.
|
4
|
-
|
5
|
-
== What is Kit?
|
6
|
-
|
7
|
-
Kit's in it's infant stage and still changing too much to document everything it does or will do. The best way to understand what Kit is about is to read the motivation behind it (see below). Of course, you can always read the yard docs or source code if you want to see how it's coming.
|
8
|
-
|
9
|
-
=== Why I wrote kit
|
10
|
-
|
11
|
-
Here are two independent problems Kit will solve (each will be a separate kit).
|
12
|
-
|
13
|
-
==== Apache server running multiple virtual hosts (vhosts)
|
14
|
-
|
15
|
-
* Each time a vhost is added things have to happen, e.g. config files need to be made, directories created, etc.
|
16
|
-
* Depending on the type of vhost, these tasks may be different e.g. what directories are made, how the conifg files look, etc.
|
17
|
-
* If vhosts are removed or moved from one type to another, things need to be archived, cleaned up, etc.
|
18
|
-
* If the config file template changes, etc., the vhosts should all get updated.
|
19
|
-
|
20
|
-
==== Web development server-side site management
|
21
|
-
|
22
|
-
Unless you're strictly using a development framework, testing and deploying new code is non-trivial. Exporting your code from your git repo may be more complicated then running cp -R, e.g. compressing JavaScript and CSS. Sometimes, the only place to test a project on is in production environment . I needed a tool that made testing and updating a site running a mix of differnt web software, i.e.
|
23
|
-
|
24
|
-
* Clone my production site to one of many testing sites.
|
25
|
-
* Push update packages to any of the production or testing sites.
|
26
|
-
* Push a git branch to any of the production or testing sites.
|
27
|
-
* Allow other developers access to all of these functions without giving them shell access or elevated user privileges.
|
28
|
-
|
29
|
-
== Building your own kit
|
30
|
-
|
31
|
-
For instructions on how to build your own kit go to
|
32
|
-
* https://github.com/razor-x/kit/wiki/Building-your-own-kit
|
33
|
-
|
34
|
-
== Installation
|
35
|
-
|
36
|
-
=== Gem Installation
|
37
|
-
|
38
|
-
Download and install Kit with the following.
|
39
|
-
|
40
|
-
gem install kit
|
41
|
-
|
42
|
-
== Development
|
43
|
-
|
44
|
-
=== Source Repository
|
45
|
-
|
46
|
-
Kit is currently hosted at github. The github web page is
|
47
|
-
https://github.com/razor-x/kit. To clone the project run
|
48
|
-
|
49
|
-
git clone git://github.com/razor-x/kit.git
|
50
|
-
|
51
|
-
== License
|
52
|
-
|
53
|
-
Kit is licensed under the GPLv3.
|
54
|
-
|
55
|
-
== Warranty
|
56
|
-
|
57
|
-
This software is provided "as is" and without any express or
|
58
|
-
implied warranties, including, without limitation, the implied
|
59
|
-
warranties of merchantibility and fitness for a particular
|
60
|
-
purpose.
|
data/kits/my_kit/bit.rb
DELETED
@@ -1,54 +0,0 @@
|
|
1
|
-
class Bit
|
2
|
-
|
3
|
-
def lookup_id uniq
|
4
|
-
@@db.select_info_by_criteria :bits, [:rowid], uniq
|
5
|
-
end
|
6
|
-
|
7
|
-
def insert_new
|
8
|
-
|
9
|
-
if @project_id.nil?
|
10
|
-
|
11
|
-
p = @@db.select_info_by_name :projects, [ :rowid ], @project_name
|
12
|
-
|
13
|
-
@project_id = if p.nil? then insert_new_project else p[:rowid] end
|
14
|
-
|
15
|
-
end
|
16
|
-
|
17
|
-
uniq = { :name => @name, :project => @project_id }
|
18
|
-
data = { :root => @root, :commit => nil, :commit_time => nil }
|
19
|
-
|
20
|
-
fail DuplicateElement if lookup_id uniq
|
21
|
-
|
22
|
-
data.merge! uniq
|
23
|
-
|
24
|
-
@@db.insert_info :bits, data
|
25
|
-
end
|
26
|
-
|
27
|
-
def insert_new_project
|
28
|
-
|
29
|
-
fail DuplicateElement if @@db.select_info_by_name :projects, [ :name ], @project_name
|
30
|
-
|
31
|
-
data = { :name => @project_name, :git => @git }
|
32
|
-
@@db.insert_info :projects, data
|
33
|
-
end
|
34
|
-
|
35
|
-
def load_info
|
36
|
-
|
37
|
-
info = @@db.select_info_by_id :bits, @@info[:bits], @id
|
38
|
-
|
39
|
-
fail NoElement unless info
|
40
|
-
|
41
|
-
@name = info[:name]
|
42
|
-
@project_id = info[:project]
|
43
|
-
|
44
|
-
project_info = @@db.select_info_by_id :projects, @@info[:projects], @project_id
|
45
|
-
info.merge! project_info
|
46
|
-
|
47
|
-
@project_name = info[:name]
|
48
|
-
@root = info[:root]
|
49
|
-
@git = info[:git]
|
50
|
-
@commit = { :name => info[:commit], :time => info[:commit_time] }
|
51
|
-
|
52
|
-
end
|
53
|
-
|
54
|
-
end
|
data/kits/my_kit/config.yml
DELETED
@@ -1,36 +0,0 @@
|
|
1
|
-
# Path to this kit's root directory.
|
2
|
-
# Absolute or relative to this config file.
|
3
|
-
# If not specified, defaults to the folder that holds this config file.
|
4
|
-
#
|
5
|
-
:kits_path:
|
6
|
-
#
|
7
|
-
# Database backend to use. Available options:
|
8
|
-
# :sqlite3
|
9
|
-
#
|
10
|
-
:db_backend: :sqlite3
|
11
|
-
#
|
12
|
-
# Path to the files to save each sqlite3 database (since only sqlite3 is supported).
|
13
|
-
# Absolute or relative to this config file.
|
14
|
-
#
|
15
|
-
:db_config:
|
16
|
-
:info: "info.db"
|
17
|
-
:actions: "actions.db"
|
18
|
-
#
|
19
|
-
# Tables and columns for each database.
|
20
|
-
#
|
21
|
-
# Each table in the :info: database must be of the form
|
22
|
-
# :table_name: [ :rowid, :name, :column_name_1, :column_name_2 ]
|
23
|
-
# where :rowid and :name are required columns.
|
24
|
-
#
|
25
|
-
:info:
|
26
|
-
:bits: [ :rowid, :name, :project, :root, :commit, :commit_time ]
|
27
|
-
:projects: [ :rowid, :name, :git ]
|
28
|
-
#
|
29
|
-
# Each table in the :actions: database must be of the form
|
30
|
-
# :table_name: [ :rowid, :bit, :status, :column_name_1, :column_name_2 ]
|
31
|
-
# where :rowid, :bit, and :status are required columns.
|
32
|
-
#
|
33
|
-
:actions:
|
34
|
-
:clones: [ :rowid, :bit, :status, :src ]
|
35
|
-
:upgrades: [ :rowid, :bit, :status, :component, :file ]
|
36
|
-
:commits: [ :rowid, :bit, :status, :commit ]
|
@@ -1,16 +0,0 @@
|
|
1
|
-
CREATE TABLE clones (
|
2
|
-
"bit" INTEGER NOT NULL,
|
3
|
-
"status" TEXT NOT NULL DEFAULT ('pending'),
|
4
|
-
"src" INTEGER NOT NULL
|
5
|
-
);
|
6
|
-
CREATE TABLE upgrades (
|
7
|
-
"bit" INTEGER NOT NULL,
|
8
|
-
"status" TEXT NOT NULL DEFAULT ('pending'),
|
9
|
-
"component" TEXT NOT NULL,
|
10
|
-
"file" TEXT NOT NULL
|
11
|
-
);
|
12
|
-
CREATE TABLE commits (
|
13
|
-
"bit" INTEGER NOT NULL,
|
14
|
-
"status" TEXT NOT NULL DEFAULT ('pending'),
|
15
|
-
"commit" TEXT
|
16
|
-
);
|
@@ -1,15 +0,0 @@
|
|
1
|
-
CREATE TABLE "permissions" (
|
2
|
-
"name" INTEGER NOT NULL,
|
3
|
-
"bit" INTEGER NOT NULL
|
4
|
-
);
|
5
|
-
CREATE TABLE projects (
|
6
|
-
"name" TEXT NOT NULL,
|
7
|
-
"git" TEXT NOT NULL
|
8
|
-
);
|
9
|
-
CREATE TABLE bits (
|
10
|
-
"name" TEXT NOT NULL,
|
11
|
-
"project" INTEGER NOT NULL,
|
12
|
-
"root" TEXT NOT NULL,
|
13
|
-
"commit" TEXT,
|
14
|
-
"commit_time" INTEGER
|
15
|
-
);
|
data/spec/my_kit/my_kit.yml
DELETED
@@ -1,17 +0,0 @@
|
|
1
|
-
# Path to this kit's root directory.
|
2
|
-
# Absolute or relative to this config file.
|
3
|
-
# If not specified, defaults to the folder that holds this config file.
|
4
|
-
#
|
5
|
-
:kits_path: "../../../kits/my_kit"
|
6
|
-
#
|
7
|
-
# Database backend to use. Available options:
|
8
|
-
# :sqlite3
|
9
|
-
#
|
10
|
-
:db_backend: :sqlite3
|
11
|
-
#
|
12
|
-
# Path to the files to save each sqlite3 database (since only sqlite3 is supported).
|
13
|
-
# Absolute or relative to this config file.
|
14
|
-
#
|
15
|
-
:db_config:
|
16
|
-
:info: "info.db"
|
17
|
-
:actions: "actions.db"
|
data/spec/my_kit_spec.rb
DELETED
@@ -1,66 +0,0 @@
|
|
1
|
-
require 'kit'
|
2
|
-
|
3
|
-
describe Kit do
|
4
|
-
|
5
|
-
MY_KIT_CONFIG = "spec/my_kit/my_kit.yml"
|
6
|
-
|
7
|
-
before :all do
|
8
|
-
@kit = Kit.new MY_KIT_CONFIG
|
9
|
-
end
|
10
|
-
|
11
|
-
it "adds a new bit to new project" do
|
12
|
-
new_bit = { :name => "live", :project_name => "my_project", :root => "./my_kit_spec/my_project", :git => "git path" }
|
13
|
-
b = @kit.add_bit new_bit
|
14
|
-
|
15
|
-
b.class.should == Bit
|
16
|
-
|
17
|
-
new_bit.each do |key, value|
|
18
|
-
( b.send key ).should == value
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
it "doen not add a existing bit to project" do
|
23
|
-
new_bit = { :name => "live", :project_name => "my_project", :root => "./my_kit_spec/my_project/live" }
|
24
|
-
b = @kit.add_bit new_bit
|
25
|
-
|
26
|
-
b.should == nil
|
27
|
-
|
28
|
-
end
|
29
|
-
|
30
|
-
it "adds a new task of each type" do
|
31
|
-
|
32
|
-
# old_bit = { :name => "live", :project_name => "my_project" }
|
33
|
-
# puts Kit::Bit.lookup_id old_bit
|
34
|
-
|
35
|
-
new_bit_2 = { :name => "beta", :project_name => "my_project", :root => "./my_kit_spec/my_project/beta" }
|
36
|
-
b = @kit.add_bit new_bit_2
|
37
|
-
|
38
|
-
actions = {
|
39
|
-
:clones => { :bit => 1, :src => 2 },
|
40
|
-
:upgrades => { :bit => 1, :component => "my_component", :file => "my_file" },
|
41
|
-
:commits => { :bit => 1, :commit => "3456ABF" }
|
42
|
-
}
|
43
|
-
|
44
|
-
tasks = {}
|
45
|
-
actions.each do |key, value|
|
46
|
-
tasks[key] = @kit.add_task key, value
|
47
|
-
end
|
48
|
-
|
49
|
-
@kit.action_types.each do |t|
|
50
|
-
a = @kit.get_tasks_by_status t, :pending
|
51
|
-
actions[t].merge! ( { :rowid => tasks[t], :action => t, :status => "pending" } )
|
52
|
-
a.first.should == actions[t]
|
53
|
-
end
|
54
|
-
|
55
|
-
end
|
56
|
-
|
57
|
-
it "runs added tasks" do
|
58
|
-
@kit.run_tasks
|
59
|
-
end
|
60
|
-
|
61
|
-
|
62
|
-
after :all do
|
63
|
-
@kit.delete_dbs
|
64
|
-
end
|
65
|
-
|
66
|
-
end
|