├── .ruby ├── var ├── title ├── created ├── name ├── version ├── organization ├── summary ├── authors ├── copyrights ├── repositories ├── resources ├── ronn │ └── center.css ├── description └── requirements ├── lib ├── realms.yml ├── ealms.rb ├── realms │ ├── errors.rb │ ├── core_ext.rb │ ├── errors │ │ ├── version_conflict.rb │ │ ├── validation_error.rb │ │ └── load_error.rb │ ├── core_ext │ │ ├── file.rb │ │ ├── hash.rb │ │ ├── gem.rb │ │ └── rbconfig.rb │ ├── version.rb │ ├── index.rb │ ├── shell │ │ ├── unlock.rb │ │ ├── where.rb │ │ ├── add.rb │ │ ├── lock.rb │ │ ├── gem.rb │ │ ├── show.rb │ │ ├── path.rb │ │ ├── remove.rb │ │ ├── dump.rb │ │ ├── help.rb │ │ ├── verify.rb │ │ ├── isolate.rb │ │ └── list.rb │ ├── shell.rb │ ├── kernel.rb │ ├── rubylib.rb │ ├── interface.rb │ └── metadata.rb └── realms.rb ├── demo ├── applique │ ├── ae.rb │ ├── project.rb │ ├── realms.rb │ └── fixtures.rb ├── 01_application │ ├── applique │ │ └── fixtures.rb │ ├── 01_loading.md │ ├── 05_utils.md │ ├── 03_manager.md │ └── 02_library.md ├── fixtures │ └── projects │ │ ├── tryme │ │ ├── 1.0 │ │ │ ├── .ruby │ │ │ │ ├── name │ │ │ │ └── version │ │ │ ├── lib │ │ │ │ └── tryme.rb │ │ │ ├── bin │ │ │ │ └── tryme │ │ │ ├── Index.yml │ │ │ └── .index │ │ └── 1.1 │ │ │ ├── .ruby │ │ │ ├── name │ │ │ └── version │ │ │ ├── lib │ │ │ └── tryme.rb │ │ │ ├── bin │ │ │ └── tryme │ │ │ ├── Index.yml │ │ │ └── .index │ │ └── foo │ │ ├── lib │ │ └── foo.rb │ │ ├── Index.yml │ │ └── .index ├── 02_commandline │ ├── applique │ │ ├── fixtures.rb │ │ └── bash.rb │ ├── 05_list.md │ ├── 04_show.md │ ├── 03_rm.md │ ├── 11_gem.md │ ├── 09_verify.md │ ├── 13_where.md │ ├── 10_isolate.md │ ├── 12_path.md │ ├── 02_add.md │ └── 06_sync.md └── helpers │ ├── new_project.rdoc │ └── projects.rdoc ├── script ├── install-current.sh ├── install-0.2.0.sh └── install-master.sh ├── spec ├── fixtures │ └── projects │ │ ├── tryme │ │ ├── 1.0 │ │ │ ├── .ruby │ │ │ │ ├── name │ │ │ │ └── version │ │ │ ├── lib │ │ │ │ └── tryme.rb │ │ │ ├── bin │ │ │ │ └── tryme │ │ │ ├── Index.yml │ │ │ └── .index │ │ └── 1.1 │ │ │ ├── .ruby │ │ │ ├── name │ │ │ └── version │ │ │ ├── lib │ │ │ └── tryme.rb │ │ │ ├── bin │ │ │ └── tryme │ │ │ ├── Index.yml │ │ │ └── .index │ │ └── foo │ │ ├── lib │ │ └── foo.rb │ │ ├── Index.yml │ │ └── .index ├── spec_metadata.rb ├── runner.rb ├── spec_utils.rb ├── spec_kernel.rb ├── spec_manager.rb ├── helper.rb └── spec_library.rb ├── work ├── studies │ ├── load-speeds │ │ ├── example │ │ │ ├── name │ │ │ ├── date │ │ │ ├── loadpath │ │ │ ├── version │ │ │ └── require │ │ ├── example.json │ │ ├── example.yaml │ │ ├── example.rb │ │ └── benchmark.rb │ └── yaml-date.rb ├── deprecated │ ├── commands │ │ ├── man │ │ │ ├── .gitignore │ │ │ ├── roll-use.1.ronn │ │ │ ├── roll-copy.1.ronn │ │ │ └── roll-merge.1.ronn │ │ ├── lib │ │ │ └── realms │ │ │ │ └── shell │ │ │ │ ├── copy.rb │ │ │ │ ├── merge.rb │ │ │ │ └── use.rb │ │ └── demo │ │ │ └── 02_commandline │ │ │ ├── 08_merge.md │ │ │ ├── 07_copy.md │ │ │ └── 01_use.md │ ├── version_case.rb │ ├── once-again-into-the-breach │ │ ├── kernel.rb │ │ └── library.rb │ ├── 04_version.md │ └── xdg.rb ├── benchmarks │ ├── rubygems.roll │ ├── check.rb │ ├── profile.rb │ ├── vsgems_bm.rb │ ├── vsgems_timed.rb │ └── serializers.rb ├── reference │ ├── old-user-guide │ │ ├── red_ball.jpg │ │ ├── layout.rhtml │ │ └── Rakefile │ ├── monitor.rb │ ├── require.rb │ ├── configuration.rb │ ├── README.rdoc │ └── console.rb ├── .rsync-filter ├── consider │ ├── monitor.rb │ ├── autoload.rb │ ├── import-old.rb │ ├── plugin.rb │ ├── fake_gem.rb │ ├── import.rb │ └── version.rb └── sandbox │ └── library_on_index.rb ├── .yardopts ├── .travis.yml ├── .gitignore ├── bin └── realm ├── man ├── realm.1.ronn ├── realm-sync.1.ronn ├── realm-rm.1.ronn ├── realm-isolate.1.ronn ├── realm-path.1.ronn ├── realm-verify.1.ronn ├── realm-list.1.ronn ├── realm-show.1.ronn ├── realm-add.1.ronn └── realm-gem.1.ronn ├── Gemfile ├── Rulefile ├── Assembly ├── LICENSE.txt ├── MANIFEST ├── .index ├── HISTORY.md ├── README.md └── .gemspec /.ruby: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /var/title: -------------------------------------------------------------------------------- 1 | Roll 2 | -------------------------------------------------------------------------------- /lib/realms.yml: -------------------------------------------------------------------------------- 1 | ../.index -------------------------------------------------------------------------------- /var/created: -------------------------------------------------------------------------------- 1 | 2006-12-10 -------------------------------------------------------------------------------- /var/name: -------------------------------------------------------------------------------- 1 | realms 2 | -------------------------------------------------------------------------------- /var/version: -------------------------------------------------------------------------------- 1 | 2.0.0 2 | -------------------------------------------------------------------------------- /var/organization: -------------------------------------------------------------------------------- 1 | Rubyworks -------------------------------------------------------------------------------- /demo/applique/ae.rb: -------------------------------------------------------------------------------- 1 | require 'ae' 2 | -------------------------------------------------------------------------------- /demo/01_application/applique/fixtures.rb: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /script/install-current.sh: -------------------------------------------------------------------------------- 1 | install-0.2.0.sh -------------------------------------------------------------------------------- /demo/fixtures/projects/tryme/1.0/.ruby/name: -------------------------------------------------------------------------------- 1 | tryme -------------------------------------------------------------------------------- /demo/fixtures/projects/tryme/1.1/.ruby/name: -------------------------------------------------------------------------------- 1 | tryme -------------------------------------------------------------------------------- /spec/fixtures/projects/tryme/1.0/.ruby/name: -------------------------------------------------------------------------------- 1 | tryme -------------------------------------------------------------------------------- /spec/fixtures/projects/tryme/1.1/.ruby/name: -------------------------------------------------------------------------------- 1 | tryme -------------------------------------------------------------------------------- /var/summary: -------------------------------------------------------------------------------- 1 | Ruby Object-Oriented Library Ledger -------------------------------------------------------------------------------- /work/studies/load-speeds/example/name: -------------------------------------------------------------------------------- 1 | foo 2 | -------------------------------------------------------------------------------- /demo/fixtures/projects/tryme/1.0/.ruby/version: -------------------------------------------------------------------------------- 1 | 1.0 -------------------------------------------------------------------------------- /demo/fixtures/projects/tryme/1.1/.ruby/version: -------------------------------------------------------------------------------- 1 | 1.1 -------------------------------------------------------------------------------- /spec/fixtures/projects/tryme/1.0/.ruby/version: -------------------------------------------------------------------------------- 1 | 1.0 -------------------------------------------------------------------------------- /spec/fixtures/projects/tryme/1.1/.ruby/version: -------------------------------------------------------------------------------- 1 | 1.1 -------------------------------------------------------------------------------- /var/authors: -------------------------------------------------------------------------------- 1 | --- 2 | - Trans 3 | -------------------------------------------------------------------------------- /work/studies/load-speeds/example/date: -------------------------------------------------------------------------------- 1 | 2010-10-01 2 | -------------------------------------------------------------------------------- /work/studies/load-speeds/example/loadpath: -------------------------------------------------------------------------------- 1 | lib 2 | -------------------------------------------------------------------------------- /work/studies/load-speeds/example/version: -------------------------------------------------------------------------------- 1 | 1.3.0 2 | -------------------------------------------------------------------------------- /work/studies/load-speeds/example/require: -------------------------------------------------------------------------------- 1 | facets >2.8 2 | -------------------------------------------------------------------------------- /var/copyrights: -------------------------------------------------------------------------------- 1 | --- 2 | - 2006 Thomas Sawyer (BSD-2-Clause) 3 | -------------------------------------------------------------------------------- /work/deprecated/commands/man/.gitignore: -------------------------------------------------------------------------------- 1 | *.gz 2 | *.html 3 | -------------------------------------------------------------------------------- /demo/fixtures/projects/foo/lib/foo.rb: -------------------------------------------------------------------------------- 1 | $foo_message = "Foo 0.8.2" 2 | -------------------------------------------------------------------------------- /lib/ealms.rb: -------------------------------------------------------------------------------- 1 | #require_relative 'reamls' 2 | require 'realms' 3 | -------------------------------------------------------------------------------- /spec/fixtures/projects/foo/lib/foo.rb: -------------------------------------------------------------------------------- 1 | $foo_message = "Foo 0.8.2" 2 | -------------------------------------------------------------------------------- /demo/fixtures/projects/tryme/1.0/lib/tryme.rb: -------------------------------------------------------------------------------- 1 | $tryme_message = "Try Me v1.0" -------------------------------------------------------------------------------- /demo/fixtures/projects/tryme/1.1/lib/tryme.rb: -------------------------------------------------------------------------------- 1 | $tryme_message = "Try Me v1.1" -------------------------------------------------------------------------------- /spec/fixtures/projects/tryme/1.0/lib/tryme.rb: -------------------------------------------------------------------------------- 1 | $tryme_message = "Try Me v1.0" -------------------------------------------------------------------------------- /spec/fixtures/projects/tryme/1.1/lib/tryme.rb: -------------------------------------------------------------------------------- 1 | $tryme_message = "Try Me v1.1" -------------------------------------------------------------------------------- /var/repositories: -------------------------------------------------------------------------------- 1 | --- 2 | upstream: git://github.com/rubyworks/roll.git 3 | -------------------------------------------------------------------------------- /demo/fixtures/projects/tryme/1.0/bin/tryme: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require 'tryme' 3 | -------------------------------------------------------------------------------- /demo/fixtures/projects/tryme/1.1/bin/tryme: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require 'tryme' 3 | -------------------------------------------------------------------------------- /spec/fixtures/projects/tryme/1.0/bin/tryme: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require 'tryme' 3 | -------------------------------------------------------------------------------- /spec/fixtures/projects/tryme/1.1/bin/tryme: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require 'tryme' 3 | -------------------------------------------------------------------------------- /.yardopts: -------------------------------------------------------------------------------- 1 | --title "Rolling with Ruby" 2 | --output "site/doc" 3 | --protected 4 | lib 5 | - [A-Z][A-Z]* 6 | -------------------------------------------------------------------------------- /spec/spec_metadata.rb: -------------------------------------------------------------------------------- 1 | require_relative 'helper' 2 | 3 | describe Realms::Library::Metadata do 4 | 5 | end 6 | -------------------------------------------------------------------------------- /work/studies/load-speeds/example.json: -------------------------------------------------------------------------------- 1 | {"name": "foo", "version": "1.3.0", "loadpath": ["lib"], "date": "2010-10-10"} 2 | -------------------------------------------------------------------------------- /work/studies/load-speeds/example.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | name: foo 3 | version: 1.3.0 4 | loadpath: [lib] 5 | date: 2010-10-10 6 | -------------------------------------------------------------------------------- /work/benchmarks/rubygems.roll: -------------------------------------------------------------------------------- 1 | /home/trans/.rbenv/versions/1.9.3-rc1/lib/ruby/gems/1.9.1/gems/* 2 | /home/trans/.gem/ruby/1.9.1/gems/* 3 | -------------------------------------------------------------------------------- /work/reference/old-user-guide/red_ball.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/rubyworks/realms/master/work/reference/old-user-guide/red_ball.jpg -------------------------------------------------------------------------------- /lib/realms/errors.rb: -------------------------------------------------------------------------------- 1 | require_relative 'errors/load_error' 2 | require_relative 'errors/validation_error' 3 | require_relative 'errors/version_conflict' 4 | -------------------------------------------------------------------------------- /demo/fixtures/projects/foo/Index.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: foo 3 | version: 0.8.2 4 | 5 | title: Foo 6 | 7 | authors: 8 | - Thomas Sawyer 9 | 10 | -------------------------------------------------------------------------------- /spec/fixtures/projects/foo/Index.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: foo 3 | version: 0.8.2 4 | 5 | title: Foo 6 | 7 | authors: 8 | - Thomas Sawyer 9 | 10 | -------------------------------------------------------------------------------- /var/resources: -------------------------------------------------------------------------------- 1 | --- 2 | home: http://rubyworks.github.com/roll 3 | code: http://rubyworks.github.com/roll 4 | mail: http://groups.google.com/groups/rubyworks-mailinglist 5 | 6 | -------------------------------------------------------------------------------- /demo/02_commandline/applique/fixtures.rb: -------------------------------------------------------------------------------- 1 | When "given an empty cache" do 2 | ledger = Realms::Library::Utils.lock_file 3 | File.open(ledger, 'w'){ |f| f << '{}' } 4 | end 5 | 6 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | --- 2 | language: ruby 3 | script: "bundle exec ruby spec/runner.rb | tapout" 4 | rvm: 5 | - 1.9.2 6 | - 1.9.3 7 | - rbx-19mode 8 | - jruby-19mode 9 | 10 | -------------------------------------------------------------------------------- /lib/realms/core_ext.rb: -------------------------------------------------------------------------------- 1 | require_relative 'core_ext/file' 2 | require_relative 'core_ext/hash' 3 | 4 | require_relative 'core_ext/gem' 5 | #require_relative 'core_ext/rbconfig' 6 | 7 | -------------------------------------------------------------------------------- /var/ronn/center.css: -------------------------------------------------------------------------------- 1 | #man {position: relative; max: 800px; margin: 0 auto; padding-left: 200px;} 2 | .man-navigation{ left:auto; left: 0; width:200px; border-right:1px solid #dbdbdb; } 3 | -------------------------------------------------------------------------------- /var/description: -------------------------------------------------------------------------------- 1 | Rolls is a library set manager for Ruby built on top of the Library gem. 2 | With Rolls, code repositories can be made visible to Ruby just by setting 3 | an environment variable. 4 | -------------------------------------------------------------------------------- /work/.rsync-filter: -------------------------------------------------------------------------------- 1 | - .svn 2 | - .svn 3 | - scrap 4 | P usage 5 | P statcvs 6 | P statsvn 7 | P robot.txt 8 | P wiki 9 | P usage 10 | P statcvs 11 | P statsvn 12 | P robot.txt 13 | P wiki 14 | -------------------------------------------------------------------------------- /work/studies/load-speeds/example.rb: -------------------------------------------------------------------------------- 1 | { 2 | 'name'=>'roll', 3 | 'version'=>'1.3.0', 4 | 'loadpath'=>nil, 5 | 'date'=>'2010-10-10', 6 | 'requires'=>[['facets', '2.8.4+']], 7 | 'buildreqs'=>[['qed']] 8 | } 9 | -------------------------------------------------------------------------------- /demo/fixtures/projects/tryme/1.0/Index.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: tryme 3 | version: "1.0" 4 | 5 | title: TryMe 6 | 7 | authors: 8 | - Thomas Sawyer 9 | 10 | resources: 11 | homepage: http://tryme.foo 12 | -------------------------------------------------------------------------------- /spec/fixtures/projects/tryme/1.0/Index.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: tryme 3 | version: "1.0" 4 | 5 | title: TryMe 6 | 7 | authors: 8 | - Thomas Sawyer 9 | 10 | resources: 11 | homepage: http://tryme.foo 12 | -------------------------------------------------------------------------------- /spec/runner.rb: -------------------------------------------------------------------------------- 1 | require 'minitest/autorun' 2 | 3 | dir = File.dirname(__FILE__) 4 | 5 | Dir.entries(dir).each do |spec| 6 | next unless spec.start_with?('spec_') 7 | require_relative spec 8 | end 9 | 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .setup 2 | .rdoc 3 | .yardoc 4 | doc/rdoc 5 | man/*.gz 6 | man/*.html 7 | man/*.1 8 | log 9 | pkg 10 | site/doc 11 | site/rdoc 12 | site/yard 13 | site/manual 14 | tmp 15 | web 16 | wiki 17 | work/sandbox 18 | *.lock 19 | -------------------------------------------------------------------------------- /lib/realms/errors/version_conflict.rb: -------------------------------------------------------------------------------- 1 | module Realms 2 | class Library 3 | 4 | # Raise when two versions come into conflict. 5 | # 6 | class VersionConflict < ::Version::Error 7 | end 8 | 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /var/requirements: -------------------------------------------------------------------------------- 1 | --- 2 | - versus 3 | - autoload 4 | - qed (test) 5 | - ae (test) 6 | - minitest (test) 7 | - minitap (test) 8 | - tapout (test) 9 | - detroit (build) 10 | - setup 5.0+ (build) 11 | 12 | -------------------------------------------------------------------------------- /lib/realms/errors/validation_error.rb: -------------------------------------------------------------------------------- 1 | module Realms 2 | class Library 3 | 4 | # Library ValidationError is raised when library metadata is not conforming. 5 | # 6 | class ValidationError < ::RuntimeError 7 | end 8 | 9 | end 10 | end 11 | -------------------------------------------------------------------------------- /lib/realms/core_ext/file.rb: -------------------------------------------------------------------------------- 1 | class File 2 | 3 | # 4 | RE_PATH_SEPERATOR = Regexp.new('[' + Regexp.escape(File::Separator) + %q{\\\/} + ']') 5 | 6 | # 7 | def self.split_root(path) 8 | path.split(RE_PATH_SEPERATOR, 2) 9 | end 10 | 11 | end 12 | 13 | -------------------------------------------------------------------------------- /demo/fixtures/projects/tryme/1.1/Index.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: 3 | tryme 4 | 5 | version: 6 | "1.1" 7 | 8 | title: 9 | TryMe 10 | 11 | authors: 12 | - Thomas Sawyer 13 | 14 | resources: 15 | homepage: http://tryme.foo 16 | 17 | requirements: 18 | - foo 0.8+ 19 | -------------------------------------------------------------------------------- /spec/fixtures/projects/tryme/1.1/Index.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: 3 | tryme 4 | 5 | version: 6 | "1.1" 7 | 8 | title: 9 | TryMe 10 | 11 | authors: 12 | - Thomas Sawyer 13 | 14 | resources: 15 | homepage: http://tryme.foo 16 | 17 | requirements: 18 | - foo 0.8+ 19 | -------------------------------------------------------------------------------- /bin/realm: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | require 'realms' unless defined?(::Realms) 3 | require 'realms/shell' 4 | 5 | ARGV.shift if ARGV.first == '-' 6 | 7 | begin 8 | Realms::Library::Shell.main(*ARGV) 9 | rescue => err 10 | raise err if $DEBUG 11 | $stderr.puts(err.message) 12 | exit -1 13 | end 14 | 15 | -------------------------------------------------------------------------------- /work/reference/old-user-guide/layout.rhtml: -------------------------------------------------------------------------------- 1 | 2 | 3 | RUBY ROLLS 4 | 8 | 9 | 10 |
11 | <%= yield %> 12 |
13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /lib/realms/version.rb: -------------------------------------------------------------------------------- 1 | module Realms 2 | class Library 3 | 4 | # The Library::Version class is essentially a tuple (immutable array) 5 | # with special comparision operators. 6 | # 7 | # TODO: Get rid of this! 8 | # 9 | class Version < ::Version::Number 10 | end 11 | 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /spec/spec_utils.rb: -------------------------------------------------------------------------------- 1 | require_relative 'helper' 2 | 3 | describe Realms::Library::Utils do 4 | 5 | it "should get lookup paths from RUBY_LIBRARY environment if set" do 6 | lib_paths = Library::Utils.lookup_paths 7 | env_paths = ENV['RUBY_LIBRARY'].split(/[:;]/) 8 | assert lib_paths = env_paths 9 | end 10 | 11 | end 12 | -------------------------------------------------------------------------------- /man/realm.1.ronn: -------------------------------------------------------------------------------- 1 | realm(1) 2 | ======== 3 | 4 | ## Realm Commands 5 | 6 | realm-add(1) 7 | 8 | realm-gem(1) 9 | 10 | realm-isolate(1) 11 | 12 | realm-list(1) 13 | 14 | realm-path(1) 15 | 16 | realm-rm(1) 17 | 18 | realm-show(1) 19 | 20 | realm-sync(1) 21 | 22 | realm-verify(1) 23 | 24 | realm-where(1) 25 | 26 | -------------------------------------------------------------------------------- /man/realm-sync.1.ronn: -------------------------------------------------------------------------------- 1 | realm-sync(1) -- synchronize the load cache 2 | =========================================== 3 | 4 | ## SYNOPSIS 5 | 6 | `realm-sync` [] 7 | 8 | ## DESCRIPTION 9 | 10 | `realm-sync` synchronizes the load cache to the load environment setting given 11 | by the `RUBY_LIBRARY` environment variable. 12 | 13 | ## SEE ALSO 14 | 15 | realm(1), realm-gem(1) 16 | 17 | -------------------------------------------------------------------------------- /work/benchmarks/check.rb: -------------------------------------------------------------------------------- 1 | require 'open3' 2 | require 'benchmark' 3 | 4 | def run(cmd) 5 | Open3.popen3(cmd) do |stdin, stdout, stderr| 6 | out = stdout.read 7 | err = stderr.read 8 | puts out unless out.empty? 9 | puts err unless err.empty? 10 | end 11 | end 12 | 13 | run %[export RUBY_LIBRARY="$GEM_PATH"; export RUBYOPT="-rolls"; ruby -e'require "nokogiri"'] 14 | 15 | -------------------------------------------------------------------------------- /work/consider/monitor.rb: -------------------------------------------------------------------------------- 1 | BEGIN { 2 | module Kernel 3 | 4 | h = Hash.new 5 | 6 | define_method(:requiree) do 7 | h 8 | end 9 | 10 | r = method :require 11 | 12 | define_method(:require) do |a| 13 | r.call(a) 14 | h[a] = caller 15 | end 16 | 17 | end 18 | } 19 | 20 | 21 | def p(*args) 22 | super *(args << caller[0]) 23 | end 24 | 25 | -------------------------------------------------------------------------------- /demo/02_commandline/05_list.md: -------------------------------------------------------------------------------- 1 | # List Command 2 | 3 | To see a list of available libraries use the `list` command. 4 | 5 | `realm list` 6 | 7 | The standard output will look like: 8 | 9 | foo ruby tryme 10 | 11 | Notice the entry for ruby. You won't find this project in our temporary 12 | projects location. It is a built-in library that represents Ruby's standard 13 | library. 14 | 15 | -------------------------------------------------------------------------------- /demo/02_commandline/04_show.md: -------------------------------------------------------------------------------- 1 | # Show Command 2 | 3 | As a developer managing the load environment you want to be able to easily 4 | inspect libraries in the environment. A simply review of any library 5 | can be obtained using `realm show`. 6 | 7 | `realm show tryme` 8 | 9 | A specific version of a library can be specified with the `-v` option. 10 | loadpaths. 11 | 12 | `realm show tryme -v 1.0` 13 | 14 | -------------------------------------------------------------------------------- /man/realm-rm.1.ronn: -------------------------------------------------------------------------------- 1 | roll-rm(1) -- remove path from the environment's load cache 2 | =========================================================== 3 | 4 | ## SYNOPSIS 5 | 6 | `roll-rm` [] 7 | 8 | ## DESCRIPTION 9 | 10 | `roll-rm` removes a path from the load cache, re-syning it in the process. 11 | If no `` is given the present working directory is used. 12 | 13 | ## SEE ALSO 14 | 15 | realm(1), realm-add(1) 16 | -------------------------------------------------------------------------------- /work/reference/old-user-guide/Rakefile: -------------------------------------------------------------------------------- 1 | namespace 'guide' do 2 | desc "build user guide" 3 | task :build do 4 | require 'erb' 5 | require 'redcloth' 6 | File.open('index.html', 'w') do |out| 7 | out << erb('layout.rhtml') do 8 | RedCloth.new(File.read('guide.tt')).to_html 9 | end 10 | end 11 | end 12 | end 13 | 14 | def erb(file) 15 | ERB.new(File.read(file)).result(binding) 16 | end 17 | 18 | -------------------------------------------------------------------------------- /lib/realms/core_ext/hash.rb: -------------------------------------------------------------------------------- 1 | class Hash 2 | 3 | # 4 | # Transform keys of hash returning a new hash. 5 | # 6 | def rekey #:yield: 7 | if block_given? 8 | inject({}){|h,(k,v)| h[yield(k)]=v; h} 9 | else 10 | inject({}){|h,(k,v)| h[k.to_sym]=v; h} 11 | end 12 | end 13 | 14 | # 15 | # In-place rekey. 16 | # 17 | def rekey! #:yield: 18 | replace(rekey{|k| yield(k) }) 19 | end 20 | 21 | end 22 | 23 | -------------------------------------------------------------------------------- /man/realm-isolate.1.ronn: -------------------------------------------------------------------------------- 1 | realm-isolate(1) -- produce a isolated environment for a project 2 | ================================================================ 3 | 4 | ## SYNOPSIS 5 | 6 | `realm isolate` 7 | 8 | ## DESCRIPTION 9 | 10 | `roll-isolate` produces a special environment specifically catered to the 11 | current project based on it's dependencies. 12 | 13 | ## SEE ALSO 14 | 15 | realm(1), realm-verify(1), realm-list(1) 16 | 17 | -------------------------------------------------------------------------------- /demo/01_application/01_loading.md: -------------------------------------------------------------------------------- 1 | # Load and Require 2 | 3 | The `library` method can be used to activate a library, constraining it to a 4 | particular version. 5 | 6 | library('tryme', '1.1') 7 | 8 | If we try to constrain a library to an incompatible version subsequent to this 9 | a `VersionConflict` exception will be raised. 10 | 11 | expect Realms::Library::VersionConflict do 12 | library('tryme', '1.0') 13 | end 14 | 15 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # encoding: utf-8 3 | 4 | source "http://rubygems.org" 5 | gemspec 6 | 7 | =begin 8 | gem "autoload" 9 | gem "versus" 10 | 11 | group :development do 12 | 13 | group :build do 14 | gem "detroit" 15 | gem "setup", ">= 5.0" 16 | end 17 | 18 | group :test do 19 | gem "qed" 20 | gem "ae" 21 | gem "minitest" 22 | gem "tapout" 23 | gem "minitap" 24 | end 25 | 26 | end 27 | =end 28 | 29 | -------------------------------------------------------------------------------- /demo/fixtures/projects/foo/.index: -------------------------------------------------------------------------------- 1 | --- 2 | type: ruby 3 | revision: 2013 4 | sources: 5 | - Index.yml 6 | authors: 7 | - name: Thomas Sawyer 8 | email: transfire@gmail.com 9 | organizations: [] 10 | requirements: [] 11 | conflicts: [] 12 | alternatives: [] 13 | resources: [] 14 | repositories: [] 15 | categories: [] 16 | paths: 17 | load: 18 | - lib 19 | copyrights: [] 20 | name: foo 21 | title: Foo 22 | version: 0.8.2 23 | date: '2013-01-16' 24 | -------------------------------------------------------------------------------- /spec/fixtures/projects/foo/.index: -------------------------------------------------------------------------------- 1 | --- 2 | type: ruby 3 | revision: 2013 4 | sources: 5 | - Index.yml 6 | authors: 7 | - name: Thomas Sawyer 8 | email: transfire@gmail.com 9 | organizations: [] 10 | requirements: [] 11 | conflicts: [] 12 | alternatives: [] 13 | resources: [] 14 | repositories: [] 15 | categories: [] 16 | paths: 17 | load: 18 | - lib 19 | copyrights: [] 20 | name: foo 21 | title: Foo 22 | version: 0.8.2 23 | date: '2013-01-16' 24 | -------------------------------------------------------------------------------- /man/realm-path.1.ronn: -------------------------------------------------------------------------------- 1 | realm-path(1) -- produce a unix-style path list 2 | =============================================== 3 | 4 | ## SYNOPSIS 5 | 6 | `realm path` 7 | 8 | ## DESCRIPTION 9 | 10 | `realm-path` prints out a UNIX style path list suitable for appending to the 11 | system $PATH variable. This allows executables located in library bin 12 | directories to be available via the command-line. 13 | 14 | ## SEE ALSO 15 | 16 | realm(1), realm-exec(1) 17 | 18 | -------------------------------------------------------------------------------- /man/realm-verify.1.ronn: -------------------------------------------------------------------------------- 1 | realm-verify(1) -- verify the availablity of a libraries dependencies 2 | ===================================================================== 3 | 4 | ## SYNOPSIS 5 | 6 | `realm verify` 7 | 8 | ## DESCRIPTION 9 | 10 | `realm-verify` runs through each of a project depenedencies, and their 11 | subsequent dependencies, to make sure that they can be met by the load 12 | environment. 13 | 14 | ## SEE ALSO 15 | 16 | realm(1), realm-isolate(1), realm-list(1) 17 | 18 | -------------------------------------------------------------------------------- /work/benchmarks/profile.rb: -------------------------------------------------------------------------------- 1 | require 'open3' 2 | require 'profile' 3 | 4 | $bench_env = File.dirname(__FILE__) + '/rubygems.roll' 5 | 6 | def run(cmd) 7 | cmd = %[export RUBY_LIBRARY="#{$bench_env}"; export RUBYOPT=""; ] + cmd 8 | Open3.popen3(cmd) do |stdin, stdout, stderr| 9 | out = stdout.read 10 | err = stderr.read 11 | puts out unless out.empty? 12 | puts err unless err.empty? 13 | end 14 | end 15 | 16 | run %[ruby -rprofile -roll -e'require "facets"'] 17 | 18 | -------------------------------------------------------------------------------- /demo/fixtures/projects/tryme/1.0/.index: -------------------------------------------------------------------------------- 1 | --- 2 | type: ruby 3 | revision: 2013 4 | sources: 5 | - Index.yml 6 | authors: 7 | - name: Thomas Sawyer 8 | organizations: [] 9 | requirements: [] 10 | conflicts: [] 11 | alternatives: [] 12 | resources: 13 | - type: homepage 14 | uri: http://tryme.foo 15 | label: Homepage 16 | repositories: [] 17 | categories: [] 18 | paths: 19 | load: 20 | - lib 21 | copyrights: [] 22 | name: tryme 23 | title: TryMe 24 | version: '1.0' 25 | date: '2013-01-16' 26 | -------------------------------------------------------------------------------- /spec/fixtures/projects/tryme/1.0/.index: -------------------------------------------------------------------------------- 1 | --- 2 | type: ruby 3 | revision: 2013 4 | sources: 5 | - Index.yml 6 | authors: 7 | - name: Thomas Sawyer 8 | organizations: [] 9 | requirements: [] 10 | conflicts: [] 11 | alternatives: [] 12 | resources: 13 | - type: homepage 14 | uri: http://tryme.foo 15 | label: Homepage 16 | repositories: [] 17 | categories: [] 18 | paths: 19 | load: 20 | - lib 21 | copyrights: [] 22 | name: tryme 23 | title: TryMe 24 | version: '1.0' 25 | date: '2013-01-16' 26 | -------------------------------------------------------------------------------- /demo/fixtures/projects/tryme/1.1/.index: -------------------------------------------------------------------------------- 1 | --- 2 | type: ruby 3 | revision: 2013 4 | sources: 5 | - Index.yml 6 | authors: 7 | - name: Thomas Sawyer 8 | organizations: [] 9 | requirements: 10 | - version: 0.8+ 11 | name: foo 12 | conflicts: [] 13 | alternatives: [] 14 | resources: 15 | - type: homepage 16 | uri: http://tryme.foo 17 | label: Homepage 18 | repositories: [] 19 | categories: [] 20 | paths: 21 | load: 22 | - lib 23 | copyrights: [] 24 | name: tryme 25 | title: TryMe 26 | version: '1.1' 27 | date: '2013-01-16' 28 | -------------------------------------------------------------------------------- /spec/fixtures/projects/tryme/1.1/.index: -------------------------------------------------------------------------------- 1 | --- 2 | type: ruby 3 | revision: 2013 4 | sources: 5 | - Index.yml 6 | authors: 7 | - name: Thomas Sawyer 8 | organizations: [] 9 | requirements: 10 | - version: 0.8+ 11 | name: foo 12 | conflicts: [] 13 | alternatives: [] 14 | resources: 15 | - type: homepage 16 | uri: http://tryme.foo 17 | label: Homepage 18 | repositories: [] 19 | categories: [] 20 | paths: 21 | load: 22 | - lib 23 | copyrights: [] 24 | name: tryme 25 | title: TryMe 26 | version: '1.1' 27 | date: '2013-01-16' 28 | -------------------------------------------------------------------------------- /man/realm-list.1.ronn: -------------------------------------------------------------------------------- 1 | realm-list(1) -- list available libraries in load environment 2 | ============================================================= 3 | 4 | ## SYNOPSIS 5 | 6 | `realm-list` 7 | 8 | ## DESCRIPTION 9 | 10 | `realm-list` prints a multi-column list of the names of the available libraries 11 | in the current roll environment. 12 | 13 | ## OPTIONS 14 | 15 | * `-v`/`--verbose` - Prodoces a detailed list of name, version, release date 16 | and path for each library. 17 | 18 | ## SEE ALSO 19 | 20 | realm(1) 21 | -------------------------------------------------------------------------------- /lib/realms/index.rb: -------------------------------------------------------------------------------- 1 | module Realms 2 | 3 | # 4 | # Access to project metadata via constant names. 5 | # 6 | # @example 7 | # Realms::VERSION #=> "2.0.0" 8 | # 9 | def self.const_missing(name) 10 | index[name.to_s.downcase] || super(name) 11 | end 12 | 13 | # 14 | # Access to project metadata. 15 | # 16 | def self.index 17 | @index ||= ( 18 | require 'yaml' 19 | file = File.expand_path('../realms.yml', File.dirname(__FILE__)) 20 | YAML.load_file(file) 21 | ) 22 | end 23 | 24 | end 25 | -------------------------------------------------------------------------------- /demo/applique/project.rb: -------------------------------------------------------------------------------- 1 | require 'pathname' 2 | 3 | project_directory = Pathname.new('projects') 4 | 5 | When 'Given a project directory "(((\S+)))"' do |name| 6 | @project_directory = project_directory + name 7 | libdir = @project_directory + 'lib' 8 | FileUtils.mkdir_p(libdir) unless libdir.exist? 9 | end 10 | 11 | When 'With a file "(((\S+)))" containing' do |name, text| 12 | file = @project_directory + name 13 | FileUtils.mkdir_p(file.parent) unless file.parent.exist? 14 | File.open(file.to_s, 'w'){ |f| f << text } 15 | end 16 | 17 | -------------------------------------------------------------------------------- /lib/realms/core_ext/gem.rb: -------------------------------------------------------------------------------- 1 | if not defined?(Gem) 2 | 3 | module Gem 4 | # Some libraries, such as RDoc search through 5 | # all libraries for plugins using this method. 6 | # If RubyGems is not being used, then Realms 7 | # emulates it. 8 | # 9 | # Gem.find_files('rdoc/discover') 10 | # 11 | # TODO: Perhaps it should override if it exists 12 | # and call back to it on failuer? 13 | def self.find_files(path) 14 | ::Library.search(path).map{ |f| f.to_s } 15 | end 16 | end 17 | 18 | end 19 | 20 | -------------------------------------------------------------------------------- /work/deprecated/commands/man/roll-use.1.ronn: -------------------------------------------------------------------------------- 1 | roll-use(1) -- list or change current environment 2 | ================================================= 3 | 4 | ## SYNOPSIS 5 | 6 | `roll-use` [] 7 | 8 | ## DESCRIPTION 9 | 10 | Without a ``, `roll-use` prints out a list of available environments. 11 | An arrow (`=>`) indicates the current environment. The envioronment can be 12 | changed by supplying the desired environment's ``. 13 | 14 | ## SEE ALSO 15 | 16 | roll(1), roll-list(1), 17 | 18 | 19 | -------------------------------------------------------------------------------- /demo/helpers/new_project.rdoc: -------------------------------------------------------------------------------- 1 | = Additional Project 2 | 3 | == Neo 0.0.1 4 | 5 | Given a project directory "neo/0.0.1". 6 | 7 | With a file "VERSION" containing... 8 | 9 | name: neo 10 | vers: 0.0.1 11 | 12 | With a file "PROFILE" containing... 13 | 14 | title : Neo 15 | author : Thomas Sawyer 16 | homepage: http://neo.foo 17 | 18 | With a file "lib/neo.rb" containing... 19 | 20 | $neo_message = "Neo v0.0.1" 21 | 22 | With a file ".ruby/name" containing... 23 | 24 | neo 25 | 26 | With a file ".ruby/version" containing... 27 | 28 | 0.0.1 29 | 30 | -------------------------------------------------------------------------------- /demo/02_commandline/03_rm.md: -------------------------------------------------------------------------------- 1 | # Remove Command 2 | 3 | The `remove` command can be used to remove locations from the load cache. 4 | 5 | `realm rm projects` 6 | 7 | Since `projects` was the only lookup location in the load cache, 8 | now that it has been removed we can see that there are no entries 9 | in the cache any longer. 10 | 11 | ledger = Dir['cache/ruby/*.ledger'].first 12 | json = File.read(ledger).strip 13 | json.assert == "{}" 14 | 15 | When using the `rm` command, if no directory is given then the current 16 | working directory is assumed. 17 | 18 | -------------------------------------------------------------------------------- /man/realm-show.1.ronn: -------------------------------------------------------------------------------- 1 | realm-show(1) -- show library details 2 | ===================================== 3 | 4 | ## SYNOPSIS 5 | 6 | `realm show` [] 7 | 8 | ## DESCRIPTION 9 | 10 | `realm-show` prints information about a library in the load environement. 11 | If `` is not given then the library at the current path is assumed. 12 | 13 | ## OPTIONS 14 | 15 | * `-j`, `--json`: 16 | Dump the information in JSON format. 17 | 18 | * `-y`, `--yaml`: 19 | Dump the information in YAML format. 20 | 21 | ## SEE ALSO 22 | 23 | realm(1), realm-list(1) 24 | 25 | -------------------------------------------------------------------------------- /demo/01_application/05_utils.md: -------------------------------------------------------------------------------- 1 | # Utils Module 2 | 3 | The Utils module encapsulates the configuration data used to setup 4 | the Realms system, as well as a number shared functions used throughout 5 | the system. 6 | 7 | ## lookup_paths 8 | 9 | Realms gets a list of globs used to lookup libraries via the `Utils#lookup_paths` 10 | method. It's definition is desrived from the `RUBY_LIBRARY` environment setting. 11 | 12 | Realms::Library::Utils.lookup_paths #=> ENV['RUBY_LIBRARY'].split(/[:;]/) 13 | 14 | It will fallback to `GEM_PATH` or `GEM_HOME` if `RUBY_LIBRARY` is not set. 15 | 16 | -------------------------------------------------------------------------------- /demo/02_commandline/11_gem.md: -------------------------------------------------------------------------------- 1 | # Gem Command 2 | 3 | The `realm gem` command it very simply. All it does is wrap the real `gem` 4 | command in a wrapper. The `gem` command is executed as usual, but afterwards 5 | Realms looks to see if there are any environments that are in of need re-syncing 6 | because of the potential changes made by the gems command to an environment 7 | lookup location, i.e. `$GEM_PATH` or `$GEM_HOME`. 8 | 9 | In other words you can run `gem install` and have the Realm cache that includes 10 | the gem re-synced automatically: 11 | 12 | `realm gem install ansi` 13 | 14 | -------------------------------------------------------------------------------- /work/deprecated/commands/man/roll-copy.1.ronn: -------------------------------------------------------------------------------- 1 | roll-copy(1) -- copy an environment to make a new environment 2 | ============================================================= 3 | 4 | ## SYNOPSIS 5 | 6 | `roll-copy` [] 7 | 8 | ## DESCRIPTION 9 | 10 | `roll-copy` copys an environment to make a new environment with a ``. 11 | If `` is given then that environment will be copied. If `` 12 | is not given then the current envionrment will be copied. 13 | 14 | ## SEE ALSO 15 | 16 | roll(1), roll-merge(1), 17 | 18 | 19 | -------------------------------------------------------------------------------- /demo/02_commandline/09_verify.md: -------------------------------------------------------------------------------- 1 | # Verify Command 2 | 3 | The `verify` command is similar to the `isolate` command, but rather the 4 | output an isolation template, it validates that the libraries's requirements 5 | can be met by the load environment. 6 | 7 | `realm verify tryme -v 1.1` 8 | 9 | This will display each dependency and an indicator as to whether the 10 | environment contains the dependency. 11 | 12 | The standard output will look something like: 13 | 14 | ok foo 0.8+ 15 | 16 | Which means the requirement 'foo 0.8+' was successfully loaded via the 17 | current environment. 18 | 19 | -------------------------------------------------------------------------------- /work/deprecated/commands/man/roll-merge.1.ronn: -------------------------------------------------------------------------------- 1 | roll-merge(1) -- merge one environment into another 2 | =================================================== 3 | 4 | ## SYNOPSIS 5 | 6 | `roll-merge` [] 7 | 8 | ## DESCRIPTION 9 | 10 | `roll-merge` merges the lookup list of a one environment into another. 11 | The `` specifies from which environment to get the lookup list, 12 | and the `` specifies to which environment to append the list. 13 | If `` is not given then the current environment is assumed. 14 | 15 | ## SEE ALSO 16 | 17 | roll(1), roll-copy(1), 18 | 19 | 20 | -------------------------------------------------------------------------------- /demo/02_commandline/13_where.md: -------------------------------------------------------------------------------- 1 | # Where Command 2 | 3 | The `relam where` command gives the absolute path of the file that would 4 | be required given feature as it would be passed to the require method. 5 | For example, to see the fullname of the file that `require "tryme"` would 6 | actually load, we can type 7 | 8 | `realm where tryme` 9 | 10 | The standard output would look something like: 11 | 12 | .../tmp/projects/tryme/1.1/lib/tryme.rb 13 | 14 | Where '...' is the absolute path to this project, wherever it may reside, 15 | since that is what we are testing. 16 | 17 | @stdout.assert.include?('tmp/projects/tryme/1.1/lib/tryme.rb') 18 | 19 | Just to be sure. 20 | 21 | -------------------------------------------------------------------------------- /lib/realms/shell/unlock.rb: -------------------------------------------------------------------------------- 1 | module Realms 2 | class Library 3 | module Shell 4 | register :unlock 5 | register :clear 6 | 7 | # 8 | # Remove the load cache. 9 | # 10 | def unlock 11 | op.banner = "Usage: relam unlock" 12 | op.separator "Clear current roll cache." 13 | 14 | parse 15 | 16 | file = Utils.lock_file 17 | 18 | if File.exist?(file) 19 | Utils.unlock 20 | puts "Removed load cache at #{file}." 21 | else 22 | puts "Not locked." 23 | end 24 | end 25 | 26 | # Alias for unlock. 27 | alias :clear :unlock 28 | 29 | end 30 | end 31 | end 32 | -------------------------------------------------------------------------------- /spec/spec_kernel.rb: -------------------------------------------------------------------------------- 1 | require_relative 'helper' 2 | 3 | describe Kernel do 4 | 5 | describe "#library" do 6 | 7 | before do 8 | Library::Utils.reset! 9 | end 10 | 11 | it "activates a library, constraining it to a single version" do 12 | library('tryme', '1.1') 13 | 14 | assert $LOAD_MANAGER['tryme'].class == Library 15 | assert $LOAD_MANAGER['tryme'].version.to_s == '1.1' 16 | end 17 | 18 | it "will raise an error if given a conflicting version" do 19 | library('tryme', '1.1') 20 | 21 | assert_raises(Library::VersionConflict) do 22 | library('tryme', '1.0') 23 | end 24 | end 25 | 26 | end 27 | 28 | end 29 | 30 | -------------------------------------------------------------------------------- /demo/applique/realms.rb: -------------------------------------------------------------------------------- 1 | abort "Remove -realms from RUBYOPT before running these tests." if ENV['RUBYOPT'].index('-realms') 2 | 3 | $realms_root = File.expand_path(File.dirname(__FILE__) + '../../..') 4 | 5 | #ENV['XDG_CONFIG_HOME'] = File.join($project_root, "tmp/qed/config") 6 | ENV['XDG_CACHE_HOME'] = File.join($realms_root, "tmp/qed/cache") 7 | ENV['RUBY_LIBRARY'] = File.join($realms_root, "demo/fixtures/projects/*") 8 | 9 | # Make sure we use local version of files. 10 | $:.unshift('lib') 11 | 12 | require 'realms' 13 | #require 'realms/shell' 14 | 15 | # let's do some pre-start checks 16 | 17 | assert(Realms::Library::Utils.tmpdir == File.join($realms_root, "tmp/qed/cache/ruby")) 18 | 19 | -------------------------------------------------------------------------------- /lib/realms/shell/where.rb: -------------------------------------------------------------------------------- 1 | module Realms 2 | class Library 3 | module Shell 4 | register :where 5 | 6 | # 7 | # Display the absolute path of a feature. 8 | # 9 | def where 10 | op.banner = "Usage: realm where " 11 | op.separator "Display absolute path to a feature." 12 | 13 | #op.on('--all', '-a', "Search all rolls.") do 14 | # opts[:all] = true 15 | #end 16 | 17 | parse 18 | 19 | feature = argv.first 20 | 21 | if path = $LOAD_MANAGER.find(feature) 22 | $stdout.puts path 23 | else 24 | $stderr.puts "Not found." 25 | end 26 | end 27 | 28 | end 29 | end 30 | end 31 | -------------------------------------------------------------------------------- /man/realm-add.1.ronn: -------------------------------------------------------------------------------- 1 | relam-add(1) -- add path to current library cache 2 | ================================================= 3 | 4 | ## SYNOPSIS 5 | 6 | `realm add` [] 7 | 8 | ## DESCRIPTION 9 | 10 | `realm add` inserts a path into the load cache, re-syncing it in the process. 11 | If no cache exists the command aborts with an error. 12 | 13 | If no `` is given the present working directory is used. 14 | 15 | The `add` command is only useful for temporary additions and when a load 16 | cache (aka called a locked ledger) is being used. To add locations more 17 | generally which can be used in locked more or live mode export to the 18 | `RUBY_LIBRARY` environment variable. 19 | 20 | ## SEE ALSO 21 | 22 | realm(1), realm-rm(1) 23 | 24 | -------------------------------------------------------------------------------- /spec/spec_manager.rb: -------------------------------------------------------------------------------- 1 | require_relative 'helper' 2 | 3 | describe Realms::Library::Manager do 4 | 5 | describe "$LOAD_MANAGER" do 6 | 7 | before do 8 | Library::Utils.reset! 9 | end 10 | 11 | it "lists the library names via #keys" do 12 | assert $LOAD_MANAGER.keys.sort == ['foo', 'ruby', 'tryme'] 13 | end 14 | 15 | it "is delegated to by Library.names" do 16 | assert Realms::Library.names == $LOAD_MANAGER.keys 17 | end 18 | 19 | it "reduces a list of library version to one when activated" do 20 | assert $LOAD_MANAGER['tryme'].is_a?(Array) 21 | 22 | library('tryme') 23 | 24 | assert $LOAD_MANAGER['tryme'].is_a?(Realms::Library) 25 | end 26 | 27 | end 28 | 29 | end 30 | 31 | -------------------------------------------------------------------------------- /work/consider/autoload.rb: -------------------------------------------------------------------------------- 1 | # TODO: Roll compatible autoload. 2 | 3 | =begin 4 | class Module 5 | # Autoload script. 6 | # 7 | # NOTE: Rolls has to neuter this functionality b/c of a "bug" in Ruby 8 | # which doesn't allow autoload from using overridden require methods. 9 | def autoload(constant, file) 10 | #Library.ledger.autoload(constant, file) 11 | $LEDGER.autoload(constant, file) 12 | end 13 | 14 | # Autoload script. 15 | # 16 | # NOTE: Rolls has to neuter this functionality b/c og a "bug" in Ruby 17 | # which doesn't allow autoload from using overridden require methods. 18 | def self.autoload(constant, file) 19 | #Library.ledger.autoload(constant, file) 20 | $LEDGER.autoload(constant, file) 21 | end 22 | end 23 | =end 24 | -------------------------------------------------------------------------------- /Rulefile: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | #require 'pom' 4 | #PROJECT = POM::Project.new(Dir.pwd) 5 | 6 | desc "Install Rolls" 7 | task :install do 8 | system %[setup.rb] 9 | end 10 | 11 | desc "Build the manual" 12 | task "man" do 13 | cmd = [] 14 | cmd << "RONN_STYLE='./.config/ronn'" 15 | cmd << "ronn -br5" 16 | cmd << "--organization=RUBYWORKS" 17 | cmd << "--style='man,toc,center'" 18 | cmd << "--manual='Roll Manual' man/man1/*.ronn" 19 | 20 | sh cmd.join(' ') 21 | 22 | sh "mkdir -p web/manual/" 23 | sh "mv man1/*.html web/manual/" 24 | 25 | sh "gzip -f man/man1/*.1" 26 | end 27 | 28 | 29 | desc "Generate Documentation" 30 | task "doc" do 31 | # TODO: Switched to YARD 32 | #system %[rdoc -o doc/rdoc -m README -t "Realms" README lib] 33 | end 34 | 35 | -------------------------------------------------------------------------------- /work/reference/monitor.rb: -------------------------------------------------------------------------------- 1 | module ::Kernel 2 | class << self 3 | alias_method :require_without_monitor, :require 4 | alias_method :load_without_monitor, :load 5 | end 6 | 7 | alias_method :require_without_monitor, :require 8 | alias_method :load_without_monitor, :load 9 | 10 | # Require script and print what is being require. 11 | def require(file) 12 | $stderr.puts "monitor require: #{file}\n#{caller.inspect}\n\n" 13 | require_without_monitor(file) 14 | end 15 | 16 | module_function :require 17 | 18 | # Load script and print what is being loaded. 19 | def load(file, wrap=false) 20 | $stderr.puts "monitor load: #{file}\n#{caller.inspect}\n\n" 21 | load_without_monitor(file, wrap) 22 | end 23 | 24 | module_function :load 25 | end 26 | 27 | -------------------------------------------------------------------------------- /man/realm-gem.1.ronn: -------------------------------------------------------------------------------- 1 | realm-gem(1) -- run a gem command then re-sync the load cache 2 | ============================================================= 3 | 4 | ## SYNOPSIS 5 | 6 | `realm gem` 7 | 8 | ## DESCRIPTION 9 | 10 | `roll-gem` simply passes the arguments given on to the `gem` command. 11 | After successful completion of which Realms automatically re-syncs the 12 | load cache to make sure it is current. 13 | 14 | ## EXAMPLES 15 | 16 | This is particularlly useful when installing a new gem when Realms is 17 | managing the gem paths. 18 | 19 | $ realm gem install ansi 20 | 21 | This is effectively the same as doing: 22 | 23 | $ gem install ansi 24 | $ realm sync 25 | 26 | ## SEE ALSO 27 | 28 | realm(1), realm-sync(1), 29 | 30 | 31 | -------------------------------------------------------------------------------- /work/consider/import-old.rb: -------------------------------------------------------------------------------- 1 | 2 | module Kernel 3 | 4 | # Load a library into a specific base module/class. 5 | # If not base is given the the lib is loaded into 6 | # the instance class (singleton) or the current object. 7 | 8 | def import( path, base=nil ) 9 | base ||= (class << self; self; end) 10 | 11 | if path =~ /^[\/~.]/ 12 | path = File.expand_path(path) 13 | else 14 | $LOAD_PATH.each do |lp| 15 | file = File.join(lp,path) 16 | if File.exist?(file) 17 | path = file 18 | break 19 | end 20 | end 21 | end 22 | 23 | base.module_eval(File.read(path)) 24 | end 25 | 26 | end 27 | 28 | 29 | class Module 30 | 31 | # Import library into module space. 32 | 33 | def import( path ) 34 | super( path, self ) 35 | end 36 | 37 | end 38 | -------------------------------------------------------------------------------- /lib/realms/shell/add.rb: -------------------------------------------------------------------------------- 1 | module Realms 2 | class Library 3 | module Shell 4 | 5 | register :add 6 | 7 | # 8 | # Add paths into the current libraries. 9 | # 10 | def add 11 | op.banner = "Usage: realm add [PATH ...]" 12 | op.separator "Add library path(s) into locked load environment." 13 | 14 | parse 15 | 16 | if argv.empty? 17 | paths = [Dir.pwd] 18 | else 19 | paths = argv 20 | end 21 | 22 | if !Utils.locked? 23 | $LOAD_MANAGER = Manager.new 24 | end 25 | 26 | paths.each do |path| 27 | puts path 28 | $LOAD_MANAGER.add(path) 29 | end 30 | Utils.lock(:active=>true) 31 | puts " '-> #{Utils.lock_file}" 32 | end 33 | 34 | end 35 | end 36 | end 37 | -------------------------------------------------------------------------------- /script/install-0.2.0.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | pwddir=$(pwd) 4 | tmpdir="/tmp/rolls-install" 5 | 6 | mkdir $tmpdir 7 | cd $tmpdir 8 | 9 | wget https://github.com/rubyworks/autoload/archive/0.3.0.zip 10 | unzip 0.3.0.zip 11 | rm 0.3.0.zip 12 | 13 | wget https://github.com/rubyworks/versus/archive/0.2.0.zip 14 | unzip 0.2.0.zip 15 | rm 0.2.0.zip 16 | 17 | wget https://github.com/rubyworks/library/archive/0.2.0.zip 18 | unzip 0.2.0.zip 19 | rm 0.2.0.zip 20 | 21 | wget https://github.com/rubyworks/rolls/archive/2.0.0.zip 22 | unzip 2.0.0.zip 23 | rm 2.0.0.zip 24 | 25 | cd autoload-0.3.0 26 | ruby setup.rb 27 | cd .. 28 | 29 | cd versus-0.2.0 30 | ruby setup.rb 31 | cd .. 32 | 33 | cd library-0.2.0 34 | ruby setup.rb 35 | cd .. 36 | 37 | cd rolls-2.0.0 38 | ruby setup.rb 39 | cd .. 40 | 41 | cd $pwddir 42 | rm -r $tmpdir 43 | 44 | -------------------------------------------------------------------------------- /Assembly: -------------------------------------------------------------------------------- 1 | --- 2 | gem: 3 | active: true 4 | 5 | github: 6 | gh_pages: web 7 | 8 | # TODO: When available 9 | #rubytest: 10 | # active: false 11 | 12 | syntax: 13 | active: false 14 | 15 | vclog: 16 | output: 17 | - log/history.html 18 | - log/changes.html 19 | active: false 20 | 21 | dnote: 22 | title: Source Notes 23 | output: log/notes.html 24 | 25 | locat: 26 | output: log/locat.html 27 | 28 | email: 29 | mailto: 30 | - ruby-talk@ruby-lang.org 31 | - rubyworks-mailinglist@googlegroups.com 32 | from : <%= ENV['EMAIL_ACCOUNT'] %> 33 | server : <%= ENV['EMAIL_SERVER'] %> 34 | port : <%= ENV['EMAIL_PORT'] %> 35 | account : <%= ENV['EMAIL_ACCOUNT'] %> 36 | domain : <%= ENV['EMAIL_DOMAIN'] %> 37 | login : <%= ENV['EMAIL_LOGIN'] %> 38 | secure : <%= ENV['EMAIL_SECURE'] %> 39 | 40 | -------------------------------------------------------------------------------- /work/deprecated/commands/lib/realms/shell/copy.rb: -------------------------------------------------------------------------------- 1 | module Realms 2 | 3 | module Shell 4 | 5 | # 6 | # Copy roll file. 7 | # 8 | def copy 9 | opts = {} 10 | 11 | op.banner = "Usage: roll copy [to]\n" + 12 | " roll copy [from] [to]" 13 | op.separator "Copy a roll." 14 | op.on('--lock', '-l', "Lock after copying.") do 15 | opts[:lock] = true 16 | end 17 | op.on('--force', '-f', "Force overwrite of pre-existing roll.") do 18 | opts[:force] = true 19 | end 20 | 21 | parse 22 | 23 | src, dst = *argv 24 | 25 | fdst = Roll.copy(dst, src, opts) 26 | 27 | if opts[:lock] 28 | puts "Locked '#{dst}`." 29 | else 30 | puts "Saved '#{dst}`." 31 | end 32 | end 33 | 34 | end 35 | 36 | end 37 | 38 | -------------------------------------------------------------------------------- /script/install-master.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | pwddir=$(pwd) 4 | tmpdir="/tmp/rolls-install" 5 | 6 | mkdir $tmpdir 7 | cd $tmpdir 8 | 9 | wget https://github.com/rubyworks/autoload/archive/master.zip 10 | unzip master.zip 11 | rm master.zip 12 | 13 | wget https://github.com/rubyworks/versus/archive/master.zip 14 | unzip master.zip 15 | rm master.zip 16 | 17 | wget https://github.com/rubyworks/library/archive/master.zip 18 | unzip master.zip 19 | rm master.zip 20 | 21 | wget https://github.com/rubyworks/rolls/archive/master.zip 22 | unzip master.zip 23 | rm master.zip 24 | 25 | cd autoload-master 26 | ruby setup.rb 27 | cd .. 28 | 29 | cd versus-master 30 | ruby setup.rb 31 | cd .. 32 | 33 | cd library-master 34 | ruby setup.rb 35 | cd .. 36 | 37 | cd rolls-master 38 | ruby setup.rb 39 | cd .. 40 | 41 | cd $pwddir 42 | rm -r $tmpdir 43 | 44 | -------------------------------------------------------------------------------- /demo/02_commandline/10_isolate.md: -------------------------------------------------------------------------------- 1 | # Isolate Command 2 | 3 | Load path isolation has become the recent rage with Ruby load tools. 4 | With Realms, isolation isn't as necessary because it already insulates 5 | each project's files. However, for those seeking *maximum insulary protection*, 6 | Realms provides the `isolate` command. 7 | 8 | To use it provide the path to the project to be isolated, or if no path is 9 | given the project in the present working directory will be used. 10 | 11 | `roll isolate projects/tryme/1.1` 12 | 13 | To have a project automatically use a local isolation environment set the shell 14 | variable $roll_isolate. 15 | 16 | `export roll_isolate=true` 17 | 18 | Now when the project code is executed (with roll.rb loaded, of course), it 19 | will have limited access to just the projects listed in it's local index. 20 | 21 | -------------------------------------------------------------------------------- /demo/02_commandline/12_path.md: -------------------------------------------------------------------------------- 1 | # Path Command 2 | 3 | The `path` command outputs a colon (or semi-colon) separated string of bin/ 4 | paths for the indexed libraries, which is suitable for appending to a shell 5 | environments `PATH` variable. This can be used to setup executable lookup 6 | on Linux systems. 7 | 8 | Given a set of projects with executables and an current environment setup 9 | including them, we can run the `path` command and get a list of each 10 | project bin directory, if it has one. 11 | 12 | `roll path` 13 | 14 | The standard output of which will be a colon separated list of executable 15 | directories of the projects in the current environment. 16 | 17 | @stdout.assert.include?('tmp/projects/tryme/1.1/bin') 18 | 19 | But only the latest versions of each project are included. 20 | 21 | @stdout.refute.include?('tmp/projects/tryme/1.0/bin') 22 | 23 | -------------------------------------------------------------------------------- /lib/realms/shell/lock.rb: -------------------------------------------------------------------------------- 1 | module Realms 2 | class Library 3 | module Shell 4 | register :lock 5 | register :cache 6 | 7 | # 8 | # Synchronize the load cache to RUBY_LIBRARY setting. This caches all the 9 | # neccessary information about the available libraries, so start-up times 10 | # are faster. 11 | # 12 | def lock 13 | active = false 14 | 15 | op.banner = "Usage: realm lock" 16 | op.separator "Serialize ledger and save." 17 | 18 | op.on('--active', '-a', "include library activity") do |val| 19 | active = val 20 | end 21 | 22 | parse 23 | 24 | file = Utils.lock(:active=>active) 25 | 26 | $stdout.puts "Cached at: #{Utils.lock_file}" 27 | end 28 | 29 | # Alternate term for lock. 30 | alias :cache :lock 31 | 32 | end 33 | end 34 | end 35 | -------------------------------------------------------------------------------- /work/deprecated/commands/demo/02_commandline/08_merge.md: -------------------------------------------------------------------------------- 1 | = Merge Command 2 | 3 | Another useful command for working with load environments is `merge`. 4 | As the name indicates, `merge` makes it possible to take one environment 5 | and combine it with another. 6 | 7 | `roll merge testing development` 8 | 9 | This example would merge the `testing` environment into the `development` 10 | environment. To merge a load environment into the current environment 11 | simply leave out the last argument. 12 | 13 | `roll merge testing` 14 | 15 | So in this case we've merged the testing environment into the current environment, 16 | namely the default, `production`. 17 | 18 | If we try to merge an environment that doesn't exist, we will get an 19 | error telling us as much. 20 | 21 | expect RuntimeError do 22 | `roll merge notaname wherever` 23 | end 24 | 25 | @stderr.assert.include?('does not exist') 26 | 27 | -------------------------------------------------------------------------------- /demo/applique/fixtures.rb: -------------------------------------------------------------------------------- 1 | #require 'erb' 2 | 3 | $DEMO_DIR = File.dirname(File.dirname(__FILE__)) 4 | 5 | # Link tmp/qed/projects to fixtures/projects. 6 | FileUtils.ln_s($DEMO_DIR + '/fixtures/projects', 'projects') 7 | 8 | # 9 | #def cached_setup 10 | # Realms::Library::Utils.sync 11 | #end 12 | 13 | # 14 | #def live_setup 15 | # ledger = Dir['cache/ruby/*.ledger'].first 16 | # FileUtils.rm(ledger) if ledger 17 | #end 18 | 19 | 20 | =begin 21 | # 22 | def copy_fixture(name) 23 | srcdir = File.join(DEMO_DIR, 'fixtures', name) 24 | paths = Dir.glob(File.join(srcdir, '**', '*'), File::FNM_DOTMATCH) 25 | paths.each do |path| 26 | basename = File.basename(path) 27 | next if basename == '.' 28 | next if basename == '..' 29 | dest = path.sub(srcdir+'/', '') 30 | if File.directory?(path) 31 | FileUtils.mkdir(dest) 32 | else 33 | text = ERB.new(File.read(path)).result 34 | File.open(dest, 'w'){ |f| f << text } 35 | end 36 | end 37 | end 38 | =end 39 | -------------------------------------------------------------------------------- /lib/realms/shell/gem.rb: -------------------------------------------------------------------------------- 1 | module Realms 2 | class Library 3 | module Shell 4 | 5 | register :gem 6 | 7 | # 8 | # Run a gem command then re-lock any locked rolls that contain 9 | # paths in the current gem home. 10 | # 11 | def gem 12 | op.banner = "Usage: roll gem ..." 13 | op.separator "Run gem command and relock roll afterwards." 14 | op.on("--sudo", "-s", "Run gem command as super user.") do 15 | opts[:sudo] = true 16 | end 17 | 18 | op.order!(args) 19 | 20 | cmd = "gem " + args.join(' ') 21 | cmd = "sudo " + cmd if opts[:sudo] 22 | 23 | gem_rolls = Realms.lock_gem_rolls 24 | 25 | if success = system(cmd) 26 | puts 27 | if gem_rolls.empty? 28 | puts "No rolls required re-locking." 29 | else 30 | puts "Locked:" 31 | gem_rolls.each do |name| 32 | puts "- #{name}" 33 | end 34 | end 35 | end 36 | end 37 | 38 | end 39 | end 40 | end 41 | -------------------------------------------------------------------------------- /demo/helpers/projects.rdoc: -------------------------------------------------------------------------------- 1 | = Basic Set of Projects 2 | 3 | == TryMe 1.0 4 | 5 | Given a project directory "tryme/1.0". 6 | 7 | With a file "VERSION" containing... 8 | 9 | name: tryme 10 | vers: 1.0 11 | 12 | With a file "PROFILE" containing... 13 | 14 | title : TryMe 15 | author : Thomas Sawyer 16 | homepage: http://tryme.foo 17 | 18 | With a file "lib/tryme.rb" containing... 19 | 20 | $tryme_message = "Try Me v1.0" 21 | 22 | With a file ".ruby/name" containing... 23 | 24 | tryme 25 | 26 | With a file ".ruby/version" containing... 27 | 28 | 1.0 29 | 30 | == TryMe 1.1 31 | 32 | Given a project directory "tryme/1.1". 33 | 34 | With a file "VERSION" containing... 35 | 36 | name: tryme 37 | vers: 1.1 38 | 39 | With a file "PROFILE" containing... 40 | 41 | title : TryMe 42 | author : Thomas Sawyer 43 | homepage: http://tryme.foo 44 | 45 | With a file "lib/tryme.rb" containing... 46 | 47 | $tryme_message = "Try Me v1.1" 48 | 49 | With a file ".ruby/name" containing... 50 | 51 | tryme 52 | 53 | With a file ".ruby/version" containing... 54 | 55 | 1.1 56 | 57 | -------------------------------------------------------------------------------- /lib/realms/shell/show.rb: -------------------------------------------------------------------------------- 1 | module Realms 2 | class Library 3 | module Shell 4 | register :show 5 | 6 | # 7 | # Show library details. 8 | # 9 | def show 10 | version = nil 11 | 12 | op.banner = "Usage: realm show [name]" 13 | op.separator "Show details about a library." 14 | 15 | op.on('--version', '-v [VERSION]', "Show greater than or equal version.") do |val| 16 | version = val 17 | end 18 | 19 | parse 20 | 21 | name = argv.first || raise(ArgumentError, "name of library needed") 22 | 23 | if $LOAD_MANAGER.key?(name) 24 | if version 25 | libs = $LOAD_MANAGER[name] 26 | library = Array(libs).select{ |lib| lib.version.satisfy?(">= #{version}") }.min 27 | else 28 | library = $LOAD_MANAGER.current(name) 29 | end 30 | end 31 | 32 | if library 33 | puts library.metadata.to_h.to_yaml 34 | else 35 | $stderr.puts "Library not found." 36 | end 37 | end 38 | 39 | end 40 | end 41 | end 42 | -------------------------------------------------------------------------------- /lib/realms/shell/path.rb: -------------------------------------------------------------------------------- 1 | module Realms 2 | class Library 3 | module Shell 4 | register :path 5 | 6 | # Build a list of all library bin locations and writes that list as a 7 | # environment setting shell script. On Linux, add a call to this in your 8 | # .bashrc file, e.g. 9 | # 10 | # export PATH="$(realm path):$PATH" 11 | # 12 | # Or better, put this in a `.config/bashrc/ruby.sh` file. And then 13 | # in your `.bashrc file: 14 | # 15 | # if [ -f ~/.config/bashrc/ruby.sh ]; then 16 | # source ~/.config/bashrc/ruby.sh 17 | # fi 18 | # 19 | def path 20 | cache = false 21 | 22 | op.banner = "Usage: realm path" 23 | op.separator "Generate list of executable paths usable in PATH environment variable." 24 | 25 | op.on('--cache', '-c', "Create/update the load cache first.") do |val| 26 | cache = val 27 | end 28 | 29 | parse 30 | 31 | Utils.lock if cache 32 | 33 | $stdout.puts $LOAD_MANAGER::PATH() 34 | end 35 | 36 | end 37 | end 38 | end 39 | -------------------------------------------------------------------------------- /work/studies/yaml-date.rb: -------------------------------------------------------------------------------- 1 | module Kernel 2 | alias_method :old_require, :require 3 | alias_method :old_load, :load 4 | alias_method :old_autoload, :autoload 5 | 6 | def require(path) 7 | p "require: #{path}" 8 | old_require(path) 9 | end 10 | 11 | module_function :require 12 | 13 | def load(path, wrap=nil) 14 | p "load: #{path}" 15 | old_load(path, wrap) 16 | end 17 | 18 | module_function :load 19 | 20 | def autoload(constant, path) 21 | p "autoload: #{path}" 22 | old_autoload(constant, path) 23 | end 24 | 25 | module_function :autoload 26 | end 27 | 28 | 29 | class Module 30 | alias_method :old_autoload, :autoload 31 | 32 | def autoload(constant, path) 33 | p "autoload: #{path}" 34 | old_autoload(constant, path) 35 | end 36 | 37 | def self.autoload(constant, path) 38 | p "autoload: #{path}" 39 | old_autoload(constant, path) 40 | end 41 | end 42 | 43 | # now the test 44 | 45 | l1 = $".dup 46 | 47 | require 'yaml' 48 | 49 | l2 = $".dup 50 | $".clear 51 | 52 | puts "LOADING YAML DOCUMENT" 53 | 54 | YAML.load <<-HERE 55 | date: 2010-10-01 56 | HERE 57 | 58 | p $" - l2 59 | 60 | -------------------------------------------------------------------------------- /spec/helper.rb: -------------------------------------------------------------------------------- 1 | abort "Remove -realms from RUBYOPT before running these tests." if ENV['RUBYOPT'].index('-realms') 2 | 3 | $realms_root = File.expand_path(File.dirname(__FILE__) + '/..') 4 | 5 | #ENV['XDG_CONFIG_HOME'] = File.join($project_root, "tmp/config") 6 | ENV['XDG_CACHE_HOME'] = File.join($realms_root, "tmp/cache") 7 | ENV['RUBY_LIBRARY'] = File.join($realms_root, "spec/fixtures/projects/*") 8 | 9 | # link tmp/projects to spec/fixtures/projects 10 | tmp_projects = File.join($realms_root, 'tmp/projects') 11 | unless File.exist?(tmp_projects) 12 | require 'fileutils' 13 | FileUtils.ln_s(File.join($realms_root, 'spec/fixtures/projects'), tmp_projects) 14 | end 15 | 16 | # test from within tmp directoy 17 | Dir.chdir('tmp') 18 | 19 | # Make sure we use local version of files. 20 | $:.unshift('../lib') 21 | 22 | require 'minitap' 23 | 24 | require 'realms' 25 | #require 'realms/shell' 26 | 27 | # pre-start checks 28 | raise unless Realms::Library::Utils.tmpdir == File.join($realms_root, "tmp/cache/ruby") 29 | 30 | # include Realms at top-level for convenience 31 | include Realms 32 | 33 | require 'minitest/autorun' 34 | MiniTest::Unit.runner = MiniTest::TapY.new 35 | 36 | -------------------------------------------------------------------------------- /demo/02_commandline/02_add.md: -------------------------------------------------------------------------------- 1 | # Add Command 2 | 3 | The `add` command is used to add locations to the load cache. For example, 4 | given a set of Ruby projects under a `projects` directory, we could add all 5 | those project with the following command. 6 | 7 | `realm add projects/*` 8 | 9 | If a load cache does not exist when `add` is invoked, then a cache will be 10 | created containing only the specified paths. 11 | 12 | The cache is stored in the users home directory at `~/.cache/ruby/` (where `~/.cache` 13 | is the default value for XDG_CACHE_HOME environment variable.) For the purposes 14 | of this demonstration we have adjusted this location behind the scenes to 15 | `cache/ruby/` (in the project's `tmp/qed/` directory). If we take a look we 16 | will see there is a `.ledger` file there. 17 | 18 | ledger = Dir['cache/ruby/*.ledger'].first 19 | 20 | To confirm that the cache has indeed been setup as expected we can read 21 | in this file and ensure it contains the projects, which are TryMe v1.0 22 | and TryMe v1.1. 23 | 24 | text = File.read(ledger) 25 | 26 | text.assert.include?('projects/tryme/1.0') 27 | text.assert.include?('projects/tryme/1.1') 28 | 29 | -------------------------------------------------------------------------------- /work/benchmarks/vsgems_bm.rb: -------------------------------------------------------------------------------- 1 | require 'open3' 2 | require 'benchmark' 3 | 4 | # prime any file system caches 5 | #require 'facets' 6 | #require 'nokogiri' 7 | 8 | $bench_env = File.dirname(__FILE__) + '/rubygems.roll' 9 | 10 | def run(cmd) 11 | cmd = %[export RUBY_LIBRARY="#{$bench_env}"; export RUBYOPT=""; ] + cmd 12 | Open3.popen3(cmd) do |stdin, stdout, stderr| 13 | out = stdout.read 14 | err = stderr.read 15 | puts out unless out.empty? 16 | puts err unless err.empty? 17 | end 18 | end 19 | 20 | puts 21 | puts "RubyGems" 22 | 23 | Benchmark.bm(25) do |x| 24 | x.report(" Require Gems: "){ run %[ruby -rubygems -e'nil'] } 25 | x.report(" Require Facets: "){ run %[ruby -rubygems -e'require "facets"'] } 26 | x.report(" Require Nokogiri: "){ run %[ruby -rubygems -e'require "nokogiri"'] } 27 | end 28 | 29 | puts 30 | puts "Ruby Roll" 31 | 32 | Benchmark.bm(25) do |x| 33 | x.report(" Reqiure Roll: "){ run %[ruby -rolls -e'nil'] } 34 | x.report(" Require Facets: "){ run %[ruby -rolls -e'require "facets"'] } 35 | x.report(" Require Nokogiri: "){ run %[ruby -rolls -e'require "nokogiri"'] } 36 | end 37 | 38 | puts 39 | -------------------------------------------------------------------------------- /work/consider/plugin.rb: -------------------------------------------------------------------------------- 1 | # = plugin.rb 2 | # 3 | # Development Notes: 4 | # 5 | # TODO This still needs love. It should work more like Library ultimately. 6 | 7 | # Straighfoward, flexible and reuable plugin system. 8 | 9 | module Plugin 10 | 11 | # Lookup pugins. 12 | 13 | def plugins(glob) 14 | glob = File.join(Config::CONFIG['datadir'], 'ruby', 'plugins', glob) 15 | Dir.glob(glob) 16 | end 17 | 18 | # Does plugin exist? 19 | 20 | def has_plugin?(glob) 21 | !plugins(glob).empty? 22 | end 23 | 24 | # Require plugin(s). 25 | 26 | def require_plugin(glob) 27 | plugs = [] 28 | #files = plugins(glob) 29 | glob = File.join(Config::CONFIG['datadir'], 'ruby', 'plugins', glob) 30 | files = Dir.glob(glob) 31 | files.each { |file| plugs.concat(File.read_list(file)) } 32 | plugs.each { |plug| require plug } 33 | end 34 | 35 | # Load plugin(s). 36 | 37 | def load_plugin( glob ) 38 | plugins = [] 39 | files = plugins(glob) 40 | files.each { |file| plugins.concat(File.read_list(file)) } 41 | plugins.each { |plugin| load plugin } 42 | end 43 | 44 | # TODO import plugin? 45 | 46 | end 47 | 48 | 49 | class Object 50 | include Plugin 51 | end 52 | -------------------------------------------------------------------------------- /demo/01_application/03_manager.md: -------------------------------------------------------------------------------- 1 | # The Manager 2 | 3 | At the heart of Realms lies a global Manager instanace. It is essentially a Hash 4 | of library names indexing library objects. 5 | 6 | $LOAD_MANAGER.keys.sort.assert == ['foo', 'ruby', 'tryme'] 7 | 8 | The Library class redirects a number of calls to the $LOAD_MANAGER, so we could 9 | invoke the same methods on it instead. 10 | 11 | Realms::Library.names.assert == $LOAD_MANAGER.keys 12 | 13 | Which we choose to use is mostly a matter of taste. The Realms::Library class 14 | methods were designed for end-user readability, whereas $LOAD_MANAGER is used 15 | internally. For the rest of this demo we will use $LOAD_MANAGER since this 16 | demonstration is specifically about it. 17 | 18 | The values of $LOAD_MANAGER will always be either a Library object or an array 19 | of Library objects of the same name but differnt versions. 20 | 21 | When a particular library is activated for the first time the corresponding 22 | array value will be replaced by that library. 23 | 24 | $LOAD_MANAGER['tryme'].assert.is_a?(Array) 25 | 26 | library('tryme') 27 | 28 | $LOAD_MANAGER['tryme'].assert.is_a?(Realms::Library) 29 | 30 | This is how Realms handles version control. 31 | 32 | -------------------------------------------------------------------------------- /lib/realms/shell/remove.rb: -------------------------------------------------------------------------------- 1 | module Realms 2 | class Library 3 | module Shell 4 | register :remove 5 | register :rm 6 | 7 | # 8 | # Remove path from current roll. 9 | # 10 | def remove 11 | op.banner = "Usage: relam remove [PATH ...]" 12 | op.separator "Remove library path(s) from load cache." 13 | 14 | parse 15 | 16 | if argv.empty? 17 | paths = [Dir.pwd] 18 | else 19 | paths = argv 20 | end 21 | 22 | if Utils.locked? 23 | find = [] 24 | 25 | $LOAD_MANAGER.each do |name, libs| 26 | Array(libs).each do |lib| 27 | find << [name, lib, path] if paths.any?{ |path| File.expand_path(lib.location) == File.expand_path(path) } 28 | end 29 | end 30 | 31 | find.each do |name, lib, path| 32 | puts path 33 | $LOAD_MANAGER[name].delete(lib) 34 | end 35 | 36 | Utils.lock(:active=>true) 37 | 38 | puts " ^- #{Utils.lock_file}" 39 | else 40 | puts "Cannot remove paths unless load manager is locked." 41 | end 42 | end 43 | 44 | alias :rm :remove 45 | 46 | end 47 | end 48 | end 49 | -------------------------------------------------------------------------------- /lib/realms/shell/dump.rb: -------------------------------------------------------------------------------- 1 | # Realms 2 | # Copyright (c) 2013 Rubyworks 3 | # BSD-2-Clause License 4 | # 5 | # encoding: utf-8 6 | 7 | module Realms 8 | class Library 9 | 10 | module Shell 11 | 12 | # 13 | # Dump the ledger. 14 | # 15 | def dump 16 | opts = {} 17 | 18 | op.banner = "Usage: realm dump" 19 | op.separator "Dump manager's ledger in serialized format." 20 | 21 | op.on('-j', '--JSON', "Output in JSON format.") do 22 | opts[:format] = :json 23 | end 24 | 25 | op.on('-y', '--yaml', "Output in YAML format.") do 26 | opts[:format] = :yaml 27 | end 28 | 29 | op.on('-m', '--marshal', "Output in Ruby's own serialization format.") do 30 | opts[:format] = :marshal 31 | end 32 | 33 | parse 34 | 35 | case opts[:format] 36 | when :json 37 | out = JSON.fast_generate($LOAD_MANAGER.to_h) 38 | when :yaml 39 | out = $LOAD_MANAGER.to_h.to_yaml 40 | when :marshal 41 | out = Marshal.dump($LOAD_MANAGER.to_h) 42 | else 43 | out = JSON.pretty_generate($LOAD_MANAGER.to_h) 44 | end 45 | 46 | puts out 47 | end 48 | 49 | end 50 | 51 | end 52 | end 53 | -------------------------------------------------------------------------------- /lib/realms/errors/load_error.rb: -------------------------------------------------------------------------------- 1 | module Realms 2 | class Library 3 | 4 | # Library::LoadError is a subclass of Ruby's standard LoadError class, 5 | # modified slightly to provide better error messages. 6 | # 7 | class LoadError < ::LoadError 8 | 9 | # 10 | # Setup new LoadError instance. 11 | # 12 | def initialize(failed_path, library_name=nil) 13 | super() 14 | 15 | @failed_path = failed_path 16 | @library_name = library_name 17 | 18 | if library_name 19 | @message = "#{@library_name}:#{@failed_path}" 20 | else 21 | @message = failed_path 22 | end 23 | 24 | clean_backtrace 25 | end 26 | 27 | # 28 | # Error message string. 29 | # 30 | def to_s 31 | "LoadError: cannot load such file -- #{@message}" 32 | end 33 | 34 | # 35 | # Take an +error+ and remove any mention of 'library' from it's backtrace. 36 | # Will leaving the backtrace untouched if $DEBUG is set to true. 37 | # 38 | def clean_backtrace 39 | return if ENV['debug'] || $DEBUG 40 | bt = backtrace 41 | bt = bt.reject{ |e| $RUBY_IGNORE_CALLERS.any?{ |re| re =~ e } } if bt 42 | set_backtrace(bt) 43 | end 44 | end 45 | 46 | end 47 | end 48 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | BSD-2-Clause License 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions 5 | are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in the 12 | documentation and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 | OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 | OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 | SUCH DAMAGE. 25 | 26 | -------------------------------------------------------------------------------- /work/benchmarks/vsgems_timed.rb: -------------------------------------------------------------------------------- 1 | require 'open3' 2 | 3 | $bench_env = File.dirname(__FILE__) + '/rubygems.roll' 4 | 5 | def time(cmd) 6 | cmd = %[export RUBY_LIBRARY="#{$bench_env}"; export RUBYOPT=""; ] + cmd 7 | t = Time.now 8 | Open3.popen3(cmd) do |stdin, stdout, stderr| 9 | out_str = stdout.read 10 | err_str = stderr.read 11 | puts out_str unless out_str.empty? 12 | puts err_str unless err_str.empty? 13 | end 14 | Time.now - t 15 | end 16 | 17 | # primers 18 | time_gems_req = time %[ruby -rubygems -e'nil'] 19 | time_roll_req = time %[ruby -rolls -e'nil'] 20 | 21 | time_gems_use = time %[ruby -rubygems -e'require "facets"'] 22 | time_roll_use = time %[ruby -rolls -e'require "facets"'] 23 | 24 | # real 25 | time_gems_req = time %[ruby -rubygems -e'nil'] 26 | time_roll_req = time %[ruby -rolls -e'nil'] 27 | 28 | time_gems_use = time %[ruby -rubygems -e'require "facets"'] 29 | time_roll_use = time %[ruby -rolls -e'require "facets"'] 30 | 31 | time_gems_load = time_gems_use - time_gems_req 32 | time_roll_load = time_roll_use - time_roll_req 33 | 34 | puts " %-16s %-16s" % [ 'Rolls', 'Gems' ] 35 | puts "REQUIRE : %-16.8f %-16.8f" % [ time_roll_req, time_gems_req ] 36 | puts "UTILIZE : %-16.8f %-16.8f" % [ time_roll_load, time_gems_load ] 37 | puts "COMBINED: %-16.8f %-16.8f" % [ time_roll_use, time_gems_use ] 38 | -------------------------------------------------------------------------------- /work/studies/load-speeds/benchmark.rb: -------------------------------------------------------------------------------- 1 | require 'benchmark' 2 | 3 | def load_ruby 4 | eval(File.read('example.rb')) 5 | end 6 | 7 | def load_yaml 8 | YAML.load(File.new("example.yaml")) 9 | end 10 | 11 | def load_json 12 | JSON.load(File.new("example.json")) 13 | end 14 | 15 | def load_files 16 | data = {} 17 | #data['name'] = File.read('example/name') 18 | data['version'] = File.read('example/version') 19 | #data['loadpath'] = File.read('example/loadpath').strip.split(/\n/) 20 | data['require'] = File.read('example/loadpath').strip.split(/\n/) 21 | data 22 | end 23 | 24 | count = 10000 25 | 26 | puts 27 | puts "Files:" 28 | 29 | Benchmark.bm(25) do |x| 30 | x.report(" Files: "){ count.times{ load_files } } 31 | end 32 | 33 | puts 34 | puts "Ruby:" 35 | 36 | Benchmark.bm(25) do |x| 37 | x.report(" Ruby: "){ count.times{ load_ruby } } 38 | end 39 | 40 | puts 41 | puts "YAML:" 42 | 43 | Benchmark.bm(25) do |x| 44 | x.report(" Require YAML: "){ require 'yaml' } 45 | end 46 | 47 | Benchmark.bm(25) do |x| 48 | x.report(" YAML: "){ count.times{ load_yaml } } 49 | end 50 | 51 | puts 52 | puts "JSON:" 53 | 54 | Benchmark.bm(25) do |x| 55 | x.report(" Require JSON: "){ require 'json' } 56 | end 57 | 58 | Benchmark.bm(25) do |x| 59 | x.report(" JSON: "){ count.times{ load_json } } 60 | end 61 | 62 | -------------------------------------------------------------------------------- /lib/realms.rb: -------------------------------------------------------------------------------- 1 | require 'fileutils' 2 | require 'rbconfig' 3 | #require 'tmpdir' 4 | require 'yaml' 5 | require 'json' 6 | require 'versus' 7 | require 'autoload' 8 | 9 | require 'realms/index' 10 | require 'realms/core_ext' 11 | require 'realms/utils' 12 | require 'realms/errors' 13 | require 'realms/library' 14 | require 'realms/interface' 15 | require 'realms/metadata' 16 | require 'realms/manager' 17 | require 'realms/rubylib' 18 | #require 'realms/shell' 19 | 20 | # 21 | # Global load manager tracks available libraries and handles all loading. 22 | # 23 | $LOAD_MANAGER = Realms::Library::Manager.new 24 | 25 | # 26 | # When a library is being loaded from it will be pushed onto the load stack, 27 | # and popped off when finished. 28 | # 29 | $LOAD_STACK = [] 30 | 31 | # 32 | # Special #acquire feature allows scripts to be evaled into the context 33 | # of a module or class. This table makes sure it can only ever happen once. 34 | # 35 | $LOADED_SCOPE_FEATURES = Hash.new{ |h,k| h[k] = [] } 36 | 37 | # 38 | # Top namespace for Realms, primarily it only contains the Library class. 39 | # All other supporting classes and modules are within the Library class. 40 | # This makes it a clean toplevel include. 41 | # 42 | # @example 43 | # include Realms 44 | # 45 | module Realms 46 | #extend Library::ClassInterface 47 | 48 | # Should this be here? Or just in `olls.rb`? 49 | Library::Utils.bootstrap! 50 | end 51 | 52 | -------------------------------------------------------------------------------- /MANIFEST: -------------------------------------------------------------------------------- 1 | #!mast .index .yardopts bin lib man script test *.md *.txt 2 | .index 3 | .yardopts 4 | bin/realm 5 | lib/ealms.rb 6 | lib/realms/core_ext/file.rb 7 | lib/realms/core_ext/gem.rb 8 | lib/realms/core_ext/hash.rb 9 | lib/realms/core_ext/rbconfig.rb 10 | lib/realms/core_ext.rb 11 | lib/realms/errors/load_error.rb 12 | lib/realms/errors/validation_error.rb 13 | lib/realms/errors/version_conflict.rb 14 | lib/realms/errors.rb 15 | lib/realms/index.rb 16 | lib/realms/interface.rb 17 | lib/realms/kernel.rb 18 | lib/realms/library.rb 19 | lib/realms/manager.rb 20 | lib/realms/metadata.rb 21 | lib/realms/rubylib.rb 22 | lib/realms/shell/add.rb 23 | lib/realms/shell/dump.rb 24 | lib/realms/shell/gem.rb 25 | lib/realms/shell/help.rb 26 | lib/realms/shell/isolate.rb 27 | lib/realms/shell/list.rb 28 | lib/realms/shell/lock.rb 29 | lib/realms/shell/path.rb 30 | lib/realms/shell/remove.rb 31 | lib/realms/shell/show.rb 32 | lib/realms/shell/unlock.rb 33 | lib/realms/shell/verify.rb 34 | lib/realms/shell/where.rb 35 | lib/realms/shell.rb 36 | lib/realms/utils.rb 37 | lib/realms/version.rb 38 | lib/realms.rb 39 | lib/realms.yml 40 | man/realm-add.1.ronn 41 | man/realm-gem.1.ronn 42 | man/realm-isolate.1.ronn 43 | man/realm-list.1.ronn 44 | man/realm-path.1.ronn 45 | man/realm-rm.1.ronn 46 | man/realm-show.1.ronn 47 | man/realm-sync.1.ronn 48 | man/realm-verify.1.ronn 49 | man/realm.1.ronn 50 | script/install-0.2.0.sh 51 | script/install-current.sh 52 | script/install-master.sh 53 | script/setup 54 | HISTORY.md 55 | README.md 56 | LICENSE.txt 57 | -------------------------------------------------------------------------------- /lib/realms/core_ext/rbconfig.rb: -------------------------------------------------------------------------------- 1 | require 'rbconfig' 2 | 3 | module ::RbConfig 4 | 5 | # 6 | # Return the path to the data directory associated with the given 7 | # library name. 8 | # 9 | # Normally this is just: 10 | # 11 | # "#{Config::CONFIG['datadir']}/#{name}" 12 | # 13 | # But it may be modified by packages like RubyGems and Realms to handle 14 | # versioned data directories. 15 | # 16 | def self.datadir(name, versionless=false) 17 | if lib = Library.instance(name) 18 | lib.datadir(versionless) 19 | elsif defined?(super) 20 | super(name) 21 | else 22 | File.join(CONFIG['datadir'], name) 23 | end 24 | end 25 | 26 | # 27 | # Return the path to the configuration directory. 28 | # 29 | def self.confdir(name) 30 | if lib = Library.instance(name) 31 | lib.confdir 32 | else 33 | File.join(CONFIG['confdir'], name) 34 | end 35 | end 36 | 37 | # 38 | # Patterns used to identiy a Windows platform. 39 | # 40 | WIN_PATTERNS = [ 41 | /bccwin/i, 42 | /cygwin/i, 43 | /djgpp/i, 44 | /mingw/i, 45 | /mswin/i, 46 | /wince/i, 47 | ] 48 | 49 | #WINDOWS_PLATFORM = !!WIN_PATTERNS.find{ |r| RUBY_PLATFORM =~ r } 50 | 51 | # 52 | # Is this a windows platform? This method compares the entires 53 | # in +WIN_PATTERNS+ against +RUBY_PLATFORM+. 54 | # 55 | def self.windows_platform? 56 | case RUBY_PLATFORM 57 | when *WIN_PATTERNS 58 | true 59 | else 60 | false 61 | end 62 | end 63 | 64 | end 65 | 66 | -------------------------------------------------------------------------------- /work/deprecated/commands/lib/realms/shell/merge.rb: -------------------------------------------------------------------------------- 1 | module Realms 2 | 3 | module Shell 4 | 5 | # 6 | # Merge one roll with another. 7 | # 8 | def merge 9 | op.banner = "Usage: roll merge [from]\n" + 10 | " roll merge [from] [to]" 11 | op.separator "Merge roll files." 12 | op.on('--lock', '-l', "Lock after merging.") do 13 | opts[:lock] = true 14 | end 15 | 16 | parse 17 | 18 | if argv.size == 1 19 | src = Realms.roll_file 20 | dst = Realms.construct_roll_file(argv[0]) 21 | else 22 | src = Realms.construct_roll_file(argv[0]) 23 | dst = Realms.construct_roll_file(argv[1]) 24 | end 25 | 26 | safe_merge(src, dst) 27 | 28 | if opts[:lock] 29 | Roll.lock(dst) 30 | puts "Saved & Locked: #{dst}" 31 | else 32 | puts "Saved: #{dst}" 33 | end 34 | end 35 | 36 | private 37 | 38 | # Merge files safely. 39 | # 40 | def safe_merge(src, dst) 41 | if not File.exist?(src) 42 | $stderr.puts "File does not exist -- '#{src}`" 43 | exit -1 44 | end 45 | 46 | if not File.exist?(dst) 47 | $stderr.puts "'#{dst}` already exists. Use --force option to overwrite." 48 | exit -1 49 | end 50 | 51 | src_txt = File.read(src).strip 52 | dst_txt = File.read(src).strip 53 | 54 | File.open(dst, 'w') do |file| 55 | file << dst_txt + "\n" + src_txt 56 | end 57 | end 58 | 59 | end 60 | 61 | end 62 | 63 | -------------------------------------------------------------------------------- /work/consider/fake_gem.rb: -------------------------------------------------------------------------------- 1 | # TODO: Instead of supporting gemspecs as is, create a tool 2 | # that will add a .package file to each one. 3 | # 4 | def load_gemspec 5 | return false unless File.basename(File.dirname(location)) == 'gems' 6 | specfile = File.join(location, '..', '..', 'specifications', File.basename(location) + '.gemspec') 7 | if File.exist?(specfile) 8 | fakegem = FakeGem.load(specfile) 9 | self.name = fakegem.name 10 | self.version = fakegem.version 11 | self.loadpath = fakegem.require_paths 12 | true 13 | else 14 | false 15 | end 16 | end 17 | 18 | # Ecapsulates the fake parsing of a gemspec. 19 | # 20 | module FakeGem 21 | module Gem #:nodoc: 22 | class Specification #:nodoc: 23 | attr :fake_options 24 | def initialize(&block) 25 | @fake_options = {} 26 | yield(self) 27 | end 28 | def method_missing(sym, *args) 29 | name = sym.to_s 30 | case name 31 | when /=$/ 32 | @fake_options[name.chomp('=')] = args.first 33 | else 34 | @fake_options[name] 35 | end 36 | end 37 | end 38 | class Requirement 39 | def initialize(*a) 40 | end 41 | end 42 | end 43 | # 44 | def self.load(file) 45 | text = File.read(file) 46 | fake_spec = eval(text, binding) 47 | fake_spec 48 | end 49 | end 50 | 51 | -------------------------------------------------------------------------------- /lib/realms/shell/help.rb: -------------------------------------------------------------------------------- 1 | module Realms 2 | class Library 3 | module Shell 4 | register :help 5 | 6 | # 7 | # Display main help message. 8 | # 9 | def help 10 | spacer = " %-32s %s" 11 | 12 | op.banner = "USAGE:\n realm [--OPT1 --OPT2 ...]" 13 | 14 | op.separator " " 15 | op.separator "COMMANDS:" 16 | op.separator spacer % ["list ", "List available libraries."] 17 | op.separator spacer % ["dump ", "Dump serialized ledger."] 18 | op.separator spacer % ["path ", "Output bin PATH list."] 19 | op.separator spacer % ["show ", "Show library details."] 20 | op.separator spacer % ["where ", "Locate a library feature."] 21 | op.separator spacer % ["add ", "Insert directory into current ledger."] 22 | op.separator spacer % ["rm ", "Remove directory from current ledger."] 23 | op.separator spacer % ["lock ", "Cache load ledger."] 24 | op.separator spacer % ["unlock ", "Unlock load ledger."] 25 | op.separator spacer % ["verify ", "Verify library requirements are available."] 26 | op.separator spacer % ["isolate ", "Create an isolation list for a library."] 27 | #op.separator spacer % ["gem ", "Run gem command, then re-lock ledger."] 28 | 29 | op.separator " " 30 | op.separator "GENERAL OPTIONS:" 31 | 32 | puts op 33 | end 34 | 35 | end 36 | 37 | end 38 | end 39 | -------------------------------------------------------------------------------- /work/deprecated/version_case.rb: -------------------------------------------------------------------------------- 1 | Covers 'roll/version' 2 | 3 | Case Roll::Version do 4 | 5 | Concern "Ensure functionality of Roll's Version class." 6 | 7 | Unit :to_s do 8 | v = Roll::Version.new('1.2.3') 9 | v.to_s.assert == '1.2.3' 10 | end 11 | 12 | Unit :to_str do 13 | v = Roll::Version.new('1.2.3') 14 | v.to_str.assert == '1.2.3' 15 | end 16 | 17 | #def test_inspect 18 | # v = Roll::Version.new('1.2.3') 19 | # assert_equal('1.2.3', v.inspect) 20 | #end 21 | 22 | Unit :[] do 23 | v = Roll::Version.new('1.2.3') 24 | v[0].assert == 1 25 | v[1].assert == 2 26 | v[2].assert == 3 27 | end 28 | 29 | Unit :<=> do 30 | v1 = Roll::Version.new('1.2.3') 31 | v2 = Roll::Version.new('1.2.4') 32 | (v2 <=> v1).assert == 1 33 | end 34 | 35 | # def =~( other ) 36 | # #other = other.to_t 37 | # upver = other.dup 38 | # upver[0] += 1 39 | # @self >= other and @self < upver 40 | # end 41 | 42 | Unit :=~, "pessimistic constraint" do 43 | v1 = Roll::Version.new('1.2.4') 44 | v2 = Roll::Version.new('1.2') 45 | assert(v1 =~ v2) 46 | end 47 | 48 | Unit :major do 49 | v = Roll::Version.new('1.2.3') 50 | v.major.assert == 1 51 | end 52 | 53 | Unit :minor do 54 | v = Roll::Version.new('1.2.3') 55 | v.minor.assert == 2 56 | end 57 | 58 | Unit :patch do 59 | v = Roll::Version.new('1.2.3') 60 | v.patch.assert == 3 61 | end 62 | 63 | Unit :parse_constraint do 64 | constraint = Roll::Version.parse_constraint("~> 1.0.0") 65 | constraint.assert == ["=~", Roll::Version['1.0.0']] 66 | end 67 | 68 | end 69 | 70 | -------------------------------------------------------------------------------- /work/deprecated/commands/lib/realms/shell/use.rb: -------------------------------------------------------------------------------- 1 | module Realms 2 | 3 | module Shell 4 | 5 | # 6 | # Show/Change current environment. 7 | # 8 | def use 9 | op.banner = "Usage: roll use [name]" 10 | op.separator "Display/Switch current roll." 11 | op.separator " " 12 | op.separator "NOTE: Switching rolls spawns a new child shell." 13 | op.separator "You can set $ROLL_FILE= instead to avoid this." 14 | #op.on("--clear", "-c") do 15 | # args.unshift 'system' 16 | #end 17 | 18 | parse 19 | 20 | name = args.first 21 | 22 | if name 23 | switch_rolls(name) 24 | else 25 | show_rolls 26 | end 27 | end 28 | 29 | private 30 | 31 | # 32 | def switch_rolls(name) 33 | shell_stack = ENV['roll_shell_stack'] 34 | 35 | old_roll_file = Roll.roll_file 36 | new_roll_file = Roll.construct_roll_name(name) 37 | 38 | stack = "#{shell_stack}:#{old_roll_file}" 39 | 40 | ENV['roll_shell_stack'] = stack 41 | ENV['roll_file'] = new_roll_file 42 | 43 | puts "Roll is now `#{name}'." 44 | 45 | exec("$SHELL") # -i") 46 | end 47 | 48 | # 49 | def show_rolls 50 | curr = ::Roll.environment.name 51 | envs = ::Roll.environments.sort 52 | if envs.empty? 53 | puts "No environments." 54 | else 55 | puts 56 | envs.each do |env| 57 | if curr == env 58 | puts "=> #{env}" 59 | else 60 | puts " #{env}" 61 | end 62 | end 63 | puts 64 | end 65 | end 66 | 67 | end 68 | 69 | end 70 | -------------------------------------------------------------------------------- /spec/spec_library.rb: -------------------------------------------------------------------------------- 1 | require_relative 'helper' 2 | 3 | describe Realms::Library do 4 | 5 | let(:tryme10){ Realms::Library.new('projects/tryme/1.0') } 6 | let(:tryme11){ Realms::Library.new('projects/tryme/1.1') } 7 | 8 | it "should initialize given the location of a project" do 9 | assert tryme10.kind_of?(Realms::Library) 10 | end 11 | 12 | it "should provide access to basic metadata" do 13 | assert tryme10.name == "tryme" 14 | assert tryme11.name == "tryme" 15 | 16 | assert tryme10.version.to_s == "1.0" 17 | assert tryme11.version.to_s == "1.1" 18 | end 19 | 20 | it "should provide secondary metadata from a `.index` or `.gemspec` file via #[]" do 21 | #tryme10.metadata['resources']['homepage'].assert == "http://tryme.foo" 22 | #tryme11.metadata['resources']['homepage'].assert == "http://tryme.foo" 23 | end 24 | 25 | it "should load scripts from the library" do 26 | tryme10.load('tryme.rb') 27 | 28 | assert $tryme_message == "Try Me v1.0" 29 | 30 | #assert_raises(Realms::Library::VersionConflict) do 31 | # tryme11.load('tryme.rb') 32 | #end 33 | end 34 | 35 | it "should require scripts from the library" do 36 | tryme10.require('tryme') 37 | 38 | assert $tryme_message == "Try Me v1.0" 39 | 40 | # different version will raise an error 41 | assert_raises(Realms::Library::VersionConflict) do 42 | tryme11.load('tryme.rb') 43 | end 44 | 45 | # same version can be required again 46 | tryme10.require('tryme') 47 | 48 | # bypass this constraint using :force option 49 | tryme11.require('tryme', :force=>true) 50 | assert $tryme_message == "Try Me v1.1" 51 | end 52 | 53 | end 54 | 55 | -------------------------------------------------------------------------------- /.index: -------------------------------------------------------------------------------- 1 | --- 2 | type: ruby 3 | revision: 2013 4 | sources: 5 | - var 6 | authors: 7 | - name: Trans 8 | email: transfire@gmail.com 9 | organizations: [] 10 | requirements: 11 | - name: versus 12 | - name: autoload 13 | - groups: 14 | - test 15 | development: true 16 | name: qed 17 | - groups: 18 | - test 19 | development: true 20 | name: ae 21 | - groups: 22 | - test 23 | development: true 24 | name: minitest 25 | - groups: 26 | - test 27 | development: true 28 | name: minitap 29 | - groups: 30 | - test 31 | development: true 32 | name: tapout 33 | - groups: 34 | - build 35 | development: true 36 | name: detroit 37 | - groups: 38 | - build 39 | version: 5.0+ 40 | development: true 41 | name: setup 42 | conflicts: [] 43 | alternatives: [] 44 | resources: 45 | - type: home 46 | uri: http://rubyworks.github.com/roll 47 | label: Homepage 48 | - type: code 49 | uri: http://rubyworks.github.com/roll 50 | label: Source Code 51 | - type: mail 52 | uri: http://groups.google.com/groups/rubyworks-mailinglist 53 | label: Mailing List 54 | repositories: 55 | - name: upstream 56 | scm: git 57 | uri: git://github.com/rubyworks/roll.git 58 | categories: [] 59 | paths: 60 | load: 61 | - lib 62 | copyrights: 63 | - holder: Thomas Sawyer 64 | year: '2006' 65 | license: BSD-2-Clause 66 | created: '2006-12-10' 67 | summary: Ruby Object-Oriented Library Ledger 68 | title: Roll 69 | version: 2.0.0 70 | name: realms 71 | description: ! 'Rolls is a library set manager for Ruby built on top of the Library 72 | gem. 73 | 74 | With Rolls, code repositories can be made visible to Ruby just by setting 75 | 76 | an environment variable.' 77 | date: '2013-01-17' 78 | -------------------------------------------------------------------------------- /lib/realms/shell/verify.rb: -------------------------------------------------------------------------------- 1 | module Realms 2 | class Library 3 | module Shell 4 | register :verify 5 | 6 | # 7 | # Verify that a library's requirements are available. 8 | # 9 | # @return nothing 10 | # 11 | def verify 12 | version = nil 13 | development = nil 14 | 15 | op.banner = "Usage: realm verify [name]" 16 | op.separator "Verify dependencies are available." 17 | 18 | op.on('--version', '-v [VERSION]', "version constraint") do |val| 19 | version = val 20 | end 21 | 22 | op.on('--development', '-d', "include development requirements") do |val| 23 | development = val 24 | end 25 | 26 | parse 27 | 28 | name = argv.first 29 | 30 | if name 31 | library = $LOAD_MANAGER.current(name, version) 32 | else 33 | root = Dir.pwd # TODO: lookup root of project? 34 | library = $LOAD_MANAGER.add(root) 35 | end 36 | 37 | if library.requirements.empty? 38 | puts "Project #{library.name} has no requirements." 39 | else 40 | verify_via_isolation(library, development) 41 | end 42 | end 43 | 44 | # 45 | # 46 | # 47 | def verify_via_isolation(library, development) 48 | $LOAD_MANAGER.isolate_library(library, development) 49 | $LOAD_MANAGER.each do |name, lib| 50 | puts "\u2713 %s %s" % ["#{lib.name}-#{lib.version}", lib.location] 51 | end 52 | end 53 | 54 | # 55 | # 56 | # 57 | #def verify_via_activation(library, development) 58 | # $LOAD_MANAGER.activate_library(library) 59 | # $LOAD_MANAGER.verify_library(library, development) 60 | # puts "#{library.name}-#{library.version} looks good" 61 | #end 62 | 63 | end 64 | end 65 | end 66 | -------------------------------------------------------------------------------- /work/consider/import.rb: -------------------------------------------------------------------------------- 1 | # Python-like +import+ support. 2 | # (or should we use Perl's +use+ instead?) 3 | # 4 | # TODO Feature starting with './' should be loaded from => dirname(__FILE__). 5 | # TODO Intergrate w/ "Rolls" (versioning, metadata, Library class, etc.) 6 | 7 | class Module 8 | 9 | def import( feature, opts={} ) 10 | if from = opts[:from] 11 | file = lookup_feature(File.join(from,feature)) 12 | else 13 | file = lookup_feature(feature) 14 | end 15 | 16 | namespace = feature.split('/').collect{|name|name.capitalize} 17 | 18 | mod = namespace.inject(Object) do |parent,name| 19 | if parent.const_defined?(name) 20 | parent.const_get(name) 21 | else 22 | parent.const_set(name, Module.new) 23 | end 24 | end 25 | 26 | mod.module_eval File.read(file) 27 | mod.extend mod 28 | mod 29 | end 30 | 31 | def new(*a,&b) 32 | aspect.new(*a,&b) 33 | end 34 | 35 | def aspect 36 | @aspect_ ||= Class.new{include self} 37 | end 38 | 39 | def lookup_feature( feature, load_path=$LOAD_PATH ) 40 | feature = feature.to_s 41 | search = '{'+load_path.join(',')+'}/'+feature.to_s+'.rb' 42 | files = Dir.glob(search) 43 | file = files[0] 44 | return file 45 | end 46 | 47 | #def const_missing(const) 48 | # if Object == self 49 | # feature = "#{const}".gsub('::','/').downcase 50 | # else 51 | # feature = "#{self}::#{const}".gsub('::','/').downcase 52 | # end 53 | # file = lookup_feature(feature) 54 | # if file 55 | # import feature 56 | # else 57 | # const_set(const, Module.new) 58 | # end 59 | #end 60 | 61 | end 62 | 63 | 64 | class Object 65 | 66 | def import(*a) 67 | Object.import(*a) 68 | end 69 | 70 | end 71 | 72 | 73 | if __FILE__ == $0 74 | 75 | import 'demo', :from => 'demo' 76 | 77 | Demo.hello 78 | 79 | end 80 | 81 | -------------------------------------------------------------------------------- /demo/02_commandline/applique/bash.rb: -------------------------------------------------------------------------------- 1 | require 'stringio' 2 | require 'session' 3 | 4 | PWD = Dir.pwd 5 | 6 | When 'standard output', 'will look like' do |text| 7 | out = @stdout.tabto(0).strip # FIXME: QED is over unindenting the text 8 | out.assert == text 9 | end 10 | 11 | # Override shell operator to internal roll command. 12 | def `(cmd) #` for highlighter 13 | case cmd 14 | #when /^roll\ use/ 15 | # can't run b/c of child shell 16 | when /^roll/ 17 | cmd = cmd.sub('roll', 'ruby -Ilib bin/roll -') 18 | end 19 | stdout, stderr = shell.execute(cmd) 20 | #puts stdout 21 | #puts stderr 22 | @stdout = stdout 23 | @stderr = stderr 24 | raise "#{stderr}" if shell.status != 0 25 | return @stdout 26 | end 27 | 28 | def shell 29 | @shell ||= ( 30 | sh = ::Session::Bash.new 31 | sh.execute %[unset RUBYENV] 32 | sh.execute %[unset roll_environment] 33 | sh.execute %[export RUBYOPT="-rubygems"] 34 | sh.execute %[export XDG_CONFIG_HOME="#{PWD}/tmp/config"] 35 | sh.execute %[export XDG_CACHE_HOME="#{PWD}/tmp/cache"] 36 | sh 37 | ) 38 | end 39 | 40 | =begin 41 | def `(cmd) #` 42 | case cmd 43 | when /^roll\ use\ (.*?)$/ 44 | name = $1.strip 45 | ENV['RUBYENV'] = name 46 | $LEDGER = Roll::Ledger.new(name) # pretty crazy, but should be ok for testing 47 | when /^roll/ 48 | cmd = cmd.sub('roll', '').strip 49 | argv = *Shellwords.shellwords(cmd) 50 | out, err = capture do 51 | Roll::Command.main(*argv) 52 | end 53 | out.rewind; err.rewind 54 | @stdout, @stderr = out.read, err.read 55 | return @stdout 56 | else 57 | #super(cmd) # TODO: why did `export` not work? 58 | end 59 | end 60 | 61 | def capture 62 | out = StringIO.new 63 | err = StringIO.new 64 | $stdout = out 65 | $stderr = err 66 | yield 67 | return out, err 68 | ensure 69 | $stdout = STDOUT 70 | $stderr = STDERR 71 | end 72 | =end 73 | 74 | -------------------------------------------------------------------------------- /demo/02_commandline/06_sync.md: -------------------------------------------------------------------------------- 1 | # Sync Command 2 | 3 | When we insert a new lookup location, the index is automatically regenerated. 4 | However when the situation on disc changes, our index can become out-of-sync 5 | with the reality of the projects in the lookup locations. 6 | 7 | As demonstrate in "Roll List" we know that the current environment, the default 8 | `production`, has two different libraries, `tryme` and `foo`. To demonstrate 9 | `sync` let's purposefully remove the `foo` project. 10 | 11 | `rm -r tmp/projects/foo` 12 | 13 | Now the environment has an index entry for a project that is no longer present. 14 | When utilizing the environment in your scripts, this will not effect anything, 15 | any missing projects will simply be ignored. 16 | 17 | To refresh the environment's index, bringing it back into sync, issue the `sync` 18 | command. 19 | 20 | `roll sync` 21 | 22 | We can take a peak at the production configuration file to verify that foo 23 | is in fact no longer present. 24 | 25 | text = File.read('tmp/config/roll/environments/production') 26 | text.refute.include?('foo') 27 | 28 | If we wish to re-sync all environments in one go, we can do that too by 29 | specifying the pseudo-environment 'all'. 30 | 31 | `roll sync all` 32 | 33 | When do we need to re-sync a load environment? 34 | 35 | * When a project is added, removed or renamed within a lookup location. 36 | * When a project's name or loadpath has changed. 37 | 38 | The later means that the `.ruby/name` or `.ruby/loadpath` files would 39 | have changed. 40 | 41 | The `sync` command offer one last feature that allows us to check if 42 | and environment is out-of-sync or not, without actually re-syncing. 43 | To do this provide the `--check` or `-c` option. 44 | 45 | `roll sync --check` 46 | 47 | The standard output will look like: 48 | 49 | Index for `production` is in-sync. 50 | 51 | This is similar to the previously mentioned `show --status` command. 52 | 53 | -------------------------------------------------------------------------------- /demo/01_application/02_library.md: -------------------------------------------------------------------------------- 1 | # Library Instances 2 | 3 | The Library class can be initialized given the location of the project. 4 | 5 | tryme10 = Realms::Library.new('projects/tryme/1.0') 6 | tryme11 = Realms::Library.new('projects/tryme/1.1') 7 | 8 | With a library instance in hand we can query it for information about itself. 9 | 10 | tryme10.name.assert == "tryme" 11 | tryme11.name.assert == "tryme" 12 | 13 | tryme10.version.to_s.assert == "1.0" 14 | tryme11.version.to_s.assert == "1.1" 15 | 16 | TODO: Secondary information, taken from the `.index` or `.gemspec` file, can be 17 | queried via the `#[]` method. 18 | 19 | #tryme10.metadata['resources']['homepage'].assert == "http://tryme.foo" 20 | #tryme11.metadata['resources']['homepage'].assert == "http://tryme.foo" 21 | 22 | Of course, the most important function of a library is to load and require 23 | a script. With an Library instance in hand this can be achieved directly. 24 | 25 | tryme10.load('tryme.rb') 26 | $tryme_message.assert == "Try Me v1.0" 27 | 28 | But if we try to load from another version, we will get a VersionConflict 29 | error. 30 | 31 | expect Realms::Library::VersionConflict do 32 | tryme11.load('tryme.rb') 33 | end 34 | 35 | However, we can bypass this constraint (if we know what you are doing!) with 36 | the :force option. 37 | 38 | tryme11.load('tryme.rb', :force=>true) 39 | $tryme_message.assert == "Try Me v1.1" 40 | 41 | Notice that when requiring files directly via a Library instance, if a file 42 | is required from two different versions of a library, a VersionConflict 43 | error will be rasied. 44 | 45 | expect Realms::Library::VersionConflict do 46 | tryme11.require('tryme') 47 | end 48 | 49 | But there is no error if we use the active version. 50 | 51 | tryme10.require('tryme') 52 | 53 | TODO: In the future, I think we will put in a version check, and a :force 54 | option to override. 55 | 56 | -------------------------------------------------------------------------------- /work/reference/require.rb: -------------------------------------------------------------------------------- 1 | # NOT USED. 2 | 3 | # TITLE: 4 | # 5 | # Require / Load Module Extensions 6 | # 7 | # SUMMARY: 8 | # 9 | # In module require and load. 10 | # 11 | # AUTHORS: 12 | # 13 | # - Thomas Sawyer 14 | 15 | class Module 16 | 17 | # Load file into module/class namespace. 18 | 19 | def module_load( path ) 20 | if path =~ /^[\/~.]/ 21 | file = File.expand_path(path) 22 | else 23 | $LOAD_PATH.each do |lp| 24 | file = File.join(lp,path) 25 | break if File.exist?(file) 26 | file = nil 27 | end 28 | end 29 | 30 | raise LoadError, "unknown file -- #{path}" unless file 31 | 32 | module_eval(File.read(file)) 33 | end 34 | 35 | # Require file into module/class namespace. 36 | 37 | def module_require( path ) 38 | if path =~ /^[\/~.]/ 39 | file = File.expand_path(path) 40 | else 41 | $LOAD_PATH.each do |lp| 42 | file = File.join(lp,path) 43 | break if File.exist?(file) 44 | file += '.rb' 45 | break if File.exist?(file) 46 | file = nil 47 | end 48 | end 49 | 50 | raise LoadError, "unknown file -- #{path}" unless file 51 | 52 | @loaded ||= {} 53 | if @loaded.key?(file) 54 | false 55 | else 56 | @loaded[file] = true 57 | script = File.read(file) 58 | module_eval(script) 59 | true 60 | end 61 | end 62 | end 63 | 64 | 65 | class Class 66 | alias_method :class_load, :module_load 67 | alias_method :class_require, :module_require 68 | end 69 | 70 | 71 | 72 | =begin 73 | class ::Module 74 | 75 | alias_method :module_require_without_roll, :module_require 76 | 77 | # Module require script. 78 | 79 | def module_require(file) 80 | Library.module_require(self, file) 81 | end 82 | 83 | alias_method :module_load_without_roll, :module_load 84 | 85 | # Module load script. 86 | 87 | def module_load(file, wrap=false) 88 | Library.module_load(self, file, wrap) 89 | end 90 | 91 | end 92 | =end 93 | 94 | -------------------------------------------------------------------------------- /lib/realms/shell/isolate.rb: -------------------------------------------------------------------------------- 1 | module Realms 2 | class Library 3 | module Shell 4 | register :isolate 5 | 6 | # 7 | # Create an isolation index. 8 | # 9 | def isolate 10 | development = false 11 | format = nil 12 | 13 | op.banner = "Usage: realm isolate [PATH]" 14 | op.separator "Create an isolation template." 15 | 16 | op.on('--development', '-d', "include development dependencies.") do 17 | development = true 18 | end 19 | 20 | op.on('--gem', '-g', "Generate a template for use via RubyGems.") do 21 | format = :gem 22 | end 23 | 24 | op.on('--lib', '-l', "Generate a template in YAML format.") do 25 | format = :library 26 | end 27 | 28 | parse 29 | 30 | location = argv.first || Dir.pwd # TODO: Utils.locate_root ? 31 | 32 | library = $LOAD_MANAGER.add(location) 33 | 34 | generate_isolation_template(location, development, format) 35 | end 36 | 37 | private 38 | 39 | # 40 | # Generate isolation template. 41 | # 42 | def generate_isolation_template(library, development, format=nil) 43 | $LOAD_MANAGER.isolate_library(library, development) 44 | case format 45 | when :gem 46 | $LOAD_MANAGER.each do |name, lib| 47 | puts "gem '%s', '= %s'" % [lib.name, lib.version] 48 | end 49 | when :gemfile 50 | $LOAD_MANAGER.each do |name, lib| 51 | puts "gem '%s', '= %s'" % [lib.name, lib.version] 52 | end 53 | when :yaml 54 | puts $LOAD_MANAGER.map{ |name, lib| 55 | { 'name'=>lib.name, 'version'=>lib.version.to_s } 56 | }.to_yaml 57 | when :library 58 | $LOAD_MANAGER.each do |name, lib| 59 | puts "library '%s', '= %s'" % [lib.name, lib.version] 60 | end 61 | else 62 | JSON.pretty_generate($LOAD_MANAGER.to_h) 63 | end 64 | end 65 | 66 | end 67 | end 68 | end 69 | -------------------------------------------------------------------------------- /work/deprecated/commands/demo/02_commandline/07_copy.md: -------------------------------------------------------------------------------- 1 | = Copy Command 2 | 3 | As developer's we want to be able to setup new library environments 4 | based on existing environments. 5 | 6 | To copy the current environment, we can issue the `copy` command. 7 | 8 | `roll copy experiment` 9 | 10 | Where `experiment` is the name of the new load environment built from the 11 | current environment (production). If we compare the output of their respective 12 | indexes we will see they are exactly the same, 13 | 14 | `roll show --index`.assert == `roll show --index experiment` 15 | 16 | It is also possible to copy a named environment to a new environment. 17 | 18 | `roll copy experiment alternate` 19 | 20 | This will copy the `experiment` environment we just created to a new 21 | environment called `alternate`. Again we can verify they are identical 22 | in content. 23 | 24 | `roll show --index experiment`.assert == `roll show --index alternate` 25 | 26 | If we try to copy an environment that doesn't exist, we will get an 27 | error telling us as much. 28 | 29 | expect RuntimeError do 30 | `roll copy notaname wherever` 31 | end 32 | 33 | @stderr.assert.include?('does not exist') 34 | 35 | If we try to copy an environment over a pre-existing environment, we will 36 | get an error telling us that we need to use the `--force` option in order 37 | to overwrite it. 38 | 39 | expect RuntimeError do 40 | `roll copy alternate experiment` 41 | end 42 | 43 | @stderr.assert.include?('already exists') 44 | @stderr.assert.include?('--force option to overwrite') 45 | 46 | By supplying the `--force` option we can go ahead and perform the operation. 47 | 48 | `roll copy alternate experiment` 49 | 50 | And again we verify the contents are identical. 51 | 52 | `roll show --index alternate`.assert == `roll show --index experiment` 53 | 54 | (TODO: Note, with this last step we should alter +experiment+ first to make 55 | the final test more robust. It's too easy to get a false positive here. 56 | But we'll let it go for the moment.) 57 | 58 | -------------------------------------------------------------------------------- /work/benchmarks/serializers.rb: -------------------------------------------------------------------------------- 1 | require 'benchmark' 2 | require 'csv' 3 | require 'yaml' 4 | require 'json' 5 | require 'tmpdir' 6 | 7 | count = 1000 8 | 9 | file = Dir.tmpdir + "/roll-benchmark-file" 10 | 11 | data = [ 12 | ["row1", "of", "CSV", "data"], 13 | ["row2", "of", "CSV", "data"], 14 | ["row3", "of", "CSV", "data"], 15 | ["row4", "of", "CSV", "data"] 16 | ] 17 | 18 | Benchmark.bm(25) do |x| 19 | x.report(" File Write: ") do 20 | count.times do 21 | File.open(file + '.txt', "w") do |csv| 22 | data.each do |row| 23 | csv << row.inspect 24 | end 25 | end 26 | end 27 | end 28 | 29 | x.report(" File Read: ") do 30 | count.times do 31 | array = [] 32 | File.readlines(file + '.txt').each do |line| 33 | line = line.strip.chomp('"').sub(/^\"/,'') 34 | next if line.empty? 35 | next if line =~ /^#/ 36 | row = line.split('","') 37 | array << row 38 | end 39 | array 40 | end 41 | end 42 | 43 | x.report(" CSV Write ") do 44 | count.times do 45 | CSV.open(file + '.cvs', "wb") do |csv| 46 | data.each do |row| 47 | csv << row 48 | end 49 | end 50 | end 51 | end 52 | 53 | x.report(" CSV Read: ") do 54 | count.times do 55 | array = [] 56 | CSV.foreach(file + '.cvs') do |row| 57 | array << row 58 | end 59 | array 60 | end 61 | end 62 | 63 | x.report(" Marshal Write: ") do 64 | count.times do 65 | File.open(file + '.marshal', "wb") do |w| 66 | w << Marshal.dump(data) 67 | end 68 | end 69 | end 70 | 71 | x.report(" Marshal Read: ") do 72 | count.times do 73 | Marshal.load(File.new(file + '.marshal')) 74 | end 75 | end 76 | 77 | x.report(" YAML Write: ") do 78 | count.times do 79 | File.open(file + '.yaml', "wb") do |w| 80 | w << data.to_yaml 81 | end 82 | end 83 | end 84 | 85 | x.report(" YAML Read: ") do 86 | count.times do 87 | YAML.load(File.new(file + '.yaml')) 88 | end 89 | end 90 | 91 | x.report(" JSON Write: ") do 92 | count.times do 93 | File.open(file + '.yaml', "wb") do |w| 94 | w << JSON.dump(data) 95 | end 96 | end 97 | end 98 | 99 | x.report(" JSON Read: ") do 100 | count.times do 101 | JSON.load(File.new(file + '.yaml')) 102 | end 103 | end 104 | 105 | end 106 | 107 | -------------------------------------------------------------------------------- /work/deprecated/once-again-into-the-breach/kernel.rb: -------------------------------------------------------------------------------- 1 | $RUBY_IGNORE_CALLERS ||= [] 2 | $RUBY_IGNORE_CALLERS << /#{__FILE__}/ # TODO: should this be more general, e.g. File.dirname(__FILE__) ? 3 | 4 | module ::Kernel 5 | 6 | class << self 7 | alias __require__ require 8 | alias __load__ load 9 | end 10 | 11 | alias __require__ require 12 | alias __load__ load 13 | 14 | # 15 | # Acquire feature - This is Roll's modern require/load method. 16 | # It differs from the usual `#require` or `#load` primarily by 17 | # the fact that it will search the current loading library, 18 | # i.e. the one belonging to the feature on the top of the 19 | # #LOAD_STACK, before looking elsewhere. The reason we can't 20 | # adjust `#require` to do this is becuase it could load a local 21 | # feature when a non-local feature was intended. For example, if 22 | # a library contained 'fileutils.rb' then this would be loaded 23 | # rather the Ruby's standard library. When using `#acquire`, 24 | # one would have to use the `ruby/` prefix to ensure the Ruby 25 | # library gets loaded. 26 | # 27 | # @param pathname [String] 28 | # The pathname of the feature to acquire. 29 | # 30 | # @param options [Hash] 31 | # Load options are `:wrap`, `:load`, `:legacy` and `:search`. 32 | # 33 | # @return [true, false] 34 | # Was the feature newly required or successfully loaded, depending 35 | # on the `:load` option settings. 36 | # 37 | def acquire(pathname, options={}) #, &block) 38 | Ledger.acquire(pathname, options) #, &block) 39 | end 40 | 41 | module_function :acquire 42 | 43 | # 44 | # Require feature - This is the same as acquire except that the 45 | # `:legacy` option is fixed as `true`. 46 | # 47 | # @param pathname [String] 48 | # The pathname of the feature to require. 49 | # 50 | # @param options [Hash] 51 | # Load options can be `:wrap`, `:load` and `:search`. 52 | # 53 | # @return [true,false] if feature was newly required 54 | # 55 | def require(pathname, options={}) #, &block) 56 | Ledger.require(pathname, options) #, &block) 57 | end 58 | 59 | module_function :require 60 | 61 | # 62 | # Load feature - This is the same as acquire except that the 63 | # `:legacy` and `:load` options are fixed as `true`. 64 | # 65 | # @param pathname [String] 66 | # The pathname of the feature to load. 67 | # 68 | # @param options [Hash] 69 | # Load options can be :wrap and :search. 70 | # 71 | # @return [true, false] if feature was successfully loaded 72 | # 73 | def load(pathname, options={}) #, &block) 74 | Ledger.load(pathname, options) #, &block) 75 | end 76 | 77 | module_function :load 78 | 79 | end 80 | -------------------------------------------------------------------------------- /work/sandbox/library_on_index.rb: -------------------------------------------------------------------------------- 1 | require 'roll/library' 2 | 3 | if defined? ::Library 4 | 5 | ::Library.setup 6 | 7 | else 8 | 9 | class Library 10 | 11 | STATIC_LOAD_PATH = $LOAD_PATH.dup 12 | 13 | #INDEX_FILE = "index.yaml" 14 | 15 | # The ledger 16 | @ledger = Hash.new{ |h,k| h[k] = [] } 17 | 18 | def self.ledger 19 | @ledger 20 | end 21 | 22 | def self.scan 23 | $LOAD_PATH.each do |lpath| 24 | next unless File.directory?(lpath) 25 | Dir.chdir(lpath) do 26 | libs = Dir.glob('*') 27 | libs.each do |lib| 28 | name = lib.chomp('.rb').chomp('.so') 29 | ledger[name] << lpath 30 | end 31 | end 32 | end 33 | end 34 | 35 | =begin 36 | libraries = Dir.glob('{' + $LOAD_PATH.join(',') + '}/*') 37 | libraries.each do |load_path| 38 | if File.file?(load_path) 39 | name = File.basename(load_path) 40 | @register << [name, load_path, nil] 41 | @register << [name.chomp('.rb'), load_path, nil] 42 | else 43 | index_file = File.join(load_path, INDEX_FILE) 44 | if File.file?(index_file) 45 | data = Roll::Package.open(index_file) 46 | data.register.each do |match, paths| 47 | @register << [match, load_path, paths] 48 | end 49 | else 50 | @register << [File.basename(load_path)+'/', load_path, ''] 51 | end 52 | end 53 | end 54 | @register.sort!{ |kv1, kv2| kv2[0] <=> kv1[0] } 55 | end 56 | =end 57 | 58 | # Inspection. 59 | 60 | def inspect 61 | if version 62 | "#" 63 | else 64 | "#" 65 | end 66 | end 67 | 68 | end 69 | 70 | 71 | module Kernel 72 | 73 | alias_method :require0, :require 74 | 75 | def require(reference) 76 | puts reference 77 | lib = reference.split('/').first 78 | name = lib.chomp('.rb').chomp('.so') 79 | if paths = Library.ledger[name] 80 | hold = $LOAD_PATH 81 | begin 82 | $LOAD_PATH.replace(paths) 83 | Kernel.require(reference) 84 | rescue LoadError => e 85 | puts reference + " (error)" 86 | $LOAD_PATH.replace(Library::STATIC_LOAD_PATH) 87 | require0(reference) 88 | ensure 89 | $LOAD_PATH.replace(hold) 90 | end 91 | else 92 | require0(reference) 93 | end 94 | end 95 | 96 | end 97 | 98 | end 99 | 100 | 101 | 102 | if __FILE__ == $0 103 | 104 | t = Time.now 105 | 106 | #Library.scan 107 | 108 | now = Time.now 109 | puts "#{now - t} secs" 110 | 111 | #Library.ledger.each do |lib, paths| 112 | # puts lib + " " + paths.join(" ") 113 | #end 114 | 115 | require 'cgi' 116 | 117 | require 'net/http' 118 | require 'net/http' 119 | 120 | require 'redcloth' 121 | 122 | now = Time.now 123 | puts "#{now - t} secs" 124 | 125 | end 126 | 127 | -------------------------------------------------------------------------------- /work/deprecated/commands/demo/02_commandline/01_use.md: -------------------------------------------------------------------------------- 1 | # Use Command 2 | 3 | The use command provides a convenient way to list available load environments, 4 | see which environment is current and switching between them. To list the 5 | available environments simply issue the `use` command with no additional 6 | parameters. 7 | 8 | `realm use` 9 | 10 | The standard output will look like: 11 | 12 | development 13 | => production 14 | testing 15 | 16 | Notice the arrow pointing to "production". This tells us which environment 17 | is current. We can switch environments by following the `use` command with 18 | the name of the environment desired. 19 | 20 | `realm use testing` 21 | 22 | Running `realm use` again we would see: 23 | 24 | development 25 | production 26 | => testing 27 | 28 | Switching between environments with `use` also means switching shells prompts. 29 | The `use` command actually spawns a new child shell after each invocation 30 | in order to effect shell variables. This means we can switch back to the 31 | previous environment quickly just by typing `exit`. 32 | 33 | We can actually see the stack of child shells create by `use` using the `stack` 34 | command. 35 | 36 | `realm stack` 37 | 38 | The standard output of which, at this point, would look like: 39 | 40 | production 41 | 42 | Which means, that if we used `exit` we would leave the "testing" environment 43 | and return to "production". 44 | 45 | There is another way to switch between environments, without spawning a new 46 | child shell, by setting the RUBYENV variable manually. 47 | 48 | `export RUBYENV=development` 49 | 50 | While setting the RUBYENV variable will avoid creating a new child shell, 51 | it will not adjust PATH settings, if your shell setup is using `realm path` to 52 | set the executable look-up locations. 53 | 54 | Switching between environments is also instrumental in creating new 55 | environments. For example, let's say we want to add a new experimental 56 | load environment. 57 | 58 | `realm use experimental` 59 | 60 | Invoking the `use` command to create a new load environment doesn't actually 61 | change anything except the current environment name. So if an unwanted name 62 | were accidentally typed, there is no harm done. Simply reissue the `use` 63 | command, or use `exit` to correct. 64 | 65 | To instantiate the new environment --writing the environments configuration 66 | file to disc, we need to insert a *lookup* location. 67 | 68 | `realm in tmp/projects` 69 | 70 | We will explore the `in` command more in the next section, for now we need 71 | only know that it added 'tmp/projects' to the experimental environment and 72 | saved the environment configuration to disc. We can verify this by having 73 | a look at the list of environments again. 74 | 75 | `realm use` 76 | 77 | The standard output will look like: 78 | 79 | development 80 | => experimental 81 | production 82 | testing 83 | 84 | -------------------------------------------------------------------------------- /work/deprecated/04_version.md: -------------------------------------------------------------------------------- 1 | # Version Class 2 | 3 | *DEPRECATED* Realms now uses the Versus gems Version::Number class. 4 | 5 | Realms has a version class which it uses to compare versions 6 | via various constraints. 7 | 8 | First, a version object will return the string representation 9 | via #to_s. 10 | 11 | v = Realms::Version.new('1.2.3') 12 | '1.2.3'.assert == v.to_s 13 | 14 | It will also do this for #to_str. 15 | 16 | v = Realm::Version.new('1.2.3') 17 | '1.2.3'.assert == v.to_str 18 | 19 | The actual segments of a version are stored in an array. 20 | We can access those via #[]. 21 | 22 | v = Realms::Version.new('1.2.3') 23 | 1.assert == v[0] 24 | 2.assert == v[1] 25 | 3.assert == v[2] 26 | 27 | In addition certain segmetns have special names. 28 | The first is accessible via #major. 29 | 30 | v = Realms::Version.new('1.2.3') 31 | v.major.assert == 1 32 | 33 | The second is accessible via #minor. 34 | 35 | v = Realms::Version.new('1.2.3') 36 | v.minor.assert == 2 37 | 38 | The third is accessible via #patch. 39 | 40 | v = Realms::Version.new('1.2.3') 41 | v.patch.assert == 3 42 | 43 | And lastly anything beyond the patch number is accessible 44 | via #build. 45 | 46 | v = Realms::Version.new('1.2.3.pre.1') 47 | v.build.assert == 'pre.1' 48 | 49 | Two version can be compared with the #<=> method, which 50 | importantly also makes lists of versions sortable. 51 | 52 | v1 = Realms::Version.new('1.2.3') 53 | v2 = Realms::Version.new('1.2.4') 54 | (v2 <=> v1).assert == 1 55 | 56 | While #=~ provides *pessimistic* constraint comparison. 57 | 58 | v1 = Realms::Version.new('1.2.4') 59 | v2 = Realms::Version.new('1.2') 60 | assert(v1 =~ v2) 61 | 62 | The Version class also provides some useful singleton methods 63 | such as #parse_constraint. This method deciphers a comparision string. 64 | 65 | a = Realms::Version.parse_constraint("~> 1.0.0") 66 | e = ["=~", Realms::Version['1.0.0']] 67 | a.assert == e 68 | 69 | Equality can be written with `==` or `=`. 70 | 71 | a = Realms::Version.parse_constraint("= 0.9.0") 72 | e = ["==", Realms::Version['0.9.0']] 73 | a.assert == e 74 | 75 | Without an operator equality is implied. 76 | 77 | a = Realms::Version.parse_constraint("1.1") 78 | e = [ "==", Realms::Version['1.1'] ] 79 | a.assert == e 80 | 81 | This is usefuly for parsing requirement configurations. Using it, the Version 82 | class can build contraint comparison procedures. 83 | 84 | compare = Realms::Version.constraint_lambda("=1.0") 85 | compare.call('1.0').assert == true 86 | compare.call('0.9').assert == false 87 | 88 | Greater than 89 | 90 | compare = Realms::Version.constraint_lambda(">1.0") 91 | compare.call('1.1').assert == true 92 | compare.call('0.9').assert == false 93 | 94 | Less than 95 | 96 | compare = Realms::Version.constraint_lambda("<1.0") 97 | compare.call('1.1').assert == false 98 | compare.call('0.9').assert == true 99 | 100 | -------------------------------------------------------------------------------- /HISTORY.md: -------------------------------------------------------------------------------- 1 | # RELEASE HISTORY 2 | 3 | ## 2.0.0 / 2012-01-08 4 | 5 | Ruby Rolls and spun-off the underlying Library and Library::Ledger 6 | classes as a separate project. This serves two important purposes. 7 | First, Library reserves it's namespace in gem space. And second, 8 | the separation helps focus the purpose of each project. Where Library 9 | provides the object basis of working with libraries. Whereas Rolls 10 | provides the higher level system for managing library sets ("gem sets"). 11 | 12 | This realease also renames the package name from `roll` to `rolls`. 13 | It's rolls off the tounge better ;) 14 | 15 | Changes: 16 | 17 | * Spin-off Library and Library::Ledger classes. 18 | * Rename gem from `roll` to `rolls`. 19 | 20 | 21 | ## 1.2.0 / 2010-06-15 22 | 23 | This release gets roll command working and improves 24 | the reliability of the system as a whole, including making 25 | metadata lookup more consistant (hint: you want a PACKAGE file). 26 | It is even partially compatible with Gem stores now (exceptions 27 | being loadpaths other than lib/ and the use of autoload). 28 | 29 | Changes: 30 | 31 | * Reworked metadata system (in line with evolving POM). 32 | * Improved search heuristics (usually much faster now). 33 | 34 | 35 | ## 1.1.0 / 2010-03-01 36 | 37 | This release fix a few bugs and makes a few adjustments, 38 | but mostly cleans up code behind the scenes. 39 | 40 | Changes: 41 | 42 | * Fix incorrect multi-match and absolute path lookup 43 | * Support for Rubinius RUBY_IGNORE_CALLERS 44 | 45 | 46 | ## 1.0.0 / 2010-02-11 47 | 48 | This release overhauls the underlying system, which is now very 49 | fast. It supports customizable library environments, and banashes 50 | all traces of package management to the domain of other tools. 51 | 52 | Changes: 53 | 54 | * Overhauled the entire underlying system. 55 | * Start-up time is blazing fast, loading's is pretty good too. 56 | * Metadata uses POM standard, although not dependent (yet?). 57 | * Environments provide selectable sets of available libraries. 58 | 59 | 60 | ## 0.9.4 / 2008-06-05 61 | 62 | The .roll file is no longer used. Instead Rolls is now 63 | using a VERSION file combined with meta/ entries for 64 | loadpath and dependencies (ie. requires). 65 | 66 | Changes: 67 | 68 | * VERSION and meta/ entries are used instead of '.roll'. 69 | 70 | 71 | ## 0.9.3 / 2007-02-10 72 | 73 | Changes: 74 | 75 | * Change roll file format and name. It is now .roll. 76 | * Relative require with #use should now work. 77 | 78 | 79 | ## 0.9.2 / 2007-12-17 80 | 81 | Changes: 82 | 83 | * Changed roll file format from ROLLRC to {name}.roll. 84 | * The name change enabled an order of magnitude increase in startup time! 85 | 86 | 87 | ## 0.9.1 / 2007-11-27 88 | 89 | Changes: 90 | 91 | * Standard metadate file is now ROLLRC. 92 | * Improved parsing of ROLLRC file, #release is now a Time object. 93 | 94 | 95 | ## 0.9.0 / 2007-11-12 96 | 97 | Changes: 98 | 99 | * Removed Roll namespace. Library and VersionNumber are now in toplevel. 100 | * Fixed spelling of 'version' in Library#<=>. 101 | * Kernel#require and load now route to Library meta-methods. 102 | * @roll and related methods have been renamed to @package. 103 | * Reduced scan glob to single pattern. Scanning is over 3x faster! 104 | 105 | -------------------------------------------------------------------------------- /lib/realms/shell/list.rb: -------------------------------------------------------------------------------- 1 | module Realms 2 | class Library 3 | module Shell 4 | register :list 5 | 6 | # 7 | # List available libraries. 8 | # 9 | def list 10 | opts = {} 11 | 12 | op.banner = "Usage: realm list" 13 | op.separator "List available libraries." 14 | 15 | op.on('--verbose', '-v', "Show detailed listing.") do 16 | opts[:verbose] = true 17 | end 18 | 19 | parse 20 | 21 | if $LOAD_MANAGER.keys.empty? 22 | $stderr.puts "No libraries found." 23 | else 24 | if opts[:verbose] 25 | list_details 26 | else 27 | list_names 28 | end 29 | end 30 | end 31 | 32 | private 33 | 34 | # 35 | # List names of available libraries. 36 | # 37 | # @todo Currently this list names in four columns. In future it would be nice to 38 | # set the number of columns to max screen width. This can be done with ansi gem 39 | # but it would be better if there was a built-in way to do this in Ruby. 40 | # 41 | # @return nothing 42 | # 43 | def list_names 44 | names = $LOAD_MANAGER.keys.sort 45 | if names.empty? 46 | puts "No libraries found." 47 | else 48 | max = names.map{ |name| name.size }.max + 4 49 | rows = ((names.size + 4) / 4).to_i 50 | cols = [] 51 | names.each_with_index do |name, i| 52 | c = i % rows 53 | cols[c] ||= [] 54 | cols[c] << name 55 | end 56 | out = "" 57 | cols.each do |row| 58 | row.each do |name| 59 | out << ("%-#{max}s" % [name]) 60 | end 61 | out << "\n" 62 | end 63 | puts out 64 | end 65 | end 66 | 67 | # 68 | # List libraries in detail with name, version, release date and location. 69 | # 70 | # @todo Add lib paths. 71 | # 72 | # @return nothing 73 | # 74 | def list_details 75 | max = ::Hash.new{|h,k| h[k]=0 } 76 | list = [] 77 | 78 | names = $LOAD_MANAGER.names.sort 79 | 80 | names.each do |name| 81 | next if name == 'ruby' 82 | 83 | libs = $LOAD_MANAGER[name] 84 | libs = Array(libs).sort 85 | 86 | libs.each do |lib| 87 | data = lib.to_h.rekey 88 | #data[:loadpath] = data[:loadpath].join(' ') 89 | data[:date] = Utils.iso_date(data[:date]) 90 | 91 | data.each do |k,v| 92 | max[k] = v.to_s.size if v.to_s.size > max[k] 93 | end 94 | 95 | list << data 96 | end 97 | end 98 | 99 | max = max.values_at(:name, :version, :date, :location) #, :loadpath) 100 | 101 | list = list.map do |data| 102 | data.values_at(:name, :version, :date, :location) #, :loadpath) 103 | end 104 | 105 | mask = max.map{ |size| "%-#{size}s" }.join(' ') + "\n" 106 | 107 | out = '' 108 | list.each do |name, vers, date, locs, lpath| 109 | str = mask % [name, vers, date, locs, lpath] 110 | out << str 111 | end 112 | 113 | puts out 114 | end 115 | 116 | end 117 | end 118 | end 119 | -------------------------------------------------------------------------------- /lib/realms/shell.rb: -------------------------------------------------------------------------------- 1 | module Realms 2 | class Library 3 | 4 | # The Shell module encapsulates shell commands. 5 | # 6 | # Each command is simply a method that has been registerd via 7 | # the `register` dsl method. 8 | # 9 | module Shell 10 | extend self 11 | 12 | # 13 | # Initialize and execute command. This method looks for the first 14 | # non-option (i.e. not starting with a `-`) entry in +argv+ array. 15 | # This is used as the command name, which is capitalized to match 16 | # the name and find the corresponding command class. 17 | # 18 | def self.main(*argv) 19 | require 'optparse' 20 | 21 | #cmd = argv.shift 22 | idx = argv.index{ |e| e !~ /^\-/ } 23 | cmd = idx ? argv.delete_at(idx) : 'help' 24 | 25 | #begin 26 | # require "realms/shell/#{cmd}" 27 | #rescue LoadError 28 | # cmd = 'help' 29 | # require "realms/shell/#{cmd}" 30 | #end 31 | 32 | @arguments = argv 33 | 34 | raise "unknown command" unless commands.include?(cmd) 35 | 36 | __send__(cmd) 37 | end 38 | 39 | private 40 | 41 | # 42 | # 43 | # 44 | def self.register(command) 45 | commands << command.to_s 46 | end 47 | 48 | # 49 | # Available commands. 50 | # 51 | def commands 52 | @@commands ||= [] 53 | end 54 | 55 | # 56 | # Instance of OptionParser. 57 | # 58 | def options 59 | @options ||= ( 60 | OptionParser.new do |opt| 61 | opt.on_tail("--warn", "-w", "Show warnings.") do 62 | $VERBOSE = true 63 | end 64 | 65 | opt.on_tail("--debug", "Run in debugging mode.") do 66 | $DEBUG = true 67 | end 68 | 69 | opt.on_tail("--help", "-h", "Show help for command.") do 70 | puts op 71 | exit 72 | end 73 | end 74 | ) 75 | end 76 | 77 | # @deprecated 78 | alias :op :options 79 | 80 | # 81 | # Command line arguments. 82 | # 83 | def arguments 84 | @arguments 85 | end 86 | 87 | # @deprecated 88 | alias :argv :arguments 89 | 90 | # 91 | # Parse the command line. 92 | # 93 | def parse(argv=nil) 94 | @arguments = argv if argv 95 | 96 | #op.on_tail("--warn", "-w", "Show warnings.") do 97 | # $VERBOSE = true 98 | #end 99 | 100 | #op.on_tail("--debug", "Run in debugging mode.") do 101 | # $DEBUG = true 102 | #end 103 | 104 | #op.on_tail("--help", "-h", "Display this help message.") do 105 | # puts op 106 | # exit 107 | #end 108 | 109 | op.parse!(@arguments) 110 | end 111 | 112 | end 113 | 114 | end 115 | 116 | end 117 | 118 | require 'realms/shell/add' 119 | require 'realms/shell/dump' 120 | require 'realms/shell/gem' 121 | require 'realms/shell/help' 122 | require 'realms/shell/isolate' 123 | require 'realms/shell/list' 124 | require 'realms/shell/lock' 125 | require 'realms/shell/path' 126 | require 'realms/shell/remove' 127 | require 'realms/shell/show' 128 | require 'realms/shell/unlock' 129 | require 'realms/shell/verify' 130 | require 'realms/shell/where' 131 | 132 | # Copyright (c)2013 Rubyworks (BSD-2-Clause License) 133 | -------------------------------------------------------------------------------- /lib/realms/kernel.rb: -------------------------------------------------------------------------------- 1 | # TODO: Con't use module_function, but define the class methods and have the instance methods call those. 2 | 3 | #require 'library' # this must be loaded in first 4 | 5 | $RUBY_IGNORE_CALLERS ||= [] 6 | $RUBY_IGNORE_CALLERS << /#{__FILE__}/ # TODO: should this be more general, e.g. File.dirname(__FILE__) ? 7 | 8 | module ::Kernel 9 | 10 | # 11 | # In which library is the current file participating? 12 | # 13 | # @return [Library] The library currently loading features. 14 | # 15 | def __LIBRARY__ 16 | $LOAD_STACK.last 17 | end 18 | 19 | # 20 | # Activate a library, same as `Library.instance` but will raise and error 21 | # if the library is not found. This can also take a block to yield on the 22 | # library. 23 | # 24 | # @param name [String] 25 | # The library's name. 26 | # 27 | # @param constraint [String] 28 | # A valid version constraint. 29 | # 30 | # @return [Library] The Library instance. 31 | # 32 | def library(name, constraint=nil, &block) #:yield: 33 | $LOAD_MANAGER.activate(name, constraint, &block) 34 | end 35 | 36 | module_function :library 37 | 38 | 39 | unless method_defined?(:require_without_realms) 40 | 41 | class << self 42 | alias require_without_realms require 43 | alias load_without_realms load 44 | end 45 | 46 | alias require_without_realms require 47 | alias load_without_realms load 48 | 49 | # 50 | # Load feature. 51 | # 52 | # @param pathname [String] 53 | # The pathname of the feature to load. 54 | # 55 | # @param options [Hash] 56 | # Load options can be :wrap and :search. 57 | # 58 | # @return [true, false] if feature was successfully loaded 59 | # 60 | def load(pathname, options={}) 61 | $LOAD_MANAGER.load(pathname, options) 62 | end 63 | 64 | module_function :load 65 | 66 | # 67 | # Require feature. 68 | # 69 | # @param pathname [String] 70 | # The pathname of the feature to require. 71 | # 72 | # @param options [Hash] 73 | # Load options can be `:wrap`, `:load` and `:search`. 74 | # 75 | # @return [true,false] if feature was newly required 76 | # 77 | def require(pathname, options={}) 78 | $LOAD_MANAGER.require(pathname, options) 79 | end 80 | 81 | module_function :require 82 | 83 | # 84 | # Require relative to current library. 85 | # @param pathname [String] 86 | # The pathname of the feature to acquire. 87 | # 88 | # @param options [Hash] 89 | # Acquire options. 90 | # 91 | # @return [true, false] 92 | # Was the feature newly required. 93 | # 94 | def require_local(pathname, options={}) 95 | $LOAD_MANAGER.require_relative(pathname, options) 96 | end 97 | 98 | module_function :require_local 99 | 100 | # TODO: Do we need to do anything with require_relative ? 101 | 102 | 103 | #module_function :acquire 104 | 105 | end 106 | 107 | end 108 | 109 | class Module 110 | private 111 | 112 | # 113 | # Acquire feature. 114 | # 115 | # @param pathname [String] 116 | # The pathname of the feature to acquire. 117 | # 118 | # @param options [Hash] 119 | # Aquire options (if any). 120 | # 121 | # @return [true,false] 122 | # Was the feature newly acquired or not. 123 | # 124 | def acquire(pathname, options={}) #, &block) 125 | $LOAD_MANAGER.acquire(self, pathname, options) #, &block) 126 | end 127 | 128 | end 129 | 130 | -------------------------------------------------------------------------------- /work/consider/version.rb: -------------------------------------------------------------------------------- 1 | # = VersionNumber 2 | # 3 | # VersionNumber is a simplified form of a Tuple class 4 | # desgined specifically for dealing with version numbers. 5 | # 6 | # == Authors 7 | # 8 | # * Thomas Sawyer (7rans) 9 | # 10 | # == Todo 11 | # 12 | # * Maybe add Kernel method #version ? 13 | # 14 | # * If Tuple were standard part of Ruby this probably would 15 | # not be needed or at least might be simple sublcass instead. 16 | # 17 | # == Copyright 18 | # 19 | # Copyright (c) 2005 Thomas Sawyer 20 | # 21 | # Ruby License 22 | # 23 | # This module is free software. You may use, modify, and/or redistribute this 24 | # software under the same terms as Ruby. 25 | # 26 | # This program is distributed in the hope that it will be useful, but WITHOUT 27 | # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 28 | # FOR A PARTICULAR PURPOSE. 29 | 30 | # = VersionNumber 31 | # 32 | # VersionNumber is a simplified form of a Tuple class 33 | # desgined specifically for dealing with version numbers. 34 | # 35 | class VersionNumber #< Tuple 36 | 37 | #include Enumerable 38 | include Comparable 39 | 40 | def initialize( *args ) 41 | args = args.join('.').split(/\W+/) 42 | @self = args.collect { |i| i.to_i } 43 | end 44 | 45 | def to_s ; @self.join('.') ; end 46 | 47 | # This is here only becuase File.join calls it instead of to_s. 48 | 49 | def to_str ; @self.join('.') ; end 50 | 51 | def inspect 52 | @self.to_s 53 | end 54 | 55 | def [](i) 56 | @self.fetch(i,0) 57 | end 58 | 59 | # "Spaceship" comparsion operator. 60 | 61 | def <=>( other ) 62 | #other = other.to_t 63 | [@self.size, other.size].max.times do |i| 64 | c = @self[i] <=> other[i] 65 | return c if c != 0 66 | end 67 | 0 68 | end 69 | 70 | # For pessimistic constraint (like '~>' in gems) 71 | 72 | def =~( other ) 73 | #other = other.to_t 74 | upver = other.dup 75 | upver[0] += 1 76 | @self >= other and @self < upver 77 | end 78 | 79 | # Major is the first number in the version series. 80 | 81 | def major ; @self[0] ; end 82 | 83 | # Minor is the second number in the version series. 84 | 85 | def minor ; @self[1] || 0 ; end 86 | 87 | # Teeny is third number in the version series. 88 | 89 | def teeny ; @self[2] || 0 ; end 90 | 91 | # 92 | def bump(which=:teeny) 93 | case which 94 | when :major 95 | self.class.new(major+1) 96 | when :minor 97 | self.class.new(major, minor+1) 98 | when :teeny 99 | self.class.new(major, minor, teeny+1) 100 | else 101 | # ??? 102 | end 103 | end 104 | 105 | # Delegate to the array. 106 | 107 | def method_missing( sym, *args, &blk ) 108 | @self.send(sym, *args, &blk ) rescue super 109 | end 110 | 111 | # Parses a string constraint returning the operation as a lambda. 112 | 113 | def self.constraint_lambda( constraint ) 114 | op, val = *parse_constraint( constraint ) 115 | lambda { |t| t.send(op, val) } 116 | end 117 | 118 | def self.parse_constraint( constraint ) 119 | constraint = constraint.strip 120 | re = %r{^(=~|~>|<=|>=|==|=|<|>)?\s*(\d+(:?[-.]\d+)*)$} 121 | if md = re.match( constraint ) 122 | if op = md[1] 123 | op = '=~' if op == '~>' 124 | op = '==' if op == '=' 125 | val = new( *md[2].split(/\W+/) ) 126 | else 127 | op = '==' 128 | val = new( *constraint.split(/\W+/) ) 129 | end 130 | else 131 | raise ArgumentError, "invalid constraint" 132 | end 133 | return op, val 134 | end 135 | 136 | end 137 | -------------------------------------------------------------------------------- /work/deprecated/once-again-into-the-breach/library.rb: -------------------------------------------------------------------------------- 1 | require 'library' 2 | require 'library/rubylib' 3 | 4 | # Rolls adds some convenience methods to Library's metaclass 5 | # for interfacing with the current ledger. This provides a 6 | # nicer API for a some uses, e.g. `Library.list`. 7 | # 8 | class Library 9 | 10 | # 11 | # Access to the library ledger (`$LEDGER`). 12 | # 13 | # @return [Array] The `$LEDGER` array. 14 | # 15 | def self.ledger 16 | $LEDGER 17 | end 18 | 19 | # 20 | # Library names from ledger. 21 | # 22 | # @return [Array] The keys from `$LEDGER` array. 23 | # 24 | def self.names 25 | $LEDGER.keys 26 | end 27 | 28 | # 29 | # Library names from ledger. 30 | # 31 | # @return [Array] The keys from `$LEDGER` array. 32 | # 33 | def self.list 34 | $LEDGER.keys 35 | end 36 | 37 | # 38 | # Require a feature from the library. 39 | # 40 | # @param [String] pathname 41 | # The pathname of feature relative to library's loadpath. 42 | # 43 | # @param [Hash] options 44 | # 45 | # @return [true,false] If feature was newly required or successfully loaded. 46 | # 47 | def self.require(pathname, options={}) 48 | Ledger.require(pathname, options) 49 | end 50 | 51 | # 52 | # Load file path. This is just like #require except that previously 53 | # loaded files will be reloaded and standard extensions will not be 54 | # automatically appended. 55 | # 56 | # @param pathname [String] 57 | # pathname of feature relative to library's loadpath 58 | # 59 | # @return [true,false] if feature was successfully loaded 60 | # 61 | def self.load(pathname, options={}) 62 | Ledger.load(pathname, options) 63 | end 64 | 65 | # 66 | # Roll-style loading. First it looks for a specific library via `:`. 67 | # If `:` is not present it then tries the current loading library. 68 | # Failing that it fallsback to Ruby itself. 69 | # 70 | # require('facets:string/margin') 71 | # 72 | # To "load" the library, rather than "require" it, set the +:load+ 73 | # option to true. 74 | # 75 | # require('facets:string/margin', :load=>true) 76 | # 77 | # @param pathname [String] 78 | # pathname of feature relative to library's loadpath 79 | # 80 | # @return [true, false] if feature was newly required 81 | # 82 | def self.acquire(pathname, options={}) 83 | Ledger.acquire(pathname, options) 84 | end 85 | 86 | # 87 | # A shortcut for #instance. 88 | # 89 | # @return [Library,NilClass] The activated Library instance, or `nil` if not found. 90 | # 91 | def self.[](name, constraint=nil) 92 | $LEDGER.activate(name, constraint) if $LEDGER.key?(name) 93 | end 94 | 95 | # 96 | # Get an instance of a library by name, or name and version. 97 | # Libraries are singleton, so once loaded the same object is 98 | # always returned. 99 | # 100 | # @todo This method might be deprecated. 101 | # 102 | # @return [Library,NilClass] The activated Library instance, or `nil` if not found. 103 | # 104 | def self.instance(name, constraint=nil) 105 | $LEDGER.activate(name, constraint) if $LEDGER.key?(name) 106 | end 107 | 108 | # 109 | # Activate a library. Same as #instance but will raise and error if the 110 | # library is not found. This can also take a block to yield on the library. 111 | # 112 | # @param [String] name 113 | # Name of library. 114 | # 115 | # @param [String] constraint 116 | # Valid version constraint. 117 | # 118 | # @raise [LoadError] 119 | # If library not found. 120 | # 121 | # @return [Library] 122 | # The activated Library object. 123 | # 124 | def self.activate(name, constraint=nil) #:yield: 125 | library = $LEDGER.activate(name, constraint) 126 | yield(library) if block_given? 127 | library 128 | end 129 | 130 | # 131 | # Like `#new`, but adds library to library ledger. 132 | # 133 | # @todo Better name for this method? 134 | # 135 | # @return [Library] The new library. 136 | # 137 | def self.add(location) 138 | $LEDGER.add_location(location) 139 | 140 | #library = new(location) 141 | #$LEDGER.add_library(library) 142 | #library 143 | end 144 | 145 | end 146 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [Homepage](http://rubyworks.github.com/realms) / 2 | [Documentation](http://wiki.github.com/rubyworks/realms) / 3 | [Report Issue](http://github.com/rubyworks/realms/issues) / 4 | [Source Code](http://github.com/rubyworks/realms) 5 | ( [![Build Status](https://travis-ci.org/rubyworks/realms.png)](https://travis-ci.org/rubyworks/realms) ) 6 | 7 | 8 | ``` 9 | <| 10 | A 11 | /.\ 12 | <| [""M# 13 | A | # Realms 14 | /.\ [""M# 15 | [""M# | # U"U#U 16 | | # | # \ .:/ 17 | | # | #___| # 18 | | "--' .-" 19 | |"-"-"-"-"-#-#-## 20 | | # ## ###### 21 | \ .::::'/ 22 | \ ::::'/ 23 | :8a| # # ## 24 | ::88a ### 25 | ::::888a 8a ##::. 26 | ::::::888a88a[]:::: 27 | :::::::::SUNDOGa8a::::. .. 28 | :::::8::::888:Y8888:::::::::... 29 | ::':::88::::888::Y88a______________________________________________________ 30 | :: ::::88a::::88a:Y88a __---__-- __ 31 | ' .: ::Y88a:::::8a:Y88a __----_-- -------_-__ 32 | :' ::::8P::::::::::88aa. _ _- -- --_ --- __ --- __-- 33 | .:: :::::::::::::::::::Y88as88a...s88aa. 34 | ``` 35 | 36 | # REALMS 37 | 38 | REALMS is a library management system for Ruby. In fact, the name is 39 | an anacronym which stands for *Ruby Enhanced Library Management System*. 40 | Okay, it sounds neat, but what does Realms actually do? 41 | 42 | Realms core functionality is to take a list of file system locations, sift 43 | through them to find Ruby projects and make them available via Ruby's `require` 44 | and `load` methods. It does this in such a way that is *customizable* and *fast*. 45 | 46 | Along with some supporting functionality, this bestows a variety of useful 47 | possibilities to Ruby developers: 48 | 49 | * Work with libraries in an object-oriented manner. 50 | * Develop interdependent projects in real time without installs or vendoring. 51 | * Create isolated library environments based on project requirements. 52 | * Nullify the need for per-project gemsets and multiple copies of the same gem. 53 | * Access libraries anywhere; there is no special "home" path they *must* reside. 54 | * Serve gem installed libraries faster than RubyGems itself. 55 | 56 | 57 | ## Limitations 58 | 59 | Ruby has a "bug" which prevents `#autoload` from using custom `#require` 60 | methods. So autoload paths cannot make use of Realms. However, Realms 61 | has a fallback system which allows autoload to work so long as the path 62 | lies within the current library. It is only a show-stopper when autoload 63 | is used to load scripts from outside dependencies. This is not as significant 64 | as it might seem for two reasons. 1) Most uses of autoload are interal; 65 | and 2) autoload is in the process of being deprecated as of Ruby 2.0. So 66 | it is best to discontinue it's use anyway. 67 | 68 | 69 | ## Documentation 70 | 71 | Because there is fair amount of information to cover this section will 72 | refer you to the project wiki pages for instruction. Most users can follow 73 | the [Quick Start Guide](https://github.com/rubyworks/realms/wiki/Quick-Start-Guide). 74 | For more detailed instruction on how setup Realms and get the most out select 75 | from the following links: 76 | 77 | * [Installation](https://github.com/rubyworks/realms/wiki/Installation) 78 | * [System Setup](https://github.com/rubyworks/realms/wiki/System-Setup) 79 | * [Project Conformity](https://github.com/rubyworks/library/wiki/Project-Conformity) 80 | * [Run Modes](https://github.com/rubyworks/realms/wiki/Run-Modes) 81 | * [Dependency Isolation](https://github.com/rubyworks/realms/wiki/Dependency-Isolation) 82 | * [Configuring Locations](https://github.com/realms/library/wiki/Configuring-Locations) 83 | * [API Usage](https://github.com/rubyworks/realms/wiki/API-Usage) 84 | 85 | 86 | ## FAQ 87 | 88 | Realms was originally called Roll and was RubyForge project #1004. 89 | She's actually been around a while! :) 90 | 91 | 92 | ## Copyrights 93 | 94 | Realms is copyrighted open source software. 95 | 96 | Copyright (c) 2006 Rubyworks 97 | 98 | It can be modified and redistributable in accordance with the **BSD-2-Clause** license. 99 | 100 | See the LICENSE.txt file details. 101 | -------------------------------------------------------------------------------- /work/reference/configuration.rb: -------------------------------------------------------------------------------- 1 | module Roll 2 | 3 | # 4 | # @return [Configuration] roll configuration object 5 | def config 6 | @config ||= Configuration.new 7 | end 8 | 9 | # 10 | class Configuration 11 | 12 | # Get a setting's value. A setting is read either from the user's 13 | # home settings files or from environment variables. 14 | def [](name) 15 | name = name.to_s.downcase 16 | file = File.join(home_settings_directory, name) 17 | if File.file?(file) 18 | val = File.read(file).strip 19 | val = nil if val.empty? 20 | else 21 | var = "roll_#{name}" 22 | val = ENV[var] || ENV[var.upcase] 23 | end 24 | val 25 | end 26 | 27 | # 28 | def roll_file 29 | self['file'] 30 | end 31 | 32 | # 33 | def roll_name 34 | self['name'] 35 | end 36 | 37 | # Default environment name, looks for `default_name` setting, 38 | # otherwise uses DEFAULT_NAME constant. If no current name is set, 39 | # this value will be used. 40 | # 41 | # @return [String] default environment name 42 | def default_name 43 | @default_name ||= self['default_name'] || DEFAULT_NAME 44 | end 45 | 46 | # Default environment file. 47 | # 48 | # @return [String, nil] default environment file name 49 | def default_file 50 | @default_file ||= self['default_file'] 51 | end 52 | 53 | # Home configuration directory. 54 | def home_directory 55 | File.join(XDG.config_home, 'roll') 56 | end 57 | 58 | # Cache directory. 59 | def cache_directory 60 | File.join(XDG.cache_home, 'roll') 61 | end 62 | 63 | ## Project local Roll's config directory. This will be either `.roll/` 64 | ## or `.config/roll/`. 65 | #def local_directory 66 | # @local_directory ||= ( 67 | # Dir['{.roll,.config/roll'].first || '.roll' 68 | # ) 69 | #end 70 | 71 | # 72 | def home_settings_directory 73 | @home_settings_directory ||= File.join(home_directory, 'settings') 74 | end 75 | 76 | # Environment home directory. 77 | def home_environment_directory 78 | @home_environment_directory ||= home_directory 79 | end 80 | 81 | ## Project local environments directory. 82 | #def local_environment_directory 83 | # @local_environment_directory ||= ( 84 | # File.join(local_directory) #, 'environments') # TODO: keep environments? 85 | # ) 86 | #end 87 | 88 | # Returns the name of the current environment. 89 | ##def current_environment 90 | # ENV['roll_environment'] || ENV['RUBYENV'] || default_environment 91 | #end 92 | 93 | # List of local environments. 94 | #def local_environments 95 | # Dir[File.join(local_environment_directory, '*')].map do |file| 96 | # File.basename(file) 97 | # end 98 | #end 99 | 100 | # List of home environment names. 101 | def home_environments 102 | Dir[File.join(home_environment_directory, '*')].map do |file| 103 | File.file?(file) ? File.basename(file) : nil 104 | end.compact 105 | end 106 | 107 | # 108 | def system_environments 109 | environments - home_environments 110 | end 111 | 112 | # List of all available user environments. 113 | def environments 114 | list = XDG.search_config('roll/*').map do |file| 115 | File.file?(file) ? File.basename(file) : nil 116 | end.compact 117 | end 118 | 119 | #-- 120 | # List of all available environments. 121 | # TODO: Add system wide environments. 122 | #def environments 123 | # #local_environments + home_environments # + system_environments 124 | # home_environments # + system_environments 125 | # #Dir[File.join('{'+DIRS.join(',')+'}', '*')].map do |file| 126 | # # File.basename(file) 127 | # #end 128 | #end 129 | #++ 130 | 131 | # TODO: Add system wide locations. 132 | def find_environment_file(name) 133 | dirs = [local_environment_directory, home_environment_directory] 134 | dirs.find do |dir| 135 | file = File.join(dir, name) 136 | return file if File.file?(file) 137 | return file+'.roll' if File.file?(file+'.roll') 138 | end 139 | return nil 140 | end 141 | 142 | # Default gem home directory path. 143 | def gem_home 144 | if defined? RUBY_FRAMEWORK_VERSION then 145 | File.join File.dirname(CONFIG["sitedir"]), 'Gems', CONFIG["ruby_version"] 146 | elsif CONFIG["rubylibprefix"] then 147 | File.join(CONFIG["rubylibprefix"], 'gems', CONFIG["ruby_version"]) 148 | else 149 | File.join(CONFIG["libdir"], ruby_engine, 'gems', CONFIG["ruby_version"]) 150 | end 151 | end 152 | 153 | # A wrapper around RUBY_ENGINE const that may not be defined. 154 | def ruby_engine 155 | if defined? RUBY_ENGINE then 156 | RUBY_ENGINE 157 | else 158 | 'ruby' 159 | end 160 | end 161 | 162 | end 163 | 164 | end 165 | -------------------------------------------------------------------------------- /work/deprecated/xdg.rb: -------------------------------------------------------------------------------- 1 | #require 'library/core_ext/rbconfig' 2 | 3 | module Roll 4 | 5 | # XDG utility functions. 6 | # 7 | # @see http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html 8 | module XDG 9 | extend self 10 | 11 | # User's home directory. 12 | def home 13 | File.expand_path('~') # ENV['HOME'] 14 | end 15 | 16 | # Freedesktop.org standard location for configuration files. 17 | def config_home 18 | File.expand_path(ENV['XDG_CONFIG_HOME'] || File.join(home, '.config')) 19 | end 20 | 21 | # Location of user's personal config directory. 22 | def data_home 23 | File.expand_path(ENV['XDG_DATA_HOME'] || File.join(home, '.local', 'share')) 24 | end 25 | 26 | # Freedesktop.org standard location for temporary cache. 27 | def cache_home 28 | File.expand_path(ENV['XDG_CACHE_HOME'] || File.join(home, '.cache')) 29 | end 30 | 31 | # List of system config directories. 32 | def config_dirs 33 | dirs = ENV['XDG_CONFIG_DIRS'].to_s.split(/[:;]/) 34 | if dirs.empty? 35 | dirs = [File.join(::RbConfig::CONFIG['sysconfdir'], 'xdg')] 36 | end 37 | dirs.collect{ |d| File.expand_path(d) } 38 | end 39 | 40 | # List of system data directories. 41 | def data_dirs 42 | dirs = ENV['XDG_DATA_DIRS'].to_s.split(/[:;]/) 43 | if dirs.empty? 44 | dirs = [::RbConfig::CONFIG['datarootdir']] # what about local? 45 | end 46 | dirs.collect{ |d| File.expand_path(d) } 47 | end 48 | 49 | # Lookup configuration file. 50 | def search_config(*glob) 51 | flag = 0 52 | flag = (flag | glob.pop) while Fixnum === glob.last 53 | find = [] 54 | [config_home, *config_dirs].each do |dir| 55 | path = File.join(dir, *glob) 56 | if block_given? 57 | find.concat(Dir.glob(path, flag).select(&block)) 58 | else 59 | find.concat(Dir.glob(path, flag)) 60 | end 61 | end 62 | find 63 | end 64 | 65 | # Lookup data file. 66 | # 67 | # @param glob [Array] look-up globs 68 | # 69 | def search_data(*glob) 70 | flag = 0 71 | flag = (flag | glob.pop) while Fixnum === glob.last 72 | find = [] 73 | [data_home, *data_dirs].each do |dir| 74 | path = File.join(dir, *glob) 75 | if block_given? 76 | find.concat(Dir.glob(path, flag).select(&block)) 77 | else 78 | find.concat(Dir.glob(path, flag)) 79 | end 80 | end 81 | find 82 | end 83 | 84 | end 85 | 86 | end 87 | 88 | 89 | =begin 90 | module XDG 91 | extend self 92 | 93 | # User's home directory. 94 | def home 95 | File.expand_path('~') # ENV['HOME'] 96 | end 97 | 98 | # Freedesktop.org standard location for configuration files. 99 | def config_home 100 | File.expand_path(ENV['XDG_CONFIG_HOME'] || File.join(home, '.config')) 101 | end 102 | 103 | # Location of user's personal config directory. 104 | def data_home 105 | File.expand_path(ENV['XDG_DATA_HOME'] || File.join(home, '.local', 'share')) 106 | end 107 | 108 | # Freedesktop.org standard location for temporary cache. 109 | def cache_home 110 | File.expand_path(ENV['XDG_CACHE_HOME'] || File.join(home, '.cache')) 111 | end 112 | 113 | # List of system config directories. 114 | def config_dirs 115 | dirs = ENV['XDG_CONFIG_DIRS'].to_s.split(/[:;]/) 116 | if dirs.empty? 117 | dirs = [File.join(::RbConfig::CONFIG['sysconfdir'], 'xdg')] 118 | end 119 | dirs.collect{ |d| File.expand_path(d) } 120 | end 121 | 122 | # List of system data directories. 123 | def data_dirs 124 | dirs = ENV['XDG_DATA_DIRS'].to_s.split(/[:;]/) 125 | if dirs.empty? 126 | dirs = [::RbConfig::CONFIG['datarootdir']] # what about local? 127 | end 128 | dirs.collect{ |d| File.expand_path(d) } 129 | end 130 | 131 | # Lookup configuration file. 132 | def search_config(*glob) 133 | flag = 0 134 | flag = (flag | glob.pop) while Fixnum === glob.last 135 | find = [] 136 | [config_home, *config_dirs].each do |dir| 137 | path = File.join(dir, *glob) 138 | if block_given? 139 | find.concat(Dir.glob(path, flag).select(&block)) 140 | else 141 | find.concat(Dir.glob(path, flag)) 142 | end 143 | end 144 | find 145 | end 146 | 147 | # Lookup data file. 148 | def search_data(*glob) 149 | flag = 0 150 | flag = (flag | glob.pop) while Fixnum === glob.last 151 | find = [] 152 | [data_home, *data_dirs].each do |dir| 153 | path = File.join(dir, *glob) 154 | if block_given? 155 | find.concat(Dir.glob(path, flag).select(&block)) 156 | else 157 | find.concat(Dir.glob(path, flag)) 158 | end 159 | end 160 | find 161 | end 162 | end 163 | =end 164 | 165 | -------------------------------------------------------------------------------- /lib/realms/rubylib.rb: -------------------------------------------------------------------------------- 1 | module Realms 2 | 3 | # RubyLibrary is a specialized subclass of Library specifically designed 4 | # to serve Ruby's standard library locations. It is used to speed up load 5 | # times for for library files that are standard Ruby scripts and should never 6 | # be overriden by any 3rd party libraries. Good examples are 'ostruct' and 7 | # 'optparse'. 8 | # 9 | # This class is in the proccess of being refined to exclude certian 3rd 10 | # party redistributions, such RDoc and Soap4r. 11 | # 12 | class RubyLibrary < Library 13 | 14 | include ::RbConfig 15 | 16 | # 17 | def self.instance 18 | @r ||= new 19 | end 20 | 21 | # 22 | # Setup Ruby library. 23 | # 24 | def initialize(*) #(location, metadata={}) 25 | paths = CONFIG.values_at( 26 | 'rubylibdir', 27 | 'archdir', 28 | 'sitedir', 29 | 'sitelibdir', 30 | 'sitearchdir', 31 | 'vendordir', 32 | 'vendorlibdir', 33 | 'vendorarchdir' 34 | ) 35 | 36 | location = find_base_path(paths) 37 | loadpath = paths.map{ |d| d.sub(location + '/','') } 38 | 39 | @location = location 40 | @loadpath = loadpath 41 | @name = 'ruby' 42 | @metadata = {} # TODO: can we fillout Ruby's metadata some ? 43 | end 44 | 45 | # 46 | # Then name of RubyLibrary is `ruby`. 47 | # 48 | def name 49 | 'ruby' 50 | end 51 | 52 | # 53 | # Ruby version is RUBY_VERSION. 54 | # 55 | def version 56 | RUBY_VERSION 57 | end 58 | 59 | # TODO: Remove rugbygems from $LOAD_PATH and use that? 60 | 61 | # TODO: Sometimes people add paths directly to $LOAD_PATH, 62 | # should these be accessible via `ruby/`? 63 | 64 | # 65 | # Load path is essentially $LOAD_PATH, less gem paths. 66 | # 67 | def loadpath 68 | #$LOAD_PATH - ['.'] 69 | @loadpath 70 | end 71 | 72 | alias load_path loadpath 73 | 74 | # 75 | # Release date. 76 | # 77 | # @todo This currently just returns current date/time. 78 | # Is there a way to get Ruby's own release date? 79 | # 80 | def date 81 | Time.now 82 | end 83 | 84 | # 85 | alias released date 86 | 87 | # 88 | # Ruby requires nothing. 89 | # 90 | def requirements 91 | [] 92 | end 93 | 94 | # 95 | # Ruby needs to ignore a few 3rd party libraries. They will 96 | # be picked up by the final fallback to Ruby's original require 97 | # if all else fails. 98 | # 99 | def find(file, suffix=true) 100 | return nil if /^rdoc/ =~ file 101 | super(file, suffix) 102 | end 103 | 104 | # 105 | # Location of executables, which for Ruby is `RbConfig::CONFIG['bindir']`. 106 | # 107 | def bindir 108 | ::RbConfig::CONFIG['bindir'] 109 | end 110 | 111 | # 112 | # Is there a `bin/` location? 113 | # 114 | def bindir? 115 | File.exist?(bindir) 116 | end 117 | 118 | # 119 | # Location of library system configuration files. 120 | # For Ruby this is `RbConfig::CONFIG['sysconfdir']`. 121 | # 122 | def confdir 123 | ::RbConfig::CONFIG['sysconfdir'] 124 | end 125 | 126 | # 127 | # Is there a "`etc`" location? 128 | # 129 | def confdir? 130 | File.exist?(confdir) 131 | end 132 | 133 | # 134 | # Location of library shared data directory. For Ruby this is 135 | # `RbConfig::CONFIG['datadir']`. 136 | # 137 | def datadir 138 | ::RbConfig::CONFIG['datadir'] 139 | end 140 | 141 | # 142 | # Is there a `data/` location? 143 | # 144 | def datadir? 145 | File.exist?(datadir) 146 | end 147 | 148 | # 149 | # Require library +file+ given as a Script instance. 150 | # 151 | # @param [String] feature 152 | # Instance of Feature. 153 | # 154 | # @return [Boolean] Success of requiring the feature. 155 | # 156 | def require_absolute(feature) 157 | return false if $".include?(feature.localname) # ruby 1.8 does not use absolutes 158 | success = super(feature) 159 | $" << feature.localname # ruby 1.8 does not use absolutes TODO: move up? 160 | $".uniq! 161 | success 162 | end 163 | 164 | # 165 | # Load library +file+ given as a Script instance. 166 | # 167 | # @param [String] feature 168 | # Instance of Feature. 169 | # 170 | # @return [Boolean] Success of loading the feature. 171 | # 172 | def load_absolute(feature, wrap=nil) 173 | success = super(feature, wrap) 174 | $" << feature.localname # ruby 1.8 does not use absolutes TODO: move up? 175 | $".uniq! 176 | success 177 | end 178 | 179 | # 180 | # The loadpath sorted by largest path first. 181 | # 182 | def loadpath_sorted 183 | loadpath.sort{ |a,b| b.size <=> a.size } 184 | end 185 | 186 | ## 187 | ## Construct a Script match. 188 | ## 189 | #def libfile(lpath, file, ext=nil) 190 | # Library::Feature.new(self, lpath, file, ext) 191 | #end 192 | 193 | private 194 | 195 | # Given an array of path strings, find the longest common prefix path. 196 | def find_base_path(paths) 197 | return paths.first if paths.length <= 1 198 | arr = paths.sort 199 | f = arr.first.split('/') 200 | l = arr.last.split('/') 201 | i = 0 202 | i += 1 while f[i] == l[i] && i <= f.length 203 | f.slice(0, i).join('/') 204 | end 205 | 206 | end 207 | 208 | end 209 | -------------------------------------------------------------------------------- /work/reference/README.rdoc: -------------------------------------------------------------------------------- 1 | = RUBY ROLLER 2 | 3 |
  4 |                   ____
  5 |               ,dP9CGG88@b,
  6 |             ,IP""YICCG888@@b,
  7 |            dIi   ,IICGG8888@b
  8 |           dCIIiciIICCGG8888@@b
  9 |   ________GCCIIIICCCGGG8888@@@________________
 10 |           GGCCCCCCCGGG88888@@@
 11 |           GGGGCCCGGGG88888@@@@...
 12 |           Y8GGGGGG8888888@@@@P.....
 13 |            Y88888888888@@@@@P......
 14 |            `Y8888888@@@@@@@P'......
 15 |               `@@@@@@@@@P'.......
 16 |                   """"........
 17 | 
18 | 19 | * home: http://rubyworks.github.com/rolls 20 | * work: http://github.com/rubyworks/rolls 21 | 22 | 23 | == DESCRIPTION 24 | 25 | Roller is a library manager for Ruby. With Roller developers can run their 26 | programs in real time --no install phase is required for one program 27 | to depend on another. This makes it very easy to work on a set of 28 | interdependent projects, without vendoring. It also makes easy to 29 | create isolated library environments. Yet Roller does so efficiently 30 | because there need only be a single copy of any given version of a library 31 | on disc. And libraries can be stored anywhere. There is no special place 32 | they must all reside. You simply tell Roller where they reside. And that 33 | includes your Gem home. Roller can serve gem installed libraries as easily 34 | as it serves development libraries. 35 | 36 | 37 | == STATUS 38 | 39 | Roller works fairly well. I have used it for development for years, so 40 | on the whole it stays in working order. However it is still under 41 | development, so configuration is still subject to a fair bit of change. 42 | The loading heuristics are quite advanced, which accounts for the speed, 43 | but as a trade-off the loading procedure is more complex. 44 | 45 | 46 | == HOW TO USE 47 | 48 | === Setting Up 49 | 50 | To use roll regularly you first need to add it your RUBYOPT environment 51 | variable. 52 | 53 | $ export RUBYOPT="-roll" 54 | 55 | If you want to use RubyGems as a fallback, this can be done too: 56 | 57 | $ export RUBYOPT="-roll -rubygems" 58 | 59 | The alternative to this is to add your gem locations to your roll 60 | environment (see below). 61 | 62 | To support executables you will also need to add a line to your startup 63 | .bashrc (or equivalent) file. 64 | 65 | export PATH="$PATH:$(roll path)" 66 | 67 | This will add the +bin+ locations of the programs encompassed by your 68 | current roll environment. 69 | 70 | (NOTE: The way bin paths are handled might change to a symlink directory 71 | in the future if limitations of long environment variables prove problematic. 72 | So far I have not had any issues with the PATH approach.) 73 | 74 | === Preparing your Projects 75 | 76 | For a project to be detected by Roller it must conform to a 77 | minimal POM[http://proutils.github.com/pom] setup. Specifically, 78 | the project must have .meta/ file with `type: ruby`. 79 | That is the bare minimum for a project to be loadable via Roller. 80 | The only exception is for installed gems. If you point Roller torwards 81 | a gem home, Roller will gather the necessary metadata from the gem's 82 | .gemspec file instead. 83 | 84 | See Meta[http://wiki.github.com/rubyworks/meta] for more information about 85 | the .meta/ file. 86 | 87 | === Library Management 88 | 89 | Next you need to setup an roll *environment*. The default environment 90 | is called +production+. You can add a library search location to it 91 | using +roll in+. Eg. 92 | 93 | $ roll in /opt/ruby/ 94 | 95 | As a developer you will may want to setup a +development+ environment. 96 | To change or add an environment use the +use+ command. 97 | 98 | $ roll use development 99 | 100 | Then you can add the paths you want. For instance my development 101 | environment is essentially constructed like this: 102 | 103 | $ roll in ~/programs/proutils 104 | $ roll in ~/programs/rubyworks 105 | $ roll in ~/programs/trans 106 | 107 | By default these paths will be searched for POM conforming projects 108 | up to a depth of three sub-directories. That's suitable for 109 | most needs. You can specify the the depth explicitly with the 110 | --depth or -d option. You can roll in the 111 | current working directory by leaving off the path argument. 112 | If the current directory has a +.ruby+ directory, a depth of +1+ 113 | will automatically be used. 114 | 115 | In the same way you can add gem locations to you roll environment. 116 | For instance on my system: 117 | 118 | $ sudo roll in /usr/lib/ruby/gems/1.8/gems 119 | 120 | Note the use of +sudo+ here. Roller will create .ruby/ 121 | entries automatically in each gem if not already present. Since these 122 | are system-wide gems +sudo+ is needed to give rolls write access. 123 | This is only necessary the first time any new gem is rolled in. 124 | 125 | If a rolled in location changes --say you start a new project, or 126 | install a new gem, you can resync you roll index via the +sync+ command. 127 | 128 | $ roll sync 129 | 130 | Resyncing is only needed when a new project is added to an enironments 131 | lookup locations, or if one of the already included projects change 132 | the `name` or `load_path` in the `.meta` file. To clarify, take a look at the 133 | +show+ command. 134 | 135 | $ roll show --index 136 | 137 | The +use+ command stores the current environment name until the 138 | end of the bash session. To set it perminently, adjust the RUBYENV 139 | environment variable or write the fallback default in the 140 | $HOME/.config/roll/default file. 141 | 142 | For see the rest of the +roll+ commands, use roll help. 143 | 144 | Now you are *read to roll*! 145 | 146 | === Autoload Caveat 147 | 148 | Ruby has a "bug" in that #autoload will not use a customized #require 149 | method. Roller will still work with autoload, if the a library has 150 | already been activated. 151 | 152 | 153 | == LEARNING MORE 154 | 155 | The above provides a brief overview of using roll. But there is more to 156 | it. To get a deeper understanding of the system and how to use +roll+ to 157 | it fullest extent, please visit http://proutils.github.org/roll/. 158 | 159 | 160 | == HOW TO INSTALL 161 | 162 | === Manual Installation (Recommended) 163 | 164 | First you need a copy of the roll tarball (or zip) archive. 165 | You will find them here[http://github.com/proutils/roll/download]. 166 | You will of course need to unpack the file. For example, 167 | 168 | $ tar -xvzf roll-1.0.0 169 | 170 | If you already have Ruby Setup installed on your system you can 171 | use it to install Roller (See: http://setup.rubyforge.org). 172 | 173 | $ cd roll-1.0.0 174 | $ sudo setup.rb 175 | 176 | Otherwise, Roller includes a copy of Ruby Setup that you can 177 | use. 178 | 179 | $ cd roll-1.0.0 180 | $ sudo script/setup. 181 | 182 | On Windows, this last line will need to be 'ruby script/setup'. 183 | 184 | === RubyGems Installation 185 | 186 | We strongly recommend installing Roller manually b/c Roller is a 187 | peer to RubyGems. However, the last we tested it, Roller could 188 | be install via Gems as a means of trying it out --though you won't 189 | get the full benefits of the system. 190 | 191 | gem install roll 192 | 193 | If you like Roller, then later you can uninstall the gem and 194 | do a proper manual install. 195 | 196 | 197 | == BY THE WAY 198 | 199 | Roller was RubyForge project #1004. She's been around a while! ;) 200 | 201 | 202 | == LICENSE & COPYRIGHT 203 | 204 | Roller Copyright (c) 2006,2009 Thomas Sawyer 205 | 206 | Roller is distributed under the same terms as Ruby. 207 | 208 | See the LICENSE file details. 209 | 210 | -------------------------------------------------------------------------------- /lib/realms/interface.rb: -------------------------------------------------------------------------------- 1 | module Realms 2 | class Library 3 | 4 | # The ClassInterface module provides a convenience interface via the Library 5 | # metaclass, primarily giving it methods for interacting with the current 6 | # load manager. 7 | # 8 | module ClassInterface 9 | 10 | # 11 | # Access to global load stack. 12 | # When loading files, the current library doing the loading is pushed 13 | # on this stack, and then popped-off when it is finished. 14 | # 15 | # @return [Array] The `$LOAD_STACK` array. 16 | # 17 | def load_stack 18 | $LOAD_STACK 19 | end 20 | 21 | # 22 | # Access to library load manager. 23 | # 24 | # @return [Manager] The global load manager. 25 | # 26 | def load_manager 27 | $LOAD_MANAGER 28 | end 29 | 30 | # 31 | # Library names from manager. 32 | # 33 | # @return [Array] The keys from `$LOAD_MANAGER` array. 34 | # 35 | def names 36 | $LOAD_MANAGER.keys 37 | end 38 | 39 | alias_method :list, :names 40 | 41 | # 42 | # A shortcut for #instance. 43 | # 44 | # @return [Library,NilClass] The activated Library instance, or `nil` if not found. 45 | # 46 | def [](name, constraint=nil) 47 | $LOAD_MANAGER.activate(name, constraint) if $LOAD_MANAGER.key?(name) 48 | end 49 | 50 | # 51 | # Get an instance of a library by name, or name and version. 52 | # Libraries are singleton, so once loaded the same object is 53 | # always returned. 54 | # 55 | # @todo This method might be deprecated. 56 | # 57 | # @return [Library,NilClass] The activated Library instance, or `nil` if not found. 58 | # 59 | def instance(name, constraint=nil) 60 | $LOAD_MANAGER.activate(name, constraint) if $LOAD_MANAGER.key?(name) 61 | end 62 | 63 | # 64 | # Activate a library. Same as #instance but will raise and error if the 65 | # library is not found. This can also take a block to yield on the library. 66 | # 67 | # @param [String] name 68 | # Name of library. 69 | # 70 | # @param [String] constraint 71 | # Valid version constraint. 72 | # 73 | # @raise [LoadError] 74 | # If library not found. 75 | # 76 | # @return [Library] 77 | # The activated Library object. 78 | # 79 | def activate(name, constraint=nil, &block) #:yield: 80 | $LOAD_MANAGER.activate(name, constraint, &block) 81 | end 82 | 83 | # 84 | # Like `#new`, but adds library to library manager. 85 | # 86 | # @todo Better name for this method? 87 | # 88 | # @return [Library] The new library. 89 | # 90 | def add(location) 91 | $LOAD_MANAGER.add(location) 92 | end 93 | 94 | # 95 | # Find matching library features. This is the "mac daddy" method used by 96 | # the #require and #load methods to find the specified +path+ among 97 | # the various libraries and their load paths. 98 | # 99 | def find(path, options={}) 100 | $LOAD_MANAGER.find(path, options) 101 | end 102 | 103 | =begin 104 | # 105 | # Brute force variation of `#find` looks through all libraries for a 106 | # matching features. This serves as the fallback method if `#find` comes 107 | # up empty. 108 | # 109 | # @param [String] path 110 | # path name for which to search 111 | # 112 | # @param [Hash] options 113 | # Search options. 114 | # 115 | # @option options [Boolean] :latest 116 | # Search only the active or most current version of any library. 117 | # 118 | # @option options [Boolean] :suffix 119 | # Automatically try standard extensions if pathname has none. 120 | # 121 | # @option options [Boolean] :legacy 122 | # Do not match within library's +name+ directory, eg. `lib/foo/*`. 123 | # 124 | # @return [Feature,Array] Matching feature(s). 125 | # 126 | def find_any(path, options={}) 127 | $LOAD_MANAGER.find_any(path, options) 128 | end 129 | =end 130 | 131 | # 132 | # Brute force search looks through all libraries for matching features. 133 | # This is the same as #find_any, but returns a list of matches rather 134 | # then the first matching feature found. 135 | # 136 | # @param [String] pattern 137 | # Glob pattern for which to search. 138 | # 139 | # @param [Hash] options 140 | # Search options. 141 | # 142 | # @option options [Boolean] :latest 143 | # Search only the active or most current version of any library. 144 | # 145 | # @option options [Boolean] :suffix 146 | # Automatically try standard extensions if pathname has none. 147 | # 148 | # @option options [Boolean] :legacy 149 | # Do not match within library's +name+ directory, eg. `lib/foo/*`. 150 | # 151 | # @return [Feature,Array] Matching feature(s). 152 | # 153 | def search(pattern, options={}) 154 | $LOAD_MANAGER.search(pattern, options) 155 | end 156 | 157 | =begin 158 | # 159 | # Search for all matching library files that match the given pattern. 160 | # This could be of useful for plugin loader. 161 | # 162 | # @param [Hash] options 163 | # Glob matching options. 164 | # 165 | # @option options [Boolean] :latest 166 | # Search only activated libraries or the most recent version 167 | # of a given library. 168 | # 169 | # @return [Array] Matching file paths. 170 | # 171 | # @todo Should this return list of Feature objects instead of file paths? 172 | # 173 | def glob(match, options={}) 174 | $LOAD_MANAGER.glob(match, options) 175 | end 176 | =end 177 | 178 | # 179 | # Require a feature from the library. 180 | # 181 | # @param [String] pathname 182 | # The pathname of feature relative to library's loadpath. 183 | # 184 | # @param [Hash] options 185 | # 186 | # @return [true,false] If feature was newly required or successfully loaded. 187 | # 188 | def require(pathname, options={}) 189 | $LOAD_MANAGER.require(pathname, options) 190 | end 191 | 192 | # 193 | # Load file path. This is just like #require except that previously 194 | # loaded files will be reloaded and standard extensions will not be 195 | # automatically appended. 196 | # 197 | # @param pathname [String] 198 | # pathname of feature relative to library's loadpath 199 | # 200 | # @return [true,false] if feature was successfully loaded 201 | # 202 | def load(pathname, options={}) #, &block) 203 | $LOAD_MANAGER.load(pathname, options) 204 | end 205 | 206 | # 207 | # Like require but also with local lookup. It will first check to see 208 | # if the currently loading library has the path relative to its load paths. 209 | # 210 | # acquire('core_ext/margin') 211 | # 212 | # To "load" the library, rather than "require" it, set the +:load+ 213 | # option to true. 214 | # 215 | # acquire('core_ext/string/margin', :load=>true) 216 | # 217 | # @param pathname [String] 218 | # Pathname of feature relative to library's loadpath. 219 | # 220 | # @return [true, false] If feature was newly required. 221 | # 222 | def acquire(pathname, options={}) #, &block) 223 | $LOAD_MANAGER.acquire(pathname, options) 224 | end 225 | 226 | # 227 | # Lookup libraries that have a depenedency on the given library name 228 | # and version. 229 | # 230 | # @todo Does not yet handle version constraint. 231 | # @todo Sucky name. 232 | # 233 | # @return [Array] 234 | # 235 | def depend_upon(match_name) #, constraint) 236 | $LOAD_MANAGER.depend_upon(match_name) #, constraint) 237 | end 238 | 239 | # 240 | # Go thru each library and collect bin paths. 241 | # 242 | # @todo Should this be defined on Manager? 243 | # 244 | def PATH() 245 | $LOAD_MANAGER.PATH() 246 | end 247 | 248 | end 249 | 250 | extend ClassInterface 251 | 252 | end 253 | end 254 | -------------------------------------------------------------------------------- /.gemspec: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | 3 | require 'yaml' 4 | require 'pathname' 5 | 6 | module Indexer 7 | 8 | # Convert index data into a gemspec. 9 | # 10 | # Notes: 11 | # * Assumes all executables are in bin/. 12 | # * Does not yet handle default_executable setting. 13 | # * Does not yet handle platform setting. 14 | # * Does not yet handle required_ruby_version. 15 | # * Support for rdoc entries is weak. 16 | # 17 | class GemspecExporter 18 | 19 | # File globs to include in package --unless a manifest file exists. 20 | FILES = ".index .yardopts alt bin data demo ext features lib man spec test try* [A-Z]*.*" unless defined?(FILES) 21 | 22 | # File globs to omit from FILES. 23 | OMIT = "Config.rb" unless defined?(OMIT) 24 | 25 | # Standard file patterns. 26 | PATTERNS = { 27 | :root => '{.index,Gemfile}', 28 | :bin => 'bin/*', 29 | :lib => 'lib/{**/}*', #.rb', 30 | :ext => 'ext/{**/}extconf.rb', 31 | :doc => '*.{txt,rdoc,md,markdown,tt,textile}', 32 | :test => '{test,spec}/{**/}*.rb' 33 | } unless defined?(PATTERNS) 34 | 35 | # For which revision of indexer spec is this converter intended? 36 | REVISION = 2013 unless defined?(REVISION) 37 | 38 | # 39 | def self.gemspec 40 | new.to_gemspec 41 | end 42 | 43 | # 44 | attr :metadata 45 | 46 | # 47 | def initialize(metadata=nil) 48 | @root_check = false 49 | 50 | if metadata 51 | root_dir = metadata.delete(:root) 52 | if root_dir 53 | @root = root_dir 54 | @root_check = true 55 | end 56 | metadata = nil if metadata.empty? 57 | end 58 | 59 | @metadata = metadata || YAML.load_file(root + '.index') 60 | 61 | if @metadata['revision'].to_i != REVISION 62 | warn "This gemspec exporter was not designed for this revision of index metadata." 63 | end 64 | end 65 | 66 | # 67 | def has_root? 68 | root ? true : false 69 | end 70 | 71 | # 72 | def root 73 | return @root if @root || @root_check 74 | @root_check = true 75 | @root = find_root 76 | end 77 | 78 | # 79 | def manifest 80 | return nil unless root 81 | @manifest ||= Dir.glob(root + 'manifest{,.txt}', File::FNM_CASEFOLD).first 82 | end 83 | 84 | # 85 | def scm 86 | return nil unless root 87 | @scm ||= %w{git hg}.find{ |m| (root + ".#{m}").directory? }.to_sym 88 | end 89 | 90 | # 91 | def files 92 | return [] unless root 93 | @files ||= \ 94 | if manifest 95 | File.readlines(manifest). 96 | map{ |line| line.strip }. 97 | reject{ |line| line.empty? || line[0,1] == '#' } 98 | else 99 | list = [] 100 | Dir.chdir(root) do 101 | FILES.split(/\s+/).each do |pattern| 102 | list.concat(glob(pattern)) 103 | end 104 | OMIT.split(/\s+/).each do |pattern| 105 | list = list - glob(pattern) 106 | end 107 | end 108 | list 109 | end.select{ |path| File.file?(path) }.uniq 110 | end 111 | 112 | # 113 | def glob_files(pattern) 114 | return [] unless root 115 | Dir.chdir(root) do 116 | Dir.glob(pattern).select do |path| 117 | File.file?(path) && files.include?(path) 118 | end 119 | end 120 | end 121 | 122 | def patterns 123 | PATTERNS 124 | end 125 | 126 | def executables 127 | @executables ||= \ 128 | glob_files(patterns[:bin]).map do |path| 129 | File.basename(path) 130 | end 131 | end 132 | 133 | def extensions 134 | @extensions ||= \ 135 | glob_files(patterns[:ext]).map do |path| 136 | File.basename(path) 137 | end 138 | end 139 | 140 | def name 141 | metadata['name'] || metadata['title'].downcase.gsub(/\W+/,'_') 142 | end 143 | 144 | def homepage 145 | page = ( 146 | metadata['resources'].find{ |r| r['type'] =~ /^home/i } || 147 | metadata['resources'].find{ |r| r['name'] =~ /^home/i } || 148 | metadata['resources'].find{ |r| r['name'] =~ /^web/i } 149 | ) 150 | page ? page['uri'] : false 151 | end 152 | 153 | def licenses 154 | metadata['copyrights'].map{ |c| c['license'] }.compact 155 | end 156 | 157 | def require_paths 158 | paths = metadata['paths'] || {} 159 | paths['load'] || ['lib'] 160 | end 161 | 162 | # 163 | # Convert to gemnspec. 164 | # 165 | def to_gemspec 166 | if has_root? 167 | Gem::Specification.new do |gemspec| 168 | to_gemspec_data(gemspec) 169 | to_gemspec_paths(gemspec) 170 | end 171 | else 172 | Gem::Specification.new do |gemspec| 173 | to_gemspec_data(gemspec) 174 | to_gemspec_paths(gemspec) 175 | end 176 | end 177 | end 178 | 179 | # 180 | # Convert pure data settings. 181 | # 182 | def to_gemspec_data(gemspec) 183 | gemspec.name = name 184 | gemspec.version = metadata['version'] 185 | gemspec.summary = metadata['summary'] 186 | gemspec.description = metadata['description'] 187 | 188 | metadata['authors'].each do |author| 189 | gemspec.authors << author['name'] 190 | 191 | if author.has_key?('email') 192 | if gemspec.email 193 | gemspec.email << author['email'] 194 | else 195 | gemspec.email = [author['email']] 196 | end 197 | end 198 | end 199 | 200 | gemspec.licenses = licenses 201 | 202 | requirements = metadata['requirements'] || [] 203 | requirements.each do |req| 204 | next if req['optional'] 205 | next if req['external'] 206 | 207 | name = req['name'] 208 | groups = req['groups'] || [] 209 | 210 | version = gemify_version(req['version']) 211 | 212 | if groups.empty? or groups.include?('runtime') 213 | # populate runtime dependencies 214 | if gemspec.respond_to?(:add_runtime_dependency) 215 | gemspec.add_runtime_dependency(name,*version) 216 | else 217 | gemspec.add_dependency(name,*version) 218 | end 219 | else 220 | # populate development dependencies 221 | if gemspec.respond_to?(:add_development_dependency) 222 | gemspec.add_development_dependency(name,*version) 223 | else 224 | gemspec.add_dependency(name,*version) 225 | end 226 | end 227 | end 228 | 229 | # convert external dependencies into gemspec requirements 230 | requirements.each do |req| 231 | next unless req['external'] 232 | gemspec.requirements << ("%s-%s" % req.values_at('name', 'version')) 233 | end 234 | 235 | gemspec.homepage = homepage 236 | gemspec.require_paths = require_paths 237 | gemspec.post_install_message = metadata['install_message'] 238 | end 239 | 240 | # 241 | # Set gemspec settings that require a root directory path. 242 | # 243 | def to_gemspec_paths(gemspec) 244 | gemspec.files = files 245 | gemspec.extensions = extensions 246 | gemspec.executables = executables 247 | 248 | if Gem::VERSION < '1.7.' 249 | gemspec.default_executable = gemspec.executables.first 250 | end 251 | 252 | gemspec.test_files = glob_files(patterns[:test]) 253 | 254 | unless gemspec.files.include?('.document') 255 | gemspec.extra_rdoc_files = glob_files(patterns[:doc]) 256 | end 257 | end 258 | 259 | # 260 | # Return a copy of this file. This is used to generate a local 261 | # .gemspec file that can automatically read the index file. 262 | # 263 | def self.source_code 264 | File.read(__FILE__) 265 | end 266 | 267 | private 268 | 269 | def find_root 270 | root_files = patterns[:root] 271 | if Dir.glob(root_files).first 272 | Pathname.new(Dir.pwd) 273 | elsif Dir.glob("../#{root_files}").first 274 | Pathname.new(Dir.pwd).parent 275 | else 276 | #raise "Can't find root of project containing `#{root_files}'." 277 | warn "Can't find root of project containing `#{root_files}'." 278 | nil 279 | end 280 | end 281 | 282 | def glob(pattern) 283 | if File.directory?(pattern) 284 | Dir.glob(File.join(pattern, '**', '*')) 285 | else 286 | Dir.glob(pattern) 287 | end 288 | end 289 | 290 | def gemify_version(version) 291 | case version 292 | when /^(.*?)\+$/ 293 | ">= #{$1}" 294 | when /^(.*?)\-$/ 295 | "< #{$1}" 296 | when /^(.*?)\~$/ 297 | "~> #{$1}" 298 | else 299 | version 300 | end 301 | end 302 | 303 | end 304 | 305 | end 306 | 307 | Indexer::GemspecExporter.gemspec -------------------------------------------------------------------------------- /work/reference/console.rb: -------------------------------------------------------------------------------- 1 | module Rolls 2 | 3 | # Roll management console module extends the Rolls module 4 | # with general purpose functions. 5 | # 6 | module Console0 7 | 8 | # 9 | # The environment variable used to specify a named roll. 10 | # 11 | ENVIRNMENT_VARIABLE = 'RUBYROLL' 12 | 13 | # 14 | # The default roll to use, if none is specified. 15 | # 16 | DEFAULT_ROLLNAME = 'default' 17 | 18 | # 19 | # Setup Rolls. 20 | # 21 | def bootstrap!(name=nil) 22 | require 'library' 23 | 24 | $LEDGER = Ledger.new 25 | $LOAD_STACK = [] 26 | $LOAD_CACHE = {} 27 | 28 | if !roll_file 29 | warn "no such roll -- `#{rollname}'" 30 | return 31 | end 32 | 33 | if File.exist?(lock_file) 34 | ledger = YAML.load(File.new(lock_file)) 35 | 36 | # TODO: Put RUBYENV in serialized ledger 37 | #ENV['RUBYENV'] = ledger.delete('RUBYENV') 38 | 39 | $LEDGER.replace(ledger) 40 | else 41 | paths = load_roll(roll_file) 42 | 43 | ENV['RUBY_LIBRARY'] = paths.join( windows_platform? ? ';' : ':' ) 44 | 45 | Ledger.prime(*paths) #, :exound=>true) 46 | end 47 | 48 | #bootstrap_legacy if legacy? 49 | 50 | # NOTE: It doesn't look like we can not do this b/c it prevents gems from working 51 | # when a file has the same name as something in the ruby lib and site locations. 52 | # For example, if we install the test-unit gem and require `test/unit`. 53 | #$LEDGER['ruby'] = RubyLibrary.new 54 | 55 | require 'library/kernel' 56 | end 57 | 58 | # 59 | #def legacy? 60 | # ENV['roll_legacy'] != 'false' 61 | #end 62 | 63 | ## Legacy mode manages a traditional loadpath. 64 | #def bootstrap_legacy 65 | # return unless legacy? 66 | # $LEDGER.each do |name, libs| 67 | # #next if name == 'ruby' 68 | # #next if name == 'site_ruby' 69 | # sorted_libs = [libs].flatten.sort 70 | # lib = sorted_libs.first 71 | # lib.absolute_loadpath.each do |path| 72 | # $LOAD_PATH.unshift(path) 73 | # end 74 | # end 75 | #end 76 | 77 | # dirs = [] 78 | # dirs << ENV['XDG_CONFIG_HOME'] || File.join(home, '.config') 79 | # dirs << ENV['XDG_CONFIG_DIRS'].to_s.split(/[:;]/) 80 | # XDG_CONFIG_PATHS = dirs.flatten.map{ |dir| [File.expand_path(dir) } 81 | 82 | # 83 | # 84 | # 85 | def config_paths 86 | @config_paths ||= ( 87 | paths = [] 88 | paths << File.expand_path("~/.roll") 89 | paths << File.expand_path("~/.config/roll") 90 | paths << "/etc/roll" 91 | paths.select{ |path| File.directory?(path) } 92 | ) 93 | end 94 | 95 | # 96 | # Find Roll configuration file. 97 | # 98 | def find_config(file) 99 | config_paths.each do |path| 100 | f = File.join(path, file) 101 | return f if File.exist?(f) 102 | end 103 | nil 104 | end 105 | 106 | # 107 | # Search Roll's config locations for mathing file glob. 108 | # 109 | def search_config(glob) 110 | list = [] 111 | config_paths.each do |path| 112 | list.concat(Dir[File.join(path, glob)]) 113 | end 114 | list 115 | end 116 | 117 | # 118 | # Return array of available rolls. 119 | # 120 | def available_rolls 121 | search_config('*.roll').map { |r| File.basename(r).chomp('.roll') } 122 | end 123 | 124 | =begin 125 | # 126 | # The Roll file to use. 127 | # 128 | def roll_file(name=nil) 129 | @roll_file ||= {} 130 | 131 | name ||= rollname() 132 | 133 | return @roll_file[name] unless @roll_file[name].nil? 134 | 135 | @roll_file[name] = ( 136 | file = false 137 | if name?(name) 138 | file = find_config(name + '.roll') 139 | else 140 | file = File.expand_path(name) 141 | file = file + '.roll' if File.extname(file) != '.roll' && !File.exist?(file) 142 | file = false unless File.exist?(file) 143 | end 144 | 145 | file || false 146 | ) 147 | end 148 | =end 149 | 150 | # 151 | # 152 | # 153 | def roll_file 154 | File.expand_path(ENV['RUBY_ROLL'] || '~/.ruby/current.roll') 155 | end 156 | 157 | # 158 | # Lock file is the same as roll_file but will `.lock` extension. 159 | # 160 | def lock_file 161 | roll_file.chomp('.roll') + '.lock' 162 | end 163 | 164 | # 165 | # Selected roll. This will either be a name coresponding to a file in the 166 | # standard configuration locations (`~/.roll`, `~/.config/roll` or `/etc/roll`), 167 | # or it can be a pathname to an otherwise located file. 168 | # 169 | def rollname 170 | @rollname ||= ENV[ENVIRNMENT_VARIABLE] || rollname_from_file || DEFAULT_ROLLNAME 171 | end 172 | 173 | # 174 | # Typically the roll is configured by environment variable (`RUBYROLL`) but 175 | # if need be it can be configured via a config file of the same name. 176 | # 177 | def rollname_from_file 178 | if file = find_config('RUBYROLL') 179 | File.read(file).strip 180 | else 181 | nil 182 | end 183 | end 184 | 185 | # 186 | # Construct ledger using pathnames in given `file`. 187 | # 188 | #def load_ledger(file) 189 | # make_ledger(File.readlines(file)) 190 | #end 191 | 192 | # 193 | # Construct a ledger. 194 | # 195 | def load_roll(file) 196 | list = [] 197 | 198 | paths = File.readlines(file) 199 | paths = paths.map{ |g| Dir[g.strip] }.flatten 200 | 201 | paths.each do |path| 202 | path = path.strip 203 | 204 | next if path[0,1] == '#' 205 | next if path.empty? 206 | 207 | if !File.directory?(path) 208 | warn "invalid library path -- `#{path}'" if ENV['debug'] 209 | next 210 | end 211 | 212 | #begin 213 | list << path 214 | #rescue Exception => error 215 | # warn error.message if ENV['debug'] 216 | # #warn "invalid library path -- `#{path}'" if ENV['roll_debug'] 217 | #end 218 | end 219 | 220 | list 221 | end 222 | 223 | # 224 | # FIXME: This should be done via Library::Ledger somehow. 225 | # Could use prime_expound. 226 | # 227 | def make_ledger(file) 228 | list = load_roll(file) 229 | ledger = Library::Ledger.new 230 | list.each do |path| 231 | ledger << path 232 | end 233 | ledger 234 | end 235 | 236 | # 237 | # Lock a ledger. 238 | # 239 | # @return [String] full pathname of lock file. 240 | # 241 | def lock(file=nil, options={}) 242 | if file 243 | ledger = make_ledger(file) 244 | output = options[:output] || file + '.lock' 245 | else 246 | ledger = $LEDGER 247 | output = options[:output] || lock_file 248 | end 249 | 250 | File.open(output, 'w+') do |f| 251 | f << ledger.to_yaml 252 | end 253 | 254 | return output 255 | end 256 | 257 | # 258 | # Remove a ledger lock. 259 | # 260 | # @param [String] name 261 | # Name of roll. If not given the curent roll is used. 262 | # 263 | # @return [String] Full pathname of cache file. 264 | # 265 | def unlock(name=nil) 266 | file = roll_file(name) 267 | raise IOError, "#{name} is not a roll" unless file 268 | lock_file = file.chomp('.roll') + '.lock' 269 | if File.exist?(lock_file) 270 | File.delete(lock_file) 271 | lock_file 272 | else 273 | nil 274 | end 275 | end 276 | 277 | # 278 | # Insert path into current roll. 279 | # 280 | # @return [String] roll file 281 | # 282 | def insert(*paths) 283 | paths.map!{ |path| File.expand_path(path) } 284 | File.open(roll_file, 'a') do |file| 285 | file << "\n" 286 | file << paths.join("\n") 287 | end 288 | roll_file 289 | end 290 | 291 | # 292 | # Remove path(s) from current roll. 293 | # 294 | # @return [String] roll file 295 | # 296 | def remove(*paths) 297 | paths.map!{ |path| File.expand_path(path) } 298 | list = File.readlines(roll_file) 299 | list = list - paths 300 | File.open(roll_file, 'w') do |file| 301 | file << list.join("\n") 302 | end 303 | roll_file 304 | end 305 | 306 | # 307 | # Does this location have a .index file? 308 | # 309 | def index?(location) 310 | file = ::File.join(location, '.index') 311 | return false unless File.file?(file) 312 | return true 313 | end 314 | 315 | # 316 | # Return list of locked rolls. 317 | # 318 | def locked_rolls 319 | Dir[File.join(config_home, '*.lock')].map do |file| 320 | file.chomp('.lock') + '.roll' 321 | end 322 | end 323 | 324 | # 325 | # 326 | # 327 | def copy(dst, src=nil, opts={}) 328 | if src 329 | src = Roll.construct_roll_file(src) 330 | dst = Roll.construct_roll_file(dst) 331 | else 332 | src = Roll.roll_file 333 | dst = Roll.construct_roll_file(dst) 334 | end 335 | 336 | safe_copy(src, dst) 337 | 338 | if opts[:lock] 339 | Roll.lock(dst) 340 | puts "Locked '#{dst}`." 341 | else 342 | puts "Saved '#{dst}`." 343 | end 344 | end 345 | 346 | # 347 | # Lock rolls that contain locations relative to the current gem home. 348 | # 349 | # @todo Better name for this method ? 350 | # 351 | # @return [Array] list of roll files that were re-locked 352 | # 353 | def lock_gem_rolls 354 | relock = [] 355 | 356 | locked_rolls.each do |file| 357 | File.each_line do |path| 358 | path = path.strip 359 | if gem_path?(path) 360 | relock << file 361 | break 362 | end 363 | end 364 | end 365 | 366 | relock.each do |file| 367 | lock(file) 368 | end 369 | 370 | relock 371 | end 372 | 373 | private 374 | 375 | # 376 | # Copy a file safely. 377 | # 378 | def safe_copy(src, dst) 379 | if not File.exist?(src) 380 | $stderr.puts "File does not exist -- '#{src}`" 381 | exit -1 382 | end 383 | if File.exist?(dst) && !opts[:force] 384 | $stderr.puts "'#{dst}` already exists. Use --force option to overwrite." 385 | exit -1 386 | end 387 | FileUtils.cp(src, dst) 388 | end 389 | 390 | # 391 | # Is the given file a path (as opposed to just a name)? 392 | # 393 | def path?(file) 394 | /\W/ =~ file 395 | end 396 | 397 | # 398 | # Is the given file just a name (as opposed to a path)? 399 | # 400 | def name?(file) 401 | /\W/ !~ file 402 | end 403 | 404 | # 405 | # Does the current roll include any entires that lie within 406 | # the current gem home? 407 | # 408 | def gem_path?(path) 409 | dir = ENV['GEM_HOME'] || gem_home 410 | rex = ::Regexp.new("^#{Regexp.escape(dir)}\/") 411 | rex =~ path 412 | end 413 | 414 | # 415 | # Default gem home directory path. 416 | # 417 | # @return [String] Gem home path. 418 | # 419 | def gem_home 420 | if defined? RUBY_FRAMEWORK_VERSION then 421 | File.join File.dirname(CONFIG["sitedir"]), 'Gems', CONFIG["ruby_version"] 422 | elsif CONFIG["rubylibprefix"] then 423 | File.join(CONFIG["rubylibprefix"], 'gems', CONFIG["ruby_version"]) 424 | else 425 | File.join(CONFIG["libdir"], ruby_engine, 'gems', CONFIG["ruby_version"]) 426 | end 427 | end 428 | 429 | end 430 | 431 | end 432 | -------------------------------------------------------------------------------- /lib/realms/metadata.rb: -------------------------------------------------------------------------------- 1 | module Realms 2 | class Library 3 | 4 | # The Metadata class encapsulates a library's basic information, in particular 5 | # name, version and load path. 6 | # 7 | class Metadata 8 | 9 | # 10 | # 11 | # 12 | def self.load(location) 13 | m = new(:location=>location) 14 | m.load_metadata 15 | m 16 | end 17 | 18 | # 19 | # Setup new metadata object. 20 | # 21 | # @param [Hash] metadata 22 | # Library metadata overrides anything loaded from disc, but usually 23 | # only `:location` is given. 24 | # 25 | # @option metadata [String] :location 26 | # Location of project on disc. If this is provided metadata will be 27 | # loaded from available `.index` or `.gemspec` file. 28 | # 29 | def initialize(metadata={}) 30 | @table = {} 31 | 32 | case metadata 33 | when Hash 34 | update(metadata) 35 | else 36 | @table[:location] = metadata.to_s 37 | load_metadata 38 | end 39 | end 40 | 41 | # 42 | # Update metadata with data hash. 43 | # 44 | # @param [Hash] data 45 | # Data to merge into metadata table. 46 | # 47 | def update(data) 48 | data.each do |key, value| 49 | __send__("#{key}=", value) if respond_to?("#{key}=") 50 | end 51 | end 52 | 53 | # 54 | # Get library location. 55 | # 56 | def location 57 | @table[:location] 58 | end 59 | 60 | # 61 | # Set library locations. 62 | # 63 | def location=(path) 64 | @table[:location] = path.to_s 65 | end 66 | 67 | # 68 | # Name of library. 69 | # 70 | def name 71 | @table[:name] 72 | end 73 | 74 | # 75 | # Set name. 76 | # 77 | def name=(string) 78 | @table[:name] = string.to_s if string 79 | end 80 | 81 | # 82 | # Version number. 83 | # 84 | # Technically, a library should not appear in a ledger list if it lacks 85 | # a version. However, just in case this occurs (say by a hand edited 86 | # environment) we fallback to a version of '0.0.0'. 87 | # 88 | def version 89 | @table[:version] ||= Version::Number.new('0.0.0') 90 | end 91 | 92 | # 93 | # Set version, converts string into Version number class. 94 | # 95 | def version=(string) 96 | @table[:version] = Version::Number.new(string) if string 97 | end 98 | 99 | # 100 | # Release date. 101 | # 102 | def date 103 | @table[:date] 104 | end 105 | 106 | alias_method :released, :date 107 | 108 | # 109 | # Set the date. 110 | # 111 | # TODO: Should we convert date to Time object? 112 | # 113 | def date=(date) 114 | @table[:date] = date 115 | end 116 | 117 | alias_method :released=, :date= 118 | 119 | # 120 | # Paths, the only one used currently is `load`. 121 | # 122 | def paths 123 | @table[:paths] || {} 124 | end 125 | 126 | # 127 | # Set paths map. 128 | # 129 | # @param [Hash] paths 130 | # Paths map. 131 | # 132 | def paths=(paths) 133 | @table[:paths] = ( 134 | h = {} 135 | paths.each do |key, val| 136 | val = (String === val ? split_path(val) : val) 137 | h[key.to_sym] = Array(val) 138 | end 139 | h 140 | ) 141 | end 142 | 143 | # 144 | # Local lib paths. 145 | # 146 | def lib_paths 147 | paths[:lib] || ['lib'] 148 | end 149 | 150 | # 151 | # Set the local lib paths. 152 | # 153 | def lib_paths=(paths) 154 | case paths 155 | when nil 156 | paths = ['lib'] 157 | when String 158 | paths = split_path(path) 159 | end 160 | paths[:lib] = paths 161 | end 162 | 163 | =begin 164 | # 165 | # Load path with library location. 166 | # 167 | def load_path 168 | lib_paths.map{ |path| File.join(location, path) } 169 | end 170 | 171 | alias_method :loadpath, :load_path 172 | =end 173 | 174 | # 175 | # Runtime and development requirements combined. 176 | # 177 | def requirements 178 | @table[:requirements] 179 | end 180 | 181 | # 182 | # Runtime and development requirements combined. 183 | # 184 | def requirements=(requirements) 185 | @table[:requirements] = Array(requirements) 186 | end 187 | 188 | # 189 | # Runtime requirements. 190 | # 191 | def runtime_requirements 192 | @runtime_requirements ||= requirements.reject{ |r| r['development'] } 193 | end 194 | 195 | # 196 | # Development requirements. 197 | # 198 | def development_requirements 199 | @development_requirements ||= requirements.select{ |r| r['development'] } 200 | end 201 | 202 | # TODO: Should we support +active+ setting? 203 | 204 | # 205 | # Is the library active? If not it should be ignored. 206 | # 207 | def active? 208 | @active 209 | end 210 | 211 | # 212 | # Set active. 213 | # 214 | def active=(boolean) 215 | @active = boolean 216 | end 217 | 218 | # 219 | # Open access to non-primary metadata. 220 | # 221 | def [](name) 222 | @table[name.to_sym] 223 | end 224 | 225 | # 226 | # Does this location have `.index` file? 227 | # 228 | def dotindex? 229 | @_dotindex ||= File.exist?(File.join(location, '.index')) 230 | end 231 | 232 | # 233 | # 234 | # 235 | def gemspec? 236 | true if Dir[File.join(location, '*.gemspec')].first 237 | end 238 | 239 | # 240 | # Deterime if the location is a gem location. It does this by looking 241 | # for the corresponding `gems/specification/*.gemspec` file. 242 | # 243 | def gem? 244 | #return true if Dir[File.join(location, '*.gemspec')].first 245 | pkgname = File.basename(location) 246 | gemsdir = File.dirname(location) 247 | specdir = File.join(File.dirname(gemsdir), 'specifications') 248 | Dir[File.join(specdir, "#{pkgname}.gemspec")].first 249 | end 250 | 251 | # 252 | # Access to complete gemspec. This is for use with extended metadata. 253 | # 254 | def gemspec 255 | @gemspec ||= ( 256 | require 'rubygems' 257 | ::Gem::Specification.load(gemspec_file) 258 | ) 259 | end 260 | 261 | =begin 262 | # 263 | # Verify that a library's requirements are all available in the ledger. 264 | # Returns a list of `[name, version]` of Libraries that were not found. 265 | # 266 | # @return [Array] List of missing requirements. 267 | # 268 | def missing_requirements(development=false) #verbose=false) 269 | libs, fail = [], [] 270 | reqs = development ? requirements : runtime_requirements 271 | reqs.each do |req| 272 | name = req['name'] 273 | vers = req['version'] 274 | lib = Library[name, vers] 275 | if lib 276 | libs << lib 277 | #$stdout.puts " [LOAD] #{name} #{vers}" if verbose 278 | unless libs.include?(lib) or fail.include?([lib,vers]) 279 | lib.verify_requirements(development) #verbose) 280 | end 281 | else 282 | fail << [name, vers] 283 | #$stdout.puts " [FAIL] #{name} #{vers}" if verbose 284 | end 285 | end 286 | return fail 287 | end 288 | 289 | # 290 | # Like {#missing_requirements} but returns `true`/`false`. 291 | # 292 | def missing_requirements?(development=false) 293 | list = missing_requirements(development=false) 294 | list.empty? ? false : true 295 | end 296 | =end 297 | 298 | # 299 | # Returns hash of primary metadata. 300 | # 301 | # @return [Hash] primary metdata 302 | # 303 | def to_h 304 | { 'location' => location, 305 | 'name' => name, 306 | 'version' => version.to_s, 307 | 'date' => date.to_s, 308 | 'paths' => { 'lib' => lib_paths }, 309 | 'requirements' => requirements, 310 | #'active' => active? 311 | } 312 | end 313 | 314 | private 315 | 316 | # 317 | # Load metadata. 318 | # 319 | def load_metadata 320 | if dotindex? 321 | load_dotindex 322 | elsif gem? or gemspec? 323 | load_gemspec 324 | end 325 | end 326 | 327 | # 328 | # Load metadata for .index file. 329 | # 330 | def load_dotindex 331 | file = File.join(location, '.index') 332 | data = YAML.load_file(file) 333 | update(data) 334 | end 335 | 336 | # Load metadata from a gemspec. This is a fallback option. It is highly 337 | # recommended that a project have a `.index` file instead. 338 | # 339 | # This method requires that the `metaspec` gem be installed. # TODO: metaspec gem name ? 340 | # 341 | # TODO: Deprecate YAML form of gemspec, RubyGems no longer supports it. 342 | # 343 | def load_gemspec 344 | 345 | text = File.read(gemspec_file) 346 | if text =~ /\A---/ 347 | require 'yaml' 348 | spec = YAML.load(text) 349 | else 350 | #spec = eval(text) #, gemspec_file) 351 | spec = ::Gem::Specification.load(gemspec_file) 352 | end 353 | 354 | data = {} 355 | data[:name] = spec.name 356 | data[:version] = spec.version.to_s 357 | data[:date] = spec.date 358 | 359 | data[:paths] = { 360 | 'load' => spec.require_paths 361 | } 362 | 363 | data[:requirements] = [] 364 | 365 | spec.runtime_dependencies.each do |dep| 366 | req = { 367 | 'name' => dep.name, 368 | 'version' => dep.requirement.to_s 369 | } 370 | data[:requirements] << req 371 | end 372 | 373 | spec.development_dependencies.each do |dep| 374 | req = { 375 | 'name' => dep.name, 376 | 'version' => dep.requirement.to_s, 377 | 'development' => true 378 | } 379 | data[:requirements] << req 380 | end 381 | 382 | update(data) 383 | end 384 | 385 | # 386 | # Returns the path to the .gemspec file. 387 | # 388 | def gemspec_file 389 | gemspec_file_system || gemspec_file_local 390 | end 391 | 392 | # 393 | # Returns the path to a gemspec file located in the project location, 394 | # if it exists. Otherwise returns +nil+. 395 | # 396 | def gemspec_file_local 397 | @_gemspec_file_local ||= Dir[File.join(location, '*.gemspec')].first 398 | end 399 | 400 | # 401 | # Returns the path to a gemspec file located in the gems/specifications 402 | # directory, if it exists. Otherwise returns +nil+. 403 | # 404 | def gemspec_file_system 405 | @_gemspec_file_system ||= ( 406 | pkgname = File.basename(location) 407 | gemsdir = File.dirname(location) 408 | specdir = File.join(File.dirname(gemsdir), 'specifications') 409 | Dir[File.join(specdir, "#{pkgname}.gemspec")].first 410 | ) 411 | end 412 | 413 | # 414 | #def require_indexer 415 | # require 'rubygems' 416 | # require 'indexer' 417 | # require 'indexer/rubygems' 418 | #end 419 | 420 | # 421 | def split_path(path) 422 | path.strip.split(/[,;:\ \n\t]/).map{|s| s.strip} 423 | end 424 | 425 | end 426 | 427 | end 428 | 429 | end 430 | 431 | # Fake 432 | #module Gem 433 | # class Specification < Hash 434 | # def initialize 435 | # yield(self) 436 | # end 437 | # def method_missing(s,v=nil,*a,&b) 438 | # case s.to_s 439 | # when /=$/ 440 | # self[s.to_s.chomp('=').to_sym] = v 441 | # else 442 | # self[s] 443 | # end 444 | # end 445 | # end 446 | #end 447 | 448 | 449 | --------------------------------------------------------------------------------