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 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.2"
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. If characters such as "*" or "?" appear in the path, it will be treated as a regular expression, and any back slashes should be escaped (i.e. "C:\\Program Files\\*" vs "C:\Program Files").
43
-
44
- When a non-regular expression is given, the path must match exactly to be removed.
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
- nonexistent = []
71
- found = WindowsPathArray.new
72
- duplicates = []
73
- idx = 0
74
- @currPath.paths.each do |p|
75
- pathname = Pathname.new(p).cleanpath
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
- idx += 1
84
- end
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? @add
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
- # See if @remove looks like a regular expression
107
- if @remove.index("*") || @remove.index("?")
108
- # File glob "*" not quite the same as reg ex "*" - need to add "." character
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
- # Takes an array of paths or indices and removes them from the current path. Yields
147
- # each path before deleting it, if a block was provided
148
- def remove_paths(paths_to_remove)
149
- @paths_removed ||= 0
150
- adjust = 0
151
- paths_to_remove.each do |p|
152
- if p.is_a?(Fixnum)
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.2
7
- date: 2007-02-07 00:00:00 -08:00
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: []