pathological 0.2.1

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/.rvmrc ADDED
@@ -0,0 +1,57 @@
1
+ #!/usr/bin/env bash
2
+
3
+ # WARNING: DO NOT MANUALLY EDIT THIS FILE UNLESS YOU KNOW WHAT YOU ARE DOING.
4
+ # This file was generated automatically using ofe/tools/rvmrc_create.sh (which is in turn a wrapper around the
5
+ # rvm command rvm --rvmrc). It was generated in the following way:
6
+ #
7
+ # $ rvmrc_create.sh use 1.9.2@pathological --create
8
+ #
9
+ # Please use rvmrc_create.sh if you want to change what this project rvmrc does.
10
+
11
+ # This is an RVM Project .rvmrc file, used to automatically load the ruby
12
+ # development environment upon cd'ing into the directory
13
+
14
+ # First we specify our desired <ruby>[@<gemset>], the @gemset name is optional.
15
+ environment_id="ruby-1.9.2-p180@pathological"
16
+
17
+ #
18
+ # First we attempt to load the desired environment directly from the environment
19
+ # file. This is very fast and efficicent compared to running through the entire
20
+ # CLI and selector. If you want feedback on which environment was used then
21
+ # insert the word 'use' after --create as this triggers verbose mode.
22
+ #
23
+ if [[ -d "${rvm_path:-$HOME/.rvm}/environments" \
24
+ && -s "${rvm_path:-$HOME/.rvm}/environments/$environment_id" ]] ; then
25
+ \. "${rvm_path:-$HOME/.rvm}/environments/$environment_id"
26
+
27
+ [[ -s ".rvm/hooks/after_use" ]] && . ".rvm/hooks/after_use"
28
+ else
29
+ # If the environment file has not yet been created, use the RVM CLI to select.
30
+ rvm --create use "$environment_id"
31
+ fi
32
+
33
+ #
34
+ # If you use an RVM gemset file to install a list of gems (*.gems), you can have
35
+ # it be automatically loaded. Uncomment the following and adjust the filename if
36
+ # necessary.
37
+ #
38
+ # filename=".gems"
39
+ # if [[ -s "$filename" ]] ; then
40
+ # rvm gemset import "$filename" | grep -v already | grep -v listed | grep -v complete | sed '/^$/d'
41
+ # fi
42
+
43
+ #
44
+ # If you use bundler and would like to run bundle each time you enter the
45
+ # directory, you can uncomment the following code.
46
+ #
47
+ # # Ensure that Bundler is installed. Install it if it is not.
48
+ # if ! command -v bundle >/dev/null; then
49
+ # printf "The rubygem 'bundler' is not installed. Installing it now.\n"
50
+ # gem install bundler
51
+ # fi
52
+ #
53
+ # # Bundle while reducing excess noise.
54
+ # printf "Bundling your gems. This may take a few minutes on a fresh clone.\n"
55
+ # bundle | grep -v '^Using ' | grep -v ' is complete' | sed '/^$/d'
56
+ #
57
+
data/.yardopts ADDED
@@ -0,0 +1 @@
1
+ --no-private lib/pathological/base.rb - README.md LICENSE
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Dependencies are specified in pathological.gemspec
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,26 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ pathological (0.1.4)
5
+
6
+ GEM
7
+ remote: http://rubygems.org/
8
+ specs:
9
+ fakefs (0.4.0)
10
+ minitest (2.5.1)
11
+ rdiscount (1.6.8)
12
+ rr (1.0.3)
13
+ scope (0.2.3)
14
+ minitest
15
+ yard (0.7.2)
16
+
17
+ PLATFORMS
18
+ ruby
19
+
20
+ DEPENDENCIES
21
+ fakefs
22
+ pathological!
23
+ rdiscount (~> 1.6.8)
24
+ rr (>= 1.0.3)
25
+ scope (>= 0.2.3)
26
+ yard (~> 0.7.2)
data/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2011 Ooyala, Inc.
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,167 @@
1
+ Pathological
2
+ ============
3
+
4
+ Pathological is a Ruby tool that provides a lightweight mechanism for managing your project's load path.
5
+
6
+ The problem
7
+ -----------
8
+
9
+ When you're writing a gem, you don't have to worry about paths much, because Rubygems makes sure that `lib/`
10
+ makes it into your path for you. On the other hand, if you have large Ruby projects which aren't organized as
11
+ gems, you may encounter some of the following problems:
12
+
13
+ * If you don't have relative requires, you have to run your project from the project root.
14
+ * If you want relative requires, you have something nasty like this in your code:
15
+
16
+ require File.expand_path(File.join(File.dirname(__FILE__), 'myfile'))
17
+
18
+ * Ruby 1.9.2 breaks your load path if you are expecting `.` to be in it. You might have to use
19
+ `require_relative` or similar to remedy this.
20
+ * You have symlinks to shared libraries or non-gemified vendor code living all over your project in order
21
+ to keep your load paths sane.
22
+
23
+ Pathological provides one way to manage these issues.
24
+
25
+ Using pathological
26
+ ------------------
27
+
28
+ Getting started with pathological is easy. First, make a file called `Pathfile` at your project root:
29
+
30
+ $ cd path/to/myproject
31
+ $ touch Pathfile
32
+
33
+ Now require the gem at the start of any executable ruby file:
34
+
35
+ #!/usr/bin/env ruby
36
+
37
+ require "rubygems" # If you're using 1.8
38
+ require "pathological"
39
+ # other requires...
40
+
41
+ Now your project root will be in your load path. If your project has, for example, `lib/foo.rb`, then `require
42
+ lib/foo` will work in any of your ruby files. This works because when Pathological is required it will search
43
+ up the directory tree until it finds a `Pathfile`. (It will raise an error if there this cannot be found).
44
+
45
+ `Pathfile`s should be kept in version control.
46
+
47
+ Adding other paths to your load path
48
+ ------------------------------------
49
+
50
+ To add more paths to your load path, just put the paths in your `Pathfile`. The paths are relative to the
51
+ location of the `Pathfile`. The paths will be inserted in the order they appear; the project root itself will
52
+ be first. If any of the paths are not valid directories, then an exception will be raised when Pathological is
53
+ required.
54
+
55
+ #### Example
56
+
57
+ Suppose that you have a directory structure like this:
58
+
59
+ repos/
60
+ |-shared_lib/
61
+ | `-common.rb
62
+ `-my_project/
63
+ |-Pathfile
64
+ |-run_my_project.rb
65
+ `-foo.rb
66
+
67
+ and that `Pathfile` contains the following:
68
+
69
+ ../shared_lib
70
+
71
+ Then inside `run_my_project.rb`:
72
+
73
+ require "rubygems"
74
+ require "pathological"
75
+ require "foo"
76
+ require "common"
77
+ # ...
78
+
79
+ Installation
80
+ ------------
81
+
82
+ Pathological is packaged as a Rubygem and hence can be trivially installed with
83
+
84
+ $ gem install pathological
85
+
86
+ Advanced usage
87
+ --------------
88
+
89
+ In some cases, you might want slightly different behavior. This customization is done through the use of
90
+ custom modes. You may use any combination of modes.
91
+
92
+ #### debug
93
+
94
+ This adds debugging statements to `STDOUT` that explain what Pathological is doing.
95
+
96
+ #### excluderoot
97
+
98
+ In this mode, the project root (where the `Pathfile` is located) is not added to the load path (so only paths
99
+ specified *in* the `Pathfile` will be loaded).
100
+
101
+ #### noexceptions
102
+
103
+ This is used if you don't want to raise exceptions if you have bad paths (i.e. non-existent paths or not
104
+ directories) in your `Pathfile`.
105
+
106
+ #### bundlerize
107
+
108
+ Bundlerize mode enables Bundler to work with your project regardless of your current directory, in the same
109
+ way as Pathological, by attempting to set the `BUNDLE_GEMFILE` environment variable to match the directory
110
+ where the `Pathfile` is located. Note that you have to run this before requiring `bundler/setup`. Also, this
111
+ will not take effect if you are running with `bundle exec`.
112
+
113
+ #### parentdir
114
+
115
+ This mode makes Pathological add the unique parents of all paths it finds (instead of the paths themselves).
116
+ The purpose of parentdir is to enable Pathological to work in a drop-in fashion with legacy code written with
117
+ all requires being relative to the root of the codebase. Note that this will allow one to require files
118
+ located in any child of the parents, not just from the directories specified in the `Pathfile`. This mode
119
+ should be avoided if possible.
120
+
121
+ There are two ways to specify modes. First, you can enable any modes you want using the Pathological API:
122
+
123
+ require "pathological/base"
124
+ Pathological.debug_mode
125
+ Pathological.parentdir_mode
126
+ Pathological.add_paths!
127
+
128
+ A quicker way is also provided: if you only need to use one special mode, then there is a dedicated file you
129
+ can require:
130
+
131
+ require "pathological/bundlerize"
132
+
133
+ Public API
134
+ ----------
135
+
136
+ For even more configurable custom integration with Pathological, a public API is provided. See the generated
137
+ documentation for details on the following public methods:
138
+
139
+ Pathological#add_paths!
140
+ Pathological#find_load_paths
141
+ Pathological#find_pathfile
142
+ Pathological#reset!
143
+
144
+ Authors
145
+ -------
146
+
147
+ Pathological was written by the following Ooyala engineers:
148
+
149
+ * [Daniel MacDougall](mailto:dmac@ooyala.com)
150
+ * [Caleb Spare](mailto:caleb@ooyala.com)
151
+ * [Sami Abu-El-Haija](mailto:sami@ooyala.com)
152
+
153
+ Credits
154
+ -------
155
+
156
+ * Harry Robertson for the idea to *not* use a dot-prefixed configuration file
157
+
158
+ Contributing
159
+ ------------
160
+
161
+ If you would like to commit a patch, great! Just do the usual github pull request stuff and we'll check it
162
+ out.
163
+
164
+ License
165
+ -------
166
+
167
+ Pathological is licensed under the MIT license.
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require "bundler"
2
+ Bundler::GemHelper.install_tasks
data/TODO.md ADDED
@@ -0,0 +1,70 @@
1
+ TODO
2
+ ====
3
+
4
+ Tasks
5
+ -----
6
+
7
+ * Bundler compatibility.
8
+ * Push to the Ooyala github account; release on rubygems.org
9
+ * Mode for adding one directory above given paths to the current.
10
+ * Public API:
11
+ * Get all loaded files that come from Pathological directories
12
+
13
+ Design decisions
14
+ ----------------
15
+
16
+ * Should we allow for including other Pathfiles? Proposed syntaxes:
17
+
18
+ include path/to/other/Pathfile
19
+ import path/to/other/Pathfile # Rakefile
20
+ i path/to/other/Pathfile
21
+ source path/to/other/Pathfile # Bash
22
+ . path/to/other/Pathfile # Bash
23
+ path/to/other/Pathfile # Distinguishable from regular path if Pathfile is not a directory
24
+
25
+ **Not needed now --Caleb**
26
+
27
+ * Do we like `>` to signify directives? Alternatives:
28
+
29
+ > exclude-root # Current syntax
30
+ exclude-root # Only problem is if you want to include a directory with the same name as a directive
31
+
32
+ We could also prefix each type of line to make things unambiguous:
33
+
34
+ p path/to/lib/
35
+ d exclude-root
36
+
37
+ **Fine for now --Caleb**
38
+
39
+ * Right now there's a small problem with comments: if your path includes the character `#`, then the rest
40
+ will be chopped off (interpreted as a comment). We could remedy this by only allowing for comments to
41
+ start at the beginning of lines:
42
+
43
+ # Yes
44
+ ../lib/ # No
45
+
46
+ **Let's leave this alone for now; probably a non-issue --Caleb**
47
+
48
+ * Right our require paths tend to look like this (using `shared_lib/` as an example):
49
+
50
+ ``` ruby
51
+ require "shared_lib/utils/foo_util"
52
+ ```
53
+
54
+ To support this, you would need your `Pathfile` to include the directory *above* `shared_lib/`. The
55
+ downside of this is that it doesn't play well with the idea of using our `Pathfile`s to tell our deploy
56
+ scripts what to include. We could potentially add a new construct to allow the user to specify which
57
+ subdirectories they would be using. Example (just off the top of my head):
58
+
59
+ path/to/repo/dir/{shared_lib, common, vendor}
60
+
61
+ However, we'd still have to add `path/to/repo/dir` to the `$LOAD_PATH`, so the only way to enforce this at
62
+ require time would be to use a custom `require`. This is all quite a high cost to pay in terms of design
63
+ simplicity, but yet being able to use Pathfiles as a single place to document what dependencies to pull in
64
+ seems very appealing. Any ideas?
65
+
66
+ **After chatting with some people, we're going to leave this as is and truncate the `shared_lib` from our
67
+ paths. --Caleb**
68
+
69
+ **Actually, I think I'm going to add an optional mode to add one directory _above_ to the load path
70
+ instead of the given path, in order to accomomdate this use case. --Caleb**
@@ -0,0 +1,3 @@
1
+ require "pathological/base"
2
+
3
+ Pathological.add_paths!
@@ -0,0 +1,192 @@
1
+ require "pathname"
2
+
3
+ module Pathological
4
+ PATHFILE_NAME = "Pathfile"
5
+
6
+ class PathologicalException < RuntimeError; end
7
+ class NoPathfileException < PathologicalException; end
8
+
9
+ # Add paths to the load path.
10
+ #
11
+ # @param [String] load_path the load path to use.
12
+ # @param [Array<String>] paths the array of new load paths (if +nil+, the result of {find_load_paths}).
13
+ def self.add_paths!(load_path = $LOAD_PATH, paths = nil)
14
+ begin
15
+ paths ||= find_load_paths
16
+ rescue NoPathfileException
17
+ STDERR.puts "Warning: using Pathological, but no Pathfile was found."
18
+ return
19
+ end
20
+ paths.each do |path|
21
+ if load_path.include? path
22
+ debug "Skipping <#{path}>, which is already in the load path."
23
+ else
24
+ debug "Adding <#{path}> to load path."
25
+ load_path << path
26
+ @@loaded_paths << path
27
+ end
28
+ end
29
+ end
30
+
31
+ # For some pathfile, parse it and find all the load paths that it references.
32
+ #
33
+ # @param [String, nil] pathfile the pathfile to inspect. Uses {find_pathfile} if +nil+.
34
+ # @return [Array<String>] the resulting array of paths.
35
+ def self.find_load_paths(pathfile = nil)
36
+ pathfile ||= find_pathfile
37
+ raise NoPathfileException unless pathfile
38
+ begin
39
+ pathfile_handle = File.open(pathfile)
40
+ rescue Errno::ENOENT
41
+ raise NoPathfileException
42
+ rescue
43
+ raise PathologicalException, "There was an error opening the pathfile <#{pathfile}>."
44
+ end
45
+ parse_pathfile(pathfile_handle)
46
+ end
47
+
48
+ # Find the pathfile by searching up from a starting directory. Symlinks are expanded out.
49
+ #
50
+ # @param [String] directory the starting directory. Defaults to the directory containing the running file.
51
+ # @return [String, nil] the absolute path to the pathfile (if it exists), otherwise +nil+.
52
+ def self.find_pathfile(directory = nil)
53
+ # If we're in IRB, use the working directory as the root of the search path for the Pathfile.
54
+ if $0 != __FILE__ && $0 == "irb"
55
+ directory = Dir.pwd
56
+ debug "In IRB -- using the cwd (#{directory}) as the search root for Pathfile."
57
+ end
58
+ return nil if directory && !File.directory?(directory)
59
+ # Find the full, absolute path of this directory, resolving symlinks. If no directory was given, use the
60
+ # directory where the executed file resides.
61
+ full_path = real_path(directory || $0)
62
+ current_path = directory ? full_path : File.dirname(full_path)
63
+ loop do
64
+ debug "Searching <#{current_path}> for Pathfile."
65
+ pathfile = File.join(current_path, PATHFILE_NAME)
66
+ if File.file? pathfile
67
+ debug "Pathfile found: <#{pathfile}>."
68
+ return pathfile
69
+ end
70
+ new_path = File.dirname current_path
71
+ if new_path == current_path
72
+ debug "Reached filesystem root, but no Pathfile found."
73
+ return nil
74
+ end
75
+ current_path = new_path
76
+ end
77
+ end
78
+
79
+ # Find all loaded ruby files that come from directories added to the load path by Pathological. This is only
80
+ # available in Ruby 1.9 due to the behavior of +$"+. This method works in a "best guess" fashion by
81
+ # determining the +$LOAD_PATH+ entry to which loaded file corresponds.
82
+ #
83
+ # @return [Array<String>] the array of paths
84
+ def self.find_loaded_files
85
+ unless RUBY_VERSION =~ /^1\.9/
86
+ raise PathologicalException, "#find_loaded_files is only available in Ruby 1.9."
87
+ end
88
+ $".select { |file| @@loaded_paths.any? { ... } }
89
+ end
90
+
91
+ # Convenience functions for the various modes in which Pathological may run.
92
+
93
+ def self.debug_mode; @@debug = true; end
94
+ def self.bundlerize_mode
95
+ pathfile = Pathological.find_pathfile
96
+ raise NoPathfileException unless pathfile
97
+ bundle_gemfile = File.join(File.dirname(pathfile), "Gemfile")
98
+ unless File.file? bundle_gemfile
99
+ raise PathologicalException, "No Gemfile found in #{File.dirname(pathfile)}."
100
+ end
101
+ ENV["BUNDLE_GEMFILE"] = bundle_gemfile
102
+ end
103
+ def self.parentdir_mode; @@add_parents = true; end
104
+ def self.noexceptions_mode; @@no_exceptions = true; end
105
+ def self.excluderoot_mode; @@exclude_root = true; end
106
+
107
+ # Reset all Pathological options (useful if you want to require a different Pathfile)
108
+ def self.reset!
109
+ # Debug mode -- print out information about load paths
110
+ @@debug = false
111
+ # Parentdir mode -- add unique parents of specified directories.
112
+ @@add_parents = false
113
+ # Noexceptions mode -- don't raise exceptions if the Pathfile contains bad paths
114
+ @@no_exceptions = false
115
+ # Excluderoot mode -- don't add the project root (where the Pathfile lives) to the load path
116
+ @@exclude_root = false
117
+
118
+ @@loaded_paths ||= []
119
+ @@loaded_paths.each { |path| $LOAD_PATH.delete path }
120
+ @@loaded_paths = []
121
+ end
122
+
123
+ # private module methods
124
+
125
+ # Print debugging info
126
+ #
127
+ # @private
128
+ # @param [String] message the debugging message
129
+ # @return [void]
130
+ def self.debug(message); puts "[Pathological Debug] >> #{message}" if @@debug; end
131
+
132
+ # Turn a path into an absolute path with no useless parts and no symlinks.
133
+ #
134
+ # @private
135
+ # @param [String] the path
136
+ # @return [String] the absolute real path
137
+ def self.real_path(path); Pathname.new(path).realpath.to_s; end
138
+
139
+ # Parse a pathfile and return the appropriate paths.
140
+ #
141
+ # @private
142
+ # @param [IO] pathfile handle to the pathfile to parse
143
+ # @return [Array<String>] array of paths found
144
+ def self.parse_pathfile(pathfile)
145
+ root = File.dirname(real_path(pathfile.path))
146
+ raw_paths = [root]
147
+ pathfile.each do |line|
148
+ # Trim comments
149
+ line = line.split(/#/, 2)[0].strip
150
+ next if line.empty?
151
+ raw_path = File.expand_path(File.join(root, line.strip))
152
+ raw_paths << (@@add_parents ? File.dirname(raw_path) : raw_path)
153
+ end
154
+
155
+ paths = []
156
+ raw_paths.each do |path|
157
+ unless File.directory? path
158
+ unless @@no_exceptions
159
+ raise PathologicalException, "Bad path in Pathfile: #{path}"
160
+ end
161
+ debug "Ignoring non-existent path: #{path}"
162
+ next
163
+ end
164
+ next if @@exclude_root && File.expand_path(path) == File.expand_path(root)
165
+ paths << path
166
+ end
167
+ @@exclude_root ? paths.reject { |path| File.expand_path(path) == File.expand_path(root) } : paths
168
+ end
169
+
170
+ # Determine whether a path is a (strict) descendent of another path
171
+ #
172
+ # @private
173
+ # @param [String] ancestor_path the path of the prospective ancestor
174
+ # @param [String] descendent_path the path of the prospective descendent
175
+ # @return [Boolean] whether descendent_path is some strict descendent of ancestor_path
176
+ def self.is_descendent?(ancestor_path, descendent_path)
177
+ # Delete trailing slash to match File#dirname
178
+ ancestor_path = ancestor_path[0..-2] if ancestor_path.size > 1 && ancestor_path.end_with? "/"
179
+ current_path = File.dirname(descendent_path)
180
+ previous_path = nil
181
+ until current_path == previous_path
182
+ return true if current_path == ancestor_path
183
+ previous_path, current_path = current_path, File.dirname(current_path)
184
+ end
185
+ false
186
+ end
187
+
188
+ private_class_method :debug, :real_path, :parse_pathfile
189
+
190
+ # Reset options
191
+ Pathological.reset!
192
+ end
@@ -0,0 +1,9 @@
1
+ # Make bundler compatible with Pathological (that is, enable Bundler projects to be run from anywhere as
2
+ # Pathological allows) by setting the BUNDLE_GEMFILE env variable.
3
+ #
4
+ # To use this, you *must* require pathological/bundlerize before you require bundler/setup.
5
+
6
+ require "pathological/base"
7
+
8
+ Pathological.bundlerize_mode
9
+ Pathological.add_paths!
@@ -0,0 +1,4 @@
1
+ require "pathological/base"
2
+
3
+ Pathological.debug_mode
4
+ Pathological.add_paths!
@@ -0,0 +1,4 @@
1
+ require "pathological/base"
2
+
3
+ Pathological.excluderoot_mode
4
+ Pathological.add_paths!
@@ -0,0 +1,4 @@
1
+ require "pathological/base"
2
+
3
+ Pathological.noexceptions_mode
4
+ Pathological.add_paths!
@@ -0,0 +1,8 @@
1
+ # In parentdir mode, Pathological will not add the individual specified paths to $LOAD_PATH, but will instead
2
+ # add the unique parents of the specified paths. This is to enable compatibility with legacy code where
3
+ # require paths are all written relative to a common repository root.
4
+
5
+ require "pathological/base"
6
+
7
+ Pathological.parentdir_mode
8
+ Pathological.add_paths!
@@ -0,0 +1,3 @@
1
+ module Pathological
2
+ VERSION = "0.2.1"
3
+ end
@@ -0,0 +1,33 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.unshift File.expand_path("../lib", __FILE__)
3
+ require "pathological/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "pathological"
7
+ s.version = Pathological::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">=0") if s.respond_to? :required_rubygems_version=
11
+ s.specification_version = 2 if s.respond_to? :specification_version=
12
+
13
+ s.authors = "Daniel MacDougall", "Caleb Spare"
14
+ s.email = "dmac@ooyala.com", "caleb@ooyala.com"
15
+ s.homepage = "http://www.ooyala.com"
16
+ s.rubyforge_project = "pathological"
17
+
18
+ s.summary = "A nice way to manage your project's require paths."
19
+ s.description = <<-DESCRIPTION
20
+ Pathological provides a way to manage a project's require paths by using a small config file that
21
+ indicates all directories to include in the load path.
22
+ DESCRIPTION
23
+
24
+ s.files = `git ls-files`.split("\n").reject { |f| f == ".gitignore" }
25
+ s.require_paths = ["lib"]
26
+
27
+ # Require rr >= 1.0.3 and scope >= 0.2.3 for mutual compatibility.
28
+ s.add_development_dependency "rr", ">= 1.0.3"
29
+ s.add_development_dependency "scope", ">= 0.2.3"
30
+ s.add_development_dependency "yard", "~> 0.7.2"
31
+ s.add_development_dependency "rdiscount", "~> 1.6.8"
32
+ s.add_development_dependency "fakefs"
33
+ end
@@ -0,0 +1,180 @@
1
+ require "rubygems"
2
+ require "scope"
3
+ require "rr"
4
+ require "minitest/autorun"
5
+ require "stringio"
6
+ require "fakefs/safe"
7
+
8
+ # It's kind of funny that we need to do this hack, given that Pathological is intended to work around it...
9
+ $:.unshift(File.join(File.dirname(__FILE__), "../../lib"))
10
+ require "pathological/base"
11
+
12
+ module Pathological
13
+ class BaseTest < Scope::TestCase
14
+ include RR::Adapters::MiniTest
15
+ def assert_load_path(expected_load_path)
16
+ assert_equal expected_load_path.uniq.sort, @load_path.uniq.sort
17
+ end
18
+
19
+ context "Pathological" do
20
+ setup_once { FakeFS.activate! }
21
+ setup do
22
+ Pathological.reset!
23
+ @load_path = []
24
+ FakeFS::FileSystem.clear
25
+ # FakeFS has not implemented the necessary calls for Pathname#realpath to work.
26
+ stub(Pathological).real_path(anything) { |p| p }
27
+ end
28
+ teardown_once { FakeFS.deactivate! }
29
+
30
+ context "#add_paths!" do
31
+ should "not raise an error but print a warning when there's no pathfile" do
32
+ mock(Pathological).find_pathfile { nil }
33
+ mock(STDERR).puts(anything) { |m| assert_match /^Warning/, m }
34
+ Pathological.add_paths! @load_path
35
+ assert_load_path []
36
+ end
37
+
38
+ should "append the requested paths" do
39
+ paths = ["foo"]
40
+ Pathological.add_paths! @load_path, paths
41
+ assert_load_path paths
42
+ end
43
+
44
+ should "append the paths that #find_load_paths finds" do
45
+ paths = ["foo"]
46
+ mock(Pathological).find_load_paths { paths }
47
+ Pathological.add_paths! @load_path
48
+ assert_load_path paths
49
+ end
50
+ end
51
+
52
+ context "#find_load_paths" do
53
+ should "raise a NoPathfileException on a nil pathfile" do
54
+ mock(Pathological).find_pathfile { nil }
55
+ assert_raises(NoPathfileException) { Pathological.find_load_paths(nil) }
56
+ end
57
+
58
+ should "use #find_pathfile to find the Pathfile and #parse_pathfile to parse it." do
59
+ paths = ["path1"]
60
+ mock(Pathological).find_pathfile { "foo" }
61
+ mock(File).open("foo") { "bar" }
62
+ mock(Pathological).parse_pathfile("bar") { paths }
63
+ assert_equal paths, Pathological.find_load_paths
64
+ end
65
+ end
66
+
67
+ context "#find_pathfile" do
68
+ setup do
69
+ @working_directory = "/foo/bar/baz"
70
+ FileUtils.mkdir_p @working_directory
71
+ FileUtils.cd @working_directory
72
+ end
73
+
74
+ should "find a pathfile in this directory" do
75
+ pathfile = "/foo/bar/baz/Pathfile"
76
+ FileUtils.touch pathfile
77
+ assert_equal pathfile, Pathological.find_pathfile(@working_directory)
78
+ end
79
+
80
+ should "find a pathfile in a parent directory" do
81
+ pathfile = "/foo/bar/Pathfile"
82
+ FileUtils.touch pathfile
83
+ assert_equal pathfile, Pathological.find_pathfile(@working_directory)
84
+ end
85
+
86
+ should "find a pathfile at the root" do
87
+ pathfile = "/Pathfile"
88
+ FileUtils.touch pathfile
89
+ assert_equal pathfile, Pathological.find_pathfile(@working_directory)
90
+ end
91
+
92
+ should "locate a pathfile in the real path even if we're running from a symlinked directory" do
93
+ pathfile = "/foo/bar/baz/Pathfile"
94
+ FileUtils.touch pathfile
95
+ FileUtils.touch "/Pathfile" # Shouldn't find this one
96
+ symlinked_directory = "/foo/bar/quux"
97
+ FileUtils.ln_s @working_directory, symlinked_directory
98
+ stub(Pathological).real_path(anything) { |path| path.gsub("quux", "baz") }
99
+ assert_equal pathfile, Pathological.find_pathfile(@working_directory)
100
+ end
101
+ end
102
+
103
+ context "loading pathological" do
104
+ setup do
105
+ @pathfile_contents = ""
106
+ @pathfile = "/Pathfile"
107
+ $0 = "/my_file"
108
+ FileUtils.touch @pathfile
109
+ FileUtils.cd "/"
110
+ end
111
+
112
+ # Load in pathfile contents and load Pathological
113
+ def load_and_run!
114
+ File.open(@pathfile, "w") { |f| f.write(@pathfile_contents) }
115
+ Pathological.add_paths!(@load_path)
116
+ end
117
+
118
+ should "use an empty Pathfile correctly" do
119
+ load_and_run!
120
+ assert_load_path ["/"]
121
+ end
122
+
123
+ should "add some paths as appropriate" do
124
+ paths = ["/foo/bar", "/baz"]
125
+ paths.each do |path|
126
+ FileUtils.mkdir_p path
127
+ @pathfile_contents << "#{path}\n"
128
+ end
129
+ load_and_run!
130
+ assert_load_path(paths << "/")
131
+ end
132
+
133
+ should "throw exceptions on bad load paths" do
134
+ path = "/foo/bar"
135
+ @pathfile_contents << "#{path}"
136
+ assert_raises(PathologicalException) { load_and_run! }
137
+ end
138
+
139
+ should "print some debug info in debug mode" do
140
+ Pathological.debug_mode
141
+ mock(Pathological).puts(anything).at_least(3)
142
+ Pathological.add_paths!
143
+ end
144
+
145
+ should "set $BUNDLE_GEMFILE correctly in bundlerize mode" do
146
+ FileUtils.touch "/Gemfile"
147
+ Pathological.bundlerize_mode
148
+ Pathological.add_paths!
149
+ assert_equal "/Gemfile", ENV["BUNDLE_GEMFILE"]
150
+ end
151
+
152
+ should "add the correct directories in parentdir mode" do
153
+ paths = ["/foo/bar/baz1", "/foo/bar/baz2", "/foo/quux"]
154
+ paths.each { |path| FileUtils.mkdir_p path }
155
+ @pathfile_contents = paths.join("\n")
156
+ Pathological.parentdir_mode
157
+ load_and_run!
158
+ assert_load_path ["/", "/foo/bar", "/foo"]
159
+ end
160
+
161
+ should "not raise exceptions on bad paths in noexceptions mode" do
162
+ path = "/foo/bar"
163
+ @pathfile_contents << path
164
+ Pathological.noexceptions_mode
165
+ load_and_run!
166
+ assert_load_path ["/"]
167
+ end
168
+
169
+ should "not add the project root in excluderoot mode" do
170
+ path = "/foo/bar"
171
+ FileUtils.mkdir_p path
172
+ @pathfile_contents << path
173
+ Pathological.excluderoot_mode
174
+ load_and_run!
175
+ assert_load_path ["/foo/bar"]
176
+ end
177
+ end
178
+ end
179
+ end
180
+ end
@@ -0,0 +1,10 @@
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") }
metadata ADDED
@@ -0,0 +1,123 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: pathological
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Daniel MacDougall
9
+ - Caleb Spare
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2011-09-09 00:00:00.000000000Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: rr
17
+ requirement: &70277329396620 !ruby/object:Gem::Requirement
18
+ none: false
19
+ requirements:
20
+ - - ! '>='
21
+ - !ruby/object:Gem::Version
22
+ version: 1.0.3
23
+ type: :development
24
+ prerelease: false
25
+ version_requirements: *70277329396620
26
+ - !ruby/object:Gem::Dependency
27
+ name: scope
28
+ requirement: &70277329396080 !ruby/object:Gem::Requirement
29
+ none: false
30
+ requirements:
31
+ - - ! '>='
32
+ - !ruby/object:Gem::Version
33
+ version: 0.2.3
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: *70277329396080
37
+ - !ruby/object:Gem::Dependency
38
+ name: yard
39
+ requirement: &70277329395580 !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ~>
43
+ - !ruby/object:Gem::Version
44
+ version: 0.7.2
45
+ type: :development
46
+ prerelease: false
47
+ version_requirements: *70277329395580
48
+ - !ruby/object:Gem::Dependency
49
+ name: rdiscount
50
+ requirement: &70277329395080 !ruby/object:Gem::Requirement
51
+ none: false
52
+ requirements:
53
+ - - ~>
54
+ - !ruby/object:Gem::Version
55
+ version: 1.6.8
56
+ type: :development
57
+ prerelease: false
58
+ version_requirements: *70277329395080
59
+ - !ruby/object:Gem::Dependency
60
+ name: fakefs
61
+ requirement: &70277329394700 !ruby/object:Gem::Requirement
62
+ none: false
63
+ requirements:
64
+ - - ! '>='
65
+ - !ruby/object:Gem::Version
66
+ version: '0'
67
+ type: :development
68
+ prerelease: false
69
+ version_requirements: *70277329394700
70
+ description: ! " Pathological provides a way to manage a project's require paths
71
+ by using a small config file that\n indicates all directories to include in the
72
+ load path.\n"
73
+ email:
74
+ - dmac@ooyala.com
75
+ - caleb@ooyala.com
76
+ executables: []
77
+ extensions: []
78
+ extra_rdoc_files: []
79
+ files:
80
+ - .rvmrc
81
+ - .yardopts
82
+ - Gemfile
83
+ - Gemfile.lock
84
+ - LICENSE
85
+ - README.md
86
+ - Rakefile
87
+ - TODO.md
88
+ - lib/pathological.rb
89
+ - lib/pathological/base.rb
90
+ - lib/pathological/bundlerize.rb
91
+ - lib/pathological/debug.rb
92
+ - lib/pathological/excluderoot.rb
93
+ - lib/pathological/noexceptions.rb
94
+ - lib/pathological/parentdir.rb
95
+ - lib/pathological/version.rb
96
+ - pathological.gemspec
97
+ - test/pathological/base_test.rb
98
+ - test/unit.watchr.rb
99
+ homepage: http://www.ooyala.com
100
+ licenses: []
101
+ post_install_message:
102
+ rdoc_options: []
103
+ require_paths:
104
+ - lib
105
+ required_ruby_version: !ruby/object:Gem::Requirement
106
+ none: false
107
+ requirements:
108
+ - - ! '>='
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ required_rubygems_version: !ruby/object:Gem::Requirement
112
+ none: false
113
+ requirements:
114
+ - - ! '>='
115
+ - !ruby/object:Gem::Version
116
+ version: '0'
117
+ requirements: []
118
+ rubyforge_project: pathological
119
+ rubygems_version: 1.8.7
120
+ signing_key:
121
+ specification_version: 2
122
+ summary: A nice way to manage your project's require paths.
123
+ test_files: []