roll 0.8.0 → 1.1.0
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/{LICENSE → COPYING} +1 -1
- data/HISTORY +62 -0
- data/README.rdoc +169 -0
- data/TODO +4 -0
- data/bin/roll +3 -44
- data/lib/oll.rb +1 -2
- data/lib/roll.rb +87 -0
- data/lib/roll/command.rb +207 -0
- data/lib/roll/config.rb +80 -0
- data/lib/roll/environment.rb +317 -0
- data/lib/roll/errors.rb +13 -0
- data/lib/roll/kernel.rb +41 -0
- data/lib/roll/ledger.rb +299 -0
- data/lib/roll/library.rb +241 -558
- data/lib/roll/locals.rb +96 -0
- data/lib/roll/metadata.rb +112 -0
- data/lib/roll/original.rb +10 -0
- data/lib/roll/version.rb +91 -101
- data/meta/active +1 -0
- data/meta/authors +1 -0
- data/meta/contact +1 -0
- data/meta/created +1 -0
- data/meta/description +5 -0
- data/meta/homepage +1 -0
- data/meta/maintainer +1 -0
- data/meta/name +1 -0
- data/meta/repository +1 -0
- data/meta/ruby +2 -0
- data/meta/suite +1 -0
- data/meta/summary +1 -0
- data/meta/version +1 -0
- data/script/rdoc +4 -0
- data/script/setup +1344 -0
- data/script/test +23 -0
- data/test/benchmarks/vsgems.rb +11 -0
- data/test/benchmarks/vsgems_bm.rb +17 -0
- data/test/demonstrations/01_library.rdoc +33 -0
- data/test/demonstrations/04_version.rdoc +56 -0
- data/test/fixtures/env.list +1 -0
- data/{demo/sample → test/fixtures}/inspect.rb +0 -0
- data/test/fixtures/tryme/1.0/lib/tryme.rb +1 -0
- data/test/fixtures/tryme/1.0/meta/homepage +1 -0
- data/test/fixtures/tryme/1.0/meta/name +1 -0
- data/test/fixtures/tryme/1.0/meta/version +1 -0
- data/test/fixtures/tryme/1.1/lib/tryme.rb +1 -0
- data/test/fixtures/tryme/1.1/meta/homepage +1 -0
- data/test/fixtures/tryme/1.1/meta/name +1 -0
- data/test/fixtures/tryme/1.1/meta/version +1 -0
- data/test/{test_version.rb → unit/version_test.rb} +21 -21
- data/test/unitcases/version_case.rb +69 -0
- metadata +102 -65
- data/README +0 -17
- data/demo/bench/bench_load.rb +0 -7
- data/demo/sample/tryme/1.0/lib/tryme.rb +0 -1
- data/demo/sample/tryme/1.1/lib/tryme.rb +0 -1
- data/lib/roll/attributes.rb +0 -72
- data/lib/roll/package.rb +0 -300
- data/lib/roll/remote.rb +0 -37
- data/meta/ROLL-0.8.0.roll +0 -21
- data/task/rdoc +0 -9
- data/task/setup +0 -1616
- data/task/test +0 -5
- data/test/test_library.rb +0 -10
data/lib/roll/ledger.rb
ADDED
@@ -0,0 +1,299 @@
|
|
1
|
+
module Roll
|
2
|
+
require 'roll/original'
|
3
|
+
require 'roll/environment'
|
4
|
+
require 'roll/library'
|
5
|
+
|
6
|
+
# = Ledger class
|
7
|
+
#
|
8
|
+
class Ledger
|
9
|
+
|
10
|
+
include Enumerable
|
11
|
+
|
12
|
+
#
|
13
|
+
def initialize
|
14
|
+
@index = Hash.new{|h,k| h[k] = []}
|
15
|
+
|
16
|
+
@environment = Environment.new
|
17
|
+
|
18
|
+
@environment.each do |name, paths|
|
19
|
+
paths.each do |path|
|
20
|
+
unless File.directory?(path)
|
21
|
+
warn "roll: invalid path for #{name} -- #{path}"
|
22
|
+
next
|
23
|
+
end
|
24
|
+
lib = Library.new(path, name)
|
25
|
+
@index[name] << lib if lib.active?
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
@load_stack = []
|
30
|
+
@load_monitor = Hash.new{ |h,k| h[k]=[] }
|
31
|
+
end
|
32
|
+
|
33
|
+
#
|
34
|
+
def enironment
|
35
|
+
@environment
|
36
|
+
end
|
37
|
+
|
38
|
+
#
|
39
|
+
def [](name)
|
40
|
+
@index[name]
|
41
|
+
end
|
42
|
+
|
43
|
+
#
|
44
|
+
def []=(name, value)
|
45
|
+
@index[name] = value
|
46
|
+
end
|
47
|
+
|
48
|
+
#
|
49
|
+
def include?(name)
|
50
|
+
@index.include?(name)
|
51
|
+
end
|
52
|
+
|
53
|
+
#
|
54
|
+
def names
|
55
|
+
@index.keys
|
56
|
+
end
|
57
|
+
|
58
|
+
#
|
59
|
+
def each(&block)
|
60
|
+
@index.each(&block)
|
61
|
+
end
|
62
|
+
|
63
|
+
#
|
64
|
+
def size
|
65
|
+
@index.size
|
66
|
+
end
|
67
|
+
|
68
|
+
#
|
69
|
+
def load_stack
|
70
|
+
@load_stack
|
71
|
+
end
|
72
|
+
|
73
|
+
# NOTE: Not used yet.
|
74
|
+
def load_monitor
|
75
|
+
@load_monitor
|
76
|
+
end
|
77
|
+
|
78
|
+
#--
|
79
|
+
# TODO: Should Ruby's underlying require be tried first,
|
80
|
+
# then fallback to Rolls. Or vice-versa?
|
81
|
+
#++
|
82
|
+
|
83
|
+
#
|
84
|
+
def require(path)
|
85
|
+
#begin
|
86
|
+
# original_require(path)
|
87
|
+
#rescue LoadError => load_error
|
88
|
+
# lib, file = *match(path)
|
89
|
+
# if lib && file
|
90
|
+
# constrain(lib)
|
91
|
+
# lib.require_absolute(file)
|
92
|
+
# else
|
93
|
+
# raise clean_backtrace(load_error)
|
94
|
+
# end
|
95
|
+
#end
|
96
|
+
lib, file = *match(path)
|
97
|
+
if lib && file
|
98
|
+
constrain(lib)
|
99
|
+
lib.require_absolute(file)
|
100
|
+
else
|
101
|
+
begin
|
102
|
+
original_require(path)
|
103
|
+
rescue LoadError => load_error
|
104
|
+
raise clean_backtrace(load_error)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
end
|
109
|
+
|
110
|
+
#
|
111
|
+
def load(path, wrap=nil)
|
112
|
+
lib, file = *match(path, false)
|
113
|
+
if lib && file
|
114
|
+
constrain(lib)
|
115
|
+
lib.load_absolute(file, wrap)
|
116
|
+
else
|
117
|
+
begin
|
118
|
+
original_load(path, wrap)
|
119
|
+
rescue LoadError => load_error
|
120
|
+
raise clean_backtrace(load_error)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
# Use acquire to use Roll-style loading. This first
|
126
|
+
# looks for a specific library via ':'. If ':' is
|
127
|
+
# not present it then tries the current library.
|
128
|
+
# Failing that it fallsback to Ruby itself.
|
129
|
+
#
|
130
|
+
# acquire('facets:string/margin')
|
131
|
+
#
|
132
|
+
# To "load" the library, rather than "require" it set
|
133
|
+
# the +:load+ option to true.
|
134
|
+
#
|
135
|
+
# acquire('facets:string/margin', :load=>true)
|
136
|
+
#
|
137
|
+
def acquire(file, opts={})
|
138
|
+
if file.index(':') # a specific library
|
139
|
+
name, file = file.split(':')
|
140
|
+
lib = Library.open(name)
|
141
|
+
else # try the current library
|
142
|
+
cur = load_stack.last
|
143
|
+
if cur && cur.include?(file)
|
144
|
+
lib = cur
|
145
|
+
elsif !file.index('/') # is this a library name?
|
146
|
+
if cur = Library.instance(file)
|
147
|
+
lib = cur
|
148
|
+
file = lib.default # default file to load
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
if opts[:load]
|
153
|
+
lib ? lib.load(file) : original_load(file)
|
154
|
+
else
|
155
|
+
lib ? lib.require(file) : original_require(file)
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
#
|
160
|
+
def constrain(lib)
|
161
|
+
cmp = self[lib.name]
|
162
|
+
if Array === cmp
|
163
|
+
self[lib.name] = lib
|
164
|
+
else
|
165
|
+
if lib.version != cmp.version
|
166
|
+
raise VersionError
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
private
|
172
|
+
|
173
|
+
# Find require matches.
|
174
|
+
def match(path, suffix=true)
|
175
|
+
path = path.to_s
|
176
|
+
|
177
|
+
return nil if /^\// =~ path # absolute path
|
178
|
+
|
179
|
+
if path.index(':') # a specified library
|
180
|
+
name, path = path.split(':')
|
181
|
+
lib = Library.open(name)
|
182
|
+
if lib.active?
|
183
|
+
file = lib.find(path, suffix)
|
184
|
+
return lib, file
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
matches = []
|
189
|
+
|
190
|
+
# try the load stack first
|
191
|
+
load_stack.reverse_each do |lib|
|
192
|
+
if file = lib.find(path, suffix)
|
193
|
+
return [lib, file] unless $VERBOSE
|
194
|
+
matches << [lib, file]
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
# TODO: Perhaps the selected and unselected should be kept in separate lists?
|
199
|
+
unselected, selected = *@index.partition{ |name, libs| Array === libs }
|
200
|
+
|
201
|
+
selected.each do |(name, lib)|
|
202
|
+
if file = lib.find(path, suffix)
|
203
|
+
#matches << [lib, file]
|
204
|
+
#return matches.first unless $VERBOSE
|
205
|
+
return [lib, file] unless $VERBOSE
|
206
|
+
matches << [lib, file]
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
unselected.each do |(name, libs)|
|
211
|
+
pos = []
|
212
|
+
libs.each do |lib|
|
213
|
+
if file = lib.find(path, suffix)
|
214
|
+
pos << [lib, file]
|
215
|
+
end
|
216
|
+
end
|
217
|
+
unless pos.empty?
|
218
|
+
latest = pos.sort{ |a,b| b[0].version <=> a[0].version }.first
|
219
|
+
return latest unless $VERBOSE
|
220
|
+
matches << latest
|
221
|
+
#return matches.first unless $VERBOSE
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
matches.uniq!
|
226
|
+
|
227
|
+
if matches.size > 1
|
228
|
+
warn_multiples(path, matches)
|
229
|
+
end
|
230
|
+
|
231
|
+
matches.first
|
232
|
+
end
|
233
|
+
|
234
|
+
#
|
235
|
+
def warn_multiples(path, matches)
|
236
|
+
warn "multiple matches for same request -- #{path}"
|
237
|
+
matches.each do |lib, file|
|
238
|
+
warn " #{file}"
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
#
|
243
|
+
def clean_backtrace(error)
|
244
|
+
if $DEBUG
|
245
|
+
error
|
246
|
+
else
|
247
|
+
bt = error.backtrace
|
248
|
+
bt = bt.reject{ |e| /roll/ =~ e }
|
249
|
+
error.set_backtrace(bt)
|
250
|
+
error
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
254
|
+
end#class Ledger
|
255
|
+
|
256
|
+
#--
|
257
|
+
# Ledger augments the Library metaclass.
|
258
|
+
#++
|
259
|
+
class << Library
|
260
|
+
|
261
|
+
#
|
262
|
+
def ledger
|
263
|
+
@ledger ||= Ledger.new
|
264
|
+
end
|
265
|
+
|
266
|
+
# Current environment
|
267
|
+
def environment
|
268
|
+
ledger.environment
|
269
|
+
end
|
270
|
+
|
271
|
+
# List of library names.
|
272
|
+
def list
|
273
|
+
ledger.names
|
274
|
+
end
|
275
|
+
|
276
|
+
#
|
277
|
+
def require(path)
|
278
|
+
ledger.require(path)
|
279
|
+
end
|
280
|
+
|
281
|
+
#
|
282
|
+
def load(path, wrap=nil)
|
283
|
+
ledger.load(path, wrap)
|
284
|
+
end
|
285
|
+
|
286
|
+
#
|
287
|
+
def load_stack
|
288
|
+
ledger.load_stack
|
289
|
+
end
|
290
|
+
|
291
|
+
# NOTE: Not used yet.
|
292
|
+
def load_monitor
|
293
|
+
ledger.load_monitor
|
294
|
+
end
|
295
|
+
|
296
|
+
end
|
297
|
+
|
298
|
+
end#module Roll
|
299
|
+
|
data/lib/roll/library.rb
CHANGED
@@ -1,635 +1,318 @@
|
|
1
|
-
#
|
2
|
-
#
|
3
|
-
# library.rb
|
4
|
-
#
|
5
|
-
# LICENSE:
|
6
|
-
#
|
7
|
-
# Copyright (c)2007 Thomas Sawyer, Ruby License
|
8
|
-
#
|
9
|
-
# TODO:
|
10
|
-
#
|
11
|
-
# - Commented out #import for now. Facets' module_require and module_load
|
12
|
-
# are probably better. Implement those for Rolls instead. (Yes?)
|
13
|
-
# - Maybe add autopackage install system?
|
14
|
-
# - What about remotes? What about version tiers when remote requiring?
|
15
|
-
|
16
|
-
require 'rbconfig'
|
17
|
-
require 'fileutils'
|
18
|
-
require 'roll/package'
|
1
|
+
#require 'rbconfig'
|
19
2
|
require 'roll/version'
|
20
|
-
|
21
|
-
|
22
|
-
# We need to hold a copy of the original $LOAD_PATH
|
23
|
-
# for specified "ruby: ..." loads.
|
24
|
-
|
25
|
-
$RUBY_PATH = $LOAD_PATH.dup
|
26
|
-
|
27
|
-
# Locations of rolls-ready libraries.
|
28
|
-
# # We could use the site_ruby locations instead, but that creates an odd sort of overlap in
|
29
|
-
# # the load paths, and would also promote putting the information file in the lib/ dir. So
|
30
|
-
# # I think it's better to use a separate location. (After all site_ruby may just fade away.)
|
31
|
-
# $LOAD_SITE = $LOAD_PATH - Config::CONFIG.values_at('rubylibdir', 'archdir') - ['.']
|
32
|
-
|
33
|
-
rolldir = 'ruby_library'
|
34
|
-
sitedir = ::Config::CONFIG['sitedir']
|
35
|
-
version = ::Config::CONFIG['ruby_version']
|
3
|
+
require 'roll/metadata'
|
4
|
+
require 'roll/errors'
|
36
5
|
|
37
|
-
|
38
|
-
|
39
|
-
# = Library Class
|
40
|
-
#
|
41
|
-
# The Library class serves as an objecified location in Ruby's load paths.
|
42
|
-
#
|
43
|
-
# The Library qua class also serves as the library manager, storing a ledger of
|
44
|
-
# available libraries.
|
45
|
-
#
|
46
|
-
# A library is roll-ready when it supplies a {name}-{verison}.roll file in either its
|
47
|
-
# base directory or in the base's meta/ directory. The roll file name is specifically
|
48
|
-
# designed to make library lookup fast. There is no need for Rolls to open the roll
|
49
|
-
# file until an actual version is used. It also gives the most flexability in repository
|
50
|
-
# layout. Rolls searches up to three subdirs deep looking for roll files. This is
|
51
|
-
# suitable to non-versioned libs, versioned libs, non-versioned subprojects and subprojects,
|
52
|
-
# including typical Subversion repository layouts.
|
53
|
-
|
54
|
-
class Library
|
55
|
-
|
56
|
-
# Dynamic link extension.
|
57
|
-
def self.dlext
|
58
|
-
@dlext ||= '.' + ::Config::CONFIG['DLEXT']
|
59
|
-
end
|
60
|
-
|
61
|
-
# Location of rolls-ready libs.
|
62
|
-
def self.load_site
|
63
|
-
$LOAD_SITE
|
64
|
-
end
|
6
|
+
module Roll
|
65
7
|
|
8
|
+
# = Library class
|
66
9
|
#
|
67
|
-
|
68
|
-
$LOAD_PATH
|
69
|
-
end
|
10
|
+
class Library
|
70
11
|
|
71
|
-
|
72
|
-
|
73
|
-
$RUBY_PATH
|
74
|
-
end
|
75
|
-
|
76
|
-
# Name of library.
|
77
|
-
attr_reader :name
|
78
|
-
|
79
|
-
# Version of library. This is a VersionNumber object.
|
80
|
-
attr_reader :version
|
12
|
+
# Dynamic link extension.
|
13
|
+
#DLEXT = '.' + ::Config::CONFIG['DLEXT']
|
81
14
|
|
82
|
-
|
83
|
-
|
15
|
+
#
|
16
|
+
#SUFFIXES = ['', '.rb', '.rbw', '.so', '.bundle', '.dll', '.sl', '.jar']
|
17
|
+
SUFFIXES = ['', '.rb', '.rbw', '.so', '.bundle', '.dll', '.sl', '.jar']
|
84
18
|
|
85
|
-
|
86
|
-
|
87
|
-
@location = location
|
88
|
-
|
89
|
-
if identity
|
90
|
-
@name = identity[:name]
|
91
|
-
@version = identity[:version]
|
92
|
-
@load_path = identity[:load_path] || identity[:load_paths]
|
93
|
-
else
|
94
|
-
identify(location)
|
95
|
-
end
|
19
|
+
#
|
20
|
+
SUFFIX_PATTERN = "{#{SUFFIXES.join(',')}}"
|
96
21
|
|
97
|
-
|
98
|
-
|
22
|
+
# Get an instance of a library by name, or name and version.
|
23
|
+
# Libraries are singleton, so once loaded the same object is
|
24
|
+
# always returned.
|
99
25
|
|
100
|
-
|
26
|
+
def self.instance(name, constraint=nil)
|
27
|
+
name = name.to_s
|
28
|
+
#raise "no library -- #{name}" unless ledger.include?(name)
|
29
|
+
return nil unless ledger.include?(name)
|
101
30
|
|
102
|
-
|
103
|
-
@version = VersionNumber.new(@version) unless VersionNumber === @version
|
104
|
-
end
|
31
|
+
library = ledger[name]
|
105
32
|
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
33
|
+
if Library===library
|
34
|
+
if constraint # TODO: it's okay if constraint fits current
|
35
|
+
raise VersionConflict, "previously selected version -- #{ledger[name].version}"
|
36
|
+
else
|
37
|
+
library
|
38
|
+
end
|
39
|
+
else # library is an array of versions
|
40
|
+
if constraint
|
41
|
+
compare = Version.constraint_lambda(constraint)
|
42
|
+
library = library.select(&compare).max
|
43
|
+
else
|
44
|
+
library = library.max
|
45
|
+
end
|
46
|
+
unless library
|
47
|
+
raise VersionError, "no library version -- #{name} #{constraint}"
|
48
|
+
end
|
49
|
+
#ledger[name] = library
|
50
|
+
#library.activate
|
51
|
+
return library
|
52
|
+
end
|
120
53
|
end
|
121
|
-
end
|
122
54
|
|
123
|
-
|
124
|
-
find = "{,meta/}*.roll" # "{,meta/}#{name}-#{version}.roll"
|
125
|
-
file = Dir.glob(File.join(location, find), File::FNM_CASEFOLD).first
|
126
|
-
end
|
55
|
+
# A shortcut for #instance.
|
127
56
|
|
128
|
-
|
129
|
-
|
130
|
-
return unless location # NEED TO DO THIS BETTER. THIS IS HERE FOR THE ONE 'ruby' CASE.
|
131
|
-
raise LoadError unless File.directory?(location)
|
132
|
-
glob = File.join(location, "{,meta/}*.roll") # "{,meta/}#{name}-#{version}.roll"
|
133
|
-
file = Dir.glob(glob, File::FNM_CASEFOLD).first
|
134
|
-
if file
|
135
|
-
@roll_file = file
|
136
|
-
@roll = Roll::Package.open(file, :name=>name, :version=>version.to_s)
|
137
|
-
else
|
138
|
-
raise "THIS SHOULD NOT POSSIBLE!"
|
139
|
-
#@roll = false #Roll::Package.new # THIS IN NO LONGER POSSIBLE
|
57
|
+
def self.[](name, constraint=nil)
|
58
|
+
instance(name, constraint)
|
140
59
|
end
|
141
|
-
#use #?
|
142
|
-
return @roll
|
143
|
-
end
|
144
|
-
|
145
|
-
# Does this library have an roll file?
|
146
|
-
#def rolled?
|
147
|
-
# roll ? true : false
|
148
|
-
#end
|
149
|
-
|
150
|
-
# Does this library have a remote source?
|
151
|
-
|
152
|
-
#def remote?
|
153
|
-
# rolled? and source and pubkey
|
154
|
-
#end
|
155
|
-
|
156
|
-
# Meta information about the libray.
|
157
|
-
def roll
|
158
|
-
@roll = load_roll if @roll.nil? # If it's false, we don't have one.
|
159
|
-
@roll
|
160
|
-
end
|
161
|
-
alias_method :info, :roll
|
162
60
|
|
163
|
-
|
164
|
-
|
165
|
-
version <=> other.verison
|
166
|
-
end
|
61
|
+
# Same as #instance but will raise and error if the library is
|
62
|
+
# not found. This can also take a block to yield on the library.
|
167
63
|
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
return unless roll # NEED TO DO THIS BETTER. THIS IS HERE FOR THE ONE 'ruby' CASE.
|
173
|
-
return @load_path if @load_path
|
174
|
-
if roll.load_path
|
175
|
-
@load_path = roll.load_path.collect{ |path| File.join(location, path) }
|
176
|
-
else
|
177
|
-
@load_path = ['lib'] # ["lib/#{name}"]
|
178
|
-
end
|
179
|
-
end
|
180
|
-
alias_method :load_path, :lib_path
|
181
|
-
alias_method :load_paths, :lib_path
|
182
|
-
|
183
|
-
# List of subdirectories that are searched for binaries.
|
184
|
-
#++
|
185
|
-
# TODO I think it would be better just to make this a fix
|
186
|
-
# convention that bin/ is always the place to put these.
|
187
|
-
# (Unlike lib/ which needs to be more flexable.)
|
188
|
-
#--
|
189
|
-
def bin_path
|
190
|
-
return @bin_path if @bin_path
|
191
|
-
return [] unless location # NEED TO DO THIS BETTER.
|
192
|
-
if roll.bin_path
|
193
|
-
@bin_path = roll.bin_path.collect{ |path| File.join(location, path) }
|
194
|
-
else
|
195
|
-
if File.directory?(File.join(location, 'bin'))
|
196
|
-
@bin_path = [File.join(location, 'bin')]
|
197
|
-
else
|
198
|
-
@bin_path = []
|
64
|
+
def self.open(name, constraint=nil) #:yield:
|
65
|
+
lib = instance(name, constraint)
|
66
|
+
unless lib
|
67
|
+
raise LoadError, "no library -- #{name}"
|
199
68
|
end
|
69
|
+
yield(lib) if block_given?
|
70
|
+
lib
|
200
71
|
end
|
201
|
-
return @bin_path
|
202
|
-
end
|
203
72
|
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
# versioned data directories.
|
209
|
-
def datadir(versionless=false)
|
210
|
-
if version and not versionless
|
211
|
-
File.join(Config::CONFIG['datadir'], name, version)
|
212
|
-
else
|
213
|
-
File.join(Config::CONFIG['datadir'], name)
|
73
|
+
#
|
74
|
+
def initialize(location, name=nil)
|
75
|
+
@location = location
|
76
|
+
@name = name
|
214
77
|
end
|
215
|
-
end
|
216
|
-
|
217
|
-
# Return the path to the configuration directory.
|
218
|
-
#--
|
219
|
-
# Can or should configuration directories be versioned?
|
220
|
-
#++
|
221
|
-
def confdir
|
222
|
-
File.join(location, 'data')
|
223
|
-
#if version
|
224
|
-
# File.join(Config::CONFIG['confdir'], name, version)
|
225
|
-
#else
|
226
|
-
# File.join(Config::CONFIG['datadir'], name)
|
227
|
-
#end
|
228
|
-
end
|
229
|
-
|
230
|
-
# Require find.
|
231
|
-
def require_find(file)
|
232
|
-
file = roll.index_file if (file.nil? or file.empty?)
|
233
|
-
glob = File.join('{' + load_path.join(',') + '}', file + "{.rb,#{Library.dlext},}")
|
234
|
-
Dir.glob(glob).first
|
235
|
-
end
|
236
|
-
|
237
|
-
# Load find.
|
238
|
-
def load_find(file)
|
239
|
-
file = roll.index_file if (file.nil? or file.empty?)
|
240
|
-
glob = File.join('{' + load_path.join(',') + '}', file)
|
241
|
-
Dir.glob(glob).first
|
242
|
-
end
|
243
78
|
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
Kernel.require(path)
|
248
|
-
else
|
249
|
-
raise LoadError, "no such file to load -- #{name}:#{file}"
|
79
|
+
#
|
80
|
+
def location
|
81
|
+
@location
|
250
82
|
end
|
251
|
-
end
|
252
83
|
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
Kernel.load(path, wrap)
|
257
|
-
else
|
258
|
-
raise LoadError, "no such file to load -- #{name}:#{file}"
|
84
|
+
#
|
85
|
+
def name
|
86
|
+
@name ||= metadata.name
|
259
87
|
end
|
260
|
-
end
|
261
88
|
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
Kernel.autoload(base, file)
|
266
|
-
else
|
267
|
-
raise LoadError, "no such file to autoload -- #{name}:#{file}"
|
89
|
+
#
|
90
|
+
def version
|
91
|
+
@version ||= metadata.version
|
268
92
|
end
|
269
|
-
end
|
270
93
|
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
mod.module_require(path) # FIXME
|
275
|
-
else
|
276
|
-
raise LoadError, "no such file to load -- #{name}:#{file}"
|
94
|
+
#
|
95
|
+
def active?
|
96
|
+
@active ||= metadata.active
|
277
97
|
end
|
278
|
-
end
|
279
98
|
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
mod.module_load(path) # FIXME
|
284
|
-
else
|
285
|
-
raise LoadError, "no such file to load -- #{name}:#{file}"
|
99
|
+
#
|
100
|
+
def loadpath
|
101
|
+
@loadpath ||= metadata.loadpath
|
286
102
|
end
|
287
|
-
end
|
288
103
|
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
mod.autoload_without_roll(base, file)
|
293
|
-
else
|
294
|
-
raise LoadError, "no such file to autoload -- #{name}:#{file}"
|
104
|
+
#
|
105
|
+
def requires
|
106
|
+
@requires ||= metadata.requires
|
295
107
|
end
|
296
|
-
end
|
297
108
|
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
#++
|
302
|
-
def utilize
|
303
|
-
lib_path.each do |path|
|
304
|
-
Library.load_path.unshift(path)
|
109
|
+
#
|
110
|
+
def released
|
111
|
+
@released ||= metadata.released
|
305
112
|
end
|
306
|
-
Library.load_path.uniq!
|
307
|
-
self
|
308
|
-
end
|
309
|
-
|
310
|
-
# Class instance variable @ledger stores the library references.
|
311
113
|
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
# First we add Ruby core and standard libraries.
|
319
|
-
@ledger['ruby'] = Library.new(nil, :name=>'ruby', :version=>VERSION, :load_path=>Library.ruby_path)
|
320
|
-
|
321
|
-
scan_working() if $DEBUG
|
322
|
-
|
323
|
-
projs1 = Dir.glob( '{' + $LOAD_SITE.join(',') + '}/*{/meta,}/*.roll', File::FNM_CASEFOLD )
|
324
|
-
projs2 = Dir.glob( '{' + $LOAD_SITE.join(',') + '}/*/*{/meta,}/*.roll', File::FNM_CASEFOLD )
|
325
|
-
projs3 = Dir.glob( '{' + $LOAD_SITE.join(',') + '}/*/*/*{/meta,}/*.roll', File::FNM_CASEFOLD )
|
326
|
-
|
327
|
-
projs = projs1 + projs2 + projs3
|
328
|
-
|
329
|
-
#dirs = projs.collect do |prj|
|
330
|
-
# metafile = File.basename(prj)
|
331
|
-
# dir = File.dirname(prj)
|
332
|
-
# dir = File.dirname(dir) if dir =~ /meta$/
|
333
|
-
# dir
|
334
|
-
#end
|
335
|
-
|
336
|
-
projs.uniq!
|
337
|
-
|
338
|
-
#dirs -= $LOAD_SITE
|
114
|
+
#
|
115
|
+
def verify
|
116
|
+
requires.each do |(name, constraint)|
|
117
|
+
Library.open(name, constraint)
|
118
|
+
end
|
119
|
+
end
|
339
120
|
|
340
|
-
|
341
|
-
name, ver = *File.basename(proj).chomp('.roll').split('-')
|
342
|
-
dir = File.dirname(proj)
|
343
|
-
dir = File.dirname(dir) if File.basename(dir) == 'meta'
|
121
|
+
# Find first matching +file+.
|
344
122
|
|
345
|
-
|
123
|
+
#def find(file, suffix=true)
|
124
|
+
# case File.extname(file)
|
125
|
+
# when *SUFFIXES
|
126
|
+
# find = File.join(lookup_glob, file)
|
127
|
+
# else
|
128
|
+
# find = File.join(lookup_glob, file + SUFFIX_PATTERN) #'{' + ".rb,#{DLEXT}" + '}')
|
129
|
+
# end
|
130
|
+
# Dir[find].first
|
131
|
+
#end
|
346
132
|
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
133
|
+
# Standard loadpath search.
|
134
|
+
#
|
135
|
+
def find(file, suffix=true)
|
136
|
+
if suffix
|
137
|
+
SUFFIXES.each do |ext|
|
138
|
+
loadpath.each do |lpath|
|
139
|
+
f = File.join(location, lpath, file + ext)
|
140
|
+
return f if File.file?(f)
|
141
|
+
end
|
142
|
+
end
|
143
|
+
else
|
144
|
+
loadpath.each do |lpath|
|
145
|
+
f = File.join(location, lpath, file)
|
146
|
+
return f if File.file?(f)
|
147
|
+
end
|
353
148
|
end
|
149
|
+
nil
|
354
150
|
end
|
355
151
|
|
356
|
-
#
|
357
|
-
#
|
358
|
-
#
|
359
|
-
#
|
360
|
-
|
361
|
-
#
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
152
|
+
# Does this library have a matching +file+? If so, the full-path
|
153
|
+
# of the file is returned.
|
154
|
+
#
|
155
|
+
# Unlike #find, this also matches within the library directory
|
156
|
+
# itself, eg. <tt>lib/foo/*</tt>. It is used by #aquire.
|
157
|
+
#
|
158
|
+
def include?(file, suffix=true)
|
159
|
+
if suffix
|
160
|
+
SUFFIXES.each do |ext|
|
161
|
+
loadpath.each do |lpath|
|
162
|
+
f = File.join(location, lpath, name, file + ext)
|
163
|
+
return f if File.file?(f)
|
164
|
+
f = File.join(location, lpath, file + ext)
|
165
|
+
return f if File.file?(f)
|
166
|
+
end
|
167
|
+
end
|
168
|
+
else
|
169
|
+
loadpath.each do |lpath|
|
170
|
+
f = File.join(location, lpath, name, file)
|
171
|
+
return f if File.file?(f)
|
172
|
+
f = File.join(location, lpath, file)
|
173
|
+
return f if File.file?(f)
|
369
174
|
end
|
370
175
|
end
|
176
|
+
nil
|
371
177
|
end
|
372
178
|
|
373
|
-
#
|
374
|
-
|
375
|
-
|
376
|
-
|
179
|
+
#def include?(file)
|
180
|
+
# case File.extname(file)
|
181
|
+
# when *SUFFIXES
|
182
|
+
# find = File.join(lookup_glob, "{#{name}/,}" + file)
|
183
|
+
# else
|
184
|
+
# find = File.join(lookup_glob, "{#{name}/,}" + file + SUFFIX_PATTERN) #'{' + ".rb,#{DLEXT}" + '}')
|
185
|
+
# end
|
186
|
+
# Dir[find].first
|
187
|
+
#end
|
377
188
|
|
378
|
-
#
|
379
|
-
def
|
380
|
-
|
381
|
-
|
382
|
-
return nil unless @ledger.include?(name)
|
383
|
-
case lib = @ledger[name]
|
384
|
-
when Library
|
385
|
-
return lib unless constraint
|
386
|
-
raise VersionConflict, "previously selected library version" # -- #{lib.version}"
|
387
|
-
#when Version
|
388
|
-
# @ledger[name] = new(lib.location, :name=>name, :version=>lib) #new(name, lib, lib.location)
|
389
|
-
when Array
|
390
|
-
if constraint
|
391
|
-
compare = VersionNumber.constrant_lambda(constraint)
|
392
|
-
version = lib.select(&compare).max
|
393
|
-
else
|
394
|
-
version = lib.max
|
395
|
-
end
|
396
|
-
unless version
|
397
|
-
raise VersionError, "no library version -- #{name} #{constraint}"
|
398
|
-
end
|
399
|
-
@ledger[name] = version #new(version.location, :name=>name, :version=>version) #new(name, version, version.location)
|
189
|
+
#
|
190
|
+
def require(file)
|
191
|
+
if path = include?(file)
|
192
|
+
require_absolute(path)
|
400
193
|
else
|
401
|
-
|
194
|
+
load_error = LoadError.new("no such file to require -- #{name}:#{file}")
|
195
|
+
raise clean_backtrace(load_error)
|
402
196
|
end
|
403
|
-
@ledger[name].roll # Make sure the roll file is loaded.
|
404
|
-
@ledger[name]
|
405
197
|
end
|
406
198
|
|
407
|
-
#
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
199
|
+
# NOT SURE ABOUT USING THIS
|
200
|
+
def require_absolute(file)
|
201
|
+
#Library.load_monitor[file] << caller if $LOAD_MONITOR
|
202
|
+
Library.load_stack << self
|
203
|
+
begin
|
204
|
+
success = original_require(file)
|
205
|
+
#rescue LoadError => load_error
|
206
|
+
# raise clean_backtrace(load_error)
|
207
|
+
ensure
|
208
|
+
Library.load_stack.pop
|
415
209
|
end
|
416
|
-
|
417
|
-
lib
|
210
|
+
success
|
418
211
|
end
|
419
212
|
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
213
|
+
#
|
214
|
+
def load(file, wrap=nil)
|
215
|
+
if path = include?(file, false)
|
216
|
+
load_absolute(path, wrap)
|
217
|
+
else
|
218
|
+
load_error = LoadError.new("no such file to load -- #{name}:#{file}")
|
219
|
+
clean_backtrace(load_error)
|
220
|
+
end
|
221
|
+
end
|
425
222
|
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
223
|
+
#
|
224
|
+
def load_absolute(file, wrap=nil)
|
225
|
+
#Library.load_monitor[file] << caller if $LOAD_MONITOR
|
226
|
+
Library.load_stack << self
|
227
|
+
begin
|
228
|
+
success = original_load(file, wrap)
|
229
|
+
#rescue LoadError => load_error
|
230
|
+
# raise clean_backtrace(load_error)
|
231
|
+
ensure
|
232
|
+
Library.load_stack.pop
|
233
|
+
end
|
234
|
+
success
|
235
|
+
end
|
431
236
|
|
237
|
+
# Inspection.
|
238
|
+
def inspect
|
239
|
+
if @version
|
240
|
+
%[#<Library #{name}/#{@version} @location="#{location}">]
|
241
|
+
else
|
242
|
+
%[#<Library #{name} @location="#{location}">]
|
243
|
+
end
|
244
|
+
end
|
432
245
|
|
433
|
-
|
434
|
-
|
435
|
-
# package name. Normally this is just
|
436
|
-
# "#{Config::CONFIG['datadir']}/#{package_name}", but may be
|
437
|
-
# modified by packages like RubyGems and Rolls to handle
|
438
|
-
# versioned data directories.
|
439
|
-
def self.datadir(name, versionless=false)
|
440
|
-
if lib = Library.instance( name )
|
441
|
-
lib.datadir( versionless )
|
442
|
-
else
|
443
|
-
File.join(CONFIG['datadir'], name)
|
246
|
+
def to_s
|
247
|
+
inspect
|
444
248
|
end
|
445
|
-
end
|
446
249
|
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
lib.confdir
|
451
|
-
else
|
452
|
-
File.join(CONFIG['datadir'], name)
|
250
|
+
# Compare by version.
|
251
|
+
def <=>(other)
|
252
|
+
version <=> other.version
|
453
253
|
end
|
454
|
-
end
|
455
|
-
end
|
456
254
|
|
255
|
+
# # List of subdirectories that are searched when loading.
|
256
|
+
# #--
|
257
|
+
# # This defualts to ['lib/{name}', 'lib']. The first entry is
|
258
|
+
# # usually proper location; the latter is added for default
|
259
|
+
# # compatability with the traditional require system.
|
260
|
+
# #++
|
261
|
+
# def libdir
|
262
|
+
# loadpath.map{ |path| File.join(location, path) }
|
263
|
+
# end
|
264
|
+
#
|
265
|
+
# # Does the library have any lib directories?
|
266
|
+
# def libdir?
|
267
|
+
# lib.any?{ |d| File.directory?(d) }
|
268
|
+
# end
|
457
269
|
|
458
|
-
|
270
|
+
# Location of executable. This is alwasy bin/. This is a fixed
|
271
|
+
# convention, unlike lib/ which needs to be more flexable.
|
272
|
+
def bindir ; File.join(location, 'bin') ; end
|
459
273
|
|
460
|
-
|
461
|
-
|
462
|
-
Library.open(name, constraint)
|
463
|
-
end
|
464
|
-
module_function :library
|
465
|
-
|
466
|
-
# Use library. This activates a library, and adds
|
467
|
-
# it's load_path to the global $LOAD_PATH.
|
468
|
-
#--
|
469
|
-
# Maybe call #import instead ?
|
470
|
-
#++
|
471
|
-
def use(name, constraint=nil)
|
472
|
-
Library.open(name, constraint).utilize
|
473
|
-
end
|
274
|
+
# Is there a <tt>bin/</tt> location?
|
275
|
+
def bindir? ; File.exist?(bindir) ; end
|
474
276
|
|
277
|
+
# Location of library system configuration files.
|
278
|
+
# This is alwasy the <tt>etc/</tt> directory.
|
279
|
+
def confdir ; File.join(location, 'etc') ; end
|
475
280
|
|
476
|
-
|
477
|
-
|
478
|
-
name, path = file.split(':')
|
479
|
-
else
|
480
|
-
name, *rest = file.split('/')
|
481
|
-
path = File.join(*rest)
|
482
|
-
end
|
483
|
-
name = nil if name == ''
|
484
|
-
lib = name ? Library.instance(name) : nil
|
485
|
-
raise LoadError, "no library found -- #{file}" if must && !lib
|
486
|
-
return lib, path
|
487
|
-
end
|
281
|
+
# Is there a <tt>etc/</tt> location?metadata.name
|
282
|
+
def confdir? ; File.exist?(confdir) ; end
|
488
283
|
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
#
|
493
|
-
# This would be a bit simpler if we mandated the
|
494
|
-
# use of the ':' notation when specifying the library
|
495
|
-
# name. Use of the ':' is robust. But we cannot do this
|
496
|
-
# w/o loosing backward-compatability. Using '/' in its
|
497
|
-
# place has the potential for pathname clashing, albeit
|
498
|
-
# the likelihood is small. There are two ways to bypass
|
499
|
-
# the problem if it arises. Use 'ruby:{path}' if the
|
500
|
-
# conflicting lib is a ruby core or standard library.
|
501
|
-
# Use ':{path}' to bypass Roll system altogether.
|
502
|
-
|
503
|
-
# # Require script.
|
504
|
-
# def require(file)
|
505
|
-
# if file.index(':')
|
506
|
-
# name, file = file.split(':')
|
507
|
-
# if name == ''
|
508
|
-
# Kernel.require(file)
|
509
|
-
# #if lib == 'ruby'
|
510
|
-
# # Ruby.require(file)
|
511
|
-
# elsif lib = Library.instance(name)
|
512
|
-
# lib.require(file)
|
513
|
-
# else
|
514
|
-
# raise LoadError, "no library found -- #{name}"
|
515
|
-
# end
|
516
|
-
# else
|
517
|
-
# name, *rest = file.split('/')
|
518
|
-
# if lib = Library.instance(name)
|
519
|
-
# lib.require(File.join(*rest))
|
520
|
-
# else
|
521
|
-
# Kernel.require(file)
|
522
|
-
# end
|
523
|
-
# end
|
524
|
-
# end
|
525
|
-
|
526
|
-
# Require script.
|
527
|
-
def require(file)
|
528
|
-
lib, path = *Kernel.parse_load_parameters(file)
|
529
|
-
if lib
|
530
|
-
lib.require(path)
|
531
|
-
else
|
532
|
-
Kernel.require(file)
|
533
|
-
end
|
534
|
-
end
|
284
|
+
# Location of library shared data directory.
|
285
|
+
# This is always the <tt>data/</tt> directory.
|
286
|
+
def datadir ; File.join(location, 'data') ; end
|
535
287
|
|
536
|
-
#
|
537
|
-
|
538
|
-
# if file.index(':')
|
539
|
-
# name, file = file.split(':')
|
540
|
-
# if name == ''
|
541
|
-
# Kernel.require(file)
|
542
|
-
# #if lib == 'ruby'
|
543
|
-
# # Ruby.load(file, safe)
|
544
|
-
# elsif lib = Library.instance(name)
|
545
|
-
# lib.load(file, wrap)
|
546
|
-
# else
|
547
|
-
# raise LoadError, "no library found -- #{name}"
|
548
|
-
# end
|
549
|
-
# else
|
550
|
-
# name, *rest = file.split('/')
|
551
|
-
# if lib = Library.instance(name)
|
552
|
-
# lib.load(File.join(*rest))
|
553
|
-
# else
|
554
|
-
# Kernel.load(file, wrap)
|
555
|
-
# end
|
556
|
-
# end
|
557
|
-
# end
|
558
|
-
|
559
|
-
# Require script.
|
560
|
-
def load(file, wrap=false)
|
561
|
-
lib, path = *Kernel.parse_load_parameters(file)
|
562
|
-
if lib
|
563
|
-
lib.load(path, wrap)
|
564
|
-
else
|
565
|
-
Kernel.load(file, wrap)
|
566
|
-
end
|
567
|
-
end
|
288
|
+
# Is there a <tt>data/</tt> location?
|
289
|
+
def datadir? ; File.exist?(datadir) ; end
|
568
290
|
|
569
|
-
#
|
570
|
-
|
571
|
-
|
572
|
-
# name, file = file.split(':')
|
573
|
-
# if name == ''
|
574
|
-
# Kernel.autoload(base, file)
|
575
|
-
# elsif lib = Library.instance(name)
|
576
|
-
# lib.autoload(base, file)
|
577
|
-
# else
|
578
|
-
# raise LoadError, "no library found -- #{name}"
|
579
|
-
# end
|
580
|
-
# else
|
581
|
-
# name, *rest = file.split('/')
|
582
|
-
# if lib = Library.instance(name)
|
583
|
-
# lib.autoload(base, File.join(*rest))
|
584
|
-
# else
|
585
|
-
# Kernel.autoload(base, file)
|
586
|
-
# end
|
587
|
-
# end
|
588
|
-
# end
|
589
|
-
|
590
|
-
=begin
|
591
|
-
# Autoload script.
|
592
|
-
def autoload(base, file)
|
593
|
-
lib, path = *Kernel.parse_load_parameters(file)
|
594
|
-
if lib
|
595
|
-
lib.autoload(base, path)
|
596
|
-
else
|
597
|
-
Kernel.autoload(base, file)
|
291
|
+
# Access to secondary metadata.
|
292
|
+
def metadata
|
293
|
+
@metadata ||= Metadata.new(location)
|
598
294
|
end
|
599
|
-
end
|
600
|
-
=end
|
601
295
|
|
602
|
-
|
603
|
-
|
604
|
-
# TODO
|
605
|
-
class ::Module
|
296
|
+
private
|
606
297
|
|
607
|
-
|
608
|
-
|
298
|
+
#
|
299
|
+
#def lookup_glob
|
300
|
+
# @lookup_glob ||= File.join(location, '{' + loadpath.join(',') + '}')
|
301
|
+
#end
|
609
302
|
|
610
|
-
|
611
|
-
|
612
|
-
|
613
|
-
|
614
|
-
|
615
|
-
|
616
|
-
|
303
|
+
#
|
304
|
+
def clean_backtrace(error)
|
305
|
+
if $DEBUG
|
306
|
+
error
|
307
|
+
else
|
308
|
+
bt = error.backtrace
|
309
|
+
bt = bt.reject{ |e| /roll/ =~ e } if bt
|
310
|
+
error.set_backtrace(bt)
|
311
|
+
error
|
312
|
+
end
|
617
313
|
end
|
618
|
-
end
|
619
|
-
=end
|
620
|
-
|
621
|
-
# TODO
|
622
314
|
|
623
|
-
|
624
|
-
|
625
|
-
# def module_require()
|
626
|
-
# end
|
627
|
-
|
628
|
-
# def module_load()
|
629
|
-
# end
|
315
|
+
end
|
630
316
|
|
631
317
|
end
|
632
318
|
|
633
|
-
# Prime the library ledger.
|
634
|
-
Library.scan
|
635
|
-
|