Class: Library

Inherits:
Object
  • Object
show all
Defined in:
lib/roll/library.rb

Overview

Library Class

The Library class serves as an objecified location in Ruby’s load paths.

The Library qua class also serves as the library manager, storing a ledger of available libraries.

A library is roll-ready when it supplies a #name-verison.roll file in either its base directory or in the base’s meta/ directory. The roll file name is specifically designed to make library lookup fast. There is no need for Rolls to open the roll file until an actual version is used. It also gives the most flexability in repository layout. Rolls searches up to three subdirs deep looking for roll files. This is suitable to non-versioned libs, versioned libs, non-versioned subprojects and subprojects, including typical Subversion repository layouts.

Defined Under Namespace

Classes: VersionConflict, VersionError

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(location, identity = nil) ⇒ Library

New libray.



86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/roll/library.rb', line 86

def initialize(location, identity=nil) #name, version, location=nil)
  @location = location

  if identity
    @name      = identity[:name]
    @version   = identity[:version]
    @load_path = identity[:load_path] || identity[:load_paths]
  else
    identify(location)
  end

  raise unless @name
  raise unless @version

  @identity = identity

  # TODO Version number needs to be more flexiable in handling non-numeric tuples.
  @version = VersionNumber.new(@version) unless VersionNumber === @version
end

Instance Attribute Details

#locationObject (readonly)

Path to library.



83
84
85
# File 'lib/roll/library.rb', line 83

def location
  @location
end

#nameObject (readonly)

Name of library.



77
78
79
# File 'lib/roll/library.rb', line 77

def name
  @name
end

#versionObject (readonly)

Version of library. This is a VersionNumber object.



80
81
82
# File 'lib/roll/library.rb', line 80

def version
  @version
end

Class Method Details

.dlextObject

Dynamic link extension.



57
58
59
# File 'lib/roll/library.rb', line 57

def self.dlext
  @dlext ||= '.' + ::Config::CONFIG['DLEXT']
end

.instance(name, constraint = nil) ⇒ Object Also known as: []

Libraries are Singleton pattern.



379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
# File 'lib/roll/library.rb', line 379

def instance(name, constraint=nil)
  name = name.to_s
  #raise "no library -- #{name}" unless @ledger.include?( name )
  return nil unless @ledger.include?(name)
  case lib = @ledger[name]
  when Library
    return lib unless constraint
    raise VersionConflict, "previously selected library version" # -- #{lib.version}"
  #when Version
  #  @ledger[name] = new(lib.location, :name=>name, :version=>lib) #new(name, lib, lib.location)
  when Array
    if constraint
      compare = VersionNumber.constrant_lambda(constraint)
      version = lib.select(&compare).max
    else
      version = lib.max
    end
    unless version
      raise VersionError, "no library version -- #{name} #{constraint}"
    end
    @ledger[name] = version #new(version.location, :name=>name, :version=>version) #new(name, version, version.location)
  else
    raise "this should never happen"
  end
  @ledger[name].roll  # Make sure the roll file is loaded.
  @ledger[name]
end

.listObject

Return a list of library names.



374
375
376
# File 'lib/roll/library.rb', line 374

def list
  @ledger.keys
end

.load_pathObject



67
68
69
# File 'lib/roll/library.rb', line 67

def self.load_path
  $LOAD_PATH
end

.load_siteObject

Location of rolls-ready libs.



62
63
64
# File 'lib/roll/library.rb', line 62

def self.load_site
  $LOAD_SITE
end

.open(name, constraint = nil) {|lib| ... } ⇒ Object

Same as #instance but will raise and error if the library is not found.

Yields:

  • (lib)


411
412
413
414
415
416
417
418
# File 'lib/roll/library.rb', line 411

def open(name, constraint=nil, &yld)
  lib = instance(name, constraint)
  unless lib
    raise LoadError, "no library -- #{name}"
  end
  yield(lib) if yld
  lib
end

.ruby_pathObject



72
73
74
# File 'lib/roll/library.rb', line 72

def self.ruby_path
  $RUBY_PATH
end

.scanObject

Scan the site locations for libraries.



317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
# File 'lib/roll/library.rb', line 317

def scan
  # First we add Ruby core and standard libraries.
  @ledger['ruby'] = Library.new(nil, :name=>'ruby', :version=>VERSION, :load_path=>Library.ruby_path)

  scan_working() if $DEBUG

  projs1 = Dir.glob( '{' + $LOAD_SITE.join(',') + '}/*{/meta,}/*.roll', File::FNM_CASEFOLD )
  projs2 = Dir.glob( '{' + $LOAD_SITE.join(',') + '}/*/*{/meta,}/*.roll', File::FNM_CASEFOLD )
  projs3 = Dir.glob( '{' + $LOAD_SITE.join(',') + '}/*/*/*{/meta,}/*.roll', File::FNM_CASEFOLD )

  projs = projs1 + projs2 + projs3

  #dirs = projs.collect do |prj|
  #  metafile = File.basename(prj)
  #  dir = File.dirname(prj)
  #  dir = File.dirname(dir) if dir =~ /meta$/
  #  dir
  #end

  projs.uniq!

  #dirs -= $LOAD_SITE

  projs.each do |proj|
    name, ver = *File.basename(proj).chomp('.roll').split('-')
    dir = File.dirname(proj)
    dir = File.dirname(dir) if File.basename(dir) == 'meta'

    name = name.downcase

    #if versions.empty?
    #  @ledger[name] ||= Library.new(dir, :name=>name, :version=>'0') #Version.new('0', dir)
    #else
      @ledger[name] ||= []
      @ledger[name] << Library.new(dir, :name=>name, :version=>ver)
    #end
  end
end

.scan_workingObject

Scan current working location to see if there’s a library. This will ascend from the current working directy to one level below root looking for a lib/ directory. – TODO CHANGE TO LOOK FRO INDEX FILE. ++



363
364
365
366
367
368
369
370
371
# File 'lib/roll/library.rb', line 363

def scan_working
  paths = Dir.pwd.split('/')
  (paths.size-1).downto(1) do |n|
    dir = File.join( *(paths.slice(0..n) << 'lib') )
    if File.directory? dir
      $LOAD_SITE.unshift dir
    end
  end
end

Instance Method Details

#<=>(other) ⇒ Object

Compare by version.



164
165
166
# File 'lib/roll/library.rb', line 164

def <=>(other)
  version <=> other.verison
end

#autoload(base, file) ⇒ Object

Library specific autoload.



263
264
265
266
267
268
269
# File 'lib/roll/library.rb', line 263

def autoload(base, file)
  if path = require_find(file)
    Kernel.autoload(base, file)
  else
    raise LoadError, "no such file to autoload -- #{name}:#{file}"
  end
end

#bin_pathObject

List of subdirectories that are searched for binaries. ++ TODO I think it would be better just to make this a fix convention that bin/ is always the place to put these. (Unlike lib/ which needs to be more flexable.) –



189
190
191
192
193
194
195
196
197
198
199
200
201
202
# File 'lib/roll/library.rb', line 189

def bin_path
  return @bin_path if @bin_path
  return [] unless location  # NEED TO DO THIS BETTER.
  if roll.bin_path
    @bin_path = roll.bin_path.collect{ |path| File.join(location, path) }
  else
    if File.directory?(File.join(location, 'bin'))
      @bin_path = [File.join(location, 'bin')]
    else
      @bin_path = []
    end
  end
  return @bin_path
end

#confdirObject

Return the path to the configuration directory. – Can or should configuration directories be versioned? ++



221
222
223
224
225
226
227
228
# File 'lib/roll/library.rb', line 221

def confdir
  File.join(location, 'data')
  #if version
  #  File.join(Config::CONFIG['confdir'], name, version)
  #else
  #  File.join(Config::CONFIG['datadir'], name)
  #end
end

#datadir(versionless = false) ⇒ Object

Return the path to the data directory associated with the given package name. Normally this is just “#'datadir'/#package_name”, but may be modified by packages like RubyGems and Rolls to handle versioned data directories.



209
210
211
212
213
214
215
# File 'lib/roll/library.rb', line 209

def datadir(versionless=false)
  if version and not versionless
    File.join(Config::CONFIG['datadir'], name, version)
  else
    File.join(Config::CONFIG['datadir'], name)
  end
end

#identify(location) ⇒ Object

Identify a library based on it’s location.



107
108
109
110
111
112
# File 'lib/roll/library.rb', line 107

def identify(location)
  file = File.join(location,'{,meta/}*.roll')
  if file = Dir.glob(file).first
    @name, @version = file.chomp('.roll').split('-')
  end
end

#inspectObject

Inspection.



115
116
117
118
119
120
121
# File 'lib/roll/library.rb', line 115

def inspect
  if version
    "#<Library #{name}/#{version}>"
  else
    "#<Library #{name}>"
  end
end

#lib_pathObject Also known as: load_path, load_paths

List of subdirectories that are searched when loading libs. In general this should include all the libs internal load paths, so long as there will be no name conflicts between directories.



171
172
173
174
175
176
177
178
179
# File 'lib/roll/library.rb', line 171

def lib_path
  return unless roll # NEED TO DO THIS BETTER. THIS IS HERE FOR THE ONE 'ruby' CASE.
  return @load_path if @load_path
  if roll.load_path
    @load_path = roll.load_path.collect{ |path| File.join(location, path) }
  else
    @load_path = ['lib']  # ["lib/#{name}"]
  end
end

#load(file, wrap = nil) ⇒ Object

Library specific load.



254
255
256
257
258
259
260
# File 'lib/roll/library.rb', line 254

def load(file, wrap=nil)
  if path = load_find(file)
    Kernel.load(path, wrap)
  else
    raise LoadError, "no such file to load -- #{name}:#{file}"
  end
end

#load_find(file) ⇒ Object

Load find.



238
239
240
241
242
# File 'lib/roll/library.rb', line 238

def load_find(file)
  file = roll.index_file if (file.nil? or file.empty?)
  glob = File.join('{' + load_path.join(',') + '}', file)
  Dir.glob(glob).first
end

#load_rollObject

Read roll file.

Raises:

  • (LoadError)


129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
# File 'lib/roll/library.rb', line 129

def load_roll
  return unless location  # NEED TO DO THIS BETTER. THIS IS HERE FOR THE ONE 'ruby' CASE.
  raise LoadError unless File.directory?(location)
  glob = File.join(location, "{,meta/}*.roll")  # "{,meta/}#{name}-#{version}.roll"
  file = Dir.glob(glob, File::FNM_CASEFOLD).first
  if file
    @roll_file = file
    @roll = Roll::Package.open(file, :name=>name, :version=>version.to_s)
  else
    raise "THIS SHOULD NOT POSSIBLE!"
    #@roll = false #Roll::Package.new # THIS IN NO LONGER POSSIBLE
  end
  #use #?
  return @roll
end

#module_autoload(mod, base, file) ⇒ Object

Library specific autoload for module.



290
291
292
293
294
295
296
# File 'lib/roll/library.rb', line 290

def module_autoload(mod, base, file)
  if path = require_find(file)
    mod.autoload_without_roll(base, file)
  else
    raise LoadError, "no such file to autoload -- #{name}:#{file}"
  end
end

#module_load(mod, file) ⇒ Object

Load into module.



281
282
283
284
285
286
287
# File 'lib/roll/library.rb', line 281

def module_load(mod, file)
  if path = load_find(file)
    mod.module_load(path)  # FIXME
  else
    raise LoadError, "no such file to load -- #{name}:#{file}"
  end
end

#module_require(mod, file) ⇒ Object

Require into module.



272
273
274
275
276
277
278
# File 'lib/roll/library.rb', line 272

def module_require(mod, file)
  if path = require_find(file)
    mod.module_require(path)  # FIXME
  else
    raise LoadError, "no such file to load -- #{name}:#{file}"
  end
end

#require(file) ⇒ Object

Library specific #require.



245
246
247
248
249
250
251
# File 'lib/roll/library.rb', line 245

def require(file)
  if path = require_find(file)
    Kernel.require(path)
  else
    raise LoadError, "no such file to load -- #{name}:#{file}"
  end
end

#require_find(file) ⇒ Object

Require find.



231
232
233
234
235
# File 'lib/roll/library.rb', line 231

def require_find(file)
  file = roll.index_file if (file.nil? or file.empty?)
  glob = File.join('{' + load_path.join(',') + '}', file + "{.rb,#{Library.dlext},}")
  Dir.glob(glob).first
end

#rollObject Also known as: info

Meta information about the libray.



157
158
159
160
# File 'lib/roll/library.rb', line 157

def roll
  @roll = load_roll if @roll.nil?  # If it's false, we don't have one.
  @roll
end

#roll_fileObject



123
124
125
126
# File 'lib/roll/library.rb', line 123

def roll_file
  find = "{,meta/}*.roll"  # "{,meta/}#{name}-#{version}.roll"
  file = Dir.glob(File.join(location, find), File::FNM_CASEFOLD).first
end

#utilizeObject

Put the libs load paths into the global lookup. – TODO Maybe call ‘import’ instead? ++



302
303
304
305
306
307
308
# File 'lib/roll/library.rb', line 302

def utilize
  lib_path.each do |path|
    Library.load_path.unshift(path)
  end
  Library.load_path.uniq!
  self
end