boom 0.2.4 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/{CHANGELOG.markdown → CHANGELOG.md} +12 -3
- data/Gemfile.lock +3 -5
- data/{LICENSE.markdown → LICENSE.md} +0 -0
- data/{README.markdown → README.md} +14 -11
- data/Rakefile +3 -5
- data/boom.gemspec +14 -26
- data/lib/boom/command.rb +8 -35
- data/lib/boom/item.rb +2 -4
- data/lib/boom/list.rb +1 -1
- data/lib/boom/storage.rb +114 -12
- data/lib/boom.rb +5 -20
- data/test/cli.sh +13 -0
- data/test/examples/data.json +17 -0
- data/test/item.sh +19 -0
- data/test/list.sh +30 -0
- data/test/roundup +307 -0
- data/test/run +8 -0
- metadata +74 -125
- data/lib/boom/config.rb +0 -89
- data/lib/boom/storage/base.rb +0 -81
- data/lib/boom/storage/gist.rb +0 -114
- data/lib/boom/storage/json.rb +0 -69
- data/lib/boom/storage/keychain.rb +0 -135
- data/lib/boom/storage/mongodb.rb +0 -84
- data/lib/boom/storage/redis.rb +0 -72
- data/test/examples/config_json.json +0 -3
- data/test/examples/test_json.json +0 -3
- data/test/examples/urls.json +0 -1
- data/test/helper.rb +0 -24
- data/test/test_color.rb +0 -30
- data/test/test_command.rb +0 -238
- data/test/test_config.rb +0 -25
- data/test/test_item.rb +0 -54
- data/test/test_list.rb +0 -79
- data/test/test_platform.rb +0 -52
data/lib/boom/storage/base.rb
DELETED
@@ -1,81 +0,0 @@
|
|
1
|
-
# coding: utf-8
|
2
|
-
|
3
|
-
# Storage is the middleman between changes the client makes in-memory and how
|
4
|
-
# it's actually persisted to disk (and vice-versa). There are also a few
|
5
|
-
# convenience methods to run searches and operations on the in-memory hash.
|
6
|
-
#
|
7
|
-
module Boom
|
8
|
-
module Storage
|
9
|
-
class Base
|
10
|
-
|
11
|
-
# Public: initializes a Storage instance by loading in your persisted data from adapter.
|
12
|
-
#
|
13
|
-
# Returns the Storage instance.
|
14
|
-
def initialize
|
15
|
-
@lists = []
|
16
|
-
bootstrap
|
17
|
-
populate
|
18
|
-
end
|
19
|
-
|
20
|
-
# run bootstrap tasks for the storage
|
21
|
-
def bootstrap ; end
|
22
|
-
|
23
|
-
# populate the in-memory store with all the lists and items
|
24
|
-
def populate ; end
|
25
|
-
|
26
|
-
# save the data
|
27
|
-
def save ; end
|
28
|
-
|
29
|
-
# Public: the in-memory collection of all Lists attached to this Storage
|
30
|
-
# instance.
|
31
|
-
#
|
32
|
-
# lists - an Array of individual List items
|
33
|
-
#
|
34
|
-
# Returns nothing.
|
35
|
-
attr_writer :lists
|
36
|
-
|
37
|
-
# Public: the list of Lists in your JSON data, sorted by number of items
|
38
|
-
# descending.
|
39
|
-
#
|
40
|
-
# Returns an Array of List objects.
|
41
|
-
def lists
|
42
|
-
@lists.sort_by { |list| -list.items.size }
|
43
|
-
end
|
44
|
-
|
45
|
-
# Public: tests whether a named List exists.
|
46
|
-
#
|
47
|
-
# name - the String name of a List
|
48
|
-
#
|
49
|
-
# Returns true if found, false if not.
|
50
|
-
def list_exists?(name)
|
51
|
-
@lists.detect { |list| list.name == name }
|
52
|
-
end
|
53
|
-
|
54
|
-
# Public: all Items in storage.
|
55
|
-
#
|
56
|
-
# Returns an Array of all Items.
|
57
|
-
def items
|
58
|
-
@lists.collect(&:items).flatten
|
59
|
-
end
|
60
|
-
|
61
|
-
# Public: tests whether a named Item exists.
|
62
|
-
#
|
63
|
-
# name - the String name of an Item
|
64
|
-
#
|
65
|
-
# Returns true if found, false if not.
|
66
|
-
def item_exists?(name)
|
67
|
-
items.detect { |item| item.name == name }
|
68
|
-
end
|
69
|
-
|
70
|
-
# Public: creates a Hash of the representation of the in-memory data
|
71
|
-
# structure. This percolates down to Items by calling to_hash on the List,
|
72
|
-
# which in tern calls to_hash on individual Items.
|
73
|
-
#
|
74
|
-
# Returns a Hash of the entire data set.
|
75
|
-
def to_hash
|
76
|
-
{ :lists => lists.collect(&:to_hash) }
|
77
|
-
end
|
78
|
-
|
79
|
-
end
|
80
|
-
end
|
81
|
-
end
|
data/lib/boom/storage/gist.rb
DELETED
@@ -1,114 +0,0 @@
|
|
1
|
-
# coding: utf-8
|
2
|
-
#
|
3
|
-
# Gist backend for Boom.
|
4
|
-
#
|
5
|
-
# Your .boom.conf file should look like this:
|
6
|
-
#
|
7
|
-
# {
|
8
|
-
# "backend": "gist",
|
9
|
-
# "gist": {
|
10
|
-
# "username": "your_github_username",
|
11
|
-
# "password": "your_github_password"
|
12
|
-
# }
|
13
|
-
# }
|
14
|
-
#
|
15
|
-
# There are two optional keys which can be under "gist":
|
16
|
-
#
|
17
|
-
# gist_id - The ID of an existing Gist to use. If not
|
18
|
-
# present, a Gist will be created the first time
|
19
|
-
# Boom is run and will be persisted to the config.
|
20
|
-
# public - Makes the Gist public. An absent value or
|
21
|
-
# any value other than boolean true will make
|
22
|
-
# the Gist private.
|
23
|
-
#
|
24
|
-
|
25
|
-
module Boom
|
26
|
-
module Storage
|
27
|
-
class Gist < Base
|
28
|
-
|
29
|
-
def bootstrap
|
30
|
-
begin
|
31
|
-
require "httparty"
|
32
|
-
|
33
|
-
self.class.send(:include, HTTParty)
|
34
|
-
self.class.base_uri "https://api.github.com"
|
35
|
-
rescue LoadError
|
36
|
-
puts "The Gist backend requires HTTParty: gem install httparty"
|
37
|
-
exit
|
38
|
-
end
|
39
|
-
|
40
|
-
unless Boom.config.attributes["gist"]
|
41
|
-
puts 'A "gist" data structure must be defined in ~/.boom.conf'
|
42
|
-
exit
|
43
|
-
end
|
44
|
-
|
45
|
-
set_up_auth
|
46
|
-
find_or_create_gist
|
47
|
-
end
|
48
|
-
|
49
|
-
def populate
|
50
|
-
@storage['lists'].each do |lists|
|
51
|
-
lists.each do |list_name, items|
|
52
|
-
@lists << list = List.new(list_name)
|
53
|
-
|
54
|
-
items.each do |item|
|
55
|
-
item.each do |name,value|
|
56
|
-
list.add_item(Item.new(name,value))
|
57
|
-
end
|
58
|
-
end
|
59
|
-
end
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
def save
|
64
|
-
self.class.post("/gists/#{@gist_id}", request_params)
|
65
|
-
end
|
66
|
-
|
67
|
-
private
|
68
|
-
|
69
|
-
def set_up_auth
|
70
|
-
username, password = Boom.config.attributes["gist"]["username"], Boom.config.attributes["gist"]["password"]
|
71
|
-
|
72
|
-
if username and password
|
73
|
-
self.class.basic_auth(username, password)
|
74
|
-
else
|
75
|
-
puts "GitHub username and password must be defined in ~/.boom.conf"
|
76
|
-
exit
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
def find_or_create_gist
|
81
|
-
@gist_id = Boom.config.attributes["gist"]["gist_id"]
|
82
|
-
@public = Boom.config.attributes["gist"]["public"] == true
|
83
|
-
|
84
|
-
if @gist_id.nil? or @gist_id.empty?
|
85
|
-
response = self.class.post("/gists", request_params)
|
86
|
-
else
|
87
|
-
response = self.class.get("/gists/#{@gist_id}", request_params)
|
88
|
-
end
|
89
|
-
|
90
|
-
@storage = MultiJson.decode(response["files"]["boom.json"]["content"]) if response["files"] and response["files"]["boom.json"]
|
91
|
-
|
92
|
-
unless @storage
|
93
|
-
puts "Boom data could not be obtained"
|
94
|
-
exit
|
95
|
-
end
|
96
|
-
|
97
|
-
unless @gist_id
|
98
|
-
Boom.config.attributes["gist"]["gist_id"] = @gist_id = response["id"]
|
99
|
-
Boom.config.save
|
100
|
-
end
|
101
|
-
end
|
102
|
-
|
103
|
-
def request_params
|
104
|
-
{
|
105
|
-
:body => MultiJson.encode({
|
106
|
-
:description => "boom!",
|
107
|
-
:public => @public,
|
108
|
-
:files => { "boom.json" => { :content => MultiJson.encode(to_hash) } }
|
109
|
-
})
|
110
|
-
}
|
111
|
-
end
|
112
|
-
end
|
113
|
-
end
|
114
|
-
end
|
data/lib/boom/storage/json.rb
DELETED
@@ -1,69 +0,0 @@
|
|
1
|
-
# coding: utf-8
|
2
|
-
#
|
3
|
-
# Json is the default storage option for boom. It writes a Json file to
|
4
|
-
# ~/.boom. Pretty neat, huh?
|
5
|
-
#
|
6
|
-
module Boom
|
7
|
-
module Storage
|
8
|
-
class Json < Base
|
9
|
-
|
10
|
-
JSON_FILE = "#{ENV['HOME']}/.boom"
|
11
|
-
|
12
|
-
# Public: the path to the Json file used by boom.
|
13
|
-
#
|
14
|
-
# Returns the String path of boom's Json representation.
|
15
|
-
def json_file
|
16
|
-
JSON_FILE
|
17
|
-
end
|
18
|
-
|
19
|
-
# Takes care of bootstrapping the Json file, both in terms of creating the
|
20
|
-
# file and in terms of creating a skeleton Json schema.
|
21
|
-
#
|
22
|
-
# Return true if successfully saved.
|
23
|
-
def bootstrap
|
24
|
-
return if File.exist?(json_file)
|
25
|
-
FileUtils.touch json_file
|
26
|
-
File.open(json_file, 'w') {|f| f.write(to_json) }
|
27
|
-
save
|
28
|
-
end
|
29
|
-
|
30
|
-
# Take a Json representation of data and explode it out into the consituent
|
31
|
-
# Lists and Items for the given Storage instance.
|
32
|
-
#
|
33
|
-
# Returns nothing.
|
34
|
-
def populate
|
35
|
-
storage = MultiJson.decode(File.new(json_file, 'r').read)
|
36
|
-
|
37
|
-
storage['lists'].each do |lists|
|
38
|
-
lists.each do |list_name, items|
|
39
|
-
@lists << list = List.new(list_name)
|
40
|
-
|
41
|
-
items.each do |item|
|
42
|
-
item.each do |name,value|
|
43
|
-
list.add_item(Item.new(name,value))
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
# Public: persists your in-memory objects to disk in Json format.
|
51
|
-
#
|
52
|
-
# lists_Json - list in Json format
|
53
|
-
#
|
54
|
-
# Returns true if successful, false if unsuccessful.
|
55
|
-
def save
|
56
|
-
File.open(json_file, 'w') {|f| f.write(to_json) }
|
57
|
-
end
|
58
|
-
|
59
|
-
# Public: the Json representation of the current List and Item assortment
|
60
|
-
# attached to the Storage instance.
|
61
|
-
#
|
62
|
-
# Returns a String Json representation of its Lists and their Items.
|
63
|
-
def to_json
|
64
|
-
MultiJson.encode(to_hash)
|
65
|
-
end
|
66
|
-
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
@@ -1,135 +0,0 @@
|
|
1
|
-
# coding: utf-8
|
2
|
-
|
3
|
-
# Keychain provides methods for using Mac OS X's Keychain as a storage option.
|
4
|
-
# It saves lists as Keychain files in ~/Library/Keychains with the filename
|
5
|
-
# format being: "Boom.list.mylist.keychain"
|
6
|
-
#
|
7
|
-
module Boom
|
8
|
-
module Storage
|
9
|
-
class Keychain < Base
|
10
|
-
|
11
|
-
KEYCHAIN_FORMAT = %r{Boom\.list\.(.+)\.keychain}
|
12
|
-
|
13
|
-
# Opens Keychain app when json_file is called during `boom edit`
|
14
|
-
#
|
15
|
-
# Returns nothing
|
16
|
-
def open_keychain_app
|
17
|
-
`open /Applications/Utilities/'Keychain Access.app' &`
|
18
|
-
end
|
19
|
-
|
20
|
-
alias_method :json_file, :open_keychain_app
|
21
|
-
|
22
|
-
# Boostraps Keychain by checking if you're using a Mac which is a prereq
|
23
|
-
#
|
24
|
-
# Returns
|
25
|
-
def bootstrap
|
26
|
-
raise RuntimeError unless is_mac?
|
27
|
-
rescue
|
28
|
-
puts('No Keychain utility to access, maybe try another storage option?')
|
29
|
-
exit
|
30
|
-
end
|
31
|
-
|
32
|
-
# Asks if you're using Mac OS X
|
33
|
-
#
|
34
|
-
# Returns true on a Mac
|
35
|
-
def is_mac?
|
36
|
-
return Boom::Platform.darwin?
|
37
|
-
end
|
38
|
-
|
39
|
-
# Populate the in-memory store with all the lists and items from Keychain
|
40
|
-
#
|
41
|
-
# Returns Array of keychain names, i.e. ["Boom.list.mylist.keychain"]
|
42
|
-
def populate
|
43
|
-
stored_keychain_lists.each do |keychain|
|
44
|
-
@lists << list = List.new(keychain.scan(KEYCHAIN_FORMAT).flatten.first)
|
45
|
-
extract_keychain_items(keychain).each do |name|
|
46
|
-
list.add_item(Item.new(name, extract_keychain_value(name, keychain)))
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
# Saves the data from memory to the correct Keychain
|
52
|
-
#
|
53
|
-
# Returns nothing
|
54
|
-
def save
|
55
|
-
@lists.each do |list|
|
56
|
-
keychain_name = list_to_filename(list.name)
|
57
|
-
create_keychain_list(keychain_name) unless stored_keychain_lists.include?(keychain_name)
|
58
|
-
unless list.items.empty?
|
59
|
-
list.items.each do |item|
|
60
|
-
store_item(item, keychain_name)
|
61
|
-
end
|
62
|
-
end
|
63
|
-
delete_unwanted_items(list)
|
64
|
-
end
|
65
|
-
delete_unwanted_lists
|
66
|
-
rescue RuntimeError
|
67
|
-
puts(e "Couldn't save to your keychain, check Console.app or above for relevant messages")
|
68
|
-
end
|
69
|
-
|
70
|
-
|
71
|
-
private
|
72
|
-
|
73
|
-
# Returns an Array of keychains stored in ~/Library/Keychains:
|
74
|
-
# => ["Boom.list.mylist.keychain"]
|
75
|
-
def stored_keychain_lists
|
76
|
-
@stored_keychain_lists ||= `security -q list-keychains |grep Boom.list` \
|
77
|
-
.split(/[\/\n\"]/).select {|kc| kc =~ KEYCHAIN_FORMAT}
|
78
|
-
end
|
79
|
-
|
80
|
-
# Create the keychain list "Boom.list.mylist.keychain" in ~/Library/Keychains
|
81
|
-
def create_keychain_list(keychain_name)
|
82
|
-
`security -q create-keychain #{keychain_name}`
|
83
|
-
end
|
84
|
-
|
85
|
-
# Saves the individual item's value to the right list/keychain
|
86
|
-
def store_item(item, keychain_name)
|
87
|
-
`security 2>/dev/null -q add-generic-password -a '#{item.name}' -s '#{item.name}' -w '#{item.value}' #{keychain_name}`
|
88
|
-
end
|
89
|
-
|
90
|
-
# Retrieves the value of a particular item in a list
|
91
|
-
def extract_keychain_value(item_name, keychain)
|
92
|
-
`security 2>&1 >/dev/null find-generic-password -ga '#{item_name}' #{keychain}`.chomp.split('"').last
|
93
|
-
end
|
94
|
-
|
95
|
-
# Gets all items in a particular list
|
96
|
-
def extract_keychain_items(keychain_name)
|
97
|
-
@stored_items ||= {}
|
98
|
-
@stored_items[keychain_name] ||= `security dump-keychain -a #{keychain_name} |grep acct` \
|
99
|
-
.split(/\s|\\n|\\"|acct|<blob>=|\"/).reject {|f| f.empty?}
|
100
|
-
end
|
101
|
-
|
102
|
-
# Converts list name to the corresponding keychain filename format based
|
103
|
-
# on the KEYCHAIN_FORMAT
|
104
|
-
def list_to_filename(list_name)
|
105
|
-
KEYCHAIN_FORMAT.source.gsub(/\(\.\+\)/, list_name).gsub('\\','')
|
106
|
-
end
|
107
|
-
|
108
|
-
# Delete's a keychain file
|
109
|
-
def delete_list(keychain_filename)
|
110
|
-
`security delete-keychain #{keychain_filename}`
|
111
|
-
end
|
112
|
-
|
113
|
-
# Delete's all keychain files you don't want anymore
|
114
|
-
def delete_unwanted_lists
|
115
|
-
(stored_keychain_lists - @lists.map {|list| list_to_filename(list.name)}).each do |filename|
|
116
|
-
delete_list(filename)
|
117
|
-
end
|
118
|
-
end
|
119
|
-
|
120
|
-
# Removes unwanted items in a list
|
121
|
-
# security util doesn't have a delete password option so we'll have to
|
122
|
-
# drop it and recreate it with what is in memory
|
123
|
-
def delete_unwanted_items(list)
|
124
|
-
filename = list_to_filename(list.name)
|
125
|
-
if (list.items.size < extract_keychain_items(filename).size)
|
126
|
-
delete_list(filename)
|
127
|
-
create_keychain_list(filename)
|
128
|
-
list.items.each do |item|
|
129
|
-
store_item(item, filename)
|
130
|
-
end unless list.items.empty?
|
131
|
-
end
|
132
|
-
end
|
133
|
-
end
|
134
|
-
end
|
135
|
-
end
|
data/lib/boom/storage/mongodb.rb
DELETED
@@ -1,84 +0,0 @@
|
|
1
|
-
# coding: utf-8
|
2
|
-
|
3
|
-
# Storage adapter that saves data from boom to MongoDB instead of JSON file.
|
4
|
-
begin
|
5
|
-
require 'mongo'
|
6
|
-
rescue LoadError
|
7
|
-
end
|
8
|
-
|
9
|
-
module Boom
|
10
|
-
module Storage
|
11
|
-
class Mongodb < Base
|
12
|
-
|
13
|
-
# Public: Initialize MongoDB connection and check dep.
|
14
|
-
#
|
15
|
-
# Returns Mongo connection
|
16
|
-
def mongo
|
17
|
-
@mongo ||= ::Mongo::Connection.new(
|
18
|
-
Boom.config.attributes["mongodb"]["host"],
|
19
|
-
Boom.config.attributes["mongodb"]["port"]
|
20
|
-
).db(Boom.config.attributes["mongodb"]["database"])
|
21
|
-
|
22
|
-
@mongo.authenticate(
|
23
|
-
Boom.config.attributes['mongodb']['username'],
|
24
|
-
Boom.config.attributes['mongodb']['password']
|
25
|
-
)
|
26
|
-
|
27
|
-
# Return connection
|
28
|
-
@mongo
|
29
|
-
rescue NameError => e
|
30
|
-
puts "You don't have the Mongo gem installed yet:\n gem install mongo"
|
31
|
-
exit
|
32
|
-
end
|
33
|
-
|
34
|
-
# Public: The MongoDB collection
|
35
|
-
#
|
36
|
-
# Returns the MongoDB collection
|
37
|
-
def collection
|
38
|
-
@collection ||= mongo.collection(Boom.config.attributes["mongodb"]["collection"])
|
39
|
-
end
|
40
|
-
|
41
|
-
# Public: Bootstrap
|
42
|
-
#
|
43
|
-
# Returns
|
44
|
-
def bootstrap
|
45
|
-
collection.insert("boom" => '{"lists": [{}]}') if collection.find_one.nil?
|
46
|
-
end
|
47
|
-
|
48
|
-
# Public: Populates the memory list from MongoDB
|
49
|
-
#
|
50
|
-
# Returns nothing
|
51
|
-
def populate
|
52
|
-
storage = MultiJson.decode(collection.find_one['boom']) || []
|
53
|
-
|
54
|
-
storage['lists'].each do |lists|
|
55
|
-
lists.each do |list_name, items|
|
56
|
-
@lists << list = List.new(list_name)
|
57
|
-
|
58
|
-
items.each do |item|
|
59
|
-
item.each do |name,value|
|
60
|
-
list.add_item(Item.new(name,value))
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
# Public: Save to MongoDB
|
68
|
-
#
|
69
|
-
# Returns Mongo ID
|
70
|
-
def save
|
71
|
-
doc = collection.find_one()
|
72
|
-
collection.update({"_id" => doc["_id"]}, {'boom' => to_json})
|
73
|
-
end
|
74
|
-
|
75
|
-
# Public: Convert to JSON
|
76
|
-
#
|
77
|
-
# Returns
|
78
|
-
def to_json
|
79
|
-
MultiJson.encode(to_hash)
|
80
|
-
end
|
81
|
-
|
82
|
-
end
|
83
|
-
end
|
84
|
-
end
|
data/lib/boom/storage/redis.rb
DELETED
@@ -1,72 +0,0 @@
|
|
1
|
-
# coding: utf-8
|
2
|
-
#
|
3
|
-
# Sup, Redis.
|
4
|
-
#
|
5
|
-
begin
|
6
|
-
require 'digest'
|
7
|
-
require 'redis'
|
8
|
-
require 'uri'
|
9
|
-
rescue LoadError
|
10
|
-
end
|
11
|
-
|
12
|
-
module Boom
|
13
|
-
module Storage
|
14
|
-
class Redis < Base
|
15
|
-
|
16
|
-
def redis
|
17
|
-
uri = URI.parse(Boom.config.attributes['uri'] || '')
|
18
|
-
|
19
|
-
@redis ||= ::Redis.new :host => (uri.host || Boom.config.attributes["redis"]["host"]),
|
20
|
-
:port => (uri.port || Boom.config.attributes["redis"]["port"]),
|
21
|
-
:user => (uri.user || Boom.config.attributes["redis"]["user"]),
|
22
|
-
:password => (uri.password || Boom.config.attributes["redis"]["password"])
|
23
|
-
rescue NameError => e
|
24
|
-
puts "You don't have Redis installed yet:\n gem install redis"
|
25
|
-
exit
|
26
|
-
end
|
27
|
-
|
28
|
-
def bootstrap
|
29
|
-
end
|
30
|
-
|
31
|
-
def populate
|
32
|
-
lists = redis.smembers("boom:lists") || []
|
33
|
-
|
34
|
-
lists.each do |sha|
|
35
|
-
list_name = redis.get("boom:lists:#{sha}:name")
|
36
|
-
@lists << list = List.new(list_name)
|
37
|
-
|
38
|
-
shas = redis.lrange("boom:lists:#{sha}:items",0,-1) || []
|
39
|
-
|
40
|
-
shas.each do |item_sha|
|
41
|
-
name = redis.get "boom:items:#{item_sha}:name"
|
42
|
-
value = redis.get "boom:items:#{item_sha}:value"
|
43
|
-
list.add_item(Item.new(name, value))
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
def clear
|
49
|
-
redis.del "boom:lists"
|
50
|
-
redis.del "boom:items"
|
51
|
-
end
|
52
|
-
|
53
|
-
def save
|
54
|
-
clear
|
55
|
-
|
56
|
-
lists.each do |list|
|
57
|
-
list_sha = Digest::SHA1.hexdigest(list.name)
|
58
|
-
redis.set "boom:lists:#{list_sha}:name", list.name
|
59
|
-
redis.sadd "boom:lists", list_sha
|
60
|
-
|
61
|
-
list.items.each do |item|
|
62
|
-
item_sha = Digest::SHA1.hexdigest(item.name)
|
63
|
-
redis.rpush "boom:lists:#{list_sha}:items", item_sha
|
64
|
-
redis.set "boom:items:#{item_sha}:name", item.name
|
65
|
-
redis.set "boom:items:#{item_sha}:value", item.value
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
end
|
71
|
-
end
|
72
|
-
end
|
data/test/examples/urls.json
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
{"lists":[{"urls":[{"github":"https://github.com"},{"blog":"http://zachholman.com"}]}]}
|
data/test/helper.rb
DELETED
@@ -1,24 +0,0 @@
|
|
1
|
-
# coding: utf-8
|
2
|
-
|
3
|
-
require 'test/unit'
|
4
|
-
|
5
|
-
begin
|
6
|
-
require 'rubygems'
|
7
|
-
require 'redgreen'
|
8
|
-
rescue LoadError
|
9
|
-
end
|
10
|
-
|
11
|
-
require 'mocha'
|
12
|
-
|
13
|
-
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
14
|
-
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
15
|
-
|
16
|
-
require 'boom'
|
17
|
-
|
18
|
-
def boom_json(name)
|
19
|
-
root = File.expand_path(File.dirname(__FILE__))
|
20
|
-
Boom::Storage::Json.any_instance.stubs(:save).returns(true)
|
21
|
-
Boom::Storage::Json.any_instance.stubs(:json_file).
|
22
|
-
returns("#{root}/examples/#{name}.json")
|
23
|
-
Boom.stubs(:storage).returns(Boom::Storage::Json.new)
|
24
|
-
end
|
data/test/test_color.rb
DELETED
@@ -1,30 +0,0 @@
|
|
1
|
-
require 'helper'
|
2
|
-
|
3
|
-
class TestColor < Test::Unit::TestCase
|
4
|
-
|
5
|
-
def test_colorize
|
6
|
-
assert_equal "\e[35mBoom!\e[0m",
|
7
|
-
Boom::Color.colorize("Boom!", :magenta)
|
8
|
-
end
|
9
|
-
|
10
|
-
def test_magenta
|
11
|
-
assert_equal "\e[35mMagenta!\e[0m",
|
12
|
-
Boom::Color.magenta("Magenta!")
|
13
|
-
end
|
14
|
-
|
15
|
-
def test_red
|
16
|
-
assert_equal "\e[31mRed!\e[0m",
|
17
|
-
Boom::Color.red("Red!")
|
18
|
-
end
|
19
|
-
|
20
|
-
def test_yellow
|
21
|
-
assert_equal "\e[33mYellow!\e[0m",
|
22
|
-
Boom::Color.yellow("Yellow!")
|
23
|
-
end
|
24
|
-
|
25
|
-
def test_cyan
|
26
|
-
assert_equal "\e[36mCyan!\e[0m",
|
27
|
-
Boom::Color.cyan("Cyan!")
|
28
|
-
end
|
29
|
-
|
30
|
-
end
|