startor 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/bin/startor +173 -0
- data/lib/Array/all_but_last.rb +24 -0
- data/lib/Array/extract_optionsX.rb +21 -0
- data/lib/Array/lastX.rb +10 -0
- data/lib/File/basename_without_extname.rb +17 -0
- data/lib/File/extname.rb +18 -0
- data/lib/File/self.gsubX.rb +54 -0
- data/lib/FileUtils/where.rb +37 -0
- data/lib/FileUtils/which.rb +20 -0
- data/lib/Files.rb +249 -0
- data/lib/Kernel/run.rb +43 -0
- data/lib/Module/alias_methods.rb +16 -0
- data/lib/OSX/HardwarePort.rb +69 -0
- data/lib/OSX/IfConfig.rb +57 -0
- data/lib/Ordinal/Array.rb +8 -0
- data/lib/Ordinal.rb +155 -0
- data/lib/Platform/OS/OSX/SystemProfiler.rb +36 -0
- data/lib/Platform/OS/OSX.rb +100 -0
- data/lib/Platform/OS/linuxQ.rb +15 -0
- data/lib/Platform/OS/nt_basedQ.rb +16 -0
- data/lib/Platform/OS/osxQ.rb +15 -0
- data/lib/Platform/OS/windowsQ.rb +26 -0
- data/lib/Platform/OS.rb +13 -0
- data/lib/String/capture.rb +20 -0
- data/lib/Thoran/String/Capture/capture.rb +26 -0
- data/lib/Thoran/String/Captures/captures.rb +26 -0
- data/lib/Version.rb +403 -0
- metadata +73 -0
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
|
data/lib/Array/lastX.rb
ADDED
@@ -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
|
data/lib/File/extname.rb
ADDED
@@ -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
|