pathological 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
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: []