wdi 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 072e4d21629eadc99678fe270a358e9314472052
4
- data.tar.gz: 92f8aa139b8714d8f24fb7450f4965bb64bfea85
3
+ metadata.gz: b84a9822c9a57a90f29324b893f0eedb76f15566
4
+ data.tar.gz: 1b86197809f81e9a00e10825d179607ddcfba10d
5
5
  SHA512:
6
- metadata.gz: ee5fa06b3dab7bc021c052e34a0cd4b9dcd9f7317453df1c252834d71a158ca682e959d0b80400e4f0c98f953e0e14b9dd1a0da1fe848ec94eeffb01235964a5
7
- data.tar.gz: 37e8829b0ed20141daf877ef632685d3f86f9eeacfde723175cd64a88b6f61886d8993e262348fd673677148e7382c433fa5f8793fef5a3552be6dac0389c82a
6
+ metadata.gz: e56f28f710f4accc04e1f385ac96188597ca03fb2126576ef580d738ce8481694c01422fef0e4d0bae8ae46e7b14499acd1ac5d6148c692d22b4cc305fc3258b
7
+ data.tar.gz: 2889d54100b1c7b3f44d160aa0e95afd79b6d2d246642fd81ab7c2df89e32937b681a69c739d1c070de1ff7291204c730369b4756274df3255217d810cf526cc
data/README.md CHANGED
@@ -1,26 +1,66 @@
1
1
  # The WDI Tool
2
2
 
3
- Use this gem to set up the WDI configuration file(s) and make changes to them. These exist in the folder ~/.wdi, and are used by the breadth of WDI command line tools in order to define common constants or development/environmental settings specific to the WDI command line tools.
3
+ Use this gem to set up the WDI configuration file(s) and make changes to them. These exist in the directory ~/.wdi, and are used by the breadth of WDI command line tools in order to define common constants or development/environmental settings specific to the WDI command line tools.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ gem install wdi
9
+ ```
10
+
11
+ It's as easy as that!
12
+
13
+ **Warning:** the current `.bash_profile` in common use by WDI NYC has aliased `wdi` to the command `cd ~/dev/wdi`. This will override the `wdi` executable loaded in the path by the gem. The alias needs to be removed from the profile and the shell reloaded for the tool to run.
4
14
 
5
15
  ## Usage
6
16
 
17
+ #### Creating a WDI directory and config file
18
+
7
19
  ```bash
8
- wdi init (--load URI)
9
- #=> if there is no .wdi folder, it creates one
10
- #=> by default it uses the example in data/default-config.json, or if
11
- #=> --load is defined (as a URI), then it attempts to use that
12
- #=> if there is a .wdi folder, this fails and suggests using `wdi config`
20
+ wdi init
13
21
  ```
14
22
 
23
+ As long as there is no `~/.wdi` directory, this command creates one. By default it uses the template file at `data/default-config.json`. If there is already a directory, you can forcefully overwrite it by using the "-f" switch. You can also specify a "load" file or URL template to copy the `config.json` file from.
24
+
25
+ #### Editing the WDI directory
26
+
27
+ ```bash
28
+ # wdi add-files <files>
29
+ ```
30
+
31
+ ... TBD (adds a file or files to the directory, and requisite keys *files.filename* to the config)...
32
+
33
+ #### Editing a WDI config file
34
+
15
35
  ```bash
16
36
  wdi config set <key(.key...)> <value>
17
37
  wdi config get <key(.key...)>
18
38
 
19
- wdi config add <key(.key...)> <value>
20
- wdi config remove <key(.key...)> (--force)
39
+ # wdi config add <key(.key...)> <value>
40
+ # wdi config remove <key(.key...)> (--force)
21
41
 
22
42
  wdi config keys (<key>)
23
43
 
24
- # wdi get-base
25
- # wdi get-repo class.current
26
- ```
44
+ # wdi get-<key>
45
+ # wdi get-<key-parent> <rest.of.key>
46
+ # wdi add-key <key> <value>
47
+ # wdi set-<key> <value>
48
+ ```
49
+
50
+ ... TBD ...
51
+
52
+ #### Navigating WDI repos
53
+
54
+ ```bash
55
+ # wdi go [:go.repo] [:go.pattern] <args>
56
+ ```
57
+
58
+ ... TBD ...
59
+
60
+ ## Development
61
+
62
+ #### Testing
63
+
64
+ Use **Aruba** (Cucumber) for CLI acceptance testing, and **Rspec** for unit testing the non-CLI modules and classes. Aruba is run with the `rake test` command, and tests are in the `/features` directory, while Rspec with the `bundle exec rspec` command (test in `/specs`, as per usual).
65
+
66
+ > Note: I'm tempted to add 'active_support/core_ext/string/inflections' as a requirement... I imagine it's insanely heavy, but should be on systems already if Rails is there... But we should try to be slim if this tool is going to be required in every WDI command line tool, right?
data/Rakefile CHANGED
@@ -1 +1,9 @@
1
1
  require "bundler/gem_tasks"
2
+ require "cucumber/rake/task"
3
+
4
+ Cucumber::Rake::Task.new(:features) do |t|
5
+ t.cucumber_opts = ['features', '-x', '--format progress']
6
+ end
7
+
8
+ desc "Run all test suites"
9
+ task :test => [:features]
@@ -1,8 +1,13 @@
1
1
  {
2
+ "name": "`whoami`",
2
3
  "base": "`echo $HOME`/dev/wdi",
3
4
  "repos": {
4
5
  "classes": {
5
6
  "current": "`echo $HOME`/dev/wdi/class_name"
6
7
  }
8
+ },
9
+ "go": {
10
+ "repo": ":repos.classes.current",
11
+ "pattern": "/$1/$2/:name"
7
12
  }
8
13
  }
@@ -0,0 +1,2 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__) + '/../../lib')
2
+ require 'aruba/cucumber'
@@ -0,0 +1,6 @@
1
+ Feature: Version
2
+ The WDI command line tool should be able to print its version
3
+
4
+ Scenario:
5
+ When I run `wdi version`
6
+ Then the output should contain "0.0.3"
@@ -10,7 +10,7 @@ module WDI
10
10
  def set(key, value)
11
11
  begin
12
12
  WDI::Config::set(key, value)
13
- say "The key '#{key}' in the WDI config file has been set to '#{value}'.", :green
13
+ say "The property '#{key}' in the WDI config file has been set to '#{value}'.", :green
14
14
  rescue WDI::ConfigError => e
15
15
  say e.message, :red
16
16
  end
@@ -19,7 +19,7 @@ module WDI
19
19
  desc "get", "get a value from the WDI config file"
20
20
  def get(key)
21
21
  begin
22
- say WDI::Config::get(WDI::Config::translate(key), key)
22
+ say WDI::Config::get(key)
23
23
  rescue WDI::ConfigError => e
24
24
  say e.message, :red
25
25
  end
@@ -39,10 +39,10 @@ module WDI
39
39
 
40
40
  # end
41
41
 
42
- desc "keys", "list the keys in the WDI config file"
42
+ desc "keys", "list the properties in the WDI config file"
43
43
  def keys(key=nil)
44
44
  begin
45
- say WDI::Config::keys(WDI::Config::translate(key), key).join("\n")
45
+ say WDI::Config::properties(key).join("\n")
46
46
  rescue WDI::ConfigError => e
47
47
  say e.message, :red
48
48
  end
@@ -50,6 +50,13 @@ module WDI
50
50
  end
51
51
 
52
52
  class Wdi < Thor
53
+ #class_option :version, alias: "-v", type: :boolean
54
+
55
+ desc "version", "get current WDI tool version"
56
+ def version
57
+ say WDI::VERSION
58
+ end
59
+
53
60
  desc "init", "initialize a new WDI directory at ~/.wdi"
54
61
  method_option :load,
55
62
  aliases: ["-l"],
@@ -6,7 +6,197 @@ require "pry"
6
6
 
7
7
  module WDI
8
8
  module Config
9
- KEY_REGEX = /^[a-z.]*$/ # only lowercase words separated by periods
9
+ KEY_REGEX = /^[a-z.]*$/ # only lowercase words separated by periods
10
+ VALUE_AS_KEY_REGEX = /:[a-z._]+/ # a value containing at least one word prefixed by ':'
11
+ ALLOWED_BASH_REGEX = /(`(echo|pwd|ls|whoami)[^\|;&]*`)/
12
+
13
+ ##############################################################
14
+ class ConfigFile
15
+ attr_reader :pairs
16
+
17
+ def initialize(json_configuration)
18
+ config = JSON.parse(json_configuration, symbolize_names: true)
19
+
20
+ @pairs = {}
21
+ recursive_build_pairs_from config
22
+ ensure_format_of_pairs
23
+ end
24
+
25
+ def has_key?(key)
26
+ key = translate_incoming(key)
27
+ @pairs.key?(key)
28
+ end
29
+
30
+ def value_at(key)
31
+ key = translate_incoming(key)
32
+
33
+ if @pairs.key?(key)
34
+ if @pairs[key].is_a? Array
35
+ return @pairs[key].map {|value| retrieve_value_with_references(value) }
36
+ else
37
+ return retrieve_value_with_references(@pairs[key])
38
+ end
39
+ elsif keys_with_prefix(key)
40
+ raise WDI::ConfigError,
41
+ "This key doesn't represent a property in the WDI config file. " +
42
+ "Try `wdi config keys #{key}`."
43
+ else
44
+ return false
45
+ end
46
+ end
47
+
48
+ def keys_with_value(value)
49
+ key_list = @pairs.select {|k,v| v == value}.keys
50
+ key_list.count == 0 ? false : key_list.map{|k| translate_outgoing(k)}
51
+ end
52
+
53
+ def set_key_value(key, value)
54
+ key = translate_incoming(key)
55
+
56
+ raise WDI::ConfigError,
57
+ "This key is not in the WDI config file." unless @pairs.key?(key)
58
+ raise WDI::ConfigError,
59
+ "This value is not formatted correctly for the WDI config file." unless value.is_a?(String)
60
+ disallow_bad_references_in value
61
+ @pairs[key] = value
62
+ end
63
+
64
+ def add_key_value(key, value)
65
+ key = translate_incoming(key)
66
+ disallow_bad_references_in value
67
+
68
+ if has_key?(key)
69
+ if @pairs[key].is_a? Array
70
+ @pairs[key] << value
71
+ else
72
+ @pairs[key] = [@pairs[key],value]
73
+ end
74
+ else
75
+ @pairs[key] = value
76
+ end
77
+ return @pairs[key]
78
+ end
79
+
80
+ def keys
81
+ @pairs.keys.map{|k| translate_outgoing(k)}
82
+ end
83
+
84
+ def keys_with_prefix(prefix=nil)
85
+ return keys if prefix.nil?
86
+ prefix = translate_outgoing(translate_incoming(prefix)) # force correct string format
87
+ key_list = keys.select{|k| (k =~ Regexp.new(prefix)) == 0 }
88
+ key_list.count == 0 ? false : key_list
89
+ end
90
+
91
+ def to_h
92
+ result = {}
93
+
94
+ keys.each do |key|
95
+ add_child_node(result, key, @pairs[translate_incoming(key)])
96
+ end
97
+
98
+ return result
99
+ end
100
+
101
+ def to_json
102
+ JSON.pretty_generate(self.to_h)
103
+ end
104
+
105
+ def to_s
106
+ @pairs.to_s
107
+ end
108
+
109
+ private
110
+ def translate_incoming(key)
111
+ if key.is_a? String
112
+ key.gsub(/\./, "_").to_sym
113
+ elsif key.is_a? Symbol
114
+ key
115
+ else
116
+ raise WDI::ConfigError,
117
+ "This property is not formatted correctly for the WDI config file."
118
+ end
119
+ end
120
+
121
+ def interpolate_commands_in(value)
122
+ value.gsub(ALLOWED_BASH_REGEX) do |command|
123
+ eval(command).chomp
124
+ end
125
+ end
126
+
127
+ def translate_outgoing(key)
128
+ key.to_s.gsub(/_/,".")
129
+ end
130
+
131
+ def retrieve_value_with_references(value)
132
+ value = interpolate_commands_in value
133
+ check_value = disallow_bad_references_in value
134
+
135
+ return value if (check_value =~ VALUE_AS_KEY_REGEX).nil?
136
+ check_value.gsub(VALUE_AS_KEY_REGEX) {|reference| value_at(reference[1..-1])}
137
+ end
138
+
139
+ def ensure_format_of_pairs
140
+ pairs.each_pair do |key, value|
141
+ key = translate_outgoing(key)
142
+
143
+ if (key =~ KEY_REGEX).nil? || key[0] == "." || key[-1] == "."
144
+ raise WDI::ConfigError,
145
+ "This property is not formatted correctly for the WDI config file."
146
+ end
147
+
148
+ if !(value.is_a?(String) || value.is_a?(Array))
149
+ raise WDI::ConfigError,
150
+ "This value is not formatted correctly for the WDI config file " + \
151
+ "(must be a string or an array of strings)."
152
+ else
153
+ disallow_bad_references_in value
154
+ end
155
+ end
156
+ end
157
+
158
+ def disallow_bad_references_in(value)
159
+ check_value = value.gsub(VALUE_AS_KEY_REGEX) do |reference|
160
+ translate_outgoing(reference) # only translate to dots if matches reference
161
+ end
162
+
163
+ check_value.scan(VALUE_AS_KEY_REGEX) do |reference|
164
+ unless has_key?(reference[1..-1])
165
+ raise WDI::ConfigError,
166
+ "This value is not formatted correctly for the WDI config file " + \
167
+ "(malformed reference)."
168
+ end
169
+ end
170
+ end
171
+
172
+ def recursive_build_pairs_from(tree, parent_key="")
173
+ tree.each_pair do |child_key, value|
174
+ if value.is_a?(Hash)
175
+ recursive_build_pairs_from(value, append_keys(parent_key, child_key))
176
+ else
177
+ @pairs[append_keys(parent_key, child_key).to_sym] = value
178
+ end
179
+ end
180
+ end
181
+
182
+ def add_child_node(node, key, value)
183
+ parent, child = key.split(".", 2)
184
+
185
+ if child.nil?
186
+ node[parent.to_sym] = value
187
+ else
188
+ node[parent.to_sym] = {} if node[parent.to_sym].nil?
189
+ add_child_node(node[parent.to_sym], child, value)
190
+ end
191
+ end
192
+
193
+ def append_keys(parent, child)
194
+ parent = (parent.nil? || parent == "") ? "" : parent.to_s + "_"
195
+ child = (child.nil? || child == "") ? "" : child.to_s
196
+ parent + child
197
+ end
198
+ end
199
+ ###############################################################
10
200
 
11
201
  def self.path
12
202
  File.expand_path("config.json", WDI::Folder::path)
@@ -16,25 +206,19 @@ module WDI
16
206
  File.exists?(self.path)
17
207
  end
18
208
 
19
- def self.file
20
- @@config ||= self.load
209
+ def self.config
210
+ @@config ||= self.load_local_configuration
21
211
  end
22
212
 
23
- def self.load
24
- @@config = JSON.parse(IO.read(self.path), symbolize_names: true)
213
+ def self.load_local_configuration
214
+ @@config = WDI::Config::ConfigFile.new(IO.read(self.path))
25
215
  end
26
216
 
27
- def self.save
28
- File.open(File.expand_path("config.json", WDI::Folder::path), "w+") do |f|
29
- f.write JSON.pretty_generate(self.file)
30
- end
31
- end
32
-
33
- def self.load_file(config_uri)
217
+ def self.load_configuration_from(config_uri)
34
218
  begin
35
219
  uri = URI(config_uri)
36
220
  config_file = ["http", "https"].include?(uri.scheme) ? uri.open.read : IO.read(config_uri)
37
- @@config = self.safe_replace(JSON.parse(config_file, symbolize_names: true))
221
+ @@config = WDI::Config::ConfigFile.new config_file
38
222
  self.save
39
223
 
40
224
  rescue Errno::ENOENT => e
@@ -48,84 +232,32 @@ module WDI
48
232
  end
49
233
  end
50
234
 
51
- ############################################
52
-
53
- def self.get(key, key_name)
54
- raise WDI::ConfigError, "This key is not in the WDI config file." if key.nil?
55
- raise WDI::ConfigError,
56
- "This key doesn't represent a property in the WDI config file. " +
57
- "Try `wdi config keys #{key_name}`." if key.is_a?(Hash)
58
- return key
59
- end
60
-
61
- def self.set(key_name, new_value)
62
- current_value = WDI::Config::translate(key_name)
63
- raise WDI::ConfigError,
64
- "This key doesn't represent a property in the WDI config file. " +
65
- "Try `wdi config keys #{key_name}`." if current_value.is_a?(Hash)
66
-
67
-
68
- self.set_child(self.file, key_name, new_value)
69
- self.save
70
- end
71
-
72
- def self.set_child(key, key_name, value)
73
- parent, child = key_name.split(".", 2)
74
- if child.nil?
75
- key[parent.to_sym] = value
76
- else
77
- self.set_child(key[parent.to_sym], child, value)
235
+ def self.save
236
+ File.open(File.expand_path("config.json", WDI::Folder::path), "w+") do |f|
237
+ f.write self.config.to_json
78
238
  end
79
239
  end
80
240
 
81
- def self.keys(tree, parent_key="", key_list=[])
82
- raise WDI::ConfigError,
83
- "There are no (sub-)keys in the WDI config file that fit this criteria." unless tree.is_a?(Hash)
84
-
85
- tree.each_pair do |child_key, value|
86
- if value.is_a?(Hash)
87
- self.keys(value, self.append_keys(parent_key, child_key), key_list)
88
- else
89
- key_list << self.append_keys(parent_key, child_key)
90
- end
91
- end
241
+ ###############################################################
242
+ ## WRAPPER MODULE METHODS
92
243
 
93
- return key_list
244
+ def self.create(config_uri)
245
+ config_uri.nil? ? self.load_local_configuration : self.load_configuration_from(config_uri)
94
246
  end
95
247
 
96
- ############################################
97
-
98
- def self.append_keys(parent, child)
99
- parent = (parent.nil? || parent == "") ? "" : parent.to_s + "."
100
- child = (child.nil? || child == "") ? "" : child.to_s
101
- parent + child
248
+ def self.get(property)
249
+ self.config.value_at property
102
250
  end
103
251
 
104
- def self.translate(key, tree=self.file)
105
- # assume we are talking about the config tree as a whole if nil
106
- return tree if key.nil?
107
-
108
- raise WDI::ConfigError,
109
- "This key is not formatted correctly for the WDI config file." unless key =~ KEY_REGEX
110
- parent, child = key.split(".", 2)
111
- value = tree[parent.to_sym]
112
- raise WDI::ConfigError, "This key is not in the WDI config file." if value.nil?
252
+ def self.set(property, value)
253
+ self.config.set_key_value property, value
254
+ self.save
255
+ end
113
256
 
114
- return (child.nil? ? value : self.translate(child, value))
257
+ def self.properties(prefix=nil)
258
+ self.config.keys_with_prefix prefix
115
259
  end
116
260
 
117
- def self.safe_replace(config)
118
- JSON.recurse_proc(config) do |line|
119
- if line.is_a?(String)
120
- # so this is not REALLY safe, but should be safe enough... maybe even too restrictive
121
- allowed_bash_regex = /(`(echo|pwd|ls)[^\|;&]*`)/
122
-
123
- result = eval( line[allowed_bash_regex] )
124
- line.gsub!( allowed_bash_regex, result.chomp ) unless result.nil?
125
- end
126
- end
127
261
 
128
- return config
129
- end
130
262
  end
131
263
  end
@@ -24,7 +24,7 @@ module WDI
24
24
 
25
25
  def self.create_with_config(remove_current_directory, file)
26
26
  self.create(remove_current_directory)
27
- WDI::Config::load_file(file)
27
+ WDI::Config::create(file)
28
28
  end
29
29
 
30
30
  def self.remove!
@@ -1,3 +1,3 @@
1
- module Wdi
2
- VERSION = "0.0.2"
1
+ module WDI
2
+ VERSION = "0.0.3"
3
3
  end
@@ -0,0 +1,315 @@
1
+ require "spec_helper"
2
+
3
+ describe WDI::Config do
4
+ describe WDI::Config::ConfigFile do # namespacing weirdness...
5
+ config_json_contents_with_interpolation = <<-JSON_CONTENTS
6
+ {
7
+ "name": "`whoami`",
8
+ "base": "`echo $HOME`/dev/wdi",
9
+ "repos": {
10
+ "classes": {
11
+ "current": "`echo $HOME`/dev/wdi/class_name"
12
+ }
13
+ },
14
+ "go": {
15
+ "repo": ":repos.classes.current",
16
+ "pattern": "/$1/$2/:name"
17
+ }
18
+ }
19
+ JSON_CONTENTS
20
+
21
+ config_json_contents = <<-JSON_CONTENTS
22
+ {
23
+ "name": "philip",
24
+ "base": "/Users/philip/dev/wdi",
25
+ "repos": {
26
+ "classes": {
27
+ "current": "/Users/philip/dev/wdi/class_name"
28
+ }
29
+ },
30
+ "go": {
31
+ "repo": ":repos.classes.current",
32
+ "pattern": "/$1/$2/:name"
33
+ }
34
+ }
35
+ JSON_CONTENTS
36
+
37
+ describe "#initialize" do
38
+ it "raises an error if properties aren't formatted for the config to work" do
39
+ expect {WDI::Config::ConfigFile.new('{"name1":"pj"}')}.to raise_error
40
+ expect {WDI::Config::ConfigFile.new('{"name_":"pj"}')}.to raise_error
41
+ expect {WDI::Config::ConfigFile.new('{"name.":"pj"}')}.to raise_error
42
+ expect {WDI::Config::ConfigFile.new('{".name":"pj"}')}.to raise_error
43
+ end
44
+
45
+ it "allows bash commands in the values" do
46
+ keys_values = {
47
+ name: "`whoami`",
48
+ base: "`echo $HOME`/dev/wdi",
49
+ repos_classes_current: "`echo $HOME`/dev/wdi/class_name",
50
+ go_repo: ":repos.classes.current",
51
+ go_pattern: "/$1/$2/:name"
52
+ }
53
+ expect(WDI::Config::ConfigFile.new(config_json_contents_with_interpolation).pairs).to \
54
+ eql(keys_values)
55
+ end
56
+
57
+ it "does not allow string values to have colon-prefixed words unless they reference properties" do
58
+ expect {WDI::Config::ConfigFile.new('{"name":":not_name"}')}.to raise_error
59
+ end
60
+ end
61
+
62
+ let!(:config) {WDI::Config::ConfigFile.new(config_json_contents)}
63
+
64
+ describe "#value_at" do
65
+ it "returns the value at the given key (as a symbol)" do
66
+ expect(config.value_at(:name)).to eql("philip")
67
+ end
68
+
69
+ it "returns the value at the given key (as a string)" do
70
+ expect(config.value_at("name")).to eql("philip")
71
+ end
72
+
73
+ it "works with dotted key strings appropriately" do
74
+ expect(config.value_at("repos.classes.current")).to \
75
+ eql("/Users/philip/dev/wdi/class_name")
76
+ end
77
+
78
+ it "works with underscored key symbols appropriately" do
79
+ expect(config.value_at(:repos_classes_current)).to \
80
+ eql("/Users/philip/dev/wdi/class_name")
81
+ end
82
+
83
+ it "raises an error when the key exists but is not a leaf node" do
84
+ expect {config.value_at("repos.classes")}.to raise_error
85
+ expect {config.value_at(:repos_classes)}.to raise_error
86
+ end
87
+
88
+ it "returns false when the key is not in the config file" do
89
+ expect(config.value_at(:not_a_key)).to be_false
90
+ end
91
+
92
+ context "the value is a property reference, ie starts with a colon" do
93
+ it "returns the referenced property value" do
94
+ expect(config.value_at("go.repo")).to \
95
+ eql("/Users/philip/dev/wdi/class_name")
96
+ end
97
+
98
+ it "works with either format for the reference" do
99
+ config.set_key_value "go.repo", ":repos_classes_current"
100
+ expect(config.value_at("go.repo")).to \
101
+ eql("/Users/philip/dev/wdi/class_name")
102
+ end
103
+
104
+ it "interpolates if the reference is in the value" do
105
+ expect(config.value_at("go.pattern")).to eql("/$1/$2/philip")
106
+ end
107
+
108
+ it "raises an error when the referenced property does not exist", :broken => true do
109
+ allow(config).to receive(:disallow_bad_references_in) # not totally secure in this working...
110
+ config.set_key_value "go.repo", ":not_a_value"
111
+
112
+ expect {config.value_at("go.repo")}.to raise_error
113
+ end
114
+ end
115
+
116
+ context "the value contains an allowed bash command" do
117
+ let!(:config) {WDI::Config::ConfigFile.new(config_json_contents_with_interpolation)}
118
+
119
+ it "returns the value with the command result interpolated" do
120
+ expect(config.value_at("base")).to eql((`echo $HOME`).chomp + "/dev/wdi")
121
+ end
122
+
123
+ it "works even when it was referenced" do
124
+ expect(config.value_at("go.repo")).to eql((`echo $HOME`).chomp + "/dev/wdi/class_name")
125
+ end
126
+ end
127
+ end
128
+
129
+ describe "#set_key_value" do
130
+ it "updates the value at the given key" do
131
+ config.set_key_value "name", "pj"
132
+ expect(config.value_at("name")).to eql("pj")
133
+ end
134
+
135
+ it "works when key is given in symbol format" do
136
+ config.set_key_value :repos_classes_current, "/"
137
+ expect(config.value_at("repos.classes.current")).to eql("/")
138
+ end
139
+
140
+ it "raises an error if the key doesn't exist" do
141
+ expect {config.set_key_value "nom", "pj"}.to raise_error
142
+ end
143
+
144
+ it "raises an error if the value isn't a string" do
145
+ expect {config.set_key_value "name", :pj}.to raise_error
146
+ end
147
+
148
+ context "with string values that have colon-prefixed words" do
149
+ it "does not allow them unless they reference properties" do
150
+ expect {config.set_key_value "name", "hello i am :not_name"}.to raise_error
151
+ end
152
+
153
+ it "allows them when they reference properties" do
154
+ expect {config.set_key_value "name", "hello i am :name"}.not_to raise_error
155
+ end
156
+ end
157
+ end
158
+
159
+ describe "#has_key?" do
160
+ it "returns true if the key exists" do
161
+ expect(config.has_key?("name")).to be_true
162
+ end
163
+
164
+ it "works when key is given in symbol format" do
165
+ expect(config.has_key?(:repos_classes_current)).to be_true
166
+ end
167
+
168
+ it "returns false if the key doesn't exist" do
169
+ expect(config.has_key?("nom")).to be_false
170
+ end
171
+ end
172
+
173
+ describe "#keys_with_value" do
174
+ it "returns the keys at the given value (as a symbol)" do
175
+ expect(config.keys_with_value("philip")).to eql(["name"])
176
+ end
177
+
178
+ it "returns the keys with dots replaced by underscores" do
179
+ expect(config.keys_with_value("/Users/philip/dev/wdi/class_name")).to \
180
+ eql(["repos.classes.current"])
181
+ end
182
+
183
+ it "returns multiple keys if necessary" do
184
+ config.add_key_value("repos.instructors.current", "/Users/philip/dev/wdi/class_name")
185
+ expect(config.keys_with_value("/Users/philip/dev/wdi/class_name")).to \
186
+ eql(["repos.classes.current","repos.instructors.current"])
187
+ end
188
+
189
+ it "returns false if the value is not present" do
190
+ expect(config.keys_with_value("not_a_value")).to be_false
191
+ end
192
+ end
193
+
194
+ describe "#keys_with_prefix" do
195
+ it "returns the keys with the given prefix" do
196
+ expect(config.keys_with_prefix("go")).to eql(["go.repo","go.pattern"])
197
+ end
198
+
199
+ it "returns the key itself if the prefix is a key" do
200
+ expect(config.keys_with_prefix("go.repo")).to eql(["go.repo"])
201
+ end
202
+
203
+ it "returns false when the key is not present" do
204
+ expect(config.keys_with_prefix("not_a_key")).to be_false
205
+ end
206
+
207
+ it "returns all keys when given no prefix" do
208
+ keys = ["name","base","repos.classes.current","go.repo","go.pattern"]
209
+ expect(config.keys_with_prefix).to match_array(keys)
210
+ end
211
+ end
212
+
213
+ describe "#add_key_value" do
214
+ it "adds a new key with the given value" do
215
+ config.add_key_value("repos.instructors.current", "/Users/philip/dev/wdi/class_name")
216
+ expect(config.value_at("repos.instructors.current")).to eql("/Users/philip/dev/wdi/class_name")
217
+ end
218
+
219
+ context "when the given key already exists and is not an array" do
220
+ it "turns the property into an array and pushes the new value on to it" do
221
+ config.add_key_value("name", "pj")
222
+ expect(config.value_at("name")).to match_array(["philip","pj"])
223
+ end
224
+ end
225
+
226
+ context "when the given key already exists and is an array" do
227
+ it "pushes the new value on to it" do
228
+ config.add_key_value("name", "pj")
229
+ config.add_key_value("name", "felipe")
230
+ expect(config.value_at("name")).to match_array(["philip","pj","felipe"])
231
+ end
232
+ end
233
+
234
+ context "with string values that have colon-prefixed words" do
235
+ it "does not allow them unless they reference properties" do
236
+ expect {config.add_key_value("name", "hello i am :not_name")}.to raise_error
237
+ end
238
+
239
+ it "allows them when they reference properties" do
240
+ expect {config.add_key_value("name", "hello i am :name")}.not_to raise_error
241
+ end
242
+ end
243
+ end
244
+
245
+ describe "#pairs", :unnecessary => true do
246
+ it "returns all of the key-value pairs" do
247
+ keys_values = {
248
+ name: "philip",
249
+ base: "/Users/philip/dev/wdi",
250
+ repos_classes_current: "/Users/philip/dev/wdi/class_name",
251
+ go_repo: ":repos.classes.current",
252
+ go_pattern: "/$1/$2/:name"
253
+ }
254
+ expect(config.pairs).to eql(keys_values)
255
+ end
256
+ end
257
+
258
+ describe "#keys", :unnecessary => true do
259
+ it "returns all of the keys" do
260
+ keys = ["name","base","repos.classes.current","go.repo","go.pattern"]
261
+ expect(config.keys).to match_array(keys)
262
+ end
263
+ end
264
+
265
+ describe "#to_h" do
266
+ it "returns the config's pairs as a hash-tree" do
267
+ config = WDI::Config::ConfigFile.new(config_json_contents_with_interpolation)
268
+ hash_tree = {
269
+ name: "`whoami`",
270
+ base: "`echo $HOME`/dev/wdi",
271
+ repos: {
272
+ classes: {
273
+ current: "`echo $HOME`/dev/wdi/class_name"
274
+ }
275
+ },
276
+ go: {
277
+ repo: ":repos.classes.current",
278
+ pattern: "/$1/$2/:name"
279
+ }
280
+ }
281
+
282
+ expect(config.to_h).to eql(hash_tree)
283
+ end
284
+ end
285
+
286
+ describe "#to_json" do
287
+ it "returns the config's pairs as a JSON string representing the hash-tree" do
288
+ config = WDI::Config::ConfigFile.new(config_json_contents_with_interpolation)
289
+ hash_tree = {
290
+ name: "`whoami`",
291
+ base: "`echo $HOME`/dev/wdi",
292
+ repos: {
293
+ classes: {
294
+ current: "`echo $HOME`/dev/wdi/class_name"
295
+ }
296
+ },
297
+ go: {
298
+ repo: ":repos.classes.current",
299
+ pattern: "/$1/$2/:name"
300
+ }
301
+ }
302
+
303
+ expect(config.to_json).to eql(JSON.pretty_generate(hash_tree)) #
304
+ end
305
+ end
306
+
307
+ describe "#to_s" do
308
+ it "returns a string version of the contents (not the correct json, but key-val pairs)" do
309
+ expect(config.to_s).to eql(config.pairs.to_s)
310
+ end
311
+ end
312
+
313
+ end
314
+
315
+ end
@@ -0,0 +1,14 @@
1
+ require "bundler"
2
+ require "pry"
3
+
4
+ Bundler.setup
5
+
6
+ Dir[File.expand_path('../../lib/wdi/*.rb', __FILE__)].each {|file| require file }
7
+
8
+ RSpec.configure do |config|
9
+ config.filter_run_excluding unnecessary: true
10
+ config.filter_run_excluding broken: true
11
+
12
+ config.color = true
13
+ config.formatter = "documentation"
14
+ end
@@ -5,10 +5,11 @@ require 'wdi/version'
5
5
 
6
6
  Gem::Specification.new do |spec|
7
7
  spec.name = "wdi"
8
- spec.version = Wdi::VERSION
8
+ spec.version = WDI::VERSION
9
9
  spec.authors = ["Philip Hughes"]
10
10
  spec.email = ["pj@ga.co"]
11
- spec.summary = %q{A utility for dealing with and configuring the WDI folder and command line tools.}
11
+ spec.summary = %q{A utility for working with (and configuring) the WDI directory and WDI command line tools.}
12
+ spec.description = %q{TBC}
12
13
  spec.homepage = "https://github.com/ga-instructors/wdi-gem"
13
14
  spec.license = "BSD 3-Clause"
14
15
 
@@ -18,8 +19,10 @@ Gem::Specification.new do |spec|
18
19
  spec.require_paths = ["lib"]
19
20
 
20
21
  spec.add_development_dependency "bundler", "~> 1.5"
21
- spec.add_development_dependency "rake", ">= 0.0"
22
- spec.add_development_dependency "pry", ">= 0.0"
22
+ spec.add_development_dependency "rake", "~> 10.2"
23
+ spec.add_development_dependency "rspec", '~> 2.14', '>= 2.14.1'
24
+ spec.add_development_dependency "aruba", '~> 0.5', '>= 0.5.4'
25
+ spec.add_development_dependency "pry", '~> 0.9', '>= 0.9.12'
23
26
 
24
27
  spec.add_runtime_dependency "thor", "~> 0.19"
25
28
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: wdi
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Philip Hughes
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-03-30 00:00:00.000000000 Z
11
+ date: 2014-03-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -28,30 +28,76 @@ dependencies:
28
28
  name: rake
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.2'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.2'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '2.14'
48
+ - - ">="
49
+ - !ruby/object:Gem::Version
50
+ version: 2.14.1
51
+ type: :development
52
+ prerelease: false
53
+ version_requirements: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - "~>"
56
+ - !ruby/object:Gem::Version
57
+ version: '2.14'
31
58
  - - ">="
32
59
  - !ruby/object:Gem::Version
33
- version: '0.0'
60
+ version: 2.14.1
61
+ - !ruby/object:Gem::Dependency
62
+ name: aruba
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: '0.5'
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ version: 0.5.4
34
71
  type: :development
35
72
  prerelease: false
36
73
  version_requirements: !ruby/object:Gem::Requirement
37
74
  requirements:
75
+ - - "~>"
76
+ - !ruby/object:Gem::Version
77
+ version: '0.5'
38
78
  - - ">="
39
79
  - !ruby/object:Gem::Version
40
- version: '0.0'
80
+ version: 0.5.4
41
81
  - !ruby/object:Gem::Dependency
42
82
  name: pry
43
83
  requirement: !ruby/object:Gem::Requirement
44
84
  requirements:
85
+ - - "~>"
86
+ - !ruby/object:Gem::Version
87
+ version: '0.9'
45
88
  - - ">="
46
89
  - !ruby/object:Gem::Version
47
- version: '0.0'
90
+ version: 0.9.12
48
91
  type: :development
49
92
  prerelease: false
50
93
  version_requirements: !ruby/object:Gem::Requirement
51
94
  requirements:
95
+ - - "~>"
96
+ - !ruby/object:Gem::Version
97
+ version: '0.9'
52
98
  - - ">="
53
99
  - !ruby/object:Gem::Version
54
- version: '0.0'
100
+ version: 0.9.12
55
101
  - !ruby/object:Gem::Dependency
56
102
  name: thor
57
103
  requirement: !ruby/object:Gem::Requirement
@@ -66,7 +112,7 @@ dependencies:
66
112
  - - "~>"
67
113
  - !ruby/object:Gem::Version
68
114
  version: '0.19'
69
- description:
115
+ description: TBC
70
116
  email:
71
117
  - pj@ga.co
72
118
  executables:
@@ -81,11 +127,15 @@ files:
81
127
  - Rakefile
82
128
  - bin/wdi
83
129
  - data/default-config.json
130
+ - features/support/env.rb
131
+ - features/version.feature
84
132
  - lib/wdi.rb
85
133
  - lib/wdi/cli.rb
86
134
  - lib/wdi/config.rb
87
135
  - lib/wdi/folder.rb
88
136
  - lib/wdi/version.rb
137
+ - spec/config_spec.rb
138
+ - spec/spec_helper.rb
89
139
  - wdi.gemspec
90
140
  homepage: https://github.com/ga-instructors/wdi-gem
91
141
  licenses:
@@ -110,6 +160,10 @@ rubyforge_project:
110
160
  rubygems_version: 2.2.2
111
161
  signing_key:
112
162
  specification_version: 4
113
- summary: A utility for dealing with and configuring the WDI folder and command line
114
- tools.
115
- test_files: []
163
+ summary: A utility for working with (and configuring) the WDI directory and WDI command
164
+ line tools.
165
+ test_files:
166
+ - features/support/env.rb
167
+ - features/version.feature
168
+ - spec/config_spec.rb
169
+ - spec/spec_helper.rb