libgems 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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
+