gas 0.1.7 → 0.1.8

Sign up to get free protection for your applications and to get access to all the features.
data/lib/gas/version.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  module Gas
2
2
 
3
- VERSION = '0.1.7'
3
+ VERSION = '0.1.8'
4
4
 
5
5
  end
6
6
 
@@ -0,0 +1,338 @@
1
+ require './spec/spec_helper'
2
+
3
+ require './lib/gas'
4
+
5
+ require 'rspec/mocks'
6
+ require 'rspec/mocks/standalone'
7
+ require 'pry'
8
+
9
+
10
+ describe Gas::Ssh do
11
+ before :all do
12
+ @nickname = "thisaccountmaybedeletedmysteriously"
13
+ @name = "tim T"
14
+ @email = "tim@timmy.com"
15
+ end
16
+
17
+ before :each do
18
+ @uid = "teddy"
19
+ end
20
+
21
+ describe "SSH key file handling..." do
22
+
23
+ before :all do
24
+ Gas::Prompter.stub!(:user_wants_to_delete_all_ssh_data?).and_return("l") # only delete's local keys
25
+ end
26
+
27
+ after :all do
28
+ Gas::Prompter.unstub!(:user_wants_to_delete_all_ssh_data?)
29
+ end
30
+
31
+ describe "Detecting when files are missing..." do
32
+ it "should detect when an id_rsa isn't in the .gas directory" do
33
+ Gas::Ssh.corresponding_rsa_files_exist?(@uid).should be_false
34
+ end
35
+ end
36
+
37
+ describe "Detecting when files exist..." do
38
+ before :each do
39
+ create_user_no_git @uid, @uid, "a@b.com"
40
+ end
41
+
42
+ after :each do
43
+ delete_user_no_git @uid
44
+ end
45
+
46
+ it 'should detect when an id_rsa is already in the .gas directory' do
47
+ Gas::Ssh.corresponding_rsa_files_exist?(@uid).should be_true
48
+ end
49
+ end
50
+
51
+ describe "File System Changes..." do
52
+
53
+ it 'should create ssh keys in .gas && Gas.remove should be able to remove those files' do
54
+ STDIN.stub!(:gets).and_return("y\n") # forces the dialogs to
55
+ Gas::Ssh.stub!(:upload_public_key_to_github).and_return(false)
56
+
57
+ lambda do
58
+ Gas.add(@nickname,@name,@email)
59
+ end.should change{count_of_files_in(GAS_DIRECTORY)}.by(2)
60
+
61
+ lambda do
62
+ Gas.delete(@nickname)
63
+ end.should change{count_of_files_in(GAS_DIRECTORY)}.by(-2)
64
+
65
+ STDIN.unstub!(:gets)
66
+ Gas::Ssh.unstub!(:upload_public_key_to_github)
67
+ end
68
+
69
+
70
+ describe 'For the ssh directory...' do
71
+ before :each do
72
+ clean_out_ssh_directory
73
+ clean_out_gas_directory(@nickname)
74
+
75
+ # a second user for deleting
76
+ @nickname2 = "thisaccountmaybedeletedmysteriously2"
77
+ @name2 = "tim T2"
78
+ @email2 = "tim@timmy.com2"
79
+
80
+ create_user_no_git(@nickname2, @name2, @email2)
81
+ end
82
+
83
+ after :each do
84
+ Gas.delete(@nickname)
85
+ delete_user_no_git(@nickname2)
86
+ end
87
+
88
+
89
+ it "if there's no key in .ssh, the use command should place a key there" do
90
+
91
+ Gas.use @nickname2
92
+ # 3) The .ssh directory should now contain that file
93
+ File.exist?(SSH_DIRECTORY + "/id_rsa.pub").should be_true
94
+ end
95
+
96
+ it "shouldn't overwrite an existing key in ~/.ssh that isn't backed up in .gas and the user aborts" do
97
+ # 2) Create a bogus id_rsa in the .ssh directory
98
+ id_rsa, id_rsa_pub = plant_bogus_rsa_keys_in_ssh_directory
99
+ # 3) Switch to that user
100
+ Gas::Prompter.stub!(:user_wants_to_overwrite_existing_rsa_key?).and_return(false)
101
+ Gas.use @nickname2
102
+ Gas::Prompter.unstub!(:user_wants_to_overwrite_existing_rsa_key?)
103
+ # 4) The .ssh directory should not be changed
104
+ File.open(SSH_DIRECTORY + "/id_rsa", "r") do |f|
105
+ f.read.strip.should eq id_rsa
106
+ end
107
+ File.open(SSH_DIRECTORY + "/id_rsa.pub", "r") do |f|
108
+ f.read.strip.should eq id_rsa_pub
109
+ end
110
+ end
111
+
112
+ it "should overwrite an existing, unbacked-up key in ~/.ssh if user wants" do
113
+ # 2) Create a bogus id_rsa in the .ssh directory
114
+ id_rsa, id_rsa_pub = plant_bogus_rsa_keys_in_ssh_directory
115
+ # 3) Switch to that user
116
+ Gas::Prompter.stub!(:user_wants_to_overwrite_existing_rsa_key?).and_return(true)
117
+ Gas.use @nickname2
118
+ Gas::Prompter.unstub!(:user_wants_to_overwrite_existing_rsa_key?)
119
+ # 4) The .ssh directory should not be changed
120
+ File.open(SSH_DIRECTORY + "/id_rsa", "r") do |f|
121
+ f.read.strip.should_not eq id_rsa
122
+ end
123
+ end
124
+
125
+ it "If there's a key in ~/.ssh that's backed up in .gas" do
126
+ # 1) Create an alternate user
127
+ create_user_no_git(@nickname, @name, @email)
128
+ rsa, rsa_pub = Gas::Ssh.get_associated_rsa_key(@nickname)
129
+ rsa2, rsa2_pub = Gas::Ssh.get_associated_rsa_key(@nickname2)
130
+ # 2)
131
+ Gas.use @nickname2
132
+ File.open(SSH_DIRECTORY + "/id_rsa.pub", "r") do |f|
133
+ f.read.strip.should eq rsa2
134
+ end
135
+ Gas.use @nickname
136
+ File.open(SSH_DIRECTORY + "/id_rsa.pub", "r") do |f|
137
+ f.read.strip.should eq rsa
138
+ end
139
+ end
140
+
141
+ it "should delete the key in .ssh when the user is deleted" do
142
+ create_user_no_git(@nickname, @name, @email)
143
+ File.exists?(GAS_DIRECTORY + "/#{@nickname}_id_rsa").should be_true
144
+ Gas.delete @nickname
145
+ File.exists?(GAS_DIRECTORY + "/#{@nickname}_id_rsa").should be_false
146
+ end
147
+
148
+ it 'should be able to copy ssh keys in the ssh' do
149
+ # put a key pair in the ssh directory
150
+ mock_text = "this is a mock ssh file"
151
+ File.open(SSH_DIRECTORY + "/id_rsa","w+") do |f|
152
+ f.write(mock_text)
153
+ end
154
+ File.open(SSH_DIRECTORY + "/id_rsa.pub","w+") do |f|
155
+ f.write(mock_text)
156
+ end
157
+
158
+ File.exists?(GAS_DIRECTORY + "/#{@nickname}_id_rsa").should be_false
159
+ File.exists?(GAS_DIRECTORY + "/#{@nickname}_id_rsa.pub").should be_false
160
+
161
+ Gas::Ssh.use_current_rsa_files_for_this_user(@nickname)
162
+
163
+ File.exists?(GAS_DIRECTORY + "/#{@nickname}_id_rsa").should be_true
164
+ File.exists?(GAS_DIRECTORY + "/#{@nickname}_id_rsa.pub").should be_true
165
+
166
+ File.read(GAS_DIRECTORY + "/#{@nickname}_id_rsa") do |f|
167
+ f.read.should == mock_text # this part doesn't work... hmmm...
168
+ end
169
+
170
+ File.delete(GAS_DIRECTORY + "/#{@nickname}_id_rsa")
171
+ File.delete(GAS_DIRECTORY + "/#{@nickname}_id_rsa.pub")
172
+ end
173
+
174
+
175
+
176
+ it "should have a UTILITY for deleting rsa files of user" do
177
+ lambda do
178
+ Gas::Ssh.delete_associated_local_keys!(@nickname2)
179
+ end.should change{count_of_files_in(GAS_DIRECTORY)}.by(-2)
180
+ end
181
+ end
182
+
183
+ end
184
+
185
+ end
186
+
187
+ describe "Networking stuff..." do
188
+ before :all do
189
+ # make sure sample key is deleted in the github web client if you incur issues
190
+ @username = "aTestGitAccount"
191
+ @password = "plzdon'thackthetestaccount1"
192
+
193
+ config = "[#{@nickname}]\n name = #{@name}\n email = #{@email}\n\n[user2]\n name = foo\n email = bar"
194
+ @config = Gas::Config.new nil, config
195
+ @user = @config.users[0]
196
+
197
+ @credentials = {:username => @username, :password => @password}
198
+
199
+ # Code to prepare the github environment for testing
200
+ @sample_rsa = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDn74QR9yHb+hcid8iH3+FTaEwnKtwjttseJDbIA2PaivN2uvESrvHlp8Ss/cRox3fFu34QR5DpdOhlfULjTX7yKVuxhaNrAJaqg8rX8hgr9U1Botnyy1DBueEyyA3o1fxRkmwTf6FNnkt1BxWP635tD0lbmUubwaadXjQqPOf3Uw=="
201
+
202
+ Gas.delete(@nickname)
203
+ Gas::Ssh.stub!(:get_username_and_password_and_authenticate).and_return(@credentials)
204
+
205
+ VCR.use_cassette('instantiate_github_speaker', :record => :new_episodes) do
206
+ @github_speaker = Gas::GithubSpeaker.new(@user, @username, @password)
207
+ end
208
+ end
209
+
210
+ after :all do
211
+ Gas.delete(@nickname)
212
+ Gas::Ssh.unstub!(:get_username_and_password_and_authenticate)
213
+ end
214
+
215
+ describe "Should remove and insert keys into github" do
216
+ it 'UTILITY: should insert a new key into github and conversly remove that key' do
217
+ initial_request = ''
218
+ subsequent_request = ''
219
+
220
+ VCR.use_cassette('get_keys-find_none') do
221
+ initial_request = get_keys(@username, @password).length
222
+ end
223
+
224
+ VCR.use_cassette('key_installation_routine-Add_key', :record => :new_episodes) do
225
+ Gas::Ssh.key_installation_routine!(@user, @sample_rsa, @github_speaker)
226
+ end
227
+
228
+ VCR.use_cassette('get_keys-find_one') do
229
+ subsequent_request = get_keys(@username, @password).length
230
+ end
231
+
232
+ (subsequent_request - initial_request).should be(1)
233
+ end
234
+
235
+ it 'should remove the key that it just inserted, so DONT RUN ALONE' do
236
+ initial_request = ''
237
+ subsequent_request = ''
238
+
239
+ VCR.use_cassette('get_keys-find_one') do
240
+ initial_request = get_keys(@username, @password).length
241
+ end
242
+
243
+ VCR.use_cassette('key_installation_routine-Remove_key') do
244
+ lambda do
245
+ @github_speaker.remove_key! @sample_rsa
246
+ end.should change{get_keys(@username, @password).length}.by(-1)
247
+ end
248
+
249
+ VCR.use_cassette('get_keys-find_none') do
250
+ subsequent_request = get_keys(@username, @password).length
251
+ end
252
+
253
+ (subsequent_request - initial_request).should be(-1)
254
+ end
255
+
256
+ end
257
+
258
+
259
+ it "should add ssh keys to github when user is created, and delete them when destroyed" do
260
+ # yes, delete all
261
+ Gas::Prompter.stub!(:user_wants_to_delete_all_ssh_data?).and_return("a") # all keys, local and github
262
+ # create new user and use ssh handling
263
+ Gas::Prompter.stub!(:user_wants_gas_to_handle_rsa_keys?).and_return(true)
264
+ Gas::Prompter.stub!(:user_wants_to_use_key_already_in_ssh?).and_return(false)
265
+ Gas::Prompter.stub!(:user_wants_to_install_key_to_github?).and_return(true)
266
+
267
+ VCR.use_cassette('add-on-crteation-delete-on-deletion', :record => :new_episodes) do
268
+ lambda do
269
+ Gas.add(@nickname,@name,@email, @github_speaker)
270
+ end.should change{get_keys(@username, @password).length}.by(1)
271
+
272
+ lambda do
273
+ Gas::Ssh.stub!(:get_nils).and_return({ :username => @username, :password => @password })
274
+ Gas.delete(@nickname)
275
+ Gas::Ssh.unstub!(:get_nils)
276
+ end.should change{get_keys(@username, @password).length}.by(-1)
277
+ end
278
+
279
+ Gas::Prompter.unstub!(:user_wants_to_delete_all_ssh_data?)
280
+ Gas::Prompter.unstub!(:user_wants_gas_to_handle_rsa_keys?)
281
+ Gas::Prompter.unstub!(:user_wants_to_use_key_already_in_ssh?)
282
+ Gas::Prompter.unstub!(:user_wants_to_install_key_to_github?)
283
+ end
284
+
285
+ it "Gas.Delete should be able to remove the id_rsa from .gas" do
286
+ Gas::Prompter.stub!(:user_wants_to_delete_all_ssh_data?).and_return("a")
287
+ Gas::Prompter.stub!(:user_wants_gas_to_handle_rsa_keys?).and_return(true)
288
+ Gas::Prompter.stub!(:user_wants_to_use_key_already_in_ssh?).and_return(false)
289
+ Gas::Prompter.stub!(:user_wants_to_install_key_to_github?).and_return(true)
290
+
291
+ VCR.use_cassette('add-on-crteation-delete-on-deletion') do
292
+ lambda do
293
+ Gas.add(@nickname,@name,@email, @github_speaker)
294
+ end.should change{count_of_files_in(GAS_DIRECTORY)}.by(2)
295
+
296
+ lambda do
297
+ Gas::Ssh.stub!(:get_nils).and_return({:username => @username, :password => @password })
298
+ Gas.delete(@nickname)
299
+ Gas::Ssh.unstub!(:get_nils)
300
+ end.should change{count_of_files_in(GAS_DIRECTORY)}.by(-2)
301
+ end
302
+
303
+ Gas::Prompter.unstub!(:user_wants_to_delete_all_ssh_data?)
304
+ Gas::Prompter.unstub!(:user_wants_gas_to_handle_rsa_keys?)
305
+ Gas::Prompter.unstub!(:user_wants_to_use_key_already_in_ssh?)
306
+ Gas::Prompter.unstub!(:user_wants_to_install_key_to_github?)
307
+ end
308
+
309
+ it 'Gas.ssh(nickname) should be able to add ssh support to a legacy user or an opt-out' do
310
+ Gas::Prompter.stub!(:user_wants_gas_to_handle_rsa_keys?).and_return(false)
311
+ Gas.add(@nickname,@name,@email)
312
+ Gas::Prompter.unstub!(:user_wants_gas_to_handle_rsa_keys?)
313
+
314
+ Gas::Prompter.stub!(:user_wants_gas_to_handle_rsa_keys?).and_return(true)
315
+ Gas::Ssh.stub!(:upload_public_key_to_github)
316
+
317
+ lambda do
318
+ Gas.ssh(@nickname)
319
+ end.should change{count_of_files_in(GAS_DIRECTORY)}.by(2)
320
+
321
+ Gas::Ssh.delete_associated_local_keys!(@nickname)
322
+
323
+ Gas::Prompter.unstub!(:user_wants_gas_to_handle_rsa_keys?)
324
+ Gas::Ssh.unstub!(:upload_public_key_to_github)
325
+ end
326
+
327
+
328
+
329
+ it "Should be able to tell if it's ever used this key under this ISP provider before and then warn the user"
330
+
331
+ it 'Should have the ability to show if the author is associated with a specific github account NAME, stored in gas.accouts file'
332
+
333
+ it 'Should have the ability to link up with non-github git-daemons'
334
+
335
+ end
336
+
337
+
338
+ end
data/spec/spec_helper.rb CHANGED
@@ -1,10 +1,37 @@
1
1
  # encoding: utf-8
2
2
 
3
+ if ENV['COVERAGE']
4
+ require 'simplecov'
5
+ SimpleCov.start
6
+ end
7
+
8
+ require 'fileutils'
9
+ include FileUtils
10
+
11
+ # Create a virtual directory in the tmp folder so
12
+ # we don't risk damaging files on the running machine
13
+ fake_home = '/tmp/gas-virtual-fs'
14
+ rm_rf fake_home if File.exists? fake_home
15
+ mkdir_p fake_home
16
+ mkdir_p fake_home + '/.ssh'
17
+ ENV['HOME'] = fake_home
18
+
3
19
 
4
20
  RSpec.configure do |config|
5
21
  config.mock_with :rr
6
22
  end
7
23
 
24
+ # Configure VCR, this thing alows you to record HTTP traffic so you never
25
+ # Need to connect to a server. Tests run offline just fine!
26
+ require 'vcr'
27
+
28
+ VCR.configure do |c|
29
+ #c.allow_http_connections_when_no_cassette = true # set to true if you're refreshing the cassets in fixtures
30
+ c.cassette_library_dir = 'fixtures/vcr_cassettes'
31
+ c.hook_into :webmock # or :fakeweb
32
+ end
33
+
34
+
8
35
  # Mocks a cli call using ` with rr.
9
36
  # Takes a block to use as rr return block
10
37
  # @param [Object] mock_object The object to mock
@@ -14,29 +41,24 @@ def mock_cli_call(mock_object, command)
14
41
  mock(mock_object).__double_definition_create__.call(:`, command) { yield }
15
42
  end
16
43
 
17
-
18
- def move_the_testers_personal_ssh_key_out_of_way
19
- if File.exists?(SSH_DIRECTORY + "/id_rsa")
20
- @pattern_to_restore_privl = File.open(SSH_DIRECTORY + "/id_rsa","r").read # this test requires some juggling of files that may already exist.
21
- File.open(GAS_DIRECTORY + "/temp_test","w+").puts @pattern_to_restore_privl
44
+ def clean_out_ssh_directory
45
+ if File.exists?(SSH_DIRECTORY + "/id_rsa")
22
46
  File.delete(SSH_DIRECTORY + "/id_rsa")
23
47
  end
24
-
48
+
25
49
  if File.exists?(SSH_DIRECTORY + "/id_rsa.pub")
26
- @pattern_to_restore_publ = File.open(SSH_DIRECTORY + "/id_rsa.pub","r").read # We don't want to mess things up for the tester, so we will need to save these files and then delete them
27
- File.open(GAS_DIRECTORY + "/temp_test.pub","w+").puts @pattern_to_restore_publ
28
50
  File.delete(SSH_DIRECTORY + "/id_rsa.pub")
29
51
  end
30
-
52
+
31
53
  end
32
54
 
33
55
  def restore_the_testers_ssh_key
34
- if File.exists?(GAS_DIRECTORY + "/temp_test")
56
+ if File.exists?(GAS_DIRECTORY + "/temp_test")
35
57
  @pattern_to_restore_privl = File.open(GAS_DIRECTORY + "/temp_test","r").read # this test requires some juggling of files that may already exist.
36
58
  File.open(SSH_DIRECTORY + "/id_rsa","w+").puts @pattern_to_restore_privl
37
59
  File.delete(GAS_DIRECTORY + "/temp_test")
38
60
  end
39
-
61
+
40
62
  if File.exists?(GAS_DIRECTORY + "/temp_test.pub")
41
63
  @pattern_to_restore_publ = File.open(GAS_DIRECTORY + "/temp_test.pub","r").read # We don't want to mess things up for the tester, so we will need to save these files and then delete them
42
64
  File.open(SSH_DIRECTORY + "/id_rsa.pub","w+").puts @pattern_to_restore_publ
@@ -44,44 +66,98 @@ def restore_the_testers_ssh_key
44
66
  end
45
67
  end
46
68
 
47
-
48
- def clean_out_ssh_directory
49
- if File.exists?(SSH_DIRECTORY + "/id_rsa")
50
- File.delete(SSH_DIRECTORY + "/id_rsa")
69
+ def clean_out_gas_directory(nickname)
70
+ if File.exists?(GAS_DIRECTORY + "/#{nickname}_id_rsa")
71
+ File.delete(GAS_DIRECTORY + "/#{nickname}_id_rsa")
51
72
  end
52
-
53
- if File.exists?(SSH_DIRECTORY + "/id_rsa.pub")
54
- File.delete(SSH_DIRECTORY + "/id_rsa.pub")
73
+
74
+ if File.exists?(SSH_DIRECTORY + "/#{nickname}_id_rsa.pub")
75
+ File.delete(@ssh_dir + "/#{nickname}_id_rsa.pub")
55
76
  end
56
77
  end
57
78
 
58
- def clean_out_gas_directory(nickname)
59
- if File.exists?(GAS_DIRECTORY + "/#{nickname}_id_rsa")
60
- File.delete(GAS_DIRECTORY + "/#{nickname}_id_rsa")
61
- end
62
-
63
- if File.exists?(SSH_DIRECTORY + "/#{nickname}_id_rsa.pub")
64
- File.delete(@ssh_dir + "/#{nickname}_id_rsa.pub")
65
- end
79
+ # this function either mutates an existing file, or creates a new file that won't
80
+ # have been backed up by gas
81
+ def plant_bogus_rsa_keys_in_ssh_directory
82
+ id_rsa = "this rsa file is bogus and not backed up by .gas yet"
83
+ id_rsa_pub = "this pub rsa file is bogus and not backed up by .gas yet"
84
+
85
+ File.open(SSH_DIRECTORY + "/id_rsa","w+") do |f|
86
+ f.puts id_rsa
87
+ end
88
+
89
+ File.open(SSH_DIRECTORY + "/id_rsa.pub","w+") do |f|
90
+ f.puts id_rsa_pub
91
+ end
92
+
93
+ return [id_rsa, id_rsa_pub]
66
94
  end
67
95
 
68
96
 
69
97
  def create_user_no_git(nickname, name, email)
70
- Gas::Ssh.stub!(:user_wants_gas_to_handle_rsa_keys?).and_return(true)
98
+ Gas::Prompter.stub!(:user_wants_gas_to_handle_rsa_keys?).and_return(true)
71
99
  #Gas::Ssh.stub!(:user_wants_to_use_key_already_in_ssh?).and_return(false)
72
- Gas::Ssh.stub!(:user_wants_to_install_key_to_github?).and_return(false)
73
-
100
+ Gas::Prompter.stub!(:user_wants_to_install_key_to_github?).and_return(false)
101
+
74
102
  Gas.add(nickname,name,email)
75
-
76
- Gas::Ssh.unstub!(:user_wants_gas_to_handle_rsa_keys?)
103
+
104
+ Gas::Prompter.unstub!(:user_wants_gas_to_handle_rsa_keys?)
77
105
  #Gas::Ssh.unstub!(:user_wants_to_use_key_already_in_ssh?)
78
- Gas::Ssh.unstub!(:user_wants_to_install_key_to_github?)
106
+ Gas::Prompter.unstub!(:user_wants_to_install_key_to_github?)
79
107
  end
80
108
 
81
109
  # toasts ssh keys for a given nickname and removal from gas.authors
82
110
  def delete_user_no_git(nickname)
83
-
84
111
  Gas.delete(nickname)
85
-
86
112
  end
87
113
 
114
+ # Cycles through github, looking to see if rsa exists as a public key, then deletes it if it does
115
+ def remove_key_from_github_account(username, password, rsa)
116
+ # get all keys
117
+ keys = Gas::Ssh.get_keys(username, password)
118
+ # loop through arrays checking against 'key'
119
+ keys.each do |key|
120
+ if key["key"] == rsa
121
+ return Gas::Ssh.remove_key_by_id!(username, password, key["id"])
122
+ end
123
+ end
124
+
125
+ return false # key not found
126
+ end
127
+
128
+ def delete_all_keys_in_github_account!(github_speaker)
129
+ VCR.use_cassette('delete_all_keys_in_github_account', :record => :new_episodes) do
130
+ github_speaker.keys.each do |key|
131
+ Gas::GithubSpeaker.publicize_methods do
132
+ github_speaker.remove_key_by_id! key['id']
133
+ end
134
+ end
135
+ end
136
+ end
137
+
138
+ def get_keys(username, password)
139
+ server = 'api.github.com'
140
+ path = '/user/keys'
141
+
142
+ http = Net::HTTP.new(server,443)
143
+ req = Net::HTTP::Get.new(path)
144
+ http.use_ssl = true
145
+ req.basic_auth username, password
146
+ response = http.request(req)
147
+
148
+ return JSON.parse(response.body)
149
+ end
150
+
151
+ def count_of_files_in(directory_path)
152
+ Dir.glob(File.join(directory_path, '**', '*')).select { |file| File.file?(file) }.count
153
+ end
154
+
155
+ # This is used for publicizing the methods of a class so you can use TDD for projects, even in RUBY!
156
+ class Class
157
+ def publicize_methods
158
+ saved_private_instance_methods = self.private_instance_methods
159
+ self.class_eval { public(*saved_private_instance_methods) }
160
+ yield
161
+ self.class_eval { private(*saved_private_instance_methods) }
162
+ end
163
+ end