pathological 0.2.4 → 0.2.5
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile.lock +3 -1
- data/README.md +32 -18
- data/Rakefile +12 -0
- data/lib/pathological/base.rb +81 -4
- data/lib/pathological/version.rb +1 -1
- data/pathological.gemspec +3 -2
- data/test/{pathological → unit/pathological}/base_test.rb +39 -0
- metadata +24 -11
- data/test/unit.watchr.rb +0 -10
data/Gemfile.lock
CHANGED
@@ -1,13 +1,14 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
pathological (0.2.
|
4
|
+
pathological (0.2.5)
|
5
5
|
|
6
6
|
GEM
|
7
7
|
remote: http://rubygems.org/
|
8
8
|
specs:
|
9
9
|
fakefs (0.4.0)
|
10
10
|
minitest (2.5.1)
|
11
|
+
rake (0.9.2.2)
|
11
12
|
rr (1.0.3)
|
12
13
|
scope (0.2.3)
|
13
14
|
minitest
|
@@ -18,5 +19,6 @@ PLATFORMS
|
|
18
19
|
DEPENDENCIES
|
19
20
|
fakefs
|
20
21
|
pathological!
|
22
|
+
rake
|
21
23
|
rr (>= 1.0.3)
|
22
24
|
scope (>= 0.2.3)
|
data/README.md
CHANGED
@@ -32,16 +32,23 @@ Getting started with pathological is easy. First, make a file called `Pathfile`
|
|
32
32
|
|
33
33
|
Now require the gem at the start of any executable ruby file:
|
34
34
|
|
35
|
-
|
35
|
+
``` ruby
|
36
|
+
#!/usr/bin/env ruby
|
36
37
|
|
37
|
-
|
38
|
-
|
39
|
-
|
38
|
+
require "bundler/setup" # If you're using bundler
|
39
|
+
require "pathological"
|
40
|
+
|
41
|
+
# other requires...
|
42
|
+
```
|
40
43
|
|
41
44
|
Now your project root will be in your load path. If your project has, for example, `lib/foo.rb`, then `require
|
42
45
|
lib/foo` will work in any of your ruby files. This works because when Pathological is required it will search
|
43
46
|
up the directory tree until it finds a `Pathfile`. (It will raise an error if one cannot be found).
|
44
47
|
|
48
|
+
Note that Pathological should be the first require in your main file so that it will be loaded first. An
|
49
|
+
exception to this is when you're using Bundler, in which case you should `require bundler/setup` before
|
50
|
+
Pathological (and of course you should have `gem "pathological"` in your `Gemfile`).
|
51
|
+
|
45
52
|
`Pathfile`s should be kept in version control.
|
46
53
|
|
47
54
|
Adding other paths to your load path
|
@@ -70,11 +77,12 @@ and that `Pathfile` contains the following:
|
|
70
77
|
|
71
78
|
Then inside `run_my_project.rb`:
|
72
79
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
80
|
+
``` ruby
|
81
|
+
require "pathological"
|
82
|
+
require "foo"
|
83
|
+
require "common"
|
84
|
+
# ...
|
85
|
+
```
|
78
86
|
|
79
87
|
Installation
|
80
88
|
------------
|
@@ -120,15 +128,19 @@ should be avoided if possible.
|
|
120
128
|
|
121
129
|
There are two ways to specify modes. First, you can enable any modes you want using the Pathological API:
|
122
130
|
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
131
|
+
``` ruby
|
132
|
+
require "pathological/base"
|
133
|
+
Pathological.debug_mode
|
134
|
+
Pathological.parentdir_mode
|
135
|
+
Pathological.add_paths!
|
136
|
+
```
|
127
137
|
|
128
138
|
A quicker way is also provided: if you only need to use one special mode, then there is a dedicated file you
|
129
139
|
can require:
|
130
140
|
|
131
|
-
|
141
|
+
``` ruby
|
142
|
+
require "pathological/bundlerize"
|
143
|
+
```
|
132
144
|
|
133
145
|
Public API
|
134
146
|
----------
|
@@ -136,10 +148,11 @@ Public API
|
|
136
148
|
For even more configurable custom integration with Pathological, a public API is provided. See the generated
|
137
149
|
documentation for details on the following public methods:
|
138
150
|
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
151
|
+
* `Pathological#add_paths!`
|
152
|
+
* `Pathological#find_load_paths`
|
153
|
+
* `Pathological#find_pathfile`
|
154
|
+
* `Pathological#reset!`
|
155
|
+
* `Pathological#copy_outside_paths!`
|
143
156
|
|
144
157
|
Authors
|
145
158
|
-------
|
@@ -149,6 +162,7 @@ Pathological was written by the following Ooyala engineers:
|
|
149
162
|
* [Daniel MacDougall](mailto:dmac@ooyala.com)
|
150
163
|
* [Caleb Spare](mailto:caleb@ooyala.com)
|
151
164
|
* [Sami Abu-El-Haija](mailto:sami@ooyala.com)
|
165
|
+
* [Evan Chan](mailto:ev@ooyala.com)
|
152
166
|
|
153
167
|
Credits
|
154
168
|
-------
|
data/Rakefile
CHANGED
@@ -1,2 +1,14 @@
|
|
1
1
|
require "bundler"
|
2
|
+
require "rake/testtask"
|
3
|
+
|
2
4
|
Bundler::GemHelper.install_tasks
|
5
|
+
|
6
|
+
task :test => ["test:units"]
|
7
|
+
|
8
|
+
namespace :test do
|
9
|
+
Rake::TestTask.new(:units) do |task|
|
10
|
+
task.libs << "test"
|
11
|
+
task.test_files = FileList["test/unit/**/*_test.rb"]
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
data/lib/pathological/base.rb
CHANGED
@@ -76,6 +76,57 @@ module Pathological
|
|
76
76
|
end
|
77
77
|
end
|
78
78
|
|
79
|
+
# Copies directories in pathfile to a destination, such that the destination has no references to
|
80
|
+
# directories outside of the destination in the load path.
|
81
|
+
#
|
82
|
+
# Hierarchy of destination directory:
|
83
|
+
# destination/
|
84
|
+
# Pathfile # new paths
|
85
|
+
# dependency_directory/
|
86
|
+
# dependency1 # Copied from original location
|
87
|
+
#
|
88
|
+
# This is very useful for deployment, for example.
|
89
|
+
#
|
90
|
+
# @param [String] copy_outside_paths the directory to stage dependencies in
|
91
|
+
# @param [String] dependency_directory the subdir within destination to put dependencies in
|
92
|
+
#
|
93
|
+
# TODO(ev): Break this function up into a set of more functional primitives
|
94
|
+
def self.copy_outside_paths!(destination, dependency_directory = "pathological_dependencies")
|
95
|
+
saved_exclude_root = @@exclude_root
|
96
|
+
begin
|
97
|
+
self.excluderoot_mode
|
98
|
+
pathfile = self.find_pathfile
|
99
|
+
# Nothing to do if there's no Pathfile
|
100
|
+
return unless pathfile && File.file?(pathfile)
|
101
|
+
|
102
|
+
foreign_paths = self.find_load_paths(pathfile).uniq
|
103
|
+
return if foreign_paths.empty?
|
104
|
+
|
105
|
+
path_root = File.join(destination, dependency_directory)
|
106
|
+
FileUtils.mkdir_p path_root
|
107
|
+
|
108
|
+
# Copy in each path and save the relative paths to write to the rewritten Pathfile. We copy each unique
|
109
|
+
# path into the folder not as the basename, but as the longest suffix of the path necessary to make it
|
110
|
+
# unique. (Otherwise this won't work if you have two entries with the same basename in the Pathfile,
|
111
|
+
# such as "foo/lib" and "bar/lib".)
|
112
|
+
common_prefix = find_longest_common_prefix(foreign_paths)
|
113
|
+
new_pathfile_paths = foreign_paths.map do |foreign_path|
|
114
|
+
path_short_name = foreign_path.gsub(/^#{common_prefix}/, "")
|
115
|
+
symlinked_name = File.join(path_root, path_short_name)
|
116
|
+
FileUtils.mkdir_p File.split(symlinked_name)[0]
|
117
|
+
debug "About to move #{foreign_path} to #{symlinked_name}..."
|
118
|
+
copy_directory(foreign_path, symlinked_name)
|
119
|
+
File.join(dependency_directory, path_short_name)
|
120
|
+
end
|
121
|
+
# Overwrite the Pathfile with the new relative paths.
|
122
|
+
File.open(File.join(destination, "Pathfile"), "w") do |file|
|
123
|
+
new_pathfile_paths.each { |path| file.puts path }
|
124
|
+
end
|
125
|
+
ensure
|
126
|
+
@@exclude_root = saved_exclude_root
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
79
130
|
# Convenience functions for the various modes in which Pathological may run.
|
80
131
|
|
81
132
|
def self.debug_mode; @@debug = true; end
|
@@ -155,9 +206,35 @@ module Pathological
|
|
155
206
|
@@exclude_root ? paths.reject { |path| File.expand_path(path) == File.expand_path(root) } : paths
|
156
207
|
end
|
157
208
|
|
158
|
-
#
|
159
|
-
#
|
160
|
-
#
|
209
|
+
# Find the longest common path prefix amongst a list of paths
|
210
|
+
#
|
211
|
+
# @private
|
212
|
+
# @param [List<String>] a list of paths
|
213
|
+
# @return [String] the longest common prefix, or "/"
|
214
|
+
def self.find_longest_common_prefix(paths)
|
215
|
+
if paths.size == 1
|
216
|
+
common_prefix = File.split(paths[0])[0]
|
217
|
+
else
|
218
|
+
common_prefix = "/"
|
219
|
+
paths[0].split("/").reject(&:empty?).each do |part|
|
220
|
+
new_prefix = "#{common_prefix}#{part}/"
|
221
|
+
break unless paths.all? { |path| path.start_with? new_prefix }
|
222
|
+
common_prefix = new_prefix
|
223
|
+
end
|
224
|
+
end
|
225
|
+
common_prefix
|
226
|
+
end
|
227
|
+
|
228
|
+
# Copies a directory and all its symlinks to a destination.
|
229
|
+
# @private
|
230
|
+
def self.copy_directory(source, dest)
|
231
|
+
rsync_command = "rsync -r --archive --links --copy-unsafe-links --delete #{source}/ '#{dest}'"
|
232
|
+
debug `#{rsync_command}`
|
233
|
+
end
|
234
|
+
|
235
|
+
# Searches the call stack for the file that required pathological. If no file can be found, falls back to
|
236
|
+
# the currently executing file ($0). This handles the case where the app was launched by another executable
|
237
|
+
# (rake, thin, rackup, etc.)
|
161
238
|
#
|
162
239
|
# @return [String] name of file requiring pathological, or the currently executing file.
|
163
240
|
def self.requiring_filename
|
@@ -173,7 +250,7 @@ module Pathological
|
|
173
250
|
requiring_file ? requiring_file.match(/(.+):\d+/)[1] : $0 rescue $0
|
174
251
|
end
|
175
252
|
|
176
|
-
private_class_method :debug, :real_path, :parse_pathfile
|
253
|
+
private_class_method :debug, :real_path, :parse_pathfile, :find_longest_common_prefix, :copy_directory
|
177
254
|
|
178
255
|
# Reset options
|
179
256
|
Pathological.reset!
|
data/lib/pathological/version.rb
CHANGED
data/pathological.gemspec
CHANGED
@@ -10,8 +10,8 @@ Gem::Specification.new do |s|
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">=0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.specification_version = 2 if s.respond_to? :specification_version=
|
12
12
|
|
13
|
-
s.authors = "Daniel MacDougall", "Caleb Spare"
|
14
|
-
s.email = "dmac@ooyala.com", "caleb@ooyala.com"
|
13
|
+
s.authors = "Daniel MacDougall", "Caleb Spare", "Evan Chan"
|
14
|
+
s.email = "dmac@ooyala.com", "caleb@ooyala.com", "ev@ooyala.com"
|
15
15
|
s.homepage = "http://www.ooyala.com"
|
16
16
|
s.rubyforge_project = "pathological"
|
17
17
|
|
@@ -28,4 +28,5 @@ Gem::Specification.new do |s|
|
|
28
28
|
s.add_development_dependency "rr", ">= 1.0.3"
|
29
29
|
s.add_development_dependency "scope", ">= 0.2.3"
|
30
30
|
s.add_development_dependency "fakefs"
|
31
|
+
s.add_development_dependency "rake"
|
31
32
|
end
|
@@ -210,6 +210,45 @@ module Pathological
|
|
210
210
|
assert_load_path ["/foo/bar"]
|
211
211
|
end
|
212
212
|
end
|
213
|
+
|
214
|
+
context "#copy_outside_paths!" do
|
215
|
+
setup do
|
216
|
+
@destination = "/tmp/staging"
|
217
|
+
@pathfile = "/Pathfile"
|
218
|
+
FileUtils.cd "/"
|
219
|
+
FileUtils.mkdir_p @destination
|
220
|
+
@source_paths = ["/src/github1", "/src/moofoo"]
|
221
|
+
@source_paths.each { |src_dir| FileUtils.mkdir_p src_dir }
|
222
|
+
end
|
223
|
+
|
224
|
+
should "return immediately if there is no Pathfile" do
|
225
|
+
mock(Pathological).find_pathfile { nil }
|
226
|
+
Pathological.copy_outside_paths! @destination
|
227
|
+
refute File.directory?(File.join(@destination, "pathological_dependencies"))
|
228
|
+
end
|
229
|
+
|
230
|
+
should "return immediately if Pathfile is empty" do
|
231
|
+
File.open(@pathfile, "w") { |f| f.puts "\n# What the heck is this file?\n\n" }
|
232
|
+
Pathological.copy_outside_paths! @destination
|
233
|
+
refute File.directory?(File.join(@destination, "pathological_dependencies"))
|
234
|
+
end
|
235
|
+
|
236
|
+
should "copy source dirs as links and rewrite Pathfile" do
|
237
|
+
File.open(@pathfile, "w") { |f| f.puts @source_paths.join("\n") }
|
238
|
+
|
239
|
+
final_path = File.join(@destination, "pathological_dependencies")
|
240
|
+
@source_paths.each do |source_path|
|
241
|
+
mock(Pathological).copy_directory(source_path, final_path + source_path.gsub("/src", "")).once
|
242
|
+
end
|
243
|
+
Pathological.copy_outside_paths! @destination
|
244
|
+
|
245
|
+
assert File.directory?(final_path)
|
246
|
+
destination_paths = @source_paths.map do |source_path|
|
247
|
+
"pathological_dependencies#{source_path.gsub("/src", "")}"
|
248
|
+
end
|
249
|
+
assert_equal destination_paths, File.read(File.join(@destination, "Pathfile")).split("\n")
|
250
|
+
end
|
251
|
+
end
|
213
252
|
end
|
214
253
|
end
|
215
254
|
end
|
metadata
CHANGED
@@ -1,20 +1,21 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pathological
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.5
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Daniel MacDougall
|
9
9
|
- Caleb Spare
|
10
|
+
- Evan Chan
|
10
11
|
autorequire:
|
11
12
|
bindir: bin
|
12
13
|
cert_chain: []
|
13
|
-
date:
|
14
|
+
date: 2012-09-04 00:00:00.000000000Z
|
14
15
|
dependencies:
|
15
16
|
- !ruby/object:Gem::Dependency
|
16
17
|
name: rr
|
17
|
-
requirement: &
|
18
|
+
requirement: &27117160 !ruby/object:Gem::Requirement
|
18
19
|
none: false
|
19
20
|
requirements:
|
20
21
|
- - ! '>='
|
@@ -22,10 +23,10 @@ dependencies:
|
|
22
23
|
version: 1.0.3
|
23
24
|
type: :development
|
24
25
|
prerelease: false
|
25
|
-
version_requirements: *
|
26
|
+
version_requirements: *27117160
|
26
27
|
- !ruby/object:Gem::Dependency
|
27
28
|
name: scope
|
28
|
-
requirement: &
|
29
|
+
requirement: &27091120 !ruby/object:Gem::Requirement
|
29
30
|
none: false
|
30
31
|
requirements:
|
31
32
|
- - ! '>='
|
@@ -33,10 +34,10 @@ dependencies:
|
|
33
34
|
version: 0.2.3
|
34
35
|
type: :development
|
35
36
|
prerelease: false
|
36
|
-
version_requirements: *
|
37
|
+
version_requirements: *27091120
|
37
38
|
- !ruby/object:Gem::Dependency
|
38
39
|
name: fakefs
|
39
|
-
requirement: &
|
40
|
+
requirement: &27090740 !ruby/object:Gem::Requirement
|
40
41
|
none: false
|
41
42
|
requirements:
|
42
43
|
- - ! '>='
|
@@ -44,13 +45,25 @@ dependencies:
|
|
44
45
|
version: '0'
|
45
46
|
type: :development
|
46
47
|
prerelease: false
|
47
|
-
version_requirements: *
|
48
|
+
version_requirements: *27090740
|
49
|
+
- !ruby/object:Gem::Dependency
|
50
|
+
name: rake
|
51
|
+
requirement: &27090280 !ruby/object:Gem::Requirement
|
52
|
+
none: false
|
53
|
+
requirements:
|
54
|
+
- - ! '>='
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: '0'
|
57
|
+
type: :development
|
58
|
+
prerelease: false
|
59
|
+
version_requirements: *27090280
|
48
60
|
description: ! " Pathological provides a way to manage a project's require paths
|
49
61
|
by using a small config file that\n indicates all directories to include in the
|
50
62
|
load path.\n"
|
51
63
|
email:
|
52
64
|
- dmac@ooyala.com
|
53
65
|
- caleb@ooyala.com
|
66
|
+
- ev@ooyala.com
|
54
67
|
executables: []
|
55
68
|
extensions: []
|
56
69
|
extra_rdoc_files: []
|
@@ -71,8 +84,7 @@ files:
|
|
71
84
|
- lib/pathological/parentdir.rb
|
72
85
|
- lib/pathological/version.rb
|
73
86
|
- pathological.gemspec
|
74
|
-
- test/pathological/base_test.rb
|
75
|
-
- test/unit.watchr.rb
|
87
|
+
- test/unit/pathological/base_test.rb
|
76
88
|
homepage: http://www.ooyala.com
|
77
89
|
licenses: []
|
78
90
|
post_install_message:
|
@@ -93,8 +105,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
93
105
|
version: '0'
|
94
106
|
requirements: []
|
95
107
|
rubyforge_project: pathological
|
96
|
-
rubygems_version: 1.8.
|
108
|
+
rubygems_version: 1.8.10
|
97
109
|
signing_key:
|
98
110
|
specification_version: 2
|
99
111
|
summary: A nice way to manage your project's require paths.
|
100
112
|
test_files: []
|
113
|
+
has_rdoc:
|
data/test/unit.watchr.rb
DELETED
@@ -1,10 +0,0 @@
|
|
1
|
-
# Watchr script for unit tests
|
2
|
-
|
3
|
-
def run_test(test)
|
4
|
-
system("bundle exec ruby #{test}")
|
5
|
-
end
|
6
|
-
|
7
|
-
watch(/^test\/.*_test\.rb/) { |md| run_test(md[0]) }
|
8
|
-
watch(/^lib\/(.*)\.rb/) { |md| run_test("test/#{md[1]}_test.rb") }
|
9
|
-
|
10
|
-
Signal.trap("INT") { abort("\n") }
|