boom 0.1.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.markdown CHANGED
@@ -2,6 +2,16 @@
2
2
 
3
3
  ## head
4
4
 
5
+ ## 0.2.0
6
+ - Add Keychain storage to store Boom data securely in OS X's Keychain.app.
7
+ Thanks, [@davidtrogers](https://github.com/davidtrogers)!
8
+ - Switch from yajl-ruby because [OS X isn't for
9
+ developers](http://zachholman.com/2011/03/osx-isnt-for-developers/). Thanks
10
+ for finishing it up, [@antonlindstrom](https://github.com/antonlindstrom).
11
+ - Move dependencies to Bundler, because it's the One True Way™ at this point.
12
+ - Some README updates.
13
+ - `boom -v`.
14
+
5
15
  ## 0.1.2
6
16
  - Copy to clipboard doesn't hang anymore. Sweet. Thanks,
7
17
  [mcollina](https://github.com/mcollina).
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source "http://rubygems.org"
2
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,18 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ boom (0.1.2)
5
+ json_pure (~> 1.5.1)
6
+
7
+ GEM
8
+ remote: http://rubygems.org/
9
+ specs:
10
+ json_pure (1.5.1)
11
+ mocha (0.9.12)
12
+
13
+ PLATFORMS
14
+ ruby
15
+
16
+ DEPENDENCIES
17
+ boom!
18
+ mocha (~> 0.9.9)
data/README.markdown CHANGED
@@ -13,12 +13,30 @@ For more details about what boom is and how it works, check out
13
13
 
14
14
  gem install boom
15
15
 
16
+ ## Quick and Dirty
17
+
18
+ $ boom gifs
19
+ Boom! Created a new list called "gifs".
20
+
21
+ $ boom gifs melissa http://cl.ly/3pAn/animated.gif
22
+ Boom! "melissa" in "gifs" is "http://cl.ly/3pAn/animated.gif". Got it.
23
+
24
+ $ boom melissa
25
+ Boom! Just copied http://cl.ly/3pAn/animated.gif to your clipboard.
26
+
27
+ And that's just a taste! I know, you're salivating, I can hear you from here.
28
+ (Why your saliva is noisy is beyond me.) Check out the [full list of
29
+ commands](https://github.com/holman/boom/wiki/Commands).
30
+
16
31
  ## Contribute
17
32
 
18
- I'd love to include your contributions, friend. Make sure your methods are
19
- [TomDoc](http://tomdoc.org)'d properly, that existing tests pass (`rake`), and
20
- that any new functionality includes appropriate tests. Bonus points if you're
21
- not updating the gemspec or bumping boom's version.
33
+ I'd love to include your contributions, friend.
34
+
35
+ Clone this repository, then run `bundle install`. That'll install all the gem
36
+ dependencies. Make sure your methods are [TomDoc](http://tomdoc.org)'d
37
+ properly, that existing tests pass (`rake`), and that any new functionality
38
+ includes appropriate tests. Bonus points if you're not updating the gemspec or
39
+ bumping boom's version.
22
40
 
23
41
  All good? Cool! Then [send me a pull request](https://github.com/holman/boom/pull/new/master)!
24
42
 
data/boom.gemspec CHANGED
@@ -13,8 +13,8 @@ Gem::Specification.new do |s|
13
13
  ## If your rubyforge_project name is different, then edit it and comment out
14
14
  ## the sub! line in the Rakefile
15
15
  s.name = 'boom'
16
- s.version = '0.1.2'
17
- s.date = '2011-03-11'
16
+ s.version = '0.2.0'
17
+ s.date = '2011-04-11'
18
18
  s.rubyforge_project = 'boom'
19
19
 
20
20
  ## Make sure your summary is short. The description may be as long
@@ -54,7 +54,7 @@ Gem::Specification.new do |s|
54
54
 
55
55
  ## List your runtime dependencies here. Runtime dependencies are those
56
56
  ## that are needed for an end user to actually USE your code.
57
- s.add_dependency('yajl-ruby', "~> 0.7.8")
57
+ s.add_dependency('json_pure', "~> 1.5.1")
58
58
 
59
59
  ## List your development dependencies here. Development dependencies are
60
60
  ## those that are only needed during development
@@ -66,6 +66,8 @@ Gem::Specification.new do |s|
66
66
  # = MANIFEST =
67
67
  s.files = %w[
68
68
  CHANGELOG.markdown
69
+ Gemfile
70
+ Gemfile.lock
69
71
  LICENSE.markdown
70
72
  README.markdown
71
73
  Rakefile
@@ -84,6 +86,7 @@ Gem::Specification.new do |s|
84
86
  lib/boom/storage.rb
85
87
  lib/boom/storage/base.rb
86
88
  lib/boom/storage/json.rb
89
+ lib/boom/storage/keychain.rb
87
90
  lib/boom/storage/mongodb.rb
88
91
  lib/boom/storage/redis.rb
89
92
  test/examples/config_json.json
data/lib/boom.rb CHANGED
@@ -6,7 +6,7 @@ rescue LoadError
6
6
  end
7
7
 
8
8
  require 'fileutils'
9
- require 'yajl'
9
+ require 'json/pure'
10
10
 
11
11
  $:.unshift File.join(File.dirname(__FILE__), *%w[.. lib])
12
12
 
@@ -21,11 +21,12 @@ require 'boom/storage/base'
21
21
  require 'boom/storage/json'
22
22
  require 'boom/storage/redis'
23
23
  require 'boom/storage/mongodb'
24
+ require 'boom/storage/keychain'
24
25
 
25
26
  require 'boom/core_ext/symbol'
26
27
 
27
28
  module Boom
28
- VERSION = '0.1.2'
29
+ VERSION = '0.2.0'
29
30
 
30
31
  extend self
31
32
 
data/lib/boom/command.rb CHANGED
@@ -76,12 +76,14 @@ module Boom
76
76
  #
77
77
  # Returns output based on method calls.
78
78
  def delegate(command, major, minor)
79
- return all if command == 'all'
80
- return edit if command == 'edit'
81
- return switch(major) if command == 'switch'
82
- return show_storage if command == 'storage'
83
- return help if command == 'help'
84
- return help if command[0] == 45 || command[0] == '-' # any - dash options are pleas for help
79
+ return all if command == 'all'
80
+ return edit if command == 'edit'
81
+ return switch(major) if command == 'switch'
82
+ return show_storage if command == 'storage'
83
+ return version if command == "-v"
84
+ return version if command == "--version"
85
+ return help if command == 'help'
86
+ return help if command[0] == 45 || command[0] == '-' # any - dash options are pleas for help
85
87
  return echo(major,minor) if command == 'echo' || command == 'e'
86
88
  return open(major,minor) if command == 'open' || command == 'o'
87
89
 
@@ -278,6 +280,13 @@ module Boom
278
280
  storage.save
279
281
  end
280
282
 
283
+ # Public: the version of boom that you're currently running.
284
+ #
285
+ # Returns a String identifying the version number.
286
+ def version
287
+ output "You're running boom #{Boom::VERSION}. Congratulations!"
288
+ end
289
+
281
290
  # Public: launches JSON file in an editor for you to edit manually. Uses
282
291
  # the $EDITOR environment variable for editing.
283
292
  #
data/lib/boom/config.rb CHANGED
@@ -74,14 +74,14 @@ module Boom
74
74
  #
75
75
  # Returns nothing.
76
76
  def load_attributes
77
- @attributes = Yajl::Parser.new.parse(File.new(file, 'r'))
77
+ @attributes = JSON.parse(File.new(file, 'r').read)
78
78
  end
79
79
 
80
80
  # Public: writes the in-memory JSON Hash to disk.
81
81
  #
82
82
  # Returns nothing.
83
83
  def save
84
- json = Yajl::Encoder.encode(attributes, :pretty => true)
84
+ json = JSON.generate(attributes)
85
85
  File.open(file, 'w') {|f| f.write(json) }
86
86
  end
87
87
 
@@ -32,7 +32,7 @@ module Boom
32
32
  #
33
33
  # Returns nothing.
34
34
  def populate
35
- storage = Yajl::Parser.new.parse(File.new(json_file, 'r'))
35
+ storage = JSON.parse(File.new(json_file, 'r').read)
36
36
 
37
37
  storage['lists'].each do |lists|
38
38
  lists.each do |list_name, items|
@@ -61,7 +61,7 @@ module Boom
61
61
  #
62
62
  # Returns a String Json representation of its Lists and their Items.
63
63
  def to_json
64
- Yajl::Encoder.encode(to_hash, :pretty => true)
64
+ JSON.generate(to_hash)
65
65
  end
66
66
 
67
67
  end
@@ -0,0 +1,129 @@
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 asking if you're using Mac OS X which is a prereq
23
+ #
24
+ # Returns true on a Mac
25
+ def bootstrap
26
+ raise RuntimeError unless Boom::Platform.darwin?
27
+ true
28
+ rescue
29
+ puts(e 'No Keychain utility to access, maybe try another storage option?')
30
+ false
31
+ end
32
+
33
+ # Populate the in-memory store with all the lists and items from Keychain
34
+ #
35
+ # Returns Array of keychain names, i.e. ["Boom.list.mylist.keychain"]
36
+ def populate
37
+ stored_keychain_lists.each do |keychain|
38
+ @lists << list = List.new(keychain.scan(KEYCHAIN_FORMAT).flatten.first)
39
+ extract_keychain_items(keychain).each do |name|
40
+ list.add_item(Item.new(name, extract_keychain_value(name, keychain)))
41
+ end
42
+ end
43
+ end
44
+
45
+ # Saves the data from memory to the correct Keychain
46
+ #
47
+ # Returns nothing
48
+ def save
49
+ @lists.each do |list|
50
+ keychain_name = list_to_filename(list.name)
51
+ create_keychain_list(keychain_name) unless stored_keychain_lists.include?(keychain_name)
52
+ unless list.items.empty?
53
+ list.items.each do |item|
54
+ store_item(item, keychain_name)
55
+ end
56
+ end
57
+ delete_unwanted_items(list)
58
+ end
59
+ delete_unwanted_lists
60
+ rescue RuntimeError
61
+ puts(e "Couldn't save to your keychain, check Console.app or above for relevant messages")
62
+ end
63
+
64
+
65
+ private
66
+
67
+ # Returns an Array of keychains stored in ~/Library/Keychains:
68
+ # => ["Boom.list.mylist.keychain"]
69
+ def stored_keychain_lists
70
+ @stored_keychain_lists ||= `security -q list-keychains |grep Boom.list` \
71
+ .split(/[\/\n\"]/).select {|kc| kc =~ KEYCHAIN_FORMAT}
72
+ end
73
+
74
+ # Create the keychain list "Boom.list.mylist.keychain" in ~/Library/Keychains
75
+ def create_keychain_list(keychain_name)
76
+ `security -q create-keychain #{keychain_name}`
77
+ end
78
+
79
+ # Saves the individual item's value to the right list/keychain
80
+ def store_item(item, keychain_name)
81
+ `security 2>/dev/null -q add-generic-password -a '#{item.name}' -s '#{item.name}' -w '#{item.value}' #{keychain_name}`
82
+ end
83
+
84
+ # Retrieves the value of a particular item in a list
85
+ def extract_keychain_value(item_name, keychain)
86
+ `security 2>&1 >/dev/null find-generic-password -ga '#{item_name}' #{keychain}`.chomp.split('"').last
87
+ end
88
+
89
+ # Gets all items in a particular list
90
+ def extract_keychain_items(keychain_name)
91
+ @stored_items ||= {}
92
+ @stored_items[keychain_name] ||= `security dump-keychain -a #{keychain_name} |grep acct` \
93
+ .split(/\s|\\n|\\"|acct|<blob>=|\"/).reject {|f| f.empty?}
94
+ end
95
+
96
+ # Converts list name to the corresponding keychain filename format based
97
+ # on the KEYCHAIN_FORMAT
98
+ def list_to_filename(list_name)
99
+ KEYCHAIN_FORMAT.source.gsub(/\(\.\+\)/, list_name).gsub('\\','')
100
+ end
101
+
102
+ # Delete's a keychain file
103
+ def delete_list(keychain_filename)
104
+ `security delete-keychain #{keychain_filename}`
105
+ end
106
+
107
+ # Delete's all keychain files you don't want anymore
108
+ def delete_unwanted_lists
109
+ (stored_keychain_lists - @lists.map {|list| list_to_filename(list.name)}).each do |filename|
110
+ delete_list(filename)
111
+ end
112
+ end
113
+
114
+ # Removes unwanted items in a list
115
+ # security util doesn't have a delete password option so we'll have to
116
+ # drop it and recreate it with what is in memory
117
+ def delete_unwanted_items(list)
118
+ filename = list_to_filename(list.name)
119
+ if (list.items.size < extract_keychain_items(filename).size)
120
+ delete_list(filename)
121
+ create_keychain_list(filename)
122
+ list.items.each do |item|
123
+ store_item(item, filename)
124
+ end unless list.items.empty?
125
+ end
126
+ end
127
+ end
128
+ end
129
+ end
@@ -3,7 +3,6 @@
3
3
  # Storage adapter that saves data from boom to MongoDB instead of JSON file.
4
4
  begin
5
5
  require 'mongo'
6
- require 'json/pure' # Will be here for now See Issue#21
7
6
  rescue LoadError
8
7
  end
9
8
 
data/test/test_command.rb CHANGED
@@ -161,4 +161,11 @@ class TestCommand < Test::Unit::TestCase
161
161
  assert_match /We've switched you over to redis/, command('switch redis')
162
162
  end
163
163
 
164
+ def test_version_switch
165
+ assert_match /#{Boom::VERSION}/, command('-v')
166
+ end
167
+
168
+ def test_version_long
169
+ assert_match /#{Boom::VERSION}/, command('--version')
170
+ end
164
171
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: boom
3
3
  version: !ruby/object:Gem::Version
4
- hash: 31
5
- prerelease: false
4
+ hash: 23
5
+ prerelease:
6
6
  segments:
7
7
  - 0
8
- - 1
9
8
  - 2
10
- version: 0.1.2
9
+ - 0
10
+ version: 0.2.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Zach Holman
@@ -15,23 +15,23 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-03-11 00:00:00 -08:00
18
+ date: 2011-04-11 00:00:00 -07:00
19
19
  default_executable: boom
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
22
- name: yajl-ruby
22
+ name: json_pure
23
23
  prerelease: false
24
24
  requirement: &id001 !ruby/object:Gem::Requirement
25
25
  none: false
26
26
  requirements:
27
27
  - - ~>
28
28
  - !ruby/object:Gem::Version
29
- hash: 19
29
+ hash: 1
30
30
  segments:
31
- - 0
32
- - 7
33
- - 8
34
- version: 0.7.8
31
+ - 1
32
+ - 5
33
+ - 1
34
+ version: 1.5.1
35
35
  type: :runtime
36
36
  version_requirements: *id001
37
37
  - !ruby/object:Gem::Dependency
@@ -68,6 +68,8 @@ extra_rdoc_files:
68
68
  - LICENSE.markdown
69
69
  files:
70
70
  - CHANGELOG.markdown
71
+ - Gemfile
72
+ - Gemfile.lock
71
73
  - LICENSE.markdown
72
74
  - README.markdown
73
75
  - Rakefile
@@ -86,6 +88,7 @@ files:
86
88
  - lib/boom/storage.rb
87
89
  - lib/boom/storage/base.rb
88
90
  - lib/boom/storage/json.rb
91
+ - lib/boom/storage/keychain.rb
89
92
  - lib/boom/storage/mongodb.rb
90
93
  - lib/boom/storage/redis.rb
91
94
  - test/examples/config_json.json
@@ -126,7 +129,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
126
129
  requirements: []
127
130
 
128
131
  rubyforge_project: boom
129
- rubygems_version: 1.3.7
132
+ rubygems_version: 1.6.2
130
133
  signing_key:
131
134
  specification_version: 2
132
135
  summary: boom lets you access text snippets over your command line.