pathological 0.2.4 → 0.2.5
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/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") }
|