startor 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|