patheditor 1.0.2 → 1.0.3
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.
- data/Rakefile +2 -2
- data/bin/path_editor +23 -62
- data/lib/windows_path.rb +70 -0
- data/test/test_windows_path.rb +128 -0
- metadata +3 -2
data/Rakefile
CHANGED
@@ -5,7 +5,7 @@ require 'rake/gempackagetask'
|
|
5
5
|
spec = Gem::Specification.new do |s|
|
6
6
|
s.name = "patheditor"
|
7
7
|
s.summary = "A simple program to manage the Windows PATH environment variable."
|
8
|
-
s.version = "1.0.
|
8
|
+
s.version = "1.0.3"
|
9
9
|
s.author = "Justin Bailey"
|
10
10
|
s.email = "jgbailey@nospam@gmail.com"
|
11
11
|
|
@@ -14,7 +14,7 @@ This gem provides an application, path_editor, which makes it easy to add, remov
|
|
14
14
|
EOS
|
15
15
|
|
16
16
|
s.platform = Gem::Platform::RUBY
|
17
|
-
s.files = FileList["lib/**/*", "*.txt", "Rakefile"].to_a
|
17
|
+
s.files = FileList["lib/**/*", "test/**/*", "*.txt", "Rakefile"].to_a
|
18
18
|
|
19
19
|
s.bindir = "bin"
|
20
20
|
s.executables = ["path_editor"]
|
data/bin/path_editor
CHANGED
@@ -39,9 +39,10 @@ Adds the given path to the PATH environment variable. If the path already exists
|
|
39
39
|
@remove = opt_args.first
|
40
40
|
},
|
41
41
|
:opt_description => <<-EOS
|
42
|
-
Removes the given path from the environment variable.
|
43
|
-
|
44
|
-
|
42
|
+
Removes the given path from the environment variable. Special characters such as "?" and "*" will be treated
|
43
|
+
as wildcards, just like at the command line. Be sure to enclose the expression in quotes, or the command prompt will
|
44
|
+
attempt to expand them for you. Note also that the command prompt seems to switch "\" characters to "/", so matches
|
45
|
+
with those characters will appear odd.
|
45
46
|
EOS
|
46
47
|
|
47
48
|
option :names => %w(--case-sensitive), :arity => 0,
|
@@ -67,33 +68,20 @@ Forces changes to occur with confirmation. True by default unless paths are bein
|
|
67
68
|
|
68
69
|
if @clean || @add || @remove
|
69
70
|
if @clean
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
if ! pathname.exist?
|
77
|
-
nonexistent << p
|
78
|
-
elsif found.include?(pathname)
|
79
|
-
duplicates << idx
|
80
|
-
else
|
81
|
-
found << pathname
|
71
|
+
@currPath.clean do |path, reason|
|
72
|
+
case reason
|
73
|
+
when :dup
|
74
|
+
@hl.say "Removing #{path} (duplicate)"
|
75
|
+
when :notfound
|
76
|
+
@hl.say "Removing #{path} (doesn't exist)"
|
82
77
|
end
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
unless duplicates.empty?
|
87
|
-
remove_paths(duplicates) { |p| @hl.say "Removing #{p} (duplicate)" }
|
88
|
-
end
|
89
|
-
|
90
|
-
unless nonexistent.empty?
|
91
|
-
remove_paths(nonexistent){ |p| @hl.say "Removing #{p} (doesn't exist)" }
|
78
|
+
|
79
|
+
path_removed
|
92
80
|
end
|
93
81
|
end
|
94
82
|
|
95
83
|
if @add
|
96
|
-
unless @currPath.paths.include?
|
84
|
+
unless @currPath.paths.include?(@add)
|
97
85
|
@currPath.paths.add(@add)
|
98
86
|
@path_updated = true
|
99
87
|
@hl.say "Added #{@add} to path."
|
@@ -103,20 +91,9 @@ Forces changes to occur with confirmation. True by default unless paths are bein
|
|
103
91
|
end
|
104
92
|
|
105
93
|
if @remove
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
# to make sure any and all characters following are matched
|
110
|
-
@remove = @remove.gsub('\\', '\\\\\\\\').gsub("*", ".*").gsub("?", ".")
|
111
|
-
exp = @case_sensitive ? Regexp.new("^#{@remove}$") : Regexp.new("^#{@remove}$", Regexp::IGNORECASE)
|
112
|
-
paths_to_remove = []
|
113
|
-
|
114
|
-
@currPath.paths.each { |p| paths_to_remove << p if exp.match(p) }
|
115
|
-
remove_paths(paths_to_remove) unless paths_to_remove.empty?
|
116
|
-
elsif @currPath.paths.include?(@remove)
|
117
|
-
@hl.say "Removing path #{@remove}"
|
118
|
-
@currPath.paths.remove(@remove)
|
119
|
-
@path_updated = true
|
94
|
+
@currPath.remove(@remove) do |p|
|
95
|
+
@hl.say "Removing path #{p}"
|
96
|
+
path_removed
|
120
97
|
end
|
121
98
|
end
|
122
99
|
|
@@ -143,30 +120,14 @@ Forces changes to occur with confirmation. True by default unless paths are bein
|
|
143
120
|
(@automatic_confirm && ! @confirm_disabled) || false
|
144
121
|
end
|
145
122
|
|
146
|
-
#
|
147
|
-
|
148
|
-
|
149
|
-
@paths_removed
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
idx = p - adjust # adjust index based on paths removed so far.
|
154
|
-
yield @currPath.paths[idx] if block_given?
|
155
|
-
@currPath.paths.delete_at(idx)
|
156
|
-
else
|
157
|
-
yield p if block_given?
|
158
|
-
@currPath.paths.delete p
|
159
|
-
end
|
160
|
-
|
161
|
-
# If more than one path matches and the user did not specify "--no-confirmation", make
|
162
|
-
# sure to enable it here.
|
163
|
-
@path_updated = true
|
164
|
-
@automatic_confirm = true if @paths_removed > 0
|
165
|
-
@paths_removed += 1
|
166
|
-
adjust += 1
|
167
|
-
end
|
123
|
+
# Records that a path was removed
|
124
|
+
def path_removed
|
125
|
+
@path_updated = true
|
126
|
+
# first time through, @paths_removed is false. Automatic confimration
|
127
|
+
# should happen with more than one directory, therefore this will succeed.
|
128
|
+
@automatic_confirm = true if @paths_removed
|
129
|
+
@paths_removed = true
|
168
130
|
end
|
169
|
-
|
170
131
|
end
|
171
132
|
|
172
133
|
App.run unless $0 == __FILE__
|
data/lib/windows_path.rb
CHANGED
@@ -74,5 +74,75 @@ class WindowsPath
|
|
74
74
|
def update
|
75
75
|
@system["Item", "Path"] = @paths.join(";")
|
76
76
|
end
|
77
|
+
|
78
|
+
# Cleans the current path of any non-existent or duplicate directories.
|
79
|
+
# If a block is given, yields each directory removed along with a
|
80
|
+
# the symbol :dup or :notfound.
|
81
|
+
def clean # :yields: path, reason
|
82
|
+
nonexistent = []
|
83
|
+
found = WindowsPathArray.new
|
84
|
+
duplicates = []
|
85
|
+
idx = 0
|
86
|
+
@paths.each do |p|
|
87
|
+
pathname = Pathname.new(p).cleanpath
|
88
|
+
if ! pathname.exist?
|
89
|
+
nonexistent << p
|
90
|
+
elsif found.include?(pathname)
|
91
|
+
duplicates << idx
|
92
|
+
else
|
93
|
+
found << pathname
|
94
|
+
end
|
95
|
+
idx += 1
|
96
|
+
end
|
97
|
+
|
98
|
+
unless duplicates.empty?
|
99
|
+
remove_paths(duplicates) { |p| yield p, :dup if block_given? }
|
100
|
+
end
|
101
|
+
|
102
|
+
unless nonexistent.empty?
|
103
|
+
remove_paths(nonexistent) { |p| yield p, :notfound if block_given? }
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
# Removes paths matching the path given. If path is regular
|
108
|
+
# expression, it is matched directly. Any other
|
109
|
+
# pattern is treated as a potential shell "glob"
|
110
|
+
# match, which means "*" and "?" are treated
|
111
|
+
# specially.
|
112
|
+
#
|
113
|
+
# In all cases, the path(s) removed are yielded.
|
114
|
+
def remove(pattern) # :yields: path
|
115
|
+
paths_to_remove = []
|
116
|
+
@paths.each do |p|
|
117
|
+
if pattern.is_a?(Regexp)
|
118
|
+
paths_to_remove << p if pattern.match(p)
|
119
|
+
else
|
120
|
+
paths_to_remove << p if File.fnmatch(pattern, p, File::FNM_CASEFOLD | File::FNM_NOESCAPE)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
paths_to_remove.each do |p|
|
125
|
+
yield p if block_given?
|
126
|
+
@paths.delete(p)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
private
|
131
|
+
|
132
|
+
def remove_paths(paths_to_remove)
|
133
|
+
adjust = 0
|
134
|
+
paths_to_remove.each do |p|
|
135
|
+
if p.is_a?(Fixnum)
|
136
|
+
idx = p - adjust # adjust index based on paths removed so far.
|
137
|
+
yield @paths[idx] if block_given?
|
138
|
+
@paths.delete_at(idx)
|
139
|
+
else
|
140
|
+
yield p if block_given?
|
141
|
+
@paths.delete p
|
142
|
+
end
|
143
|
+
|
144
|
+
adjust += 1
|
145
|
+
end
|
146
|
+
end
|
77
147
|
|
78
148
|
end
|
@@ -0,0 +1,128 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
$:.unshift File.dirname(__FILE__) + "/../lib" unless $:.include?(File.dirname(__FILE__) + "../lib")
|
3
|
+
require 'windows_path'
|
4
|
+
|
5
|
+
class WindowsPathTests < Test::Unit::TestCase
|
6
|
+
|
7
|
+
def setup
|
8
|
+
@path = WindowsPath.new
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_clean
|
12
|
+
# add some non-existent directories
|
13
|
+
fake = add_fake
|
14
|
+
|
15
|
+
assert_dir_found fake, "Fake directory not added to current path."
|
16
|
+
@path.clean
|
17
|
+
assert_dir_not_found fake, "Fake directory found in current path after cleaning!"
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_clean_dups
|
21
|
+
fake = add_fake_dup
|
22
|
+
|
23
|
+
assert_dir_found fake, "Duplicate directory not found in path."
|
24
|
+
assert_dup_found fake, "Did not find the right number of duplicates directories in the path."
|
25
|
+
|
26
|
+
@path.clean
|
27
|
+
assert_dir_not_found fake, "Duplicate directory found in current path after cleaning!"
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_clean_and_notfound
|
31
|
+
fake_dup = add_fake_dup
|
32
|
+
fake_not_found = add_fake
|
33
|
+
|
34
|
+
assert_dup_found fake_dup, "Did not find the right number of duplicates directories in the path."
|
35
|
+
assert_dir_found fake_not_found, "Nonexistent directory not found in path."
|
36
|
+
|
37
|
+
@path.clean
|
38
|
+
assert_dir_not_found fake_dup, "Duplicate directory found in current path after cleaning!"
|
39
|
+
assert_dir_not_found fake_not_found, "Nonexistent directory found in current path after cleaning!"
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_remove_dir
|
43
|
+
fake_dir = add_fake
|
44
|
+
assert_dir_found fake_dir, "Fake directory not found in path."
|
45
|
+
@path.remove fake_dir
|
46
|
+
assert_dir_not_found fake_dir, "Fake directory found in path after removal."
|
47
|
+
end
|
48
|
+
|
49
|
+
def test_remove_glob
|
50
|
+
fake_dir = add_fake
|
51
|
+
assert_dir_found fake_dir, "Fake directory not found in path."
|
52
|
+
fake_glob = fake_dir.chop << "*"
|
53
|
+
@path.remove fake_glob
|
54
|
+
assert_dir_not_found fake_dir, "Fake directory not removed by glob: #{fake_glob}"
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_remove_regexp
|
58
|
+
fake_dir = add_fake
|
59
|
+
assert_dir_found fake_dir, "Fake directory not found in path."
|
60
|
+
fake_regex = Regexp.new("^" << fake_dir.gsub('\\', '\\\\\\\\') << "$")
|
61
|
+
@path.remove fake_regex
|
62
|
+
assert_dir_not_found fake_dir, "Fake directory not removed by regex: #{fake_regex}"
|
63
|
+
end
|
64
|
+
|
65
|
+
def test_remove_case_sensitive_glob
|
66
|
+
# Ensure matches with different case works.
|
67
|
+
fake_dir = add_fake "C:\\program files"
|
68
|
+
fake_glob = "C:\\PROGRAM*"
|
69
|
+
@path.remove fake_glob
|
70
|
+
assert_dir_not_found fake_dir, "Fake directory not removed by glob: #{fake_glob}"
|
71
|
+
end
|
72
|
+
|
73
|
+
def test_remove_glob_two_stars
|
74
|
+
# Test that a glob with wildcards on both ends works
|
75
|
+
fake_dir = add_fake "C:\\program files"
|
76
|
+
fake_glob = "*PROGRAM*"
|
77
|
+
@path.remove fake_glob
|
78
|
+
assert_dir_not_found fake_dir, "Fake directory not removed by glob: #{fake_glob}"
|
79
|
+
end
|
80
|
+
|
81
|
+
def test_remove_glob_single_char
|
82
|
+
# Test that a glob with question mark works
|
83
|
+
fake_dir = add_fake
|
84
|
+
fake_glob = fake_dir.chop << "?"
|
85
|
+
@path.remove fake_glob
|
86
|
+
assert_dir_not_found fake_dir, "Fake directory not removed by glob: #{fake_glob}"
|
87
|
+
end
|
88
|
+
|
89
|
+
# Makes a directory guarnteed not to exist
|
90
|
+
def make_fake_dir(dir)
|
91
|
+
cnt = 1
|
92
|
+
fake_dir = dir
|
93
|
+
while @path.paths.include? fake_dir
|
94
|
+
fake_dir = dir << cnt
|
95
|
+
cnt += 1
|
96
|
+
end
|
97
|
+
|
98
|
+
fake_dir
|
99
|
+
end
|
100
|
+
|
101
|
+
# Add a fake path
|
102
|
+
def add_fake(base = "C:\\foobar")
|
103
|
+
@path.paths << fake = make_fake_dir(base)
|
104
|
+
fake
|
105
|
+
end
|
106
|
+
|
107
|
+
# Add a duplicated fake path
|
108
|
+
def add_fake_dup
|
109
|
+
fake = add_fake
|
110
|
+
@path.paths << fake
|
111
|
+
|
112
|
+
fake
|
113
|
+
end
|
114
|
+
|
115
|
+
def assert_dir_found(dir, msg)
|
116
|
+
assert @path.paths.include?(dir), msg
|
117
|
+
end
|
118
|
+
|
119
|
+
def assert_dir_not_found(dir, msg)
|
120
|
+
assert ! @path.paths.include?(dir), msg
|
121
|
+
end
|
122
|
+
|
123
|
+
def assert_dup_found(dir, msg)
|
124
|
+
cnt = 0
|
125
|
+
@path.paths.each { |p| cnt += 1 if p == dir }
|
126
|
+
assert cnt == 2, msg
|
127
|
+
end
|
128
|
+
end
|
metadata
CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.0
|
|
3
3
|
specification_version: 1
|
4
4
|
name: patheditor
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 1.0.
|
7
|
-
date: 2007-02-
|
6
|
+
version: 1.0.3
|
7
|
+
date: 2007-02-12 00:00:00 -08:00
|
8
8
|
summary: A simple program to manage the Windows PATH environment variable.
|
9
9
|
require_paths:
|
10
10
|
- lib
|
@@ -30,6 +30,7 @@ authors:
|
|
30
30
|
- Justin Bailey
|
31
31
|
files:
|
32
32
|
- lib/windows_path.rb
|
33
|
+
- test/test_windows_path.rb
|
33
34
|
- README.txt
|
34
35
|
- Rakefile
|
35
36
|
test_files: []
|