libgems 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (177) hide show
  1. data/ChangeLog +5811 -0
  2. data/History.txt +887 -0
  3. data/LICENSE.txt +51 -0
  4. data/README.md +87 -0
  5. data/Rakefile +113 -0
  6. data/lib/gauntlet_libgems.rb +50 -0
  7. data/lib/libgems.rb +1246 -0
  8. data/lib/libgems/builder.rb +102 -0
  9. data/lib/libgems/command.rb +534 -0
  10. data/lib/libgems/command_manager.rb +182 -0
  11. data/lib/libgems/commands/build_command.rb +53 -0
  12. data/lib/libgems/commands/cert_command.rb +86 -0
  13. data/lib/libgems/commands/check_command.rb +80 -0
  14. data/lib/libgems/commands/cleanup_command.rb +106 -0
  15. data/lib/libgems/commands/contents_command.rb +98 -0
  16. data/lib/libgems/commands/dependency_command.rb +195 -0
  17. data/lib/libgems/commands/environment_command.rb +133 -0
  18. data/lib/libgems/commands/fetch_command.rb +67 -0
  19. data/lib/libgems/commands/generate_index_command.rb +133 -0
  20. data/lib/libgems/commands/help_command.rb +172 -0
  21. data/lib/libgems/commands/install_command.rb +178 -0
  22. data/lib/libgems/commands/list_command.rb +35 -0
  23. data/lib/libgems/commands/lock_command.rb +110 -0
  24. data/lib/libgems/commands/mirror_command.rb +111 -0
  25. data/lib/libgems/commands/outdated_command.rb +33 -0
  26. data/lib/libgems/commands/owner_command.rb +75 -0
  27. data/lib/libgems/commands/pristine_command.rb +93 -0
  28. data/lib/libgems/commands/push_command.rb +56 -0
  29. data/lib/libgems/commands/query_command.rb +280 -0
  30. data/lib/libgems/commands/rdoc_command.rb +91 -0
  31. data/lib/libgems/commands/search_command.rb +31 -0
  32. data/lib/libgems/commands/server_command.rb +86 -0
  33. data/lib/libgems/commands/sources_command.rb +157 -0
  34. data/lib/libgems/commands/specification_command.rb +125 -0
  35. data/lib/libgems/commands/stale_command.rb +27 -0
  36. data/lib/libgems/commands/uninstall_command.rb +83 -0
  37. data/lib/libgems/commands/unpack_command.rb +121 -0
  38. data/lib/libgems/commands/update_command.rb +160 -0
  39. data/lib/libgems/commands/which_command.rb +86 -0
  40. data/lib/libgems/config_file.rb +345 -0
  41. data/lib/libgems/custom_require.rb +44 -0
  42. data/lib/libgems/defaults.rb +101 -0
  43. data/lib/libgems/dependency.rb +227 -0
  44. data/lib/libgems/dependency_installer.rb +286 -0
  45. data/lib/libgems/dependency_list.rb +208 -0
  46. data/lib/libgems/doc_manager.rb +242 -0
  47. data/lib/libgems/errors.rb +35 -0
  48. data/lib/libgems/exceptions.rb +91 -0
  49. data/lib/libgems/ext.rb +18 -0
  50. data/lib/libgems/ext/builder.rb +56 -0
  51. data/lib/libgems/ext/configure_builder.rb +25 -0
  52. data/lib/libgems/ext/ext_conf_builder.rb +24 -0
  53. data/lib/libgems/ext/rake_builder.rb +39 -0
  54. data/lib/libgems/format.rb +81 -0
  55. data/lib/libgems/gem_openssl.rb +92 -0
  56. data/lib/libgems/gem_path_searcher.rb +100 -0
  57. data/lib/libgems/gem_runner.rb +79 -0
  58. data/lib/libgems/gemcutter_utilities.rb +49 -0
  59. data/lib/libgems/indexer.rb +720 -0
  60. data/lib/libgems/install_update_options.rb +125 -0
  61. data/lib/libgems/installer.rb +604 -0
  62. data/lib/libgems/local_remote_options.rb +135 -0
  63. data/lib/libgems/old_format.rb +153 -0
  64. data/lib/libgems/package.rb +97 -0
  65. data/lib/libgems/package/f_sync_dir.rb +23 -0
  66. data/lib/libgems/package/tar_header.rb +266 -0
  67. data/lib/libgems/package/tar_input.rb +222 -0
  68. data/lib/libgems/package/tar_output.rb +144 -0
  69. data/lib/libgems/package/tar_reader.rb +106 -0
  70. data/lib/libgems/package/tar_reader/entry.rb +141 -0
  71. data/lib/libgems/package/tar_writer.rb +241 -0
  72. data/lib/libgems/package_task.rb +126 -0
  73. data/lib/libgems/platform.rb +183 -0
  74. data/lib/libgems/remote_fetcher.rb +414 -0
  75. data/lib/libgems/require_paths_builder.rb +18 -0
  76. data/lib/libgems/requirement.rb +153 -0
  77. data/lib/libgems/security.rb +814 -0
  78. data/lib/libgems/server.rb +872 -0
  79. data/lib/libgems/source_index.rb +597 -0
  80. data/lib/libgems/source_info_cache.rb +395 -0
  81. data/lib/libgems/source_info_cache_entry.rb +56 -0
  82. data/lib/libgems/spec_fetcher.rb +337 -0
  83. data/lib/libgems/specification.rb +1487 -0
  84. data/lib/libgems/test_utilities.rb +147 -0
  85. data/lib/libgems/text.rb +65 -0
  86. data/lib/libgems/uninstaller.rb +278 -0
  87. data/lib/libgems/user_interaction.rb +527 -0
  88. data/lib/libgems/validator.rb +240 -0
  89. data/lib/libgems/version.rb +316 -0
  90. data/lib/libgems/version_option.rb +65 -0
  91. data/lib/rbconfig/datadir.rb +20 -0
  92. data/test/bogussources.rb +8 -0
  93. data/test/data/gem-private_key.pem +27 -0
  94. data/test/data/gem-public_cert.pem +20 -0
  95. data/test/fake_certlib/openssl.rb +7 -0
  96. data/test/foo/discover.rb +0 -0
  97. data/test/gem_installer_test_case.rb +97 -0
  98. data/test/gem_package_tar_test_case.rb +132 -0
  99. data/test/gemutilities.rb +605 -0
  100. data/test/insure_session.rb +43 -0
  101. data/test/mockgemui.rb +56 -0
  102. data/test/plugin/exception/libgems_plugin.rb +2 -0
  103. data/test/plugin/load/libgems_plugin.rb +1 -0
  104. data/test/plugin/standarderror/libgems_plugin.rb +2 -0
  105. data/test/private_key.pem +27 -0
  106. data/test/public_cert.pem +20 -0
  107. data/test/rubygems_plugin.rb +21 -0
  108. data/test/simple_gem.rb +66 -0
  109. data/test/test_config.rb +12 -0
  110. data/test/test_gem.rb +780 -0
  111. data/test/test_gem_builder.rb +27 -0
  112. data/test/test_gem_command.rb +178 -0
  113. data/test/test_gem_command_manager.rb +207 -0
  114. data/test/test_gem_commands_build_command.rb +74 -0
  115. data/test/test_gem_commands_cert_command.rb +124 -0
  116. data/test/test_gem_commands_check_command.rb +18 -0
  117. data/test/test_gem_commands_contents_command.rb +156 -0
  118. data/test/test_gem_commands_dependency_command.rb +216 -0
  119. data/test/test_gem_commands_environment_command.rb +144 -0
  120. data/test/test_gem_commands_fetch_command.rb +76 -0
  121. data/test/test_gem_commands_generate_index_command.rb +135 -0
  122. data/test/test_gem_commands_install_command.rb +315 -0
  123. data/test/test_gem_commands_list_command.rb +36 -0
  124. data/test/test_gem_commands_lock_command.rb +68 -0
  125. data/test/test_gem_commands_mirror_command.rb +60 -0
  126. data/test/test_gem_commands_outdated_command.rb +40 -0
  127. data/test/test_gem_commands_owner_command.rb +105 -0
  128. data/test/test_gem_commands_pristine_command.rb +108 -0
  129. data/test/test_gem_commands_push_command.rb +81 -0
  130. data/test/test_gem_commands_query_command.rb +426 -0
  131. data/test/test_gem_commands_server_command.rb +59 -0
  132. data/test/test_gem_commands_sources_command.rb +209 -0
  133. data/test/test_gem_commands_specification_command.rb +139 -0
  134. data/test/test_gem_commands_stale_command.rb +38 -0
  135. data/test/test_gem_commands_uninstall_command.rb +83 -0
  136. data/test/test_gem_commands_unpack_command.rb +199 -0
  137. data/test/test_gem_commands_update_command.rb +207 -0
  138. data/test/test_gem_commands_which_command.rb +66 -0
  139. data/test/test_gem_config_file.rb +287 -0
  140. data/test/test_gem_dependency.rb +149 -0
  141. data/test/test_gem_dependency_installer.rb +661 -0
  142. data/test/test_gem_dependency_list.rb +230 -0
  143. data/test/test_gem_doc_manager.rb +31 -0
  144. data/test/test_gem_ext_configure_builder.rb +84 -0
  145. data/test/test_gem_ext_ext_conf_builder.rb +173 -0
  146. data/test/test_gem_ext_rake_builder.rb +81 -0
  147. data/test/test_gem_format.rb +70 -0
  148. data/test/test_gem_gem_path_searcher.rb +78 -0
  149. data/test/test_gem_gem_runner.rb +45 -0
  150. data/test/test_gem_gemcutter_utilities.rb +103 -0
  151. data/test/test_gem_indexer.rb +673 -0
  152. data/test/test_gem_install_update_options.rb +68 -0
  153. data/test/test_gem_installer.rb +857 -0
  154. data/test/test_gem_local_remote_options.rb +97 -0
  155. data/test/test_gem_package_tar_header.rb +130 -0
  156. data/test/test_gem_package_tar_input.rb +112 -0
  157. data/test/test_gem_package_tar_output.rb +97 -0
  158. data/test/test_gem_package_tar_reader.rb +46 -0
  159. data/test/test_gem_package_tar_reader_entry.rb +109 -0
  160. data/test/test_gem_package_tar_writer.rb +144 -0
  161. data/test/test_gem_package_task.rb +59 -0
  162. data/test/test_gem_platform.rb +264 -0
  163. data/test/test_gem_remote_fetcher.rb +740 -0
  164. data/test/test_gem_requirement.rb +292 -0
  165. data/test/test_gem_server.rb +356 -0
  166. data/test/test_gem_silent_ui.rb +113 -0
  167. data/test/test_gem_source_index.rb +461 -0
  168. data/test/test_gem_spec_fetcher.rb +410 -0
  169. data/test/test_gem_specification.rb +1334 -0
  170. data/test/test_gem_stream_ui.rb +218 -0
  171. data/test/test_gem_text.rb +43 -0
  172. data/test/test_gem_uninstaller.rb +146 -0
  173. data/test/test_gem_validator.rb +63 -0
  174. data/test/test_gem_version.rb +181 -0
  175. data/test/test_gem_version_option.rb +89 -0
  176. data/test/test_kernel.rb +59 -0
  177. metadata +402 -0
@@ -0,0 +1,51 @@
1
+ RubyGems (and SlimGems) is copyrighted free software by Chad Fowler, Rich Kilmer,
2
+ Jim Weirich and others. You can redistribute it under the conditions below:
3
+
4
+ 1. You may make and give away verbatim copies of the source form of the
5
+ software without restriction, provided that you duplicate all of the
6
+ original copyright notices and associated disclaimers.
7
+
8
+ 2. You may modify your copy of the software in any way, provided that
9
+ you do at least ONE of the following:
10
+
11
+ a) place your modifications in the Public Domain or otherwise
12
+ make them Freely Available, such as by posting said
13
+ modifications to Usenet or an equivalent medium, or by allowing
14
+ the author to include your modifications in the software.
15
+
16
+ b) use the modified software only within your corporation or
17
+ organization.
18
+
19
+ c) rename any non-standard executables so the names do not conflict
20
+ with standard executables, which must also be provided.
21
+
22
+ d) make other distribution arrangements with the author.
23
+
24
+ 3. You may distribute the software in object code or executable
25
+ form, provided that you do at least ONE of the following:
26
+
27
+ a) distribute the executables and library files of the software,
28
+ together with instructions (in the manual page or equivalent)
29
+ on where to get the original distribution.
30
+
31
+ b) accompany the distribution with the machine-readable source of
32
+ the software.
33
+
34
+ c) give non-standard executables non-standard names, with
35
+ instructions on where to get the original software distribution.
36
+
37
+ d) make other distribution arrangements with the author.
38
+
39
+ 4. You may modify and include the part of the software into any other
40
+ software (possibly commercial).
41
+
42
+ 5. The scripts and library files supplied as input to or produced as
43
+ output from the software do not automatically fall under the
44
+ copyright of the software, but belong to whomever generated them,
45
+ and may be sold commercially, and may be aggregated with this
46
+ software.
47
+
48
+ 6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
49
+ IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
50
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
51
+ PURPOSE.
@@ -0,0 +1,87 @@
1
+ # SlimGems
2
+
3
+ * Website: http://slimgems.github.com/
4
+ * Github: http://github.com/slimgems/slimgems
5
+ * Get gems from: http://rubygems.org
6
+
7
+ ## Description
8
+
9
+ SlimGems is a drop-in replacement for RubyGems, a package management framework
10
+ for Ruby. We forked the project at 1.3.7, which was a great stable release.
11
+
12
+ SlimGems focuses on maintaining a sane and stable API. We believe that the
13
+ project has been put through enough stress testing by the community to lock
14
+ into the current API functionality for the forseeable future. We will also
15
+ continue to improve the runtime performance over time; we can do this
16
+ without changing the API.
17
+
18
+ ## Project Goals
19
+
20
+ 1. A fast package manager that "Just Works". We will attempt to make SlimGems
21
+ as fast as possible and believe it can be done without breaking the existing
22
+ API.
23
+
24
+ 2. A consistent and stable API. Deprecations will not occur without ample
25
+ warning to library developers *before* a release. Deprecations will not
26
+ necessarily mean removed methods or runtime warnings, and we will consult
27
+ with the community if widely used APIs ever need to be removed.
28
+
29
+ 3. Receptive and friendly project maintainers. We will listen to your bugs
30
+ and suggestions without deriding you. We believe the community deserves
31
+ a voice in matters that affect package management tools, and we respect
32
+ that voice.
33
+
34
+ 4. Improved communication with the community about future plans. We believe
35
+ it's important to keep the community informed about major changes. We will
36
+ discuss our rationale for any changes that might cause problems for other
37
+ library developers.
38
+
39
+ ## What Do I Have to do Differently to Use SlimGems?
40
+
41
+ Nothing. We maintain the same install paths, APIs and overall runtime environment
42
+ that RubyGems had. The only difference is that we have no intention on changing
43
+ this environment in future upgrades. You can upgrade safely knowing that the
44
+ newer versions of SlimGems will still be compatible with all of your code.
45
+
46
+ In short, yes, "require 'libgems'" still works.
47
+
48
+ ## Installing and Upgrading
49
+
50
+ If you're on RubyGems, you can easily upgrade to SlimGems by typing:
51
+
52
+ $ gem install slimgems
53
+
54
+ You can do this from SlimGems too, but if you have SlimGems already, upgrading
55
+ works better with:
56
+
57
+ $ gem update --system
58
+
59
+ If you don't have any RubyGems or SlimGems install, there is still the pre-gem
60
+ approach to getting software, doing it manually:
61
+
62
+ 1. Download from: http://github.com/slimgems/slimgems
63
+ 2. Unpack into a directory and cd there
64
+ 3. Install with: ruby setup.rb # you may need admin/root privilege
65
+
66
+ For more details and other options, see:
67
+
68
+ ruby setup.rb --help
69
+
70
+ ## Uninstalling
71
+
72
+ If SlimGems isn't for you, you can downgrade back to RubyGems by performing
73
+ the following intuitive command:
74
+
75
+ $ gem uninstall slimgems
76
+
77
+ Again, you might need to have administrator privileges (sudo) to run these
78
+ commands.
79
+
80
+ ## Notes about this SlimGems Fork
81
+
82
+ SlimGems is a RubyGems fork of RubyGems 1.3.7 and a limited set of backports
83
+ from 1.5.2. SlimGems is maintained by Loren Segal and others. SlimGems will
84
+ provide continual improvements with a stable API.
85
+
86
+ You can download the original RubyGems project at
87
+ http://rubyforge.org/projects/rubygems
@@ -0,0 +1,113 @@
1
+ # -*- ruby -*-
2
+
3
+ $:.unshift 'lib'
4
+
5
+ require 'libgems'
6
+ require 'libgems/package_task'
7
+ require 'rake/testtask'
8
+
9
+ task :default => :test
10
+ Rake::TestTask.new(:test) do |t|
11
+ t.options = '--seed=1'
12
+ t.ruby_opts = ['--disable-gems'] if RUBY_VERSION >= "1.9.1"
13
+ t.test_files = FileList['test/test_*.rb']
14
+ end
15
+
16
+ # These tasks expect to have the following directory structure:
17
+ #
18
+ # git/git.rubini.us/code # Rubinius git HEAD checkout
19
+ # svn/ruby/trunk # ruby subversion HEAD checkout
20
+ # svn/rubygems/trunk # SlimGems subversion HEAD checkout
21
+ #
22
+ # If you don't have this directory structure, set RUBY_PATH and/or
23
+ # RUBINIUS_PATH.
24
+
25
+ def rsync_with dir
26
+ rsync_options = "-avP --exclude '*svn*' --exclude '*swp' --exclude '*rbc'" +
27
+ " --exclude '*.rej' --exclude '*.orig' --exclude 'lib/libgems/defaults/*'"
28
+ sh "rsync #{rsync_options} bin/gem #{dir}/bin/gem"
29
+ sh "rsync #{rsync_options} lib/ #{dir}/lib"
30
+ sh "rsync #{rsync_options} test/ #{dir}/test/libgems"
31
+ sh "rsync #{rsync_options} util/gem_prelude.rb #{dir}/gem_prelude.rb"
32
+ end
33
+
34
+ def diff_with dir
35
+ diff_options = "-urpN --exclude '*svn*' --exclude '*swp' --exclude '*rbc'"
36
+ sh "diff #{diff_options} bin/gem #{dir}/bin/gem; true"
37
+ sh "diff #{diff_options} lib/ubygems.rb #{dir}/lib/ubygems.rb; true"
38
+ sh "diff #{diff_options} lib/libgems.rb #{dir}/lib/libgems.rb; true"
39
+ sh "diff #{diff_options} lib/libgems #{dir}/lib/libgems; true"
40
+ sh "diff #{diff_options} lib/rbconfig #{dir}/lib/rbconfig; true"
41
+ sh "diff #{diff_options} test #{dir}/test/libgems; true"
42
+ sh "diff #{diff_options} util/gem_prelude.rb #{dir}/gem_prelude.rb; true"
43
+ end
44
+
45
+ rubinius_dir = ENV['RUBINIUS_PATH'] || '../../../git/git.rubini.us/code'
46
+ ruby_dir = ENV['RUBY_PATH'] || '../../ruby/trunk'
47
+
48
+ desc "Updates Ruby HEAD with the currently checked-out copy."
49
+ task :update_ruby do
50
+ rsync_with ruby_dir
51
+ end
52
+
53
+ desc "Updates Rubinius HEAD with the currently checked-out copy."
54
+ task :update_rubinius do
55
+ rsync_with rubinius_dir
56
+ end
57
+
58
+ desc "Diffs Ruby HEAD with the currently checked-out copy."
59
+ task :diff_ruby do
60
+ diff_with ruby_dir
61
+ end
62
+
63
+ desc "Diffs Rubinius HEAD with the currently checked-out copy."
64
+ task :diff_rubinius do
65
+ diff_with rubinius_dir
66
+ end
67
+
68
+ desc "Get coverage for a specific test."
69
+ task "rcov:for", [:test] do |task, args|
70
+ mgem = LibGems.source_index.find_name("minitest").first rescue nil
71
+ rgem = LibGems.source_index.find_name(/rcov/).first
72
+ libs = rgem.require_paths.map { |p| File.join rgem.full_gem_path, p }
73
+ rcov = File.join rgem.full_gem_path, rgem.bindir, rgem.default_executable
74
+
75
+ if mgem
76
+ libs << mgem.require_paths.map { |p| File.join mgem.full_gem_path, p }
77
+ end
78
+
79
+ libs << "lib:test"
80
+
81
+ flags = []
82
+ flags << "-I" << libs.flatten.join(":")
83
+
84
+ rflags = []
85
+ rflags << "-i" << "lib/libgems"
86
+
87
+ ruby "#{flags.join ' '} #{rcov} #{rflags.join ' '} #{args[:test]}"
88
+ end
89
+
90
+ task :graph do
91
+ $: << File.expand_path("~/Work/p4/zss/src/graph/dev/lib")
92
+ require 'graph'
93
+ deps = Graph.new
94
+ deps.rotate
95
+
96
+ current = nil
97
+ `rake -P -s`.each_line do |line|
98
+ case line
99
+ when /^rake (.+)/
100
+ current = $1
101
+ deps[current] if current # force the node to exist, in case of a leaf
102
+ when /^\s+(.+)/
103
+ deps[current] << $1 if current
104
+ else
105
+ warn "unparsed: #{line.chomp}"
106
+ end
107
+ end
108
+
109
+
110
+ deps.boxes
111
+ deps.save "graph", nil
112
+ end
113
+
@@ -0,0 +1,50 @@
1
+ require 'libgems'
2
+ require 'gauntlet'
3
+
4
+ ##
5
+ # LibGemsGauntlet validates all current gems. Currently these packages are
6
+ # borked:
7
+ #
8
+ # Asami-0.04 : No such file or directory - bin/Asami.rb
9
+ # ObjectGraph-1.0.1 : No such file or directory - bin/objectgraph
10
+ # evil-ruby-0.1.0 : authors must be Array of Strings
11
+ # fresh_cookies-1.0.0 : authors must be Array of Strings
12
+ # plugems_deploy-0.2.0 : authors must be Array of Strings
13
+ # pmsrb-0.2.0 : authors must be Array of Strings
14
+ # pqa-1.6 : authors must be Array of Strings
15
+ # rant-0.5.7 : authors must be Array of Strings
16
+ # rvsh-0.4.5 : No such file or directory - bin/rvsh
17
+ # xen-0.1.2.1 : authors must be Array of Strings
18
+
19
+ class LibGemsGauntlet < Gauntlet
20
+ def run(name)
21
+ warn name
22
+
23
+ spec = begin
24
+ LibGems::Specification.load 'gemspec'
25
+ rescue SyntaxError
26
+ LibGems::Specification.from_yaml File.read('gemspec')
27
+ end
28
+ spec.validate
29
+
30
+ self.data[name] = false
31
+ self.dirty = true
32
+ rescue SystemCallError, LibGems::InvalidSpecificationException => e
33
+ self.data[name] = e.message
34
+ self.dirty = true
35
+ end
36
+
37
+ def should_skip?(name)
38
+ self.data[name] == false
39
+ end
40
+
41
+ def report
42
+ self.data.sort.reject { |k,v| !v }.each do |k,v|
43
+ puts "%-21s: %s" % [k, v]
44
+ end
45
+ end
46
+ end
47
+
48
+ gauntlet = LibGemsGauntlet.new
49
+ gauntlet.run_the_gauntlet ARGV.shift
50
+ gauntlet.report
@@ -0,0 +1,1246 @@
1
+ # -*- ruby -*-
2
+ # Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
3
+ # All rights reserved.
4
+ # See LICENSE.txt for permissions.
5
+
6
+ require 'rubygems'
7
+ require 'libgems/defaults'
8
+ require 'thread'
9
+
10
+ ##
11
+ # SlimGems is the Ruby standard for publishing and managing third party
12
+ # libraries.
13
+ #
14
+ # For user documentation, see:
15
+ #
16
+ # * <tt>gem help</tt> and <tt>gem help [command]</tt>
17
+ # * {SlimGems User Guide}[http://docs.rubygems.org/read/book/1]
18
+ # * {Frequently Asked Questions}[http://docs.rubygems.org/read/book/3]
19
+ #
20
+ # For gem developer documentation see:
21
+ #
22
+ # * {Creating Gems}[http://docs.rubygems.org/read/chapter/5]
23
+ # * LibGems::Specification
24
+ # * LibGems::Version for version dependency notes
25
+ #
26
+ # Further SlimGems documentation can be found at:
27
+ #
28
+ # * {SlimGems API}[http://rubygems.rubyforge.org/rdoc] (also available from
29
+ # <tt>gem server</tt>)
30
+ # * {SlimGems Bookshelf}[http://rubygem.org]
31
+ #
32
+ # == SlimGems Plugins
33
+ #
34
+ # As of #{LibGems::NAME} 1.3.2, SlimGems will load plugins installed in gems or
35
+ # $LOAD_PATH. Plugins must be named 'rubygems_plugin' (.rb, .so, etc) and
36
+ # placed at the root of your gem's #require_path. Plugins are discovered via
37
+ # LibGems::find_files then loaded. Take care when implementing a plugin as your
38
+ # plugin file may be loaded multiple times if multiple versions of your gem
39
+ # are installed.
40
+ #
41
+ # For an example plugin, see the graph gem which adds a `gem graph` command.
42
+ #
43
+ # == SlimGems Defaults, Packaging
44
+ #
45
+ # SlimGems defaults are stored in rubygems/defaults.rb. If you're packaging
46
+ # #{LibGems::NAME} or implementing Ruby you can change SlimGems' defaults.
47
+ #
48
+ # For SlimGems packagers, provide lib/libgems/operating_system.rb and
49
+ # override any defaults from lib/libgems/defaults.rb.
50
+ #
51
+ # For Ruby implementers, provide lib/libgems/#{RUBY_ENGINE}.rb and override
52
+ # any defaults from lib/libgems/defaults.rb.
53
+ #
54
+ # If you need SlimGems to perform extra work on install or uninstall, your
55
+ # defaults override file can set pre and post install and uninstall hooks.
56
+ # See LibGems::pre_install, LibGems::pre_uninstall, LibGems::post_install,
57
+ # LibGems::post_uninstall.
58
+ #
59
+ # == Bugs
60
+ #
61
+ # You can submit bugs to the
62
+ # {SlimGems bug tracker}[http://rubyforge.org/tracker/?atid=575&group_id=126]
63
+ # on RubyForge
64
+ #
65
+ # == Credits
66
+ #
67
+ # SlimGems is currently maintained by Eric Hodel.
68
+ #
69
+ # SlimGems was originally developed at RubyConf 2003 by:
70
+ #
71
+ # * Rich Kilmer -- rich(at)infoether.com
72
+ # * Chad Fowler -- chad(at)chadfowler.com
73
+ # * David Black -- dblack(at)wobblini.net
74
+ # * Paul Brannan -- paul(at)atdesk.com
75
+ # * Jim Weirch -- jim(at)weirichhouse.org
76
+ #
77
+ # Contributors:
78
+ #
79
+ # * Gavin Sinclair -- gsinclair(at)soyabean.com.au
80
+ # * George Marrows -- george.marrows(at)ntlworld.com
81
+ # * Dick Davies -- rasputnik(at)hellooperator.net
82
+ # * Mauricio Fernandez -- batsman.geo(at)yahoo.com
83
+ # * Simon Strandgaard -- neoneye(at)adslhome.dk
84
+ # * Dave Glasser -- glasser(at)mit.edu
85
+ # * Paul Duncan -- pabs(at)pablotron.org
86
+ # * Ville Aine -- vaine(at)cs.helsinki.fi
87
+ # * Eric Hodel -- drbrain(at)segment7.net
88
+ # * Daniel Berger -- djberg96(at)gmail.com
89
+ # * Phil Hagelberg -- technomancy(at)gmail.com
90
+ # * Ryan Davis -- ryand-ruby(at)zenspider.com
91
+ #
92
+ # (If your name is missing, PLEASE let us know!)
93
+ #
94
+ # Thanks!
95
+ #
96
+ # -The SlimGems Team
97
+
98
+ module LibGems
99
+ NAME = 'LibGems'
100
+ GEM_NAME = 'libgems'
101
+ VERSION = '0.0.1'
102
+ GEM_VERSION = '1.3.8'
103
+
104
+ ##
105
+ # Raised when SlimGems is unable to load or activate a gem. Contains the
106
+ # name and version requirements of the gem that either conflicts with
107
+ # already activated gems or that SlimGems is otherwise unable to activate.
108
+
109
+ class LoadError < ::LoadError
110
+ # Name of gem
111
+ attr_accessor :name
112
+
113
+ # Version requirement of gem
114
+ attr_accessor :version_requirement
115
+ end
116
+
117
+ ##
118
+ # Configuration settings from ::RbConfig
119
+
120
+ ConfigMap = {} unless defined?(ConfigMap)
121
+
122
+ require 'rbconfig'
123
+
124
+ ConfigMap.merge!(
125
+ :EXEEXT => RbConfig::CONFIG["EXEEXT"],
126
+ :RUBY_SO_NAME => RbConfig::CONFIG["RUBY_SO_NAME"],
127
+ :arch => RbConfig::CONFIG["arch"],
128
+ :bindir => RbConfig::CONFIG["bindir"],
129
+ :datadir => RbConfig::CONFIG["datadir"],
130
+ :libdir => RbConfig::CONFIG["libdir"],
131
+ :ruby_install_name => RbConfig::CONFIG["ruby_install_name"],
132
+ :ruby_version => RbConfig::CONFIG["ruby_version"],
133
+ :rubylibprefix => RbConfig::CONFIG["rubylibprefix"],
134
+ :sitedir => RbConfig::CONFIG["sitedir"],
135
+ :sitelibdir => RbConfig::CONFIG["sitelibdir"],
136
+ :vendordir => RbConfig::CONFIG["vendordir"] ,
137
+ :vendorlibdir => RbConfig::CONFIG["vendorlibdir"]
138
+ )
139
+
140
+ ##
141
+ # Default directories in a gem repository
142
+
143
+ DIRECTORIES = %w[cache doc gems specifications] unless defined?(DIRECTORIES)
144
+
145
+ RubyGemsPackageVersion = GEM_VERSION
146
+ # :startdoc:
147
+
148
+ ##
149
+ # An Array of Regexps that match windows ruby platforms.
150
+
151
+ WIN_PATTERNS = [
152
+ /bccwin/i,
153
+ /cygwin/i,
154
+ /djgpp/i,
155
+ /mingw/i,
156
+ /mswin/i,
157
+ /wince/i,
158
+ ]
159
+
160
+ @@source_index = nil
161
+ @@win_platform = nil
162
+
163
+ @configuration = nil
164
+ @loaded_specs = {}
165
+ @loaded_stacks = {}
166
+ @platforms = []
167
+ @ruby = nil
168
+ @sources = []
169
+
170
+ @post_build_hooks ||= []
171
+ @post_install_hooks ||= []
172
+ @post_uninstall_hooks ||= []
173
+ @pre_uninstall_hooks ||= []
174
+ @pre_install_hooks ||= []
175
+
176
+ ##
177
+ # Specialized eval for gemspecs that sets Gem to LibGems
178
+
179
+ def self.gemspec_eval(str, *args)
180
+ eval(<<-end_eval, *args)
181
+ begin
182
+ libgems_original_gem = nil
183
+ if Object.const_defined?(:Gem)
184
+ libgems_original_gem = Object::Gem
185
+ Object.send(:remove_const, :Gem)
186
+ end
187
+ Object.const_set(:Gem, LibGems)
188
+ #{str}
189
+ ensure
190
+ Object.send(:remove_const, :Gem)
191
+ Object.const_set(:Gem, libgems_original_gem) if libgems_original_gem
192
+ end
193
+ end_eval
194
+ end
195
+
196
+ ##
197
+ # Run code with Gem = LibGems
198
+
199
+ def self.with_rubygems_compat
200
+ libgems_original_gem = nil
201
+ if Object.const_defined?(:Gem)
202
+ libgems_original_gem = Object::Gem
203
+ Object.send(:remove_const, :Gem)
204
+ end
205
+ Object.const_set(:Gem, LibGems)
206
+ yield
207
+ ensure
208
+ Object.send(:remove_const, :Gem)
209
+ Object.const_set(:Gem, libgems_original_gem) if libgems_original_gem
210
+ end
211
+
212
+ ##
213
+ # Activates an installed gem matching +gem+. The gem must satisfy
214
+ # +version_requirements+.
215
+ #
216
+ # Returns true if the gem is activated, false if it is already
217
+ # loaded, or an exception otherwise.
218
+ #
219
+ # LibGems#activate adds the library paths in +gem+ to $LOAD_PATH. Before a LibGems
220
+ # is activated its required Gems are activated. If the version information
221
+ # is omitted, the highest version LibGems of the supplied name is loaded. If a
222
+ # LibGems is not found that meets the version requirements or a required LibGems is
223
+ # not found, a LibGems::LoadError is raised.
224
+ #
225
+ # More information on version requirements can be found in the
226
+ # LibGems::Requirement and LibGems::Version documentation.
227
+
228
+ def self.activate(gem, *version_requirements)
229
+ if version_requirements.last.is_a?(Hash)
230
+ options = version_requirements.pop
231
+ else
232
+ options = {}
233
+ end
234
+
235
+ sources = options[:sources] || []
236
+
237
+ if version_requirements.empty? then
238
+ version_requirements = LibGems::Requirement.default
239
+ end
240
+
241
+ unless gem.respond_to?(:name) and
242
+ gem.respond_to?(:requirement) then
243
+ gem = LibGems::Dependency.new(gem, version_requirements)
244
+ end
245
+
246
+ matches = LibGems.source_index.find_name(gem.name, gem.requirement)
247
+ report_activate_error(gem) if matches.empty?
248
+
249
+ if @loaded_specs[gem.name] then
250
+ # This gem is already loaded. If the currently loaded gem is not in the
251
+ # list of candidate gems, then we have a version conflict.
252
+ existing_spec = @loaded_specs[gem.name]
253
+
254
+ unless matches.any? { |spec| spec.version == existing_spec.version } then
255
+ sources_message = sources.map { |spec| spec.full_name }
256
+ stack_message = @loaded_stacks[gem.name].map { |spec| spec.full_name }
257
+
258
+ msg = "can't activate #{gem} for #{sources_message.inspect}, "
259
+ msg << "already activated #{existing_spec.full_name} for "
260
+ msg << "#{stack_message.inspect}"
261
+
262
+ e = LibGems::LoadError.new msg
263
+ e.name = gem.name
264
+ e.version_requirement = gem.requirement
265
+
266
+ raise e
267
+ end
268
+
269
+ return false
270
+ end
271
+
272
+ # new load
273
+ spec = matches.last
274
+ return false if spec.loaded?
275
+
276
+ spec.loaded = true
277
+ @loaded_specs[spec.name] = spec
278
+ @loaded_stacks[spec.name] = sources.dup
279
+
280
+ # Load dependent gems first
281
+ spec.runtime_dependencies.each do |dep_gem|
282
+ activate dep_gem, :sources => [spec, *sources]
283
+ end
284
+
285
+ # bin directory must come before library directories
286
+ spec.require_paths.unshift spec.bindir if spec.bindir
287
+
288
+ require_paths = spec.require_paths.map do |path|
289
+ File.join spec.full_gem_path, path
290
+ end
291
+
292
+ # gem directories must come after -I and ENV['RUBYLIB']
293
+ insert_index = load_path_insert_index
294
+
295
+ if insert_index then
296
+ # gem directories must come after -I and ENV['RUBYLIB']
297
+ $LOAD_PATH.insert(insert_index, *require_paths)
298
+ else
299
+ # we are probably testing in core, -I and RUBYLIB don't apply
300
+ $LOAD_PATH.unshift(*require_paths)
301
+ end
302
+
303
+ return true
304
+ end
305
+
306
+ ##
307
+ # An Array of all possible load paths for all versions of all gems in the
308
+ # LibGems installation.
309
+
310
+ def self.all_load_paths
311
+ result = []
312
+
313
+ LibGems.path.each do |gemdir|
314
+ each_load_path all_partials(gemdir) do |load_path|
315
+ result << load_path
316
+ end
317
+ end
318
+
319
+ result
320
+ end
321
+
322
+ ##
323
+ # Return all the partial paths in +gemdir+.
324
+
325
+ def self.all_partials(gemdir)
326
+ Dir[File.join(gemdir, 'gems/*')]
327
+ end
328
+
329
+ private_class_method :all_partials
330
+
331
+ ##
332
+ # See if a given gem is available.
333
+
334
+ def self.available?(gem, *requirements)
335
+ requirements = LibGems::Requirement.default if requirements.empty?
336
+
337
+ unless gem.respond_to?(:name) and
338
+ gem.respond_to?(:requirement) then
339
+ gem = LibGems::Dependency.new gem, requirements
340
+ end
341
+
342
+ !LibGems.source_index.search(gem).empty?
343
+ end
344
+
345
+ ##
346
+ # Find the full path to the executable for gem +name+. If the +exec_name+
347
+ # is not given, the gem's default_executable is chosen, otherwise the
348
+ # specified executable's path is returned. +version_requirements+ allows
349
+ # you to specify specific gem versions.
350
+
351
+ def self.bin_path(name, exec_name = nil, *version_requirements)
352
+ version_requirements = LibGems::Requirement.default if
353
+ version_requirements.empty?
354
+ specs = LibGems.source_index.find_name(name, version_requirements)
355
+
356
+ raise LibGems::GemNotFoundException,
357
+ "can't find gem #{name} (#{version_requirements})" if specs.empty?
358
+
359
+ specs = specs.find_all do |spec|
360
+ spec.executables.include?(exec_name)
361
+ end if exec_name
362
+
363
+ unless spec = specs.last
364
+ msg = "can't find gem #{name} (#{version_requirements}) with executable #{exec_name}"
365
+ raise LibGems::GemNotFoundException, msg
366
+ end
367
+
368
+ exec_name ||= spec.default_executable
369
+
370
+ unless exec_name
371
+ msg = "no default executable for #{spec.full_name} and none given"
372
+ raise LibGems::Exception, msg
373
+ end
374
+
375
+ File.join(spec.full_gem_path, spec.bindir, exec_name)
376
+ end
377
+
378
+ ##
379
+ # The mode needed to read a file as straight binary.
380
+
381
+ def self.binary_mode
382
+ 'rb'
383
+ end
384
+
385
+ ##
386
+ # The path where gem executables are to be installed.
387
+
388
+ def self.bindir(install_dir=LibGems.dir)
389
+ return File.join(install_dir, 'bin') unless
390
+ install_dir.to_s == LibGems.default_dir
391
+ LibGems.default_bindir
392
+ end
393
+
394
+ ##
395
+ # Reset the +dir+ and +path+ values. The next time +dir+ or +path+
396
+ # is requested, the values will be calculated from scratch. This is
397
+ # mainly used by the unit tests to provide test isolation.
398
+
399
+ def self.clear_paths
400
+ @gem_home = nil
401
+ @gem_path = nil
402
+ @user_home = nil
403
+
404
+ @@source_index = nil
405
+
406
+ @searcher = nil
407
+ end
408
+
409
+ ##
410
+ # The path to standard location of the user's .gemrc file.
411
+
412
+ def self.config_file
413
+ File.join LibGems.user_home, '.gemrc'
414
+ end
415
+
416
+ ##
417
+ # The standard configuration object for gems.
418
+
419
+ def self.configuration
420
+ @configuration ||= LibGems::ConfigFile.new []
421
+ end
422
+
423
+ ##
424
+ # Use the given configuration object (which implements the ConfigFile
425
+ # protocol) as the standard configuration object.
426
+
427
+ def self.configuration=(config)
428
+ @configuration = config
429
+ end
430
+
431
+ ##
432
+ # The path the the data directory specified by the gem name. If the
433
+ # package is not available as a gem, return nil.
434
+
435
+ def self.datadir(gem_name)
436
+ spec = @loaded_specs[gem_name]
437
+ return nil if spec.nil?
438
+ File.join(spec.full_gem_path, 'data', gem_name)
439
+ end
440
+
441
+ ##
442
+ # A Zlib::Deflate.deflate wrapper
443
+
444
+ def self.deflate(data)
445
+ require 'zlib'
446
+ Zlib::Deflate.deflate data
447
+ end
448
+
449
+ ##
450
+ # The path where gems are to be installed.
451
+
452
+ def self.dir
453
+ @gem_home ||= nil
454
+ set_home(ENV['LIBGEMS_HOME'] || ENV['GEM_HOME'] || LibGems.configuration.home || default_dir) unless @gem_home
455
+ @gem_home
456
+ end
457
+
458
+ ##
459
+ # Expand each partial gem path with each of the required paths specified
460
+ # in the LibGems spec. Each expanded path is yielded.
461
+
462
+ def self.each_load_path(partials)
463
+ partials.each do |gp|
464
+ base = File.basename(gp)
465
+ specfn = File.join(dir, "specifications", base + ".gemspec")
466
+ if File.exist?(specfn)
467
+ spec = gemspec_eval(File.read(specfn))
468
+ spec.require_paths.each do |rp|
469
+ yield(File.join(gp, rp))
470
+ end
471
+ else
472
+ filename = File.join(gp, 'lib')
473
+ yield(filename) if File.exist?(filename)
474
+ end
475
+ end
476
+ end
477
+
478
+ private_class_method :each_load_path
479
+
480
+ ##
481
+ # Quietly ensure the named LibGems directory contains all the proper
482
+ # subdirectories. If we can't create a directory due to a permission
483
+ # problem, then we will silently continue.
484
+
485
+ def self.ensure_gem_subdirectories(gemdir)
486
+ require 'fileutils'
487
+
488
+ LibGems::DIRECTORIES.each do |filename|
489
+ fn = File.join gemdir, filename
490
+ FileUtils.mkdir_p fn rescue nil unless File.exist? fn
491
+ end
492
+ end
493
+
494
+ ##
495
+ # Returns a list of paths matching +glob+ that can be used by a gem to pick
496
+ # up features from other gems. For example:
497
+ #
498
+ # LibGems.find_files('rdoc/discover').each do |path| load path end
499
+ #
500
+ # if +check_load_path+ is true (the default), then find_files also searches
501
+ # $LOAD_PATH for files as well as gems.
502
+ #
503
+ # Note that find_files will return all files even if they are from different
504
+ # versions of the same gem.
505
+
506
+ def self.find_files(glob, check_load_path=true)
507
+ files = []
508
+
509
+ if check_load_path
510
+ files = $LOAD_PATH.map { |load_path|
511
+ Dir["#{File.expand_path glob, load_path}#{LibGems.suffix_pattern}"]
512
+ }.flatten.select { |file| File.file? file.untaint }
513
+ end
514
+
515
+ specs = searcher.find_all glob
516
+
517
+ specs.each do |spec|
518
+ files.concat searcher.matching_files(spec, glob)
519
+ end
520
+
521
+ # $LOAD_PATH might contain duplicate entries or reference
522
+ # the spec dirs directly, so we prune.
523
+ files.uniq! if check_load_path
524
+
525
+ return files
526
+ end
527
+
528
+ ##
529
+ # Finds the user's home directory.
530
+ #--
531
+ # Some comments from the ruby-talk list regarding finding the home
532
+ # directory:
533
+ #
534
+ # I have HOME, USERPROFILE and HOMEDRIVE + HOMEPATH. Ruby seems
535
+ # to be depending on HOME in those code samples. I propose that
536
+ # it should fallback to USERPROFILE and HOMEDRIVE + HOMEPATH (at
537
+ # least on Win32).
538
+
539
+ def self.find_home
540
+ unless RUBY_VERSION > '1.9' then
541
+ ['HOME', 'USERPROFILE'].each do |homekey|
542
+ return File.expand_path(ENV[homekey]) if ENV[homekey]
543
+ end
544
+
545
+ if ENV['HOMEDRIVE'] && ENV['HOMEPATH'] then
546
+ return File.expand_path("#{ENV['HOMEDRIVE']}#{ENV['HOMEPATH']}")
547
+ end
548
+ end
549
+
550
+ File.expand_path "~"
551
+ rescue
552
+ if File::ALT_SEPARATOR then
553
+ drive = ENV['HOMEDRIVE'] || ENV['SystemDrive']
554
+ File.join(drive.to_s, '/')
555
+ else
556
+ "/"
557
+ end
558
+ end
559
+
560
+ private_class_method :find_home
561
+
562
+ ##
563
+ # Zlib::GzipReader wrapper that unzips +data+.
564
+
565
+ def self.gunzip(data)
566
+ require 'stringio'
567
+ require 'zlib'
568
+ data = StringIO.new data
569
+
570
+ Zlib::GzipReader.new(data).read
571
+ end
572
+
573
+ ##
574
+ # Zlib::GzipWriter wrapper that zips +data+.
575
+
576
+ def self.gzip(data)
577
+ require 'stringio'
578
+ require 'zlib'
579
+ zipped = StringIO.new
580
+
581
+ Zlib::GzipWriter.wrap zipped do |io| io.write data end
582
+
583
+ zipped.string
584
+ end
585
+
586
+ ##
587
+ # A Zlib::Inflate#inflate wrapper
588
+
589
+ def self.inflate(data)
590
+ require 'zlib'
591
+ Zlib::Inflate.inflate data
592
+ end
593
+
594
+ ##
595
+ # Get the default SlimGems API host. This is normally
596
+ # <tt>https://rubygems.org</tt>.
597
+
598
+ def self.host
599
+ @host ||= "https://rubygems.org"
600
+ end
601
+
602
+ ## Set the default SlimGems API host.
603
+
604
+ def self.host= host
605
+ @host = host
606
+ end
607
+
608
+ ##
609
+ # Return a list of all possible load paths for the latest version for all
610
+ # gems in the LibGems installation.
611
+
612
+ def self.latest_load_paths
613
+ result = []
614
+
615
+ LibGems.path.each do |gemdir|
616
+ each_load_path(latest_partials(gemdir)) do |load_path|
617
+ result << load_path
618
+ end
619
+ end
620
+
621
+ result
622
+ end
623
+
624
+ ##
625
+ # Return only the latest partial paths in the given +gemdir+.
626
+
627
+ def self.latest_partials(gemdir)
628
+ latest = {}
629
+ all_partials(gemdir).each do |gp|
630
+ base = File.basename(gp)
631
+ if base =~ /(.*)-((\d+\.)*\d+)/ then
632
+ name, version = $1, $2
633
+ ver = LibGems::Version.new(version)
634
+ if latest[name].nil? || ver > latest[name][0]
635
+ latest[name] = [ver, gp]
636
+ end
637
+ end
638
+ end
639
+ latest.collect { |k,v| v[1] }
640
+ end
641
+
642
+ private_class_method :latest_partials
643
+
644
+ ##
645
+ # The index to insert activated gem paths into the $LOAD_PATH.
646
+ #
647
+ # Defaults to the site lib directory unless gem_prelude.rb has loaded paths,
648
+ # then it inserts the activated gem's paths before the gem_prelude.rb paths
649
+ # so you can override the gem_prelude.rb default $LOAD_PATH paths.
650
+
651
+ def self.load_path_insert_index
652
+ index = $LOAD_PATH.index ConfigMap[:sitelibdir]
653
+ end
654
+
655
+ def self.remove_prelude_paths
656
+ LibGems::QuickLoader::GemLoadPaths.each do |path|
657
+ $LOAD_PATH.delete(path)
658
+ end
659
+ end
660
+
661
+ ##
662
+ # Loads YAML, preferring Psych
663
+
664
+ def self.load_yaml
665
+ require 'psych'
666
+ rescue ::LoadError
667
+ ensure
668
+ require 'yaml'
669
+ end
670
+
671
+ ##
672
+ # The file name and line number of the caller of the caller of this method.
673
+
674
+ def self.location_of_caller
675
+ caller[1] =~ /(.*?):(\d+).*?$/i
676
+ file = $1
677
+ lineno = $2.to_i
678
+
679
+ [file, lineno]
680
+ end
681
+
682
+ ##
683
+ # The version of the Marshal format for your Ruby.
684
+
685
+ def self.marshal_version
686
+ "#{Marshal::MAJOR_VERSION}.#{Marshal::MINOR_VERSION}"
687
+ end
688
+
689
+ ##
690
+ # Array of paths to search for Gems.
691
+
692
+ def self.path
693
+ @gem_path ||= nil
694
+
695
+ unless @gem_path then
696
+ paths = [ENV['LIBGEMS_PATH'] || ENV['GEM_PATH'] || LibGems.configuration.path || default_path]
697
+
698
+ if defined?(APPLE_GEM_HOME) and not ENV['GEM_PATH'] then
699
+ paths << APPLE_GEM_HOME
700
+ end
701
+
702
+ set_paths paths.compact.join(File::PATH_SEPARATOR)
703
+ end
704
+
705
+ @gem_path
706
+ end
707
+
708
+ ##
709
+ # Set array of platforms this SlimGems supports (primarily for testing).
710
+
711
+ def self.platforms=(platforms)
712
+ @platforms = platforms
713
+ end
714
+
715
+ ##
716
+ # Array of platforms this SlimGems supports.
717
+
718
+ def self.platforms
719
+ @platforms ||= []
720
+ if @platforms.empty?
721
+ @platforms = [LibGems::Platform::RUBY, LibGems::Platform.local]
722
+ end
723
+ @platforms
724
+ end
725
+
726
+ ##
727
+ # Adds a post-build hook that will be passed an LibGems::Installer instance
728
+ # when LibGems::Installer#install is called. The hook is called after the gem
729
+ # has been extracted and extensions have been built but before the
730
+ # executables or gemspec has been written. If the hook returns +false+ then
731
+ # the gem's files will be removed and the install will be aborted.
732
+
733
+ def self.post_build(&hook)
734
+ @post_build_hooks << hook
735
+ end
736
+
737
+ ##
738
+ # Adds a post-install hook that will be passed an LibGems::Installer instance
739
+ # when LibGems::Installer#install is called
740
+
741
+ def self.post_install(&hook)
742
+ @post_install_hooks << hook
743
+ end
744
+
745
+ ##
746
+ # Adds a post-uninstall hook that will be passed a LibGems::Uninstaller instance
747
+ # and the spec that was uninstalled when LibGems::Uninstaller#uninstall is
748
+ # called
749
+
750
+ def self.post_uninstall(&hook)
751
+ @post_uninstall_hooks << hook
752
+ end
753
+
754
+ ##
755
+ # Adds a pre-install hook that will be passed an LibGems::Installer instance
756
+ # when LibGems::Installer#install is called
757
+
758
+ def self.pre_install(&hook)
759
+ @pre_install_hooks << hook
760
+ end
761
+
762
+ ##
763
+ # Adds a pre-uninstall hook that will be passed an LibGems::Uninstaller instance
764
+ # and the spec that will be uninstalled when LibGems::Uninstaller#uninstall is
765
+ # called
766
+
767
+ def self.pre_uninstall(&hook)
768
+ @pre_uninstall_hooks << hook
769
+ end
770
+
771
+ ##
772
+ # The directory prefix this SlimGems was installed at.
773
+
774
+ def self.prefix
775
+ dir = File.dirname File.expand_path(__FILE__)
776
+ prefix = File.dirname dir
777
+
778
+ if prefix == File.expand_path(ConfigMap[:sitelibdir]) or
779
+ prefix == File.expand_path(ConfigMap[:libdir]) or
780
+ 'lib' != File.basename(dir) then
781
+ nil
782
+ else
783
+ prefix
784
+ end
785
+ end
786
+
787
+ ##
788
+ # Promotes the load paths of the +gem_name+ over the load paths of
789
+ # +over_name+. Useful for allowing one gem to override features in another
790
+ # using #find_files.
791
+
792
+ def self.promote_load_path(gem_name, over_name)
793
+ gem = LibGems.loaded_specs[gem_name]
794
+ over = LibGems.loaded_specs[over_name]
795
+
796
+ raise ArgumentError, "gem #{gem_name} is not activated" if gem.nil?
797
+ raise ArgumentError, "gem #{over_name} is not activated" if over.nil?
798
+
799
+ last_gem_path = File.join gem.full_gem_path, gem.require_paths.last
800
+
801
+ over_paths = over.require_paths.map do |path|
802
+ File.join over.full_gem_path, path
803
+ end
804
+
805
+ over_paths.each do |path|
806
+ $LOAD_PATH.delete path
807
+ end
808
+
809
+ gem = $LOAD_PATH.index(last_gem_path) + 1
810
+
811
+ $LOAD_PATH.insert(gem, *over_paths)
812
+ end
813
+
814
+ ##
815
+ # Refresh source_index from disk and clear searcher.
816
+
817
+ def self.refresh
818
+ source_index.refresh!
819
+
820
+ @searcher = nil
821
+ end
822
+
823
+ ##
824
+ # Safely read a file in binary mode on all platforms.
825
+
826
+ def self.read_binary(path)
827
+ File.open path, binary_mode do |f| f.read end
828
+ end
829
+
830
+ ##
831
+ # Report a load error during activation. The message of load error
832
+ # depends on whether it was a version mismatch or if there are not gems of
833
+ # any version by the requested name.
834
+
835
+ def self.report_activate_error(gem)
836
+ matches = LibGems.source_index.find_name(gem.name)
837
+
838
+ if matches.empty? then
839
+ error = LibGems::LoadError.new(
840
+ "Could not find RubyGem #{gem.name} (#{gem.requirement})\n")
841
+ else
842
+ error = LibGems::LoadError.new(
843
+ "RubyGem version error: " +
844
+ "#{gem.name}(#{matches.first.version} not #{gem.requirement})\n")
845
+ end
846
+
847
+ error.name = gem.name
848
+ error.version_requirement = gem.requirement
849
+ raise error
850
+ end
851
+
852
+ private_class_method :report_activate_error
853
+
854
+ ##
855
+ # Full path to +libfile+ in +gemname+. Searches for the latest gem unless
856
+ # +requirements+ is given.
857
+
858
+ def self.required_location(gemname, libfile, *requirements)
859
+ requirements = LibGems::Requirement.default if requirements.empty?
860
+
861
+ matches = LibGems.source_index.find_name gemname, requirements
862
+
863
+ return nil if matches.empty?
864
+
865
+ spec = matches.last
866
+ spec.require_paths.each do |path|
867
+ result = File.join spec.full_gem_path, path, libfile
868
+ return result if File.exist? result
869
+ end
870
+
871
+ nil
872
+ end
873
+
874
+ ##
875
+ # The path to the running Ruby interpreter.
876
+
877
+ def self.ruby
878
+ if @ruby.nil? then
879
+ @ruby = File.join(ConfigMap[:bindir],
880
+ ConfigMap[:ruby_install_name])
881
+ @ruby << ConfigMap[:EXEEXT]
882
+
883
+ # escape string in case path to ruby executable contain spaces.
884
+ @ruby.sub!(/.*\s.*/m, '"\&"')
885
+ end
886
+
887
+ @ruby
888
+ end
889
+
890
+ ##
891
+ # A LibGems::Version for the currently running ruby.
892
+
893
+ def self.ruby_version
894
+ return @ruby_version if defined? @ruby_version
895
+ version = RUBY_VERSION.dup
896
+
897
+ if defined?(RUBY_PATCHLEVEL) && RUBY_PATCHLEVEL != -1 then
898
+ version << ".#{RUBY_PATCHLEVEL}"
899
+ elsif defined?(RUBY_REVISION) then
900
+ version << ".dev.#{RUBY_REVISION}"
901
+ end
902
+
903
+ @ruby_version = LibGems::Version.new version
904
+ end
905
+
906
+ ##
907
+ # The LibGemsPathSearcher object used to search for matching installed gems.
908
+
909
+ def self.searcher
910
+ @searcher ||= LibGems::GemPathSearcher.new
911
+ end
912
+
913
+ ##
914
+ # Set the LibGems home directory (as reported by LibGems.dir).
915
+
916
+ def self.set_home(home)
917
+ home = home.gsub File::ALT_SEPARATOR, File::SEPARATOR if File::ALT_SEPARATOR
918
+ @gem_home = home
919
+ end
920
+
921
+ private_class_method :set_home
922
+
923
+ ##
924
+ # Set the LibGems search path (as reported by LibGems.path).
925
+
926
+ def self.set_paths(gpaths)
927
+ if gpaths
928
+ @gem_path = gpaths.split(File::PATH_SEPARATOR)
929
+
930
+ if File::ALT_SEPARATOR then
931
+ @gem_path.map! do |path|
932
+ path.gsub File::ALT_SEPARATOR, File::SEPARATOR
933
+ end
934
+ end
935
+
936
+ @gem_path << LibGems.dir
937
+ else
938
+ # TODO: should this be LibGems.default_path instead?
939
+ @gem_path = [LibGems.dir]
940
+ end
941
+
942
+ @gem_path.uniq!
943
+ end
944
+
945
+ private_class_method :set_paths
946
+
947
+ ##
948
+ # Returns the LibGems::SourceIndex of specifications that are in the LibGems.path
949
+
950
+ def self.source_index
951
+ @@source_index ||= SourceIndex.from_installed_gems
952
+ end
953
+
954
+ ##
955
+ # Returns an Array of sources to fetch remote gems from. If the sources
956
+ # list is empty, attempts to load the "sources" gem, then uses
957
+ # default_sources if it is not installed.
958
+
959
+ def self.sources
960
+ if !@sources || @sources.empty? then
961
+ @sources = default_sources
962
+ end
963
+
964
+ @sources
965
+ end
966
+
967
+ ##
968
+ # Need to be able to set the sources without calling
969
+ # LibGems.sources.replace since that would cause an infinite loop.
970
+
971
+ def self.sources=(new_sources)
972
+ @sources = new_sources
973
+ end
974
+
975
+ ##
976
+ # Glob pattern for require-able path suffixes.
977
+
978
+ def self.suffix_pattern
979
+ @suffix_pattern ||= "{#{suffixes.join(',')}}"
980
+ end
981
+
982
+ ##
983
+ # Suffixes for require-able paths.
984
+
985
+ def self.suffixes
986
+ ['', '.rb', '.rbw', '.so', '.bundle', '.dll', '.sl', '.jar']
987
+ end
988
+
989
+ ##
990
+ # Prints the amount of time the supplied block takes to run using the debug
991
+ # UI output.
992
+
993
+ def self.time(msg, width = 0, display = LibGems.configuration.verbose)
994
+ now = Time.now
995
+
996
+ value = yield
997
+
998
+ elapsed = Time.now - now
999
+
1000
+ ui.say "%2$*1$s: %3$3.3fs" % [-width, msg, elapsed] if display
1001
+
1002
+ value
1003
+ end
1004
+
1005
+ ##
1006
+ # Lazily loads DefaultUserInteraction and returns the default UI.
1007
+
1008
+ def self.ui
1009
+ require 'libgems/user_interaction'
1010
+
1011
+ LibGems::DefaultUserInteraction.ui
1012
+ end
1013
+
1014
+ ##
1015
+ # Use the +home+ and +paths+ values for LibGems.dir and LibGems.path. Used mainly
1016
+ # by the unit tests to provide environment isolation.
1017
+
1018
+ def self.use_paths(home, paths=[])
1019
+ clear_paths
1020
+ set_home(home) if home
1021
+ set_paths(paths.join(File::PATH_SEPARATOR)) if paths
1022
+ end
1023
+
1024
+ ##
1025
+ # The home directory for the user.
1026
+
1027
+ def self.user_home
1028
+ @user_home ||= find_home
1029
+ end
1030
+
1031
+ ##
1032
+ # Is this a windows platform?
1033
+
1034
+ def self.win_platform?
1035
+ if @@win_platform.nil? then
1036
+ @@win_platform = !!WIN_PATTERNS.find { |r| RUBY_PLATFORM =~ r }
1037
+ end
1038
+
1039
+ @@win_platform
1040
+ end
1041
+
1042
+ ##
1043
+ # Find all 'rubygems_plugin' files and load them
1044
+
1045
+ def self.load_plugin_files(plugins)
1046
+ plugins.each do |plugin|
1047
+
1048
+ # Skip older versions of the LibGemsCutter plugin: Its commands are in
1049
+ # SlimGems proper now.
1050
+
1051
+ next if plugin =~ /gemcutter-0\.[0-3]/
1052
+
1053
+ begin
1054
+ load plugin
1055
+ rescue ::Exception => e
1056
+ details = "#{plugin.inspect}: #{e.message} (#{e.class})"
1057
+ warn "Error loading #{LibGems::NAME} plugin #{details}"
1058
+ end
1059
+ end
1060
+ end
1061
+
1062
+ ##
1063
+ # Find all 'rubygems_plugin' files in installed gems and load them
1064
+
1065
+ def self.load_plugins
1066
+ load_plugin_files(find_files('libgems_plugin', false) + find_files('rubygems_plugin', false))
1067
+ end
1068
+
1069
+ ##
1070
+ # Find all 'rubygems_plugin' files in $LOAD_PATH and load them
1071
+
1072
+ def self.load_env_plugins
1073
+ path = "libgems_plugin"
1074
+
1075
+ files = []
1076
+ $LOAD_PATH.each do |load_path|
1077
+ globbed = Dir["#{File.expand_path path, load_path}#{LibGems.suffix_pattern}"]
1078
+
1079
+ globbed.each do |load_path_file|
1080
+ files << load_path_file if File.file?(load_path_file.untaint)
1081
+ end
1082
+ end
1083
+
1084
+ load_plugin_files files
1085
+ end
1086
+
1087
+ class << self
1088
+
1089
+ ##
1090
+ # Hash of loaded LibGems::Specification keyed by name
1091
+
1092
+ attr_reader :loaded_specs
1093
+
1094
+ ##
1095
+ # The list of hooks to be run before LibGems::Install#install finishes
1096
+ # installation
1097
+
1098
+ attr_reader :post_build_hooks
1099
+
1100
+ ##
1101
+ # The list of hooks to be run before LibGems::Install#install does any work
1102
+
1103
+ attr_reader :post_install_hooks
1104
+
1105
+ ##
1106
+ # The list of hooks to be run before LibGems::Uninstall#uninstall does any
1107
+ # work
1108
+
1109
+ attr_reader :post_uninstall_hooks
1110
+
1111
+ ##
1112
+ # The list of hooks to be run after LibGems::Install#install is finished
1113
+
1114
+ attr_reader :pre_install_hooks
1115
+
1116
+ ##
1117
+ # The list of hooks to be run after LibGems::Uninstall#uninstall is finished
1118
+
1119
+ attr_reader :pre_uninstall_hooks
1120
+
1121
+ # :stopdoc:
1122
+
1123
+ alias cache source_index # an alias for the old name
1124
+
1125
+ # :startdoc:
1126
+
1127
+ end
1128
+
1129
+ ##
1130
+ # Location of Marshal quick gemspecs on remote repositories
1131
+
1132
+ MARSHAL_SPEC_DIR = "quick/Marshal.#{LibGems.marshal_version}/"
1133
+
1134
+ ##
1135
+ # Location of legacy YAML quick gemspecs on remote repositories
1136
+
1137
+ YAML_SPEC_DIR = 'quick/'
1138
+
1139
+ root = ''
1140
+ autoload :Version, 'libgems/version'
1141
+ autoload :Requirement, 'libgems/requirement'
1142
+ autoload :Dependency, 'libgems/dependency'
1143
+ autoload :GemPathSearcher, 'libgems/gem_path_searcher'
1144
+ autoload :SpecFetcher, 'libgems/spec_fetcher'
1145
+ autoload :UserInteraction, 'libgems/user_interaction'
1146
+ autoload :Specification, 'libgems/specification'
1147
+ autoload :Cache, 'libgems/source_index'
1148
+ autoload :SourceIndex, 'libgems/source_index'
1149
+ autoload :Platform, 'libgems/platform'
1150
+ autoload :Builder, 'libgems/builder'
1151
+ autoload :ConfigFile, 'libgems/config_file'
1152
+ end
1153
+
1154
+ module ::Kernel
1155
+
1156
+ ##
1157
+ # Use Kernel#gem to activate a specific version of +gem_name+.
1158
+ #
1159
+ # +version_requirements+ is a list of version requirements that the
1160
+ # specified gem must match, most commonly "= example.version.number". See
1161
+ # LibGems::Requirement for how to specify a version requirement.
1162
+ #
1163
+ # If you will be activating the latest version of a gem, there is no need to
1164
+ # call Kernel#gem, Kernel#require will do the right thing for you.
1165
+ #
1166
+ # Kernel#gem returns true if the gem was activated, otherwise false. If the
1167
+ # gem could not be found, didn't match the version requirements, or a
1168
+ # different version was already activated, an exception will be raised.
1169
+ #
1170
+ # Kernel#gem should be called *before* any require statements (otherwise
1171
+ # SlimGems may load a conflicting library version).
1172
+ #
1173
+ # In older SlimGems versions, the environment variable GEM_SKIP could be
1174
+ # used to skip activation of specified gems, for example to test out changes
1175
+ # that haven't been installed yet. Now SlimGems defers to -I and the
1176
+ # RUBYLIB environment variable to skip activation of a gem.
1177
+ #
1178
+ # Example:
1179
+ #
1180
+ # GEM_SKIP=libA:libB ruby -I../libA -I../libB ./mycode.rb
1181
+
1182
+ alias_method :original_gem, :gem
1183
+
1184
+ def gem(gem_name, *version_requirements) # :doc:
1185
+ skip_list = (ENV['LIBGEMS_SKIP'] || ENV['GEM_SKIP'] || "").split(/:/)
1186
+ raise LibGems::LoadError, "skipping #{gem_name}" if skip_list.include? gem_name
1187
+ LibGems.activate(gem_name, *version_requirements)
1188
+ rescue LibGems::LoadError => e
1189
+ begin
1190
+ original_gem(gem_name, *version_requirements)
1191
+ rescue Gem::LoadError
1192
+ raise e
1193
+ end
1194
+ end
1195
+
1196
+ private :gem
1197
+
1198
+ end
1199
+
1200
+ ##
1201
+ # Return the path to the data directory associated with the named package. If
1202
+ # the package is loaded as a gem, return the gem specific data directory.
1203
+ # Otherwise return a path to the share area as define by
1204
+ # "#{ConfigMap[:datadir]}/#{package_name}".
1205
+
1206
+ def RbConfig.datadir(package_name)
1207
+ LibGems.datadir(package_name) ||
1208
+ File.join(LibGems::ConfigMap[:datadir], package_name)
1209
+ end
1210
+
1211
+ require 'libgems/exceptions'
1212
+
1213
+ begin
1214
+ ##
1215
+ # Defaults the operating system (or packager) wants to provide for SlimGems.
1216
+
1217
+ require 'libgems/defaults/operating_system'
1218
+ rescue LoadError
1219
+ end
1220
+
1221
+ if defined?(RUBY_ENGINE) then
1222
+ begin
1223
+ ##
1224
+ # Defaults the ruby implementation wants to provide for SlimGems
1225
+
1226
+ require "libgems/defaults/#{RUBY_ENGINE}"
1227
+ rescue LoadError
1228
+ end
1229
+ end
1230
+
1231
+ require 'libgems/config_file'
1232
+
1233
+ class << LibGems
1234
+ remove_method :try_activate if LibGems.respond_to?(:try_activate, true)
1235
+
1236
+ def try_activate(path)
1237
+ spec = LibGems.searcher.find(path)
1238
+ return false unless spec
1239
+
1240
+ LibGems.activate(spec.name, "= #{spec.version}")
1241
+ return true
1242
+ end
1243
+ end
1244
+
1245
+ LibGems.clear_paths
1246
+