library 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.ruby +57 -0
- data/.yardopts +6 -0
- data/COPYING.rdoc +30 -0
- data/HISTORY.rdoc +13 -0
- data/README.md +177 -0
- data/lib/library.rb +532 -0
- data/lib/library/autoload.rb +14 -0
- data/lib/library/core_ext.rb +34 -0
- data/lib/library/domain.rb +244 -0
- data/lib/library/errors.rb +49 -0
- data/lib/library/feature.rb +207 -0
- data/lib/library/kernel.rb +81 -0
- data/lib/library/ledger.rb +642 -0
- data/lib/library/metadata.rb +398 -0
- data/lib/library/rbconfig.rb +65 -0
- data/lib/library/rubygems.rb +19 -0
- data/lib/library/rubylib.rb +206 -0
- data/lib/library/version.rb +387 -0
- data/lib/ubylibs.rb +8 -0
- data/qed/01_loading.rdoc +14 -0
- data/qed/02_library.rdoc +55 -0
- data/qed/03_ledger.rdoc +30 -0
- data/qed/04_version.rdoc +101 -0
- data/qed/applique/check.rb +11 -0
- data/qed/applique/project.rb +34 -0
- data/qed/fixtures/foo/.ruby +5 -0
- data/qed/fixtures/foo/lib/foo.rb +1 -0
- data/qed/fixtures/tryme/1.0/.ruby +6 -0
- data/qed/fixtures/tryme/1.0/lib/tryme.rb +1 -0
- data/qed/fixtures/tryme/1.1/.ruby +7 -0
- data/qed/fixtures/tryme/1.1/lib/tryme.rb +1 -0
- data/qed/helpers/new_project.rdoc +29 -0
- data/qed/helpers/projects.rdoc +56 -0
- data/test/case_ledger.rb +23 -0
- data/test/case_library.rb +13 -0
- data/test/case_version.rb +89 -0
- data/test/fixture/.ruby +56 -0
- data/test/fixture/lib/foo.rb +7 -0
- data/test/helper.rb +2 -0
- metadata +144 -0
data/.ruby
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
---
|
2
|
+
source:
|
3
|
+
- var
|
4
|
+
authors:
|
5
|
+
- name: trans
|
6
|
+
email: transfire@gmail.com
|
7
|
+
copyrights:
|
8
|
+
- holder: Rubyworks
|
9
|
+
year: '2006'
|
10
|
+
license: BSD-2-Clause
|
11
|
+
replacements: []
|
12
|
+
alternatives: []
|
13
|
+
requirements:
|
14
|
+
- name: detroit
|
15
|
+
groups:
|
16
|
+
- build
|
17
|
+
development: true
|
18
|
+
- name: setup
|
19
|
+
version: 5.0+
|
20
|
+
groups:
|
21
|
+
- build
|
22
|
+
development: true
|
23
|
+
- name: rubytest
|
24
|
+
groups:
|
25
|
+
- test
|
26
|
+
development: true
|
27
|
+
- name: lemon
|
28
|
+
groups:
|
29
|
+
- test
|
30
|
+
development: true
|
31
|
+
- name: ae
|
32
|
+
groups:
|
33
|
+
- test
|
34
|
+
development: true
|
35
|
+
dependencies: []
|
36
|
+
conflicts: []
|
37
|
+
repositories:
|
38
|
+
- uri: git://github.com/rubyworks/library.git
|
39
|
+
scm: git
|
40
|
+
name: upstream
|
41
|
+
resources:
|
42
|
+
home: http://rubyworks.github.com/library
|
43
|
+
code: http://github.com/rubyworks/library
|
44
|
+
mail: http://groups.google.com/groups/rubyworks-mailinglist
|
45
|
+
extra: {}
|
46
|
+
load_path:
|
47
|
+
- lib
|
48
|
+
revision: 0
|
49
|
+
created: '2006-12-10'
|
50
|
+
summary: Objectifying the Ruby Library
|
51
|
+
title: Library
|
52
|
+
version: 0.1.0
|
53
|
+
name: library
|
54
|
+
description: ! "The Library class encapsulates the essential nature \nof a Ruby library
|
55
|
+
--a location on disk from which\nscripts can be required."
|
56
|
+
organization: rubyworks
|
57
|
+
date: '2012-01-10'
|
data/.yardopts
ADDED
data/COPYING.rdoc
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
= COPYRIGHT NOTICES
|
2
|
+
|
3
|
+
== Library
|
4
|
+
|
5
|
+
Copyright:: (c) 2006 Rubyworks
|
6
|
+
License:: BSD-2-Clause
|
7
|
+
Website:: http://rubyworks.github.com/library
|
8
|
+
|
9
|
+
Copyright (c) 2006 Rubyworks. All rights reserved.
|
10
|
+
|
11
|
+
Redistribution and use in source and binary forms, with or without modification, are
|
12
|
+
permitted provided that the following conditions are met:
|
13
|
+
|
14
|
+
1. Redistributions of source code must retain the above copyright notice, this list of
|
15
|
+
conditions and the following disclaimer.
|
16
|
+
|
17
|
+
2. Redistributions in binary form must reproduce the above copyright notice, this list
|
18
|
+
of conditions and the following disclaimer in the documentation and/or other materials
|
19
|
+
provided with the distribution.
|
20
|
+
|
21
|
+
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
|
22
|
+
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
23
|
+
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
|
24
|
+
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
25
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
26
|
+
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
27
|
+
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
28
|
+
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
29
|
+
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
30
|
+
|
data/HISTORY.rdoc
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
= RELEASE HISTORY
|
2
|
+
|
3
|
+
== 0.1.0 / 2012-01-10
|
4
|
+
|
5
|
+
The Library gem is a spin-off of the Rolls gem. The Library class
|
6
|
+
is at the heart of Rolls, but is well defined enough to stand on its
|
7
|
+
own as a separate supporting package. By having it as a separate
|
8
|
+
project it becomes easier to focus on it's essential functionality.
|
9
|
+
|
10
|
+
Changes:
|
11
|
+
|
12
|
+
* Spin-off from Rolls and release.
|
13
|
+
|
data/README.md
ADDED
@@ -0,0 +1,177 @@
|
|
1
|
+
# RUBY LIBRARY
|
2
|
+
|
3
|
+
<img src="" />
|
4
|
+
|
5
|
+
[home](http://rubyworks.github.com/library) /
|
6
|
+
[code](http://github.com/rubyworks/library)
|
7
|
+
|
8
|
+
|
9
|
+
## DESCRIPTION
|
10
|
+
|
11
|
+
Library is, as its name implies, the objectification of the Ruby library.
|
12
|
+
Along with the Library Ledger, which keeps an indexed list of available
|
13
|
+
libraries, a variety of useful features are bestowed to Ruby developers.
|
14
|
+
|
15
|
+
* Work with libraries in an object-oriented manner.
|
16
|
+
* Develop interdependent projects in real time without installing, linking or vendoring.
|
17
|
+
* Create isolated library environments based on project requirements.
|
18
|
+
* Libraries can be stored anywhere. There is no special "home" path they must reside.
|
19
|
+
* Serve gem installed libraries as easily as it serves developer's libraries.
|
20
|
+
* Is the foundation of the Rolls gem, which provides a superset of library management functions.
|
21
|
+
|
22
|
+
IMPORTANT: Presently gem installed packages can only be served if a `.ruby` file
|
23
|
+
is part of the gem package. This should be fixed in the next release. To work
|
24
|
+
around the `dotruby` gem can be used to generate a `.ruby` file for installed
|
25
|
+
gems.
|
26
|
+
|
27
|
+
|
28
|
+
## USAGE
|
29
|
+
|
30
|
+
### Using the API
|
31
|
+
|
32
|
+
The basics of the Library API are fairly simple. Given a location on disc
|
33
|
+
that houses a Ruby library, e.g. `projects/hello`, a new Library instance
|
34
|
+
can be created like any other object.
|
35
|
+
|
36
|
+
mylib = Library.new('projects/hello')
|
37
|
+
|
38
|
+
With a library object in hand, we can require or load files from that library.
|
39
|
+
|
40
|
+
mylib.require 'world'
|
41
|
+
|
42
|
+
Or look at information about the library.
|
43
|
+
|
44
|
+
mylib.name #=> 'hello'
|
45
|
+
mylib.version #=> '1.0.0'
|
46
|
+
|
47
|
+
Crating a library object via`#new` gives us a one-off object. But to persist
|
48
|
+
the library and make it available by name we can use `#add` instead.
|
49
|
+
|
50
|
+
Library.add('projects/hello')
|
51
|
+
|
52
|
+
Or, delving down a bit deeper into the belly of system, one could simply
|
53
|
+
feed the path to the master Ledger instance.
|
54
|
+
|
55
|
+
$LEDGER << 'projects/hello'
|
56
|
+
|
57
|
+
Both have the same exact effect. Our library will then be available via
|
58
|
+
Library's various look-up methods. There are a few of these. One of these is
|
59
|
+
the Kernel method `#library`.
|
60
|
+
|
61
|
+
library('hello')
|
62
|
+
|
63
|
+
Another is `#[]` class method.
|
64
|
+
|
65
|
+
Library['hello']
|
66
|
+
|
67
|
+
There are many other useful Library methods, see the API documentation
|
68
|
+
for more details.
|
69
|
+
|
70
|
+
### Using RUBYLIBS
|
71
|
+
|
72
|
+
To use Library on a regular basis, add library paths to the `RUBYLIBS`
|
73
|
+
environment variable. (NOTICE It is plural!!!)
|
74
|
+
|
75
|
+
export RUBYLIBS="~/workspace/ruby-projects"
|
76
|
+
|
77
|
+
And add `-rubylibs` to the RUBYOPT environment variable.
|
78
|
+
|
79
|
+
export RUBYOPT="-rubylibs"
|
80
|
+
|
81
|
+
You might already have `-rubygems` there, which is fine too.
|
82
|
+
|
83
|
+
export RUBYOPT="-rubylibs -rubygems"
|
84
|
+
|
85
|
+
If you want access to project executables you will also need to append the
|
86
|
+
project `bin` locations to the PATH environment variable.
|
87
|
+
|
88
|
+
export PATH="$PATH:$(ruby -e'Library::PATH()')"
|
89
|
+
|
90
|
+
This will add the `bin` locations of the programs encompassed by your
|
91
|
+
current `RUBYLIBS` setting.
|
92
|
+
|
93
|
+
Of course, you will probably want to add these lines to your startup `.bashrc`
|
94
|
+
file (or equivalent) so they are ready to go every time you bring up your
|
95
|
+
shell console.
|
96
|
+
|
97
|
+
### Preping Projects
|
98
|
+
|
99
|
+
For a project to be usable via Library it must conform to common organizational
|
100
|
+
conventions for a Ruby project and it should have a `.ruby` file.
|
101
|
+
|
102
|
+
It is highly recommend that a project have a `.ruby` file although a `.gemspec`
|
103
|
+
file can serve as a fallback if a `.ruby` file isn't found. But relying on a
|
104
|
+
`.gemspec` is going to slow things down a fair bit. It also requires that
|
105
|
+
the `dotruby` library be installed.
|
106
|
+
|
107
|
+
To activate .gemspec support set the environment variable `RUBYLIBS_GEMSPEC=true`.
|
108
|
+
|
109
|
+
See http://dotruby.github.com/dotruby for more information about `.ruby` files.
|
110
|
+
|
111
|
+
|
112
|
+
### Autoload Caveat
|
113
|
+
|
114
|
+
Ruby has a "bug" which prevents `#autoload` from using custom `#require`
|
115
|
+
methods. So `#autoload` calls cannot make use of the Library setup.
|
116
|
+
This is not as significant as it might seem since `#autoload` is being
|
117
|
+
deprecated as of Ruby 2.0. So it is best to discontinue it's use anyway.
|
118
|
+
|
119
|
+
|
120
|
+
## LEARNING MORE
|
121
|
+
|
122
|
+
The above provides a brief overview of using the Library gem. But there is
|
123
|
+
more to it. To get a deeper understanding of the system its fullest extent,
|
124
|
+
please visit http://rubyworks.github.org/library.
|
125
|
+
|
126
|
+
|
127
|
+
## INSTALLATION
|
128
|
+
|
129
|
+
### RubyGems Installation
|
130
|
+
|
131
|
+
We strongly recommend installing Roller manually b/c Roller is a
|
132
|
+
peer to RubyGems. However, the last we tested it, Roller could
|
133
|
+
be install via Gems as a means of trying it out --though you won't
|
134
|
+
get the full benefits of the system.
|
135
|
+
|
136
|
+
$ gem install library
|
137
|
+
|
138
|
+
If you like Roller, then later you can uninstall the gem and
|
139
|
+
do a proper manual install.
|
140
|
+
|
141
|
+
|
142
|
+
### Manual Installation
|
143
|
+
|
144
|
+
Manual installation is recommended for regular usage, since it
|
145
|
+
can then be loaded without going through RubyGems.
|
146
|
+
|
147
|
+
First you need a copy of the tarball (or zip) archive. You will
|
148
|
+
find them [here](http://github.com/rubyworks/library/download).
|
149
|
+
You will of course need to unpack the file. For example,
|
150
|
+
|
151
|
+
$ tar -xvzf library-0.1.0
|
152
|
+
|
153
|
+
If you already have Ruby Setup installed on your system you can
|
154
|
+
use it to install (See: http://rubyworks.github.com/setup).
|
155
|
+
|
156
|
+
$ cd library-0.1.0
|
157
|
+
$ sudo setup.rb
|
158
|
+
|
159
|
+
Otherwise, the package includes a copy of Ruby Setup that you can
|
160
|
+
use.
|
161
|
+
|
162
|
+
$ cd library-0.1.0
|
163
|
+
$ sudo script/setup.
|
164
|
+
|
165
|
+
On Windows, this last line will need to be 'ruby script/setup'.
|
166
|
+
|
167
|
+
|
168
|
+
## COPYRIGHTS
|
169
|
+
|
170
|
+
Ruby Library
|
171
|
+
|
172
|
+
Copyright (c) 2006 Rubyworks
|
173
|
+
|
174
|
+
Ruby Library is distributable in accordance with the **FreeBSD** license.
|
175
|
+
|
176
|
+
See the COPYING.rdoc file details.
|
177
|
+
|
data/lib/library.rb
ADDED
@@ -0,0 +1,532 @@
|
|
1
|
+
require 'library/core_ext'
|
2
|
+
require 'library/ledger'
|
3
|
+
require 'library/errors'
|
4
|
+
require 'library/metadata'
|
5
|
+
require 'library/feature'
|
6
|
+
require 'library/version'
|
7
|
+
require 'library/domain'
|
8
|
+
|
9
|
+
# Library class encapsulates a location on disc that contains a Ruby
|
10
|
+
# project, with loadable features, of course.
|
11
|
+
#
|
12
|
+
class Library
|
13
|
+
|
14
|
+
#
|
15
|
+
# Library ledger.
|
16
|
+
#
|
17
|
+
$LEDGER = Ledger.new
|
18
|
+
|
19
|
+
#
|
20
|
+
# When loading files, the current library doing the loading is pushed
|
21
|
+
# on this stack, and then popped-off when it is finished.
|
22
|
+
#
|
23
|
+
$LOAD_STACK = []
|
24
|
+
|
25
|
+
#
|
26
|
+
#
|
27
|
+
#
|
28
|
+
$LOAD_CACHE = {}
|
29
|
+
|
30
|
+
# Dynamic link extension.
|
31
|
+
#DLEXT = '.' + ::RbConfig::CONFIG['DLEXT']
|
32
|
+
|
33
|
+
# TODO: Some extensions are platform specific --only add the ones needed
|
34
|
+
# for the current platform to SUFFIXES.
|
35
|
+
|
36
|
+
#
|
37
|
+
# Possible suffixes for feature files, that #require will try automatically.
|
38
|
+
#
|
39
|
+
SUFFIXES = ['.rb', '.rbw', '.so', '.bundle', '.dll', '.sl', '.jar'] #, '']
|
40
|
+
|
41
|
+
#
|
42
|
+
# Extensions glob, joins extensions with comma and wrap in curly brackets.
|
43
|
+
#
|
44
|
+
SUFFIX_PATTERN = "{#{SUFFIXES.join(',')}}"
|
45
|
+
|
46
|
+
#
|
47
|
+
# A shortcut for #instance.
|
48
|
+
#
|
49
|
+
# @return [Library,NilClass] The activated Library instance, or `nil` if not found.
|
50
|
+
#
|
51
|
+
def self.[](name, constraint=nil)
|
52
|
+
$LEDGER.activate(name, constraint) if $LEDGER.key?(name)
|
53
|
+
end
|
54
|
+
|
55
|
+
#
|
56
|
+
# Get an instance of a library by name, or name and version.
|
57
|
+
# Libraries are singleton, so once loaded the same object is
|
58
|
+
# always returned.
|
59
|
+
#
|
60
|
+
# @todo This method might be deprecated.
|
61
|
+
#
|
62
|
+
# @return [Library,NilClass] The activated Library instance, or `nil` if not found.
|
63
|
+
#
|
64
|
+
def self.instance(name, constraint=nil)
|
65
|
+
$LEDGER.activate(name, constraint) if $LEDGER.key?(name)
|
66
|
+
end
|
67
|
+
|
68
|
+
#
|
69
|
+
# Activate a library. Same as #instance but will raise and error if the
|
70
|
+
# library is not found. This can also take a block to yield on the library.
|
71
|
+
#
|
72
|
+
# @param [String] name
|
73
|
+
# Name of library.
|
74
|
+
#
|
75
|
+
# @param [String] constraint
|
76
|
+
# Valid version constraint.
|
77
|
+
#
|
78
|
+
# @raise [LoadError]
|
79
|
+
# If library not found.
|
80
|
+
#
|
81
|
+
# @return [Library]
|
82
|
+
# The activated Library object.
|
83
|
+
#
|
84
|
+
def self.activate(name, constraint=nil) #:yield:
|
85
|
+
library = $LEDGER.activate(name, constraint)
|
86
|
+
yield(library) if block_given?
|
87
|
+
library
|
88
|
+
end
|
89
|
+
|
90
|
+
#
|
91
|
+
# Like `#new`, but adds library to library ledger.
|
92
|
+
#
|
93
|
+
# @todo Better name for this method?
|
94
|
+
#
|
95
|
+
# @return [Library] The new library.
|
96
|
+
#
|
97
|
+
def self.add(location)
|
98
|
+
$LEDGER.add_location(location)
|
99
|
+
|
100
|
+
#library = new(location)
|
101
|
+
#$LEDGER.add_library(library)
|
102
|
+
#library
|
103
|
+
end
|
104
|
+
|
105
|
+
#
|
106
|
+
# New Library object.
|
107
|
+
#
|
108
|
+
# If data is given it must have `:name` and `:version`. It can
|
109
|
+
# also have `:loadpath`, `:date`, and `:omit`.
|
110
|
+
#
|
111
|
+
# @param location [String]
|
112
|
+
# Expanded file path to library's root directory.
|
113
|
+
#
|
114
|
+
# @param metadata [Hash]
|
115
|
+
# Overriding matadata (to circumvent loading it from `.ruby` file).
|
116
|
+
#
|
117
|
+
def initialize(location, metadata={})
|
118
|
+
raise TypeError, "not a directory - #{location}" unless File.directory?(location)
|
119
|
+
|
120
|
+
@location = location
|
121
|
+
@metadata = Metadata.new(location, metadata)
|
122
|
+
|
123
|
+
raise ValidationError, "Non-conforming library (missing name) -- `#{location}'" unless name
|
124
|
+
raise ValidationError, "Non-conforming library (missing version) -- `#{location}'" unless version
|
125
|
+
end
|
126
|
+
|
127
|
+
#
|
128
|
+
# Activate a library.
|
129
|
+
#
|
130
|
+
# @return [true,false] Has the library has been activated?
|
131
|
+
#
|
132
|
+
def activate
|
133
|
+
current = $LEDGER[name]
|
134
|
+
|
135
|
+
if Library === current
|
136
|
+
raise VersionConflict.new(self, current) if current != self
|
137
|
+
else
|
138
|
+
## NOTE: we are only doing this for the sake of autoload
|
139
|
+
## which does not honor a customized require method.
|
140
|
+
#if Library.autoload_hack?
|
141
|
+
# absolute_loadpath.each do |path|
|
142
|
+
# $LOAD_PATH.unshift(path)
|
143
|
+
# end
|
144
|
+
#end
|
145
|
+
$LEDGER[name] = self
|
146
|
+
end
|
147
|
+
|
148
|
+
# TODO: activate runtime requirements?
|
149
|
+
#verify
|
150
|
+
end
|
151
|
+
|
152
|
+
#
|
153
|
+
# Is this library active in global ledger?
|
154
|
+
#
|
155
|
+
def active?
|
156
|
+
$LEDGER[name] == self
|
157
|
+
end
|
158
|
+
|
159
|
+
#
|
160
|
+
# Location of library files on disc.
|
161
|
+
#
|
162
|
+
def location
|
163
|
+
@location
|
164
|
+
end
|
165
|
+
|
166
|
+
#
|
167
|
+
# Access to library metadata. Metadata is gathered from
|
168
|
+
# the `.ruby` file or a `.gemspec` file.
|
169
|
+
#
|
170
|
+
# @return [Metadata] metadata object
|
171
|
+
#
|
172
|
+
def metadata
|
173
|
+
@metadata
|
174
|
+
end
|
175
|
+
|
176
|
+
#
|
177
|
+
# Library's "unixname".
|
178
|
+
#
|
179
|
+
# @return [String] name of library
|
180
|
+
#
|
181
|
+
def name
|
182
|
+
@name ||= metadata.name
|
183
|
+
end
|
184
|
+
|
185
|
+
#
|
186
|
+
# Library's version number.
|
187
|
+
#
|
188
|
+
# @return [VersionNumber] version number
|
189
|
+
#
|
190
|
+
def version
|
191
|
+
@version ||= metadata.version
|
192
|
+
end
|
193
|
+
|
194
|
+
#
|
195
|
+
# Library's internal load path(s). This will default to `['lib']`
|
196
|
+
# if not otherwise given.
|
197
|
+
#
|
198
|
+
# @return [Array] list of load paths
|
199
|
+
#
|
200
|
+
def load_path
|
201
|
+
metadata.load_path
|
202
|
+
end
|
203
|
+
|
204
|
+
alias_method :loadpath, :load_path
|
205
|
+
|
206
|
+
#
|
207
|
+
# Release date.
|
208
|
+
#
|
209
|
+
# @return [Time] library's release date
|
210
|
+
#
|
211
|
+
def date
|
212
|
+
metadata.date
|
213
|
+
end
|
214
|
+
|
215
|
+
#
|
216
|
+
# Alias for +#date+.
|
217
|
+
#
|
218
|
+
alias_method :released, :date
|
219
|
+
|
220
|
+
#
|
221
|
+
# Library's requirements. Note that in gemspec terminology these are
|
222
|
+
# called *dependencies*.
|
223
|
+
#
|
224
|
+
# @return [Array] list of requirements
|
225
|
+
#
|
226
|
+
def requirements
|
227
|
+
metadata.requirements
|
228
|
+
end
|
229
|
+
|
230
|
+
#
|
231
|
+
# Runtime requirements.
|
232
|
+
#
|
233
|
+
# @return [Array] list of runtime requirements
|
234
|
+
#
|
235
|
+
def runtime_requirements
|
236
|
+
requirements.select{ |req| !req['development'] }
|
237
|
+
end
|
238
|
+
|
239
|
+
#
|
240
|
+
# Omit library form ledger?
|
241
|
+
#
|
242
|
+
# @return [Boolean] if true, omit library from ledger
|
243
|
+
#
|
244
|
+
def omit
|
245
|
+
@metadata.omit
|
246
|
+
end
|
247
|
+
|
248
|
+
#
|
249
|
+
# Same as `#omit`.
|
250
|
+
#
|
251
|
+
alias_method :omit?, :omit
|
252
|
+
|
253
|
+
#
|
254
|
+
# Returns a list of load paths expand to full path names.
|
255
|
+
#
|
256
|
+
# @return [Array<String>] list of expanded load paths
|
257
|
+
#
|
258
|
+
def absolute_loadpath
|
259
|
+
loadpath.map{ |lp| ::File.join(location, lp) }
|
260
|
+
end
|
261
|
+
|
262
|
+
#
|
263
|
+
# Take requirements and open them. This will reveal any
|
264
|
+
# version conflicts or missing dependencies.
|
265
|
+
#
|
266
|
+
# @param [Boolean] development
|
267
|
+
# Include development dependencies?
|
268
|
+
#
|
269
|
+
def verify(development=false)
|
270
|
+
reqs = development ? requirements : runtime_requirements
|
271
|
+
reqs.each do |req|
|
272
|
+
name, constraint = req['name'], req['version']
|
273
|
+
Library.open(name, constraint)
|
274
|
+
end
|
275
|
+
end
|
276
|
+
|
277
|
+
#
|
278
|
+
# Does a library contain a relative +file+ within it's loadpath.
|
279
|
+
# If so return the libary file object for it, otherwise +false+.
|
280
|
+
#
|
281
|
+
# Note that this method was designed to maximize speed.
|
282
|
+
#
|
283
|
+
# @param [#to_s] file
|
284
|
+
# The relative pathname of the file to find.
|
285
|
+
#
|
286
|
+
# @param [Hash] options
|
287
|
+
# The Hash of optional settings to adjust search behavior.
|
288
|
+
#
|
289
|
+
# @option options [Boolean] :suffix
|
290
|
+
# Automatically try standard extensions if pathname has none.
|
291
|
+
#
|
292
|
+
# @option options [Boolean] :legacy
|
293
|
+
# (deprecated) Do not match within library's +name+ directory, eg. `lib/foo/*`.
|
294
|
+
#
|
295
|
+
# @return [Feature,nil] The feature, if found.
|
296
|
+
#
|
297
|
+
def find(pathname, options={})
|
298
|
+
main = options[:main]
|
299
|
+
#legacy = options[:legacy]
|
300
|
+
suffix = options[:suffix] || options[:suffix].nil?
|
301
|
+
#suffix = false if options[:load]
|
302
|
+
suffix = false if SUFFIXES.include?(::File.extname(pathname))
|
303
|
+
if suffix
|
304
|
+
loadpath.each do |lpath|
|
305
|
+
SUFFIXES.each do |ext|
|
306
|
+
f = ::File.join(location, lpath, pathname + ext)
|
307
|
+
return feature(lpath, pathname, ext) if ::File.file?(f)
|
308
|
+
end
|
309
|
+
end #unless legacy
|
310
|
+
legacy_loadpath.each do |lpath|
|
311
|
+
SUFFIXES.each do |ext|
|
312
|
+
f = ::File.join(location, lpath, pathname + ext)
|
313
|
+
return feature(lpath, pathname, ext) if ::File.file?(f)
|
314
|
+
end
|
315
|
+
end unless main
|
316
|
+
else
|
317
|
+
loadpath.each do |lpath|
|
318
|
+
f = ::File.join(location, lpath, pathname)
|
319
|
+
return feature(lpath, pathname) if ::File.file?(f)
|
320
|
+
end #unless legacy
|
321
|
+
legacy_loadpath.each do |lpath|
|
322
|
+
f = ::File.join(location, lpath, pathname)
|
323
|
+
return feature(lpath, pathname) if ::File.file?(f)
|
324
|
+
end unless main
|
325
|
+
end
|
326
|
+
nil
|
327
|
+
end
|
328
|
+
|
329
|
+
#
|
330
|
+
# Alias for #find.
|
331
|
+
#
|
332
|
+
alias_method :include?, :find
|
333
|
+
|
334
|
+
#
|
335
|
+
#
|
336
|
+
#
|
337
|
+
def legacy?
|
338
|
+
!legacy_loadpath.empty?
|
339
|
+
end
|
340
|
+
|
341
|
+
#
|
342
|
+
# What is `legacy_loadpath`? Well, library doesn't require you to put your
|
343
|
+
# library's scripts in a named lib path, e.g. `lib/foo/`. Instead one can
|
344
|
+
# just put them in `lib/` b/c Library keeps things indexed by honest to
|
345
|
+
# goodness library names. The `legacy_path` then is used to handle these
|
346
|
+
# old style paths along with the new.
|
347
|
+
#
|
348
|
+
def legacy_loadpath
|
349
|
+
@legacy_loadpath ||= (
|
350
|
+
path = []
|
351
|
+
loadpath.each do |lp|
|
352
|
+
llp = File.join(lp, name)
|
353
|
+
dir = File.join(location, llp)
|
354
|
+
path << llp if File.directory?(dir)
|
355
|
+
end
|
356
|
+
path
|
357
|
+
)
|
358
|
+
end
|
359
|
+
|
360
|
+
#
|
361
|
+
# Create a new Feature object from +lpath+, +pathname+ and +ext+.
|
362
|
+
#
|
363
|
+
def feature(lpath, pathname, ext=nil)
|
364
|
+
Feature.new(self, lpath, pathname, ext)
|
365
|
+
end
|
366
|
+
|
367
|
+
#
|
368
|
+
# Requre feature from library.
|
369
|
+
#
|
370
|
+
def require(pathname, options={})
|
371
|
+
if feature = find(pathname, options)
|
372
|
+
feature.require(options)
|
373
|
+
else
|
374
|
+
raise LoadError.new(path, name) # TODO: silently?
|
375
|
+
end
|
376
|
+
end
|
377
|
+
|
378
|
+
#
|
379
|
+
# Load feature form library.
|
380
|
+
#
|
381
|
+
def load(pathname, options={})
|
382
|
+
#options[:load] = true
|
383
|
+
if feature = find(pathname, options)
|
384
|
+
feature.load(options)
|
385
|
+
else
|
386
|
+
raise LoadError.new(pathname, self.name)
|
387
|
+
end
|
388
|
+
end
|
389
|
+
|
390
|
+
#
|
391
|
+
# Inspect library instance.
|
392
|
+
#
|
393
|
+
def inspect
|
394
|
+
if version
|
395
|
+
%[#<Library #{name}/#{version} @location="#{location}">]
|
396
|
+
else
|
397
|
+
%[#<Library #{name} @location="#{location}">]
|
398
|
+
end
|
399
|
+
end
|
400
|
+
|
401
|
+
#
|
402
|
+
# Same as #inspect.
|
403
|
+
#
|
404
|
+
def to_s
|
405
|
+
inspect
|
406
|
+
end
|
407
|
+
|
408
|
+
#
|
409
|
+
# Compare by version.
|
410
|
+
#
|
411
|
+
def <=>(other)
|
412
|
+
version <=> other.version
|
413
|
+
end
|
414
|
+
|
415
|
+
#
|
416
|
+
# Return default feature. This is the feature that has same name as
|
417
|
+
# the library itself.
|
418
|
+
#
|
419
|
+
def default
|
420
|
+
@default ||= find(name, :main=>true)
|
421
|
+
end
|
422
|
+
|
423
|
+
#--
|
424
|
+
# # List of subdirectories that are searched when loading.
|
425
|
+
# #--
|
426
|
+
# # This defualts to ['lib/{name}', 'lib']. The first entry is
|
427
|
+
# # usually proper location; the latter is added for default
|
428
|
+
# # compatability with the traditional require system.
|
429
|
+
# #++
|
430
|
+
# def libdir
|
431
|
+
# loadpath.map{ |path| ::File.join(location, path) }
|
432
|
+
# end
|
433
|
+
#
|
434
|
+
# # Does the library have any lib directories?
|
435
|
+
# def libdir?
|
436
|
+
# lib.any?{ |d| ::File.directory?(d) }
|
437
|
+
# end
|
438
|
+
#++
|
439
|
+
|
440
|
+
#
|
441
|
+
# Location of executable. This is alwasy bin/. This is a fixed
|
442
|
+
# convention, unlike lib/ which needs to be more flexable.
|
443
|
+
#
|
444
|
+
def bindir
|
445
|
+
::File.join(location, 'bin')
|
446
|
+
end
|
447
|
+
|
448
|
+
#
|
449
|
+
# Is there a `bin/` location?
|
450
|
+
#
|
451
|
+
def bindir?
|
452
|
+
::File.exist?(bindir)
|
453
|
+
end
|
454
|
+
|
455
|
+
#
|
456
|
+
# Location of library system configuration files.
|
457
|
+
# This is alwasy the `etc/` directory.
|
458
|
+
#
|
459
|
+
def confdir
|
460
|
+
::File.join(location, 'etc')
|
461
|
+
end
|
462
|
+
|
463
|
+
#
|
464
|
+
# Is there a `etc/` location?
|
465
|
+
#
|
466
|
+
def confdir?
|
467
|
+
::File.exist?(confdir)
|
468
|
+
end
|
469
|
+
|
470
|
+
# Location of library shared data directory.
|
471
|
+
# This is always the `data/` directory.
|
472
|
+
def datadir
|
473
|
+
::File.join(location, 'data')
|
474
|
+
end
|
475
|
+
|
476
|
+
# Is there a `data/` location?
|
477
|
+
def datadir?
|
478
|
+
::File.exist?(datadir)
|
479
|
+
end
|
480
|
+
|
481
|
+
#
|
482
|
+
#def to_rb
|
483
|
+
# to_h.inspect
|
484
|
+
#end
|
485
|
+
|
486
|
+
#
|
487
|
+
# Convert to hash.
|
488
|
+
#
|
489
|
+
# @return [Hash] The library metadata in a hash.
|
490
|
+
#
|
491
|
+
def to_h
|
492
|
+
{
|
493
|
+
:location => location,
|
494
|
+
:name => name,
|
495
|
+
:version => version.to_s,
|
496
|
+
:loadpath => loadpath,
|
497
|
+
:date => date.to_s,
|
498
|
+
:requirements => requirements
|
499
|
+
}
|
500
|
+
end
|
501
|
+
|
502
|
+
module ::Kernel
|
503
|
+
#
|
504
|
+
# In which library is the current file participating?
|
505
|
+
#
|
506
|
+
# @return [Library] The library currently loading features.
|
507
|
+
#
|
508
|
+
def __LIBRARY__
|
509
|
+
$LOAD_STACK.last.library
|
510
|
+
end
|
511
|
+
|
512
|
+
#
|
513
|
+
# Activate a library, same as `Library.instance` but will raise and error
|
514
|
+
# if the library is not found. This can also take a block to yield on the
|
515
|
+
# library.
|
516
|
+
#
|
517
|
+
# @param name [String]
|
518
|
+
# The library's name.
|
519
|
+
#
|
520
|
+
# @param constraint [String]
|
521
|
+
# A valid version constraint.
|
522
|
+
#
|
523
|
+
# @return [Library] The Library instance.
|
524
|
+
#
|
525
|
+
def library(name, constraint=nil, &block) #:yield:
|
526
|
+
Library.activate(name, constraint, &block)
|
527
|
+
end
|
528
|
+
|
529
|
+
module_function :library
|
530
|
+
end
|
531
|
+
|
532
|
+
end
|