startor 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 998bba49132f5d6805135b181e5ce13cbc00555318f7c3e164c949527dc103df
4
+ data.tar.gz: 58b182ce0395000d88a10ee09bbe251f9be5af668f8ed1f905e5a147d74066ee
5
+ SHA512:
6
+ metadata.gz: 68e883397b9a44f78a1b8ab0717652b3a686767a8ce5473dfb1e0f2fabd33bba7749862516402db8215feb9f7ad00cdb98db4bff5f8b521feb5e1004e1aee387
7
+ data.tar.gz: 7c9ed15bfa22c96dd580bd6420836a0a7b41f5fac1dbaef41ae37835c25745a6642f2950df8394bfdc8a0321ed915d9977c485ff3af5e2cbc8f9a57324ca620d
data/bin/startor ADDED
@@ -0,0 +1,173 @@
1
+ #!/usr/bin/env ruby
2
+ # startor
3
+
4
+ # 20181106
5
+ # 0.6.0
6
+
7
+ # History: Derived from https://kremalicious.com/simple-tor-setup-on-mac-os-x/...
8
+
9
+ # Prerequisites:
10
+ # 1. tor binary is installed.
11
+ # 2. Ruby is installed, which it should be already!
12
+
13
+ # Installation:
14
+ # 1. Press the <cmd> and <space> keys on the keyboard simultaneously.
15
+ # 2. Type: "Terminal.app" and press the <return> key.
16
+ # 3. Type: "gem install startor"
17
+
18
+ # How to use:
19
+ # 1. Press the <cmd> and <space> keys on the keyboard simultaneously.
20
+ # 2. Type: "Terminal.app" and press the <return> key.
21
+ # 3. Type: "startor setup" and press the <return> key.
22
+ # 4. Type: "startor" and press the <return> key.
23
+ # 5. If prompted, enter the password you use to login to your computer.
24
+ # 6. When wanting stop tor, go to the same window as the commands immediately above were entered and press the <ctrl> and <c> keys on the keyboard simultaneously.
25
+ # 7. If prompted, enter the password you use to login to your computer.
26
+
27
+ # Notes:
28
+ # 1. The hardware ports can be any of: 'Thunderbolt Ethernet', 'Thunderbolt Bridge', 'Wi-Fi', 'Ethernet', 'Bluetooth PAN', or 'Display Ethernet'.
29
+ # 2. See `networksetup -listallnetworkservices` for the complete list of hardware ports on your machine.
30
+
31
+ # Todo: (one or more of the following, in no particular order)
32
+ # 1. Turn this into a gem. Done as of 0.6.0.
33
+ # 2. Turn this into a brew formula.
34
+ # 3. Remove some of the comments here and put those into a README or INSTALL or other files as appropriate.
35
+ # 4. Create a(n) .app out of this by using some simple wrapper code.
36
+ # 5. Make it cross-platform: OSX, Linux, and Windows, at least.
37
+ # 6. Clean up the required libraries so that they are either gemified and/or reduced in number.
38
+
39
+ # Changes:
40
+ # Gemification and further tidying...
41
+ # 1. + startor.gemspec
42
+ # 2. Added to the section of comments entitled "Installation", which includes making use of the startor gem.
43
+
44
+ require 'FileUtils/which'
45
+ require 'Kernel/run'
46
+ require 'OSX/HardwarePort'
47
+ require 'OSX/IfConfig'
48
+
49
+ def install_homebrew
50
+ if FileUtils.which('brew')
51
+ puts 'Homebrew is already installed!'
52
+ else
53
+ run('/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"', show: true)
54
+ end
55
+ end
56
+
57
+ def install_tor
58
+ if FileUtils.which('tor')
59
+ puts 'tor is already installed!'
60
+ else
61
+ run('brew install tor', show: true)
62
+ end
63
+ end
64
+
65
+ def setup
66
+ install_homebrew
67
+ install_tor
68
+ end
69
+
70
+ def tor_installed?
71
+ FileUtils.which('tor')
72
+ end
73
+
74
+ def check_for_tor_program
75
+ unless tor_installed?
76
+ puts "tor was not found. You must install tor first."
77
+ puts "The easist way to install it is by running `startor setup`."
78
+ exit
79
+ end
80
+ end
81
+
82
+ def enter_admin_password
83
+ system('sudo -v')
84
+ end
85
+
86
+ def active_network_interfaces
87
+ OSX::IfConfig.new.active_interfaces
88
+ end
89
+
90
+ def active_network_ports
91
+ active_network_interfaces.collect do |active_network_interface|
92
+ if hardware_port = OSX::HardwarePort.find_by_device(active_network_interface)
93
+ hardware_port.name
94
+ end
95
+ end.compact
96
+ end
97
+
98
+ def setup_interfaces
99
+ active_network_ports.each do |active_network_port|
100
+ run("sudo networksetup -setsocksfirewallproxy '#{active_network_port}' 127.0.0.1 9050 off", show: true)
101
+ end
102
+ end
103
+
104
+ def puts_with_colour(string, colour)
105
+ system("echo \"$(tput setaf #{colour})\"")
106
+ puts string
107
+ system('echo "$(tput sgr0)"') # color reset
108
+ end
109
+
110
+ def puts_green(string)
111
+ puts_with_colour(string, 64) # Set console text colour to green(ish).
112
+ end
113
+
114
+ def puts_orange(string)
115
+ puts_with_colour(string, 136) # Set console text colour to orange.
116
+ end
117
+
118
+ def enable_proxy
119
+ active_network_ports.each do |active_network_port|
120
+ run("sudo networksetup -setsocksfirewallproxystate '#{active_network_port}' on", show: true)
121
+ puts_green('SOCKS proxy 127.0.0.1:9050 enabled.')
122
+ puts_orange('Starting Tor...')
123
+ end
124
+ end
125
+
126
+ def system_tor
127
+ system('tor')
128
+ end
129
+
130
+ def exec_tor
131
+ exec('tor')
132
+ end
133
+
134
+ def disable_proxy
135
+ active_network_ports.each do |active_network_port|
136
+ run("sudo networksetup -setsocksfirewallproxystate '#{active_network_port}' off", show: true)
137
+ puts_green('SOCKS proxy disabled.')
138
+ end
139
+ end
140
+
141
+ def common_up
142
+ check_for_tor_program
143
+ enter_admin_password
144
+ setup_interfaces
145
+ enable_proxy
146
+ end
147
+
148
+ def explicit_up
149
+ common_up
150
+ exec_tor
151
+ end
152
+
153
+ def implicit_up
154
+ common_up
155
+ system_tor
156
+ end
157
+
158
+ def down
159
+ disable_proxy
160
+ end
161
+
162
+ def main
163
+ case ARGV[0]
164
+ when 'up'; explicit_up
165
+ when 'down'; down
166
+ when 'setup'; setup
167
+ else; implicit_up
168
+ end
169
+ rescue SystemExit, Interrupt
170
+ down if tor_installed?
171
+ end
172
+
173
+ main
@@ -0,0 +1,24 @@
1
+ # Array#all_but_last
2
+
3
+ # 20080831
4
+ # 0.1.0
5
+
6
+ # Description: This returns a copy of the receiving array with the last element removed.
7
+
8
+ # Changes since 0.0:
9
+ # 1. I've added require 'Array/lastX', since I think it is reasonable that each file should load its own dependencies.
10
+
11
+ # Todo:
12
+ # 1. Conditionally do the require depending on whether the method already exists on Array and/or on whether rubylib has been defined elsewhere, since the require will fail in either case; and if rubylib is available, but this method isn't.
13
+
14
+ require 'Array/lastX'
15
+
16
+ class Array
17
+
18
+ def all_but_last
19
+ d = self.dup
20
+ d.last!
21
+ d
22
+ end
23
+
24
+ end
@@ -0,0 +1,21 @@
1
+ # Array/extract_optionsX.rb
2
+ # Array#extract_options!
3
+
4
+ # 20140402
5
+ # 0.1.1
6
+
7
+ # History: Stolen wholesale from ActiveSupport.
8
+
9
+ # Changes:
10
+ # 1. + #extract_options (no exclamation). Whereas I had previously had #extract_options mean the same as what I now call #peek_options, I decided that Array has some precedents for method names which do not have a bang method, but which do modify the receiver in place; #shift, #unshift, #push, and #pop come to mind...
11
+ # 0/1
12
+ # 2. Some minor tidying.
13
+
14
+ class Array
15
+
16
+ def extract_options!
17
+ last.is_a?(::Hash) ? pop : {}
18
+ end
19
+ alias_method :extract_options, :extract_options!
20
+
21
+ end
@@ -0,0 +1,10 @@
1
+ # Array#last!
2
+ # 20060630
3
+ #
4
+ # Description: Sometimes it makes more sense to treat arrays this way.
5
+ #
6
+ # Discussion: This and first! were taken from Skink2Quick from a few months ago.
7
+
8
+ class Array
9
+ alias_method :last!, :pop
10
+ end
@@ -0,0 +1,17 @@
1
+ # File#basename_without_extname
2
+ # File/basename_without_extname
3
+
4
+ # 2010.06.05
5
+ # 0.0.0
6
+
7
+ # Description: This returns the basename without the extension for a given File instance without the need to specify what the extension is because it makes use of File.extension which works that out.
8
+
9
+ require 'File/extname'
10
+
11
+ class File
12
+
13
+ def basename_without_extname
14
+ File.basename(path, extname)
15
+ end
16
+
17
+ end
@@ -0,0 +1,18 @@
1
+ # File/extname.rb
2
+ # File#extname
3
+
4
+ # 20140412
5
+ # 0.2.0
6
+
7
+ # Description: This is the instance method version of the class method on File by the same name.
8
+
9
+ # Changes since 0.1:
10
+ # 1. Using the built-in class-method now.
11
+
12
+ class File
13
+
14
+ def extname
15
+ File.extname(path)
16
+ end
17
+
18
+ end
@@ -0,0 +1,54 @@
1
+ # File/self.gsubX
2
+ # File.gsub!
3
+
4
+ # 20111122
5
+ # 0.0.1
6
+
7
+ # Description: This takes a file and replaces any text it finds according to a regular expression with a supplied string.
8
+
9
+ # History:
10
+ # 1. Separated class and instance methods to their own files at File#gsubX 0.3.6/0.4.
11
+
12
+ # Changes:
13
+ # 1. /File.gsubX/File\/self.gsubX/.
14
+
15
+ class File
16
+
17
+ def self.gsub!(filename, replacement_pattern, replacement_text, selection_pattern = nil)
18
+ replacement_pattern = (
19
+ case replacement_pattern
20
+ when String; Regexp.new(Regexp.escape(replacement_pattern))
21
+ when Regexp; replacement_pattern
22
+ else; raise
23
+ end
24
+ )
25
+ selection_pattern = replacement_pattern unless selection_pattern
26
+ selection_pattern = (
27
+ case selection_pattern
28
+ when String; Regexp.new(Regexp.escape(selection_pattern))
29
+ when Regexp; selection_pattern
30
+ else; raise
31
+ end
32
+ )
33
+ file_handle = self.open(filename, 'r')
34
+ tmp_file_handle = self.new(filename + '.tmp', 'w')
35
+ modified = false
36
+ file_handle.each do |line|
37
+ if line =~ Regexp.new(selection_pattern)
38
+ tmp_file_handle.print line.gsub(Regexp.new(replacement_pattern), replacement_text)
39
+ modified = true
40
+ else
41
+ tmp_file_handle.print line
42
+ end
43
+ end
44
+ file_handle.close
45
+ tmp_file_handle.close
46
+ if modified
47
+ self.delete(filename)
48
+ self.rename(filename + '.tmp', filename)
49
+ else
50
+ self.delete(filename + '.tmp')
51
+ end
52
+ end
53
+
54
+ end
@@ -0,0 +1,37 @@
1
+ # FileUtils/where.rb
2
+ # FileUtils#where
3
+
4
+ # 20140912
5
+ # 0.0.2
6
+
7
+ # History: Derived from where 0.2.3---the original command version I wrote in Ruby.
8
+
9
+ # Changes:
10
+ # 1. Removed trailing spaces.
11
+ # 2. - require 'File/extension', since it doesn't seem to be being used.
12
+ # 3. /require 'File/basename_without_extension'/require 'File/basename_without_extname'/, and uses thereof.
13
+ # 4. /require 'Platform/windowsQ'/require 'Platform/OS', and use thereof.
14
+
15
+ require 'File/basename_without_extname'
16
+ require 'Platform/OS'
17
+
18
+ module FileUtils
19
+
20
+ def where(executable_sought)
21
+ paths = ENV['PATH'].split(/:/)
22
+ sought_paths = []
23
+ paths.uniq.each do |path|
24
+ Dir["#{path}/*"].each do |executable|
25
+ if Platform::OS.windows?
26
+ sought_paths << executable if File.basename_without_extname(executable) == File.basename_without_extname(executable_sought)
27
+ else
28
+ sought_paths << executable if File.basename(executable) == executable_sought
29
+ end
30
+ end
31
+ end
32
+ sought_paths.empty? ? nil : sought_paths
33
+ end
34
+
35
+ module_function :where
36
+
37
+ end
@@ -0,0 +1,20 @@
1
+ # FileUtils#which
2
+
3
+ # 20100320
4
+ # 0.0.0
5
+
6
+ require 'FileUtils/where'
7
+
8
+ module FileUtils
9
+
10
+ def which(executable_sought)
11
+ if where_results = FileUtils.where(executable_sought)
12
+ where_results[0]
13
+ else
14
+ nil
15
+ end
16
+ end
17
+
18
+ module_function :which
19
+
20
+ end
data/lib/Files.rb ADDED
@@ -0,0 +1,249 @@
1
+ # Files.rb
2
+ # Files
3
+
4
+ # 20140508
5
+ # 0.8.3
6
+
7
+ # Changes since 0.7: (Switched from using Files to OpenStructs for @files instance variable because Ruby can't open more than some hundreds of files and nil was being returned after that limit had been reached.)
8
+ # 1. - Files.files_for().
9
+ # 2. + Files.with_attributes().
10
+ # 3. /return_files_object/return_ostruct_object/.
11
+ # 4. ~ Files.in_path___with_pattern___(), so as to make reference to Files.with_attributes().
12
+ # 5. ~ Files#absolute_paths(), to not rely upon an extension to File.
13
+ # 6. ~ Files#dirnames(), to not rely upon an extension to File.
14
+ # 7. ~ Files#absolute_dirnames(), to not rely upon an extension to File.
15
+ # 8 - require_relative './File'.
16
+ # 0/1
17
+ # 9. Even though MacRuby is supposed to be an MRI 1.9.2 analogue, it doesn't know Kernel#require_relative, so I've added a 'backport' for it in Ruby.
18
+ # 1/2
19
+ # 10. I don't need require_relative if I am altering the path and wrapping this up as a gem does that automatically for me.
20
+ # 11. However, perhaps I can't assume that someone will be using RubyGems, so I've got some $LOAD_PATH manipulation stuff there instead. It also means that I don't have to change any of the test code, else I'd have to it in there. Perhaps it doesn't matter terribly which of these ways I do this?
21
+ # 12. - ruby '1.9.3' from the Gemfile, since I had merely copied and pasted that from another project.
22
+ # 2/3
23
+ # 13. /MiniTest::Unit::TestCase/MiniTest::Test/.
24
+ # 14. + gem 'minitest' to all children test files and to the Gemfile so as to silence the warnings.
25
+ # 15. Moved test/all.rb to test/Files.rb.
26
+ # 16. Moved all children tests to test/Files/ as was forshadowed by the first line of the test files prior to 8.3.
27
+ # 17. ~ TC_Files_instance_methods_performing_operations#test_gsub! and #test_move, so that they were actually testing the instance methods and not the class methods as they were, thereby helping improve test coverage to 99.07%.
28
+ # 18. + TC_Files_instance_methods#test_initialize_with_no_filenames_and_no_path_or_pattern, so as to achieve 100% test coverage finally.
29
+ # 19. /TC_Files_instance_methods#test_initialize_with_no_path_or_pattern/TC_Files_instance_methods#test_initialize_with_a_filename/, so as to make the name more accurate.
30
+ # 20. /TC_Files_instance_methods#test_initialize_and_a_path/TC_Files_instance_methods#test_initialize_with_a_path/, so as to make the name more accurate.
31
+ # 21. /TC_Files_instance_methods#test_initialize_and_a_pattern/TC_Files_instance_methods#test_initialize_with_a_pattern/, so as to make the name more accurate.
32
+ # 22. /TC_Files_instance_methods#test_initialize_and_a_path_and_pattern/TC_Files_instance_methods#test_initialize_with_a_path_and_pattern/, so as to make the name more accurate.
33
+ # 23. Updated lib/Array/extract_optionsX.rb to the latest version.
34
+ # 24. Added lib/Array/all_but_last.rb, since it was a missing dependency.
35
+ # 25. Added lib/Array/lastX.rb, since it too was a missing dependency.
36
+ # 26. ~ Files#sort_method_macro, #sorter_macro, and #reverse_sort_method_macro, so as to make use of instance_eval rather than eval.
37
+ # 27. Added Kernel/require_relative.rb back, since I should be able to run the specs with MacRuby as well.
38
+ # 28. Updated the gemspec with latest version number.
39
+
40
+ # Todo:
41
+ # 1. Ensure that the interface is sufficiently usable that it will be reading for a 1.0 release after some more tinkering through the remainder of 0.8 and 0.9.
42
+
43
+ $LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__))) unless
44
+ $LOAD_PATH.include?(File.dirname(__FILE__)) || $LOAD_PATH.include?(File.expand_path(File.dirname(__FILE__)))
45
+
46
+ require 'Array/extract_optionsX'
47
+ require 'File/self.gsubX'
48
+ require 'fileutils'
49
+ require 'Module/alias_methods'
50
+ require 'ostruct'
51
+
52
+ class Files
53
+
54
+ class << self
55
+
56
+ def find(options = {})
57
+ path, pattern, return_ostruct_object = options[:path], options[:pattern], options[:return_ostruct_object]
58
+ case
59
+ when path && pattern
60
+ in_path___with_pattern___(path, pattern, return_ostruct_object)
61
+ when path && !pattern
62
+ in_path___(path, return_ostruct_object)
63
+ when !path && pattern
64
+ with_pattern___(pattern, return_ostruct_object)
65
+ when !path && !pattern
66
+ here(return_ostruct_object)
67
+ end
68
+ end
69
+ alias_methods :all, :find
70
+
71
+ def in_path___with_pattern___(path, pattern, return_ostruct_object = true)
72
+ files = with_attributes(Dir["#{path}/#{pattern}"])
73
+ if return_ostruct_object
74
+ files_object = Files.new
75
+ files_object.files = files
76
+ files_object
77
+ else
78
+ files
79
+ end
80
+ end
81
+ alias_methods :in_path_matching, :in_path___matching___,
82
+ :in_path_with_pattern, :in_path___with_pattern___
83
+
84
+ def in_path___(path, return_ostruct_object = true)
85
+ in_path___matching___(path, '*', return_ostruct_object)
86
+ end
87
+ alias_methods :in, :in_path, :in_path___
88
+
89
+ def with_pattern___(pattern, return_ostruct_object = true)
90
+ in_path___matching___('./', pattern, return_ostruct_object)
91
+ end
92
+ alias_methods :with_pattern, :with_pattern___
93
+
94
+ def here(return_ostruct_object = true)
95
+ in_path___matching___('./', '*', return_ostruct_object)
96
+ end
97
+
98
+ def with_attributes(paths)
99
+ paths.collect do |path|
100
+ begin
101
+ f = {}
102
+ f[:path] = path
103
+ f[:size] = File.stat(path).size
104
+ f[:ftype] = File.stat(path).ftype
105
+ f[:mode] = File.stat(path).mode
106
+ f[:gid] = File.stat(path).gid
107
+ f[:uid] = File.stat(path).uid
108
+ f[:ctime] = File.stat(path).ctime
109
+ f[:mtime] = File.stat(path).mtime
110
+ f[:atime] = File.stat(path).atime
111
+ OpenStruct.new(f)
112
+ rescue
113
+ end
114
+ end
115
+ end
116
+
117
+ def gsub!(filenames, replacement_pattern, replacement_text, selection_pattern = nil)
118
+ filenames.each do |filename|
119
+ File.gsub!(filename, replacement_pattern, replacement_text, selection_pattern)
120
+ end
121
+ end
122
+
123
+ def move(filenames, replacement_pattern, replacement_text)
124
+ filenames.each do |filename|
125
+ new_filename = filename.gsub(/#{replacement_pattern}/, replacement_text)
126
+ FileUtils.mv(filename, new_filename)
127
+ end
128
+ end
129
+ alias_methods :ren, :rename, :mv, :move
130
+
131
+ end # class << self
132
+
133
+ include Enumerable
134
+
135
+ attr_writer :files
136
+ attr_reader :path
137
+ attr_reader :pattern
138
+
139
+ def initialize(*args)
140
+ options = args.extract_options!
141
+ @args, @path, @pattern = args, options[:path], options[:pattern]
142
+ load_metaprogrammed_methods
143
+ end
144
+
145
+ def files
146
+ @files ||= (
147
+ if !@args.empty?
148
+ Files.with_attributes(@args.flatten)
149
+ elsif path && pattern
150
+ Files.find(path: path, pattern: pattern, return_ostruct_object: false)
151
+ elsif path
152
+ Files.find(path: path, return_ostruct_object: false)
153
+ elsif pattern
154
+ Files.find(pattern: pattern, return_ostruct_object: false)
155
+ else
156
+ []
157
+ end
158
+ )
159
+ end
160
+
161
+ def each
162
+ files.each{|f| yield f}
163
+ end
164
+
165
+ def paths
166
+ files.collect{|f| f.path}
167
+ end
168
+
169
+ def absolute_paths
170
+ files.collect{|f| File.expand_path(f.path)}
171
+ end
172
+
173
+ def dirnames
174
+ files.collect{|f| File.dirname(f.path)}
175
+ end
176
+
177
+ def absolute_dirnames
178
+ files.collect{|f| File.dirname(File.absolute_path(f.path))}
179
+ end
180
+
181
+ def gsub!(replacement_pattern, replacement_text)
182
+ Files.gsub!(paths, replacement_pattern, replacement_text)
183
+ end
184
+
185
+ def move(replacement_pattern, replacement_text)
186
+ Files.move(paths, replacement_pattern, replacement_text)
187
+ end
188
+ alias_methods :ren, :rename, :mv, :move
189
+
190
+ def path=(new_path)
191
+ @path = new_path
192
+ set_files
193
+ end
194
+
195
+ def pattern=(new_pattern)
196
+ @pattern = new_pattern
197
+ set_files
198
+ end
199
+
200
+ private
201
+
202
+ def set_files
203
+ @files = nil
204
+ files
205
+ end
206
+
207
+ def load_metaprogrammed_methods
208
+ sort_method_macro
209
+ reverse_sort_method_macro
210
+ sorter_macro
211
+ end
212
+
213
+ def sort_method_macro
214
+ %w(atime ctime mtime size ftype mode gid uid filename).each do |method|
215
+ instance_eval("
216
+ def sort_by_#{method}
217
+ files.sort! do |a,b|
218
+ by_#{method}(a,b)
219
+ end
220
+ self
221
+ end
222
+ ")
223
+ end
224
+ end
225
+
226
+ def sorter_macro
227
+ %w(atime ctime mtime size ftype mode gid uid filename).each do |method|
228
+ instance_eval("
229
+ def by_#{method}(a,b)
230
+ a.#{method} <=> b.#{method}
231
+ end
232
+ ")
233
+ end
234
+ end
235
+
236
+ def reverse_sort_method_macro
237
+ %w(atime ctime mtime size ftype mode gid uid filename).each do |method|
238
+ instance_eval("
239
+ def reverse_sort_by_#{method}
240
+ files.sort! do |a,b|
241
+ by_#{method}(a,b)
242
+ end.reverse!
243
+ self
244
+ end
245
+ ")
246
+ end
247
+ end
248
+
249
+ end
data/lib/Kernel/run.rb ADDED
@@ -0,0 +1,43 @@
1
+ # Kernel/run.rb
2
+ # Kernel#run
3
+
4
+ # 20170613
5
+ # 0.1.5
6
+
7
+ # Changes:
8
+ # 1. Make use of a number of options, substituting ENV['DRY_RUN'] for options[:dry_run], and adding :show and :dont_raise.
9
+ # 0/1
10
+ # 2. When showing the output make it clear that it is a dry run.
11
+ # 1/2
12
+ # 3. If the :dry_run option is specified, then it makes no sense to test $? for success, so group all that code in the unless.
13
+ # 2/3
14
+ # 4. The logic was reversed for whether to raise or not.
15
+ # 3/4
16
+ # 5. Really fixed the raise logic finally, I think.
17
+ # 4/5
18
+ # 6. Yet another attempt at fixing the raise logic.
19
+
20
+ # Todo:
21
+ # 1. Even though this is a small method it might be good idea to add some automated tests.
22
+
23
+ require 'Array/extract_optionsX'
24
+
25
+ module Kernel
26
+
27
+ def run(*args)
28
+ options = args.extract_options!
29
+ command = args
30
+ if options[:show] && !options[:dry_run]
31
+ puts command.join(' ')
32
+ elsif options[:show] && options[:dry_run]
33
+ puts "DRY RUN *** #{command.join(' ')} *** DRY RUN"
34
+ end
35
+ unless options[:dry_run]
36
+ system(*command)
37
+ if !$?.success? && !options[:dont_raise]
38
+ raise "#{command.inspect} failed to exit cleanly."
39
+ end
40
+ end
41
+ end
42
+
43
+ end
@@ -0,0 +1,16 @@
1
+ # Module#alias_methods
2
+
3
+ # 20080831
4
+ # 0.0.0
5
+
6
+ # Description: I have a penchance for having multiple method names and having line after line of alias_method calls is kinda ugly.
7
+
8
+ require 'Array/all_but_last'
9
+
10
+ class Module
11
+
12
+ def alias_methods(*args)
13
+ args.all_but_last.each{|e| alias_method e.to_sym, args.last.to_sym}
14
+ end
15
+
16
+ end