From 421d1751d0a1883c387e4b0bec7167053346834c Mon Sep 17 00:00:00 2001 From: No Author Date: Fri, 28 Feb 2003 18:13:00 +0000 Subject: [PATCH 001/707] New repository initialized by cvs2svn. git-svn-id: svn+ssh://rubyforge.org/var/svn/rubygems/trunk@1 3d4018f9-ac1a-0410-99e9-8a154d859a19 From e69d8ce80a694359c97a6bcda049e6f2c37a9f8d Mon Sep 17 00:00:00 2001 From: Jim Weirich Date: Thu, 10 Aug 2006 18:06:59 +0000 Subject: [PATCH 002/707] moved everything up one directory git-svn-id: svn+ssh://rubyforge.org/var/svn/rubygems/trunk@1060 3d4018f9-ac1a-0410-99e9-8a154d859a19 --- LICENSE.txt | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 LICENSE.txt diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 00000000..d82f2ce7 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,53 @@ +RubyGems is copyrighted free software by Chad Fowler, Rich Kilmer, Jim +Weirich and others. You can redistribute it and/or modify it under +either the terms of the GPL (see COPYING.txt file), or the conditions +below: + + 1. You may make and give away verbatim copies of the source form of the + software without restriction, provided that you duplicate all of the + original copyright notices and associated disclaimers. + + 2. You may modify your copy of the software in any way, provided that + you do at least ONE of the following: + + a) place your modifications in the Public Domain or otherwise + make them Freely Available, such as by posting said + modifications to Usenet or an equivalent medium, or by allowing + the author to include your modifications in the software. + + b) use the modified software only within your corporation or + organization. + + c) rename any non-standard executables so the names do not conflict + with standard executables, which must also be provided. + + d) make other distribution arrangements with the author. + + 3. You may distribute the software in object code or executable + form, provided that you do at least ONE of the following: + + a) distribute the executables and library files of the software, + together with instructions (in the manual page or equivalent) + on where to get the original distribution. + + b) accompany the distribution with the machine-readable source of + the software. + + c) give non-standard executables non-standard names, with + instructions on where to get the original software distribution. + + d) make other distribution arrangements with the author. + + 4. You may modify and include the part of the software into any other + software (possibly commercial). + + 5. The scripts and library files supplied as input to or produced as + output from the software do not automatically fall under the + copyright of the software, but belong to whomever generated them, + and may be sold commercially, and may be aggregated with this + software. + + 6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE. From bfdce64ee7b157fabb4714715d043051bda8f6c9 Mon Sep 17 00:00:00 2001 From: Jim Weirich Date: Sat, 6 Jan 2007 20:27:49 +0000 Subject: [PATCH 003/707] Fixed typo in LICENSE.txt file (COPY.txt changed to GPL.txt). git-svn-id: svn+ssh://rubyforge.org/var/svn/rubygems/trunk@1188 3d4018f9-ac1a-0410-99e9-8a154d859a19 --- LICENSE.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE.txt b/LICENSE.txt index d82f2ce7..db88c5e1 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,6 +1,6 @@ RubyGems is copyrighted free software by Chad Fowler, Rich Kilmer, Jim Weirich and others. You can redistribute it and/or modify it under -either the terms of the GPL (see COPYING.txt file), or the conditions +either the terms of the GPL (see the GPL.txt file), or the conditions below: 1. You may make and give away verbatim copies of the source form of the From 616e5802a43e112fe5460eb1ebb27bfbce88c090 Mon Sep 17 00:00:00 2001 From: Andre Arko Date: Tue, 9 Mar 2010 17:09:16 -0800 Subject: [PATCH 004/707] Add changelog, standardize text files --- bundler/README.md | 303 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 303 insertions(+) create mode 100644 bundler/README.md diff --git a/bundler/README.md b/bundler/README.md new file mode 100644 index 00000000..652b99e2 --- /dev/null +++ b/bundler/README.md @@ -0,0 +1,303 @@ +## Bundler : A gem to bundle gems + +Bundler is a tool that manages gem dependencies for your ruby application. It +takes a gem manifest file and is able to fetch, download, and install the gems +and all child dependencies specified in this manifest. It can manage any update +to the gem manifest file and update the bundle's gems accordingly. It also lets +you run any ruby code in context of the bundle's gem environment. + +## Installation + +If you are upgrading from Bundler 0.8, be sure to read the upgrade notes +located at the bottom of this file. + +Bundler has no dependencies besides Ruby and RubyGems. You can install the +latest release via RubyGems: + + gem install bundler + +If you want to contribute, or need a change that hasn't been released yet, +just clone the git repository and install the gem with rake: + + rake install + +## Usage + +The first thing to do is create a gem manifest file named `Gemfile` at the +root directory of your application. This can quickly be done by running +`bundle init` in the directory that you wish the Gemfile to be created in. + +### Gemfile + +This is where you specify all of your application's dependencies. The +following is an example. For more information, refer to Bundler::Dsl. + + # Add :gemcutter as a source that Bundler will use to find gems listed + # in the manifest. At least one source should be listed. URLs may also + # be used, such as http://gems.github.com. + # + source :gemcutter + + # Specify a dependency on rails. When bundler downloads gems, + # it will download rails as well as all of rails' dependencies + # (such as activerecord, actionpack, etc...) + # + # At least one dependency must be specified + # + gem "rails" + + # Specify a dependency on rack v.1.0.0. The version is optional. + # If present, it can be specified the same way as with rubygems' + # #gem method. + # + gem "rack", "1.0.0" + + # Add a git repository as a source. Valid options include :branch, :tag, + # and :ref. Next, add any gems that you want from that repo. + # + git "git://github.com/indirect/rails3-generators.git" + gem "rails3-generators" + +### Groups + +Applications may have dependencies that are specific to certain environments, +such as testing or deployment. + +You can specify groups of gems in the Gemfile using the following syntax: + + gem "nokogiri", :group => :test + + # or + + group :test do + gem "webrat" + end + +Note that Bundler adds all the gems without an explicit group name to the +`:default` group. + +Groups are involved in a number of scenarios: + +1. When installing gems using bundle install, you can choose to leave + out any group by specifying `--without {group name}`. This can be + helpful if, for instance, you have a gem that you cannot compile + in certain environments. +2. When setting up load paths using Bundler.setup, Bundler will, by + default, add the load paths for all groups. You can restrict the + groups to add by doing `Bundler.setup(:group, :names)`. If you do + this, you need to specify the `:default` group if you want it + included. +3. When auto-requiring files using Bundler.require, Bundler will, + by default, auto-require just the `:default` group. You can specify + a list of groups to auto-require such as + `Bundler.require(:default, :test)` + +### Installing gems + +Once the Gemfile manifest file has been created, the next step is to install +all the gems needed to satisfy the manifest's dependencies. The command to +do this is `bundle install`. + +This command will load the Gemfile, resolve all the dependencies, download +all gems that are missing, and install them to the bundler's gem repository. +Gems that are already installed into the system RubyGems repository will be +referenced, rather than installed again. Every time an update is made to the +Gemfile, run `bundle install` again to install any newly needed gems. + +If you want to install the gems into the project's folder, like Bundler 0.8 +and earlier did, you can run `bundle install vendor`, and the gems will +be installed into the `vendor` subdirectory of your project. + +### Locking dependencies + +By default, bundler will only ensure that the activated gems satisfy the +Gemfile's dependencies. If you install a newer version of a gem and it +satisfies the dependencies, it will be used instead of the older one. + +The command `bundle lock` will lock the bundle to the current set of +resolved gems. This ensures that, until the lock file is removed, +`bundle install` and `Bundle.setup` will always activate the same gems. + +When you are distributing your application, you should add the Gemfile and +Gemfile.lock files to your source control, so that the set of libraries your +code will run against are fixed. Simply run `bundle install` after checking +out or deploying your code to ensure your libraries are present. + +DO NOT add the .bundle directory to your source control. The files there are +internal to bundler and vary between machines. If you are using git, you can +exclude all machine-specific bundler files by adding a single line to your +.gitignore file containing `.bundle`. + +### Running the application + +Bundler must be required and setup before anything else is required. This +is because it will configure all the load paths and manage gems for you. +To do this, include the following at the beginning of your code. + + begin + # Try to require the preresolved locked set of gems. + require File.expand_path('../.bundle/environment', __FILE__) + rescue LoadError + # Fall back on doing an unlocked resolve at runtime. + require "rubygems" + require "bundler" + Bundler.setup + end + + # Your application's requires come here, e.g. + # require 'date' # a ruby standard library + # require 'rack' # a bundled gem + + # Alternatively, you can require all the bundled libs at once + # Bundler.require + +The `bundle exec` command provides a way to run arbitrary ruby code in +context of the bundle. For example: + + bundle exec ruby my_ruby_script.rb + +To enter a shell that will run all gem executables (such as `rake`, `rails`, +etc... ) use `bundle exec bash` (replacing bash for whatever your favorite +shell is). + +### Packing the bundle's gems + +When sharing or deploying an application, you may want to include +everything necessary to install gem dependencies. `bundle package` will +copy .gem files for all of the bundle's dependencies into vendor/cache. +After that, `bundle install` will always work, since it will install the +local .gem files, and will not contact any of the remote sources. + +## Gem resolution + +One of the most important things that the bundler does is do a +dependency resolution on the full list of gems that you specify, all +at once. This differs from the one-at-a-time dependency resolution that +Rubygems does, which can result in the following problem: + + # On my system: + # activesupport 3.0.pre + # activesupport 2.3.4 + # activemerchant 1.4.2 + # rails 2.3.4 + # + # activemerchant 1.4.2 depends on activesupport >= 2.3.2 + + gem "activemerchant", "1.4.2" + # results in activating activemerchant, as well as + # activesupport 3.0.pre, since it is >= 2.3.2 + + gem "rails", "2.3.4" + # results in: + # can't activate activesupport (= 2.3.4, runtime) + # for ["rails-2.3.4"], already activated + # activesupport-3.0.pre for ["activemerchant-1.4.2"] + +This is because activemerchant has a broader dependency, which results +in the activation of a version of activesupport that does not satisfy +a more narrow dependency. + +Bundler solves this problem by evaluating all dependencies at once, +so it can detect that all gems *together* require activesupport "2.3.4". + +## Upgrading from Bundler 0.8 to 0.9 and above + +Upgrading to Bundler 0.9 from Bundler 0.8 requires upgrading several +API calls in your Gemfile, and some workarounds if you are using Rails 2.3. + +### Rails 2.3 + +Using Bundler 0.9 with Rails 2.3 requires adding a preinitializer, and +making a few changes to boot.rb. The exact changes needed can be found at +[http://gist.github.com/302406](http://gist.github.com/302406). + +### Gemfile Removals + +Bundler 0.9 removes the following Bundler 0.8 Gemfile APIs: + +1. `disable_system_gems`: This is now the default (and only) option + for bundler. Bundler uses the system gems you have specified + in the Gemfile, and only the system gems you have specified + (and their dependencies) +2. `disable_rubygems`: This is no longer supported. We are looking + into ways to get the fastest performance out of each supported + scenario, and we will make speed the default where possible. +3. `clear_sources`: Bundler now defaults to an empty source + list. If you want to include Rubygems, you can add the source + via source "http://gemcutter.org". If you use bundle init, this + source will be automatically added for you in the generated + Gemfile +4. `bundle_path`: You can specify this setting when installing + via `bundle install /path/to/bundle`. Bundler will remember + where you installed the dependencies to on a particular + machine for future installs, loads, setups, etc. +5. `bin_path`: Bundler no longer generates binaries in the root + of your app. You should use `bundle exec` to execute binaries + in the current context. + +### Gemfile Changes + +Bundler 0.9 changes the following Bundler 0.8 Gemfile APIs: + +1. Bundler 0.8 supported :only and :except as APIs for describing + groups of gems. Bundler 0.9 supports a single `group` method, + which you can use to group gems together. See the above "Group" + section for more information. + + This means that `gem "foo", :only => :production` becomes + `gem "foo", :group => :production`, and + `only :production { gem "foo" }` becomes + `group :production { gem "foo" }` + + The short version is: group your gems together logically, and + use the available commands to make use of the groups you've + created. + +2. `:require_as` becomes `:require` + +3. `:vendored_at` is fully removed; you should use `:path` + +### API Changes + +1. `Bundler.require_env(:environment)` becomes + `Bundler.require(:multiple, :groups)`. You must + now specify the default group (the default group is the + group made up of the gems not assigned to any group) + explicitly. So `Bundler.require_env(:test)` becomes + `Bundler.require(:default, :test)` + +2. `require 'vendor/gems/environment'`: In unlocked + mode, where using system gems, this becomes + `Bundler.setup(:multiple, :groups)`. If you don't + specify any groups, this puts all groups on the load + path. In locked, mode, it becomes `require '.bundle/environment'` + +## More information + +Explanations of common Bundler use cases can be found in [Using Bundler in Real Life](http://yehudakatz.com/2010/02/09/using-bundler-in-real-life/). The general philosophy behind Bundler 0.9 is explained at some length in [Bundler 0.9: Heading Toward 1.0](http://yehudakatz.com/2010/02/01/bundler-0-9-heading-toward-1-0/). + +### Deploying to memory-constrained servers + +When deploying to a server that is memory-constrained, like Dreamhost, you should run `bundle package` on your local development machine, and then check in the resulting `Gemfile.lock` file and `vendor/cache` directory. The lockfile and cached gems will mean bundler can just install the gems immediately, without contacting any gem servers or using a lot of memory to resolve the dependency tree. On the server, you only need to run `bundle install` after you update your deployed code. + +### Other questions + +Any remaining questions may be asked via IRC in [#carlhuda](irc://irc.freenode.net/carlhuda) on Freenode, or via email on the [Bundler mailing list](http://groups.google.com/group/ruby-bundler). + +## Reporting bugs + +Please report all bugs on the github issue tracker for the project, located at [http://github.com/carlhuda/bundler/issues/](http://github.com/carlhuda/bundler/issues/). + +The best possible scenario is a ticket with a fix for the bug and a test for the fix. If that's not possible, instructions to reproduce the issue are vitally important. If you're not sure exactly how to reproduce the issue that you are seeing, create a gist of the following information and include it in your ticket: + + - Whether you have locked or not + - What version of bundler you are using + - Your Gemfile + - The command you ran to generate exception(s) + - The exception backtrace(s) + +If you are using Rails 2.3, please also include: + + - Your boot.rb file + - Your preinitializer.rb file + - Your environment.rb file From 1fd5b43d2276a67f3888f136dfa9dc498a46a67b Mon Sep 17 00:00:00 2001 From: Andre Arko Date: Wed, 10 Mar 2010 10:10:20 -0800 Subject: [PATCH 005/707] Link to more detailed Rails 2.3.5 blogpost, ask for more info on tickets --- bundler/README.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/bundler/README.md b/bundler/README.md index 652b99e2..a654bcdb 100644 --- a/bundler/README.md +++ b/bundler/README.md @@ -208,8 +208,8 @@ API calls in your Gemfile, and some workarounds if you are using Rails 2.3. ### Rails 2.3 Using Bundler 0.9 with Rails 2.3 requires adding a preinitializer, and -making a few changes to boot.rb. The exact changes needed can be found at -[http://gist.github.com/302406](http://gist.github.com/302406). +making a few changes to boot.rb. A detailed description of the changes +needed can be found in [Bundler 0.9 and Rails 2.3.5](http://andre.arko.net/2010/02/13/using-bundler-09-with-rails-235/). ### Gemfile Removals @@ -274,7 +274,7 @@ Bundler 0.9 changes the following Bundler 0.8 Gemfile APIs: ## More information -Explanations of common Bundler use cases can be found in [Using Bundler in Real Life](http://yehudakatz.com/2010/02/09/using-bundler-in-real-life/). The general philosophy behind Bundler 0.9 is explained at some length in [Bundler 0.9: Heading Toward 1.0](http://yehudakatz.com/2010/02/01/bundler-0-9-heading-toward-1-0/). +Explanations of common Bundler use cases can be found in [Using Bundler in Real Life](http://yehudakatz.com/2010/02/09/using-bundler-in-real-life/). The general philosophy behind Bundler 0.9 is explained at some length in [Bundler 0.9: Heading Toward 1.0](http://yehudakatz.com/2010/02/01/bundler-0-9-heading-toward-1-0/). Using Bundler with a Rails 2.3.5 app is explained with more detail in [Bundler 0.9 and Rails 2.3.5](http://andre.arko.net/2010/02/13/using-bundler-09-with-rails-235/). ### Deploying to memory-constrained servers @@ -292,6 +292,8 @@ The best possible scenario is a ticket with a fix for the bug and a test for the - Whether you have locked or not - What version of bundler you are using + - What version of Ruby you are using + - Whether you are using RVM, and if so what version - Your Gemfile - The command you ran to generate exception(s) - The exception backtrace(s) From 78656017cb1bc531b8751a357eea0098d0f31f76 Mon Sep 17 00:00:00 2001 From: Andre Arko Date: Wed, 10 Mar 2010 10:34:17 -0800 Subject: [PATCH 006/707] Add troubleshooting suggestions to the readme --- bundler/README.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/bundler/README.md b/bundler/README.md index a654bcdb..940b0954 100644 --- a/bundler/README.md +++ b/bundler/README.md @@ -286,7 +286,12 @@ Any remaining questions may be asked via IRC in [#carlhuda](irc://irc.freenode.n ## Reporting bugs -Please report all bugs on the github issue tracker for the project, located at [http://github.com/carlhuda/bundler/issues/](http://github.com/carlhuda/bundler/issues/). +Before reporting a bug, try these troubleshooting steps: + + rm -rf ~/.bundle/ ~/.gem/ .bundle/ Gemfile.lock + bundle install + +If you are still having problems, please report bugs to the github issue tracker for the project, located at [http://github.com/carlhuda/bundler/issues/](http://github.com/carlhuda/bundler/issues/). The best possible scenario is a ticket with a fix for the bug and a test for the fix. If that's not possible, instructions to reproduce the issue are vitally important. If you're not sure exactly how to reproduce the issue that you are seeing, create a gist of the following information and include it in your ticket: From c7f59a09d871aef612aff22ee7324f41fb897b99 Mon Sep 17 00:00:00 2001 From: Andre Arko Date: Mon, 15 Mar 2010 11:02:52 -0700 Subject: [PATCH 007/707] Clarify installing --without in the readme --- bundler/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundler/README.md b/bundler/README.md index 940b0954..813dc364 100644 --- a/bundler/README.md +++ b/bundler/README.md @@ -79,7 +79,7 @@ Note that Bundler adds all the gems without an explicit group name to the Groups are involved in a number of scenarios: 1. When installing gems using bundle install, you can choose to leave - out any group by specifying `--without {group name}`. This can be + out any group by specifying `--without group1 group2`. This can be helpful if, for instance, you have a gem that you cannot compile in certain environments. 2. When setting up load paths using Bundler.setup, Bundler will, by From 4773f61e7a3a5712416a7ec52bd0b5840b9a413d Mon Sep 17 00:00:00 2001 From: Andre Arko Date: Thu, 25 Mar 2010 23:39:32 -0700 Subject: [PATCH 008/707] Update changelog and link from readme --- bundler/README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/bundler/README.md b/bundler/README.md index 813dc364..5225f540 100644 --- a/bundler/README.md +++ b/bundler/README.md @@ -274,6 +274,12 @@ Bundler 0.9 changes the following Bundler 0.8 Gemfile APIs: ## More information +### Development + +For information about future plans and changes that will happen between now and bundler 1.0, see the [ROADMAP](http://github.com/carlhuda/bundler/blob/master/ROADMAP.md). To see what has changed in each version of bundler, starting with 0.9.5, see the [CHANGELOG](http://github.com/carlhuda/bundler/blob/master/CHANGELOG.md). + +### Usage + Explanations of common Bundler use cases can be found in [Using Bundler in Real Life](http://yehudakatz.com/2010/02/09/using-bundler-in-real-life/). The general philosophy behind Bundler 0.9 is explained at some length in [Bundler 0.9: Heading Toward 1.0](http://yehudakatz.com/2010/02/01/bundler-0-9-heading-toward-1-0/). Using Bundler with a Rails 2.3.5 app is explained with more detail in [Bundler 0.9 and Rails 2.3.5](http://andre.arko.net/2010/02/13/using-bundler-09-with-rails-235/). ### Deploying to memory-constrained servers From 69a9221d3291de1cab166d5028b3bf108c098a62 Mon Sep 17 00:00:00 2001 From: Andre Arko Date: Thu, 25 Mar 2010 23:39:32 -0700 Subject: [PATCH 009/707] Update changelog and link from readme --- bundler/README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/bundler/README.md b/bundler/README.md index 813dc364..5225f540 100644 --- a/bundler/README.md +++ b/bundler/README.md @@ -274,6 +274,12 @@ Bundler 0.9 changes the following Bundler 0.8 Gemfile APIs: ## More information +### Development + +For information about future plans and changes that will happen between now and bundler 1.0, see the [ROADMAP](http://github.com/carlhuda/bundler/blob/master/ROADMAP.md). To see what has changed in each version of bundler, starting with 0.9.5, see the [CHANGELOG](http://github.com/carlhuda/bundler/blob/master/CHANGELOG.md). + +### Usage + Explanations of common Bundler use cases can be found in [Using Bundler in Real Life](http://yehudakatz.com/2010/02/09/using-bundler-in-real-life/). The general philosophy behind Bundler 0.9 is explained at some length in [Bundler 0.9: Heading Toward 1.0](http://yehudakatz.com/2010/02/01/bundler-0-9-heading-toward-1-0/). Using Bundler with a Rails 2.3.5 app is explained with more detail in [Bundler 0.9 and Rails 2.3.5](http://andre.arko.net/2010/02/13/using-bundler-09-with-rails-235/). ### Deploying to memory-constrained servers From d72b0d224f940a0b03293b66dc6f7ff3acfc59f9 Mon Sep 17 00:00:00 2001 From: Andre Arko Date: Tue, 30 Mar 2010 16:21:28 -0700 Subject: [PATCH 010/707] IRC channel, woo! --- bundler/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundler/README.md b/bundler/README.md index 5225f540..93bc6e34 100644 --- a/bundler/README.md +++ b/bundler/README.md @@ -288,7 +288,7 @@ When deploying to a server that is memory-constrained, like Dreamhost, you shoul ### Other questions -Any remaining questions may be asked via IRC in [#carlhuda](irc://irc.freenode.net/carlhuda) on Freenode, or via email on the [Bundler mailing list](http://groups.google.com/group/ruby-bundler). +Any remaining questions may be asked via IRC in [#bundler](irc://irc.freenode.net/bundler) on Freenode, or via email on the [Bundler mailing list](http://groups.google.com/group/ruby-bundler). ## Reporting bugs From 07168ddc8b7ff212f2b3955fbe441ec5069b55e9 Mon Sep 17 00:00:00 2001 From: Andre Arko Date: Thu, 1 Apr 2010 16:16:23 -0700 Subject: [PATCH 011/707] Point to web docs --- bundler/README.md | 174 +--------------------------------------------- 1 file changed, 3 insertions(+), 171 deletions(-) diff --git a/bundler/README.md b/bundler/README.md index 5225f540..6bf96bd4 100644 --- a/bundler/README.md +++ b/bundler/README.md @@ -6,169 +6,11 @@ and all child dependencies specified in this manifest. It can manage any update to the gem manifest file and update the bundle's gems accordingly. It also lets you run any ruby code in context of the bundle's gem environment. -## Installation +## Installation and usage -If you are upgrading from Bundler 0.8, be sure to read the upgrade notes -located at the bottom of this file. +See [gembundler.com](http://gembundler.com) for up-to-date installation and usage instructions -Bundler has no dependencies besides Ruby and RubyGems. You can install the -latest release via RubyGems: - - gem install bundler - -If you want to contribute, or need a change that hasn't been released yet, -just clone the git repository and install the gem with rake: - - rake install - -## Usage - -The first thing to do is create a gem manifest file named `Gemfile` at the -root directory of your application. This can quickly be done by running -`bundle init` in the directory that you wish the Gemfile to be created in. - -### Gemfile - -This is where you specify all of your application's dependencies. The -following is an example. For more information, refer to Bundler::Dsl. - - # Add :gemcutter as a source that Bundler will use to find gems listed - # in the manifest. At least one source should be listed. URLs may also - # be used, such as http://gems.github.com. - # - source :gemcutter - - # Specify a dependency on rails. When bundler downloads gems, - # it will download rails as well as all of rails' dependencies - # (such as activerecord, actionpack, etc...) - # - # At least one dependency must be specified - # - gem "rails" - - # Specify a dependency on rack v.1.0.0. The version is optional. - # If present, it can be specified the same way as with rubygems' - # #gem method. - # - gem "rack", "1.0.0" - - # Add a git repository as a source. Valid options include :branch, :tag, - # and :ref. Next, add any gems that you want from that repo. - # - git "git://github.com/indirect/rails3-generators.git" - gem "rails3-generators" - -### Groups - -Applications may have dependencies that are specific to certain environments, -such as testing or deployment. - -You can specify groups of gems in the Gemfile using the following syntax: - - gem "nokogiri", :group => :test - - # or - - group :test do - gem "webrat" - end - -Note that Bundler adds all the gems without an explicit group name to the -`:default` group. - -Groups are involved in a number of scenarios: - -1. When installing gems using bundle install, you can choose to leave - out any group by specifying `--without group1 group2`. This can be - helpful if, for instance, you have a gem that you cannot compile - in certain environments. -2. When setting up load paths using Bundler.setup, Bundler will, by - default, add the load paths for all groups. You can restrict the - groups to add by doing `Bundler.setup(:group, :names)`. If you do - this, you need to specify the `:default` group if you want it - included. -3. When auto-requiring files using Bundler.require, Bundler will, - by default, auto-require just the `:default` group. You can specify - a list of groups to auto-require such as - `Bundler.require(:default, :test)` - -### Installing gems - -Once the Gemfile manifest file has been created, the next step is to install -all the gems needed to satisfy the manifest's dependencies. The command to -do this is `bundle install`. - -This command will load the Gemfile, resolve all the dependencies, download -all gems that are missing, and install them to the bundler's gem repository. -Gems that are already installed into the system RubyGems repository will be -referenced, rather than installed again. Every time an update is made to the -Gemfile, run `bundle install` again to install any newly needed gems. - -If you want to install the gems into the project's folder, like Bundler 0.8 -and earlier did, you can run `bundle install vendor`, and the gems will -be installed into the `vendor` subdirectory of your project. - -### Locking dependencies - -By default, bundler will only ensure that the activated gems satisfy the -Gemfile's dependencies. If you install a newer version of a gem and it -satisfies the dependencies, it will be used instead of the older one. - -The command `bundle lock` will lock the bundle to the current set of -resolved gems. This ensures that, until the lock file is removed, -`bundle install` and `Bundle.setup` will always activate the same gems. - -When you are distributing your application, you should add the Gemfile and -Gemfile.lock files to your source control, so that the set of libraries your -code will run against are fixed. Simply run `bundle install` after checking -out or deploying your code to ensure your libraries are present. - -DO NOT add the .bundle directory to your source control. The files there are -internal to bundler and vary between machines. If you are using git, you can -exclude all machine-specific bundler files by adding a single line to your -.gitignore file containing `.bundle`. - -### Running the application - -Bundler must be required and setup before anything else is required. This -is because it will configure all the load paths and manage gems for you. -To do this, include the following at the beginning of your code. - - begin - # Try to require the preresolved locked set of gems. - require File.expand_path('../.bundle/environment', __FILE__) - rescue LoadError - # Fall back on doing an unlocked resolve at runtime. - require "rubygems" - require "bundler" - Bundler.setup - end - - # Your application's requires come here, e.g. - # require 'date' # a ruby standard library - # require 'rack' # a bundled gem - - # Alternatively, you can require all the bundled libs at once - # Bundler.require - -The `bundle exec` command provides a way to run arbitrary ruby code in -context of the bundle. For example: - - bundle exec ruby my_ruby_script.rb - -To enter a shell that will run all gem executables (such as `rake`, `rails`, -etc... ) use `bundle exec bash` (replacing bash for whatever your favorite -shell is). - -### Packing the bundle's gems - -When sharing or deploying an application, you may want to include -everything necessary to install gem dependencies. `bundle package` will -copy .gem files for all of the bundle's dependencies into vendor/cache. -After that, `bundle install` will always work, since it will install the -local .gem files, and will not contact any of the remote sources. - -## Gem resolution +## Gem dependency resolution One of the most important things that the bundler does is do a dependency resolution on the full list of gems that you specify, all @@ -205,12 +47,6 @@ so it can detect that all gems *together* require activesupport "2.3.4". Upgrading to Bundler 0.9 from Bundler 0.8 requires upgrading several API calls in your Gemfile, and some workarounds if you are using Rails 2.3. -### Rails 2.3 - -Using Bundler 0.9 with Rails 2.3 requires adding a preinitializer, and -making a few changes to boot.rb. A detailed description of the changes -needed can be found in [Bundler 0.9 and Rails 2.3.5](http://andre.arko.net/2010/02/13/using-bundler-09-with-rails-235/). - ### Gemfile Removals Bundler 0.9 removes the following Bundler 0.8 Gemfile APIs: @@ -278,10 +114,6 @@ Bundler 0.9 changes the following Bundler 0.8 Gemfile APIs: For information about future plans and changes that will happen between now and bundler 1.0, see the [ROADMAP](http://github.com/carlhuda/bundler/blob/master/ROADMAP.md). To see what has changed in each version of bundler, starting with 0.9.5, see the [CHANGELOG](http://github.com/carlhuda/bundler/blob/master/CHANGELOG.md). -### Usage - -Explanations of common Bundler use cases can be found in [Using Bundler in Real Life](http://yehudakatz.com/2010/02/09/using-bundler-in-real-life/). The general philosophy behind Bundler 0.9 is explained at some length in [Bundler 0.9: Heading Toward 1.0](http://yehudakatz.com/2010/02/01/bundler-0-9-heading-toward-1-0/). Using Bundler with a Rails 2.3.5 app is explained with more detail in [Bundler 0.9 and Rails 2.3.5](http://andre.arko.net/2010/02/13/using-bundler-09-with-rails-235/). - ### Deploying to memory-constrained servers When deploying to a server that is memory-constrained, like Dreamhost, you should run `bundle package` on your local development machine, and then check in the resulting `Gemfile.lock` file and `vendor/cache` directory. The lockfile and cached gems will mean bundler can just install the gems immediately, without contacting any gem servers or using a lot of memory to resolve the dependency tree. On the server, you only need to run `bundle install` after you update your deployed code. From eadc4293eef871bbf56b51f5a84c9d096af6d7f3 Mon Sep 17 00:00:00 2001 From: Andre Arko Date: Sat, 17 Apr 2010 12:57:15 -0700 Subject: [PATCH 012/707] Note that v0.9 is the stable branch --- bundler/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bundler/README.md b/bundler/README.md index bbc123bf..d57bcd45 100644 --- a/bundler/README.md +++ b/bundler/README.md @@ -1,3 +1,5 @@ +### Note: the master branch is currently unstable while 0.10 is being worked on.
The current stable version of bundler is in the branch named `v0.9`. + ## Bundler : A gem to bundle gems Bundler is a tool that manages gem dependencies for your ruby application. It From 46ad0b773a11ea0ad6b1cba3ae6717036276958b Mon Sep 17 00:00:00 2001 From: Andre Arko Date: Mon, 14 Jun 2010 11:54:50 -0700 Subject: [PATCH 013/707] Update readme for 1.0 beta --- bundler/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundler/README.md b/bundler/README.md index d57bcd45..8579b357 100644 --- a/bundler/README.md +++ b/bundler/README.md @@ -1,4 +1,4 @@ -### Note: the master branch is currently unstable while 0.10 is being worked on.
The current stable version of bundler is in the branch named `v0.9`. +### Note: the master branch is currently unstable while 1.0 is in beta.
The current stable version of bundler is in the branch named `v0.9`. ## Bundler : A gem to bundle gems From 7b41b5d39b17083d2974bcbe6bbcb77830dbb86a Mon Sep 17 00:00:00 2001 From: Yehuda Katz Date: Mon, 2 Aug 2010 10:49:44 -0700 Subject: [PATCH 014/707] Provide additional troubleshooting instructions --- bundler/README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/bundler/README.md b/bundler/README.md index 8579b357..b7c11187 100644 --- a/bundler/README.md +++ b/bundler/README.md @@ -135,11 +135,13 @@ If you are still having problems, please report bugs to the github issue tracker The best possible scenario is a ticket with a fix for the bug and a test for the fix. If that's not possible, instructions to reproduce the issue are vitally important. If you're not sure exactly how to reproduce the issue that you are seeing, create a gist of the following information and include it in your ticket: - - Whether you have locked or not - What version of bundler you are using - What version of Ruby you are using - Whether you are using RVM, and if so what version - Your Gemfile + - Your Gemfile.lock + - If you are on 0.9, whether you have locked or not + - If you are on 1.0, the result of `bundle config` - The command you ran to generate exception(s) - The exception backtrace(s) From cd0a708553ffde740ca8d5e3ff7388237a27c2d8 Mon Sep 17 00:00:00 2001 From: Andre Arko Date: Wed, 11 Aug 2010 12:32:28 -0700 Subject: [PATCH 015/707] Clean up README, factor out ISSUES --- bundler/README.md | 67 +++-------------------------------------------- 1 file changed, 3 insertions(+), 64 deletions(-) diff --git a/bundler/README.md b/bundler/README.md index b7c11187..151cf44e 100644 --- a/bundler/README.md +++ b/bundler/README.md @@ -1,5 +1,3 @@ -### Note: the master branch is currently unstable while 1.0 is in beta.
The current stable version of bundler is in the branch named `v0.9`. - ## Bundler : A gem to bundle gems Bundler is a tool that manages gem dependencies for your ruby application. It @@ -12,38 +10,6 @@ you run any ruby code in context of the bundle's gem environment. See [gembundler.com](http://gembundler.com) for up-to-date installation and usage instructions -## Gem dependency resolution - -One of the most important things that the bundler does is do a -dependency resolution on the full list of gems that you specify, all -at once. This differs from the one-at-a-time dependency resolution that -Rubygems does, which can result in the following problem: - - # On my system: - # activesupport 3.0.pre - # activesupport 2.3.4 - # activemerchant 1.4.2 - # rails 2.3.4 - # - # activemerchant 1.4.2 depends on activesupport >= 2.3.2 - - gem "activemerchant", "1.4.2" - # results in activating activemerchant, as well as - # activesupport 3.0.pre, since it is >= 2.3.2 - - gem "rails", "2.3.4" - # results in: - # can't activate activesupport (= 2.3.4, runtime) - # for ["rails-2.3.4"], already activated - # activesupport-3.0.pre for ["activemerchant-1.4.2"] - -This is because activemerchant has a broader dependency, which results -in the activation of a version of activesupport that does not satisfy -a more narrow dependency. - -Bundler solves this problem by evaluating all dependencies at once, -so it can detect that all gems *together* require activesupport "2.3.4". - ## Upgrading from Bundler 0.8 to 0.9 and above Upgrading to Bundler 0.9 from Bundler 0.8 requires upgrading several @@ -114,39 +80,12 @@ Bundler 0.9 changes the following Bundler 0.8 Gemfile APIs: ### Development -For information about future plans and changes that will happen between now and bundler 1.0, see the [ROADMAP](http://github.com/carlhuda/bundler/blob/master/ROADMAP.md). To see what has changed in each version of bundler, starting with 0.9.5, see the [CHANGELOG](http://github.com/carlhuda/bundler/blob/master/CHANGELOG.md). - -### Deploying to memory-constrained servers - -When deploying to a server that is memory-constrained, like Dreamhost, you should run `bundle package` on your local development machine, and then check in the resulting `Gemfile.lock` file and `vendor/cache` directory. The lockfile and cached gems will mean bundler can just install the gems immediately, without contacting any gem servers or using a lot of memory to resolve the dependency tree. On the server, you only need to run `bundle install` after you update your deployed code. +For information about future plans and changes that will happen in the future, see the [ROADMAP](http://github.com/carlhuda/bundler/blob/master/ROADMAP.md). To see what has changed in each version of bundler, starting with 0.9.5, see the [CHANGELOG](http://github.com/carlhuda/bundler/blob/master/CHANGELOG.md). ### Other questions Any remaining questions may be asked via IRC in [#bundler](irc://irc.freenode.net/bundler) on Freenode, or via email on the [Bundler mailing list](http://groups.google.com/group/ruby-bundler). -## Reporting bugs - -Before reporting a bug, try these troubleshooting steps: - - rm -rf ~/.bundle/ ~/.gem/ .bundle/ Gemfile.lock - bundle install - -If you are still having problems, please report bugs to the github issue tracker for the project, located at [http://github.com/carlhuda/bundler/issues/](http://github.com/carlhuda/bundler/issues/). - -The best possible scenario is a ticket with a fix for the bug and a test for the fix. If that's not possible, instructions to reproduce the issue are vitally important. If you're not sure exactly how to reproduce the issue that you are seeing, create a gist of the following information and include it in your ticket: - - - What version of bundler you are using - - What version of Ruby you are using - - Whether you are using RVM, and if so what version - - Your Gemfile - - Your Gemfile.lock - - If you are on 0.9, whether you have locked or not - - If you are on 1.0, the result of `bundle config` - - The command you ran to generate exception(s) - - The exception backtrace(s) - -If you are using Rails 2.3, please also include: +### Issues - - Your boot.rb file - - Your preinitializer.rb file - - Your environment.rb file +See [ISSUES](http://github.com/carlhuda/bundler/blob/master/ISSUES.md). \ No newline at end of file From 09af28af7a2e8f59577b7b42104f751a3cf091c4 Mon Sep 17 00:00:00 2001 From: Andre Arko Date: Tue, 24 Aug 2010 15:33:41 -0700 Subject: [PATCH 016/707] =?UTF-8?q?Refactor=20UPGRADING=20out=20of=20READM?= =?UTF-8?q?E,=20add=200.9=20=E2=86=92=201.0=20notes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bundler/README.md | 78 +++++------------------------------------------ 1 file changed, 7 insertions(+), 71 deletions(-) diff --git a/bundler/README.md b/bundler/README.md index 151cf44e..c6c9414c 100644 --- a/bundler/README.md +++ b/bundler/README.md @@ -1,4 +1,4 @@ -## Bundler : A gem to bundle gems +# Bundler: a gem to bundle gems Bundler is a tool that manages gem dependencies for your ruby application. It takes a gem manifest file and is able to fetch, download, and install the gems @@ -8,84 +8,20 @@ you run any ruby code in context of the bundle's gem environment. ## Installation and usage -See [gembundler.com](http://gembundler.com) for up-to-date installation and usage instructions +See [gembundler.com](http://gembundler.com) for up-to-date installation and usage instructions. -## Upgrading from Bundler 0.8 to 0.9 and above - -Upgrading to Bundler 0.9 from Bundler 0.8 requires upgrading several -API calls in your Gemfile, and some workarounds if you are using Rails 2.3. - -### Gemfile Removals - -Bundler 0.9 removes the following Bundler 0.8 Gemfile APIs: - -1. `disable_system_gems`: This is now the default (and only) option - for bundler. Bundler uses the system gems you have specified - in the Gemfile, and only the system gems you have specified - (and their dependencies) -2. `disable_rubygems`: This is no longer supported. We are looking - into ways to get the fastest performance out of each supported - scenario, and we will make speed the default where possible. -3. `clear_sources`: Bundler now defaults to an empty source - list. If you want to include Rubygems, you can add the source - via source "http://gemcutter.org". If you use bundle init, this - source will be automatically added for you in the generated - Gemfile -4. `bundle_path`: You can specify this setting when installing - via `bundle install /path/to/bundle`. Bundler will remember - where you installed the dependencies to on a particular - machine for future installs, loads, setups, etc. -5. `bin_path`: Bundler no longer generates binaries in the root - of your app. You should use `bundle exec` to execute binaries - in the current context. - -### Gemfile Changes - -Bundler 0.9 changes the following Bundler 0.8 Gemfile APIs: - -1. Bundler 0.8 supported :only and :except as APIs for describing - groups of gems. Bundler 0.9 supports a single `group` method, - which you can use to group gems together. See the above "Group" - section for more information. +## Troubleshooting - This means that `gem "foo", :only => :production` becomes - `gem "foo", :group => :production`, and - `only :production { gem "foo" }` becomes - `group :production { gem "foo" }` - - The short version is: group your gems together logically, and - use the available commands to make use of the groups you've - created. - -2. `:require_as` becomes `:require` - -3. `:vendored_at` is fully removed; you should use `:path` - -### API Changes - -1. `Bundler.require_env(:environment)` becomes - `Bundler.require(:multiple, :groups)`. You must - now specify the default group (the default group is the - group made up of the gems not assigned to any group) - explicitly. So `Bundler.require_env(:test)` becomes - `Bundler.require(:default, :test)` - -2. `require 'vendor/gems/environment'`: In unlocked - mode, where using system gems, this becomes - `Bundler.setup(:multiple, :groups)`. If you don't - specify any groups, this puts all groups on the load - path. In locked, mode, it becomes `require '.bundle/environment'` - -## More information +For help with common problems, see [ISSUES](http://github.com/carlhuda/bundler/blob/master/ISSUES.md). ### Development -For information about future plans and changes that will happen in the future, see the [ROADMAP](http://github.com/carlhuda/bundler/blob/master/ROADMAP.md). To see what has changed in each version of bundler, starting with 0.9.5, see the [CHANGELOG](http://github.com/carlhuda/bundler/blob/master/CHANGELOG.md). +To see what has changed in each version of bundler, starting with 0.9.5, see the [CHANGELOG](http://github.com/carlhuda/bundler/blob/master/CHANGELOG.md). For information about changes that will happen in the future, see the [ROADMAP](http://github.com/carlhuda/bundler/blob/master/ROADMAP.md). ### Other questions Any remaining questions may be asked via IRC in [#bundler](irc://irc.freenode.net/bundler) on Freenode, or via email on the [Bundler mailing list](http://groups.google.com/group/ruby-bundler). -### Issues +## Upgrading from Bundler 0.8 to 0.9 and above -See [ISSUES](http://github.com/carlhuda/bundler/blob/master/ISSUES.md). \ No newline at end of file +See [UPGRADING](http://github.com/carlhuda/bundler/blob/master/UPGRADING.md). \ No newline at end of file From 6d4388c27814aa89b7e8a74084c686b915f8c94d Mon Sep 17 00:00:00 2001 From: Andre Arko Date: Tue, 24 Aug 2010 16:29:06 -0700 Subject: [PATCH 017/707] Make Other Questions its own readme section --- bundler/README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/bundler/README.md b/bundler/README.md index c6c9414c..1bb9b91b 100644 --- a/bundler/README.md +++ b/bundler/README.md @@ -18,10 +18,10 @@ For help with common problems, see [ISSUES](http://github.com/carlhuda/bundler/b To see what has changed in each version of bundler, starting with 0.9.5, see the [CHANGELOG](http://github.com/carlhuda/bundler/blob/master/CHANGELOG.md). For information about changes that will happen in the future, see the [ROADMAP](http://github.com/carlhuda/bundler/blob/master/ROADMAP.md). -### Other questions +## Upgrading from Bundler 0.8 to 0.9 and above -Any remaining questions may be asked via IRC in [#bundler](irc://irc.freenode.net/bundler) on Freenode, or via email on the [Bundler mailing list](http://groups.google.com/group/ruby-bundler). +See [UPGRADING](http://github.com/carlhuda/bundler/blob/master/UPGRADING.md). -## Upgrading from Bundler 0.8 to 0.9 and above +## Other questions -See [UPGRADING](http://github.com/carlhuda/bundler/blob/master/UPGRADING.md). \ No newline at end of file +Feel free to chat with the Bundler core team (and many other users) on IRC in the [#bundler](irc://irc.freenode.net/bundler) channel on Freenode, or via email on the [Bundler mailing list](http://groups.google.com/group/ruby-bundler). From a5dec5b22053e03a5bad2566a7cd9736e794b096 Mon Sep 17 00:00:00 2001 From: Andre Arko Date: Fri, 1 Oct 2010 22:11:12 -0700 Subject: [PATCH 018/707] Document the `1-0-stable` branch in the readme, remove outdated roadmap --- bundler/README.md | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/bundler/README.md b/bundler/README.md index 1bb9b91b..0cd4dd15 100644 --- a/bundler/README.md +++ b/bundler/README.md @@ -6,22 +6,24 @@ and all child dependencies specified in this manifest. It can manage any update to the gem manifest file and update the bundle's gems accordingly. It also lets you run any ruby code in context of the bundle's gem environment. -## Installation and usage +### Installation and usage See [gembundler.com](http://gembundler.com) for up-to-date installation and usage instructions. -## Troubleshooting +### Troubleshooting For help with common problems, see [ISSUES](http://github.com/carlhuda/bundler/blob/master/ISSUES.md). ### Development -To see what has changed in each version of bundler, starting with 0.9.5, see the [CHANGELOG](http://github.com/carlhuda/bundler/blob/master/CHANGELOG.md). For information about changes that will happen in the future, see the [ROADMAP](http://github.com/carlhuda/bundler/blob/master/ROADMAP.md). +To see what has changed in recent versions of bundler, see the [CHANGELOG](http://github.com/carlhuda/bundler/blob/master/CHANGELOG.md). -## Upgrading from Bundler 0.8 to 0.9 and above +The `master` branch contains our current progress towards version 1.1. Because of that, please submit bugfix pull requests against the `1-0-stable` branch. + +### Upgrading from Bundler 0.8 to 0.9 and above See [UPGRADING](http://github.com/carlhuda/bundler/blob/master/UPGRADING.md). -## Other questions +### Other questions Feel free to chat with the Bundler core team (and many other users) on IRC in the [#bundler](irc://irc.freenode.net/bundler) channel on Freenode, or via email on the [Bundler mailing list](http://groups.google.com/group/ruby-bundler). From 5c29e98e594e88c3f2dd71f9aeb2a3567e42f0d5 Mon Sep 17 00:00:00 2001 From: Ryan Davis Date: Fri, 14 Jan 2011 17:40:38 -0800 Subject: [PATCH 019/707] Moved test/* to test/rubygems to match 1.9 --- test/rubygems/test_gem.rb | 776 ++++++++++++++++++++++++++++++ test/rubygems/test_gem_version.rb | 181 +++++++ 2 files changed, 957 insertions(+) create mode 100644 test/rubygems/test_gem.rb create mode 100644 test/rubygems/test_gem_version.rb diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb new file mode 100644 index 00000000..83fd6f5e --- /dev/null +++ b/test/rubygems/test_gem.rb @@ -0,0 +1,776 @@ +require File.expand_path('../gemutilities', __FILE__) +require 'rubygems' +require 'rubygems/gem_openssl' +require 'rubygems/installer' +require 'pathname' +require 'tmpdir' + +class TestGem < RubyGemTestCase + + def setup + super + + @additional = %w[a b].map { |d| File.join @tempdir, d } + @default_dir_re = if RUBY_VERSION > '1.9' then + %r|/.*?[Rr]uby.*?/[Gg]ems/[0-9.]+| + else + %r|/[Rr]uby/[Gg]ems/[0-9.]+| + end + + util_remove_interrupt_command + end + + def test_self_all_load_paths + util_make_gems + + expected = [ + File.join(@gemhome, *%W[gems #{@a1.full_name} lib]), + File.join(@gemhome, *%W[gems #{@a2.full_name} lib]), + File.join(@gemhome, *%W[gems #{@a3a.full_name} lib]), + File.join(@gemhome, *%W[gems #{@a_evil9.full_name} lib]), + File.join(@gemhome, *%W[gems #{@b2.full_name} lib]), + File.join(@gemhome, *%W[gems #{@c1_2.full_name} lib]), + File.join(@gemhome, *%W[gems #{@pl1.full_name} lib]), + ] + + assert_equal expected, Gem.all_load_paths.sort + end + + def test_self_available? + util_make_gems + assert(Gem.available?("a")) + assert(Gem.available?("a", "1")) + assert(Gem.available?("a", ">1")) + assert(!Gem.available?("monkeys")) + end + + def test_self_bin_path_bin_name + util_exec_gem + assert_equal @abin_path, Gem.bin_path('a', 'abin') + end + + def test_self_bin_path_bin_name_version + util_exec_gem + assert_equal @abin_path, Gem.bin_path('a', 'abin', '4') + end + + def test_self_bin_path_name + util_exec_gem + assert_equal @exec_path, Gem.bin_path('a') + end + + def test_self_bin_path_name_version + util_exec_gem + assert_equal @exec_path, Gem.bin_path('a', nil, '4') + end + + def test_self_bin_path_nonexistent_binfile + quick_gem 'a', '2' do |s| + s.executables = ['exec'] + end + assert_raises(Gem::GemNotFoundException) do + Gem.bin_path('a', 'other', '2') + end + end + + def test_self_bin_path_no_bin_file + quick_gem 'a', '1' + assert_raises(Gem::Exception) do + Gem.bin_path('a', nil, '1') + end + end + + def test_self_bin_path_not_found + assert_raises(Gem::GemNotFoundException) do + Gem.bin_path('non-existent') + end + end + + def test_self_bin_path_bin_file_gone_in_latest + util_exec_gem + quick_gem 'a', '10' do |s| + s.executables = [] + s.default_executable = nil + end + # Should not find a-10's non-abin (bug) + assert_equal @abin_path, Gem.bin_path('a', 'abin') + end + + def test_self_bindir + assert_equal File.join(@gemhome, 'bin'), Gem.bindir + assert_equal File.join(@gemhome, 'bin'), Gem.bindir(Gem.dir) + assert_equal File.join(@gemhome, 'bin'), Gem.bindir(Pathname.new(Gem.dir)) + end + + def test_self_bindir_default_dir + default = Gem.default_dir + bindir = if defined?(RUBY_FRAMEWORK_VERSION) then + '/usr/bin' + else + RbConfig::CONFIG['bindir'] + end + + assert_equal bindir, Gem.bindir(default) + assert_equal bindir, Gem.bindir(Pathname.new(default)) + end + + def test_self_clear_paths + Gem.dir + Gem.path + searcher = Gem.searcher + source_index = Gem.source_index + + Gem.clear_paths + + assert_equal nil, Gem.instance_variable_get(:@gem_home) + assert_equal nil, Gem.instance_variable_get(:@gem_path) + refute_equal searcher, Gem.searcher + refute_equal source_index.object_id, Gem.source_index.object_id + end + + def test_self_configuration + expected = Gem::ConfigFile.new [] + Gem.configuration = nil + + assert_equal expected, Gem.configuration + end + + def test_self_datadir + foo = nil + + Dir.chdir @tempdir do + FileUtils.mkdir_p 'data' + File.open File.join('data', 'foo.txt'), 'w' do |fp| + fp.puts 'blah' + end + + foo = quick_gem 'foo' do |s| s.files = %w[data/foo.txt] end + install_gem foo + end + + Gem.source_index = nil + + gem 'foo' + + expected = File.join @gemhome, 'gems', foo.full_name, 'data', 'foo' + + assert_equal expected, Gem.datadir('foo') + end + + def test_self_datadir_nonexistent_package + assert_nil Gem.datadir('xyzzy') + end + + def test_self_default_dir + assert_match @default_dir_re, Gem.default_dir + end + + def test_self_default_exec_format + orig_RUBY_INSTALL_NAME = Gem::ConfigMap[:ruby_install_name] + Gem::ConfigMap[:ruby_install_name] = 'ruby' + + assert_equal '%s', Gem.default_exec_format + ensure + Gem::ConfigMap[:ruby_install_name] = orig_RUBY_INSTALL_NAME + end + + def test_self_default_exec_format_18 + orig_RUBY_INSTALL_NAME = Gem::ConfigMap[:ruby_install_name] + Gem::ConfigMap[:ruby_install_name] = 'ruby18' + + assert_equal '%s18', Gem.default_exec_format + ensure + Gem::ConfigMap[:ruby_install_name] = orig_RUBY_INSTALL_NAME + end + + def test_self_default_exec_format_jruby + orig_RUBY_INSTALL_NAME = Gem::ConfigMap[:ruby_install_name] + Gem::ConfigMap[:ruby_install_name] = 'jruby' + + assert_equal 'j%s', Gem.default_exec_format + ensure + Gem::ConfigMap[:ruby_install_name] = orig_RUBY_INSTALL_NAME + end + + def test_self_default_sources + assert_equal %w[http://rubygems.org/], Gem.default_sources + end + + def test_self_dir + assert_equal @gemhome, Gem.dir + end + + def test_self_ensure_gem_directories + FileUtils.rm_r @gemhome + Gem.use_paths @gemhome + + Gem.ensure_gem_subdirectories @gemhome + + assert File.directory?(File.join(@gemhome, "cache")) + end + + def test_self_ensure_gem_directories_missing_parents + gemdir = File.join @tempdir, 'a/b/c/gemdir' + FileUtils.rm_rf File.join(@tempdir, 'a') rescue nil + refute File.exist?(File.join(@tempdir, 'a')), + "manually remove #{File.join @tempdir, 'a'}, tests are broken" + Gem.use_paths gemdir + + Gem.ensure_gem_subdirectories gemdir + + assert File.directory?("#{gemdir}/cache") + end + + unless win_platform? then # only for FS that support write protection + def test_self_ensure_gem_directories_write_protected + gemdir = File.join @tempdir, "egd" + FileUtils.rm_r gemdir rescue nil + refute File.exist?(gemdir), "manually remove #{gemdir}, tests are broken" + FileUtils.mkdir_p gemdir + FileUtils.chmod 0400, gemdir + Gem.use_paths gemdir + + Gem.ensure_gem_subdirectories gemdir + + refute File.exist?("#{gemdir}/cache") + ensure + FileUtils.chmod 0600, gemdir + end + + def test_self_ensure_gem_directories_write_protected_parents + parent = File.join(@tempdir, "egd") + gemdir = "#{parent}/a/b/c" + + FileUtils.rm_r parent rescue nil + refute File.exist?(parent), "manually remove #{parent}, tests are broken" + FileUtils.mkdir_p parent + FileUtils.chmod 0400, parent + Gem.use_paths(gemdir) + + Gem.ensure_gem_subdirectories gemdir + + refute File.exist?("#{gemdir}/cache") + ensure + FileUtils.chmod 0600, parent + end + end + + def test_ensure_ssl_available + orig_Gem_ssl_available = Gem.ssl_available? + + Gem.ssl_available = true + Gem.ensure_ssl_available + + Gem.ssl_available = false + e = assert_raises Gem::Exception do Gem.ensure_ssl_available end + assert_equal 'SSL is not installed on this system', e.message + ensure + Gem.ssl_available = orig_Gem_ssl_available + end + + def test_self_find_files + discover_path = File.join 'lib', 'sff', 'discover.rb' + cwd = File.expand_path '..', __FILE__ + $LOAD_PATH.unshift cwd.dup + + foo1 = quick_gem 'sff', '1' do |s| + s.files << discover_path + end + + foo2 = quick_gem 'sff', '2' do |s| + s.files << discover_path + end + + path = File.join 'gems', foo1.full_name, discover_path + write_file(path) { |fp| fp.puts "# #{path}" } + + path = File.join 'gems', foo2.full_name, discover_path + write_file(path) { |fp| fp.puts "# #{path}" } + + @fetcher = Gem::FakeFetcher.new + Gem::RemoteFetcher.fetcher = @fetcher + + Gem.source_index = util_setup_spec_fetcher foo1, foo2 + + Gem.searcher = nil + + expected = [ + File.expand_path('../sff/discover.rb', __FILE__), + File.join(foo2.full_gem_path, discover_path), + File.join(foo1.full_gem_path, discover_path), + ] + + assert_equal expected, Gem.find_files('sff/discover') + assert_equal expected, Gem.find_files('sff/**.rb'), '[ruby-core:31730]' + ensure + assert_equal cwd, $LOAD_PATH.shift + end + + def test_self_latest_load_paths + util_make_gems + + expected = [ + File.join(@gemhome, *%W[gems #{@a3a.full_name} lib]), + File.join(@gemhome, *%W[gems #{@a_evil9.full_name} lib]), + File.join(@gemhome, *%W[gems #{@b2.full_name} lib]), + File.join(@gemhome, *%W[gems #{@c1_2.full_name} lib]), + File.join(@gemhome, *%W[gems #{@pl1.full_name} lib]), + ] + + assert_equal expected, Gem.latest_load_paths.sort + end + + def test_self_loaded_specs + foo = quick_gem 'foo' + install_gem foo + Gem.source_index = nil + + Gem.activate 'foo' + + assert_equal true, Gem.loaded_specs.keys.include?('foo') + end + + def util_path + ENV.delete "GEM_HOME" + ENV.delete "GEM_PATH" + end + + def test_self_path + assert_equal [Gem.dir], Gem.path + end + + def test_self_path_default + util_path + + if defined? APPLE_GEM_HOME + orig_APPLE_GEM_HOME = APPLE_GEM_HOME + Object.send :remove_const, :APPLE_GEM_HOME + end + Gem.instance_variable_set :@gem_path, nil + + assert_equal [Gem.default_path, Gem.dir].flatten, Gem.path + ensure + Object.const_set :APPLE_GEM_HOME, orig_APPLE_GEM_HOME + end + + unless win_platform? + def test_self_path_APPLE_GEM_HOME + util_path + + Gem.clear_paths + apple_gem_home = File.join @tempdir, 'apple_gem_home' + Gem.const_set :APPLE_GEM_HOME, apple_gem_home + + assert_includes Gem.path, apple_gem_home + ensure + Gem.send :remove_const, :APPLE_GEM_HOME + end + + def test_self_path_APPLE_GEM_HOME_GEM_PATH + Gem.clear_paths + ENV['GEM_PATH'] = @gemhome + apple_gem_home = File.join @tempdir, 'apple_gem_home' + Gem.const_set :APPLE_GEM_HOME, apple_gem_home + + refute Gem.path.include?(apple_gem_home) + ensure + Gem.send :remove_const, :APPLE_GEM_HOME + end + end + + def test_self_path_ENV_PATH + Gem.send :set_paths, nil + path_count = Gem.path.size + Gem.clear_paths + + ENV['GEM_PATH'] = @additional.join(File::PATH_SEPARATOR) + + assert_equal @additional, Gem.path[0,2] + + assert_equal path_count + @additional.size, Gem.path.size, + "extra path components: #{Gem.path[2..-1].inspect}" + assert_equal Gem.dir, Gem.path.last + end + + def test_self_path_duplicate + Gem.clear_paths + util_ensure_gem_dirs + dirs = @additional + [@gemhome] + [File.join(@tempdir, 'a')] + + ENV['GEM_HOME'] = @gemhome + ENV['GEM_PATH'] = dirs.join File::PATH_SEPARATOR + + assert_equal @gemhome, Gem.dir + + paths = [Gem.dir] + assert_equal @additional + paths, Gem.path + end + + def test_self_path_overlap + Gem.clear_paths + + util_ensure_gem_dirs + ENV['GEM_HOME'] = @gemhome + ENV['GEM_PATH'] = @additional.join(File::PATH_SEPARATOR) + + assert_equal @gemhome, Gem.dir + + paths = [Gem.dir] + assert_equal @additional + paths, Gem.path + end + + def test_self_platforms + assert_equal [Gem::Platform::RUBY, Gem::Platform.local], Gem.platforms + end + + def test_self_prefix + file_name = File.expand_path __FILE__ + + prefix = File.dirname File.dirname(file_name) + prefix = File.dirname prefix if File.basename(prefix) == 'test' + + assert_equal prefix, Gem.prefix + end + + def test_self_prefix_libdir + orig_libdir = Gem::ConfigMap[:libdir] + + file_name = File.expand_path __FILE__ + prefix = File.dirname File.dirname(file_name) + prefix = File.dirname prefix if File.basename(prefix) == 'test' + + Gem::ConfigMap[:libdir] = prefix + + assert_nil Gem.prefix + ensure + Gem::ConfigMap[:libdir] = orig_libdir + end + + def test_self_prefix_sitelibdir + orig_sitelibdir = Gem::ConfigMap[:sitelibdir] + + file_name = File.expand_path __FILE__ + prefix = File.dirname File.dirname(file_name) + prefix = File.dirname prefix if File.basename(prefix) == 'test' + + Gem::ConfigMap[:sitelibdir] = prefix + + assert_nil Gem.prefix + ensure + Gem::ConfigMap[:sitelibdir] = orig_sitelibdir + end + + def test_self_refresh + util_make_gems + + a1_spec = File.join @gemhome, "specifications", @a1.spec_name + + FileUtils.mv a1_spec, @tempdir + + refute Gem.source_index.gems.include?(@a1.full_name) + + FileUtils.mv File.join(@tempdir, @a1.spec_name), a1_spec + + Gem.refresh + + assert_includes Gem.source_index.gems, @a1.full_name + assert_equal nil, Gem.instance_variable_get(:@searcher) + end + + def test_self_required_location + util_make_gems + + assert_equal File.join(@tempdir, *%w[gemhome gems c-1.2 lib code.rb]), + Gem.required_location("c", "code.rb") + assert_equal File.join(@tempdir, *%w[gemhome gems a-1 lib code.rb]), + Gem.required_location("a", "code.rb", "< 2") + assert_equal File.join(@tempdir, *%w[gemhome gems a-2 lib code.rb]), + Gem.required_location("a", "code.rb", "= 2") + end + + def test_self_ruby_escaping_spaces_in_path + orig_ruby = Gem.ruby + orig_bindir = Gem::ConfigMap[:bindir] + orig_ruby_install_name = Gem::ConfigMap[:ruby_install_name] + orig_exe_ext = Gem::ConfigMap[:EXEEXT] + + Gem::ConfigMap[:bindir] = "C:/Ruby 1.8/bin" + Gem::ConfigMap[:ruby_install_name] = "ruby" + Gem::ConfigMap[:EXEEXT] = ".exe" + Gem.instance_variable_set("@ruby", nil) + + assert_equal "\"C:/Ruby 1.8/bin/ruby.exe\"", Gem.ruby + ensure + Gem.instance_variable_set("@ruby", orig_ruby) + Gem::ConfigMap[:bindir] = orig_bindir + Gem::ConfigMap[:ruby_install_name] = orig_ruby_install_name + Gem::ConfigMap[:EXEEXT] = orig_exe_ext + end + + def test_self_ruby_path_without_spaces + orig_ruby = Gem.ruby + orig_bindir = Gem::ConfigMap[:bindir] + orig_ruby_install_name = Gem::ConfigMap[:ruby_install_name] + orig_exe_ext = Gem::ConfigMap[:EXEEXT] + + Gem::ConfigMap[:bindir] = "C:/Ruby18/bin" + Gem::ConfigMap[:ruby_install_name] = "ruby" + Gem::ConfigMap[:EXEEXT] = ".exe" + Gem.instance_variable_set("@ruby", nil) + + assert_equal "C:/Ruby18/bin/ruby.exe", Gem.ruby + ensure + Gem.instance_variable_set("@ruby", orig_ruby) + Gem::ConfigMap[:bindir] = orig_bindir + Gem::ConfigMap[:ruby_install_name] = orig_ruby_install_name + Gem::ConfigMap[:EXEEXT] = orig_exe_ext + end + + def test_self_ruby_version_1_8_5 + util_set_RUBY_VERSION '1.8.5' + + assert_equal Gem::Version.new('1.8.5'), Gem.ruby_version + ensure + util_restore_RUBY_VERSION + end + + def test_self_ruby_version_1_8_6p287 + util_set_RUBY_VERSION '1.8.6', 287 + + assert_equal Gem::Version.new('1.8.6.287'), Gem.ruby_version + ensure + util_restore_RUBY_VERSION + end + + def test_self_ruby_version_1_9_2dev_r23493 + util_set_RUBY_VERSION '1.9.2', -1, 23493 + + assert_equal Gem::Version.new('1.9.2.dev.23493'), Gem.ruby_version + ensure + util_restore_RUBY_VERSION + end + + def test_self_searcher + assert_kind_of Gem::GemPathSearcher, Gem.searcher + end + + def test_self_set_paths + other = File.join @tempdir, 'other' + path = [@userhome, other].join File::PATH_SEPARATOR + Gem.send :set_paths, path + + assert_equal [@userhome, other, @gemhome], Gem.path + end + + def test_self_set_paths_nonexistent_home + ENV['GEM_HOME'] = @gemhome + Gem.clear_paths + + other = File.join @tempdir, 'other' + + ENV['HOME'] = other + + Gem.send :set_paths, other + + assert_equal [other, @gemhome], Gem.path + end + + def test_self_source_index + assert_kind_of Gem::SourceIndex, Gem.source_index + end + + def test_self_sources + assert_equal %w[http://gems.example.com/], Gem.sources + end + + def test_ssl_available_eh + orig_Gem_ssl_available = Gem.ssl_available? + + Gem.ssl_available = true + assert_equal true, Gem.ssl_available? + + Gem.ssl_available = false + assert_equal false, Gem.ssl_available? + ensure + Gem.ssl_available = orig_Gem_ssl_available + end + + def test_self_use_paths + util_ensure_gem_dirs + + Gem.use_paths @gemhome, @additional + + assert_equal @gemhome, Gem.dir + assert_equal @additional + [Gem.dir], Gem.path + end + + def test_self_user_dir + assert_equal File.join(@userhome, '.gem', Gem.ruby_engine, + Gem::ConfigMap[:ruby_version]), Gem.user_dir + end + + def test_self_user_home + if ENV['HOME'] then + assert_equal ENV['HOME'], Gem.user_home + else + assert true, 'count this test' + end + end + + if Gem.win_platform? then + def test_self_user_home_userprofile + skip 'Ruby 1.9 properly handles ~ path expansion' unless '1.9' > RUBY_VERSION + + Gem.clear_paths + + # safe-keep env variables + orig_home, orig_user_profile = ENV['HOME'], ENV['USERPROFILE'] + + # prepare for the test + ENV.delete('HOME') + ENV['USERPROFILE'] = "W:\\Users\\RubyUser" + + assert_equal 'W:/Users/RubyUser', Gem.user_home + + ensure + ENV['HOME'] = orig_home + ENV['USERPROFILE'] = orig_user_profile + end + + def test_self_user_home_user_drive_and_path + skip 'Ruby 1.9 properly handles ~ path expansion' unless '1.9' > RUBY_VERSION + + Gem.clear_paths + + # safe-keep env variables + orig_home, orig_user_profile = ENV['HOME'], ENV['USERPROFILE'] + orig_home_drive, orig_home_path = ENV['HOMEDRIVE'], ENV['HOMEPATH'] + + # prepare the environment + ENV.delete('HOME') + ENV.delete('USERPROFILE') + ENV['HOMEDRIVE'] = 'Z:' + ENV['HOMEPATH'] = "\\Users\\RubyUser" + + assert_equal 'Z:/Users/RubyUser', Gem.user_home + + ensure + ENV['HOME'] = orig_home + ENV['USERPROFILE'] = orig_user_profile + ENV['HOMEDRIVE'] = orig_home_drive + ENV['HOMEPATH'] = orig_home_path + end + end + + def test_load_plugins + plugin_path = File.join "lib", "rubygems_plugin.rb" + + Dir.chdir @tempdir do + FileUtils.mkdir_p 'lib' + File.open plugin_path, "w" do |fp| + fp.puts "TestGem::TEST_SPEC_PLUGIN_LOAD = :loaded" + end + + foo = quick_gem 'foo', '1' do |s| + s.files << plugin_path + end + + install_gem foo + end + + Gem.source_index = nil + + gem 'foo' + + Gem.load_plugins + + assert_equal :loaded, TEST_SPEC_PLUGIN_LOAD + end + + def test_load_env_plugins + with_plugin('load') { Gem.load_env_plugins } + assert_equal :loaded, TEST_PLUGIN_LOAD + + util_remove_interrupt_command + + # Should attempt to cause a StandardError + with_plugin('standarderror') { Gem.load_env_plugins } + assert_equal :loaded, TEST_PLUGIN_STANDARDERROR + + util_remove_interrupt_command + + # Should attempt to cause an Exception + with_plugin('exception') { Gem.load_env_plugins } + assert_equal :loaded, TEST_PLUGIN_EXCEPTION + end + + def with_plugin(path) + test_plugin_path = File.expand_path "../plugin/#{path}", __FILE__ + + # A single test plugin should get loaded once only, in order to preserve + # sane test semantics. + refute_includes $LOAD_PATH, test_plugin_path + $LOAD_PATH.unshift test_plugin_path + + capture_io do + yield + end + ensure + $LOAD_PATH.delete test_plugin_path + end + + def util_ensure_gem_dirs + Gem.ensure_gem_subdirectories @gemhome + @additional.each do |dir| + Gem.ensure_gem_subdirectories @gemhome + end + end + + def util_exec_gem + spec, _ = quick_gem 'a', '4' do |s| + s.default_executable = 'exec' + s.executables = ['exec', 'abin'] + end + + @exec_path = File.join spec.full_gem_path, spec.bindir, 'exec' + @abin_path = File.join spec.full_gem_path, spec.bindir, 'abin' + end + + def util_set_RUBY_VERSION(version, patchlevel = nil, revision = nil) + if Gem.instance_variables.include? :@ruby_version or + Gem.instance_variables.include? '@ruby_version' then + Gem.send :remove_instance_variable, :@ruby_version + end + + @RUBY_VERSION = RUBY_VERSION + @RUBY_PATCHLEVEL = RUBY_PATCHLEVEL if defined?(RUBY_PATCHLEVEL) + @RUBY_REVISION = RUBY_REVISION if defined?(RUBY_REVISION) + + Object.send :remove_const, :RUBY_VERSION + Object.send :remove_const, :RUBY_PATCHLEVEL if defined?(RUBY_PATCHLEVEL) + Object.send :remove_const, :RUBY_REVISION if defined?(RUBY_REVISION) + + Object.const_set :RUBY_VERSION, version + Object.const_set :RUBY_PATCHLEVEL, patchlevel if patchlevel + Object.const_set :RUBY_REVISION, revision if revision + end + + def util_restore_RUBY_VERSION + Object.send :remove_const, :RUBY_VERSION + Object.send :remove_const, :RUBY_PATCHLEVEL if defined?(RUBY_PATCHLEVEL) + Object.send :remove_const, :RUBY_REVISION if defined?(RUBY_REVISION) + + Object.const_set :RUBY_VERSION, @RUBY_VERSION + Object.const_set :RUBY_PATCHLEVEL, @RUBY_PATCHLEVEL if + defined?(@RUBY_PATCHLEVEL) + Object.const_set :RUBY_REVISION, @RUBY_REVISION if + defined?(@RUBY_REVISION) + end + + def util_remove_interrupt_command + Gem::Commands.send :remove_const, :InterruptCommand if + Gem::Commands.const_defined? :InterruptCommand + end + +end + diff --git a/test/rubygems/test_gem_version.rb b/test/rubygems/test_gem_version.rb new file mode 100644 index 00000000..22c449fe --- /dev/null +++ b/test/rubygems/test_gem_version.rb @@ -0,0 +1,181 @@ +require File.expand_path('../gemutilities', __FILE__) +require "rubygems/version" + +class TestGemVersion < RubyGemTestCase + + def test_bump + assert_bumped_version_equal "5.3", "5.2.4" + end + + def test_bump_alpha + assert_bumped_version_equal "5.3", "5.2.4.a" + end + + def test_bump_alphanumeric + assert_bumped_version_equal "5.3", "5.2.4.a10" + end + + def test_bump_trailing_zeros + assert_bumped_version_equal "5.1", "5.0.0" + end + + def test_bump_one_level + assert_bumped_version_equal "6", "5" + end + + # FIX: For "legacy reasons," any object that responds to +version+ + # is returned unchanged. I'm not certain why. + + def test_class_create + fake = Object.new + def fake.version; "1.0" end + + assert_same fake, Gem::Version.create(fake) + assert_nil Gem::Version.create(nil) + assert_equal v("5.1"), Gem::Version.create("5.1") + end + + def test_eql_eh + assert_version_eql "1.2", "1.2" + refute_version_eql "1.2", "1.2.0" + refute_version_eql "1.2", "1.3" + refute_version_eql "1.2.b1", "1.2.b.1" + end + + def test_equals2 + assert_version_equal "1.2", "1.2" + refute_version_equal "1.2", "1.3" + assert_version_equal "1.2.b1", "1.2.b.1" + end + + # REVISIT: consider removing as too impl-bound + def test_hash + assert_equal v("1.2").hash, v("1.2").hash + refute_equal v("1.2").hash, v("1.3").hash + refute_equal v("1.2").hash, v("1.2.0").hash + end + + def test_initialize + ["1.0", "1.0 ", " 1.0 ", "1.0\n", "\n1.0\n"].each do |good| + assert_version_equal "1.0", good + end + + assert_version_equal "1", 1 + end + + def test_initialize_bad + ["junk", "1.0\n2.0"].each do |bad| + e = assert_raises ArgumentError do + Gem::Version.new bad + end + + assert_equal "Malformed version number string #{bad}", e.message + end + end + + def test_prerelease + assert_prerelease "1.2.0.a" + assert_prerelease "2.9.b" + assert_prerelease "22.1.50.0.d" + assert_prerelease "1.2.d.42" + + assert_prerelease '1.A' + + refute_prerelease "1.2.0" + refute_prerelease "2.9" + refute_prerelease "22.1.50.0" + end + + def test_release + assert_release_equal "1.2.0", "1.2.0.a" + assert_release_equal "1.1", "1.1.rc10" + assert_release_equal "1.9.3", "1.9.3.alpha.5" + assert_release_equal "1.9.3", "1.9.3" + end + + def test_spaceship + assert_equal( 0, v("1.0") <=> v("1.0.0")) + assert_equal( 1, v("1.0") <=> v("1.0.a")) + assert_equal( 1, v("1.8.2") <=> v("0.0.0")) + assert_equal( 1, v("1.8.2") <=> v("1.8.2.a")) + assert_equal( 1, v("1.8.2.b") <=> v("1.8.2.a")) + assert_equal(-1, v("1.8.2.a") <=> v("1.8.2")) + assert_equal( 1, v("1.8.2.a10") <=> v("1.8.2.a9")) + assert_equal( 0, v("") <=> v("0")) + + assert_nil v("1.0") <=> "whatever" + end + + def test_spermy_recommendation + assert_spermy_equal "~> 1.0", "1" + assert_spermy_equal "~> 1.0", "1.0" + assert_spermy_equal "~> 1.2", "1.2" + assert_spermy_equal "~> 1.2", "1.2.0" + assert_spermy_equal "~> 1.2", "1.2.3" + assert_spermy_equal "~> 1.2", "1.2.3.a.4" + end + + def test_to_s + assert_equal "5.2.4", v("5.2.4").to_s + end + + # Asserts that +version+ is a prerelease. + + def assert_prerelease version + assert v(version).prerelease?, "#{version} is a prerelease" + end + + # Assert that +expected+ is the "spermy" recommendation for +version". + + def assert_spermy_equal expected, version + assert_equal expected, v(version).spermy_recommendation + end + + # Assert that bumping the +unbumped+ version yields the +expected+. + + def assert_bumped_version_equal expected, unbumped + assert_version_equal expected, v(unbumped).bump + end + + # Assert that +release+ is the correct non-prerelease +version+. + + def assert_release_equal release, version + assert_version_equal release, v(version).release + end + + # Assert that two versions are equal. Handles strings or + # Gem::Version instances. + + def assert_version_equal expected, actual + assert_equal v(expected), v(actual) + end + + # Assert that two versions are eql?. Checks both directions. + + def assert_version_eql first, second + first, second = v(first), v(second) + assert first.eql?(second), "#{first} is eql? #{second}" + assert second.eql?(first), "#{second} is eql? #{first}" + end + + # Refute the assumption that +version+ is a prerelease. + + def refute_prerelease version + refute v(version).prerelease?, "#{version} is NOT a prerelease" + end + + # Refute the assumption that two versions are eql?. Checks both + # directions. + + def refute_version_eql first, second + first, second = v(first), v(second) + refute first.eql?(second), "#{first} is NOT eql? #{second}" + refute second.eql?(first), "#{second} is NOT eql? #{first}" + end + + # Refute the assumption that the two versions are equal?. + + def refute_version_equal unexpected, actual + refute_equal v(unexpected), v(actual) + end +end From 8d703dc32d47297a11f405de975707d3e7452151 Mon Sep 17 00:00:00 2001 From: Ryan Davis Date: Fri, 14 Jan 2011 17:40:38 -0800 Subject: [PATCH 020/707] Moved test/* to test/rubygems to match 1.9 --- test/rubygems/test_gem_requirement.rb | 292 ++++++++++++++++++++++++++ 1 file changed, 292 insertions(+) create mode 100644 test/rubygems/test_gem_requirement.rb diff --git a/test/rubygems/test_gem_requirement.rb b/test/rubygems/test_gem_requirement.rb new file mode 100644 index 00000000..ba82f019 --- /dev/null +++ b/test/rubygems/test_gem_requirement.rb @@ -0,0 +1,292 @@ +require File.expand_path('../gemutilities', __FILE__) +require "rubygems/requirement" + +class TestGemRequirement < RubyGemTestCase + + def test_equals2 + r = req "= 1.2" + assert_equal r, r.dup + assert_equal r.dup, r + + refute_requirement_equal "= 1.2", "= 1.3" + refute_requirement_equal "= 1.3", "= 1.2" + + refute_equal Object.new, req("= 1.2") + refute_equal req("= 1.2"), Object.new + end + + def test_initialize + assert_requirement_equal "= 2", "2" + assert_requirement_equal "= 2", ["2"] + assert_requirement_equal "= 2", v(2) + end + + def test_class_available_as_gem_version_requirement + assert_same Gem::Requirement, Gem::Version::Requirement, + "Gem::Version::Requirement is aliased for old YAML compatibility." + end + + def test_parse + assert_equal ['=', Gem::Version.new(1)], Gem::Requirement.parse(' 1') + assert_equal ['=', Gem::Version.new(1)], Gem::Requirement.parse('= 1') + assert_equal ['>', Gem::Version.new(1)], Gem::Requirement.parse('> 1') + assert_equal ['=', Gem::Version.new(1)], Gem::Requirement.parse("=\n1") + + assert_equal ['=', Gem::Version.new(2)], + Gem::Requirement.parse(Gem::Version.new('2')) + end + + def test_parse_bad + e = assert_raises ArgumentError do + Gem::Requirement.parse nil + end + + assert_equal 'Illformed requirement [nil]', e.message + + e = assert_raises ArgumentError do + Gem::Requirement.parse "" + end + + assert_equal 'Illformed requirement [""]', e.message + end + + def test_prerelease_eh + r = req '= 1' + + refute r.prerelease? + + r = req '= 1.a' + + assert r.prerelease? + + r = req '> 1.a', '< 2' + + assert r.prerelease? + end + + def test_satisfied_by_eh_bang_equal + r = req '!= 1.2' + + assert_satisfied_by nil, r + assert_satisfied_by "1.1", r + refute_satisfied_by "1.2", r + assert_satisfied_by "1.3", r + end + + def test_satisfied_by_eh_blank + r = req "1.2" + + refute_satisfied_by nil, r + refute_satisfied_by "1.1", r + assert_satisfied_by "1.2", r + refute_satisfied_by "1.3", r + end + + def test_satisfied_by_eh_equal + r = req "= 1.2" + + refute_satisfied_by nil, r + refute_satisfied_by "1.1", r + assert_satisfied_by "1.2", r + refute_satisfied_by "1.3", r + end + + def test_satisfied_by_eh_gt + r = req "> 1.2" + + refute_satisfied_by "1.1", r + refute_satisfied_by "1.2", r + assert_satisfied_by "1.3", r + + assert_raises NoMethodError do + r.satisfied_by? nil + end + end + + def test_satisfied_by_eh_gte + r = req ">= 1.2" + + refute_satisfied_by "1.1", r + assert_satisfied_by "1.2", r + assert_satisfied_by "1.3", r + + assert_raises NoMethodError do + r.satisfied_by? nil + end + end + + def test_satisfied_by_eh_list + r = req "> 1.1", "< 1.3" + + refute_satisfied_by "1.1", r + assert_satisfied_by "1.2", r + refute_satisfied_by "1.3", r + + assert_raises NoMethodError do + r.satisfied_by? nil + end + end + + def test_satisfied_by_eh_lt + r = req "< 1.2" + + assert_satisfied_by "1.1", r + refute_satisfied_by "1.2", r + refute_satisfied_by "1.3", r + + assert_raises NoMethodError do + r.satisfied_by? nil + end + end + + def test_satisfied_by_eh_lte + r = req "<= 1.2" + + assert_satisfied_by "1.1", r + assert_satisfied_by "1.2", r + refute_satisfied_by "1.3", r + + assert_raises NoMethodError do + r.satisfied_by? nil + end + end + + def test_satisfied_by_eh_tilde_gt + r = req "~> 1.2" + + refute_satisfied_by "1.1", r + assert_satisfied_by "1.2", r + assert_satisfied_by "1.3", r + + assert_raises NoMethodError do + r.satisfied_by? nil + end + end + + def test_satisfied_by_eh_good + assert_satisfied_by "0.2.33", "= 0.2.33" + assert_satisfied_by "0.2.34", "> 0.2.33" + assert_satisfied_by "1.0", "= 1.0" + assert_satisfied_by "1.0", "1.0" + assert_satisfied_by "1.8.2", "> 1.8.0" + assert_satisfied_by "1.112", "> 1.111" + assert_satisfied_by "0.2", "> 0.0.0" + assert_satisfied_by "0.0.0.0.0.2", "> 0.0.0" + assert_satisfied_by "0.0.1.0", "> 0.0.0.1" + assert_satisfied_by "10.3.2", "> 9.3.2" + assert_satisfied_by "1.0.0.0", "= 1.0" + assert_satisfied_by "10.3.2", "!= 9.3.4" + assert_satisfied_by "10.3.2", "> 9.3.2" + assert_satisfied_by "10.3.2", "> 9.3.2" + assert_satisfied_by " 9.3.2", ">= 9.3.2" + assert_satisfied_by "9.3.2 ", ">= 9.3.2" + assert_satisfied_by "", "= 0" + assert_satisfied_by "", "< 0.1" + assert_satisfied_by " ", "< 0.1 " + assert_satisfied_by "", " < 0.1" + assert_satisfied_by " ", "> 0.a " + assert_satisfied_by "", " > 0.a" + assert_satisfied_by "3.1", "< 3.2.rc1" + assert_satisfied_by "3.2.0", "> 3.2.0.rc1" + assert_satisfied_by "3.2.0.rc2", "> 3.2.0.rc1" + assert_satisfied_by "3.0.rc2", "< 3.0" + assert_satisfied_by "3.0.rc2", "< 3.0.0" + assert_satisfied_by "3.0.rc2", "< 3.0.1" + end + + def test_illformed_requirements + [ ">>> 1.3.5", "> blah" ].each do |rq| + assert_raises ArgumentError, "req [#{rq}] should fail" do + Gem::Requirement.new rq + end + end + end + + def test_satisfied_by_eh_boxed + refute_satisfied_by "1.3", "~> 1.4" + assert_satisfied_by "1.4", "~> 1.4" + assert_satisfied_by "1.5", "~> 1.4" + refute_satisfied_by "2.0", "~> 1.4" + + refute_satisfied_by "1.3", "~> 1.4.4" + refute_satisfied_by "1.4", "~> 1.4.4" + assert_satisfied_by "1.4.4", "~> 1.4.4" + assert_satisfied_by "1.4.5", "~> 1.4.4" + refute_satisfied_by "1.5", "~> 1.4.4" + refute_satisfied_by "2.0", "~> 1.4.4" + + refute_satisfied_by "1.1.pre", "~> 1.0.0" + refute_satisfied_by "1.1.pre", "~> 1.1" + refute_satisfied_by "2.0.a", "~> 1.0" + refute_satisfied_by "2.0.a", "~> 2.0" + end + + def test_satisfied_by_eh_multiple + req = [">= 1.4", "<= 1.6", "!= 1.5"] + + refute_satisfied_by "1.3", req + assert_satisfied_by "1.4", req + refute_satisfied_by "1.5", req + assert_satisfied_by "1.6", req + refute_satisfied_by "1.7", req + refute_satisfied_by "2.0", req + end + + def test_satisfied_by_boxed + refute_satisfied_by "1.3", "~> 1.4" + assert_satisfied_by "1.4", "~> 1.4" + assert_satisfied_by "1.5", "~> 1.4" + refute_satisfied_by "2.0", "~> 1.4" + + refute_satisfied_by "1.3", "~> 1.4.4" + refute_satisfied_by "1.4", "~> 1.4.4" + assert_satisfied_by "1.4.4", "~> 1.4.4" + assert_satisfied_by "1.4.5", "~> 1.4.4" + refute_satisfied_by "1.5", "~> 1.4.4" + refute_satisfied_by "2.0", "~> 1.4.4" + end + + def test_bad + refute_satisfied_by "", "> 0.1" + refute_satisfied_by "1.2.3", "!= 1.2.3" + refute_satisfied_by "1.2.003.0.0", "!= 1.02.3" + refute_satisfied_by "4.5.6", "< 1.2.3" + refute_satisfied_by "1.0", "> 1.1" + refute_satisfied_by "", "= 0.1" + refute_satisfied_by "1.1.1", "> 1.1.1" + refute_satisfied_by "1.2", "= 1.1" + refute_satisfied_by "1.40", "= 1.1" + refute_satisfied_by "1.3", "= 1.40" + refute_satisfied_by "9.3.3", "<= 9.3.2" + refute_satisfied_by "9.3.1", ">= 9.3.2" + refute_satisfied_by "9.3.03", "<= 9.3.2" + refute_satisfied_by "1.0.0.1", "= 1.0" + end + + # Assert that two requirements are equal. Handles Gem::Requirements, + # strings, arrays, numbers, and versions. + + def assert_requirement_equal expected, actual + assert_equal req(expected), req(actual) + end + + # Assert that +version+ satisfies +requirement+. + + def assert_satisfied_by version, requirement + assert req(requirement).satisfied_by?(v(version)), + "#{requirement} is satisfied by #{version}" + end + + # Refute the assumption that two requirements are equal. + + def refute_requirement_equal unexpected, actual + refute_equal req(unexpected), req(actual) + end + + # Refute the assumption that +version+ satisfies +requirement+. + + def refute_satisfied_by version, requirement + refute req(requirement).satisfied_by?(v(version)), + "#{requirement} is not satisfied by #{version}" + end +end From b19902a663471edad339a33500af61ef3ed08693 Mon Sep 17 00:00:00 2001 From: Ryan Davis Date: Fri, 14 Jan 2011 18:09:46 -0800 Subject: [PATCH 021/707] test require cleanup --- test/rubygems/test_gem.rb | 2 +- test/rubygems/test_gem_version.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 83fd6f5e..57c0a8c7 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1,4 +1,4 @@ -require File.expand_path('../gemutilities', __FILE__) +require "test/rubygems/gemutilities" require 'rubygems' require 'rubygems/gem_openssl' require 'rubygems/installer' diff --git a/test/rubygems/test_gem_version.rb b/test/rubygems/test_gem_version.rb index 22c449fe..28e0d2e4 100644 --- a/test/rubygems/test_gem_version.rb +++ b/test/rubygems/test_gem_version.rb @@ -1,4 +1,4 @@ -require File.expand_path('../gemutilities', __FILE__) +require "test/rubygems/gemutilities" require "rubygems/version" class TestGemVersion < RubyGemTestCase From 0664ad19457af9484bd45432fa74d71c2e1db34c Mon Sep 17 00:00:00 2001 From: Ryan Davis Date: Fri, 14 Jan 2011 18:09:46 -0800 Subject: [PATCH 022/707] test require cleanup --- test/rubygems/test_gem_requirement.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/rubygems/test_gem_requirement.rb b/test/rubygems/test_gem_requirement.rb index ba82f019..725dc131 100644 --- a/test/rubygems/test_gem_requirement.rb +++ b/test/rubygems/test_gem_requirement.rb @@ -1,4 +1,4 @@ -require File.expand_path('../gemutilities', __FILE__) +require "test/rubygems/gemutilities" require "rubygems/requirement" class TestGemRequirement < RubyGemTestCase From f805bec87ddbbf173ec216bfc776f7c912fac614 Mon Sep 17 00:00:00 2001 From: Eric Hodel Date: Wed, 19 Jan 2011 14:56:09 -0800 Subject: [PATCH 023/707] Move RubyGemTestCase to Gem::TestCase that lives in lib/ along with other test cases. Also, fix some uninstaller tests that failed and should never have worked in the first place. --- test/rubygems/test_gem.rb | 4 ++-- test/rubygems/test_gem_version.rb | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 57c0a8c7..c7e0e837 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1,11 +1,11 @@ -require "test/rubygems/gemutilities" +require 'rubygems/test_case' require 'rubygems' require 'rubygems/gem_openssl' require 'rubygems/installer' require 'pathname' require 'tmpdir' -class TestGem < RubyGemTestCase +class TestGem < Gem::TestCase def setup super diff --git a/test/rubygems/test_gem_version.rb b/test/rubygems/test_gem_version.rb index 28e0d2e4..f578063e 100644 --- a/test/rubygems/test_gem_version.rb +++ b/test/rubygems/test_gem_version.rb @@ -1,7 +1,7 @@ -require "test/rubygems/gemutilities" +require 'rubygems/test_case' require "rubygems/version" -class TestGemVersion < RubyGemTestCase +class TestGemVersion < Gem::TestCase def test_bump assert_bumped_version_equal "5.3", "5.2.4" From 13d2e243ec02822973ea48a332e7c6e0f641c672 Mon Sep 17 00:00:00 2001 From: Eric Hodel Date: Wed, 19 Jan 2011 14:56:09 -0800 Subject: [PATCH 024/707] Move RubyGemTestCase to Gem::TestCase that lives in lib/ along with other test cases. Also, fix some uninstaller tests that failed and should never have worked in the first place. --- test/rubygems/test_gem_requirement.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/rubygems/test_gem_requirement.rb b/test/rubygems/test_gem_requirement.rb index 725dc131..4ee31d6d 100644 --- a/test/rubygems/test_gem_requirement.rb +++ b/test/rubygems/test_gem_requirement.rb @@ -1,7 +1,7 @@ -require "test/rubygems/gemutilities" +require 'rubygems/test_case' require "rubygems/requirement" -class TestGemRequirement < RubyGemTestCase +class TestGemRequirement < Gem::TestCase def test_equals2 r = req "= 1.2" From 76a08a52fa2b40ffe3c35f0efdef9b4dd0f3ee31 Mon Sep 17 00:00:00 2001 From: Ryan Davis Date: Fri, 11 Feb 2011 17:58:57 -0800 Subject: [PATCH 025/707] AWESOME! Added the _first_ tests for Gem.activate. WTF?!? --- test/rubygems/test_gem.rb | 274 ++++++++++++++++++++++++++++++-------- 1 file changed, 220 insertions(+), 54 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index c7e0e837..d12f3cad 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -20,6 +20,172 @@ def setup util_remove_interrupt_command end + def assert_activate expected, *specs + Gem.activate specs.first.name + + expected.each do |spec| + assert_includes Gem.loaded_specs.values.map(&:full_name), spec + end + end + + def test_self_activate + foo = util_spec 'foo', '1' + + assert_activate %w[foo-1], foo + end + + def test_self_activate_loaded + foo = util_spec 'foo', '1' + assert Gem.activate 'foo' + refute Gem.activate 'foo' + end + + ## + # [A1] depends on + # [B] > 0 (satisfied by 2.0) + # [B1] depends on + # [C] > 0 (satisfied by 1.0) + # [B2] depends on nothing! + # [C1] depends on nothing + + def test_self_activate_dropped + a1, = util_spec 'a', '1', 'b' => nil + b1, = util_spec 'b', '1', 'c' => nil + b2, = util_spec 'b', '2' + c1, = util_spec 'c', '1' + + assert_activate %w[b-2 a-1], a1, b1, b2, c1 + end + + ## + # [A] depends on + # [B] >= 1.0 (satisfied by 1.1) depends on + # [Z] + # [C] >= 1.0 depends on + # [B] = 1.0 + # + # and should backtrack to resolve using b-1.0, pruning Z from the + # resolve. + + def test_self_activate_raggi_the_edgecase_generator + a, _ = util_spec 'a', '1.0', 'b' => '>= 1.0', 'c' => '>= 1.0' + b1, _ = util_spec 'b', '1.0' + b2, _ = util_spec 'b', '1.1', 'z' => '>= 1.0' + c, _ = util_spec 'c', '1.0', 'b' => '= 1.0' + + assert_activate %w[b-1.0 c-1.0 a-1.0], a, b1, b2, c + end + + ## + # [A] depends on + # [B] >= 1.0 (satisfied by 2.0) + # [C] = 1.0 depends on + # [B] ~> 1.0 + # + # and should resolve using b-1.0 + + def test_self_activate_over + a, _ = util_spec 'a', '1.0', 'b' => '>= 1.0', 'c' => '= 1.0' + b1, _ = util_spec 'b', '1.0' + b2, _ = util_spec 'b', '2.0' + c, _ = util_spec 'c', '1.0', 'b' => '~> 1.0' + + assert_activate %w[b-1.0 c-1.0 a-1.0], a, b1, b2, c + end + + ## + # [A] depends on + # [B] ~> 1.0 (satisfied by 1.1) + # [C] = 1.0 depends on + # [B] = 1.0 + # + # and should resolve using b-1.0 + # + # TODO: this is not under, but over... under would require depth + # first resolve through a dependency that is later pruned. + + def test_self_activate_under + a, _ = util_spec 'a', '1.0', 'b' => '~> 1.0', 'c' => '= 1.0' + b10, _ = util_spec 'b', '1.0' + b11, _ = util_spec 'b', '1.1' + c, _ = util_spec 'c', '1.0', 'b' => '= 1.0' + + assert_activate %w[b-1.0 c-1.0 a-1.0], a, b10, b11, c + end + + # under + # + # [A] depends on + # [B] ~> 1.0 (satisfied by 1.0) + # [C] = 1.0 depends on + # [B] = 2.0 + + def test_self_activate_divergent + a, _ = util_spec 'a', '1.0', 'b' => '~> 1.0', 'c' => '= 1.0' + b1, _ = util_spec 'b', '1.0' + b2, _ = util_spec 'b', '2.0' + c, _ = util_spec 'c', '1.0', 'b' => '= 2.0' + + assert_raises Gem::DependencyError do + assert_activate :ignored, a, b1, b2, c + end + end + + def test_self_activate_platform_alternate + util_setup_wxyz + util_set_arch 'cpu-my_platform1' + + assert_activate %w[x-1-cpu-my_platform-1 w-1], @w1, @x1_m + end + + def test_self_activate_platform_bump + util_setup_wxyz + + assert_activate %w[y-1 z-1], @z1, @y1 + end + + def test_self_activate_prerelease + util_setup_c1_pre + + assert_activate %w[a-1.a b-1 c-1.a], @c1_pre, @a1_pre, @b1 + end + + def test_self_activate_old_required + util_setup_d + e1, = util_spec 'e', '1', 'd' => '= 1' + util_clear_gems + + assert_activate %w[d-1 e-1], e1, @d1, @d2 + end + + def util_setup_c1_pre + @c1_pre = util_spec 'c', '1.a', "a" => "1.a", "b" => "1" + end + + def util_setup_d + @d1 = util_spec 'd', '1' + @d2 = util_spec 'd', '2' + end + + def util_setup_wxyz + @x1_m = util_spec 'x', '1' do |s| + s.platform = Gem::Platform.new %w[cpu my_platform 1] + end + + @x1_o = util_spec 'x', '1' do |s| + s.platform = Gem::Platform.new %w[cpu other_platform 1] + end + + @w1 = util_spec 'w', '1', 'x' => nil + + @y1 = util_spec 'y', '1' + @y1_1_p = util_spec 'y', '1.1' do |s| + s.platform = Gem::Platform.new %w[cpu my_platform 1] + end + + @z1 = util_spec 'z', '1', 'y' => nil + end + def test_self_all_load_paths util_make_gems @@ -135,27 +301,27 @@ def test_self_configuration assert_equal expected, Gem.configuration end - def test_self_datadir - foo = nil - - Dir.chdir @tempdir do - FileUtils.mkdir_p 'data' - File.open File.join('data', 'foo.txt'), 'w' do |fp| - fp.puts 'blah' - end - - foo = quick_gem 'foo' do |s| s.files = %w[data/foo.txt] end - install_gem foo - end - - Gem.source_index = nil - - gem 'foo' - - expected = File.join @gemhome, 'gems', foo.full_name, 'data', 'foo' - - assert_equal expected, Gem.datadir('foo') - end + # def test_self_datadir + # foo = nil + # + # Dir.chdir @tempdir do + # FileUtils.mkdir_p 'data' + # File.open File.join('data', 'foo.txt'), 'w' do |fp| + # fp.puts 'blah' + # end + # + # foo = quick_gem 'foo' do |s| s.files = %w[data/foo.txt] end + # install_gem foo + # end + # + # Gem.source_index = nil + # + # gem 'foo' + # + # expected = File.join @gemhome, 'gems', foo.full_name, 'data', 'foo' + # + # assert_equal expected, Gem.datadir('foo') + # end def test_self_datadir_nonexistent_package assert_nil Gem.datadir('xyzzy') @@ -320,15 +486,15 @@ def test_self_latest_load_paths assert_equal expected, Gem.latest_load_paths.sort end - def test_self_loaded_specs - foo = quick_gem 'foo' - install_gem foo - Gem.source_index = nil - - Gem.activate 'foo' - - assert_equal true, Gem.loaded_specs.keys.include?('foo') - end + # def test_self_loaded_specs + # foo = quick_gem 'foo' + # install_gem foo + # Gem.source_index = nil + # + # Gem.activate 'foo' + # + # assert_equal true, Gem.loaded_specs.keys.include?('foo') + # end def util_path ENV.delete "GEM_HOME" @@ -662,30 +828,30 @@ def test_self_user_home_user_drive_and_path end end - def test_load_plugins - plugin_path = File.join "lib", "rubygems_plugin.rb" - - Dir.chdir @tempdir do - FileUtils.mkdir_p 'lib' - File.open plugin_path, "w" do |fp| - fp.puts "TestGem::TEST_SPEC_PLUGIN_LOAD = :loaded" - end - - foo = quick_gem 'foo', '1' do |s| - s.files << plugin_path - end - - install_gem foo - end - - Gem.source_index = nil - - gem 'foo' - - Gem.load_plugins - - assert_equal :loaded, TEST_SPEC_PLUGIN_LOAD - end + # def test_load_plugins + # plugin_path = File.join "lib", "rubygems_plugin.rb" + # + # Dir.chdir @tempdir do + # FileUtils.mkdir_p 'lib' + # File.open plugin_path, "w" do |fp| + # fp.puts "TestGem::TEST_SPEC_PLUGIN_LOAD = :loaded" + # end + # + # foo = quick_gem 'foo', '1' do |s| + # s.files << plugin_path + # end + # + # install_gem foo + # end + # + # Gem.source_index = nil + # + # gem 'foo' + # + # Gem.load_plugins + # + # assert_equal :loaded, TEST_SPEC_PLUGIN_LOAD + # end def test_load_env_plugins with_plugin('load') { Gem.load_env_plugins } From 5ed4865cdb7dbc6a737e516ec5f5f850e7c7c101 Mon Sep 17 00:00:00 2001 From: Erik Hollensbe Date: Sat, 12 Feb 2011 14:41:46 -0500 Subject: [PATCH 026/707] ! Gem.cache_dir always references the proper cache dir. Pass true to support a user path. ! Gem.cache_gem, given a filename always references the cache gem. Pass true to support a user path. --- test/rubygems/test_gem.rb | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index d12f3cad..72010246 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -783,6 +783,20 @@ def test_self_user_home end end + def test_self_cache_dir + util_ensure_gem_dirs + + assert_equal File.join(@gemhome, 'cache'), Gem.cache_dir + assert_equal File.join(@userhome, '.gem', Gem.ruby_engine, Gem::ConfigMap[:ruby_version], 'cache'), Gem.cache_dir(true) + end + + def test_self_cache_gem + util_ensure_gem_dirs + + assert_equal File.join(@gemhome, 'cache', 'test.gem'), Gem.cache_gem('test.gem') + assert_equal File.join(@userhome, '.gem', Gem.ruby_engine, Gem::ConfigMap[:ruby_version], 'cache', 'test.gem'), Gem.cache_gem('test.gem', true) + end + if Gem.win_platform? then def test_self_user_home_userprofile skip 'Ruby 1.9 properly handles ~ path expansion' unless '1.9' > RUBY_VERSION From c731f8301b2733d2dbd2581d12ef0926b5b07237 Mon Sep 17 00:00:00 2001 From: Erik Hollensbe Date: Sat, 12 Feb 2011 15:56:43 -0500 Subject: [PATCH 027/707] Checkpointing; cache api slightly modified and redocumented; applied to most non-test places. --- test/rubygems/test_gem.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 72010246..0166bcae 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -787,14 +787,14 @@ def test_self_cache_dir util_ensure_gem_dirs assert_equal File.join(@gemhome, 'cache'), Gem.cache_dir - assert_equal File.join(@userhome, '.gem', Gem.ruby_engine, Gem::ConfigMap[:ruby_version], 'cache'), Gem.cache_dir(true) + assert_equal File.join(@userhome, '.gem', Gem.ruby_engine, Gem::ConfigMap[:ruby_version], 'cache'), Gem.cache_dir(Gem.user_dir) end def test_self_cache_gem util_ensure_gem_dirs assert_equal File.join(@gemhome, 'cache', 'test.gem'), Gem.cache_gem('test.gem') - assert_equal File.join(@userhome, '.gem', Gem.ruby_engine, Gem::ConfigMap[:ruby_version], 'cache', 'test.gem'), Gem.cache_gem('test.gem', true) + assert_equal File.join(@userhome, '.gem', Gem.ruby_engine, Gem::ConfigMap[:ruby_version], 'cache', 'test.gem'), Gem.cache_gem('test.gem', Gem.user_dir) end if Gem.win_platform? then From 08f752dbb0dbbd7d725920a239e6c489cc5521fd Mon Sep 17 00:00:00 2001 From: Erik Hollensbe Date: Sat, 12 Feb 2011 16:09:24 -0500 Subject: [PATCH 028/707] test_gem.rb --- test/rubygems/test_gem.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 0166bcae..42582566 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -372,7 +372,7 @@ def test_self_ensure_gem_directories Gem.ensure_gem_subdirectories @gemhome - assert File.directory?(File.join(@gemhome, "cache")) + assert File.directory?(Gem.cache_dir(@gemhome)) end def test_self_ensure_gem_directories_missing_parents @@ -384,7 +384,7 @@ def test_self_ensure_gem_directories_missing_parents Gem.ensure_gem_subdirectories gemdir - assert File.directory?("#{gemdir}/cache") + assert File.directory?(Gem.cache_dir(gemdir)) end unless win_platform? then # only for FS that support write protection @@ -398,7 +398,7 @@ def test_self_ensure_gem_directories_write_protected Gem.ensure_gem_subdirectories gemdir - refute File.exist?("#{gemdir}/cache") + refute File.exist?(Gem.cache_dir(gemdir)) ensure FileUtils.chmod 0600, gemdir end @@ -415,7 +415,7 @@ def test_self_ensure_gem_directories_write_protected_parents Gem.ensure_gem_subdirectories gemdir - refute File.exist?("#{gemdir}/cache") + refute File.exist?(Gem.cache_dir(gemdir)) ensure FileUtils.chmod 0600, parent end From 75f6c048aabf28a8e407a67f0c7e13845bc63c00 Mon Sep 17 00:00:00 2001 From: Ryan Davis Date: Sat, 12 Feb 2011 16:51:57 -0800 Subject: [PATCH 029/707] Tweaks for different exception thrown for divergent activation --- test/rubygems/test_gem.rb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index d12f3cad..3b8111cb 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -126,9 +126,12 @@ def test_self_activate_divergent b2, _ = util_spec 'b', '2.0' c, _ = util_spec 'c', '1.0', 'b' => '= 2.0' - assert_raises Gem::DependencyError do + e = assert_raises Gem::LoadError do assert_activate :ignored, a, b1, b2, c end + + assert_match /can\'t activate b .= 2.0, runtime./, e.message + assert_match /already activated b-1.0/, e.message end def test_self_activate_platform_alternate From 438e74cb56a5ebd125dfe5e83fc69769fe0b8ffc Mon Sep 17 00:00:00 2001 From: Ryan Davis Date: Tue, 15 Feb 2011 21:32:55 -0800 Subject: [PATCH 030/707] ! Rewrote how Gem::activate resolves dependencies. One failure left. Pong to Eric --- test/rubygems/test_gem.rb | 206 ++++++++++++++++++++++---------------- 1 file changed, 117 insertions(+), 89 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 3b8111cb..577cf16a 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -21,11 +21,18 @@ def setup end def assert_activate expected, *specs - Gem.activate specs.first.name - - expected.each do |spec| - assert_includes Gem.loaded_specs.values.map(&:full_name), spec + specs.each do |spec| + case spec + when String + Gem.activate spec + else + Gem.activate spec.name + end end + + loaded = Gem.loaded_specs.values.map(&:full_name) + + assert_equal expected.sort, loaded.sort if expected end def test_self_activate @@ -40,42 +47,6 @@ def test_self_activate_loaded refute Gem.activate 'foo' end - ## - # [A1] depends on - # [B] > 0 (satisfied by 2.0) - # [B1] depends on - # [C] > 0 (satisfied by 1.0) - # [B2] depends on nothing! - # [C1] depends on nothing - - def test_self_activate_dropped - a1, = util_spec 'a', '1', 'b' => nil - b1, = util_spec 'b', '1', 'c' => nil - b2, = util_spec 'b', '2' - c1, = util_spec 'c', '1' - - assert_activate %w[b-2 a-1], a1, b1, b2, c1 - end - - ## - # [A] depends on - # [B] >= 1.0 (satisfied by 1.1) depends on - # [Z] - # [C] >= 1.0 depends on - # [B] = 1.0 - # - # and should backtrack to resolve using b-1.0, pruning Z from the - # resolve. - - def test_self_activate_raggi_the_edgecase_generator - a, _ = util_spec 'a', '1.0', 'b' => '>= 1.0', 'c' => '>= 1.0' - b1, _ = util_spec 'b', '1.0' - b2, _ = util_spec 'b', '1.1', 'z' => '>= 1.0' - c, _ = util_spec 'c', '1.0', 'b' => '= 1.0' - - assert_activate %w[b-1.0 c-1.0 a-1.0], a, b1, b2, c - end - ## # [A] depends on # [B] >= 1.0 (satisfied by 2.0) @@ -90,7 +61,7 @@ def test_self_activate_over b2, _ = util_spec 'b', '2.0' c, _ = util_spec 'c', '1.0', 'b' => '~> 1.0' - assert_activate %w[b-1.0 c-1.0 a-1.0], a, b1, b2, c + assert_activate %w[b-1.0 c-1.0 a-1.0], a, c, "b" end ## @@ -110,11 +81,46 @@ def test_self_activate_under b11, _ = util_spec 'b', '1.1' c, _ = util_spec 'c', '1.0', 'b' => '= 1.0' - assert_activate %w[b-1.0 c-1.0 a-1.0], a, b10, b11, c + assert_activate %w[b-1.0 c-1.0 a-1.0], a, c, "b" end - # under + ## + # [A1] depends on + # [B] > 0 (satisfied by 2.0) + # [B1] depends on + # [C] > 0 (satisfied by 1.0) + # [B2] depends on nothing! + # [C1] depends on nothing + + def test_self_activate_dropped + a1, = util_spec 'a', '1', 'b' => nil + b1, = util_spec 'b', '1', 'c' => nil + b2, = util_spec 'b', '2' + c1, = util_spec 'c', '1' + + assert_activate %w[b-2 a-1], a1, "b" + end + + ## + # [A] depends on + # [B] >= 1.0 (satisfied by 1.1) depends on + # [Z] + # [C] >= 1.0 depends on + # [B] = 1.0 # + # and should backtrack to resolve using b-1.0, pruning Z from the + # resolve. + + def test_self_activate_raggi_the_edgecase_generator + a, _ = util_spec 'a', '1.0', 'b' => '>= 1.0', 'c' => '>= 1.0' + b1, _ = util_spec 'b', '1.0' + b2, _ = util_spec 'b', '1.1', 'z' => '>= 1.0' + c, _ = util_spec 'c', '1.0', 'b' => '= 1.0' + + assert_activate %w[b-1.0 c-1.0 a-1.0], a, c, "b" + end + + ## # [A] depends on # [B] ~> 1.0 (satisfied by 1.0) # [C] = 1.0 depends on @@ -127,47 +133,70 @@ def test_self_activate_divergent c, _ = util_spec 'c', '1.0', 'b' => '= 2.0' e = assert_raises Gem::LoadError do - assert_activate :ignored, a, b1, b2, c + assert_activate nil, a, c, "b" end assert_match /can\'t activate b .= 2.0, runtime./, e.message assert_match /already activated b-1.0/, e.message end + ## + # DOC + def test_self_activate_platform_alternate - util_setup_wxyz + @x1_m = util_spec 'x', '1' do |s| + s.platform = Gem::Platform.new %w[cpu my_platform 1] + end + + @x1_o = util_spec 'x', '1' do |s| + s.platform = Gem::Platform.new %w[cpu other_platform 1] + end + + @w1 = util_spec 'w', '1', 'x' => nil + util_set_arch 'cpu-my_platform1' assert_activate %w[x-1-cpu-my_platform-1 w-1], @w1, @x1_m end + ## + # DOC + def test_self_activate_platform_bump - util_setup_wxyz + @y1 = util_spec 'y', '1' + + @y1_1_p = util_spec 'y', '1.1' do |s| + s.platform = Gem::Platform.new %w[cpu my_platform 1] + end + + @z1 = util_spec 'z', '1', 'y' => nil assert_activate %w[y-1 z-1], @z1, @y1 end + ## + # DOC + def test_self_activate_prerelease - util_setup_c1_pre + @c1_pre = util_spec 'c', '1.a', "a" => "1.a", "b" => "1" + @a1_pre = util_spec 'a', '1.a' + @b1 = util_spec 'b', '1' do |s| + s.add_dependency 'a' + s.add_development_dependency 'aa' + end assert_activate %w[a-1.a b-1 c-1.a], @c1_pre, @a1_pre, @b1 end + ## + # DOC + def test_self_activate_old_required - util_setup_d e1, = util_spec 'e', '1', 'd' => '= 1' - util_clear_gems - - assert_activate %w[d-1 e-1], e1, @d1, @d2 - end - - def util_setup_c1_pre - @c1_pre = util_spec 'c', '1.a', "a" => "1.a", "b" => "1" - end - - def util_setup_d @d1 = util_spec 'd', '1' @d2 = util_spec 'd', '2' + + assert_activate %w[d-1 e-1], e1, "d" end def util_setup_wxyz @@ -304,27 +333,27 @@ def test_self_configuration assert_equal expected, Gem.configuration end - # def test_self_datadir - # foo = nil - # - # Dir.chdir @tempdir do - # FileUtils.mkdir_p 'data' - # File.open File.join('data', 'foo.txt'), 'w' do |fp| - # fp.puts 'blah' - # end - # - # foo = quick_gem 'foo' do |s| s.files = %w[data/foo.txt] end - # install_gem foo - # end - # - # Gem.source_index = nil - # - # gem 'foo' - # - # expected = File.join @gemhome, 'gems', foo.full_name, 'data', 'foo' - # - # assert_equal expected, Gem.datadir('foo') - # end + def test_self_datadir + foo = nil + + Dir.chdir @tempdir do + FileUtils.mkdir_p 'data' + File.open File.join('data', 'foo.txt'), 'w' do |fp| + fp.puts 'blah' + end + + foo = quick_gem 'foo' do |s| s.files = %w[data/foo.txt] end + install_gem foo + end + + Gem.source_index = nil + + gem 'foo' + + expected = File.join @gemhome, 'gems', foo.full_name, 'data', 'foo' + + assert_equal expected, Gem.datadir('foo') + end def test_self_datadir_nonexistent_package assert_nil Gem.datadir('xyzzy') @@ -489,15 +518,15 @@ def test_self_latest_load_paths assert_equal expected, Gem.latest_load_paths.sort end - # def test_self_loaded_specs - # foo = quick_gem 'foo' - # install_gem foo - # Gem.source_index = nil - # - # Gem.activate 'foo' - # - # assert_equal true, Gem.loaded_specs.keys.include?('foo') - # end + def test_self_loaded_specs + foo = quick_gem 'foo' + install_gem foo + Gem.source_index = nil + + Gem.activate 'foo' + + assert_equal true, Gem.loaded_specs.keys.include?('foo') + end def util_path ENV.delete "GEM_HOME" @@ -940,6 +969,5 @@ def util_remove_interrupt_command Gem::Commands.send :remove_const, :InterruptCommand if Gem::Commands.const_defined? :InterruptCommand end - end From 7a5e8482d10a3735d6f369ae79b484ba6b966417 Mon Sep 17 00:00:00 2001 From: Ryan Davis Date: Wed, 16 Feb 2011 02:16:47 -0800 Subject: [PATCH 031/707] removed dead code after unfactoring tests. Improved divergent test --- test/rubygems/test_gem.rb | 28 ++++++---------------------- 1 file changed, 6 insertions(+), 22 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 577cf16a..360147b5 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -136,8 +136,8 @@ def test_self_activate_divergent assert_activate nil, a, c, "b" end - assert_match /can\'t activate b .= 2.0, runtime./, e.message - assert_match /already activated b-1.0/, e.message + assert_match /Unable to activate b-2.0,/, e.message + assert_match /but a-1.0 depends on b .~> 1.0/, e.message end ## @@ -175,7 +175,10 @@ def test_self_activate_platform_bump end ## - # DOC + # [C] depends on + # [A] = 1.a + # [B] = 1.0 depends on + # [A] >= 0 (satisfied by 1.a) def test_self_activate_prerelease @c1_pre = util_spec 'c', '1.a', "a" => "1.a", "b" => "1" @@ -199,25 +202,6 @@ def test_self_activate_old_required assert_activate %w[d-1 e-1], e1, "d" end - def util_setup_wxyz - @x1_m = util_spec 'x', '1' do |s| - s.platform = Gem::Platform.new %w[cpu my_platform 1] - end - - @x1_o = util_spec 'x', '1' do |s| - s.platform = Gem::Platform.new %w[cpu other_platform 1] - end - - @w1 = util_spec 'w', '1', 'x' => nil - - @y1 = util_spec 'y', '1' - @y1_1_p = util_spec 'y', '1.1' do |s| - s.platform = Gem::Platform.new %w[cpu my_platform 1] - end - - @z1 = util_spec 'z', '1', 'y' => nil - end - def test_self_all_load_paths util_make_gems From 877415207075077e018bb143d652edaa164d29f5 Mon Sep 17 00:00:00 2001 From: Ryan Davis Date: Wed, 16 Feb 2011 03:02:39 -0800 Subject: [PATCH 032/707] quell -w test warnings --- test/rubygems/test_gem.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 360147b5..ae8d575a 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -136,8 +136,8 @@ def test_self_activate_divergent assert_activate nil, a, c, "b" end - assert_match /Unable to activate b-2.0,/, e.message - assert_match /but a-1.0 depends on b .~> 1.0/, e.message + assert_match(/Unable to activate b-2.0,/, e.message) + assert_match(/but a-1.0 depends on b .~> 1.0/, e.message) end ## From d75af80e5567e49d66e87d03d76c4fa589de47ee Mon Sep 17 00:00:00 2001 From: Ryan Davis Date: Wed, 16 Feb 2011 12:57:55 -0800 Subject: [PATCH 033/707] Added test_self_activate_unrelated to cover previous fix --- test/rubygems/test_gem.rb | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index ae8d575a..9d1b6691 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -47,6 +47,19 @@ def test_self_activate_loaded refute Gem.activate 'foo' end + ## + # [A] depends on + # [B] >= 1.0 (satisfied by 2.0) + # [C] depends on nothing + + def test_self_activate_unrelated + a = util_spec 'a', '1.0', 'b' => '>= 1.0' + b = util_spec 'b', '1.0' + c = util_spec 'c', '1.0' + + assert_activate %w[b-1.0 c-1.0 a-1.0], a, c, "b" + end + ## # [A] depends on # [B] >= 1.0 (satisfied by 2.0) From b514eb8b2284cffcc74da1b87fefde66a5262aa5 Mon Sep 17 00:00:00 2001 From: Eric Hodel Date: Wed, 16 Feb 2011 17:28:25 -0800 Subject: [PATCH 034/707] Remove unused variables to satisfy ruby 1.9.3dev --- test/rubygems/test_gem.rb | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 62d4bc68..fece40d2 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -42,7 +42,7 @@ def test_self_activate end def test_self_activate_loaded - foo = util_spec 'foo', '1' + util_spec 'foo', '1' assert Gem.activate 'foo' refute Gem.activate 'foo' end @@ -54,7 +54,7 @@ def test_self_activate_loaded def test_self_activate_unrelated a = util_spec 'a', '1.0', 'b' => '>= 1.0' - b = util_spec 'b', '1.0' + util_spec 'b', '1.0' c = util_spec 'c', '1.0' assert_activate %w[b-1.0 c-1.0 a-1.0], a, c, "b" @@ -70,8 +70,8 @@ def test_self_activate_unrelated def test_self_activate_over a, _ = util_spec 'a', '1.0', 'b' => '>= 1.0', 'c' => '= 1.0' - b1, _ = util_spec 'b', '1.0' - b2, _ = util_spec 'b', '2.0' + util_spec 'b', '1.0' + util_spec 'b', '2.0' c, _ = util_spec 'c', '1.0', 'b' => '~> 1.0' assert_activate %w[b-1.0 c-1.0 a-1.0], a, c, "b" @@ -90,8 +90,8 @@ def test_self_activate_over def test_self_activate_under a, _ = util_spec 'a', '1.0', 'b' => '~> 1.0', 'c' => '= 1.0' - b10, _ = util_spec 'b', '1.0' - b11, _ = util_spec 'b', '1.1' + util_spec 'b', '1.0' + util_spec 'b', '1.1' c, _ = util_spec 'c', '1.0', 'b' => '= 1.0' assert_activate %w[b-1.0 c-1.0 a-1.0], a, c, "b" @@ -107,9 +107,9 @@ def test_self_activate_under def test_self_activate_dropped a1, = util_spec 'a', '1', 'b' => nil - b1, = util_spec 'b', '1', 'c' => nil - b2, = util_spec 'b', '2' - c1, = util_spec 'c', '1' + util_spec 'b', '1', 'c' => nil + util_spec 'b', '2' + util_spec 'c', '1' assert_activate %w[b-2 a-1], a1, "b" end @@ -126,8 +126,8 @@ def test_self_activate_dropped def test_self_activate_raggi_the_edgecase_generator a, _ = util_spec 'a', '1.0', 'b' => '>= 1.0', 'c' => '>= 1.0' - b1, _ = util_spec 'b', '1.0' - b2, _ = util_spec 'b', '1.1', 'z' => '>= 1.0' + util_spec 'b', '1.0' + util_spec 'b', '1.1', 'z' => '>= 1.0' c, _ = util_spec 'c', '1.0', 'b' => '= 1.0' assert_activate %w[b-1.0 c-1.0 a-1.0], a, c, "b" @@ -141,8 +141,8 @@ def test_self_activate_raggi_the_edgecase_generator def test_self_activate_divergent a, _ = util_spec 'a', '1.0', 'b' => '~> 1.0', 'c' => '= 1.0' - b1, _ = util_spec 'b', '1.0' - b2, _ = util_spec 'b', '2.0' + util_spec 'b', '1.0' + util_spec 'b', '2.0' c, _ = util_spec 'c', '1.0', 'b' => '= 2.0' e = assert_raises Gem::LoadError do From 92797842d49bd76fa73f8750eee4dd2a7c9d043f Mon Sep 17 00:00:00 2001 From: Ryan Davis Date: Thu, 17 Feb 2011 17:53:42 -0800 Subject: [PATCH 035/707] Swiched as many tests over to quick_spec from quick_gem to write to disk less --- test/rubygems/test_gem.rb | 60 +++++++++++++++++++-------------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index fece40d2..c7941280 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -260,7 +260,7 @@ def test_self_bin_path_name_version end def test_self_bin_path_nonexistent_binfile - quick_gem 'a', '2' do |s| + quick_spec 'a', '2' do |s| s.executables = ['exec'] end assert_raises(Gem::GemNotFoundException) do @@ -269,7 +269,7 @@ def test_self_bin_path_nonexistent_binfile end def test_self_bin_path_no_bin_file - quick_gem 'a', '1' + quick_spec 'a', '1' assert_raises(Gem::Exception) do Gem.bin_path('a', nil, '1') end @@ -283,7 +283,7 @@ def test_self_bin_path_not_found def test_self_bin_path_bin_file_gone_in_latest util_exec_gem - quick_gem 'a', '10' do |s| + quick_spec 'a', '10' do |s| s.executables = [] s.default_executable = nil end @@ -339,7 +339,7 @@ def test_self_datadir fp.puts 'blah' end - foo = quick_gem 'foo' do |s| s.files = %w[data/foo.txt] end + foo = quick_spec 'foo' do |s| s.files = %w[data/foo.txt] end install_gem foo end @@ -516,7 +516,7 @@ def test_self_latest_load_paths end def test_self_loaded_specs - foo = quick_gem 'foo' + foo = quick_spec 'foo' install_gem foo Gem.source_index = nil @@ -871,30 +871,30 @@ def test_self_user_home_user_drive_and_path end end - # def test_load_plugins - # plugin_path = File.join "lib", "rubygems_plugin.rb" - # - # Dir.chdir @tempdir do - # FileUtils.mkdir_p 'lib' - # File.open plugin_path, "w" do |fp| - # fp.puts "TestGem::TEST_SPEC_PLUGIN_LOAD = :loaded" - # end - # - # foo = quick_gem 'foo', '1' do |s| - # s.files << plugin_path - # end - # - # install_gem foo - # end - # - # Gem.source_index = nil - # - # gem 'foo' - # - # Gem.load_plugins - # - # assert_equal :loaded, TEST_SPEC_PLUGIN_LOAD - # end + def test_load_plugins + plugin_path = File.join "lib", "rubygems_plugin.rb" + + Dir.chdir @tempdir do + FileUtils.mkdir_p 'lib' + File.open plugin_path, "w" do |fp| + fp.puts "TestGem::TEST_SPEC_PLUGIN_LOAD = :loaded" + end + + foo = quick_spec 'foo', '1' do |s| + s.files << plugin_path + end + + install_gem foo + end + + Gem.source_index = nil + + gem 'foo' + + Gem.load_plugins + + assert_equal :loaded, TEST_SPEC_PLUGIN_LOAD + end def test_load_env_plugins with_plugin('load') { Gem.load_env_plugins } @@ -936,7 +936,7 @@ def util_ensure_gem_dirs end def util_exec_gem - spec, _ = quick_gem 'a', '4' do |s| + spec, _ = quick_spec 'a', '4' do |s| s.default_executable = 'exec' s.executables = ['exec', 'abin'] end From 7c7efaf1871fb34b70088ca1b5a0ab1bfa580d99 Mon Sep 17 00:00:00 2001 From: raggi Date: Tue, 22 Feb 2011 13:24:14 -0800 Subject: [PATCH 036/707] Add failing test for the try_activate failure case of lazy activation. Test is currently non-working I think due to util methodology --- test/rubygems/test_gem.rb | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index c7941280..dd559c59 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -23,6 +23,8 @@ def setup def assert_activate expected, *specs specs.each do |spec| case spec + when Array + Gem.activate *spec when String Gem.activate spec else @@ -153,6 +155,31 @@ def test_self_activate_divergent assert_match(/but a-1.0 depends on b .~> 1.0/, e.message) end + ## + # Example case, rails 3 installed and rails 2.3.9 installed. Activating + # rails 2.3.9. + # + # [A] 2.3.9 and 3.0.0 installed (+deps) + # + # [A] 2.3.9 depends on + # [B] = 2.3.9 + + def test_non_latest_unresolved_spec_with_path_activation + a, _ = util_spec 'a', '2.3.9', 'b' => '= 2.3.9' + util_spec 'b', '2.3.9' do |spec| + spec.files << 'lib/b.rb' + end + # Latest versions we don't want to activate: + util_spec 'a', '3.0.0' + util_spec 'b', '3.0.0' do |spec| + spec.files << 'lib/b.rb' + end + + assert_activate %w[a-2.3.9], ['a', '< 3.0.0'] + assert Gem.try_activate('b'), 'Path activation of b.rb must find b-2.3.9' + assert_activate %w[a-2.3.9 b-2.3.9] + end + ## # DOC From c35a2142f12810424689a0820ea523f528122c0f Mon Sep 17 00:00:00 2001 From: Eric Hodel Date: Tue, 22 Feb 2011 16:17:24 -0800 Subject: [PATCH 037/707] Ensure @tempdir/gems directory is created in util_gem. Use regular classes in rubygems_plugin files. Use util_gem in test_non_latest_unresolved_spec_with_path_activation so it fails properly now. Clear Gem.searcher when loading plugins too as the searcher is used to find files. --- test/rubygems/test_gem.rb | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index dd559c59..099beb3d 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -165,13 +165,13 @@ def test_self_activate_divergent # [B] = 2.3.9 def test_non_latest_unresolved_spec_with_path_activation - a, _ = util_spec 'a', '2.3.9', 'b' => '= 2.3.9' - util_spec 'b', '2.3.9' do |spec| + a, _ = util_gem 'a', '2.3.9', 'b' => '= 2.3.9' + util_gem 'b', '2.3.9' do |spec| spec.files << 'lib/b.rb' end # Latest versions we don't want to activate: - util_spec 'a', '3.0.0' - util_spec 'b', '3.0.0' do |spec| + util_gem 'a', '3.0.0' + util_gem 'b', '3.0.0' do |spec| spec.files << 'lib/b.rb' end @@ -904,7 +904,7 @@ def test_load_plugins Dir.chdir @tempdir do FileUtils.mkdir_p 'lib' File.open plugin_path, "w" do |fp| - fp.puts "TestGem::TEST_SPEC_PLUGIN_LOAD = :loaded" + fp.puts "class TestGem; TEST_SPEC_PLUGIN_LOAD = :loaded; end" end foo = quick_spec 'foo', '1' do |s| @@ -915,6 +915,7 @@ def test_load_plugins end Gem.source_index = nil + Gem.searcher = nil gem 'foo' From a2d23fcad971cbd5ed0c2f4609920ba4b232ba12 Mon Sep 17 00:00:00 2001 From: Ryan Davis Date: Tue, 22 Feb 2011 17:33:23 -0800 Subject: [PATCH 038/707] Removed warning and a totally bogus test... test needs complete rewriting and verification under 1.5 before it can come back --- test/rubygems/test_gem.rb | 27 +-------------------------- 1 file changed, 1 insertion(+), 26 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 099beb3d..7e17e6e4 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -24,7 +24,7 @@ def assert_activate expected, *specs specs.each do |spec| case spec when Array - Gem.activate *spec + Gem.activate(*spec) when String Gem.activate spec else @@ -155,31 +155,6 @@ def test_self_activate_divergent assert_match(/but a-1.0 depends on b .~> 1.0/, e.message) end - ## - # Example case, rails 3 installed and rails 2.3.9 installed. Activating - # rails 2.3.9. - # - # [A] 2.3.9 and 3.0.0 installed (+deps) - # - # [A] 2.3.9 depends on - # [B] = 2.3.9 - - def test_non_latest_unresolved_spec_with_path_activation - a, _ = util_gem 'a', '2.3.9', 'b' => '= 2.3.9' - util_gem 'b', '2.3.9' do |spec| - spec.files << 'lib/b.rb' - end - # Latest versions we don't want to activate: - util_gem 'a', '3.0.0' - util_gem 'b', '3.0.0' do |spec| - spec.files << 'lib/b.rb' - end - - assert_activate %w[a-2.3.9], ['a', '< 3.0.0'] - assert Gem.try_activate('b'), 'Path activation of b.rb must find b-2.3.9' - assert_activate %w[a-2.3.9 b-2.3.9] - end - ## # DOC From deb0d7320d4f57609c662133b1f52bf993331094 Mon Sep 17 00:00:00 2001 From: Ryan Davis Date: Wed, 23 Feb 2011 15:19:31 -0800 Subject: [PATCH 039/707] Fixed tests to ALWAYS run in the tempdir. Gem files in project root would cause tests to fail --- test/rubygems/test_gem.rb | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 7e17e6e4..3327efbc 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -467,8 +467,8 @@ def test_ensure_ssl_available def test_self_find_files discover_path = File.join 'lib', 'sff', 'discover.rb' - cwd = File.expand_path '..', __FILE__ - $LOAD_PATH.unshift cwd.dup + cwd = File.expand_path("test/rubygems", @project_dir) + $LOAD_PATH.unshift cwd foo1 = quick_gem 'sff', '1' do |s| s.files << discover_path @@ -492,7 +492,7 @@ def test_self_find_files Gem.searcher = nil expected = [ - File.expand_path('../sff/discover.rb', __FILE__), + File.expand_path('test/rubygems/sff/discover.rb', @project_dir), File.join(foo2.full_gem_path, discover_path), File.join(foo1.full_gem_path, discover_path), ] @@ -901,19 +901,19 @@ def test_load_plugins def test_load_env_plugins with_plugin('load') { Gem.load_env_plugins } - assert_equal :loaded, TEST_PLUGIN_LOAD + assert_equal :loaded, TEST_PLUGIN_LOAD rescue nil util_remove_interrupt_command # Should attempt to cause a StandardError with_plugin('standarderror') { Gem.load_env_plugins } - assert_equal :loaded, TEST_PLUGIN_STANDARDERROR + assert_equal :loaded, TEST_PLUGIN_STANDARDERROR rescue nil util_remove_interrupt_command # Should attempt to cause an Exception with_plugin('exception') { Gem.load_env_plugins } - assert_equal :loaded, TEST_PLUGIN_EXCEPTION + assert_equal :loaded, TEST_PLUGIN_EXCEPTION rescue nil end def with_plugin(path) From a26d6361665257f9929ec34df718d95ee9e8e3c4 Mon Sep 17 00:00:00 2001 From: Ryan Davis Date: Wed, 23 Feb 2011 15:56:50 -0800 Subject: [PATCH 040/707] Added Gem::RUBYGEMS_DIR to help clean up tests --- test/rubygems/test_gem.rb | 28 +++++++--------------------- 1 file changed, 7 insertions(+), 21 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 3327efbc..666d7f5c 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -467,7 +467,7 @@ def test_ensure_ssl_available def test_self_find_files discover_path = File.join 'lib', 'sff', 'discover.rb' - cwd = File.expand_path("test/rubygems", @project_dir) + cwd = File.expand_path("test/rubygems", @@project_dir) $LOAD_PATH.unshift cwd foo1 = quick_gem 'sff', '1' do |s| @@ -492,7 +492,7 @@ def test_self_find_files Gem.searcher = nil expected = [ - File.expand_path('test/rubygems/sff/discover.rb', @project_dir), + File.expand_path('test/rubygems/sff/discover.rb', @@project_dir), File.join(foo2.full_gem_path, discover_path), File.join(foo1.full_gem_path, discover_path), ] @@ -621,22 +621,12 @@ def test_self_platforms end def test_self_prefix - file_name = File.expand_path __FILE__ - - prefix = File.dirname File.dirname(file_name) - prefix = File.dirname prefix if File.basename(prefix) == 'test' - - assert_equal prefix, Gem.prefix + assert_equal @@project_dir, Gem.prefix end def test_self_prefix_libdir orig_libdir = Gem::ConfigMap[:libdir] - - file_name = File.expand_path __FILE__ - prefix = File.dirname File.dirname(file_name) - prefix = File.dirname prefix if File.basename(prefix) == 'test' - - Gem::ConfigMap[:libdir] = prefix + Gem::ConfigMap[:libdir] = @@project_dir assert_nil Gem.prefix ensure @@ -645,12 +635,7 @@ def test_self_prefix_libdir def test_self_prefix_sitelibdir orig_sitelibdir = Gem::ConfigMap[:sitelibdir] - - file_name = File.expand_path __FILE__ - prefix = File.dirname File.dirname(file_name) - prefix = File.dirname prefix if File.basename(prefix) == 'test' - - Gem::ConfigMap[:sitelibdir] = prefix + Gem::ConfigMap[:sitelibdir] = @@project_dir assert_nil Gem.prefix ensure @@ -917,7 +902,8 @@ def test_load_env_plugins end def with_plugin(path) - test_plugin_path = File.expand_path "../plugin/#{path}", __FILE__ + test_plugin_path = File.expand_path("test/rubygems/plugin/#{path}", + @@project_dir) # A single test plugin should get loaded once only, in order to preserve # sane test semantics. From 2ca9ae61a0bcd39a2b25a74ba1d777a1862d6637 Mon Sep 17 00:00:00 2001 From: Ryan Davis Date: Thu, 24 Feb 2011 15:02:17 -0800 Subject: [PATCH 041/707] + #require now checks unresolved dependencies first --- test/rubygems/test_gem.rb | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 666d7f5c..0d5dd50d 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -43,6 +43,18 @@ def test_self_activate assert_activate %w[foo-1], foo end + def test_self_activate_via_require + a1 = new_spec "a", "1", "b" => "= 1" + b1 = new_spec "b", "1", nil, "lib/b/c.rb" + b2 = new_spec "b", "2", nil, "lib/b/c.rb" + + install_specs a1, b1 + + Gem.activate "a", "= 1" + require "b/c" + assert_equal %w(a-1 b-1), Gem.loaded_specs.values.map(&:full_name).sort + end + def test_self_activate_loaded util_spec 'foo', '1' assert Gem.activate 'foo' From d339a85dbefc1d9f543cdd967cf78f7c926ec821 Mon Sep 17 00:00:00 2001 From: Ryan Davis Date: Thu, 24 Feb 2011 15:37:17 -0800 Subject: [PATCH 042/707] cleanup --- test/rubygems/test_gem.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 0d5dd50d..8b9293c9 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -48,8 +48,6 @@ def test_self_activate_via_require b1 = new_spec "b", "1", nil, "lib/b/c.rb" b2 = new_spec "b", "2", nil, "lib/b/c.rb" - install_specs a1, b1 - Gem.activate "a", "= 1" require "b/c" assert_equal %w(a-1 b-1), Gem.loaded_specs.values.map(&:full_name).sort @@ -57,6 +55,7 @@ def test_self_activate_via_require def test_self_activate_loaded util_spec 'foo', '1' + assert Gem.activate 'foo' refute Gem.activate 'foo' end From 837c5c1d15e1a10e8f38f44aeb80a66c35cb4d5d Mon Sep 17 00:00:00 2001 From: Ryan Davis Date: Thu, 24 Feb 2011 16:11:51 -0800 Subject: [PATCH 043/707] More edge cases per Evan's review --- test/rubygems/test_gem.rb | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 8b9293c9..13502489 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -43,6 +43,10 @@ def test_self_activate assert_activate %w[foo-1], foo end + def loaded_spec_names + Gem.loaded_specs.values.map(&:full_name).sort + end + def test_self_activate_via_require a1 = new_spec "a", "1", "b" => "= 1" b1 = new_spec "b", "1", nil, "lib/b/c.rb" @@ -50,7 +54,31 @@ def test_self_activate_via_require Gem.activate "a", "= 1" require "b/c" - assert_equal %w(a-1 b-1), Gem.loaded_specs.values.map(&:full_name).sort + + assert_equal %w(a-1 b-1), loaded_spec_names + end + + def test_self_activate_via_require_not_too_eager + a1 = new_spec "a", "1", "b" => "= 1" + b1 = new_spec "b", "1", nil, "lib/b/c.rb" + b2 = new_spec "b", "2", nil, "lib/benchmark.rb" + + Gem.activate "a", "= 1" + require 'benchmark' + + assert_equal %w(a-1), loaded_spec_names + end + + def test_self_activate_via_require_respects_loaded_files + require 'benchmark' # stdlib + + a1 = new_spec "a", "1", "b" => "= 1" + b1 = new_spec "b", "1", nil, "lib/benchmark.rb" + + Gem.activate "a", "= 1" + + refute require('benchmark'), "benchmark should have already been loaded" + assert_equal %w(a-1), loaded_spec_names end def test_self_activate_loaded From d7281c887ac625447bf36e6bdf28fa6c7d6bc3be Mon Sep 17 00:00:00 2001 From: Ryan Davis Date: Thu, 24 Feb 2011 18:17:08 -0800 Subject: [PATCH 044/707] Switched from benchmark to pathname to remove warnings. Added test_self_activate_via_require_(two|three)_hops --- test/rubygems/test_gem.rb | 44 ++++++++++++++++++++++++++++++++++----- 1 file changed, 39 insertions(+), 5 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 13502489..830ba13d 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -61,23 +61,57 @@ def test_self_activate_via_require def test_self_activate_via_require_not_too_eager a1 = new_spec "a", "1", "b" => "= 1" b1 = new_spec "b", "1", nil, "lib/b/c.rb" - b2 = new_spec "b", "2", nil, "lib/benchmark.rb" + b2 = new_spec "b", "2", nil, "lib/pathname.rb" + + install_specs a1, b1, b2 Gem.activate "a", "= 1" - require 'benchmark' + require 'pathname' assert_equal %w(a-1), loaded_spec_names end + def test_self_activate_via_require_two_hops + a1 = new_spec "a", "1", "b" => "= 1" + b1 = new_spec "b", "1", "c" => "= 1" + b2 = new_spec "b", "2", "c" => "= 2" + c1 = new_spec "c", "1", nil, "lib/d.rb" + c2 = new_spec "c", "2", nil, "lib/d.rb" + + install_specs a1, b1, b2, c1, c2 + + Gem.activate "a", "= 1" + require 'd' + + assert_equal %w(a-1 c-1), loaded_spec_names + end + + def test_self_activate_via_require_three_hops + a1 = new_spec "a", "1", "b" => "= 1" + b1 = new_spec "b", "1", "c" => "= 1" + b2 = new_spec "b", "2", "c" => "= 2" + c1 = new_spec "c", "1", "d" => "= 1" + c2 = new_spec "c", "2", "d" => "= 2" + d1 = new_spec "d", "1", nil, "lib/e.rb" + d2 = new_spec "d", "2", nil, "lib/e.rb" + + install_specs a1, b1, b2, c1, c2, d1, d2 + + Gem.activate "a", "= 1" + require 'e' + + assert_equal %w(a-1 d-1), loaded_spec_names + end + def test_self_activate_via_require_respects_loaded_files - require 'benchmark' # stdlib + require 'pathname' # stdlib a1 = new_spec "a", "1", "b" => "= 1" - b1 = new_spec "b", "1", nil, "lib/benchmark.rb" + b1 = new_spec "b", "1", nil, "lib/pathname.rb" Gem.activate "a", "= 1" - refute require('benchmark'), "benchmark should have already been loaded" + refute require('pathname'), "pathname should have already been loaded" assert_equal %w(a-1), loaded_spec_names end From d2e0d1baefbc347f3a908cc1f415f8b98e1080e6 Mon Sep 17 00:00:00 2001 From: BigCat Date: Sat, 26 Feb 2011 02:13:34 +0800 Subject: [PATCH 045/707] Fix the problem Gem::Version#initialize modifies parameter object When `version` is `String`, #to_s returns the original string and #strip! modifies that. This causes two problems: * When `version` is a frozen string, a exception will be thron. * The string will be modified while it's unexcepted for caller. Fixed that and added a test case --- test/rubygems/test_gem_version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/rubygems/test_gem_version.rb b/test/rubygems/test_gem_version.rb index f578063e..701c88ff 100644 --- a/test/rubygems/test_gem_version.rb +++ b/test/rubygems/test_gem_version.rb @@ -56,7 +56,7 @@ def test_hash end def test_initialize - ["1.0", "1.0 ", " 1.0 ", "1.0\n", "\n1.0\n"].each do |good| + ["1.0", "1.0 ", " 1.0 ", "1.0\n", "\n1.0\n", "1.0".freeze].each do |good| assert_version_equal "1.0", good end From 357e2466c400fec3cd8c513130a69dc46424aa96 Mon Sep 17 00:00:00 2001 From: Ryan Davis Date: Mon, 28 Feb 2011 16:19:07 -0800 Subject: [PATCH 046/707] Removed Gem._unresolved Minor refactorings in Gem.activate to clean up old/dead _unresolved code. ! Changed gem activation to not recurse on sub-deps except when unambiguous. + Added Gem.unresolved_deps to track ambiguous dependencies + Dependency#to_s now only outputs type if non-runtime. + Dependency#type now returns :runtime if nil + Requirement#as_list is now sorted to help with testing. Refactored Specification#conflicts... minor unoptimization Added extra tests for ambiguous and unambigous activation of trees. --- test/rubygems/test_gem.rb | 82 +++++++++++++++++++-------------------- 1 file changed, 39 insertions(+), 43 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 830ba13d..6b63a500 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -47,6 +47,10 @@ def loaded_spec_names Gem.loaded_specs.values.map(&:full_name).sort end + def unresolved_names + Gem.unresolved_deps.values.map(&:to_s).sort + end + def test_self_activate_via_require a1 = new_spec "a", "1", "b" => "= 1" b1 = new_spec "b", "1", nil, "lib/b/c.rb" @@ -58,61 +62,38 @@ def test_self_activate_via_require assert_equal %w(a-1 b-1), loaded_spec_names end - def test_self_activate_via_require_not_too_eager - a1 = new_spec "a", "1", "b" => "= 1" - b1 = new_spec "b", "1", nil, "lib/b/c.rb" - b2 = new_spec "b", "2", nil, "lib/pathname.rb" - - install_specs a1, b1, b2 - - Gem.activate "a", "= 1" - require 'pathname' - - assert_equal %w(a-1), loaded_spec_names - end - - def test_self_activate_via_require_two_hops + def test_self_activate_deep_unambiguous a1 = new_spec "a", "1", "b" => "= 1" b1 = new_spec "b", "1", "c" => "= 1" b2 = new_spec "b", "2", "c" => "= 2" - c1 = new_spec "c", "1", nil, "lib/d.rb" - c2 = new_spec "c", "2", nil, "lib/d.rb" + c1 = new_spec "c", "1" + c2 = new_spec "c", "2" install_specs a1, b1, b2, c1, c2 Gem.activate "a", "= 1" - require 'd' - - assert_equal %w(a-1 c-1), loaded_spec_names + assert_equal %w(a-1 b-1 c-1), loaded_spec_names end - def test_self_activate_via_require_three_hops - a1 = new_spec "a", "1", "b" => "= 1" - b1 = new_spec "b", "1", "c" => "= 1" - b2 = new_spec "b", "2", "c" => "= 2" - c1 = new_spec "c", "1", "d" => "= 1" - c2 = new_spec "c", "2", "d" => "= 2" - d1 = new_spec "d", "1", nil, "lib/e.rb" - d2 = new_spec "d", "2", nil, "lib/e.rb" + def test_self_activate_ambiguous + a1 = new_spec "a", "1", "b" => "> 0" + b1 = new_spec "b", "1", "c" => ">= 1" + b2 = new_spec "b", "2", "c" => ">= 2" + c1 = new_spec "c", "1", nil, "lib/d.rb" + c2 = new_spec "c", "2", nil, "lib/d.rb" - install_specs a1, b1, b2, c1, c2, d1, d2 + install_specs a1, b1, b2, c1, c2 Gem.activate "a", "= 1" - require 'e' - - assert_equal %w(a-1 d-1), loaded_spec_names - end - - def test_self_activate_via_require_respects_loaded_files - require 'pathname' # stdlib + assert_equal %w(a-1), loaded_spec_names + assert_equal ["b (> 0)"], unresolved_names - a1 = new_spec "a", "1", "b" => "= 1" - b1 = new_spec "b", "1", nil, "lib/pathname.rb" + require "d" - Gem.activate "a", "= 1" + assert_equal %w(a-1 b-2 c-2), loaded_spec_names + assert_equal [], unresolved_names - refute require('pathname'), "pathname should have already been loaded" - assert_equal %w(a-1), loaded_spec_names + flunk end def test_self_activate_loaded @@ -146,10 +127,14 @@ def test_self_activate_unrelated def test_self_activate_over a, _ = util_spec 'a', '1.0', 'b' => '>= 1.0', 'c' => '= 1.0' util_spec 'b', '1.0' + util_spec 'b', '1.1' util_spec 'b', '2.0' c, _ = util_spec 'c', '1.0', 'b' => '~> 1.0' - assert_activate %w[b-1.0 c-1.0 a-1.0], a, c, "b" + Gem.activate "a" + + assert_equal %w[a-1.0 c-1.0], loaded_spec_names + assert_equal ["b (>= 1.0, ~> 1.0)"], unresolved_names end ## @@ -208,6 +193,17 @@ def test_self_activate_raggi_the_edgecase_generator assert_activate %w[b-1.0 c-1.0 a-1.0], a, c, "b" end + def test_self_activate_conflict + util_spec 'b', '1.0' + util_spec 'b', '2.0' + + gem "b", "= 1.0" + + assert_raises Gem::LoadError do + gem "b", "= 2.0" + end + end + ## # [A] depends on # [B] ~> 1.0 (satisfied by 1.0) @@ -224,8 +220,8 @@ def test_self_activate_divergent assert_activate nil, a, c, "b" end - assert_match(/Unable to activate b-2.0,/, e.message) - assert_match(/but a-1.0 depends on b .~> 1.0/, e.message) + assert_match(/Unable to activate c-1.0,/, e.message) + assert_match(/because b-1.0 conflicts with b .= 2.0/, e.message) end ## From 818dcce4322dc2933982a3a18535c18f74d37cd5 Mon Sep 17 00:00:00 2001 From: Ryan Davis Date: Mon, 28 Feb 2011 18:10:57 -0800 Subject: [PATCH 047/707] Added more test cases and #save_loaded_features --- test/rubygems/test_gem.rb | 80 ++++++++++++++++++++++++++++++++------- 1 file changed, 67 insertions(+), 13 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 6b63a500..cf49e776 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -75,24 +75,78 @@ def test_self_activate_deep_unambiguous assert_equal %w(a-1 b-1 c-1), loaded_spec_names end - def test_self_activate_ambiguous - a1 = new_spec "a", "1", "b" => "> 0" - b1 = new_spec "b", "1", "c" => ">= 1" - b2 = new_spec "b", "2", "c" => ">= 2" - c1 = new_spec "c", "1", nil, "lib/d.rb" - c2 = new_spec "c", "2", nil, "lib/d.rb" + def save_loaded_features + old_loaded_features = $LOADED_FEATURES.dup + yield + ensure + $LOADED_FEATURES.replace old_loaded_features + end - install_specs a1, b1, b2, c1, c2 + def test_self_activate_ambiguous_direct + save_loaded_features do + a1 = new_spec "a", "1", "b" => "> 0" + b1 = new_spec("b", "1", { "c" => ">= 1" }, "lib/d.rb") + b2 = new_spec("b", "2", { "c" => ">= 2" }, "lib/d.rb") + c1 = new_spec "c", "1" + c2 = new_spec "c", "2" - Gem.activate "a", "= 1" - assert_equal %w(a-1), loaded_spec_names - assert_equal ["b (> 0)"], unresolved_names + install_specs a1, b1, b2, c1, c2 + + Gem.activate "a", "= 1" + assert_equal %w(a-1), loaded_spec_names + assert_equal ["b (> 0)"], unresolved_names + + require "d" + + assert_equal %w(a-1 b-2 c-2), loaded_spec_names + assert_equal [], unresolved_names + end + + flunk + end - require "d" + def test_self_activate_ambiguous_indirect + save_loaded_features do + a1 = new_spec "a", "1", "b" => "> 0" + b1 = new_spec "b", "1", "c" => ">= 1" + b2 = new_spec "b", "2", "c" => ">= 1" + c1 = new_spec "c", "1", nil, "lib/d.rb" + c2 = new_spec "c", "2", nil, "lib/d.rb" - assert_equal %w(a-1 b-2 c-2), loaded_spec_names - assert_equal [], unresolved_names + install_specs a1, b1, b2, c1, c2 + Gem.activate "a", "= 1" + assert_equal %w(a-1), loaded_spec_names + assert_equal ["b (> 0)"], unresolved_names + + require "d" + + assert_equal %w(a-1 b-2 c-2), loaded_spec_names + assert_equal [], unresolved_names + end + flunk + end + + def test_self_activate_ambiguous_indirect_conflict + save_loaded_features do + a1 = new_spec "a", "1", "b" => "> 0" + a2 = new_spec "a", "2", "b" => "> 0" + b1 = new_spec "b", "1", "c" => ">= 1" + b2 = new_spec "b", "2", "c" => ">= 2" + c1 = new_spec "c", "1", nil, "lib/d.rb" + c2 = new_spec("c", "2", { "a" => "1" }, "lib/d.rb") # conflicts with a-2 + + install_specs a1, b1, b2, c1, c2 + + Gem.activate "a", "= 2" + assert_equal %w(a-2), loaded_spec_names + assert_equal ["b (> 0)"], unresolved_names + + require "d" + + assert_equal %w(a-2 b-1 c-1), loaded_spec_names + assert_equal [], unresolved_names + end flunk end From 32d81385df11acc7dfa18bc0a9287ec131cc3a3a Mon Sep 17 00:00:00 2001 From: Ryan Davis Date: Tue, 1 Mar 2011 00:21:13 -0800 Subject: [PATCH 048/707] Nailed the last activation/require test --- test/rubygems/test_gem.rb | 36 +++++++++++++++++++++++++++++++----- 1 file changed, 31 insertions(+), 5 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index cf49e776..58c62310 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -101,15 +101,13 @@ def test_self_activate_ambiguous_direct assert_equal %w(a-1 b-2 c-2), loaded_spec_names assert_equal [], unresolved_names end - - flunk end def test_self_activate_ambiguous_indirect save_loaded_features do a1 = new_spec "a", "1", "b" => "> 0" b1 = new_spec "b", "1", "c" => ">= 1" - b2 = new_spec "b", "2", "c" => ">= 1" + b2 = new_spec "b", "2", "c" => ">= 2" c1 = new_spec "c", "1", nil, "lib/d.rb" c2 = new_spec "c", "2", nil, "lib/d.rb" @@ -124,7 +122,28 @@ def test_self_activate_ambiguous_indirect assert_equal %w(a-1 b-2 c-2), loaded_spec_names assert_equal [], unresolved_names end - flunk + end + + def test_self_activate_ambiguous_unrelated + save_loaded_features do + a1 = new_spec "a", "1", "b" => "> 0" + b1 = new_spec "b", "1", "c" => ">= 1" + b2 = new_spec "b", "2", "c" => ">= 2" + c1 = new_spec "c", "1" + c2 = new_spec "c", "2" + d1 = new_spec "d", "1", nil, "lib/d.rb" + + install_specs a1, b1, b2, c1, c2 + + Gem.activate "a", "= 1" + assert_equal %w(a-1), loaded_spec_names + assert_equal ["b (> 0)"], unresolved_names + + require "d" + + assert_equal %w(a-1 d-1), loaded_spec_names + assert_equal ["b (> 0)"], unresolved_names + end end def test_self_activate_ambiguous_indirect_conflict @@ -147,7 +166,14 @@ def test_self_activate_ambiguous_indirect_conflict assert_equal %w(a-2 b-1 c-1), loaded_spec_names assert_equal [], unresolved_names end - flunk + end + + def test_require_missing + save_loaded_features do + assert_raises ::LoadError do + require "q" + end + end end def test_self_activate_loaded From 65953a2c622022fe7dc5753827d94a22a30de576 Mon Sep 17 00:00:00 2001 From: Eric Hodel Date: Mon, 28 Feb 2011 16:20:05 -0800 Subject: [PATCH 049/707] Add > requirement test against a prerelease version --- test/rubygems/test_gem_requirement.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/rubygems/test_gem_requirement.rb b/test/rubygems/test_gem_requirement.rb index 4ee31d6d..76ddf369 100644 --- a/test/rubygems/test_gem_requirement.rb +++ b/test/rubygems/test_gem_requirement.rb @@ -187,11 +187,15 @@ def test_satisfied_by_eh_good assert_satisfied_by " ", "> 0.a " assert_satisfied_by "", " > 0.a" assert_satisfied_by "3.1", "< 3.2.rc1" + assert_satisfied_by "3.2.0", "> 3.2.0.rc1" assert_satisfied_by "3.2.0.rc2", "> 3.2.0.rc1" + assert_satisfied_by "3.0.rc2", "< 3.0" assert_satisfied_by "3.0.rc2", "< 3.0.0" assert_satisfied_by "3.0.rc2", "< 3.0.1" + + assert_satisfied_by "3.0.rc2", "> 0" end def test_illformed_requirements From 68bc9a8e71070977ba33ff2a057d069e157c443c Mon Sep 17 00:00:00 2001 From: Eric Hodel Date: Tue, 1 Mar 2011 13:07:54 -0800 Subject: [PATCH 050/707] Fix unused variable warnings --- test/rubygems/test_gem.rb | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 58c62310..ffe75da7 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -52,9 +52,9 @@ def unresolved_names end def test_self_activate_via_require - a1 = new_spec "a", "1", "b" => "= 1" - b1 = new_spec "b", "1", nil, "lib/b/c.rb" - b2 = new_spec "b", "2", nil, "lib/b/c.rb" + new_spec "a", "1", "b" => "= 1" + new_spec "b", "1", nil, "lib/b/c.rb" + new_spec "b", "2", nil, "lib/b/c.rb" Gem.activate "a", "= 1" require "b/c" @@ -133,7 +133,7 @@ def test_self_activate_ambiguous_unrelated c2 = new_spec "c", "2" d1 = new_spec "d", "1", nil, "lib/d.rb" - install_specs a1, b1, b2, c1, c2 + install_specs a1, b1, b2, c1, c2, d1 Gem.activate "a", "= 1" assert_equal %w(a-1), loaded_spec_names @@ -155,7 +155,7 @@ def test_self_activate_ambiguous_indirect_conflict c1 = new_spec "c", "1", nil, "lib/d.rb" c2 = new_spec("c", "2", { "a" => "1" }, "lib/d.rb") # conflicts with a-2 - install_specs a1, b1, b2, c1, c2 + install_specs a1, a2, b1, b2, c1, c2 Gem.activate "a", "= 2" assert_equal %w(a-2), loaded_spec_names @@ -205,11 +205,11 @@ def test_self_activate_unrelated # and should resolve using b-1.0 def test_self_activate_over - a, _ = util_spec 'a', '1.0', 'b' => '>= 1.0', 'c' => '= 1.0' - util_spec 'b', '1.0' - util_spec 'b', '1.1' - util_spec 'b', '2.0' - c, _ = util_spec 'c', '1.0', 'b' => '~> 1.0' + util_spec 'a', '1.0', 'b' => '>= 1.0', 'c' => '= 1.0' + util_spec 'b', '1.0' + util_spec 'b', '1.1' + util_spec 'b', '2.0' + util_spec 'c', '1.0', 'b' => '~> 1.0' Gem.activate "a" From d5fd06c5db52e77427a644d26715140605cabcfd Mon Sep 17 00:00:00 2001 From: Erik Hollensbe Date: Sat, 5 Mar 2011 05:55:19 -0500 Subject: [PATCH 051/707] Initial move of ensure_gem_subdirectories --- test/rubygems/test_gem.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index ffe75da7..f496045d 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -556,7 +556,7 @@ def test_self_ensure_gem_directories end def test_self_ensure_gem_directories_missing_parents - gemdir = File.join @tempdir, 'a/b/c/gemdir' + gemdir = Gem::FileSystem.new @tempdir, 'a/b/c/gemdir' FileUtils.rm_rf File.join(@tempdir, 'a') rescue nil refute File.exist?(File.join(@tempdir, 'a')), "manually remove #{File.join @tempdir, 'a'}, tests are broken" @@ -569,7 +569,7 @@ def test_self_ensure_gem_directories_missing_parents unless win_platform? then # only for FS that support write protection def test_self_ensure_gem_directories_write_protected - gemdir = File.join @tempdir, "egd" + gemdir = Gem::FileSystem.new @tempdir, "egd" FileUtils.rm_r gemdir rescue nil refute File.exist?(gemdir), "manually remove #{gemdir}, tests are broken" FileUtils.mkdir_p gemdir @@ -585,7 +585,7 @@ def test_self_ensure_gem_directories_write_protected def test_self_ensure_gem_directories_write_protected_parents parent = File.join(@tempdir, "egd") - gemdir = "#{parent}/a/b/c" + gemdir = Gem::FileSystem.new "#{parent}/a/b/c" FileUtils.rm_r parent rescue nil refute File.exist?(parent), "manually remove #{parent}, tests are broken" From 2a349be3537e27cef2f4b552dc67241e04d2b632 Mon Sep 17 00:00:00 2001 From: Erik Hollensbe Date: Sat, 5 Mar 2011 06:06:37 -0500 Subject: [PATCH 052/707] ! API CHANGE: Gem.ensure_gem_directories is now a method on Gem::FileSystem. --- test/rubygems/test_gem.rb | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index f496045d..8b4b780d 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -550,7 +550,7 @@ def test_self_ensure_gem_directories FileUtils.rm_r @gemhome Gem.use_paths @gemhome - Gem.ensure_gem_subdirectories @gemhome + @gemhome.ensure_gem_subdirectories assert File.directory?(Gem.cache_dir(@gemhome)) end @@ -562,7 +562,7 @@ def test_self_ensure_gem_directories_missing_parents "manually remove #{File.join @tempdir, 'a'}, tests are broken" Gem.use_paths gemdir - Gem.ensure_gem_subdirectories gemdir + gemdir.ensure_gem_subdirectories assert File.directory?(Gem.cache_dir(gemdir)) end @@ -576,7 +576,7 @@ def test_self_ensure_gem_directories_write_protected FileUtils.chmod 0400, gemdir Gem.use_paths gemdir - Gem.ensure_gem_subdirectories gemdir + gemdir.ensure_gem_subdirectories refute File.exist?(Gem.cache_dir(gemdir)) ensure @@ -593,7 +593,7 @@ def test_self_ensure_gem_directories_write_protected_parents FileUtils.chmod 0400, parent Gem.use_paths(gemdir) - Gem.ensure_gem_subdirectories gemdir + gemdir.ensure_gem_subdirectories refute File.exist?(Gem.cache_dir(gemdir)) ensure @@ -1067,9 +1067,13 @@ def with_plugin(path) end def util_ensure_gem_dirs - Gem.ensure_gem_subdirectories @gemhome + @gemhome.ensure_gem_subdirectories + + # + # FIXME what does this solve precisely? -ebh + # @additional.each do |dir| - Gem.ensure_gem_subdirectories @gemhome + @gemhome.ensure_gem_subdirectories end end From 03db4e9eef4f5041eacd4f9fc40887643ff3d89d Mon Sep 17 00:00:00 2001 From: Erik Hollensbe Date: Sat, 5 Mar 2011 07:36:51 -0500 Subject: [PATCH 053/707] ! PathSupport class provides path and home information and management refactors to support the above. tests still do not pass. --- test/rubygems/test_gem.rb | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 8b4b780d..a5295f15 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -692,9 +692,10 @@ def test_self_path_default orig_APPLE_GEM_HOME = APPLE_GEM_HOME Object.send :remove_const, :APPLE_GEM_HOME end - Gem.instance_variable_set :@gem_path, nil - assert_equal [Gem.default_path, Gem.dir].flatten, Gem.path + Gem.instance_variable_set :@paths, nil + + assert_equal [Gem.default_path, Gem.dir].flatten.uniq, Gem.path ensure Object.const_set :APPLE_GEM_HOME, orig_APPLE_GEM_HOME end @@ -725,7 +726,12 @@ def test_self_path_APPLE_GEM_HOME_GEM_PATH end def test_self_path_ENV_PATH - Gem.send :set_paths, nil + # + # FIXME remove after fixing test_case + # + ENV.delete('GEM_HOME') + + Gem.instance_variable_set :@paths, nil path_count = Gem.path.size Gem.clear_paths @@ -888,9 +894,14 @@ def test_self_searcher def test_self_set_paths other = File.join @tempdir, 'other' path = [@userhome, other].join File::PATH_SEPARATOR - Gem.send :set_paths, path - assert_equal [@userhome, other, @gemhome], Gem.path + # + # FIXME remove after fixing test_case + # + ENV["GEM_HOME"] = @gemhome + Gem.paths = { :path => path } + + assert_equal [@userhome, Gem::FileSystem.new(other), @gemhome], Gem.path end def test_self_set_paths_nonexistent_home @@ -901,7 +912,7 @@ def test_self_set_paths_nonexistent_home ENV['HOME'] = other - Gem.send :set_paths, other + Gem.paths = { :path => other } assert_equal [other, @gemhome], Gem.path end From f011a13bcb2ea28b701e7b220fb1b47746b16359 Mon Sep 17 00:00:00 2001 From: Ryan Davis Date: Mon, 7 Mar 2011 17:43:26 -0800 Subject: [PATCH 054/707] - require of an activated gem could cause activation conflicts. RF#29056 --- test/rubygems/test_gem.rb | 40 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index ffe75da7..931084c5 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -168,6 +168,46 @@ def test_self_activate_ambiguous_indirect_conflict end end + def test_require_already_activated + save_loaded_features do + a1 = new_spec "a", "1", nil, "lib/d.rb" + + install_specs a1 # , a2, b1, b2, c1, c2 + + Gem.activate "a", "= 1" + assert_equal %w(a-1), loaded_spec_names + assert_equal [], unresolved_names + + assert require "d" + + assert_equal %w(a-1), loaded_spec_names + assert_equal [], unresolved_names + end + end + + def test_require_already_activated_indirect_conflict + save_loaded_features do + a1 = new_spec "a", "1", "b" => "> 0" + a2 = new_spec "a", "2", "b" => "> 0" + b1 = new_spec "b", "1", "c" => ">= 1" + b2 = new_spec "b", "2", "c" => ">= 2" + c1 = new_spec "c", "1", nil, "lib/d.rb" + c2 = new_spec("c", "2", { "a" => "1" }, "lib/d.rb") # conflicts with a-2 + + install_specs a1, a2, b1, b2, c1, c2 + + Gem.activate "a", "= 1" + Gem.activate "c", "= 1" + assert_equal %w(a-1 c-1), loaded_spec_names + assert_equal ["b (> 0)"], unresolved_names + + assert require "d" + + assert_equal %w(a-1 c-1), loaded_spec_names + assert_equal ["b (> 0)"], unresolved_names + end + end + def test_require_missing save_loaded_features do assert_raises ::LoadError do From 98e260e2d958ed22d93df08ef912cf7f8e87f3af Mon Sep 17 00:00:00 2001 From: Erik Hollensbe Date: Wed, 16 Mar 2011 01:54:25 -0400 Subject: [PATCH 055/707] Remove some stupidity. --- test/rubygems/test_gem.rb | 6 ------ 1 file changed, 6 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 50fc5ef6..3fb40a91 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -766,12 +766,6 @@ def test_self_path_APPLE_GEM_HOME_GEM_PATH end def test_self_path_ENV_PATH - # - # FIXME remove after fixing test_case - # - ENV.delete('GEM_HOME') - - Gem.instance_variable_set :@paths, nil path_count = Gem.path.size Gem.clear_paths From cbec8902cc0928fbb92ef0602a88fc8202000a2d Mon Sep 17 00:00:00 2001 From: Ryan Davis Date: Wed, 16 Mar 2011 03:46:34 -0700 Subject: [PATCH 056/707] + Gem.bin_path requires the exec_name argument. --- test/rubygems/test_gem.rb | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 931084c5..163c34d1 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -440,16 +440,6 @@ def test_self_bin_path_bin_name_version assert_equal @abin_path, Gem.bin_path('a', 'abin', '4') end - def test_self_bin_path_name - util_exec_gem - assert_equal @exec_path, Gem.bin_path('a') - end - - def test_self_bin_path_name_version - util_exec_gem - assert_equal @exec_path, Gem.bin_path('a', nil, '4') - end - def test_self_bin_path_nonexistent_binfile quick_spec 'a', '2' do |s| s.executables = ['exec'] @@ -461,14 +451,14 @@ def test_self_bin_path_nonexistent_binfile def test_self_bin_path_no_bin_file quick_spec 'a', '1' - assert_raises(Gem::Exception) do + assert_raises(ArgumentError) do Gem.bin_path('a', nil, '1') end end def test_self_bin_path_not_found assert_raises(Gem::GemNotFoundException) do - Gem.bin_path('non-existent') + Gem.bin_path('non-existent', 'blah') end end From 078692680361cf40f00b515dfe12c84e10d0c689 Mon Sep 17 00:00:00 2001 From: Erik Hollensbe Date: Thu, 17 Mar 2011 02:57:48 -0400 Subject: [PATCH 057/707] Restructuring: (refactors coming next) Gem::FS::Path is now Gem::Path Gem::Path is now the parent class for Gem::FS Indexer mostly ported. Specification mostly ported. --- test/rubygems/test_gem.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 3fb40a91..58c30cea 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -496,6 +496,8 @@ def test_self_bindir_default_dir RbConfig::CONFIG['bindir'] end + bindir = Gem::FS::Path.new(bindir) + assert_equal bindir, Gem.bindir(default) assert_equal bindir, Gem.bindir(Pathname.new(default)) end From 6ed6390901c5b2e5c8d62302f458098d5600061f Mon Sep 17 00:00:00 2001 From: Erik Hollensbe Date: Thu, 17 Mar 2011 03:10:11 -0400 Subject: [PATCH 058/707] Refactors: Gem::FS is the new Gem::FileSystem. Gem::Path is now what Gem::FileSystem::Path used to be. --- test/rubygems/test_gem.rb | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 58c30cea..30e49a14 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -496,7 +496,7 @@ def test_self_bindir_default_dir RbConfig::CONFIG['bindir'] end - bindir = Gem::FS::Path.new(bindir) + bindir = Gem::Path.new(bindir) assert_equal bindir, Gem.bindir(default) assert_equal bindir, Gem.bindir(Pathname.new(default)) @@ -598,7 +598,7 @@ def test_self_ensure_gem_directories end def test_self_ensure_gem_directories_missing_parents - gemdir = Gem::FileSystem.new @tempdir, 'a/b/c/gemdir' + gemdir = Gem::FS.new @tempdir, 'a/b/c/gemdir' FileUtils.rm_rf File.join(@tempdir, 'a') rescue nil refute File.exist?(File.join(@tempdir, 'a')), "manually remove #{File.join @tempdir, 'a'}, tests are broken" @@ -611,7 +611,7 @@ def test_self_ensure_gem_directories_missing_parents unless win_platform? then # only for FS that support write protection def test_self_ensure_gem_directories_write_protected - gemdir = Gem::FileSystem.new @tempdir, "egd" + gemdir = Gem::FS.new @tempdir, "egd" FileUtils.rm_r gemdir rescue nil refute File.exist?(gemdir), "manually remove #{gemdir}, tests are broken" FileUtils.mkdir_p gemdir @@ -627,7 +627,7 @@ def test_self_ensure_gem_directories_write_protected def test_self_ensure_gem_directories_write_protected_parents parent = File.join(@tempdir, "egd") - gemdir = Gem::FileSystem.new "#{parent}/a/b/c" + gemdir = Gem::FS.new "#{parent}/a/b/c" FileUtils.rm_r parent rescue nil refute File.exist?(parent), "manually remove #{parent}, tests are broken" @@ -937,7 +937,7 @@ def test_self_set_paths ENV["GEM_HOME"] = @gemhome Gem.paths = { :path => path } - assert_equal [@userhome, Gem::FileSystem.new(other), @gemhome], Gem.path + assert_equal [@userhome, Gem::FS.new(other), @gemhome], Gem.path end def test_self_set_paths_nonexistent_home From 16255cfe258378640f62eab1c31081b574ce26fe Mon Sep 17 00:00:00 2001 From: Erik Hollensbe Date: Sat, 19 Mar 2011 18:18:40 -0400 Subject: [PATCH 059/707] Converted most of lib/rubygems.rb to use Gem::Path. Gem::Path's constructor no longer expands the path. This was causing problems. The predictable kind. Added new methods to Gem::Path to support this conversion: Gem::Path#+ adds two strings. It performs no path handling of its own. Gem::Path#expand_path expands the current path. Gem::Path#split loops over File.split until all parts are in an array. Gem::Path#relative, given a base path argument, computes the relative path. Self-reminder to test this on windows. Gem::Path#basename computes the basename for a path with an optional extension to prune on. Gem::Path#sub performs string substitution on the path. --- test/rubygems/test_gem.rb | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index dcdbfb24..7f7c1588 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -417,7 +417,7 @@ def test_self_all_load_paths File.join(@gemhome, *%W[gems #{@b2.full_name} lib]), File.join(@gemhome, *%W[gems #{@c1_2.full_name} lib]), File.join(@gemhome, *%W[gems #{@pl1.full_name} lib]), - ] + ].map { |x| Gem::Path.new(x) } assert_equal expected, Gem.all_load_paths.sort end @@ -688,11 +688,11 @@ def test_self_latest_load_paths util_make_gems expected = [ - File.join(@gemhome, *%W[gems #{@a3a.full_name} lib]), - File.join(@gemhome, *%W[gems #{@a_evil9.full_name} lib]), - File.join(@gemhome, *%W[gems #{@b2.full_name} lib]), - File.join(@gemhome, *%W[gems #{@c1_2.full_name} lib]), - File.join(@gemhome, *%W[gems #{@pl1.full_name} lib]), + @gemhome.add(*%W[gems #{@a3a.full_name} lib]), + @gemhome.add(*%W[gems #{@a_evil9.full_name} lib]), + @gemhome.add(*%W[gems #{@b2.full_name} lib]), + @gemhome.add(*%W[gems #{@c1_2.full_name} lib]), + @gemhome.add(*%W[gems #{@pl1.full_name} lib]), ] assert_equal expected, Gem.latest_load_paths.sort From 7eecf6184f9a7eb1a592be5723491826d03dfae0 Mon Sep 17 00:00:00 2001 From: Ryan Davis Date: Thu, 31 Mar 2011 13:52:07 -0700 Subject: [PATCH 060/707] + Deprecated Gem.all_load_paths, latest_load_paths, promote_load_path, and cache. Fixed deprecate klass detection. Added caller info to help clean up tests. + Deprecated Specification#has_rdoc, default_executable, and test_suite_file(=). --- test/rubygems/test_gem.rb | 30 ------------------------------ 1 file changed, 30 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 163c34d1..70f16929 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -406,22 +406,6 @@ def test_self_activate_old_required assert_activate %w[d-1 e-1], e1, "d" end - def test_self_all_load_paths - util_make_gems - - expected = [ - File.join(@gemhome, *%W[gems #{@a1.full_name} lib]), - File.join(@gemhome, *%W[gems #{@a2.full_name} lib]), - File.join(@gemhome, *%W[gems #{@a3a.full_name} lib]), - File.join(@gemhome, *%W[gems #{@a_evil9.full_name} lib]), - File.join(@gemhome, *%W[gems #{@b2.full_name} lib]), - File.join(@gemhome, *%W[gems #{@c1_2.full_name} lib]), - File.join(@gemhome, *%W[gems #{@pl1.full_name} lib]), - ] - - assert_equal expected, Gem.all_load_paths.sort - end - def test_self_available? util_make_gems assert(Gem.available?("a")) @@ -682,20 +666,6 @@ def test_self_find_files assert_equal cwd, $LOAD_PATH.shift end - def test_self_latest_load_paths - util_make_gems - - expected = [ - File.join(@gemhome, *%W[gems #{@a3a.full_name} lib]), - File.join(@gemhome, *%W[gems #{@a_evil9.full_name} lib]), - File.join(@gemhome, *%W[gems #{@b2.full_name} lib]), - File.join(@gemhome, *%W[gems #{@c1_2.full_name} lib]), - File.join(@gemhome, *%W[gems #{@pl1.full_name} lib]), - ] - - assert_equal expected, Gem.latest_load_paths.sort - end - def test_self_loaded_specs foo = quick_spec 'foo' install_gem foo From 8fd04dc6242fd5ad78d0ee3161155cedd7fe5c95 Mon Sep 17 00:00:00 2001 From: Ryan Davis Date: Thu, 31 Mar 2011 17:06:09 -0700 Subject: [PATCH 061/707] + Deprecated Specification#has_rdoc= and default_executable= --- test/rubygems/test_gem.rb | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 70f16929..b6a588b3 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -450,7 +450,6 @@ def test_self_bin_path_bin_file_gone_in_latest util_exec_gem quick_spec 'a', '10' do |s| s.executables = [] - s.default_executable = nil end # Should not find a-10's non-abin (bug) assert_equal @abin_path, Gem.bin_path('a', 'abin') @@ -1075,7 +1074,6 @@ def util_ensure_gem_dirs def util_exec_gem spec, _ = quick_spec 'a', '4' do |s| - s.default_executable = 'exec' s.executables = ['exec', 'abin'] end From d0f1a5b7df5fb2bc4c6aac055b83873ca32c4bbc Mon Sep 17 00:00:00 2001 From: Ryan Davis Date: Mon, 4 Apr 2011 15:40:37 -0700 Subject: [PATCH 062/707] + Added Dependency#to_spec + Added Specification#find(name_or_dep, *requirements). + Added Specification#activate. Refactored activate into a sane set of methods. Switched Gem.activate* to use the new Spec/Dep API. Fixed all uses of deprecated code in impl and test. --- test/rubygems/test_gem.rb | 59 +++++++++++++++++++-------------------- 1 file changed, 29 insertions(+), 30 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index be9508e7..18d5c9b0 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -24,11 +24,11 @@ def assert_activate expected, *specs specs.each do |spec| case spec when Array - Gem.activate(*spec) + Gem::Specification.find(*spec).activate when String - Gem.activate spec + Gem::Specification.find(spec).activate else - Gem.activate spec.name + spec.activate end end @@ -51,17 +51,19 @@ def unresolved_names Gem.unresolved_deps.values.map(&:to_s).sort end + # TODO: move these to specification def test_self_activate_via_require - new_spec "a", "1", "b" => "= 1" + a1 = new_spec "a", "1", "b" => "= 1" new_spec "b", "1", nil, "lib/b/c.rb" new_spec "b", "2", nil, "lib/b/c.rb" - Gem.activate "a", "= 1" + a1.activate require "b/c" assert_equal %w(a-1 b-1), loaded_spec_names end + # TODO: move these to specification def test_self_activate_deep_unambiguous a1 = new_spec "a", "1", "b" => "= 1" b1 = new_spec "b", "1", "c" => "= 1" @@ -71,7 +73,7 @@ def test_self_activate_deep_unambiguous install_specs a1, b1, b2, c1, c2 - Gem.activate "a", "= 1" + a1.activate assert_equal %w(a-1 b-1 c-1), loaded_spec_names end @@ -82,6 +84,7 @@ def save_loaded_features $LOADED_FEATURES.replace old_loaded_features end + # TODO: move these to specification def test_self_activate_ambiguous_direct save_loaded_features do a1 = new_spec "a", "1", "b" => "> 0" @@ -92,7 +95,7 @@ def test_self_activate_ambiguous_direct install_specs a1, b1, b2, c1, c2 - Gem.activate "a", "= 1" + a1.activate assert_equal %w(a-1), loaded_spec_names assert_equal ["b (> 0)"], unresolved_names @@ -103,6 +106,7 @@ def test_self_activate_ambiguous_direct end end + # TODO: move these to specification def test_self_activate_ambiguous_indirect save_loaded_features do a1 = new_spec "a", "1", "b" => "> 0" @@ -113,7 +117,7 @@ def test_self_activate_ambiguous_indirect install_specs a1, b1, b2, c1, c2 - Gem.activate "a", "= 1" + a1.activate assert_equal %w(a-1), loaded_spec_names assert_equal ["b (> 0)"], unresolved_names @@ -124,6 +128,7 @@ def test_self_activate_ambiguous_indirect end end + # TODO: move these to specification def test_self_activate_ambiguous_unrelated save_loaded_features do a1 = new_spec "a", "1", "b" => "> 0" @@ -135,7 +140,7 @@ def test_self_activate_ambiguous_unrelated install_specs a1, b1, b2, c1, c2, d1 - Gem.activate "a", "= 1" + a1.activate assert_equal %w(a-1), loaded_spec_names assert_equal ["b (> 0)"], unresolved_names @@ -146,6 +151,7 @@ def test_self_activate_ambiguous_unrelated end end + # TODO: move these to specification def test_self_activate_ambiguous_indirect_conflict save_loaded_features do a1 = new_spec "a", "1", "b" => "> 0" @@ -157,7 +163,7 @@ def test_self_activate_ambiguous_indirect_conflict install_specs a1, a2, b1, b2, c1, c2 - Gem.activate "a", "= 2" + a2.activate assert_equal %w(a-2), loaded_spec_names assert_equal ["b (> 0)"], unresolved_names @@ -168,13 +174,14 @@ def test_self_activate_ambiguous_indirect_conflict end end + # TODO: move these to specification def test_require_already_activated save_loaded_features do a1 = new_spec "a", "1", nil, "lib/d.rb" install_specs a1 # , a2, b1, b2, c1, c2 - Gem.activate "a", "= 1" + a1.activate assert_equal %w(a-1), loaded_spec_names assert_equal [], unresolved_names @@ -185,6 +192,7 @@ def test_require_already_activated end end + # TODO: move these to specification def test_require_already_activated_indirect_conflict save_loaded_features do a1 = new_spec "a", "1", "b" => "> 0" @@ -196,8 +204,8 @@ def test_require_already_activated_indirect_conflict install_specs a1, a2, b1, b2, c1, c2 - Gem.activate "a", "= 1" - Gem.activate "c", "= 1" + a1.activate + c1.activate assert_equal %w(a-1 c-1), loaded_spec_names assert_equal ["b (> 0)"], unresolved_names @@ -216,11 +224,12 @@ def test_require_missing end end + # TODO: move these to specification def test_self_activate_loaded - util_spec 'foo', '1' + foo = util_spec 'foo', '1' - assert Gem.activate 'foo' - refute Gem.activate 'foo' + assert foo.activate + refute foo.activate end ## @@ -243,15 +252,16 @@ def test_self_activate_unrelated # [B] ~> 1.0 # # and should resolve using b-1.0 + # TODO: move these to specification def test_self_activate_over - util_spec 'a', '1.0', 'b' => '>= 1.0', 'c' => '= 1.0' + a = util_spec 'a', '1.0', 'b' => '>= 1.0', 'c' => '= 1.0' util_spec 'b', '1.0' util_spec 'b', '1.1' util_spec 'b', '2.0' util_spec 'c', '1.0', 'b' => '~> 1.0' - Gem.activate "a" + a.activate assert_equal %w[a-1.0 c-1.0], loaded_spec_names assert_equal ["b (>= 1.0, ~> 1.0)"], unresolved_names @@ -672,7 +682,7 @@ def test_self_loaded_specs install_gem foo Gem.source_index = nil - Gem.activate 'foo' + foo.activate assert_equal true, Gem.loaded_specs.keys.include?('foo') end @@ -809,17 +819,6 @@ def test_self_refresh assert_equal nil, Gem.instance_variable_get(:@searcher) end - def test_self_required_location - util_make_gems - - assert_equal File.join(@tempdir, *%w[gemhome gems c-1.2 lib code.rb]), - Gem.required_location("c", "code.rb") - assert_equal File.join(@tempdir, *%w[gemhome gems a-1 lib code.rb]), - Gem.required_location("a", "code.rb", "< 2") - assert_equal File.join(@tempdir, *%w[gemhome gems a-2 lib code.rb]), - Gem.required_location("a", "code.rb", "= 2") - end - def test_self_ruby_escaping_spaces_in_path orig_ruby = Gem.ruby orig_bindir = Gem::ConfigMap[:bindir] From b8fa5000e615ae0e46526aa061efc8b853ce68a5 Mon Sep 17 00:00:00 2001 From: Erik Hollensbe Date: Mon, 4 Apr 2011 20:31:00 -0400 Subject: [PATCH 063/707] Remove warnings related to non-existent @gem_home and @gem_path --- test/rubygems/test_gem.rb | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 18d5c9b0..0704730a 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -493,8 +493,6 @@ def test_self_clear_paths Gem.clear_paths - assert_equal nil, Gem.instance_variable_get(:@gem_home) - assert_equal nil, Gem.instance_variable_get(:@gem_path) refute_equal searcher, Gem.searcher refute_equal source_index.object_id, Gem.source_index.object_id end From 78eba69a89c850f8d9c56e684d1b6b4382db856b Mon Sep 17 00:00:00 2001 From: Evan Phoenix Date: Tue, 5 Apr 2011 11:01:45 -0700 Subject: [PATCH 064/707] + Don't glob when looking for requirable files --- test/rubygems/test_gem.rb | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 18d5c9b0..a397c2f3 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -224,6 +224,20 @@ def test_require_missing end end + def test_require_does_not_glob + save_loaded_features do + a1 = new_spec "a", "1", nil, "lib/a1.rb" + + install_specs a1 + + assert_raises ::LoadError do + require "a*" + end + + assert_equal [], loaded_spec_names + end + end + # TODO: move these to specification def test_self_activate_loaded foo = util_spec 'foo', '1' From 85757b65d0ac864caa853b9768c0e623c57d95de Mon Sep 17 00:00:00 2001 From: Erik Hollensbe Date: Wed, 6 Apr 2011 05:06:51 -0400 Subject: [PATCH 065/707] File.chmod does not handle things that look like strings but actually aren't in a POLS fashion. --- test/rubygems/test_gem.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 0704730a..9e221154 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -596,14 +596,14 @@ def test_self_ensure_gem_directories_write_protected FileUtils.rm_r gemdir rescue nil refute File.exist?(gemdir), "manually remove #{gemdir}, tests are broken" FileUtils.mkdir_p gemdir - FileUtils.chmod 0400, gemdir + gemdir.chmod 0400 Gem.use_paths gemdir gemdir.ensure_gem_subdirectories refute File.exist?(Gem.cache_dir(gemdir)) ensure - FileUtils.chmod 0600, gemdir + gemdir.chmod 0600 end def test_self_ensure_gem_directories_write_protected_parents From dfd14d6b29274fc6a38b111f54eb8737068bc13a Mon Sep 17 00:00:00 2001 From: Erik Hollensbe Date: Tue, 12 Apr 2011 10:41:40 -0400 Subject: [PATCH 066/707] Removed Gem::Path#chmod and reverted to using FileUtils. --- test/rubygems/test_gem.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 88b2519c..d1f85c99 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -610,14 +610,14 @@ def test_self_ensure_gem_directories_write_protected FileUtils.rm_r gemdir rescue nil refute File.exist?(gemdir), "manually remove #{gemdir}, tests are broken" FileUtils.mkdir_p gemdir - gemdir.chmod 0400 + FileUtils.chmod 0400, gemdir Gem.use_paths gemdir gemdir.ensure_gem_subdirectories refute File.exist?(Gem.cache_dir(gemdir)) ensure - gemdir.chmod 0600 + FileUtils.chmod 0600, gemdir end def test_self_ensure_gem_directories_write_protected_parents From ca7feb6bff4c80106ff928bc392a12c94e41684f Mon Sep 17 00:00:00 2001 From: Ryan Davis Date: Tue, 12 Apr 2011 18:10:03 -0700 Subject: [PATCH 067/707] + Refactored GemPathSearcher entirely out. RIPMF --- test/rubygems/test_gem.rb | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index a397c2f3..90854a93 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -23,12 +23,12 @@ def setup def assert_activate expected, *specs specs.each do |spec| case spec - when Array - Gem::Specification.find(*spec).activate - when String - Gem::Specification.find(spec).activate - else + when String then + Gem::Specification.find_by_name(spec).activate + when Gem::Specification then spec.activate + else + flunk spec.inspect end end @@ -677,7 +677,9 @@ def test_self_find_files Gem.source_index = util_setup_spec_fetcher foo1, foo2 + # HACK should be Gem.refresh Gem.searcher = nil + Gem::Specification.reset expected = [ File.expand_path('test/rubygems/sff/discover.rb', @@project_dir), @@ -1044,6 +1046,7 @@ def test_load_plugins Gem.source_index = nil Gem.searcher = nil + Gem::Specification.reset gem 'foo' From 6a09a299c0bb6f594a145fddcd6f09fc4738dcb0 Mon Sep 17 00:00:00 2001 From: Ryan Davis Date: Wed, 13 Apr 2011 17:44:53 -0700 Subject: [PATCH 068/707] + Added Dependency#matching_specs + to_specs. Did a lot of work to move off of Gem.source_index... but we have a long way to go. + Deprecated Gem.source_index and Gem.available? - DependencyInstaller passed around a source_index instance but used Gem.source_index. + Deprecated all of SourceIndex. Started renaming errant gem vars to dep or spec. ugh. Added some Deprecate.skip_during to make running tests a little less painful. --- test/rubygems/test_gem.rb | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 4b64d7e9..baa2b55f 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -21,6 +21,8 @@ def setup end def assert_activate expected, *specs + Gem::Specification.reset # HACK? not sure... maybe + specs.each do |spec| case spec when String then @@ -432,10 +434,12 @@ def test_self_activate_old_required def test_self_available? util_make_gems - assert(Gem.available?("a")) - assert(Gem.available?("a", "1")) - assert(Gem.available?("a", ">1")) - assert(!Gem.available?("monkeys")) + Deprecate.skip_during do + assert(Gem.available?("a")) + assert(Gem.available?("a", "1")) + assert(Gem.available?("a", ">1")) + assert(!Gem.available?("monkeys")) + end end def test_self_bin_path_bin_name From 35449d65d5c11ebb0161a0bc5519867fdfb60fa3 Mon Sep 17 00:00:00 2001 From: Ryan Davis Date: Thu, 14 Apr 2011 00:12:24 -0700 Subject: [PATCH 069/707] Cleaned up a messy test --- test/rubygems/test_gem.rb | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index baa2b55f..accfed94 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -507,12 +507,13 @@ def test_self_clear_paths Gem.dir Gem.path searcher = Gem.searcher - source_index = Gem.source_index Gem.clear_paths - refute_equal searcher, Gem.searcher - refute_equal source_index.object_id, Gem.source_index.object_id + assert_nil Gem.instance_variable_get(:@gem_home) + assert_nil Gem.instance_variable_get(:@gem_path) + assert_nil Gem::Specification.send(:class_variable_get, :@@all) + refute_same searcher, Gem.searcher end def test_self_configuration @@ -827,13 +828,13 @@ def test_self_refresh FileUtils.mv a1_spec, @tempdir - refute Gem.source_index.gems.include?(@a1.full_name) + refute_includes Gem::Specification.all.map(&:full_name), @a1.full_name FileUtils.mv File.join(@tempdir, @a1.spec_name), a1_spec Gem.refresh - assert_includes Gem.source_index.gems, @a1.full_name + assert_includes Gem::Specification.all.map(&:full_name), @a1.full_name assert_equal nil, Gem.instance_variable_get(:@searcher) end @@ -930,7 +931,9 @@ def test_self_set_paths_nonexistent_home end def test_self_source_index - assert_kind_of Gem::SourceIndex, Gem.source_index + Deprecate.skip_during do + assert_kind_of Gem::SourceIndex, Gem.source_index + end end def test_self_sources From 2375ae981d19f0abcb801e8fdfa574594d1527a9 Mon Sep 17 00:00:00 2001 From: Ryan Davis Date: Thu, 14 Apr 2011 14:39:34 -0700 Subject: [PATCH 070/707] Dependency#to_specs raises if it doesn't match anything. matching_specs doesn't. + Deprecated Gem.searcher. Switched more over to SourceIndex. Deprecated GemPathSearcher#initialize. Cleaned up some code here and there. --- test/rubygems/test_gem.rb | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index accfed94..49ad4d99 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -504,16 +504,14 @@ def test_self_bindir_default_dir end def test_self_clear_paths - Gem.dir - Gem.path - searcher = Gem.searcher + assert_match(/gemhome$/, Gem.dir) + assert_match(/gemhome$/, Gem.path.first) Gem.clear_paths assert_nil Gem.instance_variable_get(:@gem_home) assert_nil Gem.instance_variable_get(:@gem_path) assert_nil Gem::Specification.send(:class_variable_get, :@@all) - refute_same searcher, Gem.searcher end def test_self_configuration @@ -835,7 +833,6 @@ def test_self_refresh Gem.refresh assert_includes Gem::Specification.all.map(&:full_name), @a1.full_name - assert_equal nil, Gem.instance_variable_get(:@searcher) end def test_self_ruby_escaping_spaces_in_path @@ -900,10 +897,6 @@ def test_self_ruby_version_1_9_2dev_r23493 util_restore_RUBY_VERSION end - def test_self_searcher - assert_kind_of Gem::GemPathSearcher, Gem.searcher - end - def test_self_set_paths other = File.join @tempdir, 'other' path = [@userhome, other].join File::PATH_SEPARATOR From 41a60eb1d858e52d4b2cd68714a1f1b931f70d89 Mon Sep 17 00:00:00 2001 From: Erik Hollensbe Date: Sun, 17 Apr 2011 04:03:40 -0400 Subject: [PATCH 071/707] Warning cleanup --- test/rubygems/test_gem.rb | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 49ad4d99..4107dc7a 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -509,8 +509,6 @@ def test_self_clear_paths Gem.clear_paths - assert_nil Gem.instance_variable_get(:@gem_home) - assert_nil Gem.instance_variable_get(:@gem_path) assert_nil Gem::Specification.send(:class_variable_get, :@@all) end From ea4ed9a7c10472a0d4f98805ec19563e9d7e8a6c Mon Sep 17 00:00:00 2001 From: Ryan Davis Date: Sun, 17 Apr 2011 04:47:32 -0700 Subject: [PATCH 072/707] path_support.rb: do the simplest thing that could possibly work. --- test/rubygems/test_gem.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 4107dc7a..40ecf3ad 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -895,7 +895,7 @@ def test_self_ruby_version_1_9_2dev_r23493 util_restore_RUBY_VERSION end - def test_self_set_paths + def test_self_paths_eq other = File.join @tempdir, 'other' path = [@userhome, other].join File::PATH_SEPARATOR @@ -903,12 +903,12 @@ def test_self_set_paths # FIXME remove after fixing test_case # ENV["GEM_HOME"] = @gemhome - Gem.paths = { :path => path } + Gem.paths = { "GEM_PATH" => path } assert_equal [@userhome, Gem::FS.new(other), @gemhome], Gem.path end - def test_self_set_paths_nonexistent_home + def test_self_paths_eq_nonexistent_home ENV['GEM_HOME'] = @gemhome Gem.clear_paths @@ -916,7 +916,7 @@ def test_self_set_paths_nonexistent_home ENV['HOME'] = other - Gem.paths = { :path => other } + Gem.paths = { "GEM_PATH" => other } assert_equal [other, @gemhome], Gem.path end From 92f04e6d530e38c50a3bf47989f72fa407e7f06c Mon Sep 17 00:00:00 2001 From: Ryan Davis Date: Mon, 25 Apr 2011 17:49:51 -0700 Subject: [PATCH 073/707] Sound and fury (and lots of diffs), signifying nothing (except really brittle tests). Modified test/rubygems/test_gem.rb --- test/rubygems/test_gem.rb | 40 ++++++++++++++++++--------------------- 1 file changed, 18 insertions(+), 22 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 40ecf3ad..c14fec90 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -21,8 +21,6 @@ def setup end def assert_activate expected, *specs - Gem::Specification.reset # HACK? not sure... maybe - specs.each do |spec| case spec when String then @@ -56,8 +54,10 @@ def unresolved_names # TODO: move these to specification def test_self_activate_via_require a1 = new_spec "a", "1", "b" => "= 1" - new_spec "b", "1", nil, "lib/b/c.rb" - new_spec "b", "2", nil, "lib/b/c.rb" + b1 = new_spec "b", "1", nil, "lib/b/c.rb" + b2 = new_spec "b", "2", nil, "lib/b/c.rb" + + install_specs a1, b1, b2 a1.activate require "b/c" @@ -653,28 +653,22 @@ def test_ensure_ssl_available end def test_self_find_files - discover_path = File.join 'lib', 'sff', 'discover.rb' cwd = File.expand_path("test/rubygems", @@project_dir) $LOAD_PATH.unshift cwd - foo1 = quick_gem 'sff', '1' do |s| - s.files << discover_path - end - - foo2 = quick_gem 'sff', '2' do |s| - s.files << discover_path - end - - path = File.join 'gems', foo1.full_name, discover_path - write_file(path) { |fp| fp.puts "# #{path}" } + discover_path = File.join 'lib', 'sff', 'discover.rb' - path = File.join 'gems', foo2.full_name, discover_path - write_file(path) { |fp| fp.puts "# #{path}" } + foo1, foo2 = %w(1 2).map { |version| + spec = quick_gem 'sff', version do |s| + s.files << discover_path + end - @fetcher = Gem::FakeFetcher.new - Gem::RemoteFetcher.fetcher = @fetcher + write_file(File.join 'gems', spec.full_name, discover_path) do |fp| + fp.puts "# #{spec.full_name}" + end - Gem.source_index = util_setup_spec_fetcher foo1, foo2 + spec + } # HACK should be Gem.refresh Gem.searcher = nil @@ -824,13 +818,15 @@ def test_self_refresh FileUtils.mv a1_spec, @tempdir - refute_includes Gem::Specification.all.map(&:full_name), @a1.full_name + Gem.refresh + + refute_includes Gem::Specification.map(&:full_name), @a1.full_name FileUtils.mv File.join(@tempdir, @a1.spec_name), a1_spec Gem.refresh - assert_includes Gem::Specification.all.map(&:full_name), @a1.full_name + assert_includes Gem::Specification.map(&:full_name), @a1.full_name end def test_self_ruby_escaping_spaces_in_path From d184b111f6589d5c9d4d0ca939727b3b66458b42 Mon Sep 17 00:00:00 2001 From: Ryan Davis Date: Tue, 26 Apr 2011 15:51:28 -0700 Subject: [PATCH 074/707] one last fix --- test/rubygems/test_gem.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index c14fec90..cc993a30 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -95,6 +95,7 @@ def test_self_activate_ambiguous_direct c1 = new_spec "c", "1" c2 = new_spec "c", "2" + Gem::Specification.reset install_specs a1, b1, b2, c1, c2 a1.activate From 6d66f78b0b294ba37189ce692f1799eb0aab9232 Mon Sep 17 00:00:00 2001 From: Eric Hodel Date: Tue, 26 Apr 2011 17:33:42 -0700 Subject: [PATCH 075/707] + RubyGems is now under the ruby license or 2-clause BSD-license --- LICENSE.txt | 79 ++++++++++++++++++++++++++++------------------------- 1 file changed, 42 insertions(+), 37 deletions(-) diff --git a/LICENSE.txt b/LICENSE.txt index db88c5e1..776e9a48 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,53 +1,58 @@ RubyGems is copyrighted free software by Chad Fowler, Rich Kilmer, Jim Weirich and others. You can redistribute it and/or modify it under -either the terms of the GPL (see the GPL.txt file), or the conditions -below: +either the terms of the 2-clause BSDL (see the file BSDL.txt), or the +conditions below: - 1. You may make and give away verbatim copies of the source form of the - software without restriction, provided that you duplicate all of the - original copyright notices and associated disclaimers. +1. You may make and give away verbatim copies of the source form of the + software without restriction, provided that you duplicate all of the + original copyright notices and associated disclaimers. - 2. You may modify your copy of the software in any way, provided that - you do at least ONE of the following: +2. You may modify your copy of the software in any way, provided that + you do at least ONE of the following: - a) place your modifications in the Public Domain or otherwise - make them Freely Available, such as by posting said - modifications to Usenet or an equivalent medium, or by allowing - the author to include your modifications in the software. + a. place your modifications in the Public Domain or otherwise + make them Freely Available, such as by posting said + modifications to Usenet or an equivalent medium, or by allowing + the author to include your modifications in the software. - b) use the modified software only within your corporation or - organization. + b. use the modified software only within your corporation or + organization. - c) rename any non-standard executables so the names do not conflict - with standard executables, which must also be provided. + c. give non-standard executables non-standard names, with + instructions on where to get the original software distribution. - d) make other distribution arrangements with the author. + d. make other distribution arrangements with the author. - 3. You may distribute the software in object code or executable - form, provided that you do at least ONE of the following: +3. You may distribute the software in object code or executable + form, provided that you do at least ONE of the following: - a) distribute the executables and library files of the software, - together with instructions (in the manual page or equivalent) - on where to get the original distribution. + a. distribute the executables and library files of the software, + together with instructions (in the manual page or equivalent) + on where to get the original distribution. - b) accompany the distribution with the machine-readable source of - the software. + b. accompany the distribution with the machine-readable source of + the software. - c) give non-standard executables non-standard names, with - instructions on where to get the original software distribution. + c. give non-standard executables non-standard names, with + instructions on where to get the original software distribution. - d) make other distribution arrangements with the author. + d. make other distribution arrangements with the author. - 4. You may modify and include the part of the software into any other - software (possibly commercial). +4. You may modify and include the part of the software into any other + software (possibly commercial). But some files in the distribution + are not written by the author, so that they are not under these terms. - 5. The scripts and library files supplied as input to or produced as - output from the software do not automatically fall under the - copyright of the software, but belong to whomever generated them, - and may be sold commercially, and may be aggregated with this - software. + For the list of those files and their copying conditions, see the + file LEGAL. + +5. The scripts and library files supplied as input to or produced as + output from the software do not automatically fall under the + copyright of the software, but belong to whomever generated them, + and may be sold commercially, and may be aggregated with this + software. + +6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE. - 6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR - IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - PURPOSE. From f9c20fc390e71b6bef52acad400ba29d9e1c714b Mon Sep 17 00:00:00 2001 From: Eric Hodel Date: Tue, 26 Apr 2011 17:42:02 -0700 Subject: [PATCH 076/707] Correction: + RubyGems is now under the Ruby License or the MIT license --- LICENSE.txt | 2 +- MIT.txt | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 MIT.txt diff --git a/LICENSE.txt b/LICENSE.txt index 776e9a48..f2b95868 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,6 +1,6 @@ RubyGems is copyrighted free software by Chad Fowler, Rich Kilmer, Jim Weirich and others. You can redistribute it and/or modify it under -either the terms of the 2-clause BSDL (see the file BSDL.txt), or the +either the terms of the MIT license (see the file MIT.txt), or the conditions below: 1. You may make and give away verbatim copies of the source form of the diff --git a/MIT.txt b/MIT.txt new file mode 100644 index 00000000..0e6643ab --- /dev/null +++ b/MIT.txt @@ -0,0 +1,20 @@ +Copyright (c) Chad Fowler, Rich Kilmer, Jim Weirich and others. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. From 136f700bf371423a658806e469b1c9a6c9e80155 Mon Sep 17 00:00:00 2001 From: Eric Hodel Date: Wed, 27 Apr 2011 14:24:03 -0700 Subject: [PATCH 077/707] default_executable is deprecated, remove (impossible) use of it --- test/rubygems/test_gem.rb | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index cc993a30..6a64a6af 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -443,6 +443,14 @@ def test_self_available? end end + def test_self_bin_path_no_exec_name + e = assert_raises ArgumentError do + Gem.bin_path 'a' + end + + assert_equal 'you must supply exec_name', e.message + end + def test_self_bin_path_bin_name util_exec_gem assert_equal @abin_path, Gem.bin_path('a', 'abin') From c1db9d35a5b860aaac334eedefd0bc730800c667 Mon Sep 17 00:00:00 2001 From: Evan Phoenix Date: Thu, 28 Apr 2011 12:36:06 -0700 Subject: [PATCH 078/707] Remove all usage of Gem.source_index= It doesn't exist at runtime anymore, and having it exist only at test time was causing a bunch of missed failures. --- test/rubygems/test_gem.rb | 4 ---- 1 file changed, 4 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 6a64a6af..2fb24f2e 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -541,8 +541,6 @@ def test_self_datadir install_gem foo end - Gem.source_index = nil - gem 'foo' expected = File.join @gemhome, 'gems', foo.full_name, 'data', 'foo' @@ -698,7 +696,6 @@ def test_self_find_files def test_self_loaded_specs foo = quick_spec 'foo' install_gem foo - Gem.source_index = nil foo.activate @@ -1045,7 +1042,6 @@ def test_load_plugins install_gem foo end - Gem.source_index = nil Gem.searcher = nil Gem::Specification.reset From 23aa666cfc63ff622c7941cc6667c9111bfb41b1 Mon Sep 17 00:00:00 2001 From: Ryan Davis Date: Tue, 3 May 2011 03:06:55 -0700 Subject: [PATCH 079/707] Removed Gem::FS and Gem::Path. Switched off of many (but not all) of our deprecated Gem and Spec methods. Refactored Installer to work better with the new Specification. + Added TestCase#assert_path_exists and refute_path_exists. Will move to minitest. --- test/rubygems/test_gem.rb | 59 ++++++++++++++++----------------------- 1 file changed, 24 insertions(+), 35 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 2fb24f2e..c9281528 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -506,8 +506,6 @@ def test_self_bindir_default_dir RbConfig::CONFIG['bindir'] end - bindir = Gem::Path.new(bindir) - assert_equal bindir, Gem.bindir(default) assert_equal bindir, Gem.bindir(Pathname.new(default)) end @@ -595,42 +593,42 @@ def test_self_ensure_gem_directories FileUtils.rm_r @gemhome Gem.use_paths @gemhome - @gemhome.ensure_gem_subdirectories + Gem.ensure_gem_subdirectories @gemhome - assert File.directory?(Gem.cache_dir(@gemhome)) + assert File.directory? File.join(@gemhome, "cache") end def test_self_ensure_gem_directories_missing_parents - gemdir = Gem::FS.new @tempdir, 'a/b/c/gemdir' + gemdir = File.join @tempdir, 'a/b/c/gemdir' FileUtils.rm_rf File.join(@tempdir, 'a') rescue nil refute File.exist?(File.join(@tempdir, 'a')), "manually remove #{File.join @tempdir, 'a'}, tests are broken" Gem.use_paths gemdir - gemdir.ensure_gem_subdirectories + Gem.ensure_gem_subdirectories gemdir - assert File.directory?(Gem.cache_dir(gemdir)) + assert File.directory?(util_cache_dir) end unless win_platform? then # only for FS that support write protection def test_self_ensure_gem_directories_write_protected - gemdir = Gem::FS.new @tempdir, "egd" + gemdir = File.join @tempdir, "egd" FileUtils.rm_r gemdir rescue nil refute File.exist?(gemdir), "manually remove #{gemdir}, tests are broken" FileUtils.mkdir_p gemdir FileUtils.chmod 0400, gemdir Gem.use_paths gemdir - gemdir.ensure_gem_subdirectories + Gem.ensure_gem_subdirectories gemdir - refute File.exist?(Gem.cache_dir(gemdir)) + refute File.exist?(util_cache_dir) ensure FileUtils.chmod 0600, gemdir end def test_self_ensure_gem_directories_write_protected_parents parent = File.join(@tempdir, "egd") - gemdir = Gem::FS.new "#{parent}/a/b/c" + gemdir = "#{parent}/a/b/c" FileUtils.rm_r parent rescue nil refute File.exist?(parent), "manually remove #{parent}, tests are broken" @@ -638,9 +636,9 @@ def test_self_ensure_gem_directories_write_protected_parents FileUtils.chmod 0400, parent Gem.use_paths(gemdir) - gemdir.ensure_gem_subdirectories + Gem.ensure_gem_subdirectories gemdir - refute File.exist?(Gem.cache_dir(gemdir)) + refute File.exist? File.join(gemdir, "gems") ensure FileUtils.chmod 0600, parent end @@ -820,19 +818,20 @@ def test_self_prefix_sitelibdir def test_self_refresh util_make_gems - a1_spec = File.join @gemhome, "specifications", @a1.spec_name + a1_spec = @a1.spec_file + moved_path = File.join @tempdir, File.basename(a1_spec) - FileUtils.mv a1_spec, @tempdir + FileUtils.mv a1_spec, moved_path Gem.refresh - refute_includes Gem::Specification.map(&:full_name), @a1.full_name + refute_includes Gem::Specification.all_names, @a1.full_name - FileUtils.mv File.join(@tempdir, @a1.spec_name), a1_spec + FileUtils.mv moved_path, a1_spec Gem.refresh - assert_includes Gem::Specification.map(&:full_name), @a1.full_name + assert_includes Gem::Specification.all_names, @a1.full_name end def test_self_ruby_escaping_spaces_in_path @@ -907,7 +906,7 @@ def test_self_paths_eq ENV["GEM_HOME"] = @gemhome Gem.paths = { "GEM_PATH" => path } - assert_equal [@userhome, Gem::FS.new(other), @gemhome], Gem.path + assert_equal [@userhome, other, @gemhome], Gem.path end def test_self_paths_eq_nonexistent_home @@ -967,20 +966,6 @@ def test_self_user_home end end - def test_self_cache_dir - util_ensure_gem_dirs - - assert_equal File.join(@gemhome, 'cache'), Gem.cache_dir - assert_equal File.join(@userhome, '.gem', Gem.ruby_engine, Gem::ConfigMap[:ruby_version], 'cache'), Gem.cache_dir(Gem.user_dir) - end - - def test_self_cache_gem - util_ensure_gem_dirs - - assert_equal File.join(@gemhome, 'cache', 'test.gem'), Gem.cache_gem('test.gem') - assert_equal File.join(@userhome, '.gem', Gem.ruby_engine, Gem::ConfigMap[:ruby_version], 'cache', 'test.gem'), Gem.cache_gem('test.gem', Gem.user_dir) - end - if Gem.win_platform? then def test_self_user_home_userprofile skip 'Ruby 1.9 properly handles ~ path expansion' unless '1.9' > RUBY_VERSION @@ -1086,13 +1071,13 @@ def with_plugin(path) end def util_ensure_gem_dirs - @gemhome.ensure_gem_subdirectories + Gem.ensure_gem_subdirectories @gemhome # # FIXME what does this solve precisely? -ebh # @additional.each do |dir| - @gemhome.ensure_gem_subdirectories + Gem.ensure_gem_subdirectories @gemhome end end @@ -1140,5 +1125,9 @@ def util_remove_interrupt_command Gem::Commands.send :remove_const, :InterruptCommand if Gem::Commands.const_defined? :InterruptCommand end + + def util_cache_dir + File.join Gem.dir, "cache" + end end From 5d3aa3af48ef5c70502fb8d9d53725d78157ef05 Mon Sep 17 00:00:00 2001 From: Eric Hodel Date: Tue, 3 May 2011 21:04:16 -0700 Subject: [PATCH 080/707] Gem activation now delays adding a gem to loaded_specs until after it has been activated. Gem.try_activate is now tested in the failing case --- test/rubygems/test_gem.rb | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index c9281528..2bd81f28 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -932,6 +932,22 @@ def test_self_sources assert_equal %w[http://gems.example.com/], Gem.sources end + def test_self_try_activate_missing_dep + a = util_spec 'a', '1.0', 'b' => '>= 1.0' + + a_file = File.join a.gem_dir, 'lib', 'a_file.rb' + + write_file a_file do |io| + io.puts '# a_file.rb' + end + + e = assert_raises Gem::LoadError do + Gem.try_activate 'a_file' + end + + assert_match %r%Could not find b %, e.message + end + def test_ssl_available_eh orig_Gem_ssl_available = Gem.ssl_available? From adae66be3f932a66d2c03c68248e484584ca4bd1 Mon Sep 17 00:00:00 2001 From: Eric Hodel Date: Thu, 5 May 2011 12:30:17 -0700 Subject: [PATCH 081/707] - gem dep can fetch remote dependencies for non-latest gems again. + Added Gem::Requirement#specific? and Gem::Dependency#specific? --- test/rubygems/test_gem_requirement.rb | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/test/rubygems/test_gem_requirement.rb b/test/rubygems/test_gem_requirement.rb index 76ddf369..0bc6ad70 100644 --- a/test/rubygems/test_gem_requirement.rb +++ b/test/rubygems/test_gem_requirement.rb @@ -250,6 +250,19 @@ def test_satisfied_by_boxed refute_satisfied_by "2.0", "~> 1.4.4" end + def test_specific + refute req('> 1') .specific? + refute req('>= 1').specific? + + assert req('!= 1').specific? + assert req('< 1') .specific? + assert req('<= 1').specific? + assert req('= 1') .specific? + assert req('~> 1').specific? + + assert req('> 1', '> 2').specific? # GIGO + end + def test_bad refute_satisfied_by "", "> 0.1" refute_satisfied_by "1.2.3", "!= 1.2.3" From 9e4d6b09d98d6792ac1c4a0f02423d5a10630084 Mon Sep 17 00:00:00 2001 From: Erik Michaels-Ober Date: Sat, 7 May 2011 11:53:04 -0700 Subject: [PATCH 082/707] Covert all GitHub links to HTTPS --- bundler/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bundler/README.md b/bundler/README.md index 0cd4dd15..8a5f1a6e 100644 --- a/bundler/README.md +++ b/bundler/README.md @@ -12,17 +12,17 @@ See [gembundler.com](http://gembundler.com) for up-to-date installation and usag ### Troubleshooting -For help with common problems, see [ISSUES](http://github.com/carlhuda/bundler/blob/master/ISSUES.md). +For help with common problems, see [ISSUES](https://github.com/carlhuda/bundler/blob/master/ISSUES.md). ### Development -To see what has changed in recent versions of bundler, see the [CHANGELOG](http://github.com/carlhuda/bundler/blob/master/CHANGELOG.md). +To see what has changed in recent versions of bundler, see the [CHANGELOG](https://github.com/carlhuda/bundler/blob/master/CHANGELOG.md). The `master` branch contains our current progress towards version 1.1. Because of that, please submit bugfix pull requests against the `1-0-stable` branch. ### Upgrading from Bundler 0.8 to 0.9 and above -See [UPGRADING](http://github.com/carlhuda/bundler/blob/master/UPGRADING.md). +See [UPGRADING](https://github.com/carlhuda/bundler/blob/master/UPGRADING.md). ### Other questions From c0eb3279dbf0842509d2557c673c28929f5c8cbd Mon Sep 17 00:00:00 2001 From: Ryan Davis Date: Fri, 20 May 2011 17:54:49 -0700 Subject: [PATCH 083/707] - Fixed SecurityError in Gem::Specification.load when $SAFE=1. (ged) + Added untaints as needed to get full test run with $SAFE=1. --- test/rubygems/test_gem.rb | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 2bd81f28..a50b1445 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -5,6 +5,12 @@ require 'pathname' require 'tmpdir' +# TODO: push this up to test_case.rb once battle tested +$SAFE=1 +$LOAD_PATH.each do |path| + path.untaint +end + class TestGem < Gem::TestCase def setup From 3a5aaff2d2c58230d454235c9a769679dd798bc3 Mon Sep 17 00:00:00 2001 From: James Tucker Date: Wed, 25 May 2011 20:50:50 -0700 Subject: [PATCH 084/707] Fix namespace of Deprecate so that we avoid clobbering someone --- test/rubygems/test_gem.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index a50b1445..066f9823 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -441,7 +441,7 @@ def test_self_activate_old_required def test_self_available? util_make_gems - Deprecate.skip_during do + Gem::Deprecate.skip_during do assert(Gem.available?("a")) assert(Gem.available?("a", "1")) assert(Gem.available?("a", ">1")) @@ -929,7 +929,7 @@ def test_self_paths_eq_nonexistent_home end def test_self_source_index - Deprecate.skip_during do + Gem::Deprecate.skip_during do assert_kind_of Gem::SourceIndex, Gem.source_index end end From 5d5f06b79cf5756edc62dc00143980a72f67da3a Mon Sep 17 00:00:00 2001 From: James Tucker Date: Wed, 25 May 2011 21:08:24 -0700 Subject: [PATCH 085/707] Introduce Gem.running and utilize in deprecate_quiet to reintroduce spec warnings during gem command runs --- test/rubygems/test_gem.rb | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 066f9823..9cdffd62 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1076,6 +1076,14 @@ def test_load_env_plugins assert_equal :loaded, TEST_PLUGIN_EXCEPTION rescue nil end + def test_running + assert !Gem.running + Gem.running do + assert Gem.running + end + assert !Gem.running + end + def with_plugin(path) test_plugin_path = File.expand_path("test/rubygems/plugin/#{path}", @@project_dir) From 2ad08b1ef9bca4e850f0f31b2985fca9eaa93994 Mon Sep 17 00:00:00 2001 From: Evan Phoenix Date: Tue, 31 May 2011 17:23:08 -0700 Subject: [PATCH 086/707] Revert "+ Introduce a deprecate_quiet that respects $VERBOSE. Use in Gem::Specifications" This reverts commit 11a57b06f69f6e5c589be3ce5d51a4737db66d29. Conflicts: lib/rubygems/specification.rb --- test/rubygems/test_gem.rb | 8 -------- 1 file changed, 8 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 9cdffd62..066f9823 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1076,14 +1076,6 @@ def test_load_env_plugins assert_equal :loaded, TEST_PLUGIN_EXCEPTION rescue nil end - def test_running - assert !Gem.running - Gem.running do - assert Gem.running - end - assert !Gem.running - end - def with_plugin(path) test_plugin_path = File.expand_path("test/rubygems/plugin/#{path}", @@project_dir) From 65fe1fb03e08497eb67879238c6b91f7aa6a6d75 Mon Sep 17 00:00:00 2001 From: Evan Phoenix Date: Wed, 1 Jun 2011 21:18:13 -0700 Subject: [PATCH 087/707] Fix Gem.latest_load_paths --- test/rubygems/test_gem.rb | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 066f9823..defd3c05 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1076,6 +1076,25 @@ def test_load_env_plugins assert_equal :loaded, TEST_PLUGIN_EXCEPTION rescue nil end + def test_latest_load_paths + stem = Gem.path.first + + spec = quick_spec 'a', '4' do |s| + s.require_paths = ["lib"] + end + + install_gem spec + + # @exec_path = File.join spec.full_gem_path, spec.bindir, 'exec' + # @abin_path = File.join spec.full_gem_path, spec.bindir, 'abin' + # FileUtils.mkdir_p File.join(stem, "gems", "test-3") + + Gem::Deprecate.skip_during do + expected = [File.join(@gemhome, "gems", "a-4", "lib")] + assert_equal expected, Gem.latest_load_paths + end + end + def with_plugin(path) test_plugin_path = File.expand_path("test/rubygems/plugin/#{path}", @@project_dir) From 254e6caaa2d5ecbe07abe6bd396afb0fdcbc4f49 Mon Sep 17 00:00:00 2001 From: Eric Hodel Date: Thu, 2 Jun 2011 21:35:27 -0700 Subject: [PATCH 088/707] Test pre and post hook adding methods --- test/rubygems/test_gem.rb | 56 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index defd3c05..859715bb 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -928,6 +928,62 @@ def test_self_paths_eq_nonexistent_home assert_equal [other, @gemhome], Gem.path end + def test_self_post_build + assert_equal 1, Gem.post_build_hooks.length + + Gem.post_build do |installer| end + + assert_equal 2, Gem.post_build_hooks.length + end + + def test_self_post_install + assert_equal 1, Gem.post_install_hooks.length + + Gem.post_install do |installer| end + + assert_equal 2, Gem.post_install_hooks.length + end + + def test_self_post_reset + assert_empty Gem.post_reset_hooks + + Gem.post_reset do |installer| end + + assert_equal 1, Gem.post_reset_hooks.length + end + + def test_self_post_uninstall + assert_equal 1, Gem.post_uninstall_hooks.length + + Gem.post_uninstall do |installer| end + + assert_equal 2, Gem.post_uninstall_hooks.length + end + + def test_self_pre_install + assert_equal 1, Gem.pre_install_hooks.length + + Gem.pre_install do |installer| end + + assert_equal 2, Gem.pre_install_hooks.length + end + + def test_self_pre_reset + assert_empty Gem.pre_reset_hooks + + Gem.pre_reset do |installer| end + + assert_equal 1, Gem.pre_reset_hooks.length + end + + def test_self_pre_uninstall + assert_equal 1, Gem.pre_uninstall_hooks.length + + Gem.pre_uninstall do |installer| end + + assert_equal 2, Gem.pre_uninstall_hooks.length + end + def test_self_source_index Gem::Deprecate.skip_during do assert_kind_of Gem::SourceIndex, Gem.source_index From 6dd42b9b95125b522941660b5f3d2c940818392e Mon Sep 17 00:00:00 2001 From: Eric Hodel Date: Thu, 2 Jun 2011 22:05:07 -0700 Subject: [PATCH 089/707] - Add post-installs hooks that runs after Gem::DependencyInstaller finishes installing a set of gems - Fix documentation for the various hooks collections --- test/rubygems/test_gem.rb | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 859715bb..6342172a 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -944,6 +944,14 @@ def test_self_post_install assert_equal 2, Gem.post_install_hooks.length end + def test_self_post_installs + assert_empty Gem.post_installs_hooks + + Gem.post_installs do |gems| end + + assert_equal 1, Gem.post_installs_hooks.length + end + def test_self_post_reset assert_empty Gem.post_reset_hooks From 628a16f451ecd3e6eb2f545bc844613242254303 Mon Sep 17 00:00:00 2001 From: Evan Phoenix Date: Mon, 6 Jun 2011 22:40:18 -0700 Subject: [PATCH 090/707] Fix some warnings --- test/rubygems/test_gem.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 6342172a..ee710ed5 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -955,7 +955,7 @@ def test_self_post_installs def test_self_post_reset assert_empty Gem.post_reset_hooks - Gem.post_reset do |installer| end + Gem.post_reset { } assert_equal 1, Gem.post_reset_hooks.length end @@ -979,7 +979,7 @@ def test_self_pre_install def test_self_pre_reset assert_empty Gem.pre_reset_hooks - Gem.pre_reset do |installer| end + Gem.pre_reset { } assert_equal 1, Gem.pre_reset_hooks.length end From c6d644ce22e047735da134b34ceaaba079a3ffd9 Mon Sep 17 00:00:00 2001 From: Ryan Davis Date: Tue, 7 Jun 2011 14:54:32 -0700 Subject: [PATCH 091/707] Switched all our user-facing code to Gem::Specification.unresolved_deps. --- test/rubygems/test_gem.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index ee710ed5..aadf3c91 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -54,7 +54,7 @@ def loaded_spec_names end def unresolved_names - Gem.unresolved_deps.values.map(&:to_s).sort + Gem::Specification.unresolved_deps.values.map(&:to_s).sort end # TODO: move these to specification From aa2ec14d81420373a434d2d78d55ed0fcf501962 Mon Sep 17 00:00:00 2001 From: Eric Hodel Date: Tue, 7 Jun 2011 17:08:28 -0700 Subject: [PATCH 092/707] - Rename post_installs to done_installing --- test/rubygems/test_gem.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index aadf3c91..99a019a3 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -944,12 +944,12 @@ def test_self_post_install assert_equal 2, Gem.post_install_hooks.length end - def test_self_post_installs - assert_empty Gem.post_installs_hooks + def test_self_done_installing + assert_empty Gem.done_installing_hooks - Gem.post_installs do |gems| end + Gem.done_installing do |gems| end - assert_equal 1, Gem.post_installs_hooks.length + assert_equal 1, Gem.done_installing_hooks.length end def test_self_post_reset From af7f672dc01a76e9f1c0ff44760b1c6d8f255827 Mon Sep 17 00:00:00 2001 From: Evan Phoenix Date: Sat, 11 Jun 2011 23:12:19 -0700 Subject: [PATCH 093/707] Break some tests that only use require out for clarity --- test/rubygems/test_gem.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 99a019a3..a70b3a94 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -66,7 +66,9 @@ def test_self_activate_via_require install_specs a1, b1, b2 a1.activate - require "b/c" + save_loaded_features do + require "b/c" + end assert_equal %w(a-1 b-1), loaded_spec_names end From b653d56ddb1456a9ef9af7b0040dd8cc136c1e5b Mon Sep 17 00:00:00 2001 From: Eric Hodel Date: Wed, 15 Jun 2011 16:40:24 -0700 Subject: [PATCH 094/707] - Added Gem::rubygems_version which is like Gem::ruby_version --- test/rubygems/test_gem.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index a70b3a94..cadef137 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -904,6 +904,10 @@ def test_self_ruby_version_1_9_2dev_r23493 util_restore_RUBY_VERSION end + def test_self_rubygems_version + assert_equal Gem::Version.new(Gem::VERSION), Gem.rubygems_version + end + def test_self_paths_eq other = File.join @tempdir, 'other' path = [@userhome, other].join File::PATH_SEPARATOR From 25df280fd489553e738cefaed8797c1fefbf953d Mon Sep 17 00:00:00 2001 From: Ryan Davis Date: Mon, 20 Jun 2011 15:20:30 -0700 Subject: [PATCH 095/707] - Gem::Requirement.satisfied_by? raises ArgumentError if given a non-version arg. --- test/rubygems/test_gem_requirement.rb | 37 ++++++++++++++++++++------- 1 file changed, 28 insertions(+), 9 deletions(-) diff --git a/test/rubygems/test_gem_requirement.rb b/test/rubygems/test_gem_requirement.rb index 0bc6ad70..ef288b0b 100644 --- a/test/rubygems/test_gem_requirement.rb +++ b/test/rubygems/test_gem_requirement.rb @@ -67,28 +67,37 @@ def test_prerelease_eh def test_satisfied_by_eh_bang_equal r = req '!= 1.2' - assert_satisfied_by nil, r assert_satisfied_by "1.1", r refute_satisfied_by "1.2", r assert_satisfied_by "1.3", r + + assert_raises ArgumentError do + assert_satisfied_by nil, r + end end def test_satisfied_by_eh_blank r = req "1.2" - refute_satisfied_by nil, r refute_satisfied_by "1.1", r assert_satisfied_by "1.2", r refute_satisfied_by "1.3", r + + assert_raises ArgumentError do + assert_satisfied_by nil, r + end end def test_satisfied_by_eh_equal r = req "= 1.2" - refute_satisfied_by nil, r refute_satisfied_by "1.1", r assert_satisfied_by "1.2", r refute_satisfied_by "1.3", r + + assert_raises ArgumentError do + assert_satisfied_by nil, r + end end def test_satisfied_by_eh_gt @@ -98,7 +107,7 @@ def test_satisfied_by_eh_gt refute_satisfied_by "1.2", r assert_satisfied_by "1.3", r - assert_raises NoMethodError do + assert_raises ArgumentError do r.satisfied_by? nil end end @@ -110,7 +119,7 @@ def test_satisfied_by_eh_gte assert_satisfied_by "1.2", r assert_satisfied_by "1.3", r - assert_raises NoMethodError do + assert_raises ArgumentError do r.satisfied_by? nil end end @@ -122,7 +131,7 @@ def test_satisfied_by_eh_list assert_satisfied_by "1.2", r refute_satisfied_by "1.3", r - assert_raises NoMethodError do + assert_raises ArgumentError do r.satisfied_by? nil end end @@ -134,7 +143,7 @@ def test_satisfied_by_eh_lt refute_satisfied_by "1.2", r refute_satisfied_by "1.3", r - assert_raises NoMethodError do + assert_raises ArgumentError do r.satisfied_by? nil end end @@ -146,7 +155,7 @@ def test_satisfied_by_eh_lte assert_satisfied_by "1.2", r refute_satisfied_by "1.3", r - assert_raises NoMethodError do + assert_raises ArgumentError do r.satisfied_by? nil end end @@ -158,7 +167,7 @@ def test_satisfied_by_eh_tilde_gt assert_satisfied_by "1.2", r assert_satisfied_by "1.3", r - assert_raises NoMethodError do + assert_raises ArgumentError do r.satisfied_by? nil end end @@ -206,6 +215,16 @@ def test_illformed_requirements end end + def test_satisfied_by_eh_non_versions + assert_raises ArgumentError do + req(">= 0").satisfied_by? Object.new + end + + assert_raises ArgumentError do + req(">= 0").satisfied_by? Gem::Requirement.default + end + end + def test_satisfied_by_eh_boxed refute_satisfied_by "1.3", "~> 1.4" assert_satisfied_by "1.4", "~> 1.4" From 4d7e2ecf5ff58368237361e6064c78d17d857471 Mon Sep 17 00:00:00 2001 From: Ryan Davis Date: Mon, 20 Jun 2011 15:22:54 -0700 Subject: [PATCH 096/707] - Gem::Requirement#<=> should return nil on non-requirement arg. --- test/rubygems/test_gem_requirement.rb | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/test/rubygems/test_gem_requirement.rb b/test/rubygems/test_gem_requirement.rb index ef288b0b..7e1ecb2a 100644 --- a/test/rubygems/test_gem_requirement.rb +++ b/test/rubygems/test_gem_requirement.rb @@ -269,6 +269,16 @@ def test_satisfied_by_boxed refute_satisfied_by "2.0", "~> 1.4.4" end + def test_spaceship + assert_equal -1, req("= 0") <=> req("= 1") + assert_equal 0, req("= 0") <=> req("= 0") + assert_equal 1, req("= 1") <=> req("= 0") + + assert_nil req("= 1") <=> v("42") + + flunk "not yet" + end + def test_specific refute req('> 1') .specific? refute req('>= 1').specific? From ec5e431be1d37ebea6d897de2fdf0b97f3b10643 Mon Sep 17 00:00:00 2001 From: Ryan Davis Date: Mon, 20 Jun 2011 15:25:32 -0700 Subject: [PATCH 097/707] I am a dumbass... that is all. --- test/rubygems/test_gem_requirement.rb | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/rubygems/test_gem_requirement.rb b/test/rubygems/test_gem_requirement.rb index 7e1ecb2a..e3d84b98 100644 --- a/test/rubygems/test_gem_requirement.rb +++ b/test/rubygems/test_gem_requirement.rb @@ -275,8 +275,6 @@ def test_spaceship assert_equal 1, req("= 1") <=> req("= 0") assert_nil req("= 1") <=> v("42") - - flunk "not yet" end def test_specific From 0900c45bba8503a3226d2baff8749cb8cab66c15 Mon Sep 17 00:00:00 2001 From: Ryan Davis Date: Wed, 22 Jun 2011 14:09:38 -0700 Subject: [PATCH 098/707] cleaned up deprecation warnings in test --- test/rubygems/test_gem_requirement.rb | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/test/rubygems/test_gem_requirement.rb b/test/rubygems/test_gem_requirement.rb index e3d84b98..0a07bc0a 100644 --- a/test/rubygems/test_gem_requirement.rb +++ b/test/rubygems/test_gem_requirement.rb @@ -270,11 +270,13 @@ def test_satisfied_by_boxed end def test_spaceship - assert_equal -1, req("= 0") <=> req("= 1") - assert_equal 0, req("= 0") <=> req("= 0") - assert_equal 1, req("= 1") <=> req("= 0") + Gem::Deprecate.skip_during do + assert_equal -1, req("= 0") <=> req("= 1") + assert_equal 0, req("= 0") <=> req("= 0") + assert_equal 1, req("= 1") <=> req("= 0") - assert_nil req("= 1") <=> v("42") + assert_nil req("= 1") <=> v("42") + end end def test_specific From 7d12a0bfee51f654399f4cc0b5ef840000f9310e Mon Sep 17 00:00:00 2001 From: Ryan Davis Date: Wed, 22 Jun 2011 17:59:02 -0700 Subject: [PATCH 099/707] quell warning --- test/rubygems/test_gem_requirement.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/rubygems/test_gem_requirement.rb b/test/rubygems/test_gem_requirement.rb index 0a07bc0a..3680d55f 100644 --- a/test/rubygems/test_gem_requirement.rb +++ b/test/rubygems/test_gem_requirement.rb @@ -271,7 +271,7 @@ def test_satisfied_by_boxed def test_spaceship Gem::Deprecate.skip_during do - assert_equal -1, req("= 0") <=> req("= 1") + assert_equal(-1, req("= 0") <=> req("= 1")) assert_equal 0, req("= 0") <=> req("= 0") assert_equal 1, req("= 1") <=> req("= 0") From 09be09bacc8739005937201f156b5176a6686fec Mon Sep 17 00:00:00 2001 From: Ryan Davis Date: Wed, 22 Jun 2011 18:14:58 -0700 Subject: [PATCH 100/707] test for APPLE_GEM_HOME were not right... the const is on Object, not Gem --- test/rubygems/test_gem.rb | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index cadef137..a73dbe11 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -738,11 +738,14 @@ def test_self_path_APPLE_GEM_HOME Gem.clear_paths apple_gem_home = File.join @tempdir, 'apple_gem_home' - Gem.const_set :APPLE_GEM_HOME, apple_gem_home + + old, $-w = $-w, nil + Object.const_set :APPLE_GEM_HOME, apple_gem_home + $-w = old assert_includes Gem.path, apple_gem_home ensure - Gem.send :remove_const, :APPLE_GEM_HOME + Object.send :remove_const, :APPLE_GEM_HOME end def test_self_path_APPLE_GEM_HOME_GEM_PATH From 758db3c5a218e7617421f989288aee648e162087 Mon Sep 17 00:00:00 2001 From: Postmodern Date: Wed, 29 Jun 2011 13:40:59 -0700 Subject: [PATCH 101/707] Replace usage of the term "spermy" with "approximate". * The "spermy" or "twiddle wakka" operator (~>) is similar to the greater-equal-then (>=) version operator, except that it matches families of versions. This version operator also uses a Tilde character, which is commonly used to denote approximate values (See definition 2.b http://www.merriam-webster.com/dictionary/tilde). --- test/rubygems/test_gem_version.rb | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/test/rubygems/test_gem_version.rb b/test/rubygems/test_gem_version.rb index 701c88ff..723b274e 100644 --- a/test/rubygems/test_gem_version.rb +++ b/test/rubygems/test_gem_version.rb @@ -106,13 +106,13 @@ def test_spaceship assert_nil v("1.0") <=> "whatever" end - def test_spermy_recommendation - assert_spermy_equal "~> 1.0", "1" - assert_spermy_equal "~> 1.0", "1.0" - assert_spermy_equal "~> 1.2", "1.2" - assert_spermy_equal "~> 1.2", "1.2.0" - assert_spermy_equal "~> 1.2", "1.2.3" - assert_spermy_equal "~> 1.2", "1.2.3.a.4" + def test_approximate_recommendation + assert_approximate_equal "~> 1.0", "1" + assert_approximate_equal "~> 1.0", "1.0" + assert_approximate_equal "~> 1.2", "1.2" + assert_approximate_equal "~> 1.2", "1.2.0" + assert_approximate_equal "~> 1.2", "1.2.3" + assert_approximate_equal "~> 1.2", "1.2.3.a.4" end def test_to_s @@ -125,10 +125,10 @@ def assert_prerelease version assert v(version).prerelease?, "#{version} is a prerelease" end - # Assert that +expected+ is the "spermy" recommendation for +version". + # Assert that +expected+ is the "approximate" recommendation for +version". - def assert_spermy_equal expected, version - assert_equal expected, v(version).spermy_recommendation + def assert_approximate_equal expected, version + assert_equal expected, v(version).approximate_recommendation end # Assert that bumping the +unbumped+ version yields the +expected+. From cc90501dc5ea758798d7b91aa3b4dd48048ce23b Mon Sep 17 00:00:00 2001 From: Eric Hodel Date: Sat, 23 Jul 2011 10:18:18 -0700 Subject: [PATCH 102/707] Don't set APPLE_GEM_HOME if it didn't exist --- test/rubygems/test_gem.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index a73dbe11..ca5b201c 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -720,7 +720,7 @@ def test_self_path def test_self_path_default util_path - if defined? APPLE_GEM_HOME + if defined?(APPLE_GEM_HOME) orig_APPLE_GEM_HOME = APPLE_GEM_HOME Object.send :remove_const, :APPLE_GEM_HOME end @@ -729,7 +729,7 @@ def test_self_path_default assert_equal [Gem.default_path, Gem.dir].flatten.uniq, Gem.path ensure - Object.const_set :APPLE_GEM_HOME, orig_APPLE_GEM_HOME + Object.const_set :APPLE_GEM_HOME, orig_APPLE_GEM_HOME if orig_APPLE_GEM_HOME end unless win_platform? From e8eed6dbe74a14da29d5476e233143cdfc6396e1 Mon Sep 17 00:00:00 2001 From: Eric Hodel Date: Tue, 26 Jul 2011 17:43:32 -0700 Subject: [PATCH 103/707] Ignore meaningless tests instead of skiping them. Patch by usa --- test/rubygems/test_gem.rb | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index ca5b201c..c33518a1 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1061,9 +1061,9 @@ def test_self_user_home end end - if Gem.win_platform? then + if Gem.win_platform? && '1.9' > RUBY_VERSION + # Ruby 1.9 properly handles ~ path expansion, so no need to run such tests. def test_self_user_home_userprofile - skip 'Ruby 1.9 properly handles ~ path expansion' unless '1.9' > RUBY_VERSION Gem.clear_paths @@ -1082,8 +1082,6 @@ def test_self_user_home_userprofile end def test_self_user_home_user_drive_and_path - skip 'Ruby 1.9 properly handles ~ path expansion' unless '1.9' > RUBY_VERSION - Gem.clear_paths # safe-keep env variables From 37bdc43942f6b827d63414c94e03df0d8f5e32d5 Mon Sep 17 00:00:00 2001 From: Eric Hodel Date: Tue, 26 Jul 2011 20:41:58 -0700 Subject: [PATCH 104/707] Fix 1.9.3 unused variable warnings --- test/rubygems/test_gem.rb | 6 ------ 1 file changed, 6 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index c33518a1..349da8f7 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1148,18 +1148,12 @@ def test_load_env_plugins end def test_latest_load_paths - stem = Gem.path.first - spec = quick_spec 'a', '4' do |s| s.require_paths = ["lib"] end install_gem spec - # @exec_path = File.join spec.full_gem_path, spec.bindir, 'exec' - # @abin_path = File.join spec.full_gem_path, spec.bindir, 'abin' - # FileUtils.mkdir_p File.join(stem, "gems", "test-3") - Gem::Deprecate.skip_during do expected = [File.join(@gemhome, "gems", "a-4", "lib")] assert_equal expected, Gem.latest_load_paths From 9f43a45558812bbd3e2a7bc8df350e6de32dd577 Mon Sep 17 00:00:00 2001 From: Eric Hodel Date: Thu, 4 Aug 2011 15:21:34 -0700 Subject: [PATCH 105/707] - Gem repository directories are no longer world-writable. Patch by Sakuro OZAWA. Ruby Bug #4930 --- test/rubygems/test_gem.rb | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 349da8f7..c0295bbb 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -606,6 +606,20 @@ def test_self_ensure_gem_directories assert File.directory? File.join(@gemhome, "cache") end + def test_self_ensure_gem_directories_safe_permissions + FileUtils.rm_r @gemhome + Gem.use_paths @gemhome + + old_umask = File.umask + File.umask 0 + Gem.ensure_gem_subdirectories @gemhome + + assert_equal 0, File::Stat.new(@gemhome).mode & 022 + assert_equal 0, File::Stat.new(File.join(@gemhome, "cache")).mode & 022 + ensure + File.umask old_umask + end unless win_platform? + def test_self_ensure_gem_directories_missing_parents gemdir = File.join @tempdir, 'a/b/c/gemdir' FileUtils.rm_rf File.join(@tempdir, 'a') rescue nil From ed8017f1f790243fc40ab51149d4279950cf57c7 Mon Sep 17 00:00:00 2001 From: Andre Arko Date: Sun, 2 Oct 2011 18:53:48 -0700 Subject: [PATCH 106/707] real-world spec for index search cache bug refs #1446 --- bundler/spec/realworld/edgecases_spec.rb | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 bundler/spec/realworld/edgecases_spec.rb diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb new file mode 100644 index 00000000..20cbebb0 --- /dev/null +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -0,0 +1,9 @@ +describe "real world edgecases", :realworld => true do + it "ignores extra gems with bad platforms" do + install_gemfile <<-G + source :rubygems + gem "linecache" + G + err.should eq("") + end +end \ No newline at end of file From b5b3772cdfeb6ce33e69412af9f2039f32bb3adb Mon Sep 17 00:00:00 2001 From: Andre Arko Date: Sun, 2 Oct 2011 19:25:36 -0700 Subject: [PATCH 107/707] hardcode linecache version --- bundler/spec/realworld/edgecases_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index 20cbebb0..9d369d38 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -2,7 +2,7 @@ it "ignores extra gems with bad platforms" do install_gemfile <<-G source :rubygems - gem "linecache" + gem "linecache", "0.46" G err.should eq("") end From 440e61fd1a5068f5f3685892b7454b04cc8e95b9 Mon Sep 17 00:00:00 2001 From: Terence Lee Date: Mon, 3 Oct 2011 20:00:35 -0500 Subject: [PATCH 108/707] this test only applies to 1.8 --- bundler/spec/realworld/edgecases_spec.rb | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index 9d369d38..04fe5a6e 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -1,9 +1,12 @@ describe "real world edgecases", :realworld => true do - it "ignores extra gems with bad platforms" do - install_gemfile <<-G - source :rubygems - gem "linecache", "0.46" - G - err.should eq("") + if RUBY_VERSION < "1.9" + # there is no rbx-relative-require gem that will install on 1.9 + it "ignores extra gems with bad platforms" do + install_gemfile <<-G + source :rubygems + gem "linecache", "0.46" + G + err.should eq("") + end end -end \ No newline at end of file +end From c9b978bc5624556a18c936ac94247a37c6fbcd89 Mon Sep 17 00:00:00 2001 From: Terence Lee Date: Tue, 11 Oct 2011 02:36:20 -0700 Subject: [PATCH 109/707] test covering issue #1202 --- bundler/spec/realworld/edgecases_spec.rb | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index 04fe5a6e..4cce91eb 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -9,4 +9,14 @@ err.should eq("") end end + + # https://github.com/carlhuda/bundler/issues/1202 + it "bundle cache works with rubygems 1.3.7 and pre gems" do + install_gemfile <<-G + source :rubygems + gem "rack", "1.3.0.beta2" + G + bundle :cache + out.should_not include("Removing outdated .gem files from vendor/cache") + end end From 99d2e24280a043993e9cf68510dec943282830a5 Mon Sep 17 00:00:00 2001 From: Andre Arko Date: Fri, 21 Oct 2011 09:51:39 -1000 Subject: [PATCH 110/707] add :ruby => "1.9" spec filter --- bundler/spec/realworld/edgecases_spec.rb | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index 4cce91eb..219cb331 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -1,13 +1,13 @@ +require 'spec_helper' + describe "real world edgecases", :realworld => true do - if RUBY_VERSION < "1.9" - # there is no rbx-relative-require gem that will install on 1.9 - it "ignores extra gems with bad platforms" do - install_gemfile <<-G - source :rubygems - gem "linecache", "0.46" - G - err.should eq("") - end + # there is no rbx-relative-require gem that will install on 1.9 + it "ignores extra gems with bad platforms", :ruby => "1.9" do + install_gemfile <<-G + source :rubygems + gem "linecache", "0.46" + G + err.should eq("") end # https://github.com/carlhuda/bundler/issues/1202 From eda664004b85c69ea6ccee28b63eca241c25343b Mon Sep 17 00:00:00 2001 From: Andre Arko Date: Fri, 21 Oct 2011 09:52:35 -1000 Subject: [PATCH 111/707] add verified realworld spec for #1486 --- bundler/spec/realworld/edgecases_spec.rb | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index 219cb331..a227e6b5 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -19,4 +19,19 @@ bundle :cache out.should_not include("Removing outdated .gem files from vendor/cache") end + + # https://github.com/carlhuda/bundler/issues/1486 + # this is a hash collision that only manifests on 1.8.7 + it "finds the correct child versions" do + install_gemfile <<-G + source :rubygems + + gem 'i18n', '~> 0.4' + gem 'activesupport', '~> 3.0' + gem 'activerecord', '~> 3.0' + gem 'builder', '~> 2.1.2' + G + out.should include("activemodel (3.0.5)") + end + end From f90b71f39cbb1e50bc0eb46eeeeec940f9c85a1b Mon Sep 17 00:00:00 2001 From: Andre Arko Date: Fri, 21 Oct 2011 10:27:41 -1000 Subject: [PATCH 112/707] that spec is actually 1.8-only. oops. --- bundler/spec/realworld/edgecases_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index a227e6b5..c53a4d57 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -2,7 +2,7 @@ describe "real world edgecases", :realworld => true do # there is no rbx-relative-require gem that will install on 1.9 - it "ignores extra gems with bad platforms", :ruby => "1.9" do + it "ignores extra gems with bad platforms", :ruby => "1.8" do install_gemfile <<-G source :rubygems gem "linecache", "0.46" From f5bc327cd94b5bc4cc99b92850c4d42566bcd9cd Mon Sep 17 00:00:00 2001 From: Alex Koppel Date: Fri, 18 Nov 2011 12:09:25 +0100 Subject: [PATCH 113/707] Raise a more specific error class for illformed requirements --- test/rubygems/test_gem_requirement.rb | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/test/rubygems/test_gem_requirement.rb b/test/rubygems/test_gem_requirement.rb index 3680d55f..e4be5aef 100644 --- a/test/rubygems/test_gem_requirement.rb +++ b/test/rubygems/test_gem_requirement.rb @@ -37,17 +37,19 @@ def test_parse end def test_parse_bad - e = assert_raises ArgumentError do + e = assert_raises Gem::Requirement::IllformedRequirementError do Gem::Requirement.parse nil end assert_equal 'Illformed requirement [nil]', e.message - e = assert_raises ArgumentError do + e = assert_raises Gem::Requirement::IllformedRequirementError do Gem::Requirement.parse "" end assert_equal 'Illformed requirement [""]', e.message + + assert_equal Gem::Requirement::IllformedRequirementError.superclass, ArgumentError end def test_prerelease_eh @@ -209,7 +211,7 @@ def test_satisfied_by_eh_good def test_illformed_requirements [ ">>> 1.3.5", "> blah" ].each do |rq| - assert_raises ArgumentError, "req [#{rq}] should fail" do + assert_raises Gem::Requirement::IllformedRequirementError, "req [#{rq}] should fail" do Gem::Requirement.new rq end end From 510917d308b73896018a5e13feadebd4ad92e846 Mon Sep 17 00:00:00 2001 From: Alex Koppel Date: Fri, 18 Nov 2011 13:16:14 +0100 Subject: [PATCH 114/707] Stripped trailing spaces. --- test/rubygems/test_gem_requirement.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/rubygems/test_gem_requirement.rb b/test/rubygems/test_gem_requirement.rb index e4be5aef..b5cf27c5 100644 --- a/test/rubygems/test_gem_requirement.rb +++ b/test/rubygems/test_gem_requirement.rb @@ -48,7 +48,7 @@ def test_parse_bad end assert_equal 'Illformed requirement [""]', e.message - + assert_equal Gem::Requirement::IllformedRequirementError.superclass, ArgumentError end From 3b48d35d247e8ff5dd36f3f6ebfb1f9c8ea40166 Mon Sep 17 00:00:00 2001 From: Terence Lee Date: Thu, 17 Nov 2011 23:25:07 -0800 Subject: [PATCH 115/707] failing test for #1500 --- bundler/spec/realworld/edgecases_spec.rb | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index c53a4d57..1bb05425 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -34,4 +34,17 @@ out.should include("activemodel (3.0.5)") end + # https://github.com/carlhuda/bundler/issues/1500 + it "does not fail install because of gem plugins" do + realworld_system_gems("open_gem --version 1.4.2", "rake --version 0.9.2") + gemfile <<-G + source :rubygems + + gem 'rack', '1.0.0' + G + + bundle "install --path vendor/bundle", :expect_err => true + err.should_not include("Could not find rake") + err.should be_empty + end end From d9d89726b1c6b9ac5a3605e1f0fb022c09f66fb7 Mon Sep 17 00:00:00 2001 From: Ryan Davis Date: Fri, 18 Nov 2011 15:51:20 -0800 Subject: [PATCH 116/707] renamed IllformedRequirementError to BadRequirementError --- test/rubygems/test_gem_requirement.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/rubygems/test_gem_requirement.rb b/test/rubygems/test_gem_requirement.rb index b5cf27c5..4f9e01d0 100644 --- a/test/rubygems/test_gem_requirement.rb +++ b/test/rubygems/test_gem_requirement.rb @@ -37,19 +37,19 @@ def test_parse end def test_parse_bad - e = assert_raises Gem::Requirement::IllformedRequirementError do + e = assert_raises Gem::Requirement::BadRequirementError do Gem::Requirement.parse nil end assert_equal 'Illformed requirement [nil]', e.message - e = assert_raises Gem::Requirement::IllformedRequirementError do + e = assert_raises Gem::Requirement::BadRequirementError do Gem::Requirement.parse "" end assert_equal 'Illformed requirement [""]', e.message - assert_equal Gem::Requirement::IllformedRequirementError.superclass, ArgumentError + assert_equal Gem::Requirement::BadRequirementError.superclass, ArgumentError end def test_prerelease_eh @@ -211,7 +211,7 @@ def test_satisfied_by_eh_good def test_illformed_requirements [ ">>> 1.3.5", "> blah" ].each do |rq| - assert_raises Gem::Requirement::IllformedRequirementError, "req [#{rq}] should fail" do + assert_raises Gem::Requirement::BadRequirementError, "req [#{rq}] should fail" do Gem::Requirement.new rq end end From cd3b5896b16f040cb0e78dedc7fce07f9443c948 Mon Sep 17 00:00:00 2001 From: Chris Cherry Date: Sun, 20 Nov 2011 13:23:07 -0800 Subject: [PATCH 117/707] Leave the group permissions of the umask alone. --- test/rubygems/test_gem.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index c0295bbb..e9f6f154 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -614,8 +614,8 @@ def test_self_ensure_gem_directories_safe_permissions File.umask 0 Gem.ensure_gem_subdirectories @gemhome - assert_equal 0, File::Stat.new(@gemhome).mode & 022 - assert_equal 0, File::Stat.new(File.join(@gemhome, "cache")).mode & 022 + assert_equal 0, File::Stat.new(@gemhome).mode & 002 + assert_equal 0, File::Stat.new(File.join(@gemhome, "cache")).mode & 002 ensure File.umask old_umask end unless win_platform? From 31f978b5fbd0c572ceba45495654f5f0bfe5564c Mon Sep 17 00:00:00 2001 From: Steve Klabnik Date: Sat, 17 Dec 2011 21:59:45 -0500 Subject: [PATCH 118/707] removing Gem::Version::Requirement. It said you wanted it removed in 2.0. Sooooooo... --- test/rubygems/test_gem_requirement.rb | 5 ----- 1 file changed, 5 deletions(-) diff --git a/test/rubygems/test_gem_requirement.rb b/test/rubygems/test_gem_requirement.rb index 4f9e01d0..8f76fcd8 100644 --- a/test/rubygems/test_gem_requirement.rb +++ b/test/rubygems/test_gem_requirement.rb @@ -21,11 +21,6 @@ def test_initialize assert_requirement_equal "= 2", v(2) end - def test_class_available_as_gem_version_requirement - assert_same Gem::Requirement, Gem::Version::Requirement, - "Gem::Version::Requirement is aliased for old YAML compatibility." - end - def test_parse assert_equal ['=', Gem::Version.new(1)], Gem::Requirement.parse(' 1') assert_equal ['=', Gem::Version.new(1)], Gem::Requirement.parse('= 1') From c33ca5c25ab058b6674846e80ff8976c26ad9e1e Mon Sep 17 00:00:00 2001 From: Evan Phoenix Date: Wed, 14 Dec 2011 16:18:32 -0800 Subject: [PATCH 119/707] + Check loaded_specs properly when trying to satisfy a dep This may or may not cause people's rubygems installations to start raising new Gem::LoadError's, but that is because the old behavior was causing invalid versions of gems to be running, thusly causing latent bugs in their programs. --- test/rubygems/test_gem.rb | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index e9f6f154..bcc6ec99 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -359,6 +359,29 @@ def test_self_activate_conflict end end + ## + # [A] depends on + # [C] = 1.0 depends on + # [B] = 2.0 + # [B] ~> 1.0 (satisfied by 1.0) + + def test_self_activate_checks_dependencies + a, _ = util_spec 'a', '1.0' + a.add_dependency 'c', '= 1.0' + a.add_dependency 'b', '~> 1.0' + + util_spec 'b', '1.0' + util_spec 'b', '2.0' + c, _ = util_spec 'c', '1.0', 'b' => '= 2.0' + + e = assert_raises Gem::LoadError do + assert_activate nil, a, c, "b" + end + + expected = "can't satisfy 'b (~> 1.0)', already activated 'b-2.0'" + assert_equal expected, e.message + end + ## # [A] depends on # [B] ~> 1.0 (satisfied by 1.0) From d655be85b20a5f2914cc8a168f5113435fae953b Mon Sep 17 00:00:00 2001 From: Evan Phoenix Date: Tue, 20 Dec 2011 08:41:45 -0800 Subject: [PATCH 120/707] Remove useless tests --- test/rubygems/test_gem.rb | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index bcc6ec99..3f0602f5 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -17,11 +17,6 @@ def setup super @additional = %w[a b].map { |d| File.join @tempdir, d } - @default_dir_re = if RUBY_VERSION > '1.9' then - %r|/.*?[Rr]uby.*?/[Gg]ems/[0-9.]+| - else - %r|/[Rr]uby/[Gg]ems/[0-9.]+| - end util_remove_interrupt_command end @@ -537,8 +532,7 @@ def test_self_bindir_default_dir RbConfig::CONFIG['bindir'] end - assert_equal bindir, Gem.bindir(default) - assert_equal bindir, Gem.bindir(Pathname.new(default)) + assert_equal Gem.default_bindir, Gem.bindir(default) end def test_self_clear_paths @@ -581,10 +575,6 @@ def test_self_datadir_nonexistent_package assert_nil Gem.datadir('xyzzy') end - def test_self_default_dir - assert_match @default_dir_re, Gem.default_dir - end - def test_self_default_exec_format orig_RUBY_INSTALL_NAME = Gem::ConfigMap[:ruby_install_name] Gem::ConfigMap[:ruby_install_name] = 'ruby' From cea572d22fdbd8dce7923ba0e00d872ac9dc6a61 Mon Sep 17 00:00:00 2001 From: Eric Hodel Date: Mon, 9 Jan 2012 14:47:48 -0800 Subject: [PATCH 121/707] + Refactored Gem::Format into Gem::Package. Gem::OldFormat has moved to Gem::Package::Old with an identical API to Gem::Package. --- test/rubygems/test_gem.rb | 5 ----- 1 file changed, 5 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 3f0602f5..7ad515c4 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -526,11 +526,6 @@ def test_self_bindir def test_self_bindir_default_dir default = Gem.default_dir - bindir = if defined?(RUBY_FRAMEWORK_VERSION) then - '/usr/bin' - else - RbConfig::CONFIG['bindir'] - end assert_equal Gem.default_bindir, Gem.bindir(default) end From ccb5e7b947292eace95ec4198f3910c53cf217e7 Mon Sep 17 00:00:00 2001 From: Mike Gunderloy Date: Sun, 15 Jan 2012 05:49:18 -0600 Subject: [PATCH 122/707] Remove reference to missing LICENSE file --- LICENSE.txt | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/LICENSE.txt b/LICENSE.txt index f2b95868..8a0a51de 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -39,11 +39,7 @@ conditions below: d. make other distribution arrangements with the author. 4. You may modify and include the part of the software into any other - software (possibly commercial). But some files in the distribution - are not written by the author, so that they are not under these terms. - - For the list of those files and their copying conditions, see the - file LEGAL. + software (possibly commercial). 5. The scripts and library files supplied as input to or produced as output from the software do not automatically fall under the From 3ff31d48afb1571ef1912254a787d2ecf9cf76f0 Mon Sep 17 00:00:00 2001 From: Eric Hodel Date: Mon, 16 Jan 2012 16:27:45 -0800 Subject: [PATCH 123/707] Remove rest of gem_openssl.rb. Fix typo in Gem::Security::Policy tests and default to secure initialization of a policy. Work around OpenSSL::X509::Name#== on Ruby 1.8 --- test/rubygems/test_gem.rb | 26 -------------------------- 1 file changed, 26 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 7ad515c4..9f36d326 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1,6 +1,5 @@ require 'rubygems/test_case' require 'rubygems' -require 'rubygems/gem_openssl' require 'rubygems/installer' require 'pathname' require 'tmpdir' @@ -674,19 +673,6 @@ def test_self_ensure_gem_directories_write_protected_parents end end - def test_ensure_ssl_available - orig_Gem_ssl_available = Gem.ssl_available? - - Gem.ssl_available = true - Gem.ensure_ssl_available - - Gem.ssl_available = false - e = assert_raises Gem::Exception do Gem.ensure_ssl_available end - assert_equal 'SSL is not installed on this system', e.message - ensure - Gem.ssl_available = orig_Gem_ssl_available - end - def test_self_find_files cwd = File.expand_path("test/rubygems", @@project_dir) $LOAD_PATH.unshift cwd @@ -1049,18 +1035,6 @@ def test_self_try_activate_missing_dep assert_match %r%Could not find b %, e.message end - def test_ssl_available_eh - orig_Gem_ssl_available = Gem.ssl_available? - - Gem.ssl_available = true - assert_equal true, Gem.ssl_available? - - Gem.ssl_available = false - assert_equal false, Gem.ssl_available? - ensure - Gem.ssl_available = orig_Gem_ssl_available - end - def test_self_use_paths util_ensure_gem_dirs From 412e40ad517ae03d92f9afe87efd431aa966d640 Mon Sep 17 00:00:00 2001 From: Evan Phoenix Date: Tue, 17 Jan 2012 16:30:51 -0800 Subject: [PATCH 124/707] Cleanup how the default requirement is detected. Fixes #155 We previously had a @none ivar that was supposed indicate if the requirement had no real requirements. This was an attempt at an optimization that didn't work out normally because it used a lazily assignment which caused it to be recalculated on pretty much every call. --- test/rubygems/test_gem_requirement.rb | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/test/rubygems/test_gem_requirement.rb b/test/rubygems/test_gem_requirement.rb index 8f76fcd8..8bbff7b7 100644 --- a/test/rubygems/test_gem_requirement.rb +++ b/test/rubygems/test_gem_requirement.rb @@ -21,6 +21,21 @@ def test_initialize assert_requirement_equal "= 2", v(2) end + def test_empty_requirements_is_none + r = Gem::Requirement.new + assert_equal true, r.none? + end + + def test_explicit_default_is_none + r = Gem::Requirement.new ">= 0" + assert_equal true, r.none? + end + + def test_basic_non_none + r = Gem::Requirement.new "= 1" + assert_equal false, r.none? + end + def test_parse assert_equal ['=', Gem::Version.new(1)], Gem::Requirement.parse(' 1') assert_equal ['=', Gem::Version.new(1)], Gem::Requirement.parse('= 1') From 3d3eb7384fd79a2f80e530a4e1aeecf2fbd7729d Mon Sep 17 00:00:00 2001 From: Evan Phoenix Date: Fri, 10 Feb 2012 08:55:13 -0800 Subject: [PATCH 125/707] Uniquify the spec list based on directory order priority --- test/rubygems/test_gem.rb | 80 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 9f36d326..ce0ba233 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1156,6 +1156,86 @@ def test_latest_load_paths end end + def test_gem_path_ordering + refute_equal Gem.dir, Gem.user_dir + + write_file File.join(@tempdir, 'lib', "g.rb") { |fp| fp.puts "" } + write_file File.join(@tempdir, 'lib', 'm.rb') { |fp| fp.puts "" } + + g = new_spec 'g', '1', nil, "lib/g.rb" + m = new_spec 'm', '1', nil, "lib/m.rb" + + install_gem g, :install_dir => Gem.dir + m0 = install_gem m, :install_dir => Gem.dir + m1 = install_gem m, :install_dir => Gem.user_dir + + assert_equal m0.gem_dir, File.join(Gem.dir, "gems", "m-1") + assert_equal m1.gem_dir, File.join(Gem.user_dir, "gems", "m-1") + + tests = [ + [:dir0, [ Gem.dir, Gem.user_dir], m0], + [:dir1, [ Gem.user_dir, Gem.dir], m1] + ] + + tests.each do |_name, _paths, expected| + Gem.paths = { 'GEM_HOME' => _paths.first, 'GEM_PATH' => _paths } + Gem::Specification.reset + Gem.searcher = nil + + assert_equal Gem::Dependency.new('m','1').to_specs, + Gem::Dependency.new('m','1').to_specs.sort + + assert_equal \ + [expected.gem_dir], + Gem::Dependency.new('m','1').to_specs.map(&:gem_dir).sort, + "Wrong specs for #{_name}" + + spec = Gem::Dependency.new('m','1').to_spec + + assert_equal \ + File.join(_paths.first, "gems", "m-1"), + spec.gem_dir, + "Wrong spec before require for #{_name}" + refute spec.activated?, "dependency already activated for #{_name}" + + gem "m" + + spec = Gem::Dependency.new('m','1').to_spec + assert spec.activated?, "dependency not activated for #{_name}" + + assert_equal \ + File.join(_paths.first, "gems", "m-1"), + spec.gem_dir, + "Wrong spec after require for #{_name}" + + spec.instance_variable_set :@activated, false + Gem.loaded_specs.delete(spec.name) + $:.delete(File.join(spec.gem_dir, "lib")) + end + end + + def test_gem_path_ordering_short + write_file File.join(@tempdir, 'lib', "g.rb") { |fp| fp.puts "" } + write_file File.join(@tempdir, 'lib', 'm.rb') { |fp| fp.puts "" } + + g = new_spec 'g', '1', nil, "lib/g.rb" + m = new_spec 'm', '1', nil, "lib/m.rb" + + install_gem g, :install_dir => Gem.dir + install_gem m, :install_dir => Gem.dir + install_gem m, :install_dir => Gem.user_dir + + Gem.paths = { + 'GEM_HOME' => Gem.dir, + 'GEM_PATH' => [ Gem.dir, Gem.user_dir] + } + + assert_equal \ + File.join(Gem.dir, "gems", "m-1"), + Gem::Dependency.new('m','1').to_spec.gem_dir, + "Wrong spec selected" + end + def with_plugin(path) test_plugin_path = File.expand_path("test/rubygems/plugin/#{path}", @@project_dir) From 0191b348fd561aab6fe1c51561f788a3e57298cb Mon Sep 17 00:00:00 2001 From: Evan Phoenix Date: Wed, 22 Feb 2012 16:41:14 -0800 Subject: [PATCH 126/707] Improve the error message when a depedency fails to resolve The old message included the names of all gems on the system. When the list is hundreds of gems, it's not very useful. This attempts to help the user out by indicating what other gems of the same name are available (the most common reason for an activation issue) --- test/rubygems/test_gem.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index ce0ba233..2b2cd9b2 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1032,7 +1032,7 @@ def test_self_try_activate_missing_dep Gem.try_activate 'a_file' end - assert_match %r%Could not find b %, e.message + assert_match %r%Could not find 'b' %, e.message end def test_self_use_paths From 15069bf5bb5932a0a58ec31247b196e5f8759954 Mon Sep 17 00:00:00 2001 From: Evan Phoenix Date: Tue, 28 Feb 2012 16:51:55 -0800 Subject: [PATCH 127/707] Prune more deprecated code --- test/rubygems/test_gem.rb | 6 ------ 1 file changed, 6 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 2b2cd9b2..69eb2ba4 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1009,12 +1009,6 @@ def test_self_pre_uninstall assert_equal 2, Gem.pre_uninstall_hooks.length end - def test_self_source_index - Gem::Deprecate.skip_during do - assert_kind_of Gem::SourceIndex, Gem.source_index - end - end - def test_self_sources assert_equal %w[http://gems.example.com/], Gem.sources end From fda1f6d621b96826f08509c0b7d60f027883c693 Mon Sep 17 00:00:00 2001 From: Evan Phoenix Date: Tue, 6 Mar 2012 11:59:25 -0800 Subject: [PATCH 128/707] Add Gem.finish_resolve Gem.finish_resolve computes the full transitive closure over the unresolved_deps in the system. This allows for much more complicated activation scenarios because all deps are considered at the same time. --- test/rubygems/test_gem.rb | 76 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 69eb2ba4..f4db0cc5 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -133,6 +133,82 @@ def test_self_activate_ambiguous_indirect end end + def test_self_finish_resolve + save_loaded_features do + a1 = new_spec "a", "1", "b" => "> 0" + b1 = new_spec "b", "1", "c" => ">= 1" + b2 = new_spec "b", "2", "c" => ">= 2" + c1 = new_spec "c", "1" + c2 = new_spec "c", "2" + + install_specs a1, b1, b2, c1, c2 + + a1.activate + + assert_equal %w(a-1), loaded_spec_names + assert_equal ["b (> 0)"], unresolved_names + + Gem.finish_resolve + + assert_equal %w(a-1 b-2 c-2), loaded_spec_names + assert_equal [], unresolved_names + end + end + + def test_self_activate_via_require_wtf + save_loaded_features do + a1 = new_spec "a", "1", "b" => "> 0", "d" => "> 0" # this + b1 = new_spec "b", "1", { "c" => ">= 1" }, "lib/b.rb" + b2 = new_spec "b", "2", { "c" => ">= 2" }, "lib/b.rb" # this + c1 = new_spec "c", "1" + c2 = new_spec "c", "2" # this + d1 = new_spec "d", "1", { "c" => "< 2" }, "lib/d.rb" + d2 = new_spec "d", "2", { "c" => "< 2" }, "lib/d.rb" # this + + install_specs a1, b1, b2, c1, c2, d1, d2 + + a1.activate + + assert_equal %w(a-1), loaded_spec_names + assert_equal ["b (> 0)", "d (> 0)"], unresolved_names + + require "b" + + e = assert_raises Gem::LoadError do + require "d" + end + + assert_equal "unable to find a version of 'd' to activate", e.message + + assert_equal %w(a-1 b-2 c-2), loaded_spec_names + assert_equal ["d (> 0)"], unresolved_names + end + end + + def test_self_finish_resolve_wtf + save_loaded_features do + a1 = new_spec "a", "1", "b" => "> 0", "d" => "> 0" # this + b1 = new_spec "b", "1", { "c" => ">= 1" }, "lib/b.rb" # this + b2 = new_spec "b", "2", { "c" => ">= 2" }, "lib/b.rb" + c1 = new_spec "c", "1" # this + c2 = new_spec "c", "2" + d1 = new_spec "d", "1", { "c" => "< 2" }, "lib/d.rb" + d2 = new_spec "d", "2", { "c" => "< 2" }, "lib/d.rb" # this + + install_specs a1, b1, b2, c1, c2, d1, d2 + + a1.activate + + assert_equal %w(a-1), loaded_spec_names + assert_equal ["b (> 0)", "d (> 0)"], unresolved_names + + Gem.finish_resolve + + assert_equal %w(a-1 b-1 c-1 d-2), loaded_spec_names + assert_equal [], unresolved_names + end + end + # TODO: move these to specification def test_self_activate_ambiguous_unrelated save_loaded_features do From c6ee506494fbd961001a10976d225d79165c6866 Mon Sep 17 00:00:00 2001 From: Evan Phoenix Date: Tue, 6 Mar 2012 14:05:07 -0800 Subject: [PATCH 129/707] Switch Gem.needs to yield a RequestSet --- test/rubygems/test_gem.rb | 40 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index f4db0cc5..9615bcac 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1127,6 +1127,46 @@ def test_self_user_home end end + def test_self_needs + util_clear_gems + a = util_spec "a", "1" + b = util_spec "b", "1", "c" => nil + c = util_spec "c", "2" + + install_specs a, b, c + + Gem.needs do |r| + r.gem "a" + r.gem "b", "= 1" + end + + activated = Gem::Specification.map { |x| x.full_name } + + assert_equal %w!a-1 b-1 c-2!, activated.sort + end + + def test_self_needs_picks_up_unresolved_deps + save_loaded_features do + util_clear_gems + a = util_spec "a", "1" + b = util_spec "b", "1", "c" => nil + c = util_spec "c", "2" + d = new_spec "d", "1", {'e' => '= 1'}, "lib/d.rb" + e = util_spec "e", "1" + + install_specs a, b, c, d, e + + Gem.needs do |r| + r.gem "a" + r.gem "b", "= 1" + + require 'd' + end + + assert_equal %w!a-1 b-1 c-2 d-1 e-1!, loaded_spec_names + end + end + if Gem.win_platform? && '1.9' > RUBY_VERSION # Ruby 1.9 properly handles ~ path expansion, so no need to run such tests. def test_self_user_home_userprofile From 9fa142ad83a6f4f52f6acda542d235f2da992e95 Mon Sep 17 00:00:00 2001 From: Evan Phoenix Date: Fri, 9 Mar 2012 16:53:54 -0800 Subject: [PATCH 130/707] Change gemfile => gemdep, add Gem.detect_gemdeps to autoload --- test/rubygems/test_gem.rb | 69 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 9615bcac..1d0eb175 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -15,6 +15,7 @@ class TestGem < Gem::TestCase def setup super + ENV.delete 'RUBYGEMS_GEMDEPS' @additional = %w[a b].map { |d| File.join @tempdir, d } util_remove_interrupt_command @@ -1346,6 +1347,74 @@ def test_gem_path_ordering_short "Wrong spec selected" end + def test_auto_activation_of_specific_gemdeps_file + util_clear_gems + + a = new_spec "a", "1", nil, "lib/a.rb" + b = new_spec "b", "1", nil, "lib/b.rb" + c = new_spec "c", "1", nil, "lib/c.rb" + + install_specs a, b, c + + path = File.join @tempdir, "gem.deps.rb" + + File.open path, "w" do |f| + f.puts "gem 'a'" + f.puts "gem 'b'" + f.puts "gem 'c'" + end + + ENV['RUBYGEMS_GEMDEPS'] = path + + Gem.detect_gemdeps + + assert_equal %w!a-1 b-1 c-1!, loaded_spec_names + end + + def test_auto_activation_of_detected_gemdeps_file + util_clear_gems + + a = new_spec "a", "1", nil, "lib/a.rb" + b = new_spec "b", "1", nil, "lib/b.rb" + c = new_spec "c", "1", nil, "lib/c.rb" + + install_specs a, b, c + + path = File.join @tempdir, "gem.deps.rb" + + File.open path, "w" do |f| + f.puts "gem 'a'" + f.puts "gem 'b'" + f.puts "gem 'c'" + end + + ENV['RUBYGEMS_GEMDEPS'] = "-" + + assert_equal [a,b,c], Gem.detect_gemdeps + end + + def notest_auto_activation_of_gemdeps + a = new_spec "a", "1", nil, "lib/a.rb" + b = new_spec "b", "1", nil, "lib/b.rb" + c = new_spec "c", "1", nil, "lib/c.rb" + + install_specs a, b, c + + path = File.join(@tempdir, "gd-tmp") + + Gem.ensure_gem_subdirectories path + + install_gem a, :install_dir => path + install_gem b, :install_dir => path + install_gem c, :install_dir => path + + ENV['RUBYGEMS_GEMDEPS'] = path + + util_clear_gems + + assert_equal [a,b,c], Gem.detect_gemdeps + end + def with_plugin(path) test_plugin_path = File.expand_path("test/rubygems/plugin/#{path}", @@project_dir) From 95087b8961be8be545c5c95eacdfb3948c2d41af Mon Sep 17 00:00:00 2001 From: Terence Lee Date: Tue, 13 Mar 2012 22:25:14 -0500 Subject: [PATCH 131/707] fix bundle cache edge case for #1202 --- bundler/spec/realworld/edgecases_spec.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index 1bb05425..6a2ab679 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -14,7 +14,8 @@ it "bundle cache works with rubygems 1.3.7 and pre gems" do install_gemfile <<-G source :rubygems - gem "rack", "1.3.0.beta2" + gem "rack", "1.3.0.beta2" + gem "will_paginate", "3.0.pre2" G bundle :cache out.should_not include("Removing outdated .gem files from vendor/cache") From 054606a5dbf62d5a5dadb019d83186b9a129d658 Mon Sep 17 00:00:00 2001 From: rohit Date: Sun, 18 Mar 2012 11:38:47 +0530 Subject: [PATCH 132/707] Add CI status image in README --- bundler/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bundler/README.md b/bundler/README.md index 8a5f1a6e..f2a61bf1 100644 --- a/bundler/README.md +++ b/bundler/README.md @@ -1,3 +1,5 @@ +[![Build Status](https://secure.travis-ci.org/carlhuda/bundler.png?branch=master)](http://travis-ci.org/carlhuda/bundler) + # Bundler: a gem to bundle gems Bundler is a tool that manages gem dependencies for your ruby application. It From c34e812782aba7524395727555df25090977f623 Mon Sep 17 00:00:00 2001 From: Terence Lee Date: Tue, 20 Mar 2012 17:21:41 -0700 Subject: [PATCH 133/707] Test case for bundle install not checking out git During the 1.1 pre/RC releases, there were duplicate GIT source sections generated in the `Gemfile.lock`. These would confuse bundler and the wrong source would get attached to the spec. This test case breaks if we don't fix this here: https://github.com/carlhuda/bundler/commit/e31a1c7b24d3dfbce7ed39b6a723dd20f7d08c95#L1R51 --- bundler/spec/realworld/edgecases_spec.rb | 126 +++++++++++++++++++++++ 1 file changed, 126 insertions(+) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index 6a2ab679..7ae37f57 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -48,4 +48,130 @@ err.should_not include("Could not find rake") err.should be_empty end + + it "checks out git repos when the lockfile is corrupted" do + gemfile <<-G + source :rubygems + + gem 'activerecord', :github => 'carlhuda/rails-bundler-test', :branch => 'master' + gem 'activesupport', :github => 'carlhuda/rails-bundler-test', :branch => 'master' + gem 'actionpack', :github => 'carlhuda/rails-bundler-test', :branch => 'master' + G + + lockfile <<-L + GIT + remote: git://github.com/carlhuda/rails-bundler-test.git + revision: 369e28a87419565f1940815219ea9200474589d4 + branch: master + specs: + actionpack (3.2.2) + activemodel (= 3.2.2) + activesupport (= 3.2.2) + builder (~> 3.0.0) + erubis (~> 2.7.0) + journey (~> 1.0.1) + rack (~> 1.4.0) + rack-cache (~> 1.2) + rack-test (~> 0.6.1) + sprockets (~> 2.1.2) + activemodel (3.2.2) + activesupport (= 3.2.2) + builder (~> 3.0.0) + activerecord (3.2.2) + activemodel (= 3.2.2) + activesupport (= 3.2.2) + arel (~> 3.0.2) + tzinfo (~> 0.3.29) + activesupport (3.2.2) + i18n (~> 0.6) + multi_json (~> 1.0) + + GIT + remote: git://github.com/carlhuda/rails-bundler-test.git + revision: 369e28a87419565f1940815219ea9200474589d4 + branch: master + specs: + actionpack (3.2.2) + activemodel (= 3.2.2) + activesupport (= 3.2.2) + builder (~> 3.0.0) + erubis (~> 2.7.0) + journey (~> 1.0.1) + rack (~> 1.4.0) + rack-cache (~> 1.2) + rack-test (~> 0.6.1) + sprockets (~> 2.1.2) + activemodel (3.2.2) + activesupport (= 3.2.2) + builder (~> 3.0.0) + activerecord (3.2.2) + activemodel (= 3.2.2) + activesupport (= 3.2.2) + arel (~> 3.0.2) + tzinfo (~> 0.3.29) + activesupport (3.2.2) + i18n (~> 0.6) + multi_json (~> 1.0) + + GIT + remote: git://github.com/carlhuda/rails-bundler-test.git + revision: 369e28a87419565f1940815219ea9200474589d4 + branch: master + specs: + actionpack (3.2.2) + activemodel (= 3.2.2) + activesupport (= 3.2.2) + builder (~> 3.0.0) + erubis (~> 2.7.0) + journey (~> 1.0.1) + rack (~> 1.4.0) + rack-cache (~> 1.2) + rack-test (~> 0.6.1) + sprockets (~> 2.1.2) + activemodel (3.2.2) + activesupport (= 3.2.2) + builder (~> 3.0.0) + activerecord (3.2.2) + activemodel (= 3.2.2) + activesupport (= 3.2.2) + arel (~> 3.0.2) + tzinfo (~> 0.3.29) + activesupport (3.2.2) + i18n (~> 0.6) + multi_json (~> 1.0) + + GEM + remote: http://rubygems.org/ + specs: + arel (3.0.2) + builder (3.0.0) + erubis (2.7.0) + hike (1.2.1) + i18n (0.6.0) + journey (1.0.3) + multi_json (1.1.0) + rack (1.4.1) + rack-cache (1.2) + rack (>= 0.4) + rack-test (0.6.1) + rack (>= 1.0) + sprockets (2.1.2) + hike (~> 1.2) + rack (~> 1.0) + tilt (~> 1.1, != 1.3.0) + tilt (1.3.3) + tzinfo (0.3.32) + + PLATFORMS + ruby + + DEPENDENCIES + actionpack! + activerecord! + activesupport! + L + + bundle :install, :exitstatus => true + exitstatus.should == 0 + end end From 2d88099fd7179c26876a0c47761c37b339e288c5 Mon Sep 17 00:00:00 2001 From: schneems Date: Fri, 24 Aug 2012 16:13:55 -0500 Subject: [PATCH 134/707] upcase bundler keep the case of "Bundler" consistent. --- bundler/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundler/README.md b/bundler/README.md index f2a61bf1..15e04663 100644 --- a/bundler/README.md +++ b/bundler/README.md @@ -18,7 +18,7 @@ For help with common problems, see [ISSUES](https://github.com/carlhuda/bundler/ ### Development -To see what has changed in recent versions of bundler, see the [CHANGELOG](https://github.com/carlhuda/bundler/blob/master/CHANGELOG.md). +To see what has changed in recent versions of Bundler, see the [CHANGELOG](https://github.com/carlhuda/bundler/blob/master/CHANGELOG.md). The `master` branch contains our current progress towards version 1.1. Because of that, please submit bugfix pull requests against the `1-0-stable` branch. From 6b50cc02674663f67be8ff1a2623b1080848170a Mon Sep 17 00:00:00 2001 From: Andre Arko Date: Mon, 27 Aug 2012 23:34:27 -0700 Subject: [PATCH 135/707] update version in readme --- bundler/README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/bundler/README.md b/bundler/README.md index 15e04663..0c03fd40 100644 --- a/bundler/README.md +++ b/bundler/README.md @@ -20,7 +20,9 @@ For help with common problems, see [ISSUES](https://github.com/carlhuda/bundler/ To see what has changed in recent versions of Bundler, see the [CHANGELOG](https://github.com/carlhuda/bundler/blob/master/CHANGELOG.md). -The `master` branch contains our current progress towards version 1.1. Because of that, please submit bugfix pull requests against the `1-0-stable` branch. +The `master` branch contains our current progress towards version 1.3. +Please submit pull requests with bugfixes to the stable branch for +version you would like to fix. naoeutnhaoeunth ### Upgrading from Bundler 0.8 to 0.9 and above From 1ebff42687c6e02e5578d538fd62a8c39824a666 Mon Sep 17 00:00:00 2001 From: Terence Lee Date: Wed, 29 Aug 2012 16:39:03 -0500 Subject: [PATCH 136/707] remove random typing. hone: what does "naoeutnhaoeunth" mean? Andre Arko: uhhhh Andre Arko: randomly typing on the keyobard? --- bundler/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundler/README.md b/bundler/README.md index 0c03fd40..e2eec35a 100644 --- a/bundler/README.md +++ b/bundler/README.md @@ -22,7 +22,7 @@ To see what has changed in recent versions of Bundler, see the [CHANGELOG](https The `master` branch contains our current progress towards version 1.3. Please submit pull requests with bugfixes to the stable branch for -version you would like to fix. naoeutnhaoeunth +version you would like to fix. ### Upgrading from Bundler 0.8 to 0.9 and above From c8fc7023a94089c564a8c878dd7c8045f49d7309 Mon Sep 17 00:00:00 2001 From: Kouhei Sutou Date: Sun, 16 Sep 2012 10:22:18 +0900 Subject: [PATCH 137/707] Remove deprecated Gem.latest_load_paths It is described that "will be removed on or after 2011-10". --- test/rubygems/test_gem.rb | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 1d0eb175..b890e140 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1254,19 +1254,6 @@ def test_load_env_plugins assert_equal :loaded, TEST_PLUGIN_EXCEPTION rescue nil end - def test_latest_load_paths - spec = quick_spec 'a', '4' do |s| - s.require_paths = ["lib"] - end - - install_gem spec - - Gem::Deprecate.skip_during do - expected = [File.join(@gemhome, "gems", "a-4", "lib")] - assert_equal expected, Gem.latest_load_paths - end - end - def test_gem_path_ordering refute_equal Gem.dir, Gem.user_dir From e7684d023d122019cc47d2506575b87ebd4c9caf Mon Sep 17 00:00:00 2001 From: Kouhei Sutou Date: Sun, 16 Sep 2012 10:50:05 +0900 Subject: [PATCH 138/707] Remove deprecated Gem.available? It is described that "will be removed on or after 2011-11". Tests for Gem.available? are rewriten by replacement method Gem::Specification.find_by_name. --- test/rubygems/test_gem.rb | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index b890e140..afc4bbaa 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -535,16 +535,6 @@ def test_self_activate_old_required assert_activate %w[d-1 e-1], e1, "d" end - def test_self_available? - util_make_gems - Gem::Deprecate.skip_during do - assert(Gem.available?("a")) - assert(Gem.available?("a", "1")) - assert(Gem.available?("a", ">1")) - assert(!Gem.available?("monkeys")) - end - end - def test_self_bin_path_no_exec_name e = assert_raises ArgumentError do Gem.bin_path 'a' From e5ae3047e70781492cef5fe52b5297623f70fa16 Mon Sep 17 00:00:00 2001 From: Kouhei Sutou Date: Sun, 16 Sep 2012 14:38:45 +0900 Subject: [PATCH 139/707] Remove deprecated Gem::Requirement#<=> and Comparable It is described that "will be removed on or after 2011-12". --- test/rubygems/test_gem_requirement.rb | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/test/rubygems/test_gem_requirement.rb b/test/rubygems/test_gem_requirement.rb index 8bbff7b7..1de0f41f 100644 --- a/test/rubygems/test_gem_requirement.rb +++ b/test/rubygems/test_gem_requirement.rb @@ -281,16 +281,6 @@ def test_satisfied_by_boxed refute_satisfied_by "2.0", "~> 1.4.4" end - def test_spaceship - Gem::Deprecate.skip_during do - assert_equal(-1, req("= 0") <=> req("= 1")) - assert_equal 0, req("= 0") <=> req("= 0") - assert_equal 1, req("= 1") <=> req("= 0") - - assert_nil req("= 1") <=> v("42") - end - end - def test_specific refute req('> 1') .specific? refute req('>= 1').specific? From 32f07906c4fe863f3edc15b0cb6b5a899c1a54f4 Mon Sep 17 00:00:00 2001 From: Evan Phoenix Date: Sat, 6 Oct 2012 14:39:25 -0700 Subject: [PATCH 140/707] Honor RUBYGEMS_GEMDEPS on startup --- test/rubygems/test_gem.rb | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index afc4bbaa..c210d2c4 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1370,26 +1370,36 @@ def test_auto_activation_of_detected_gemdeps_file assert_equal [a,b,c], Gem.detect_gemdeps end - def notest_auto_activation_of_gemdeps + LIB_PATH = File.expand_path "../../../lib".untaint, __FILE__.untaint + + def test_looks_for_gemdeps_files_automatically_on_start + util_clear_gems + a = new_spec "a", "1", nil, "lib/a.rb" b = new_spec "b", "1", nil, "lib/b.rb" c = new_spec "c", "1", nil, "lib/c.rb" install_specs a, b, c - path = File.join(@tempdir, "gd-tmp") + path = File.join @tempdir, "gem.deps.rb" - Gem.ensure_gem_subdirectories path + File.open path, "w" do |f| + f.puts "gem 'a'" + f.puts "gem 'b'" + f.puts "gem 'c'" + end + path = File.join(@tempdir, "gd-tmp") install_gem a, :install_dir => path install_gem b, :install_dir => path install_gem c, :install_dir => path - ENV['RUBYGEMS_GEMDEPS'] = path + ENV['GEM_PATH'] = path + ENV['RUBYGEMS_GEMDEPS'] = "-" - util_clear_gems + out = `#{Gem.ruby} -I #{LIB_PATH} -rubygems -e "p Gem.loaded_specs.values.map(&:full_name).sort"` - assert_equal [a,b,c], Gem.detect_gemdeps + assert_equal '["a-1", "b-1", "c-1"]', out.strip end def with_plugin(path) From ac77c19323a7210386e6b3703249ba196ac68775 Mon Sep 17 00:00:00 2001 From: Charles Oliver Nutter Date: Fri, 28 Sep 2012 17:35:42 -0500 Subject: [PATCH 141/707] Fix error on creating a Version object with a frozen string. Conflicts: lib/rubygems/version.rb --- test/rubygems/test_gem_version.rb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/rubygems/test_gem_version.rb b/test/rubygems/test_gem_version.rb index 723b274e..4a7c2234 100644 --- a/test/rubygems/test_gem_version.rb +++ b/test/rubygems/test_gem_version.rb @@ -33,6 +33,9 @@ def fake.version; "1.0" end assert_same fake, Gem::Version.create(fake) assert_nil Gem::Version.create(nil) assert_equal v("5.1"), Gem::Version.create("5.1") + + ver = '1.1'.freeze + assert_equal v('1.1'), Gem::Version.create(ver) end def test_eql_eh From a6bb901c4f484f447fe8aade7acd29538bb195e3 Mon Sep 17 00:00:00 2001 From: Evan Phoenix Date: Sat, 6 Oct 2012 15:27:36 -0700 Subject: [PATCH 142/707] Cleanup errors --- test/rubygems/test_gem.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index c210d2c4..2c767f10 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1397,7 +1397,7 @@ def test_looks_for_gemdeps_files_automatically_on_start ENV['GEM_PATH'] = path ENV['RUBYGEMS_GEMDEPS'] = "-" - out = `#{Gem.ruby} -I #{LIB_PATH} -rubygems -e "p Gem.loaded_specs.values.map(&:full_name).sort"` + out = `#{Gem.ruby.untaint} -I #{LIB_PATH.untaint} -rubygems -e "p Gem.loaded_specs.values.map(&:full_name).sort"` assert_equal '["a-1", "b-1", "c-1"]', out.strip end From 0b31a73d08d8c59ce051e1fb45e8afda0ecb8b5b Mon Sep 17 00:00:00 2001 From: Terence Lee Date: Tue, 9 Oct 2012 16:50:55 -1000 Subject: [PATCH 143/707] change to new expect syntax for rspec --- bundler/spec/realworld/edgecases_spec.rb | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index 7ae37f57..e444e3b9 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -7,7 +7,7 @@ source :rubygems gem "linecache", "0.46" G - err.should eq("") + expect(err).to eq("") end # https://github.com/carlhuda/bundler/issues/1202 @@ -18,7 +18,7 @@ gem "will_paginate", "3.0.pre2" G bundle :cache - out.should_not include("Removing outdated .gem files from vendor/cache") + expect(out).not_to include("Removing outdated .gem files from vendor/cache") end # https://github.com/carlhuda/bundler/issues/1486 @@ -32,7 +32,7 @@ gem 'activerecord', '~> 3.0' gem 'builder', '~> 2.1.2' G - out.should include("activemodel (3.0.5)") + expect(out).to include("activemodel (3.0.5)") end # https://github.com/carlhuda/bundler/issues/1500 @@ -45,8 +45,8 @@ G bundle "install --path vendor/bundle", :expect_err => true - err.should_not include("Could not find rake") - err.should be_empty + expect(err).not_to include("Could not find rake") + expect(err).to be_empty end it "checks out git repos when the lockfile is corrupted" do @@ -172,6 +172,6 @@ L bundle :install, :exitstatus => true - exitstatus.should == 0 + expect(exitstatus).to eq(0) end end From b7b68ea8f978c0a3bca1c488364e9b2578a84b07 Mon Sep 17 00:00:00 2001 From: Simon Hengel Date: Tue, 6 Nov 2012 16:22:23 +0100 Subject: [PATCH 144/707] Fix failing test case Explanation: "rack" 1.0.0 can not be installed because of a circular dependency ("rack" depends on "thin", and "thin" depends on "rack"). For "rack" 1.0.1 (and later), "thin" is only development dependency, hence we now use 1.0.1 for our test. --- bundler/spec/realworld/edgecases_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index e444e3b9..9ec244f4 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -41,7 +41,7 @@ gemfile <<-G source :rubygems - gem 'rack', '1.0.0' + gem 'rack', '1.0.1' G bundle "install --path vendor/bundle", :expect_err => true From f42f0d2596159cefd1767d7400aa785201558d4c Mon Sep 17 00:00:00 2001 From: Simon Hengel Date: Tue, 6 Nov 2012 16:22:23 +0100 Subject: [PATCH 145/707] Fix failing test case Explanation: "rack" 1.0.0 can not be installed because of a circular dependency ("rack" depends on "thin", and "thin" depends on "rack"). For "rack" 1.0.1 (and later), "thin" is only development dependency, hence we now use 1.0.1 for our test. --- bundler/spec/realworld/edgecases_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index 7ae37f57..9be8e5fd 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -41,7 +41,7 @@ gemfile <<-G source :rubygems - gem 'rack', '1.0.0' + gem 'rack', '1.0.1' G bundle "install --path vendor/bundle", :expect_err => true From ff5c659f3ae88f0841431ed8f20f9b13e8652188 Mon Sep 17 00:00:00 2001 From: Kouhei Sutou Date: Sun, 11 Nov 2012 19:04:07 +0900 Subject: [PATCH 146/707] Don't modify entries in $LOAD_PATH directly It is not allowed in ruby 2.0.0 since r37481. See also: https://bugs.ruby-lang.org/issues/7158 https://bugs.ruby-lang.org/projects/ruby-trunk/repository/revisions/37481 --- test/rubygems/test_gem.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 2c767f10..89427ca0 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -6,8 +6,8 @@ # TODO: push this up to test_case.rb once battle tested $SAFE=1 -$LOAD_PATH.each do |path| - path.untaint +$LOAD_PATH = $LOAD_PATH.map do |path| + path.dup.untaint end class TestGem < Gem::TestCase From 68175cce9913567d4ba0b4eba4fdd290d525e007 Mon Sep 17 00:00:00 2001 From: Kouhei Sutou Date: Sun, 11 Nov 2012 19:09:15 +0900 Subject: [PATCH 147/707] Don't modify $LOAD_PATH. Sorry... It is read-only variable. This fixes "$LOAD_PATH is a read-only variable (NameError)" error introduced by ff5c659f3ae88f0841431ed8f20f9b13e8652188. --- test/rubygems/test_gem.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 89427ca0..bbc18d42 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -6,7 +6,7 @@ # TODO: push this up to test_case.rb once battle tested $SAFE=1 -$LOAD_PATH = $LOAD_PATH.map do |path| +$LOAD_PATH.map! do |path| path.dup.untaint end From 3aaf3b0520e04c3ae83ba51ba46f81499e933b91 Mon Sep 17 00:00:00 2001 From: Eric Hodel Date: Thu, 29 Nov 2012 16:04:47 -0800 Subject: [PATCH 148/707] Removed trailing whitespace. From ruby r37983 --- test/rubygems/test_gem_version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/rubygems/test_gem_version.rb b/test/rubygems/test_gem_version.rb index 4a7c2234..da3b87db 100644 --- a/test/rubygems/test_gem_version.rb +++ b/test/rubygems/test_gem_version.rb @@ -33,7 +33,7 @@ def fake.version; "1.0" end assert_same fake, Gem::Version.create(fake) assert_nil Gem::Version.create(nil) assert_equal v("5.1"), Gem::Version.create("5.1") - + ver = '1.1'.freeze assert_equal v('1.1'), Gem::Version.create(ver) end From 64b96231fc815d9aca219e159861ebc5a1f84b2a Mon Sep 17 00:00:00 2001 From: Evan Phoenix Date: Fri, 30 Nov 2012 10:19:40 -0800 Subject: [PATCH 149/707] Add ability to load a gemdeps file from parent directories --- test/rubygems/test_gem.rb | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index bbc18d42..11027048 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1402,6 +1402,38 @@ def test_looks_for_gemdeps_files_automatically_on_start assert_equal '["a-1", "b-1", "c-1"]', out.strip end + def test_looks_for_gemdeps_files_automatically_on_start_in_parent_dir + util_clear_gems + + a = new_spec "a", "1", nil, "lib/a.rb" + b = new_spec "b", "1", nil, "lib/b.rb" + c = new_spec "c", "1", nil, "lib/c.rb" + + install_specs a, b, c + + path = File.join @tempdir, "gem.deps.rb" + + File.open path, "w" do |f| + f.puts "gem 'a'" + f.puts "gem 'b'" + f.puts "gem 'c'" + end + + path = File.join(@tempdir, "gd-tmp") + install_gem a, :install_dir => path + install_gem b, :install_dir => path + install_gem c, :install_dir => path + + ENV['GEM_PATH'] = path + ENV['RUBYGEMS_GEMDEPS'] = "-" + + out = `mkdir -p sub1; cd sub1; #{Gem.ruby.untaint} -I #{LIB_PATH.untaint} -rubygems -e "p Gem.loaded_specs.values.map(&:full_name).sort"` + + Dir.rmdir "sub1" + + assert_equal '["a-1", "b-1", "c-1"]', out.strip + end + def with_plugin(path) test_plugin_path = File.expand_path("test/rubygems/plugin/#{path}", @@project_dir) From 20298568af2c11b77384af56b9982327e5882e7c Mon Sep 17 00:00:00 2001 From: Evan Phoenix Date: Fri, 30 Nov 2012 11:12:37 -0800 Subject: [PATCH 150/707] Fix test --- test/rubygems/test_gem.rb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 11027048..20e411a7 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1427,7 +1427,10 @@ def test_looks_for_gemdeps_files_automatically_on_start_in_parent_dir ENV['GEM_PATH'] = path ENV['RUBYGEMS_GEMDEPS'] = "-" - out = `mkdir -p sub1; cd sub1; #{Gem.ruby.untaint} -I #{LIB_PATH.untaint} -rubygems -e "p Gem.loaded_specs.values.map(&:full_name).sort"` + Dir.mkdir "sub1" + out = Dir.chdir "sub1" do + `#{Gem.ruby.untaint} -I #{LIB_PATH.untaint} -rubygems -e "p Gem.loaded_specs.values.map(&:full_name).sort"` + end Dir.rmdir "sub1" From b4b096f7bc8ed375f061f7e30a7195e7d967c08d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Arko?= Date: Thu, 6 Dec 2012 23:52:47 -0800 Subject: [PATCH 151/707] reword readme MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit   - remove upgrading from 0.8 and 0.9   - reword intro paragraph   - move build badge to the right of the title --- bundler/README.md | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/bundler/README.md b/bundler/README.md index e2eec35a..a232231d 100644 --- a/bundler/README.md +++ b/bundler/README.md @@ -1,16 +1,18 @@ -[![Build Status](https://secure.travis-ci.org/carlhuda/bundler.png?branch=master)](http://travis-ci.org/carlhuda/bundler) +# Bundler: a gem to bundle gems [![Build Status](https://secure.travis-ci.org/carlhuda/bundler.png?branch=master)](http://travis-ci.org/carlhuda/bundler) -# Bundler: a gem to bundle gems - -Bundler is a tool that manages gem dependencies for your ruby application. It -takes a gem manifest file and is able to fetch, download, and install the gems -and all child dependencies specified in this manifest. It can manage any update -to the gem manifest file and update the bundle's gems accordingly. It also lets -you run any ruby code in context of the bundle's gem environment. +Bundler manages the gems that a ruby application depends on. Given a list of gems, it can automatically download and install those gems, as well as any other gems needed by the gems that are listed. Before installing gems, it checks the versions of every gem to make sure that they are compatible, and can all be loaded at the same time. After the gems have been installed, Bundler can help you update some or all of them when new versions become available. Finally, it records the exact versions that have been installed, so that others can install the exact same gems. ### Installation and usage -See [gembundler.com](http://gembundler.com) for up-to-date installation and usage instructions. +See [gembundler.com](http://gembundler.com) for installation and usage instructions. tl;dr: + +``` +gem install bundler +bundle init +echo "gem 'rails'" >> Gemfile +bundle install +bundle exec rails new myapp +``` ### Troubleshooting @@ -20,13 +22,7 @@ For help with common problems, see [ISSUES](https://github.com/carlhuda/bundler/ To see what has changed in recent versions of Bundler, see the [CHANGELOG](https://github.com/carlhuda/bundler/blob/master/CHANGELOG.md). -The `master` branch contains our current progress towards version 1.3. -Please submit pull requests with bugfixes to the stable branch for -version you would like to fix. - -### Upgrading from Bundler 0.8 to 0.9 and above - -See [UPGRADING](https://github.com/carlhuda/bundler/blob/master/UPGRADING.md). +The `master` branch contains our current progress towards version 1.3. Versions 1.0 to 1.2 each have their own stable branches. Please submit bugfixes as pull requests to the stable branch for the version you would like to fix. ### Other questions From 66ce7190fbf4e46a4d87351b09a31cc8a3ffd4bc Mon Sep 17 00:00:00 2001 From: Andre Arko Date: Tue, 11 Dec 2012 16:48:59 -0800 Subject: [PATCH 152/707] Add contributing section to readme, reword --- bundler/README.md | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/bundler/README.md b/bundler/README.md index a232231d..ad1ec27d 100644 --- a/bundler/README.md +++ b/bundler/README.md @@ -1,10 +1,10 @@ # Bundler: a gem to bundle gems [![Build Status](https://secure.travis-ci.org/carlhuda/bundler.png?branch=master)](http://travis-ci.org/carlhuda/bundler) -Bundler manages the gems that a ruby application depends on. Given a list of gems, it can automatically download and install those gems, as well as any other gems needed by the gems that are listed. Before installing gems, it checks the versions of every gem to make sure that they are compatible, and can all be loaded at the same time. After the gems have been installed, Bundler can help you update some or all of them when new versions become available. Finally, it records the exact versions that have been installed, so that others can install the exact same gems. +Bundler keeps ruby applications running the same code on every machine. -### Installation and usage +It does this by managing the gems that the application depends on. Given a list of gems, it can automatically download and install those gems, as well as any other gems needed by the gems that are listed. Before installing gems, it checks the versions of every gem to make sure that they are compatible, and can all be loaded at the same time. After the gems have been installed, Bundler can help you update some or all of them when new versions become available. Finally, it records the exact versions that have been installed, so that others can install the exact same gems. -See [gembundler.com](http://gembundler.com) for installation and usage instructions. tl;dr: +### Installation and usage ``` gem install bundler @@ -14,10 +14,16 @@ bundle install bundle exec rails new myapp ``` +See [gembundler.com](http://gembundler.com) for the full documentation. + ### Troubleshooting For help with common problems, see [ISSUES](https://github.com/carlhuda/bundler/blob/master/ISSUES.md). +### Contributing + +If you'd like to contribute to Bundler, that's awesome, and we <3 you. There's a guide to contributing to Bundler (both code and general help) over in [CONTRIBUTE](https://github.com/carlhuda/bundler/blob/master/CONTRIBUTE.md) + ### Development To see what has changed in recent versions of Bundler, see the [CHANGELOG](https://github.com/carlhuda/bundler/blob/master/CHANGELOG.md). From 3c12b9c06207f5e03a5f251304be50cfb6adf2cc Mon Sep 17 00:00:00 2001 From: Eric Hodel Date: Sat, 22 Dec 2012 12:32:09 -0800 Subject: [PATCH 153/707] Fixed Gem::latest_spec_for Gem::latest_spec_for was checked in without tests or documentation so it was not updated for the API changes. This caused the push command to fail. Fixes #418 --- test/rubygems/test_gem.rb | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 20e411a7..4b84bf35 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -774,6 +774,19 @@ def test_self_find_files assert_equal cwd, $LOAD_PATH.shift end + def test_self_latest_spec_for + a1 = quick_spec 'a', 1 + a2 = quick_spec 'a', 2 + a3a = quick_spec 'a', '3.a' + + util_setup_fake_fetcher + util_setup_spec_fetcher a1, a2, a3a + + spec = Gem.latest_spec_for 'a' + + assert_equal a2, spec + end + def test_self_loaded_specs foo = quick_spec 'foo' install_gem foo From 501ddd8be4df7105c8b10c41618dfe442d2ea85d Mon Sep 17 00:00:00 2001 From: Eric Hodel Date: Sat, 22 Dec 2012 12:35:21 -0800 Subject: [PATCH 154/707] Added missing test for Gem.latest_version_for --- test/rubygems/test_gem.rb | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 4b84bf35..1cafd45f 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -787,6 +787,19 @@ def test_self_latest_spec_for assert_equal a2, spec end + def test_self_latest_version_for + a1 = quick_spec 'a', 1 + a2 = quick_spec 'a', 2 + a3a = quick_spec 'a', '3.a' + + util_setup_fake_fetcher + util_setup_spec_fetcher a1, a2, a3a + + version = Gem.latest_version_for 'a' + + assert_equal Gem::Version.new(2), version + end + def test_self_loaded_specs foo = quick_spec 'foo' install_gem foo From 48f9c4ff38b77b558e4764185917b6264e6b61d5 Mon Sep 17 00:00:00 2001 From: Eric Hodel Date: Sat, 22 Dec 2012 12:49:12 -0800 Subject: [PATCH 155/707] Added missing test for Gem.latest_rubygems_version Ordered latest_rubygems_version Restored overridden method in push command tests --- test/rubygems/test_gem.rb | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 1cafd45f..9efb0565 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -787,6 +787,19 @@ def test_self_latest_spec_for assert_equal a2, spec end + def test_self_latest_rubygems_version + r1 = quick_spec 'rubygems-update', '1.8.23' + r2 = quick_spec 'rubygems-update', '1.8.24' + r3 = quick_spec 'rubygems-update', '2.0.0.preview3' + + util_setup_fake_fetcher + util_setup_spec_fetcher r1, r2, r3 + + version = Gem.latest_rubygems_version + + assert_equal Gem::Version.new('1.8.24'), version + end + def test_self_latest_version_for a1 = quick_spec 'a', 1 a2 = quick_spec 'a', 2 From ddd08ceffa915f43914ec7a470ab58a51448957e Mon Sep 17 00:00:00 2001 From: Jeremy Evans Date: Tue, 15 Jan 2013 12:06:25 -0800 Subject: [PATCH 156/707] Make sure Gem.refresh keeps already loaded gems activated Previously, calling Gem.refresh made it so all specifications yielded by Gem::Specification.each had activated = false, even if the same specs were in Gem.loaded_specs with activated = true. For consistency, you can either clear Gem.loaded_specs when refreshing the specifications, or make sure the refreshed specifications reflect the already loaded gems. I think the latter behavior makes more sense. --- test/rubygems/test_gem.rb | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 9efb0565..8fbae7f6 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -959,6 +959,27 @@ def test_self_refresh assert_includes Gem::Specification.all_names, @a1.full_name end + def test_self_refresh_keeps_loaded_specs_activated + util_make_gems + + a1_spec = @a1.spec_file + moved_path = File.join @tempdir, File.basename(a1_spec) + + FileUtils.mv a1_spec, moved_path + + Gem.refresh + + s = Gem::Specification.first + s.activate + + Gem.refresh + + Gem::Specification.each{|spec| assert spec.activated? if spec == s} + + Gem.loaded_specs.delete(s) + Gem.refresh + end + def test_self_ruby_escaping_spaces_in_path orig_ruby = Gem.ruby orig_bindir = Gem::ConfigMap[:bindir] From c7b51f5ccb89cf6323b5979a8b8186107155ca35 Mon Sep 17 00:00:00 2001 From: Erik Michaels-Ober Date: Sat, 2 Feb 2013 08:34:43 -0800 Subject: [PATCH 157/707] Convert license to Markdown format --- bundler/LICENSE.md | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 bundler/LICENSE.md diff --git a/bundler/LICENSE.md b/bundler/LICENSE.md new file mode 100644 index 00000000..4d62f8af --- /dev/null +++ b/bundler/LICENSE.md @@ -0,0 +1,23 @@ +Portions copyright (c) 2010 Andre Arko +Portions copyright (c) 2009 Engine Yard + +MIT License + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file From d264ab3c89f7f98638413d94920089e24a81d1f5 Mon Sep 17 00:00:00 2001 From: Erik Michaels-Ober Date: Sat, 2 Feb 2013 08:42:23 -0800 Subject: [PATCH 158/707] Cleanup trailing whitespace --- bundler/LICENSE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundler/LICENSE.md b/bundler/LICENSE.md index 4d62f8af..5e89f93c 100644 --- a/bundler/LICENSE.md +++ b/bundler/LICENSE.md @@ -20,4 +20,4 @@ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. From 4554b417ad206f2ae1dd61a5685118ca203745a9 Mon Sep 17 00:00:00 2001 From: Eric Hodel Date: Mon, 4 Feb 2013 16:37:11 -0800 Subject: [PATCH 159/707] Only detect gemdep files, not directories, etc. If you had a directory that matched a gemdep file name such as Isolate RubyGems would try to load it. This would cause an exception when trying to read the directory. Now only file entries are examined. --- test/rubygems/test_gem.rb | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 8fbae7f6..b98c3320 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -667,6 +667,25 @@ def test_self_default_sources assert_equal %w[http://rubygems.org/], Gem.default_sources end + def test_self_detect_gemdeps + rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], '-' + + FileUtils.mkdir_p 'detect/a/b' + FileUtils.mkdir_p 'detect/a/Isolate' + + FileUtils.touch 'detect/Isolate' + + begin + Dir.chdir 'detect/a/b' + + assert_empty Gem.detect_gemdeps + ensure + Dir.chdir @tempdir + end + ensure + ENV['RUBYGEMS_GEMDEPS'] = rubygems_gemdeps + end + def test_self_dir assert_equal @gemhome, Gem.dir end From b24d7823d1bc085622ab362a2315a37a9081d667 Mon Sep 17 00:00:00 2001 From: Eric Hodel Date: Mon, 4 Feb 2013 17:53:26 -0800 Subject: [PATCH 160/707] Gem.ruby is frozen, so untaint it for $SAFE --- test/rubygems/test_gem.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index b98c3320..fdeef699 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1476,7 +1476,7 @@ def test_looks_for_gemdeps_files_automatically_on_start ENV['GEM_PATH'] = path ENV['RUBYGEMS_GEMDEPS'] = "-" - out = `#{Gem.ruby.untaint} -I #{LIB_PATH.untaint} -rubygems -e "p Gem.loaded_specs.values.map(&:full_name).sort"` + out = `#{Gem.ruby.dup.untaint} -I #{LIB_PATH.untaint} -rubygems -e "p Gem.loaded_specs.values.map(&:full_name).sort"` assert_equal '["a-1", "b-1", "c-1"]', out.strip end @@ -1508,7 +1508,7 @@ def test_looks_for_gemdeps_files_automatically_on_start_in_parent_dir Dir.mkdir "sub1" out = Dir.chdir "sub1" do - `#{Gem.ruby.untaint} -I #{LIB_PATH.untaint} -rubygems -e "p Gem.loaded_specs.values.map(&:full_name).sort"` + `#{Gem.ruby.dup.untaint} -I #{LIB_PATH.untaint} -rubygems -e "p Gem.loaded_specs.values.map(&:full_name).sort"` end Dir.rmdir "sub1" From 1aba621a460435cc22a78b2e9b926f40b4b9d6f5 Mon Sep 17 00:00:00 2001 From: Eric Hodel Date: Tue, 12 Feb 2013 13:03:12 -0800 Subject: [PATCH 161/707] Return BINARY strings for Gem.gzip and gunzip Returning UTF-8 strings is incorrect as the tar library does not use the byte size methods (which do not exist on ruby 1.8). Fixes #450 --- test/rubygems/test_gem.rb | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index fdeef699..bf77009c 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1,3 +1,4 @@ +# coding: US-ASCII require 'rubygems/test_case' require 'rubygems' require 'rubygems/installer' @@ -1237,6 +1238,33 @@ def test_self_needs_picks_up_unresolved_deps end end + def test_self_gunzip + input = "\x1F\x8B\b\0\xED\xA3\x1AQ\0\x03\xCBH" + + "\xCD\xC9\xC9\a\0\x86\xA6\x106\x05\0\0\0" + + output = Gem.gunzip input + + assert_equal 'hello', output + + return unless Object.const_defined? :Encoding + + assert_equal Encoding::BINARY, output.encoding + end + + def test_self_gzip + input = 'hello' + + output = Gem.gzip input + + zipped = StringIO.new output + + assert_equal 'hello', Zlib::GzipReader.new(zipped).read + + return unless Object.const_defined? :Encoding + + assert_equal Encoding::BINARY, output.encoding + end + if Gem.win_platform? && '1.9' > RUBY_VERSION # Ruby 1.9 properly handles ~ path expansion, so no need to run such tests. def test_self_user_home_userprofile From ba6b29d771993e22512340fbac75efd13ed9ea91 Mon Sep 17 00:00:00 2001 From: Matthew Rudy Jacobs Date: Wed, 13 Feb 2013 13:51:25 +0000 Subject: [PATCH 162/707] use https://rubygems.org everywhere if https is the best way to access rubygems.org then it should be default everywhere including in examples on the man page --- bundler/spec/realworld/edgecases_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index 9ec244f4..3083ff09 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -141,7 +141,7 @@ multi_json (~> 1.0) GEM - remote: http://rubygems.org/ + remote: https://rubygems.org/ specs: arel (3.0.2) builder (3.0.0) From c1dec79619af415a9965e13cc656f0cd18411243 Mon Sep 17 00:00:00 2001 From: Andre Arko Date: Wed, 13 Feb 2013 15:55:18 -0800 Subject: [PATCH 163/707] limit 1.8 tests to 1.8 --- bundler/spec/realworld/edgecases_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index 9be8e5fd..d8a606e1 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -11,7 +11,7 @@ end # https://github.com/carlhuda/bundler/issues/1202 - it "bundle cache works with rubygems 1.3.7 and pre gems" do + it "bundle cache works with rubygems 1.3.7 and pre gems", :ruby => "1.8" do install_gemfile <<-G source :rubygems gem "rack", "1.3.0.beta2" @@ -23,7 +23,7 @@ # https://github.com/carlhuda/bundler/issues/1486 # this is a hash collision that only manifests on 1.8.7 - it "finds the correct child versions" do + it "finds the correct child versions", :ruby => "1.8" do install_gemfile <<-G source :rubygems From e4f04073715678130e1e1ea2b2d440e378009ac9 Mon Sep 17 00:00:00 2001 From: Andre Arko Date: Wed, 13 Feb 2013 15:55:18 -0800 Subject: [PATCH 164/707] limit 1.8 tests to 1.8 --- bundler/spec/realworld/edgecases_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index 3083ff09..57c2252c 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -11,7 +11,7 @@ end # https://github.com/carlhuda/bundler/issues/1202 - it "bundle cache works with rubygems 1.3.7 and pre gems" do + it "bundle cache works with rubygems 1.3.7 and pre gems", :ruby => "1.8" do install_gemfile <<-G source :rubygems gem "rack", "1.3.0.beta2" @@ -23,7 +23,7 @@ # https://github.com/carlhuda/bundler/issues/1486 # this is a hash collision that only manifests on 1.8.7 - it "finds the correct child versions" do + it "finds the correct child versions", :ruby => "1.8" do install_gemfile <<-G source :rubygems From b5f761073ebc7ce86299b698b6019e6722aeb626 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20Ondruch?= Date: Thu, 14 Feb 2013 13:35:20 +0100 Subject: [PATCH 165/707] Do not add last slash to Gem.user_dir if ruby_version string is empty. --- test/rubygems/test_gem.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index bf77009c..9ee78f77 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1186,8 +1186,10 @@ def test_self_use_paths end def test_self_user_dir - assert_equal File.join(@userhome, '.gem', Gem.ruby_engine, - Gem::ConfigMap[:ruby_version]), Gem.user_dir + parts = [@userhome, '.gem', Gem.ruby_engine] + parts << Gem::ConfigMap[:ruby_version] unless Gem::ConfigMap[:ruby_version].empty? + + assert_equal File.join(parts), Gem.user_dir end def test_self_user_home From be346591716ce9fe4435f5b35b61e2e0444b6948 Mon Sep 17 00:00:00 2001 From: Eric Hodel Date: Wed, 27 Feb 2013 15:47:48 -0800 Subject: [PATCH 166/707] Prefer HTTPS sources over HTTP sources While RubyGems does not appear to contain any exploitable code similar to that in the Rails + YAML exploit, using HTTPS over HTTP reduces the chance of an MITM attack when installing gems. https://rubygems.org is now the default source. When adding a http://rubygems.org via `gem sources`, RubyGems now asks for confirmation as https://rubygems.org is preferred. Gem::DependencyResolver::APISet now uses https://rubygems.org and is tested. Credit to Alex Gaynor for pointing out the use of HTTP in Gem::DependencyResolver::APISet. RubyGems now attempts to transparently upgrade HTTP sources to HTTPS. --- test/rubygems/test_gem.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index bf77009c..9be77e13 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -665,7 +665,7 @@ def test_self_default_exec_format_jruby end def test_self_default_sources - assert_equal %w[http://rubygems.org/], Gem.default_sources + assert_equal %w[https://rubygems.org/], Gem.default_sources end def test_self_detect_gemdeps From 41e285b4e6344d778a65013469050c03446d3c21 Mon Sep 17 00:00:00 2001 From: Eric Hodel Date: Tue, 5 Mar 2013 14:57:16 -0800 Subject: [PATCH 167/707] Allow specification of gem subdir permisisons This allows people installing RubyGems to reuse the API but provide their own permissions instead of adjusting umask. Fixes ruby bug #7713 --- test/rubygems/test_gem.rb | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 9be77e13..b6c74659 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -700,6 +700,18 @@ def test_self_ensure_gem_directories assert File.directory? File.join(@gemhome, "cache") end + def test_self_ensure_gem_directories_permissions + FileUtils.rm_r @gemhome + Gem.use_paths @gemhome + + Gem.ensure_gem_subdirectories @gemhome, 0750 + + assert File.directory? File.join(@gemhome, "cache") + + assert_equal 0750, File::Stat.new(@gemhome).mode & 0777 + assert_equal 0750, File::Stat.new(File.join(@gemhome, "cache")).mode & 0777 + end unless win_platform? + def test_self_ensure_gem_directories_safe_permissions FileUtils.rm_r @gemhome Gem.use_paths @gemhome From a56bf318e437a337afdffbe4d00d1f8eda683fca Mon Sep 17 00:00:00 2001 From: Eric Hodel Date: Mon, 11 Mar 2013 11:03:24 -0700 Subject: [PATCH 168/707] Revert "Prefer HTTPS sources over HTTP sources" This reverts commit be346591716ce9fe4435f5b35b61e2e0444b6948. Fixes #506 --- test/rubygems/test_gem.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index b6c74659..a7e5bbd6 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -665,7 +665,7 @@ def test_self_default_exec_format_jruby end def test_self_default_sources - assert_equal %w[https://rubygems.org/], Gem.default_sources + assert_equal %w[http://rubygems.org/], Gem.default_sources end def test_self_detect_gemdeps From b6b2835a0d2617e7e69cc9172b96cad3f5d287ec Mon Sep 17 00:00:00 2001 From: Eric Hodel Date: Mon, 11 Mar 2013 14:15:11 -0700 Subject: [PATCH 169/707] Restored HTTPS as the default source This was reverted while removing automatic HTTPS upgrade. --- test/rubygems/test_gem.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index a7e5bbd6..b6c74659 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -665,7 +665,7 @@ def test_self_default_exec_format_jruby end def test_self_default_sources - assert_equal %w[http://rubygems.org/], Gem.default_sources + assert_equal %w[https://rubygems.org/], Gem.default_sources end def test_self_detect_gemdeps From 3bd46fa26a78fec3c25f264126268972a52e17a3 Mon Sep 17 00:00:00 2001 From: Andre Arko Date: Thu, 14 Mar 2013 09:17:30 -0700 Subject: [PATCH 170/707] travis build badge for 1-3 on 1-3 --- bundler/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundler/README.md b/bundler/README.md index ad1ec27d..70e5271d 100644 --- a/bundler/README.md +++ b/bundler/README.md @@ -1,4 +1,4 @@ -# Bundler: a gem to bundle gems [![Build Status](https://secure.travis-ci.org/carlhuda/bundler.png?branch=master)](http://travis-ci.org/carlhuda/bundler) +# Bundler: a gem to bundle gems [![Build Status](https://secure.travis-ci.org/carlhuda/bundler.png?branch=1-3-stable)](http://travis-ci.org/carlhuda/bundler) Bundler keeps ruby applications running the same code on every machine. From 8a309346c8afde069be90edc4e51a4f1480e74d7 Mon Sep 17 00:00:00 2001 From: Gaston Ramos Date: Tue, 19 Mar 2013 11:12:35 -0300 Subject: [PATCH 171/707] move common installer setup stuff to a helper method --- test/rubygems/test_gem.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index b6c74659..60425eb1 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -15,6 +15,7 @@ class TestGem < Gem::TestCase def setup super + common_installer_setup ENV.delete 'RUBYGEMS_GEMDEPS' @additional = %w[a b].map { |d| File.join @tempdir, d } @@ -1632,4 +1633,3 @@ def util_cache_dir File.join Gem.dir, "cache" end end - From 0af2cda265d0b0b20aecbf2d2e87a7d782895ba6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20Ondruch?= Date: Thu, 14 Feb 2013 13:35:20 +0100 Subject: [PATCH 172/707] Do not add last slash to Gem.user_dir if ruby_version string is empty. --- test/rubygems/test_gem.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index bf77009c..9ee78f77 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1186,8 +1186,10 @@ def test_self_use_paths end def test_self_user_dir - assert_equal File.join(@userhome, '.gem', Gem.ruby_engine, - Gem::ConfigMap[:ruby_version]), Gem.user_dir + parts = [@userhome, '.gem', Gem.ruby_engine] + parts << Gem::ConfigMap[:ruby_version] unless Gem::ConfigMap[:ruby_version].empty? + + assert_equal File.join(parts), Gem.user_dir end def test_self_user_home From 24e84c6dc6c5f273089ccc6de6c63af82d508143 Mon Sep 17 00:00:00 2001 From: Eric Hodel Date: Wed, 27 Feb 2013 15:47:48 -0800 Subject: [PATCH 173/707] Prefer HTTPS sources over HTTP sources While RubyGems does not appear to contain any exploitable code similar to that in the Rails + YAML exploit, using HTTPS over HTTP reduces the chance of an MITM attack when installing gems. https://rubygems.org is now the default source. When adding a http://rubygems.org via `gem sources`, RubyGems now asks for confirmation as https://rubygems.org is preferred. Gem::DependencyResolver::APISet now uses https://rubygems.org and is tested. Credit to Alex Gaynor for pointing out the use of HTTP in Gem::DependencyResolver::APISet. RubyGems now attempts to transparently upgrade HTTP sources to HTTPS. --- test/rubygems/test_gem.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 9ee78f77..87bee96a 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -665,7 +665,7 @@ def test_self_default_exec_format_jruby end def test_self_default_sources - assert_equal %w[http://rubygems.org/], Gem.default_sources + assert_equal %w[https://rubygems.org/], Gem.default_sources end def test_self_detect_gemdeps From a5b3be41a6e1fef9b8173d73dc164c6e7f12ee3d Mon Sep 17 00:00:00 2001 From: Eric Hodel Date: Tue, 5 Mar 2013 14:57:16 -0800 Subject: [PATCH 174/707] Allow specification of gem subdir permisisons This allows people installing RubyGems to reuse the API but provide their own permissions instead of adjusting umask. Fixes ruby bug #7713 --- test/rubygems/test_gem.rb | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 87bee96a..fda83767 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -700,6 +700,18 @@ def test_self_ensure_gem_directories assert File.directory? File.join(@gemhome, "cache") end + def test_self_ensure_gem_directories_permissions + FileUtils.rm_r @gemhome + Gem.use_paths @gemhome + + Gem.ensure_gem_subdirectories @gemhome, 0750 + + assert File.directory? File.join(@gemhome, "cache") + + assert_equal 0750, File::Stat.new(@gemhome).mode & 0777 + assert_equal 0750, File::Stat.new(File.join(@gemhome, "cache")).mode & 0777 + end unless win_platform? + def test_self_ensure_gem_directories_safe_permissions FileUtils.rm_r @gemhome Gem.use_paths @gemhome From ece3d491ef5983f7b8513e6fae2a9ba799132d75 Mon Sep 17 00:00:00 2001 From: Eric Hodel Date: Mon, 11 Mar 2013 11:03:24 -0700 Subject: [PATCH 175/707] Revert "Prefer HTTPS sources over HTTP sources" This reverts commit be346591716ce9fe4435f5b35b61e2e0444b6948. Fixes #506 --- test/rubygems/test_gem.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index fda83767..8ebf35d2 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -665,7 +665,7 @@ def test_self_default_exec_format_jruby end def test_self_default_sources - assert_equal %w[https://rubygems.org/], Gem.default_sources + assert_equal %w[http://rubygems.org/], Gem.default_sources end def test_self_detect_gemdeps From 663da94e8c65966a88dbbb80dc04aa921f95c3ac Mon Sep 17 00:00:00 2001 From: Eric Hodel Date: Mon, 11 Mar 2013 14:15:11 -0700 Subject: [PATCH 176/707] Restored HTTPS as the default source This was reverted while removing automatic HTTPS upgrade. --- test/rubygems/test_gem.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 8ebf35d2..fda83767 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -665,7 +665,7 @@ def test_self_default_exec_format_jruby end def test_self_default_sources - assert_equal %w[http://rubygems.org/], Gem.default_sources + assert_equal %w[https://rubygems.org/], Gem.default_sources end def test_self_detect_gemdeps From 19a2fd380cbf3213eeb5336e473af0ac14354a37 Mon Sep 17 00:00:00 2001 From: Charles Oliver Nutter Date: Wed, 5 Jun 2013 07:15:24 -0500 Subject: [PATCH 177/707] Modify default gemspec registration to support unmodified specs. MRI 2.0 shipped with its own default spec generator that rewrites the gemspec file to contain a list of bare require names in spec.files. This required extra logic in rbinstall.rb and makes it impossible to simply copy a gemspec from a gem into the default directory to register that gem as a default gem. PR #566 adds --default functionality to `gem install` that copies the gem's unmodified gemspec to the default directory, but since unmodified gemspec contains a list of gem-relative filenames, it could not use the old default specification logic. This commit modifies default spec registration to support both formats. In the "old" style, specifications are registered with their raw filenames; we detect old style by checking the first file to see if it is prefixed with any spec.require_paths. In the "new" style, spec.require_paths are stripped off the spec's filenames before registration, and only files that start with a require_path are registered. Both the old format and the new format continue to work with this change, and we can migrate toward default specs being the unmodified originals rather than custom-built as in MRI 2.0. --- test/rubygems/test_gem.rb | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index fda83767..cf9614e9 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1557,6 +1557,34 @@ def test_looks_for_gemdeps_files_automatically_on_start_in_parent_dir assert_equal '["a-1", "b-1", "c-1"]', out.strip end + + def test_register_default_spec + Gem.clear_default_specs + + old_style = Gem::Specification.new do |spec| + spec.files = ["foo.rb", "bar.rb"] + end + + Gem.register_default_spec old_style + + assert_equal old_style, Gem.find_unresolved_default_spec("foo.rb") + assert_equal old_style, Gem.find_unresolved_default_spec("bar.rb") + assert_equal nil, Gem.find_unresolved_default_spec("baz.rb") + + Gem.clear_default_specs + + new_style = Gem::Specification.new do |spec| + spec.files = ["lib/foo.rb", "ext/bar.rb", "bin/exec", "README"] + spec.require_paths = ["lib", "ext"] + end + + Gem.register_default_spec new_style + + assert_equal new_style, Gem.find_unresolved_default_spec("foo.rb") + assert_equal new_style, Gem.find_unresolved_default_spec("bar.rb") + assert_equal nil, Gem.find_unresolved_default_spec("exec") + assert_equal nil, Gem.find_unresolved_default_spec("README") + end def with_plugin(path) test_plugin_path = File.expand_path("test/rubygems/plugin/#{path}", From 3bd66d9b122aec74a34367357f1a94800de154b9 Mon Sep 17 00:00:00 2001 From: Tim Moore Date: Tue, 11 Jun 2013 22:54:07 +1000 Subject: [PATCH 178/707] Update references to the repository URL. The repository has moved from the carlhuda account to the bundler organization. --- bundler/README.md | 8 ++++---- bundler/spec/realworld/edgecases_spec.rb | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/bundler/README.md b/bundler/README.md index 70e5271d..c5fc1fcc 100644 --- a/bundler/README.md +++ b/bundler/README.md @@ -1,4 +1,4 @@ -# Bundler: a gem to bundle gems [![Build Status](https://secure.travis-ci.org/carlhuda/bundler.png?branch=1-3-stable)](http://travis-ci.org/carlhuda/bundler) +# Bundler: a gem to bundle gems [![Build Status](https://secure.travis-ci.org/bundler/bundler.png?branch=1-3-stable)](http://travis-ci.org/bundler/bundler) Bundler keeps ruby applications running the same code on every machine. @@ -18,15 +18,15 @@ See [gembundler.com](http://gembundler.com) for the full documentation. ### Troubleshooting -For help with common problems, see [ISSUES](https://github.com/carlhuda/bundler/blob/master/ISSUES.md). +For help with common problems, see [ISSUES](https://github.com/bundler/bundler/blob/master/ISSUES.md). ### Contributing -If you'd like to contribute to Bundler, that's awesome, and we <3 you. There's a guide to contributing to Bundler (both code and general help) over in [CONTRIBUTE](https://github.com/carlhuda/bundler/blob/master/CONTRIBUTE.md) +If you'd like to contribute to Bundler, that's awesome, and we <3 you. There's a guide to contributing to Bundler (both code and general help) over in [CONTRIBUTE](https://github.com/bundler/bundler/blob/master/CONTRIBUTE.md) ### Development -To see what has changed in recent versions of Bundler, see the [CHANGELOG](https://github.com/carlhuda/bundler/blob/master/CHANGELOG.md). +To see what has changed in recent versions of Bundler, see the [CHANGELOG](https://github.com/bundler/bundler/blob/master/CHANGELOG.md). The `master` branch contains our current progress towards version 1.3. Versions 1.0 to 1.2 each have their own stable branches. Please submit bugfixes as pull requests to the stable branch for the version you would like to fix. diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index 57c2252c..fd5b607b 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -10,7 +10,7 @@ expect(err).to eq("") end - # https://github.com/carlhuda/bundler/issues/1202 + # https://github.com/bundler/bundler/issues/1202 it "bundle cache works with rubygems 1.3.7 and pre gems", :ruby => "1.8" do install_gemfile <<-G source :rubygems @@ -21,7 +21,7 @@ expect(out).not_to include("Removing outdated .gem files from vendor/cache") end - # https://github.com/carlhuda/bundler/issues/1486 + # https://github.com/bundler/bundler/issues/1486 # this is a hash collision that only manifests on 1.8.7 it "finds the correct child versions", :ruby => "1.8" do install_gemfile <<-G @@ -35,7 +35,7 @@ expect(out).to include("activemodel (3.0.5)") end - # https://github.com/carlhuda/bundler/issues/1500 + # https://github.com/bundler/bundler/issues/1500 it "does not fail install because of gem plugins" do realworld_system_gems("open_gem --version 1.4.2", "rake --version 0.9.2") gemfile <<-G From 4266a4d51a79bbe4d7e0f6d03c8e73d6319a4e80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Arko?= Date: Wed, 19 Jun 2013 12:17:53 -0600 Subject: [PATCH 179/707] trailing whitespace is how this works --- bundler/LICENSE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundler/LICENSE.md b/bundler/LICENSE.md index 5e89f93c..e356f59f 100644 --- a/bundler/LICENSE.md +++ b/bundler/LICENSE.md @@ -1,4 +1,4 @@ -Portions copyright (c) 2010 Andre Arko +Portions copyright (c) 2010 Andre Arko Portions copyright (c) 2009 Engine Yard MIT License From aca53e0ef20000fe0209368f7d79e963be90e939 Mon Sep 17 00:00:00 2001 From: Gaston Ramos Date: Tue, 19 Mar 2013 16:04:40 -0300 Subject: [PATCH 180/707] - move test_self_activate_via_require and test_self_activate_deep_unambiguous to test_gem_specification.rb file. - move loaded_spec_names and save_loaded_features to rubygems/test_case.rb --- test/rubygems/test_gem.rb | 41 --------------------------------------- 1 file changed, 41 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 8e837fe6..05ea4ba4 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -46,51 +46,10 @@ def test_self_activate assert_activate %w[foo-1], foo end - def loaded_spec_names - Gem.loaded_specs.values.map(&:full_name).sort - end - def unresolved_names Gem::Specification.unresolved_deps.values.map(&:to_s).sort end - # TODO: move these to specification - def test_self_activate_via_require - a1 = new_spec "a", "1", "b" => "= 1" - b1 = new_spec "b", "1", nil, "lib/b/c.rb" - b2 = new_spec "b", "2", nil, "lib/b/c.rb" - - install_specs a1, b1, b2 - - a1.activate - save_loaded_features do - require "b/c" - end - - assert_equal %w(a-1 b-1), loaded_spec_names - end - - # TODO: move these to specification - def test_self_activate_deep_unambiguous - a1 = new_spec "a", "1", "b" => "= 1" - b1 = new_spec "b", "1", "c" => "= 1" - b2 = new_spec "b", "2", "c" => "= 2" - c1 = new_spec "c", "1" - c2 = new_spec "c", "2" - - install_specs a1, b1, b2, c1, c2 - - a1.activate - assert_equal %w(a-1 b-1 c-1), loaded_spec_names - end - - def save_loaded_features - old_loaded_features = $LOADED_FEATURES.dup - yield - ensure - $LOADED_FEATURES.replace old_loaded_features - end - # TODO: move these to specification def test_self_activate_ambiguous_direct save_loaded_features do From 32bb2ce4a5814b6fdec04c8695165021fd536cd6 Mon Sep 17 00:00:00 2001 From: Gaston Ramos Date: Tue, 19 Mar 2013 19:39:38 -0300 Subject: [PATCH 181/707] - move more activate test cases to test_gem_specification.rb - move some helper methods to rubygems/test_case.rb --- test/rubygems/test_gem.rb | 131 -------------------------------------- 1 file changed, 131 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 05ea4ba4..2f84119b 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -23,33 +23,12 @@ def setup util_remove_interrupt_command end - def assert_activate expected, *specs - specs.each do |spec| - case spec - when String then - Gem::Specification.find_by_name(spec).activate - when Gem::Specification then - spec.activate - else - flunk spec.inspect - end - end - - loaded = Gem.loaded_specs.values.map(&:full_name) - - assert_equal expected.sort, loaded.sort if expected - end - def test_self_activate foo = util_spec 'foo', '1' assert_activate %w[foo-1], foo end - def unresolved_names - Gem::Specification.unresolved_deps.values.map(&:to_s).sort - end - # TODO: move these to specification def test_self_activate_ambiguous_direct save_loaded_features do @@ -281,116 +260,6 @@ def test_require_does_not_glob end end - # TODO: move these to specification - def test_self_activate_loaded - foo = util_spec 'foo', '1' - - assert foo.activate - refute foo.activate - end - - ## - # [A] depends on - # [B] >= 1.0 (satisfied by 2.0) - # [C] depends on nothing - - def test_self_activate_unrelated - a = util_spec 'a', '1.0', 'b' => '>= 1.0' - util_spec 'b', '1.0' - c = util_spec 'c', '1.0' - - assert_activate %w[b-1.0 c-1.0 a-1.0], a, c, "b" - end - - ## - # [A] depends on - # [B] >= 1.0 (satisfied by 2.0) - # [C] = 1.0 depends on - # [B] ~> 1.0 - # - # and should resolve using b-1.0 - # TODO: move these to specification - - def test_self_activate_over - a = util_spec 'a', '1.0', 'b' => '>= 1.0', 'c' => '= 1.0' - util_spec 'b', '1.0' - util_spec 'b', '1.1' - util_spec 'b', '2.0' - util_spec 'c', '1.0', 'b' => '~> 1.0' - - a.activate - - assert_equal %w[a-1.0 c-1.0], loaded_spec_names - assert_equal ["b (>= 1.0, ~> 1.0)"], unresolved_names - end - - ## - # [A] depends on - # [B] ~> 1.0 (satisfied by 1.1) - # [C] = 1.0 depends on - # [B] = 1.0 - # - # and should resolve using b-1.0 - # - # TODO: this is not under, but over... under would require depth - # first resolve through a dependency that is later pruned. - - def test_self_activate_under - a, _ = util_spec 'a', '1.0', 'b' => '~> 1.0', 'c' => '= 1.0' - util_spec 'b', '1.0' - util_spec 'b', '1.1' - c, _ = util_spec 'c', '1.0', 'b' => '= 1.0' - - assert_activate %w[b-1.0 c-1.0 a-1.0], a, c, "b" - end - - ## - # [A1] depends on - # [B] > 0 (satisfied by 2.0) - # [B1] depends on - # [C] > 0 (satisfied by 1.0) - # [B2] depends on nothing! - # [C1] depends on nothing - - def test_self_activate_dropped - a1, = util_spec 'a', '1', 'b' => nil - util_spec 'b', '1', 'c' => nil - util_spec 'b', '2' - util_spec 'c', '1' - - assert_activate %w[b-2 a-1], a1, "b" - end - - ## - # [A] depends on - # [B] >= 1.0 (satisfied by 1.1) depends on - # [Z] - # [C] >= 1.0 depends on - # [B] = 1.0 - # - # and should backtrack to resolve using b-1.0, pruning Z from the - # resolve. - - def test_self_activate_raggi_the_edgecase_generator - a, _ = util_spec 'a', '1.0', 'b' => '>= 1.0', 'c' => '>= 1.0' - util_spec 'b', '1.0' - util_spec 'b', '1.1', 'z' => '>= 1.0' - c, _ = util_spec 'c', '1.0', 'b' => '= 1.0' - - assert_activate %w[b-1.0 c-1.0 a-1.0], a, c, "b" - end - - def test_self_activate_conflict - util_spec 'b', '1.0' - util_spec 'b', '2.0' - - gem "b", "= 1.0" - - assert_raises Gem::LoadError do - gem "b", "= 2.0" - end - end - ## # [A] depends on # [C] = 1.0 depends on From dc4f9657415bfb0804ebdafed0e8f6559959af0b Mon Sep 17 00:00:00 2001 From: Gaston Ramos Date: Tue, 19 Mar 2013 19:56:01 -0300 Subject: [PATCH 182/707] move more activate test cases to test_gem_specification.rb --- test/rubygems/test_gem.rb | 51 --------------------------------------- 1 file changed, 51 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 2f84119b..5e1ca0ad 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -23,57 +23,6 @@ def setup util_remove_interrupt_command end - def test_self_activate - foo = util_spec 'foo', '1' - - assert_activate %w[foo-1], foo - end - - # TODO: move these to specification - def test_self_activate_ambiguous_direct - save_loaded_features do - a1 = new_spec "a", "1", "b" => "> 0" - b1 = new_spec("b", "1", { "c" => ">= 1" }, "lib/d.rb") - b2 = new_spec("b", "2", { "c" => ">= 2" }, "lib/d.rb") - c1 = new_spec "c", "1" - c2 = new_spec "c", "2" - - Gem::Specification.reset - install_specs a1, b1, b2, c1, c2 - - a1.activate - assert_equal %w(a-1), loaded_spec_names - assert_equal ["b (> 0)"], unresolved_names - - require "d" - - assert_equal %w(a-1 b-2 c-2), loaded_spec_names - assert_equal [], unresolved_names - end - end - - # TODO: move these to specification - def test_self_activate_ambiguous_indirect - save_loaded_features do - a1 = new_spec "a", "1", "b" => "> 0" - b1 = new_spec "b", "1", "c" => ">= 1" - b2 = new_spec "b", "2", "c" => ">= 2" - c1 = new_spec "c", "1", nil, "lib/d.rb" - c2 = new_spec "c", "2", nil, "lib/d.rb" - - install_specs a1, b1, b2, c1, c2 - - a1.activate - assert_equal %w(a-1), loaded_spec_names - assert_equal ["b (> 0)"], unresolved_names - - require "d" - - assert_equal %w(a-1 b-2 c-2), loaded_spec_names - assert_equal [], unresolved_names - end - end - def test_self_finish_resolve save_loaded_features do a1 = new_spec "a", "1", "b" => "> 0" From 07c50bd64947e613ee3deabaa1c2f2e7c1b50b94 Mon Sep 17 00:00:00 2001 From: Gaston Ramos Date: Tue, 19 Mar 2013 20:10:44 -0300 Subject: [PATCH 183/707] move more activate test cases to test_gem_specification.rb --- test/rubygems/test_gem.rb | 158 -------------------------------------- 1 file changed, 158 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 5e1ca0ad..7d52d384 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -45,36 +45,6 @@ def test_self_finish_resolve end end - def test_self_activate_via_require_wtf - save_loaded_features do - a1 = new_spec "a", "1", "b" => "> 0", "d" => "> 0" # this - b1 = new_spec "b", "1", { "c" => ">= 1" }, "lib/b.rb" - b2 = new_spec "b", "2", { "c" => ">= 2" }, "lib/b.rb" # this - c1 = new_spec "c", "1" - c2 = new_spec "c", "2" # this - d1 = new_spec "d", "1", { "c" => "< 2" }, "lib/d.rb" - d2 = new_spec "d", "2", { "c" => "< 2" }, "lib/d.rb" # this - - install_specs a1, b1, b2, c1, c2, d1, d2 - - a1.activate - - assert_equal %w(a-1), loaded_spec_names - assert_equal ["b (> 0)", "d (> 0)"], unresolved_names - - require "b" - - e = assert_raises Gem::LoadError do - require "d" - end - - assert_equal "unable to find a version of 'd' to activate", e.message - - assert_equal %w(a-1 b-2 c-2), loaded_spec_names - assert_equal ["d (> 0)"], unresolved_names - end - end - def test_self_finish_resolve_wtf save_loaded_features do a1 = new_spec "a", "1", "b" => "> 0", "d" => "> 0" # this @@ -99,29 +69,6 @@ def test_self_finish_resolve_wtf end end - # TODO: move these to specification - def test_self_activate_ambiguous_unrelated - save_loaded_features do - a1 = new_spec "a", "1", "b" => "> 0" - b1 = new_spec "b", "1", "c" => ">= 1" - b2 = new_spec "b", "2", "c" => ">= 2" - c1 = new_spec "c", "1" - c2 = new_spec "c", "2" - d1 = new_spec "d", "1", nil, "lib/d.rb" - - install_specs a1, b1, b2, c1, c2, d1 - - a1.activate - assert_equal %w(a-1), loaded_spec_names - assert_equal ["b (> 0)"], unresolved_names - - require "d" - - assert_equal %w(a-1 d-1), loaded_spec_names - assert_equal ["b (> 0)"], unresolved_names - end - end - # TODO: move these to specification def test_self_activate_ambiguous_indirect_conflict save_loaded_features do @@ -209,111 +156,6 @@ def test_require_does_not_glob end end - ## - # [A] depends on - # [C] = 1.0 depends on - # [B] = 2.0 - # [B] ~> 1.0 (satisfied by 1.0) - - def test_self_activate_checks_dependencies - a, _ = util_spec 'a', '1.0' - a.add_dependency 'c', '= 1.0' - a.add_dependency 'b', '~> 1.0' - - util_spec 'b', '1.0' - util_spec 'b', '2.0' - c, _ = util_spec 'c', '1.0', 'b' => '= 2.0' - - e = assert_raises Gem::LoadError do - assert_activate nil, a, c, "b" - end - - expected = "can't satisfy 'b (~> 1.0)', already activated 'b-2.0'" - assert_equal expected, e.message - end - - ## - # [A] depends on - # [B] ~> 1.0 (satisfied by 1.0) - # [C] = 1.0 depends on - # [B] = 2.0 - - def test_self_activate_divergent - a, _ = util_spec 'a', '1.0', 'b' => '~> 1.0', 'c' => '= 1.0' - util_spec 'b', '1.0' - util_spec 'b', '2.0' - c, _ = util_spec 'c', '1.0', 'b' => '= 2.0' - - e = assert_raises Gem::LoadError do - assert_activate nil, a, c, "b" - end - - assert_match(/Unable to activate c-1.0,/, e.message) - assert_match(/because b-1.0 conflicts with b .= 2.0/, e.message) - end - - ## - # DOC - - def test_self_activate_platform_alternate - @x1_m = util_spec 'x', '1' do |s| - s.platform = Gem::Platform.new %w[cpu my_platform 1] - end - - @x1_o = util_spec 'x', '1' do |s| - s.platform = Gem::Platform.new %w[cpu other_platform 1] - end - - @w1 = util_spec 'w', '1', 'x' => nil - - util_set_arch 'cpu-my_platform1' - - assert_activate %w[x-1-cpu-my_platform-1 w-1], @w1, @x1_m - end - - ## - # DOC - - def test_self_activate_platform_bump - @y1 = util_spec 'y', '1' - - @y1_1_p = util_spec 'y', '1.1' do |s| - s.platform = Gem::Platform.new %w[cpu my_platform 1] - end - - @z1 = util_spec 'z', '1', 'y' => nil - - assert_activate %w[y-1 z-1], @z1, @y1 - end - - ## - # [C] depends on - # [A] = 1.a - # [B] = 1.0 depends on - # [A] >= 0 (satisfied by 1.a) - - def test_self_activate_prerelease - @c1_pre = util_spec 'c', '1.a', "a" => "1.a", "b" => "1" - @a1_pre = util_spec 'a', '1.a' - @b1 = util_spec 'b', '1' do |s| - s.add_dependency 'a' - s.add_development_dependency 'aa' - end - - assert_activate %w[a-1.a b-1 c-1.a], @c1_pre, @a1_pre, @b1 - end - - ## - # DOC - - def test_self_activate_old_required - e1, = util_spec 'e', '1', 'd' => '= 1' - @d1 = util_spec 'd', '1' - @d2 = util_spec 'd', '2' - - assert_activate %w[d-1 e-1], e1, "d" - end - def test_self_bin_path_no_exec_name e = assert_raises ArgumentError do Gem.bin_path 'a' From 9fdd128dfa3cd1d72289f23ee58a3ac9b5e4e635 Mon Sep 17 00:00:00 2001 From: Gaston Ramos Date: Tue, 19 Mar 2013 20:23:55 -0300 Subject: [PATCH 184/707] move more activate test cases to test_gem_specification.rb --- test/rubygems/test_gem.rb | 42 --------------------------------------- 1 file changed, 42 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 7d52d384..0cb1ea47 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -92,48 +92,6 @@ def test_self_activate_ambiguous_indirect_conflict end end - # TODO: move these to specification - def test_require_already_activated - save_loaded_features do - a1 = new_spec "a", "1", nil, "lib/d.rb" - - install_specs a1 # , a2, b1, b2, c1, c2 - - a1.activate - assert_equal %w(a-1), loaded_spec_names - assert_equal [], unresolved_names - - assert require "d" - - assert_equal %w(a-1), loaded_spec_names - assert_equal [], unresolved_names - end - end - - # TODO: move these to specification - def test_require_already_activated_indirect_conflict - save_loaded_features do - a1 = new_spec "a", "1", "b" => "> 0" - a2 = new_spec "a", "2", "b" => "> 0" - b1 = new_spec "b", "1", "c" => ">= 1" - b2 = new_spec "b", "2", "c" => ">= 2" - c1 = new_spec "c", "1", nil, "lib/d.rb" - c2 = new_spec("c", "2", { "a" => "1" }, "lib/d.rb") # conflicts with a-2 - - install_specs a1, a2, b1, b2, c1, c2 - - a1.activate - c1.activate - assert_equal %w(a-1 c-1), loaded_spec_names - assert_equal ["b (> 0)"], unresolved_names - - assert require "d" - - assert_equal %w(a-1 c-1), loaded_spec_names - assert_equal ["b (> 0)"], unresolved_names - end - end - def test_require_missing save_loaded_features do assert_raises ::LoadError do From f1fd8a5ca928b80a9fd27d8260ab9dd749ec20b9 Mon Sep 17 00:00:00 2001 From: Gaston Ramos Date: Tue, 19 Mar 2013 20:45:25 -0300 Subject: [PATCH 185/707] move test_self_activate_ambiguous_indirect_conflict to test_gem_specification.rb --- test/rubygems/test_gem.rb | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 0cb1ea47..326758ec 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -69,29 +69,6 @@ def test_self_finish_resolve_wtf end end - # TODO: move these to specification - def test_self_activate_ambiguous_indirect_conflict - save_loaded_features do - a1 = new_spec "a", "1", "b" => "> 0" - a2 = new_spec "a", "2", "b" => "> 0" - b1 = new_spec "b", "1", "c" => ">= 1" - b2 = new_spec "b", "2", "c" => ">= 2" - c1 = new_spec "c", "1", nil, "lib/d.rb" - c2 = new_spec("c", "2", { "a" => "1" }, "lib/d.rb") # conflicts with a-2 - - install_specs a1, a2, b1, b2, c1, c2 - - a2.activate - assert_equal %w(a-2), loaded_spec_names - assert_equal ["b (> 0)"], unresolved_names - - require "d" - - assert_equal %w(a-2 b-1 c-1), loaded_spec_names - assert_equal [], unresolved_names - end - end - def test_require_missing save_loaded_features do assert_raises ::LoadError do From c444784bc52c587a29857b22d6f4a9ec03d158f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Arko?= Date: Wed, 19 Jun 2013 12:17:53 -0600 Subject: [PATCH 186/707] trailing whitespace is how this works --- bundler/LICENSE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundler/LICENSE.md b/bundler/LICENSE.md index 5e89f93c..e356f59f 100644 --- a/bundler/LICENSE.md +++ b/bundler/LICENSE.md @@ -1,4 +1,4 @@ -Portions copyright (c) 2010 Andre Arko +Portions copyright (c) 2010 Andre Arko Portions copyright (c) 2009 Engine Yard MIT License From d70d0c2a2453d48cde95ec48c2ceef5ad57751d6 Mon Sep 17 00:00:00 2001 From: Evan Phoenix Date: Wed, 11 Jan 2012 13:27:25 -0800 Subject: [PATCH 187/707] ! Add support for full semantic versioning versions See http://semver.org/spec/v2.0.0-rc.1 for details. --- test/rubygems/test_gem_version.rb | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/test/rubygems/test_gem_version.rb b/test/rubygems/test_gem_version.rb index da3b87db..d5deb46e 100644 --- a/test/rubygems/test_gem_version.rb +++ b/test/rubygems/test_gem_version.rb @@ -122,6 +122,19 @@ def test_to_s assert_equal "5.2.4", v("5.2.4").to_s end + def test_semver + assert_less_than "1.0.0-alpha", "1.0.0-alpha.1" + assert_less_than "1.0.0-alpha.1", "1.0.0-beta.2" + assert_less_than "1.0.0-beta.2", "1.0.0-beta.11" + assert_less_than "1.0.0-beta.11", "1.0.0-rc.1" + assert_less_than "1.0.0-rc.1", "1.0.0-rc.1+build.1" + assert_less_than "1.0.0-rc.1+build.1", "1.0.0" + assert_less_than "1.0.0", "1.0.0+0.3.7" + assert_less_than "1.0.0+0.3.7", "1.3.7+build" + assert_less_than "1.3.7+build", "1.3.7+build.2.b8f12d7" + assert_less_than "1.3.7+build.2.b8f12d7", "1.3.7+build.11.e0f985a" + end + # Asserts that +version+ is a prerelease. def assert_prerelease version @@ -161,6 +174,12 @@ def assert_version_eql first, second assert second.eql?(first), "#{second} is eql? #{first}" end + def assert_less_than left, right + l = v(left) + r = v(right) + assert l < r, "#{left} not less than #{right}" + end + # Refute the assumption that +version+ is a prerelease. def refute_prerelease version From 7884379714535c5075e5e3b76b30e5718c7c52fc Mon Sep 17 00:00:00 2001 From: Evan Phoenix Date: Wed, 11 Jan 2012 15:20:48 -0800 Subject: [PATCH 188/707] Remove support for build id, translate semver prereleases --- test/rubygems/test_gem_version.rb | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/test/rubygems/test_gem_version.rb b/test/rubygems/test_gem_version.rb index d5deb46e..2ba196e4 100644 --- a/test/rubygems/test_gem_version.rb +++ b/test/rubygems/test_gem_version.rb @@ -127,12 +127,8 @@ def test_semver assert_less_than "1.0.0-alpha.1", "1.0.0-beta.2" assert_less_than "1.0.0-beta.2", "1.0.0-beta.11" assert_less_than "1.0.0-beta.11", "1.0.0-rc.1" - assert_less_than "1.0.0-rc.1", "1.0.0-rc.1+build.1" - assert_less_than "1.0.0-rc.1+build.1", "1.0.0" - assert_less_than "1.0.0", "1.0.0+0.3.7" - assert_less_than "1.0.0+0.3.7", "1.3.7+build" - assert_less_than "1.3.7+build", "1.3.7+build.2.b8f12d7" - assert_less_than "1.3.7+build.2.b8f12d7", "1.3.7+build.11.e0f985a" + assert_less_than "1.0.0-rc1", "1.0.0" + assert_less_than "1.0.0-1", "1" end # Asserts that +version+ is a prerelease. From 463e0804bb3369dcbb1929d7b593d40a5cab94e8 Mon Sep 17 00:00:00 2001 From: Eric Hodel Date: Tue, 9 Jul 2013 19:04:41 -0700 Subject: [PATCH 189/707] Remove trailing whitespace via ruby r41874 --- test/rubygems/test_gem.rb | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index a4e5313c..6cce66ce 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1112,29 +1112,29 @@ def test_looks_for_gemdeps_files_automatically_on_start_in_parent_dir assert_equal '["a-1", "b-1", "c-1"]', out.strip end - + def test_register_default_spec Gem.clear_default_specs - + old_style = Gem::Specification.new do |spec| spec.files = ["foo.rb", "bar.rb"] end - + Gem.register_default_spec old_style - + assert_equal old_style, Gem.find_unresolved_default_spec("foo.rb") assert_equal old_style, Gem.find_unresolved_default_spec("bar.rb") assert_equal nil, Gem.find_unresolved_default_spec("baz.rb") - + Gem.clear_default_specs - + new_style = Gem::Specification.new do |spec| spec.files = ["lib/foo.rb", "ext/bar.rb", "bin/exec", "README"] spec.require_paths = ["lib", "ext"] end - + Gem.register_default_spec new_style - + assert_equal new_style, Gem.find_unresolved_default_spec("foo.rb") assert_equal new_style, Gem.find_unresolved_default_spec("bar.rb") assert_equal nil, Gem.find_unresolved_default_spec("exec") From 406e2aea20840ca3a23acb7752d5b6958f10766a Mon Sep 17 00:00:00 2001 From: Hemant Kumar Date: Tue, 16 Jul 2013 08:55:06 +0530 Subject: [PATCH 190/707] Add CodeClimate badge [ci skip] --- bundler/README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/bundler/README.md b/bundler/README.md index c5fc1fcc..a6427b90 100644 --- a/bundler/README.md +++ b/bundler/README.md @@ -1,5 +1,7 @@ -# Bundler: a gem to bundle gems [![Build Status](https://secure.travis-ci.org/bundler/bundler.png?branch=1-3-stable)](http://travis-ci.org/bundler/bundler) +[![Code Climate](https://codeclimate.com/github/bundler/bundler.png)](https://codeclimate.com/github/bundler/bundler) +[![Build Status](https://secure.travis-ci.org/bundler/bundler.png?branch=1-3-stable)](http://travis-ci.org/bundler/bundler) +# Bundler: a gem to bundle gems Bundler keeps ruby applications running the same code on every machine. It does this by managing the gems that the application depends on. Given a list of gems, it can automatically download and install those gems, as well as any other gems needed by the gems that are listed. Before installing gems, it checks the versions of every gem to make sure that they are compatible, and can all be loaded at the same time. After the gems have been installed, Bundler can help you update some or all of them when new versions become available. Finally, it records the exact versions that have been installed, so that others can install the exact same gems. From 18f5dba8c834e2d8aca4aa494221f83ac3cd3e90 Mon Sep 17 00:00:00 2001 From: Hemant Kumar Date: Tue, 16 Jul 2013 20:49:32 +0530 Subject: [PATCH 191/707] Remove extraneous whitespace --- bundler/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundler/README.md b/bundler/README.md index a6427b90..9ce536ac 100644 --- a/bundler/README.md +++ b/bundler/README.md @@ -1,7 +1,7 @@ [![Code Climate](https://codeclimate.com/github/bundler/bundler.png)](https://codeclimate.com/github/bundler/bundler) [![Build Status](https://secure.travis-ci.org/bundler/bundler.png?branch=1-3-stable)](http://travis-ci.org/bundler/bundler) -# Bundler: a gem to bundle gems +# Bundler: a gem to bundle gems Bundler keeps ruby applications running the same code on every machine. It does this by managing the gems that the application depends on. Given a list of gems, it can automatically download and install those gems, as well as any other gems needed by the gems that are listed. Before installing gems, it checks the versions of every gem to make sure that they are compatible, and can all be loaded at the same time. After the gems have been installed, Bundler can help you update some or all of them when new versions become available. Finally, it records the exact versions that have been installed, so that others can install the exact same gems. From 2c403940d6cb0dbcd00ebd43040793f278a9e911 Mon Sep 17 00:00:00 2001 From: Eric Hodel Date: Thu, 18 Jul 2013 16:15:20 -0700 Subject: [PATCH 192/707] Added Gem.find_latest_files This returns files from the latest gems, not all installed versions as in Gem.find_files. --- test/rubygems/test_gem.rb | 35 ++++++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 6cce66ce..8daed165 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -345,9 +345,7 @@ def test_self_find_files spec } - # HACK should be Gem.refresh - Gem.searcher = nil - Gem::Specification.reset + Gem.refresh expected = [ File.expand_path('test/rubygems/sff/discover.rb', @@project_dir), @@ -361,6 +359,37 @@ def test_self_find_files assert_equal cwd, $LOAD_PATH.shift end + def test_self_find_latest_files + cwd = File.expand_path("test/rubygems", @@project_dir) + $LOAD_PATH.unshift cwd + + discover_path = File.join 'lib', 'sff', 'discover.rb' + + foo1, foo2 = %w(1 2).map { |version| + spec = quick_gem 'sff', version do |s| + s.files << discover_path + end + + write_file(File.join 'gems', spec.full_name, discover_path) do |fp| + fp.puts "# #{spec.full_name}" + end + + spec + } + + Gem.refresh + + expected = [ + File.expand_path('test/rubygems/sff/discover.rb', @@project_dir), + File.join(foo2.full_gem_path, discover_path), + ] + + assert_equal expected, Gem.find_latest_files('sff/discover') + assert_equal expected, Gem.find_latest_files('sff/**.rb'), '[ruby-core:31730]' + ensure + assert_equal cwd, $LOAD_PATH.shift + end + def test_self_latest_spec_for a1 = quick_spec 'a', 1 a2 = quick_spec 'a', 2 From f9f3e89b476d2a8baaf32e9bee2b7eec793b3be2 Mon Sep 17 00:00:00 2001 From: Evan Phoenix Date: Thu, 18 Jul 2013 16:32:38 -0700 Subject: [PATCH 193/707] ! Only load plugins from the latest versions --- test/rubygems/test_gem.rb | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 8daed165..f6285957 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -13,8 +13,13 @@ class TestGem < Gem::TestCase + PLUGINS_LOADED = [] + def setup super + + PLUGINS_LOADED.clear + common_installer_setup ENV.delete 'RUBYGEMS_GEMDEPS' @@ -912,14 +917,20 @@ def test_load_plugins Dir.chdir @tempdir do FileUtils.mkdir_p 'lib' File.open plugin_path, "w" do |fp| - fp.puts "class TestGem; TEST_SPEC_PLUGIN_LOAD = :loaded; end" + fp.puts "class TestGem; PLUGINS_LOADED << 'plugin'; end" end - foo = quick_spec 'foo', '1' do |s| + foo1 = quick_spec 'foo', '1' do |s| s.files << plugin_path end - install_gem foo + install_gem foo1 + + foo2 = quick_spec 'foo', '2' do |s| + s.files << plugin_path + end + + install_gem foo2 end Gem.searcher = nil @@ -929,7 +940,7 @@ def test_load_plugins Gem.load_plugins - assert_equal :loaded, TEST_SPEC_PLUGIN_LOAD + assert_equal %w[plugin], PLUGINS_LOADED end def test_load_env_plugins From 90e7355b020e958434e1a7814d908b06afae2c35 Mon Sep 17 00:00:00 2001 From: Eric Hodel Date: Fri, 19 Jul 2013 14:26:31 -0700 Subject: [PATCH 194/707] Fix unused variable warning --- test/rubygems/test_gem.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index f6285957..0ee8d36f 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -370,7 +370,7 @@ def test_self_find_latest_files discover_path = File.join 'lib', 'sff', 'discover.rb' - foo1, foo2 = %w(1 2).map { |version| + _, foo2 = %w(1 2).map { |version| spec = quick_gem 'sff', version do |s| s.files << discover_path end From 9ffd42eebed88911bfdb2b97f464d59430f89920 Mon Sep 17 00:00:00 2001 From: Hemant Kumar Date: Thu, 25 Jul 2013 13:03:08 +0530 Subject: [PATCH 195/707] Start adding specs for bundler parallel install --- bundler/spec/realworld/edgecases_spec.rb | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index fd5b607b..3e4dc8b7 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -174,4 +174,15 @@ bundle :install, :exitstatus => true expect(exitstatus).to eq(0) end + + it "installs gems parallely" do + gemfile <<-G + source "https://rubygems.org" + + gem 'rails' + G + + bundle :install, :jobs => 4 + expect(exitstatus).to eq(0) + end end From 8faba43b226e896b041424c87d7e1a42fa9dfab8 Mon Sep 17 00:00:00 2001 From: Hemant Kumar Date: Sat, 27 Jul 2013 02:09:21 +0530 Subject: [PATCH 196/707] Add separate specs for parallel gem installation --- bundler/spec/realworld/edgecases_spec.rb | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index 3e4dc8b7..fd5b607b 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -174,15 +174,4 @@ bundle :install, :exitstatus => true expect(exitstatus).to eq(0) end - - it "installs gems parallely" do - gemfile <<-G - source "https://rubygems.org" - - gem 'rails' - G - - bundle :install, :jobs => 4 - expect(exitstatus).to eq(0) - end end From 98b7f5f18777f5680058fa2e19caea8ca1852c8e Mon Sep 17 00:00:00 2001 From: Andre Arko Date: Fri, 2 Aug 2013 23:30:03 -0700 Subject: [PATCH 197/707] update link to contrib doc closes #2578 --- bundler/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundler/README.md b/bundler/README.md index 9ce536ac..9f9b3e7e 100644 --- a/bundler/README.md +++ b/bundler/README.md @@ -24,7 +24,7 @@ For help with common problems, see [ISSUES](https://github.com/bundler/bundler/b ### Contributing -If you'd like to contribute to Bundler, that's awesome, and we <3 you. There's a guide to contributing to Bundler (both code and general help) over in [CONTRIBUTE](https://github.com/bundler/bundler/blob/master/CONTRIBUTE.md) +If you'd like to contribute to Bundler, that's awesome, and we <3 you. There's a guide to contributing to Bundler (both code and general help) over in [DEVELOPMENT](https://github.com/bundler/bundler/blob/master/DEVELOPMENT.md) ### Development From f4cee29ea5d4588a2cb03d1b27e6587f7af90a4f Mon Sep 17 00:00:00 2001 From: Andre Arko Date: Sun, 11 Aug 2013 19:43:05 -0700 Subject: [PATCH 198/707] rearrange docs a bit to be less silly --- bundler/README.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/bundler/README.md b/bundler/README.md index 9f9b3e7e..484343c2 100644 --- a/bundler/README.md +++ b/bundler/README.md @@ -16,7 +16,7 @@ bundle install bundle exec rails new myapp ``` -See [gembundler.com](http://gembundler.com) for the full documentation. +See [bundler.io](http://bundler.io) for the full documentation. ### Troubleshooting @@ -26,12 +26,14 @@ For help with common problems, see [ISSUES](https://github.com/bundler/bundler/b If you'd like to contribute to Bundler, that's awesome, and we <3 you. There's a guide to contributing to Bundler (both code and general help) over in [DEVELOPMENT](https://github.com/bundler/bundler/blob/master/DEVELOPMENT.md) -### Development +The `master` branch contains our current progress towards version 1.4. Versions 1.0-1.3 each have their own stable branches. Please submit bugfixes as pull requests to the stable branch for the version you would like to fix. -To see what has changed in recent versions of Bundler, see the [CHANGELOG](https://github.com/bundler/bundler/blob/master/CHANGELOG.md). +### Core Team -The `master` branch contains our current progress towards version 1.3. Versions 1.0 to 1.2 each have their own stable branches. Please submit bugfixes as pull requests to the stable branch for the version you would like to fix. +The Bundler core team consists of André Arko ([@indirect](http://github.com/indirect)), Terence Lee ([@hone](http://github.com/hone)), and Jessica Lynn Suttles ([@jlsuttles](http://github.com/jlsuttles)), with support and advice from original Bundler author Yehuda Katz ([@wycats](http://github.com/wycats)). ### Other questions +To see what has changed in recent versions of Bundler, see the [CHANGELOG](https://github.com/bundler/bundler/blob/master/CHANGELOG.md). + Feel free to chat with the Bundler core team (and many other users) on IRC in the [#bundler](irc://irc.freenode.net/bundler) channel on Freenode, or via email on the [Bundler mailing list](http://groups.google.com/group/ruby-bundler). From 414a268bce661bbea34aa546dcedd3f547f7d040 Mon Sep 17 00:00:00 2001 From: Justin George Date: Mon, 26 Aug 2013 12:17:09 -0700 Subject: [PATCH 199/707] add simple test for default_gems_use_full_paths --- test/rubygems/test_gem.rb | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 0ee8d36f..38a63c3b 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1181,6 +1181,28 @@ def test_register_default_spec assert_equal nil, Gem.find_unresolved_default_spec("README") end + def test_default_gems_use_full_paths + begin + engine = RUBY_ENGINE + Object.send :remove_const, :RUBY_ENGINE + Object.const_set :RUBY_ENGINE, 'ruby' + refute Gem.default_gems_use_full_paths? + ensure + Object.send :remove_const, :RUBY_ENGINE + Object.const_set :RUBY_ENGINE, engine + end + + begin + engine = RUBY_ENGINE + Object.send :remove_const, :RUBY_ENGINE + Object.const_set :RUBY_ENGINE, 'jruby' + assert Gem.default_gems_use_full_paths? + ensure + Object.send :remove_const, :RUBY_ENGINE + Object.const_set :RUBY_ENGINE, engine + end + end + def with_plugin(path) test_plugin_path = File.expand_path("test/rubygems/plugin/#{path}", @@project_dir) From 6950e4ade1d25b34f32d237efcc54ffba46876eb Mon Sep 17 00:00:00 2001 From: Eric Hodel Date: Mon, 26 Aug 2013 14:57:24 -0700 Subject: [PATCH 200/707] Fix tests for missing RUBY_ENGINE Old CRuby versions have no RUBY_ENGINE, but the new tests don't account for this. This allows the tests to pass on these old rubies (even though they don't use default gems). See #611 --- test/rubygems/test_gem.rb | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 38a63c3b..45db153c 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1183,23 +1183,28 @@ def test_register_default_spec def test_default_gems_use_full_paths begin - engine = RUBY_ENGINE - Object.send :remove_const, :RUBY_ENGINE + if defined?(RUBY_ENGINE) then + engine = RUBY_ENGINE + Object.send :remove_const, :RUBY_ENGINE + end Object.const_set :RUBY_ENGINE, 'ruby' + refute Gem.default_gems_use_full_paths? ensure Object.send :remove_const, :RUBY_ENGINE - Object.const_set :RUBY_ENGINE, engine + Object.const_set :RUBY_ENGINE, engine if engine end begin - engine = RUBY_ENGINE - Object.send :remove_const, :RUBY_ENGINE + if defined?(RUBY_ENGINE) then + engine = RUBY_ENGINE + Object.send :remove_const, :RUBY_ENGINE + end Object.const_set :RUBY_ENGINE, 'jruby' assert Gem.default_gems_use_full_paths? ensure Object.send :remove_const, :RUBY_ENGINE - Object.const_set :RUBY_ENGINE, engine + Object.const_set :RUBY_ENGINE, engine if engine end end From 6fc15962e05b48e628e491fdba2366688bda503e Mon Sep 17 00:00:00 2001 From: Eric Hodel Date: Thu, 19 Sep 2013 17:19:53 -0700 Subject: [PATCH 201/707] Test each created gem directory The test for Gem.ensure_gem_directories only tested one of the created directories. Now they're all tested. --- test/rubygems/test_gem.rb | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 45db153c..a116ddd3 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -257,7 +257,11 @@ def test_self_ensure_gem_directories Gem.ensure_gem_subdirectories @gemhome - assert File.directory? File.join(@gemhome, "cache") + assert_path_exists File.join @gemhome, 'build_info' + assert_path_exists File.join @gemhome, 'cache' + assert_path_exists File.join @gemhome, 'doc' + assert_path_exists File.join @gemhome, 'gems' + assert_path_exists File.join @gemhome, 'specifications' end def test_self_ensure_gem_directories_permissions From 62e90b80617cdabbfc54fc4822b3ec0c9dfde3ff Mon Sep 17 00:00:00 2001 From: Eric Hodel Date: Thu, 19 Sep 2013 17:22:18 -0700 Subject: [PATCH 202/707] Add extensions directory to GEM_HOME The extensions directory will hold built extensions for installed gems so a gem directory can be shared across ruby versions and platforms. See #596 --- test/rubygems/test_gem.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index a116ddd3..7d3f81a9 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -260,6 +260,7 @@ def test_self_ensure_gem_directories assert_path_exists File.join @gemhome, 'build_info' assert_path_exists File.join @gemhome, 'cache' assert_path_exists File.join @gemhome, 'doc' + assert_path_exists File.join @gemhome, 'extensions' assert_path_exists File.join @gemhome, 'gems' assert_path_exists File.join @gemhome, 'specifications' end From 5a5e933064547ee2dfcc7af1d9aa0f64aa3cd933 Mon Sep 17 00:00:00 2001 From: Eric Hodel Date: Thu, 19 Sep 2013 17:46:53 -0700 Subject: [PATCH 203/707] Add Gem.ruby_api_version Extensions must be recompiled for each Ruby API version so we need an accessor for it. See #596 --- test/rubygems/test_gem.rb | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 7d3f81a9..ac40d97c 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -644,6 +644,22 @@ def test_self_ruby_path_without_spaces Gem::ConfigMap[:EXEEXT] = orig_exe_ext end + def test_self_ruby_api_version + orig_MAJOR, Gem::ConfigMap[:MAJOR] = Gem::ConfigMap[:MAJOR], '1' + orig_MINOR, Gem::ConfigMap[:MINOR] = Gem::ConfigMap[:MINOR], '2' + orig_TEENY, Gem::ConfigMap[:TEENY] = Gem::ConfigMap[:TEENY], '3' + + Gem.instance_variable_set :@ruby_api_version, nil + + assert_equal '1.2.3', Gem.ruby_api_version + ensure + Gem.instance_variable_set :@ruby_api_version, nil + + Gem::ConfigMap[:MAJOR] = orig_MAJOR + Gem::ConfigMap[:MINOR] = orig_MINOR + Gem::ConfigMap[:TEENY] = orig_TEENY + end + def test_self_ruby_version_1_8_5 util_set_RUBY_VERSION '1.8.5' From 3af5ea366d80027100db16816ba0b1176ec84721 Mon Sep 17 00:00:00 2001 From: joyicecloud Date: Fri, 20 Sep 2013 14:30:13 -0700 Subject: [PATCH 204/707] Put old version message in the block level Change bundle update message format Change rspec bundle update message text to match in files (rubygem, git, path source, etc) --- bundler/spec/realworld/edgecases_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index fd5b607b..263ac520 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -32,7 +32,7 @@ gem 'activerecord', '~> 3.0' gem 'builder', '~> 2.1.2' G - expect(out).to include("activemodel (3.0.5)") + expect(out).to include("activemodel 3.0.5") end # https://github.com/bundler/bundler/issues/1500 From 720c90aa23f1fc8b71659a56d8a809728e72d27f Mon Sep 17 00:00:00 2001 From: Eric Hodel Date: Tue, 24 Sep 2013 16:15:51 -0700 Subject: [PATCH 205/707] Fix CVE-2013-4363, remove regexp backtracking The Gem::Version regexp used backtracking to validate gem versions, but in a different way than CVE-2013-4287. This could cause excessive CPU usage when creating Gem::Version objects including when packaging gems. See CVE-2013-4363.txt (in this commit) for details. See #626 --- test/rubygems/test_gem_version.rb | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/test/rubygems/test_gem_version.rb b/test/rubygems/test_gem_version.rb index 2ba196e4..2136034d 100644 --- a/test/rubygems/test_gem_version.rb +++ b/test/rubygems/test_gem_version.rb @@ -67,12 +67,17 @@ def test_initialize end def test_initialize_bad - ["junk", "1.0\n2.0"].each do |bad| - e = assert_raises ArgumentError do + %W[ + junk + 1.0\n2.0 + 1..2 + 1.2\ 3.4 + ].each do |bad| + e = assert_raises ArgumentError, bad do Gem::Version.new bad end - assert_equal "Malformed version number string #{bad}", e.message + assert_equal "Malformed version number string #{bad}", e.message, bad end end From cbdc6970d5bd21105b44b3528998ca7e1e99eec0 Mon Sep 17 00:00:00 2001 From: Eric Hodel Date: Tue, 24 Sep 2013 16:15:51 -0700 Subject: [PATCH 206/707] Fix CVE-2013-4363, remove regexp backtracking The Gem::Version regexp used backtracking to validate gem versions, but in a different way than CVE-2013-4287. This could cause excessive CPU usage when creating Gem::Version objects including when packaging gems. See CVE-2013-4363.txt (in this commit) for details. See #626 --- test/rubygems/test_gem_requirement.rb | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/test/rubygems/test_gem_requirement.rb b/test/rubygems/test_gem_requirement.rb index 1de0f41f..01db08e8 100644 --- a/test/rubygems/test_gem_requirement.rb +++ b/test/rubygems/test_gem_requirement.rb @@ -47,18 +47,20 @@ def test_parse end def test_parse_bad - e = assert_raises Gem::Requirement::BadRequirementError do - Gem::Requirement.parse nil - end - - assert_equal 'Illformed requirement [nil]', e.message + [ + nil, + '', + '! 1', + '= junk', + '1..2', + ].each do |bad| + e = assert_raises Gem::Requirement::BadRequirementError do + Gem::Requirement.parse bad + end - e = assert_raises Gem::Requirement::BadRequirementError do - Gem::Requirement.parse "" + assert_equal "Illformed requirement [#{bad.inspect}]", e.message end - assert_equal 'Illformed requirement [""]', e.message - assert_equal Gem::Requirement::BadRequirementError.superclass, ArgumentError end From b48212c35d49e90cc33d12412e28d4e8599411e9 Mon Sep 17 00:00:00 2001 From: Josh Kline Date: Tue, 8 Oct 2013 10:47:37 -0700 Subject: [PATCH 207/707] Fix test for Gem::Version.create change Test changes due to intentional code behavior change. The comment "FIX: For "legacy reasons," any object that responds to +version+ is returned unchanged. I'm not certain why." is no longer applicable as I removed that functionality in my previous patch. I was not certain why either :) Instead objects of type Gem::Version are simply not cast by Gem::Version.create. --- test/rubygems/test_gem_version.rb | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/test/rubygems/test_gem_version.rb b/test/rubygems/test_gem_version.rb index 2136034d..e0499fe7 100644 --- a/test/rubygems/test_gem_version.rb +++ b/test/rubygems/test_gem_version.rb @@ -23,14 +23,13 @@ def test_bump_one_level assert_bumped_version_equal "6", "5" end - # FIX: For "legacy reasons," any object that responds to +version+ - # is returned unchanged. I'm not certain why. + # A Gem::Version is already a Gem::Version and therefore not transformed by + # Gem::Version.create def test_class_create - fake = Object.new - def fake.version; "1.0" end + real = Gem::Version.new(1.0) - assert_same fake, Gem::Version.create(fake) + assert_same real, Gem::Version.create(real) assert_nil Gem::Version.create(nil) assert_equal v("5.1"), Gem::Version.create("5.1") From 0e1fde37b9887eb8001d480bcaa5be81a9659902 Mon Sep 17 00:00:00 2001 From: Eric Hodel Date: Wed, 16 Oct 2013 15:20:38 -0700 Subject: [PATCH 208/707] Require Gem::Command* for tests This is needed in various places after removing the unneeded requires from lib/rubygems/ext*. --- test/rubygems/test_gem.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index ac40d97c..a320d548 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1,6 +1,7 @@ # coding: US-ASCII require 'rubygems/test_case' require 'rubygems' +require 'rubygems/command' require 'rubygems/installer' require 'pathname' require 'tmpdir' From b285732ee0915e6dc89a4f5d6ecbe7f394fee98a Mon Sep 17 00:00:00 2001 From: Eric Hodel Date: Thu, 17 Oct 2013 13:39:47 -0700 Subject: [PATCH 209/707] Fix test bug for ruby without ENABLE_SHARED The tests did not take into ENABLE_SHARED into account properly and would fail on ruby with ENBALE_SHARED = no This also adds Gem.extension_api_version which makes the tests easier to write. --- test/rubygems/test_gem.rb | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index a320d548..88d0b1c4 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -338,6 +338,24 @@ def test_self_ensure_gem_directories_write_protected_parents end end + def test_self_extension_install_dir_shared + enable_shared, RbConfig::CONFIG['ENABLE_SHARED'] = + RbConfig::CONFIG['ENABLE_SHARED'], 'yes' + + assert_equal Gem.ruby_api_version, Gem.extension_api_version + ensure + RbConfig::CONFIG['ENABLE_SHARED'] = enable_shared + end + + def test_self_extension_install_dir_static + enable_shared, RbConfig::CONFIG['ENABLE_SHARED'] = + RbConfig::CONFIG['ENABLE_SHARED'], 'no' + + assert_equal "#{Gem.ruby_api_version}-static", Gem.extension_api_version + ensure + RbConfig::CONFIG['ENABLE_SHARED'] = enable_shared + end + def test_self_find_files cwd = File.expand_path("test/rubygems", @@project_dir) $LOAD_PATH.unshift cwd From a06210d3041e8c5dea042c3129fa32969a05f7cf Mon Sep 17 00:00:00 2001 From: Eric Hodel Date: Wed, 30 Oct 2013 21:58:17 -0700 Subject: [PATCH 210/707] Add Gem::Requirement#concat This does not check for compatibility requirements. --- test/rubygems/test_gem_requirement.rb | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/test/rubygems/test_gem_requirement.rb b/test/rubygems/test_gem_requirement.rb index 01db08e8..5c435f07 100644 --- a/test/rubygems/test_gem_requirement.rb +++ b/test/rubygems/test_gem_requirement.rb @@ -3,6 +3,14 @@ class TestGemRequirement < Gem::TestCase + def test_concat + r = req '>= 1' + + r.concat ['< 2'] + + assert_equal [['>=', v(1)], ['<', v(2)]], r.requirements + end + def test_equals2 r = req "= 1.2" assert_equal r, r.dup From 4f080d08a5c14b06d5e6273b6601fd393e830716 Mon Sep 17 00:00:00 2001 From: Eric Hodel Date: Thu, 31 Oct 2013 17:06:31 -0700 Subject: [PATCH 211/707] Add Requirement#for_lockfile This reduces duplicate code in Lockfile. --- test/rubygems/test_gem_requirement.rb | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/rubygems/test_gem_requirement.rb b/test/rubygems/test_gem_requirement.rb index 5c435f07..29a4675b 100644 --- a/test/rubygems/test_gem_requirement.rb +++ b/test/rubygems/test_gem_requirement.rb @@ -44,6 +44,12 @@ def test_basic_non_none assert_equal false, r.none? end + def test_for_lockfile + assert_equal ' (~> 1.0)', req('~> 1.0').for_lockfile + + assert_nil Gem::Requirement.default.for_lockfile + end + def test_parse assert_equal ['=', Gem::Version.new(1)], Gem::Requirement.parse(' 1') assert_equal ['=', Gem::Version.new(1)], Gem::Requirement.parse('= 1') From 958f7ddc0d95ebdbe84fa6ee80d29c783c384173 Mon Sep 17 00:00:00 2001 From: Eric Hodel Date: Tue, 5 Nov 2013 14:56:10 -0800 Subject: [PATCH 212/707] Switch to spec_fetcher for most old uses This covers all uses except pre-existing gems created in initialize and one case where strange things are happening. --- test/rubygems/test_gem.rb | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 88d0b1c4..f4222563 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -420,12 +420,13 @@ def test_self_find_latest_files end def test_self_latest_spec_for - a1 = quick_spec 'a', 1 - a2 = quick_spec 'a', 2 - a3a = quick_spec 'a', '3.a' + a2 = nil - util_setup_fake_fetcher - util_setup_spec_fetcher a1, a2, a3a + spec_fetcher do |fetcher| + fetcher.spec 'a', 1 + fetcher.spec 'a', '3.a' + a2 = fetcher.spec 'a', 2 + end spec = Gem.latest_spec_for 'a' @@ -433,12 +434,11 @@ def test_self_latest_spec_for end def test_self_latest_rubygems_version - r1 = quick_spec 'rubygems-update', '1.8.23' - r2 = quick_spec 'rubygems-update', '1.8.24' - r3 = quick_spec 'rubygems-update', '2.0.0.preview3' - - util_setup_fake_fetcher - util_setup_spec_fetcher r1, r2, r3 + spec_fetcher do |fetcher| + fetcher.spec 'rubygems-update', '1.8.23' + fetcher.spec 'rubygems-update', '1.8.24' + fetcher.spec 'rubygems-update', '2.0.0.preview3' + end version = Gem.latest_rubygems_version @@ -446,12 +446,11 @@ def test_self_latest_rubygems_version end def test_self_latest_version_for - a1 = quick_spec 'a', 1 - a2 = quick_spec 'a', 2 - a3a = quick_spec 'a', '3.a' - - util_setup_fake_fetcher - util_setup_spec_fetcher a1, a2, a3a + spec_fetcher do |fetcher| + fetcher.spec 'a', 1 + fetcher.spec 'a', 2 + fetcher.spec 'a', '3.a' + end version = Gem.latest_version_for 'a' From 7c05deeddea49186a3503ea34846d8b01dae4a10 Mon Sep 17 00:00:00 2001 From: Evan Phoenix Date: Wed, 6 Nov 2013 15:12:05 -0800 Subject: [PATCH 213/707] Fix tests to deal with DepRes returning different orders now --- test/rubygems/test_gem.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 88d0b1c4..c61d31fd 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1123,7 +1123,7 @@ def test_auto_activation_of_detected_gemdeps_file ENV['RUBYGEMS_GEMDEPS'] = "-" - assert_equal [a,b,c], Gem.detect_gemdeps + assert_equal [a,b,c], Gem.detect_gemdeps.sort_by { |s| s.name } end LIB_PATH = File.expand_path "../../../lib".untaint, __FILE__.untaint From 82fa93baedafdeb6f33a3664b3ca5e85466cca37 Mon Sep 17 00:00:00 2001 From: Eric Hodel Date: Mon, 11 Nov 2013 10:10:46 -0500 Subject: [PATCH 214/707] Allow SpecFetcherSetup#clear to happen anywhere Previously #clear was absolute, and always cleared at the end. Now it can occur arbitrarily. This implementation is a little clumsy as util_setup_spec_fetcher adds all the specs to the installed list, then we have to remove them and add them back. --- test/rubygems/test_gem.rb | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index f4222563..77cb0905 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -420,17 +420,15 @@ def test_self_find_latest_files end def test_self_latest_spec_for - a2 = nil - - spec_fetcher do |fetcher| + gems = spec_fetcher do |fetcher| fetcher.spec 'a', 1 fetcher.spec 'a', '3.a' - a2 = fetcher.spec 'a', 2 + fetcher.spec 'a', 2 end spec = Gem.latest_spec_for 'a' - assert_equal a2, spec + assert_equal gems['a-2'], spec end def test_self_latest_rubygems_version From 7a46b5b9ba600fc993bbc6a6a7efab3c4a6b2374 Mon Sep 17 00:00:00 2001 From: Eric Hodel Date: Mon, 11 Nov 2013 13:35:28 -0800 Subject: [PATCH 215/707] Replace TestCase#quick_spec with #util_spec The util_spec does everything quick_spec does and more, so quick_spec should be replaced with util_spec. --- test/rubygems/test_gem.rb | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 77cb0905..fd4d1de5 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -116,7 +116,7 @@ def test_self_bin_path_bin_name_version end def test_self_bin_path_nonexistent_binfile - quick_spec 'a', '2' do |s| + util_spec 'a', '2' do |s| s.executables = ['exec'] end assert_raises(Gem::GemNotFoundException) do @@ -125,7 +125,7 @@ def test_self_bin_path_nonexistent_binfile end def test_self_bin_path_no_bin_file - quick_spec 'a', '1' + util_spec 'a', '1' assert_raises(ArgumentError) do Gem.bin_path('a', nil, '1') end @@ -139,7 +139,7 @@ def test_self_bin_path_not_found def test_self_bin_path_bin_file_gone_in_latest util_exec_gem - quick_spec 'a', '10' do |s| + util_spec 'a', '10' do |s| s.executables = [] end # Should not find a-10's non-abin (bug) @@ -183,7 +183,7 @@ def test_self_datadir fp.puts 'blah' end - foo = quick_spec 'foo' do |s| s.files = %w[data/foo.txt] end + foo = util_spec 'foo' do |s| s.files = %w[data/foo.txt] end install_gem foo end @@ -456,7 +456,7 @@ def test_self_latest_version_for end def test_self_loaded_specs - foo = quick_spec 'foo' + foo = util_spec 'foo' install_gem foo foo.activate @@ -957,13 +957,13 @@ def test_load_plugins fp.puts "class TestGem; PLUGINS_LOADED << 'plugin'; end" end - foo1 = quick_spec 'foo', '1' do |s| + foo1 = util_spec 'foo', '1' do |s| s.files << plugin_path end install_gem foo1 - foo2 = quick_spec 'foo', '2' do |s| + foo2 = util_spec 'foo', '2' do |s| s.files << plugin_path end @@ -1273,7 +1273,7 @@ def util_ensure_gem_dirs end def util_exec_gem - spec, _ = quick_spec 'a', '4' do |s| + spec, _ = util_spec 'a', '4' do |s| s.executables = ['exec', 'abin'] end From cafc6104d084d3f48c13e30e93337944263ce132 Mon Sep 17 00:00:00 2001 From: Eric Hodel Date: Wed, 13 Nov 2013 15:50:36 -0800 Subject: [PATCH 216/707] Update MIT credits for near-identical bundler code Parts of Gem::Source::Git mirror Bundler::Source::Git and Bundler::Source::Git::GitProxy. --- MIT.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/MIT.txt b/MIT.txt index 0e6643ab..a90b9bb2 100644 --- a/MIT.txt +++ b/MIT.txt @@ -1,4 +1,5 @@ Copyright (c) Chad Fowler, Rich Kilmer, Jim Weirich and others. +Portions copyright (c) Engine Yard and Andre Arko Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the From d1840723dfc3fbed44e8bc79ceb32b694730c0cc Mon Sep 17 00:00:00 2001 From: Olivier Lacan Date: Sat, 16 Nov 2013 16:05:31 -0500 Subject: [PATCH 217/707] Update README to reflect progress towards 1.5 --- bundler/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundler/README.md b/bundler/README.md index 484343c2..74d3b7a7 100644 --- a/bundler/README.md +++ b/bundler/README.md @@ -26,7 +26,7 @@ For help with common problems, see [ISSUES](https://github.com/bundler/bundler/b If you'd like to contribute to Bundler, that's awesome, and we <3 you. There's a guide to contributing to Bundler (both code and general help) over in [DEVELOPMENT](https://github.com/bundler/bundler/blob/master/DEVELOPMENT.md) -The `master` branch contains our current progress towards version 1.4. Versions 1.0-1.3 each have their own stable branches. Please submit bugfixes as pull requests to the stable branch for the version you would like to fix. +The `master` branch contains our current progress towards version 1.5. Versions 1.0-1.3 each have their own stable branches. Please submit bugfixes as pull requests to the stable branch for the version you would like to fix. ### Core Team From f64f8455eebb15bd2a56c8d5b875b8eb6bc74787 Mon Sep 17 00:00:00 2001 From: Eric Hodel Date: Thu, 21 Nov 2013 14:50:33 -0800 Subject: [PATCH 218/707] Enable gem.deps.rb detection by default This is a big change to rubygems behavior and may need to be reverted for 2.2, depending upon other bugs in the resolver. --- test/rubygems/test_gem.rb | 54 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index ec7f7299..33d4b25e 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1245,6 +1245,60 @@ def test_default_gems_use_full_paths end end + def test_use_gemdeps + rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], nil + + spec = util_spec 'a', 1 + + refute spec.activated? + + open 'Gemfile', 'w' do |io| + io.write 'gem "a"' + end + + Gem.use_gemdeps + + assert spec.activated? + ensure + ENV['RUBYGEMS_GEMDEPS'] = rubygems_gemdeps + end + + def test_use_gemdeps_disabled + rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], '' + + spec = util_spec 'a', 1 + + refute spec.activated? + + open 'Gemfile', 'w' do |io| + io.write 'gem "a"' + end + + Gem.use_gemdeps + + refute spec.activated? + ensure + ENV['RUBYGEMS_GEMDEPS'] = rubygems_gemdeps + end + + def test_use_gemdeps_specific + rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], 'x' + + spec = util_spec 'a', 1 + + refute spec.activated? + + open 'x', 'w' do |io| + io.write 'gem "a"' + end + + Gem.use_gemdeps + + assert spec.activated? + ensure + ENV['RUBYGEMS_GEMDEPS'] = rubygems_gemdeps + end + def with_plugin(path) test_plugin_path = File.expand_path("test/rubygems/plugin/#{path}", @@project_dir) From 2ec1c9c7dbafd8dc049bd4837466391f09d08989 Mon Sep 17 00:00:00 2001 From: Eric Hodel Date: Fri, 22 Nov 2013 10:31:59 -0800 Subject: [PATCH 219/707] Revert 1b6edcd and update comments From [ruby-core:58490], this feature is too dangerous and has been reverted. --- test/rubygems/test_gem.rb | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 33d4b25e..44b6c4a1 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1258,6 +1258,24 @@ def test_use_gemdeps Gem.use_gemdeps + refute spec.activated? + ensure + ENV['RUBYGEMS_GEMDEPS'] = rubygems_gemdeps + end + + def test_use_gemdeps_automatic + rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], '-' + + spec = util_spec 'a', 1 + + refute spec.activated? + + open 'Gemfile', 'w' do |io| + io.write 'gem "a"' + end + + Gem.use_gemdeps + assert spec.activated? ensure ENV['RUBYGEMS_GEMDEPS'] = rubygems_gemdeps From 688e0ef59b689dc282977331d279f9f947190db9 Mon Sep 17 00:00:00 2001 From: Eric Hodel Date: Thu, 5 Dec 2013 16:22:11 -0800 Subject: [PATCH 220/707] Match requirement behavior of bundler in lockfile Bundler orders the versions and deduplicates (which may be a bug elsewhere in the RubyGems lockfile support). --- test/rubygems/test_gem_requirement.rb | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/test/rubygems/test_gem_requirement.rb b/test/rubygems/test_gem_requirement.rb index 29a4675b..8adaf898 100644 --- a/test/rubygems/test_gem_requirement.rb +++ b/test/rubygems/test_gem_requirement.rb @@ -47,6 +47,13 @@ def test_basic_non_none def test_for_lockfile assert_equal ' (~> 1.0)', req('~> 1.0').for_lockfile + assert_equal ' (~> 1.0, >= 1.0.1)', req('>= 1.0.1', '~> 1.0').for_lockfile + + duped = req '= 1.0' + duped.requirements << ['=', v('1.0')] + + assert_equal ' (= 1.0)', duped.for_lockfile + assert_nil Gem::Requirement.default.for_lockfile end From 07cd0024e9e4e5602f9ec6f3d63485f68fa66626 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20Ondruch?= Date: Tue, 10 Dec 2013 14:19:16 +0100 Subject: [PATCH 221/707] Rename #extension_install_dir to #extension_dir. The name is shorter and easier to type. It is the analogy to #gem_dir, which does not contain the "install" word as well. --- test/rubygems/test_gem.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 44b6c4a1..759c2fe9 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -338,7 +338,7 @@ def test_self_ensure_gem_directories_write_protected_parents end end - def test_self_extension_install_dir_shared + def test_self_extension_dir_shared enable_shared, RbConfig::CONFIG['ENABLE_SHARED'] = RbConfig::CONFIG['ENABLE_SHARED'], 'yes' @@ -347,7 +347,7 @@ def test_self_extension_install_dir_shared RbConfig::CONFIG['ENABLE_SHARED'] = enable_shared end - def test_self_extension_install_dir_static + def test_self_extension_dir_static enable_shared, RbConfig::CONFIG['ENABLE_SHARED'] = RbConfig::CONFIG['ENABLE_SHARED'], 'no' From 5dd2b0f43c42e812acb899ba9c382dd5c74d1bb9 Mon Sep 17 00:00:00 2001 From: Olivier Lacan Date: Sat, 28 Dec 2013 13:05:13 -0500 Subject: [PATCH 222/707] Display the latest released gem version. The reason I used an HTML img tag here is to support Retina resolution wherever possible. This is something we're working on for all Shields metadata badges in general but Michael from Gemfury already supports it: http://badge.fury.io/for/rb/bundler --- bundler/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundler/README.md b/bundler/README.md index 74d3b7a7..b3ca324b 100644 --- a/bundler/README.md +++ b/bundler/README.md @@ -1,5 +1,5 @@ [![Code Climate](https://codeclimate.com/github/bundler/bundler.png)](https://codeclimate.com/github/bundler/bundler) -[![Build Status](https://secure.travis-ci.org/bundler/bundler.png?branch=1-3-stable)](http://travis-ci.org/bundler/bundler) +[![Build Status](https://secure.travis-ci.org/bundler/bundler.png?branch=1-3-stable)](http://travis-ci.org/bundler/bundler) Gem Version # Bundler: a gem to bundle gems Bundler keeps ruby applications running the same code on every machine. From 2a6392ab5471cc5161de8fa485006a0c55667396 Mon Sep 17 00:00:00 2001 From: Erik Michaels-Ober Date: Mon, 30 Dec 2013 18:37:46 +0100 Subject: [PATCH 223/707] Skip failing tests on Ruby 1.8.7 --- test/rubygems/test_gem.rb | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 759c2fe9..4501fceb 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -230,6 +230,7 @@ def test_self_default_sources end def test_self_detect_gemdeps + skip 'Insecure operation - chdir' if RUBY_VERSION <= "1.8.7" rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], '-' FileUtils.mkdir_p 'detect/a/b' @@ -857,6 +858,7 @@ def test_self_needs end def test_self_needs_picks_up_unresolved_deps + skip 'loading from unsafe file' if RUBY_VERSION <= "1.8.7" save_loaded_features do util_clear_gems a = util_spec "a", "1" @@ -949,6 +951,7 @@ def test_self_user_home_user_drive_and_path end def test_load_plugins + skip 'Insecure operation - chdir' if RUBY_VERSION <= "1.8.7" plugin_path = File.join "lib", "rubygems_plugin.rb" Dir.chdir @tempdir do @@ -1102,6 +1105,7 @@ def test_auto_activation_of_specific_gemdeps_file end def test_auto_activation_of_detected_gemdeps_file + skip 'Insecure operation - chdir' if RUBY_VERSION <= "1.8.7" util_clear_gems a = new_spec "a", "1", nil, "lib/a.rb" @@ -1264,6 +1268,7 @@ def test_use_gemdeps end def test_use_gemdeps_automatic + skip 'Insecure operation - chdir' if RUBY_VERSION <= "1.8.7" rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], '-' spec = util_spec 'a', 1 @@ -1300,6 +1305,7 @@ def test_use_gemdeps_disabled end def test_use_gemdeps_specific + skip 'Insecure operation - read' if RUBY_VERSION <= "1.8.7" rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], 'x' spec = util_spec 'a', 1 From b735faa7160a130f31866addc11d0a4adbb88292 Mon Sep 17 00:00:00 2001 From: Erik Michaels-Ober Date: Mon, 30 Dec 2013 18:53:53 +0100 Subject: [PATCH 224/707] Skip more failing tests on Ruby 1.8.7 --- test/rubygems/test_gem.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 4501fceb..3c945c86 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -584,6 +584,7 @@ def test_self_prefix_sitelibdir end def test_self_refresh + skip 'Insecure operation - mkdir' if RUBY_VERSION <= "1.8.7" util_make_gems a1_spec = @a1.spec_file @@ -603,6 +604,7 @@ def test_self_refresh end def test_self_refresh_keeps_loaded_specs_activated + skip 'Insecure operation - mkdir' if RUBY_VERSION <= "1.8.7" util_make_gems a1_spec = @a1.spec_file From a2b158514b6af61cf0a50d7f2bb607f373ededb6 Mon Sep 17 00:00:00 2001 From: Tim Moore Date: Thu, 2 Jan 2014 16:12:29 +1100 Subject: [PATCH 225/707] Change build badge to the master branch. Also change the hostname to what's recommended in http://about.travis-ci.org/docs/user/status-images/ (they all redirect to the same place, but this is cleaner). [ci skip] --- bundler/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundler/README.md b/bundler/README.md index 671b6e72..2117ff5d 100644 --- a/bundler/README.md +++ b/bundler/README.md @@ -1,5 +1,5 @@ [![Code Climate](https://codeclimate.com/github/bundler/bundler.png)](https://codeclimate.com/github/bundler/bundler) -[![Build Status](https://secure.travis-ci.org/bundler/bundler.png?branch=1-3-stable)](http://travis-ci.org/bundler/bundler) +[![Build Status](https://travis-ci.org/bundler/bundler.png?branch=master)](http://travis-ci.org/bundler/bundler) Gem Version # Bundler: a gem to bundle gems From 202ccc1347ec436ed8af7a7d770aa5af8cc26180 Mon Sep 17 00:00:00 2001 From: Eric Hodel Date: Fri, 3 Jan 2014 14:42:47 -0800 Subject: [PATCH 226/707] Deprecate Gem::ConfigMap in favor of RbConfig I'm not sure what it was ever for. It just copies RbConfig::CONFIG entries, so let's just use the original source now. --- test/rubygems/test_gem.rb | 80 +++++++++++++++++++-------------------- 1 file changed, 40 insertions(+), 40 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 3c945c86..a66f5030 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -199,30 +199,30 @@ def test_self_datadir_nonexistent_package end def test_self_default_exec_format - orig_RUBY_INSTALL_NAME = Gem::ConfigMap[:ruby_install_name] - Gem::ConfigMap[:ruby_install_name] = 'ruby' + orig_RUBY_INSTALL_NAME = RbConfig::CONFIG['ruby_install_name'] + RbConfig::CONFIG['ruby_install_name'] = 'ruby' assert_equal '%s', Gem.default_exec_format ensure - Gem::ConfigMap[:ruby_install_name] = orig_RUBY_INSTALL_NAME + RbConfig::CONFIG['ruby_install_name'] = orig_RUBY_INSTALL_NAME end def test_self_default_exec_format_18 - orig_RUBY_INSTALL_NAME = Gem::ConfigMap[:ruby_install_name] - Gem::ConfigMap[:ruby_install_name] = 'ruby18' + orig_RUBY_INSTALL_NAME = RbConfig::CONFIG['ruby_install_name'] + RbConfig::CONFIG['ruby_install_name'] = 'ruby18' assert_equal '%s18', Gem.default_exec_format ensure - Gem::ConfigMap[:ruby_install_name] = orig_RUBY_INSTALL_NAME + RbConfig::CONFIG['ruby_install_name'] = orig_RUBY_INSTALL_NAME end def test_self_default_exec_format_jruby - orig_RUBY_INSTALL_NAME = Gem::ConfigMap[:ruby_install_name] - Gem::ConfigMap[:ruby_install_name] = 'jruby' + orig_RUBY_INSTALL_NAME = RbConfig::CONFIG['ruby_install_name'] + RbConfig::CONFIG['ruby_install_name'] = 'jruby' assert_equal 'j%s', Gem.default_exec_format ensure - Gem::ConfigMap[:ruby_install_name] = orig_RUBY_INSTALL_NAME + RbConfig::CONFIG['ruby_install_name'] = orig_RUBY_INSTALL_NAME end def test_self_default_sources @@ -566,21 +566,21 @@ def test_self_prefix end def test_self_prefix_libdir - orig_libdir = Gem::ConfigMap[:libdir] - Gem::ConfigMap[:libdir] = @@project_dir + orig_libdir = RbConfig::CONFIG['libdir'] + RbConfig::CONFIG['libdir'] = @@project_dir assert_nil Gem.prefix ensure - Gem::ConfigMap[:libdir] = orig_libdir + RbConfig::CONFIG['libdir'] = orig_libdir end def test_self_prefix_sitelibdir - orig_sitelibdir = Gem::ConfigMap[:sitelibdir] - Gem::ConfigMap[:sitelibdir] = @@project_dir + orig_sitelibdir = RbConfig::CONFIG['sitelibdir'] + RbConfig::CONFIG['sitelibdir'] = @@project_dir assert_nil Gem.prefix ensure - Gem::ConfigMap[:sitelibdir] = orig_sitelibdir + RbConfig::CONFIG['sitelibdir'] = orig_sitelibdir end def test_self_refresh @@ -627,46 +627,46 @@ def test_self_refresh_keeps_loaded_specs_activated def test_self_ruby_escaping_spaces_in_path orig_ruby = Gem.ruby - orig_bindir = Gem::ConfigMap[:bindir] - orig_ruby_install_name = Gem::ConfigMap[:ruby_install_name] - orig_exe_ext = Gem::ConfigMap[:EXEEXT] + orig_bindir = RbConfig::CONFIG['bindir'] + orig_ruby_install_name = RbConfig::CONFIG['ruby_install_name'] + orig_exe_ext = RbConfig::CONFIG['EXEEXT'] - Gem::ConfigMap[:bindir] = "C:/Ruby 1.8/bin" - Gem::ConfigMap[:ruby_install_name] = "ruby" - Gem::ConfigMap[:EXEEXT] = ".exe" + RbConfig::CONFIG['bindir'] = "C:/Ruby 1.8/bin" + RbConfig::CONFIG['ruby_install_name'] = "ruby" + RbConfig::CONFIG['EXEEXT'] = ".exe" Gem.instance_variable_set("@ruby", nil) assert_equal "\"C:/Ruby 1.8/bin/ruby.exe\"", Gem.ruby ensure Gem.instance_variable_set("@ruby", orig_ruby) - Gem::ConfigMap[:bindir] = orig_bindir - Gem::ConfigMap[:ruby_install_name] = orig_ruby_install_name - Gem::ConfigMap[:EXEEXT] = orig_exe_ext + RbConfig::CONFIG['bindir'] = orig_bindir + RbConfig::CONFIG['ruby_install_name'] = orig_ruby_install_name + RbConfig::CONFIG['EXEEXT'] = orig_exe_ext end def test_self_ruby_path_without_spaces orig_ruby = Gem.ruby - orig_bindir = Gem::ConfigMap[:bindir] - orig_ruby_install_name = Gem::ConfigMap[:ruby_install_name] - orig_exe_ext = Gem::ConfigMap[:EXEEXT] + orig_bindir = RbConfig::CONFIG['bindir'] + orig_ruby_install_name = RbConfig::CONFIG['ruby_install_name'] + orig_exe_ext = RbConfig::CONFIG['EXEEXT'] - Gem::ConfigMap[:bindir] = "C:/Ruby18/bin" - Gem::ConfigMap[:ruby_install_name] = "ruby" - Gem::ConfigMap[:EXEEXT] = ".exe" + RbConfig::CONFIG['bindir'] = "C:/Ruby18/bin" + RbConfig::CONFIG['ruby_install_name'] = "ruby" + RbConfig::CONFIG['EXEEXT'] = ".exe" Gem.instance_variable_set("@ruby", nil) assert_equal "C:/Ruby18/bin/ruby.exe", Gem.ruby ensure Gem.instance_variable_set("@ruby", orig_ruby) - Gem::ConfigMap[:bindir] = orig_bindir - Gem::ConfigMap[:ruby_install_name] = orig_ruby_install_name - Gem::ConfigMap[:EXEEXT] = orig_exe_ext + RbConfig::CONFIG['bindir'] = orig_bindir + RbConfig::CONFIG['ruby_install_name'] = orig_ruby_install_name + RbConfig::CONFIG['EXEEXT'] = orig_exe_ext end def test_self_ruby_api_version - orig_MAJOR, Gem::ConfigMap[:MAJOR] = Gem::ConfigMap[:MAJOR], '1' - orig_MINOR, Gem::ConfigMap[:MINOR] = Gem::ConfigMap[:MINOR], '2' - orig_TEENY, Gem::ConfigMap[:TEENY] = Gem::ConfigMap[:TEENY], '3' + orig_MAJOR, RbConfig::CONFIG['MAJOR'] = RbConfig::CONFIG['MAJOR'], '1' + orig_MINOR, RbConfig::CONFIG['MINOR'] = RbConfig::CONFIG['MINOR'], '2' + orig_TEENY, RbConfig::CONFIG['TEENY'] = RbConfig::CONFIG['TEENY'], '3' Gem.instance_variable_set :@ruby_api_version, nil @@ -674,9 +674,9 @@ def test_self_ruby_api_version ensure Gem.instance_variable_set :@ruby_api_version, nil - Gem::ConfigMap[:MAJOR] = orig_MAJOR - Gem::ConfigMap[:MINOR] = orig_MINOR - Gem::ConfigMap[:TEENY] = orig_TEENY + RbConfig::CONFIG['MAJOR'] = orig_MAJOR + RbConfig::CONFIG['MINOR'] = orig_MINOR + RbConfig::CONFIG['TEENY'] = orig_TEENY end def test_self_ruby_version_1_8_5 @@ -828,7 +828,7 @@ def test_self_use_paths def test_self_user_dir parts = [@userhome, '.gem', Gem.ruby_engine] - parts << Gem::ConfigMap[:ruby_version] unless Gem::ConfigMap[:ruby_version].empty? + parts << RbConfig::CONFIG['ruby_version'] unless RbConfig::CONFIG['ruby_version'].empty? assert_equal File.join(parts), Gem.user_dir end From 4ef366c02ec7edef2aec4b0333c85b579ce6fb80 Mon Sep 17 00:00:00 2001 From: Eric Hodel Date: Fri, 3 Jan 2014 14:45:36 -0800 Subject: [PATCH 227/707] Use RbConfig ruby_version for Gem.ruby_api_version By default this has the same value as MAJOR.MINOR.TEENY, but can be overriden from ruby's ./configure --with-ruby-version= which makes RubyGems more flexible for packagers. Fixes #770 --- test/rubygems/test_gem.rb | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index a66f5030..d2f87a9a 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -664,9 +664,7 @@ def test_self_ruby_path_without_spaces end def test_self_ruby_api_version - orig_MAJOR, RbConfig::CONFIG['MAJOR'] = RbConfig::CONFIG['MAJOR'], '1' - orig_MINOR, RbConfig::CONFIG['MINOR'] = RbConfig::CONFIG['MINOR'], '2' - orig_TEENY, RbConfig::CONFIG['TEENY'] = RbConfig::CONFIG['TEENY'], '3' + orig_ruby_version, RbConfig::CONFIG['ruby_version'] = RbConfig::CONFIG['ruby_version'], '1.2.3' Gem.instance_variable_set :@ruby_api_version, nil @@ -674,9 +672,7 @@ def test_self_ruby_api_version ensure Gem.instance_variable_set :@ruby_api_version, nil - RbConfig::CONFIG['MAJOR'] = orig_MAJOR - RbConfig::CONFIG['MINOR'] = orig_MINOR - RbConfig::CONFIG['TEENY'] = orig_TEENY + RbConfig::CONFIG['ruby_version'] = orig_ruby_version end def test_self_ruby_version_1_8_5 From 86ed8d6c3ca789375e6fa38835fe1f460e7add83 Mon Sep 17 00:00:00 2001 From: Eric Hodel Date: Mon, 6 Jan 2014 15:04:34 -0800 Subject: [PATCH 228/707] Allow Gem.read_binary for read-only files An lock cannot be obtained for a read-only file, so retry without read-write or a lock on EACCES. This allows read-only file:// repositories to work again. Bug #761 --- test/rubygems/test_gem.rb | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index d2f87a9a..513f2d4e 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -583,6 +583,24 @@ def test_self_prefix_sitelibdir RbConfig::CONFIG['sitelibdir'] = orig_sitelibdir end + def test_self_read_binary + open 'test', 'w' do |io| + io.write "\xCF\x80" + end + + assert_equal ["\xCF", "\x80"], Gem.read_binary('test').chars.to_a + + skip 'chmod not supported' if Gem.win_platform? + + begin + File.chmod 0444, 'test' + + assert_equal ["\xCF", "\x80"], Gem.read_binary('test').chars.to_a + ensure + File.chmod 0644, 'test' + end + end + def test_self_refresh skip 'Insecure operation - mkdir' if RUBY_VERSION <= "1.8.7" util_make_gems From 0b993e41c6b62c6fcb94ca0ffc17372a7d2fd780 Mon Sep 17 00:00:00 2001 From: Eric Hodel Date: Tue, 28 Jan 2014 17:02:00 -0800 Subject: [PATCH 229/707] Warn about extension building once per gem Part of #796 --- test/rubygems/test_gem.rb | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 513f2d4e..ef13c76e 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -831,6 +831,23 @@ def test_self_try_activate_missing_dep assert_match %r%Could not find 'b' %, e.message end + def test_self_try_activate_missing_extensions + util_spec 'ext', '1' do |s| + s.extensions = %w[ext/extconf.rb] + s.mark_version + s.installed_by_version = v('2.2') + end + + _, err = capture_io do + refute Gem.try_activate 'nonexistent' + end + + expected = "Ignoring ext-1 because its extensions are not built. " + + "Try: gem pristine ext-1\n" + + assert_equal expected, err + end + def test_self_use_paths util_ensure_gem_dirs From 80cb4989a6f0eb37d4de63f1bbab6b09dba5459f Mon Sep 17 00:00:00 2001 From: Eric Hodel Date: Mon, 3 Feb 2014 15:27:35 -0800 Subject: [PATCH 230/707] Add ruby_install_name helper RubyGems 2.2.1 causes CI failures on linux due to nil values in RbConfig::CONFIG. This is due to RubyGems setting RbConfig values to nil when they should not be set at all. --- test/rubygems/test_gem.rb | 40 +++++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index ef13c76e..5bc81d92 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -199,30 +199,21 @@ def test_self_datadir_nonexistent_package end def test_self_default_exec_format - orig_RUBY_INSTALL_NAME = RbConfig::CONFIG['ruby_install_name'] - RbConfig::CONFIG['ruby_install_name'] = 'ruby' - - assert_equal '%s', Gem.default_exec_format - ensure - RbConfig::CONFIG['ruby_install_name'] = orig_RUBY_INSTALL_NAME + ruby_install_name 'ruby' do + assert_equal '%s', Gem.default_exec_format + end end def test_self_default_exec_format_18 - orig_RUBY_INSTALL_NAME = RbConfig::CONFIG['ruby_install_name'] - RbConfig::CONFIG['ruby_install_name'] = 'ruby18' - - assert_equal '%s18', Gem.default_exec_format - ensure - RbConfig::CONFIG['ruby_install_name'] = orig_RUBY_INSTALL_NAME + ruby_install_name 'ruby18' do + assert_equal '%s18', Gem.default_exec_format + end end def test_self_default_exec_format_jruby - orig_RUBY_INSTALL_NAME = RbConfig::CONFIG['ruby_install_name'] - RbConfig::CONFIG['ruby_install_name'] = 'jruby' - - assert_equal 'j%s', Gem.default_exec_format - ensure - RbConfig::CONFIG['ruby_install_name'] = orig_RUBY_INSTALL_NAME + ruby_install_name 'jruby' do + assert_equal 'j%s', Gem.default_exec_format + end end def test_self_default_sources @@ -1356,6 +1347,19 @@ def test_use_gemdeps_specific ENV['RUBYGEMS_GEMDEPS'] = rubygems_gemdeps end + def ruby_install_name name + orig_RUBY_INSTALL_NAME = RbConfig::CONFIG['ruby_install_name'] + RbConfig::CONFIG['ruby_install_name'] = name + + yield + ensure + if orig_RUBY_INSTALL_NAME then + RbConfig::CONFIG['ruby_install_name'] = orig_RUBY_INSTALL_NAME + else + RbConfig::CONFIG.delete 'ruby_install_name' + end + end + def with_plugin(path) test_plugin_path = File.expand_path("test/rubygems/plugin/#{path}", @@project_dir) From 73dcb22d4e3915e26e7a04a70bd329814a4e34d5 Mon Sep 17 00:00:00 2001 From: Eric Hodel Date: Mon, 3 Feb 2014 15:33:21 -0800 Subject: [PATCH 231/707] Add ENABLE_SHARED helper See @80cb498 for a description --- test/rubygems/test_gem.rb | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 5bc81d92..c6755a17 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -331,21 +331,15 @@ def test_self_ensure_gem_directories_write_protected_parents end def test_self_extension_dir_shared - enable_shared, RbConfig::CONFIG['ENABLE_SHARED'] = - RbConfig::CONFIG['ENABLE_SHARED'], 'yes' - - assert_equal Gem.ruby_api_version, Gem.extension_api_version - ensure - RbConfig::CONFIG['ENABLE_SHARED'] = enable_shared + enable_shared 'yes' do + assert_equal Gem.ruby_api_version, Gem.extension_api_version + end end def test_self_extension_dir_static - enable_shared, RbConfig::CONFIG['ENABLE_SHARED'] = - RbConfig::CONFIG['ENABLE_SHARED'], 'no' - - assert_equal "#{Gem.ruby_api_version}-static", Gem.extension_api_version - ensure - RbConfig::CONFIG['ENABLE_SHARED'] = enable_shared + enable_shared 'no' do + assert_equal "#{Gem.ruby_api_version}-static", Gem.extension_api_version + end end def test_self_find_files @@ -1347,6 +1341,19 @@ def test_use_gemdeps_specific ENV['RUBYGEMS_GEMDEPS'] = rubygems_gemdeps end + def enable_shared value + enable_shared = RbConfig::CONFIG['ENABLE_SHARED'] + RbConfig::CONFIG['ENABLE_SHARED'] = value + + yield + ensure + if enable_shared then + RbConfig::CONFIG['enable_shared'] = enable_shared + else + RbConfig::CONFIG.delete 'enable_shared' + end + end + def ruby_install_name name orig_RUBY_INSTALL_NAME = RbConfig::CONFIG['ruby_install_name'] RbConfig::CONFIG['ruby_install_name'] = name From ac2e93b6fe9f6d2d5f18b71e61f70d5d41647d79 Mon Sep 17 00:00:00 2001 From: Eric Hodel Date: Mon, 3 Feb 2014 15:43:57 -0800 Subject: [PATCH 232/707] Pull enable_shared helper up to TestCase This functionality can be reused. --- test/rubygems/test_gem.rb | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index c6755a17..0b94e609 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1341,19 +1341,6 @@ def test_use_gemdeps_specific ENV['RUBYGEMS_GEMDEPS'] = rubygems_gemdeps end - def enable_shared value - enable_shared = RbConfig::CONFIG['ENABLE_SHARED'] - RbConfig::CONFIG['ENABLE_SHARED'] = value - - yield - ensure - if enable_shared then - RbConfig::CONFIG['enable_shared'] = enable_shared - else - RbConfig::CONFIG.delete 'enable_shared' - end - end - def ruby_install_name name orig_RUBY_INSTALL_NAME = RbConfig::CONFIG['ruby_install_name'] RbConfig::CONFIG['ruby_install_name'] = name From d395c6917788af2d9f5e8dfa1bf7326c05cee07c Mon Sep 17 00:00:00 2001 From: Eric Hodel Date: Mon, 3 Feb 2014 18:26:00 -0800 Subject: [PATCH 233/707] Restore Gem::Version::new behavior from < 2.1 Gem::Version::new used to return the same class as the input object but now returns a Gem::Version if called with the same input from a subclass. This broke backward compatibility. This broke from #447 which was a performance improvement change. This commit maintains the same behavior except when Gem::Version was subclassed and the version cache (which reduces GC) is skipped. See #447 for the original commits Fixes #805 --- test/rubygems/test_gem_version.rb | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/test/rubygems/test_gem_version.rb b/test/rubygems/test_gem_version.rb index e0499fe7..5a65b5c9 100644 --- a/test/rubygems/test_gem_version.rb +++ b/test/rubygems/test_gem_version.rb @@ -3,6 +3,9 @@ class TestGemVersion < Gem::TestCase + class V < ::Gem::Version + end + def test_bump assert_bumped_version_equal "5.3", "5.2.4" end @@ -37,6 +40,13 @@ def test_class_create assert_equal v('1.1'), Gem::Version.create(ver) end + def test_class_new_subclass + v1 = Gem::Version.new '1' + v2 = V.new '1' + + refute_same v1, v2 + end + def test_eql_eh assert_version_eql "1.2", "1.2" refute_version_eql "1.2", "1.2.0" From 149050505f97fb3b0b9df09119c831a0aaeb22a4 Mon Sep 17 00:00:00 2001 From: Sean Linsley Date: Sat, 22 Feb 2014 21:53:19 -0600 Subject: [PATCH 234/707] Update badges in README to use Shields http://shields.io/ provides many standardized badges for OSS. The PNG versions are similar to the images currently used, but the SVG versions added here are more legible on high pixel density displays. --- bundler/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bundler/README.md b/bundler/README.md index 2117ff5d..ef5a8fe2 100644 --- a/bundler/README.md +++ b/bundler/README.md @@ -1,6 +1,6 @@ -[![Code Climate](https://codeclimate.com/github/bundler/bundler.png)](https://codeclimate.com/github/bundler/bundler) -[![Build Status](https://travis-ci.org/bundler/bundler.png?branch=master)](http://travis-ci.org/bundler/bundler) -Gem Version +[![Code Climate](https://img.shields.io/codeclimate/github/bundler/bundler.svg)](https://codeclimate.com/github/bundler/bundler) +[![Build Status](https://img.shields.io/travis/bundler/bundler/master.svg)](https://travis-ci.org/bundler/bundler) +[![Version ](https://img.shields.io/gem/v/bundler.svg)](https://rubygems.org/gems/bundler) # Bundler: a gem to bundle gems Bundler keeps ruby applications running the same code on every machine. From 4032c567a1bda1b99e3bad733a5507695d4ee30d Mon Sep 17 00:00:00 2001 From: Andre Arko Date: Sun, 20 Apr 2014 21:03:20 -0700 Subject: [PATCH 235/707] add gittip to readme --- bundler/README.md | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/bundler/README.md b/bundler/README.md index ef5a8fe2..0dca3a48 100644 --- a/bundler/README.md +++ b/bundler/README.md @@ -23,18 +23,16 @@ See [bundler.io](http://bundler.io) for the full documentation. For help with common problems, see [ISSUES](https://github.com/bundler/bundler/blob/master/ISSUES.md). -### Contributing - -If you'd like to contribute to Bundler, that's awesome, and we <3 you. There's a guide to contributing to Bundler (both code and general help) over in [DEVELOPMENT](https://github.com/bundler/bundler/blob/master/DEVELOPMENT.md) +### Other questions -The `master` branch contains our current progress towards version 1.5. Versions 1.0-1.3 each have their own stable branches. Please submit bugfixes as pull requests to the stable branch for the version you would like to fix. +To see what has changed in recent versions of Bundler, see the [CHANGELOG](https://github.com/bundler/bundler/blob/master/CHANGELOG.md). -### Core Team +Feel free to chat with the Bundler core team (and many other users) on IRC in the [#bundler](irc://irc.freenode.net/bundler) channel on Freenode, or via email on the [Bundler mailing list](http://groups.google.com/group/ruby-bundler). -The Bundler core team consists of André Arko ([@indirect](http://github.com/indirect)), Terence Lee ([@hone](http://github.com/hone)), and Jessica Lynn Suttles ([@jlsuttles](http://github.com/jlsuttles)), with support and advice from original Bundler author Yehuda Katz ([@wycats](http://github.com/wycats)). +### Contributing -### Other questions +If you'd like to contribute to Bundler, that's awesome, and we <3 you. There's a guide to contributing to Bundler (both code and general help) over in [DEVELOPMENT](https://github.com/bundler/bundler/blob/master/DEVELOPMENT.md) -To see what has changed in recent versions of Bundler, see the [CHANGELOG](https://github.com/bundler/bundler/blob/master/CHANGELOG.md). +### Support work on Bundler -Feel free to chat with the Bundler core team (and many other users) on IRC in the [#bundler](irc://irc.freenode.net/bundler) channel on Freenode, or via email on the [Bundler mailing list](http://groups.google.com/group/ruby-bundler). +Bundler is developed entirely by a team of volunteers. If Bundler saves your company time and money, contribute to the [Bundler development fund on Gittip](http://www.gittip.com/bundler). Every dollar goes towards Bundler documentation, outreach, and development. \ No newline at end of file From 701976abfe36589b390af8c8bc2e9bcc5751d1bf Mon Sep 17 00:00:00 2001 From: Eric Hodel Date: Mon, 21 Apr 2014 14:38:02 -0700 Subject: [PATCH 236/707] Do not raise in Gem.use_gemdeps Gem.use_gemdeps runs before ruby is fully started so RubyGems cannot recover from exceptions it raises. Instead issue a warning suggesting users use `gem install -g` to install the missing gems. --- test/rubygems/test_gem.rb | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 0b94e609..cbe8a8ee 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1322,6 +1322,26 @@ def test_use_gemdeps_disabled ENV['RUBYGEMS_GEMDEPS'] = rubygems_gemdeps end + def test_use_gemdeps_missing_gem + rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], 'x' + + open 'x', 'w' do |io| + io.write 'gem "a"' + end + + expected = <<-EXPECTED +Unable to resolve dependency: user requested 'a (>= 0)' +You may need to `gem install -g` to install missing gems + + EXPECTED + + assert_output nil, expected do + Gem.use_gemdeps + end + ensure + ENV['RUBYGEMS_GEMDEPS'] = rubygems_gemdeps + end + def test_use_gemdeps_specific skip 'Insecure operation - read' if RUBY_VERSION <= "1.8.7" rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], 'x' From 95ee061a5a97c982f0e4039837b4846f3fb8c41d Mon Sep 17 00:00:00 2001 From: Eric Hodel Date: Mon, 21 Apr 2014 14:51:27 -0700 Subject: [PATCH 237/707] Fix test broken on 1.8.7 by @701976a --- test/rubygems/test_gem.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index cbe8a8ee..19981944 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1323,6 +1323,7 @@ def test_use_gemdeps_disabled end def test_use_gemdeps_missing_gem + skip 'Insecure operation - read' if RUBY_VERSION <= "1.8.7" rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], 'x' open 'x', 'w' do |io| From 60d96bd8f38c0b4ec35152bf5b75dce922e01e43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20F=C3=B6hring?= Date: Sat, 26 Apr 2014 19:32:55 +0200 Subject: [PATCH 238/707] Add docs badge to README --- bundler/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bundler/README.md b/bundler/README.md index 0dca3a48..1bab093a 100644 --- a/bundler/README.md +++ b/bundler/README.md @@ -1,6 +1,7 @@ [![Code Climate](https://img.shields.io/codeclimate/github/bundler/bundler.svg)](https://codeclimate.com/github/bundler/bundler) [![Build Status](https://img.shields.io/travis/bundler/bundler/master.svg)](https://travis-ci.org/bundler/bundler) [![Version ](https://img.shields.io/gem/v/bundler.svg)](https://rubygems.org/gems/bundler) +[![Inline docs ](http://inch-pages.github.io/github/bundler/bundler.svg)](http://inch-pages.github.io/github/bundler/bundler) # Bundler: a gem to bundle gems Bundler keeps ruby applications running the same code on every machine. @@ -35,4 +36,4 @@ If you'd like to contribute to Bundler, that's awesome, and we <3 you. There's a ### Support work on Bundler -Bundler is developed entirely by a team of volunteers. If Bundler saves your company time and money, contribute to the [Bundler development fund on Gittip](http://www.gittip.com/bundler). Every dollar goes towards Bundler documentation, outreach, and development. \ No newline at end of file +Bundler is developed entirely by a team of volunteers. If Bundler saves your company time and money, contribute to the [Bundler development fund on Gittip](http://www.gittip.com/bundler). Every dollar goes towards Bundler documentation, outreach, and development. From 49752a5b9d3eb3b0d3194a80820433ba36120e87 Mon Sep 17 00:00:00 2001 From: Andre Arko Date: Sun, 27 Apr 2014 10:32:58 -0700 Subject: [PATCH 239/707] minor readme cleanup [ci skip] --- bundler/README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/bundler/README.md b/bundler/README.md index 1bab093a..ceb2d7b8 100644 --- a/bundler/README.md +++ b/bundler/README.md @@ -1,10 +1,11 @@ -[![Code Climate](https://img.shields.io/codeclimate/github/bundler/bundler.svg)](https://codeclimate.com/github/bundler/bundler) -[![Build Status](https://img.shields.io/travis/bundler/bundler/master.svg)](https://travis-ci.org/bundler/bundler) [![Version ](https://img.shields.io/gem/v/bundler.svg)](https://rubygems.org/gems/bundler) +[![Build Status](https://img.shields.io/travis/bundler/bundler/master.svg)](https://travis-ci.org/bundler/bundler) +[![Code Climate](https://img.shields.io/codeclimate/github/bundler/bundler.svg)](https://codeclimate.com/github/bundler/bundler) [![Inline docs ](http://inch-pages.github.io/github/bundler/bundler.svg)](http://inch-pages.github.io/github/bundler/bundler) # Bundler: a gem to bundle gems -Bundler keeps ruby applications running the same code on every machine. + +Bundler makes sure Ruby applications run the same code on every machine. It does this by managing the gems that the application depends on. Given a list of gems, it can automatically download and install those gems, as well as any other gems needed by the gems that are listed. Before installing gems, it checks the versions of every gem to make sure that they are compatible, and can all be loaded at the same time. After the gems have been installed, Bundler can help you update some or all of them when new versions become available. Finally, it records the exact versions that have been installed, so that others can install the exact same gems. From c3f88cc6697fb02d2b601c1ef13148a15d01c858 Mon Sep 17 00:00:00 2001 From: Eric Hodel Date: Fri, 9 May 2014 15:31:55 -0700 Subject: [PATCH 240/707] Document single-digit behavior of ~> Also, add explicit tests of the zero-extension behavior so nobody breaks it by accident. Fixes #896 --- test/rubygems/test_gem_requirement.rb | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/rubygems/test_gem_requirement.rb b/test/rubygems/test_gem_requirement.rb index 8adaf898..5869ef23 100644 --- a/test/rubygems/test_gem_requirement.rb +++ b/test/rubygems/test_gem_requirement.rb @@ -277,6 +277,11 @@ def test_satisfied_by_eh_boxed refute_satisfied_by "1.1.pre", "~> 1.1" refute_satisfied_by "2.0.a", "~> 1.0" refute_satisfied_by "2.0.a", "~> 2.0" + + refute_satisfied_by "0.9", "~> 1" + assert_satisfied_by "1.0", "~> 1" + assert_satisfied_by "1.1", "~> 1" + refute_satisfied_by "2.0", "~> 1" end def test_satisfied_by_eh_multiple From f81e1b4a0b661596b94ad1d68ce84987ea146174 Mon Sep 17 00:00:00 2001 From: Andre Arko Date: Sat, 17 May 2014 16:09:52 +0100 Subject: [PATCH 241/707] add gittip badge --- bundler/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bundler/README.md b/bundler/README.md index ceb2d7b8..be95794c 100644 --- a/bundler/README.md +++ b/bundler/README.md @@ -2,6 +2,8 @@ [![Build Status](https://img.shields.io/travis/bundler/bundler/master.svg)](https://travis-ci.org/bundler/bundler) [![Code Climate](https://img.shields.io/codeclimate/github/bundler/bundler.svg)](https://codeclimate.com/github/bundler/bundler) [![Inline docs ](http://inch-pages.github.io/github/bundler/bundler.svg)](http://inch-pages.github.io/github/bundler/bundler) +[![Gittip +](http://img.shields.io/gittip/bundler.svg)](http://gittip.com/bundler) # Bundler: a gem to bundle gems From 1e020204f61ca83dc618a0144007c2b3d4aa9de5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20F=C3=B6hring?= Date: Tue, 3 Jun 2014 20:50:25 +0200 Subject: [PATCH 242/707] Update docs badge --- bundler/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundler/README.md b/bundler/README.md index be95794c..5805700e 100644 --- a/bundler/README.md +++ b/bundler/README.md @@ -1,7 +1,7 @@ [![Version ](https://img.shields.io/gem/v/bundler.svg)](https://rubygems.org/gems/bundler) [![Build Status](https://img.shields.io/travis/bundler/bundler/master.svg)](https://travis-ci.org/bundler/bundler) [![Code Climate](https://img.shields.io/codeclimate/github/bundler/bundler.svg)](https://codeclimate.com/github/bundler/bundler) -[![Inline docs ](http://inch-pages.github.io/github/bundler/bundler.svg)](http://inch-pages.github.io/github/bundler/bundler) +[![Inline docs ](http://inch-ci.org/github/bundler/bundler.svg)](http://inch-ci.org/github/bundler/bundler) [![Gittip ](http://img.shields.io/gittip/bundler.svg)](http://gittip.com/bundler) From fe757e4fcd4aaab2c623f97679ba550e23315690 Mon Sep 17 00:00:00 2001 From: Eric Hodel Date: Wed, 4 Jun 2014 15:09:02 -0700 Subject: [PATCH 243/707] Gem.use_gemdeps now allows a path parameter This allows specification of the location of the gem dependencies file without clumsy environment variable manipulation. --- test/rubygems/test_gem.rb | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 19981944..c8897d89 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1268,6 +1268,20 @@ def test_default_gems_use_full_paths end def test_use_gemdeps + spec = util_spec 'a', 1 + + refute spec.activated? + + open 'Gemfile', 'w' do |io| + io.write 'gem "a"' + end + + Gem.use_gemdeps 'Gemfile' + + assert spec.activated? + end + + def test_use_gemdeps_ENV rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], nil spec = util_spec 'a', 1 From 24a12d446547bac30d3d4d818715ed0b0d838128 Mon Sep 17 00:00:00 2001 From: Eric Hodel Date: Wed, 4 Jun 2014 16:39:22 -0700 Subject: [PATCH 244/707] Raise ArgumentError when gem deps file is missing Now that Gem.use_gemdeps prefers an argument it should raise an exception if the file given should not be found. Since the method falls back to the RUBYGEMS_GEMDEPS environment variable (which is used via gem executable stubs) the method does not raise an exception when the argument matches the RUBYGEMS_GEMDEPS environment variable. This is not great because sometimes an exception will not be raised which will be confusing, but it does maintain backwards compatibility. --- test/rubygems/test_gem.rb | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index c8897d89..f0009af4 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1299,6 +1299,15 @@ def test_use_gemdeps_ENV ENV['RUBYGEMS_GEMDEPS'] = rubygems_gemdeps end + def test_use_gemdeps_argument_missing + e = assert_raises ArgumentError do + Gem.use_gemdeps 'gem.deps.rb' + end + + assert_equal 'Unable to find gem dependencies file at gem.deps.rb', + e.message + end + def test_use_gemdeps_automatic skip 'Insecure operation - chdir' if RUBY_VERSION <= "1.8.7" rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], '-' @@ -1318,6 +1327,17 @@ def test_use_gemdeps_automatic ENV['RUBYGEMS_GEMDEPS'] = rubygems_gemdeps end + def test_use_gemdeps_automatic_missing + skip 'Insecure operation - chdir' if RUBY_VERSION <= "1.8.7" + rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], '-' + + Gem.use_gemdeps + + assert true # count + ensure + ENV['RUBYGEMS_GEMDEPS'] = rubygems_gemdeps + end + def test_use_gemdeps_disabled rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], '' From 32b1a4b2be0100abe27afa4b1be89de5baf98e00 Mon Sep 17 00:00:00 2001 From: Eric Hodel Date: Wed, 4 Jun 2014 17:00:27 -0700 Subject: [PATCH 245/707] Consistent exceptions from Gem.use_gemdeps Now an exception is always raised when an argument is given and not found. To maintain compatibility an exception is not raised when the method falls back to the RUBYGEMS_GEMDEPS environment variable. --- test/rubygems/test_gem.rb | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index f0009af4..bee4fa76 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1308,6 +1308,20 @@ def test_use_gemdeps_argument_missing e.message end + def test_use_gemdeps_argument_missing_match_ENV + rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = + ENV['RUBYGEMS_GEMDEPS'], 'gem.deps.rb' + + e = assert_raises ArgumentError do + Gem.use_gemdeps 'gem.deps.rb' + end + + assert_equal 'Unable to find gem dependencies file at gem.deps.rb', + e.message + ensure + ENV['RUBYGEMS_GEMDEPS'] = rubygems_gemdeps + end + def test_use_gemdeps_automatic skip 'Insecure operation - chdir' if RUBY_VERSION <= "1.8.7" rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], '-' From 38589a59e9474695d9af3d3979937b9082bfb40e Mon Sep 17 00:00:00 2001 From: Eric Hodel Date: Wed, 4 Jun 2014 17:28:59 -0700 Subject: [PATCH 246/707] Prefer gem.deps.rb for tests --- test/rubygems/test_gem.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index bee4fa76..502d759f 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1272,11 +1272,11 @@ def test_use_gemdeps refute spec.activated? - open 'Gemfile', 'w' do |io| + open 'gem.deps.rb', 'w' do |io| io.write 'gem "a"' end - Gem.use_gemdeps 'Gemfile' + Gem.use_gemdeps 'gem.deps.rb' assert spec.activated? end @@ -1288,7 +1288,7 @@ def test_use_gemdeps_ENV refute spec.activated? - open 'Gemfile', 'w' do |io| + open 'gem.deps.rb', 'w' do |io| io.write 'gem "a"' end @@ -1359,7 +1359,7 @@ def test_use_gemdeps_disabled refute spec.activated? - open 'Gemfile', 'w' do |io| + open 'gem.deps.rb', 'w' do |io| io.write 'gem "a"' end From 2d16d0699fd122ea51187e7b756a6997655de980 Mon Sep 17 00:00:00 2001 From: Mark Lorenz Date: Thu, 26 Jun 2014 12:16:50 -0400 Subject: [PATCH 247/707] include test for v0.X.X versions For semantic versioning I had expected only exact matches to satisfy, because breaking change can occur at even the patch level. RubyGems does not have any special `satisfied_by?` logic for v0.X.X gems, this patch documents that. --- test/rubygems/test_gem_requirement.rb | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/test/rubygems/test_gem_requirement.rb b/test/rubygems/test_gem_requirement.rb index 5869ef23..6974ff08 100644 --- a/test/rubygems/test_gem_requirement.rb +++ b/test/rubygems/test_gem_requirement.rb @@ -207,6 +207,14 @@ def test_satisfied_by_eh_tilde_gt end end + def test_satisfied_by_eh_tilde_gt_v0 + r = req "~> 0.0.1" + + refute_satisfied_by "0.1.1", r + assert_satisfied_by "0.0.2", r + assert_satisfied_by "0.0.1", r + end + def test_satisfied_by_eh_good assert_satisfied_by "0.2.33", "= 0.2.33" assert_satisfied_by "0.2.34", "> 0.2.33" From 602e3a855ac9c0495034b2ed65cf8e0992ff4140 Mon Sep 17 00:00:00 2001 From: Eric Hodel Date: Tue, 8 Jul 2014 16:53:50 -0700 Subject: [PATCH 248/707] Fix tests on ruby 1.8 --- test/rubygems/test_gem.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 502d759f..d82015fc 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1268,15 +1268,16 @@ def test_default_gems_use_full_paths end def test_use_gemdeps + gem_deps_file = 'gem.deps.rb'.untaint spec = util_spec 'a', 1 refute spec.activated? - open 'gem.deps.rb', 'w' do |io| + open gem_deps_file, 'w' do |io| io.write 'gem "a"' end - Gem.use_gemdeps 'gem.deps.rb' + Gem.use_gemdeps gem_deps_file assert spec.activated? end From b4c06990845bfe6743b054a651128b2576fb4a9e Mon Sep 17 00:00:00 2001 From: Eric Hodel Date: Mon, 14 Jul 2014 14:41:32 -0700 Subject: [PATCH 249/707] Add Gem.vendor_dir Part of #943 --- test/rubygems/test_gem.rb | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index d82015fc..e475f8b3 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -968,6 +968,14 @@ def test_self_user_home_user_drive_and_path end end + def test_self_vendor_dir + expected = + File.join RbConfig::CONFIG['vendordir'], 'gems', + RbConfig::CONFIG['ruby_version'] + + assert_equal expected, Gem.vendor_dir + end + def test_load_plugins skip 'Insecure operation - chdir' if RUBY_VERSION <= "1.8.7" plugin_path = File.join "lib", "rubygems_plugin.rb" From 42d261b6f85266a75de04e26b76e928501891f7f Mon Sep 17 00:00:00 2001 From: Eric Hodel Date: Mon, 14 Jul 2014 15:09:18 -0700 Subject: [PATCH 250/707] Add test for Gem.default_path --- test/rubygems/test_gem.rb | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index e475f8b3..fe7c7f09 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -216,6 +216,20 @@ def test_self_default_exec_format_jruby end end + def test_default_path + FileUtils.rm_rf Gem.user_home + + expected = [Gem.default_dir] + + assert_equal expected, Gem.default_path + end + + def test_default_path_user_home + expected = [Gem.user_dir, Gem.default_dir] + + assert_equal expected, Gem.default_path + end + def test_self_default_sources assert_equal %w[https://rubygems.org/], Gem.default_sources end From 440047ba7d4e103e706dcf1d783f0c15acb3f611 Mon Sep 17 00:00:00 2001 From: Eric Hodel Date: Mon, 14 Jul 2014 15:14:41 -0700 Subject: [PATCH 251/707] Include vendor repository in gem path Now gems installed with --vendor can be used by RubyGems. The vendor directory is only added to the gem path when it exists to reduce both user confusion and calls to stat(2). Part of #943 --- test/rubygems/test_gem.rb | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index fe7c7f09..6a99022f 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -217,17 +217,42 @@ def test_self_default_exec_format_jruby end def test_default_path + orig_vendordir = RbConfig::CONFIG['vendordir'] + RbConfig::CONFIG['vendordir'] = File.join @tempdir, 'vendor' + FileUtils.rm_rf Gem.user_home expected = [Gem.default_dir] assert_equal expected, Gem.default_path + ensure + RbConfig::CONFIG['vendordir'] = orig_vendordir end def test_default_path_user_home + orig_vendordir = RbConfig::CONFIG['vendordir'] + RbConfig::CONFIG['vendordir'] = File.join @tempdir, 'vendor' + expected = [Gem.user_dir, Gem.default_dir] assert_equal expected, Gem.default_path + ensure + RbConfig::CONFIG['vendordir'] = orig_vendordir + end + + def test_default_path_vendor_dir + orig_vendordir = RbConfig::CONFIG['vendordir'] + RbConfig::CONFIG['vendordir'] = File.join @tempdir, 'vendor' + + FileUtils.mkdir_p Gem.vendor_dir + + FileUtils.rm_rf Gem.user_home + + expected = [Gem.default_dir, Gem.vendor_dir] + + assert_equal expected, Gem.default_path + ensure + RbConfig::CONFIG['vendordir'] = orig_vendordir end def test_self_default_sources From 4a7bd73b50819b16e1a17c3a6dddb4ed2832452d Mon Sep 17 00:00:00 2001 From: Eric Hodel Date: Mon, 14 Jul 2014 16:43:27 -0700 Subject: [PATCH 252/707] Allow override of vendor_dir via ENV['GEM_VENDOR'] This allows rvm to use the global gems directory to install gems as vendor gems. Request from @mpapis --- test/rubygems/test_gem.rb | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 6a99022f..157e1eae 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1015,6 +1015,13 @@ def test_self_vendor_dir assert_equal expected, Gem.vendor_dir end + def test_self_vendor_dir_ENV_GEM_VENDOR + ENV['GEM_VENDOR'] = File.join @tempdir, 'vendor', 'gems' + + assert_equal ENV['GEM_VENDOR'], Gem.vendor_dir + refute Gem.vendor_dir.frozen? + end + def test_load_plugins skip 'Insecure operation - chdir' if RUBY_VERSION <= "1.8.7" plugin_path = File.join "lib", "rubygems_plugin.rb" From e5a7afa93646188ab3dccba38c702dbbe2d10663 Mon Sep 17 00:00:00 2001 From: Eric Hodel Date: Wed, 16 Jul 2014 11:56:40 -0700 Subject: [PATCH 253/707] Add test for @0a8b54d --- test/rubygems/test_gem.rb | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 157e1eae..93f66d1d 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -75,6 +75,21 @@ def test_self_finish_resolve_wtf end end + def test_self_install + spec_fetcher do |f| + f.gem 'a', 1 + f.spec 'a', 2 + end + + gemhome2 = "#{@gemhome}2" + + installed = Gem.install 'a', '= 1', :install_dir => gemhome2 + + assert_equal %w[a-1], installed.map { |spec| spec.full_name } + + assert_path_exists File.join(gemhome2, 'gems', 'a-1') + end + def test_require_missing save_loaded_features do assert_raises ::LoadError do From 55e69196f3fd74871f13db1f7d7a87827331e687 Mon Sep 17 00:00:00 2001 From: Eric Hodel Date: Thu, 17 Jul 2014 14:18:42 -0700 Subject: [PATCH 254/707] Disable --vendor when vendordir is missing JRuby does not have any vendor keys in its RbConfig::CONFIG which prevents RubyGems 2.4.0 from installing. Part of #974 --- test/rubygems/test_gem.rb | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 93f66d1d..6ac6f9d6 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1037,6 +1037,15 @@ def test_self_vendor_dir_ENV_GEM_VENDOR refute Gem.vendor_dir.frozen? end + def test_self_vendor_dir_missing + orig_vendordir = RbConfig::CONFIG['vendordir'] + RbConfig::CONFIG.delete 'vendordir' + + assert_nil Gem.vendor_dir + ensure + RbConfig::CONFIG['vendordir'] = orig_vendordir + end + def test_load_plugins skip 'Insecure operation - chdir' if RUBY_VERSION <= "1.8.7" plugin_path = File.join "lib", "rubygems_plugin.rb" From 24ecc3f0ec0e3c3111d5716926e94b4d20be71d8 Mon Sep 17 00:00:00 2001 From: Eric Hodel Date: Thu, 17 Jul 2014 14:42:18 -0700 Subject: [PATCH 255/707] Ignore vendor_dir in default_path when missing If there is no vendor_dir configured in the implementations RbConfig::CONFIG then the vendor directory must be ignored in the default path as well. Fixes #974 --- test/rubygems/test_gem.rb | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 6ac6f9d6..0da28bb9 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -244,6 +244,19 @@ def test_default_path RbConfig::CONFIG['vendordir'] = orig_vendordir end + def test_default_path_missing_vendor + orig_vendordir = RbConfig::CONFIG['vendordir'] + RbConfig::CONFIG.delete 'vendordir' + + FileUtils.rm_rf Gem.user_home + + expected = [Gem.default_dir] + + assert_equal expected, Gem.default_path + ensure + RbConfig::CONFIG['vendordir'] = orig_vendordir + end + def test_default_path_user_home orig_vendordir = RbConfig::CONFIG['vendordir'] RbConfig::CONFIG['vendordir'] = File.join @tempdir, 'vendor' From 178ff1cd5b5cc897d14ee0e3e5b7f4eddd823793 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Arko?= Date: Tue, 29 Jul 2014 13:24:47 -0700 Subject: [PATCH 256/707] flatten badges --- bundler/README.md | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/bundler/README.md b/bundler/README.md index 5805700e..094dfb47 100644 --- a/bundler/README.md +++ b/bundler/README.md @@ -1,9 +1,8 @@ -[![Version ](https://img.shields.io/gem/v/bundler.svg)](https://rubygems.org/gems/bundler) -[![Build Status](https://img.shields.io/travis/bundler/bundler/master.svg)](https://travis-ci.org/bundler/bundler) -[![Code Climate](https://img.shields.io/codeclimate/github/bundler/bundler.svg)](https://codeclimate.com/github/bundler/bundler) -[![Inline docs ](http://inch-ci.org/github/bundler/bundler.svg)](http://inch-ci.org/github/bundler/bundler) +[![Version ](https://img.shields.io/gem/v/bundler.svg?style=flat)](https://rubygems.org/gems/bundler) +[![Build Status](https://img.shields.io/travis/bundler/bundler/master.svg?style=flat)](https://travis-ci.org/bundler/bundler) +[![Code Climate](https://img.shields.io/codeclimate/github/bundler/bundler.svg?style=flat)](https://codeclimate.com/github/bundler/bundler) [![Gittip -](http://img.shields.io/gittip/bundler.svg)](http://gittip.com/bundler) +](http://img.shields.io/gittip/bundler.svg?style=flat)](http://gittip.com/bundler) # Bundler: a gem to bundle gems From d2e81b8b64232f6055516afa86dec492cbc8eff4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20F=C3=B6hring?= Date: Tue, 7 Oct 2014 12:15:10 +0200 Subject: [PATCH 257/707] Add flat docs badge to README [ci skip] --- bundler/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/bundler/README.md b/bundler/README.md index 094dfb47..9fad05e7 100644 --- a/bundler/README.md +++ b/bundler/README.md @@ -1,6 +1,7 @@ [![Version ](https://img.shields.io/gem/v/bundler.svg?style=flat)](https://rubygems.org/gems/bundler) [![Build Status](https://img.shields.io/travis/bundler/bundler/master.svg?style=flat)](https://travis-ci.org/bundler/bundler) [![Code Climate](https://img.shields.io/codeclimate/github/bundler/bundler.svg?style=flat)](https://codeclimate.com/github/bundler/bundler) +[![Inline docs ](http://inch-ci.org/github/bundler/bundler.svg?style=flat)](http://inch-ci.org/github/bundler/bundler) [![Gittip ](http://img.shields.io/gittip/bundler.svg?style=flat)](http://gittip.com/bundler) From 9ca7e6323928e04c6261293012dcc8e48ff7e125 Mon Sep 17 00:00:00 2001 From: Tuomas Kareinen Date: Sun, 16 Nov 2014 01:56:26 +0200 Subject: [PATCH 258/707] Skip pristine install for gems bundled with old Ruby MRI Rubies older than 2.0.0 do not store bundled gem specification files under `default` subdirectory, failing to be recognized as default gems and thus be skipped from pristine installs by Rubygems. We observe that old Ruby stores these gems with a regular pattern in spec's summary field: ``` $ cat ~/.rubies/ruby-1.9.3-p551/lib/ruby/gems/1.9.1/specifications/bigdecimal-1.1.0.gemspec Gem::Specification.new do |s| s.name = "bigdecimal" s.version = "1.1.0" s.summary = "This bigdecimal is bundled with Ruby" s.executables = [] end ``` We use this to detect bundled gems when using old Ruby. This allows us to run pristine install on all gems without errors: ``` $ gem pristine --all Restoring gems to pristine condition... Skipped bigdecimal-1.1.0, it is bundled with Ruby < 2.0.0 Skipped io-console-0.3, it is bundled with Ruby < 2.0.0 Skipped json-1.5.5, it is bundled with Ruby < 2.0.0 ... ``` It's unclear to me if this detection should be combined to `Gem::BasicSpecification#default_gem?` and made available to other commands (such as `gem clean`). --- test/rubygems/test_gem.rb | 31 ------------------------------- 1 file changed, 31 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 0da28bb9..25c21453 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1551,37 +1551,6 @@ def util_exec_gem @abin_path = File.join spec.full_gem_path, spec.bindir, 'abin' end - def util_set_RUBY_VERSION(version, patchlevel = nil, revision = nil) - if Gem.instance_variables.include? :@ruby_version or - Gem.instance_variables.include? '@ruby_version' then - Gem.send :remove_instance_variable, :@ruby_version - end - - @RUBY_VERSION = RUBY_VERSION - @RUBY_PATCHLEVEL = RUBY_PATCHLEVEL if defined?(RUBY_PATCHLEVEL) - @RUBY_REVISION = RUBY_REVISION if defined?(RUBY_REVISION) - - Object.send :remove_const, :RUBY_VERSION - Object.send :remove_const, :RUBY_PATCHLEVEL if defined?(RUBY_PATCHLEVEL) - Object.send :remove_const, :RUBY_REVISION if defined?(RUBY_REVISION) - - Object.const_set :RUBY_VERSION, version - Object.const_set :RUBY_PATCHLEVEL, patchlevel if patchlevel - Object.const_set :RUBY_REVISION, revision if revision - end - - def util_restore_RUBY_VERSION - Object.send :remove_const, :RUBY_VERSION - Object.send :remove_const, :RUBY_PATCHLEVEL if defined?(RUBY_PATCHLEVEL) - Object.send :remove_const, :RUBY_REVISION if defined?(RUBY_REVISION) - - Object.const_set :RUBY_VERSION, @RUBY_VERSION - Object.const_set :RUBY_PATCHLEVEL, @RUBY_PATCHLEVEL if - defined?(@RUBY_PATCHLEVEL) - Object.const_set :RUBY_REVISION, @RUBY_REVISION if - defined?(@RUBY_REVISION) - end - def util_remove_interrupt_command Gem::Commands.send :remove_const, :InterruptCommand if Gem::Commands.const_defined? :InterruptCommand From fbac79f453e4ef2efc87b2df6b3a1a5b9a0267c5 Mon Sep 17 00:00:00 2001 From: Smit Shah Date: Mon, 24 Nov 2014 23:17:58 +0530 Subject: [PATCH 259/707] Add specs to check edgecases for the resolver --- bundler/spec/realworld/edgecases_spec.rb | 35 ++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index 263ac520..67096102 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -35,6 +35,41 @@ expect(out).to include("activemodel 3.0.5") end + it "resolves dependencies correctly" do + install_gemfile <<-G + source "https://rubygems.org" + + gem 'rails', '~> 3.0' + gem 'capybara', '~> 2.2.0' + G + expect(out).to include("rails 3.0.1") + expect(out).to include("capybara 2.2.0") + end + + it "installs the latest version of gxapi_rails" do + install_gemfile <<-G + source "https://rubygems.org" + + gem "sass-rails" + gem "rails", "~> 3" + gem "gxapi_rails" + G + expect(out).to include("gxapi_rails 0.0.6") + end + + it "installs the latest version of i18n" do + install_gemfile <<-G + source "https://rubygems.org" + + gem "i18n", "~> 0.4" + gem "activesupport", "~> 3.0" + gem "activerecord", "~> 3.0" + gem "builder", "~> 2.1.2" + G + expect(out).to include("i18n 0.6.11") + expect(out).to include("activesupport 3.0.5") + end + # https://github.com/bundler/bundler/issues/1500 it "does not fail install because of gem plugins" do realworld_system_gems("open_gem --version 1.4.2", "rake --version 0.9.2") From 26a0b05bc9fc7d1c3d50f1915e6cc91260676d0c Mon Sep 17 00:00:00 2001 From: Eric Hodel Date: Sat, 29 Nov 2014 16:41:59 -0800 Subject: [PATCH 260/707] Match loaded spec for Kernel#gem and Gem.bin_path Previously we looked for newer versions when running Kernel#gem and Gem.bin_path which would lead to executable stubs attempting to use the latest version when RUBYGEMS_GEMDEPS was active or another version had been loaded. Now we first check the loaded (active) specifications against the requirement and check that version against the given dependency. Fixes #1072 --- test/rubygems/test_gem.rb | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 0da28bb9..3909404e 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -112,6 +112,20 @@ def test_require_does_not_glob end end + def test_self_bin_path_active + a1 = util_spec 'a', '1' do |s| + s.executables = ['exec'] + end + + util_spec 'a', '2' do |s| + s.executables = ['exec'] + end + + a1.activate + + assert_match 'a-1/bin/exec', Gem.bin_path('a', 'exec', '>= 0') + end + def test_self_bin_path_no_exec_name e = assert_raises ArgumentError do Gem.bin_path 'a' From 60373b59ad173a98e4a43764599e12fe775c62a3 Mon Sep 17 00:00:00 2001 From: Shannon Skipper Date: Mon, 20 Oct 2014 14:57:05 -0700 Subject: [PATCH 261/707] Suggest a runnable gem pristine command When warning about missing extensions, suggest a `gem pristine` command that is ready to be run. For example, the missing extensions warning for puma v2.9.1 was `Try: gem pristine puma-2.9.1`, which failed. This changes the suggestion to `Try: gem pristine puma --version 2.9.1`, which succeeds. --- test/rubygems/test_gem.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 69dab8bd..47f57abf 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -909,7 +909,7 @@ def test_self_try_activate_missing_extensions end expected = "Ignoring ext-1 because its extensions are not built. " + - "Try: gem pristine ext-1\n" + "Try: gem pristine ext --version 1\n" assert_equal expected, err end From b7ceaeb290d857d499058521ca2049abe4ed5e25 Mon Sep 17 00:00:00 2001 From: Smit Shah Date: Thu, 4 Dec 2014 22:07:39 +0530 Subject: [PATCH 262/707] On conflict, try traversing the dependency tree differently --- bundler/spec/realworld/edgecases_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index 67096102..8451c84a 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -42,8 +42,8 @@ gem 'rails', '~> 3.0' gem 'capybara', '~> 2.2.0' G - expect(out).to include("rails 3.0.1") - expect(out).to include("capybara 2.2.0") + expect(out).to include("rails 3.2.21") + expect(out).to include("capybara 2.2.1") end it "installs the latest version of gxapi_rails" do From 955fb7744aca4f817278032f7a7e2911a7f165cb Mon Sep 17 00:00:00 2001 From: Smit Shah Date: Thu, 4 Dec 2014 22:36:57 +0530 Subject: [PATCH 263/707] New realworld specs depend on ruby >= 1.9.2 --- bundler/spec/realworld/edgecases_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index 8451c84a..000ded4f 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -35,7 +35,7 @@ expect(out).to include("activemodel 3.0.5") end - it "resolves dependencies correctly" do + it "resolves dependencies correctly", :ruby => "1.9" do install_gemfile <<-G source "https://rubygems.org" @@ -46,7 +46,7 @@ expect(out).to include("capybara 2.2.1") end - it "installs the latest version of gxapi_rails" do + it "installs the latest version of gxapi_rails", :ruby => "1.9" do install_gemfile <<-G source "https://rubygems.org" From 77545fda4571e127db9c1639b58e7788c9003873 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Fri, 5 Dec 2014 12:16:29 -0800 Subject: [PATCH 264/707] use Gem.use_paths rather than direct assignment --- test/rubygems/test_gem.rb | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 47f57abf..0428bea2 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1145,7 +1145,7 @@ def test_gem_path_ordering ] tests.each do |_name, _paths, expected| - Gem.paths = { 'GEM_HOME' => _paths.first, 'GEM_PATH' => _paths } + Gem.use_paths _paths.first, _paths Gem::Specification.reset Gem.searcher = nil @@ -1192,10 +1192,7 @@ def test_gem_path_ordering_short install_gem m, :install_dir => Gem.dir install_gem m, :install_dir => Gem.user_dir - Gem.paths = { - 'GEM_HOME' => Gem.dir, - 'GEM_PATH' => [ Gem.dir, Gem.user_dir] - } + Gem.use_paths Gem.dir, [ Gem.dir, Gem.user_dir] assert_equal \ File.join(Gem.dir, "gems", "m-1"), From 86c7115442979d39483e48967bd6f15a65a78da2 Mon Sep 17 00:00:00 2001 From: Smit Shah Date: Mon, 22 Dec 2014 11:41:37 +0530 Subject: [PATCH 265/707] Fixed a broken i18n spec --- bundler/spec/realworld/edgecases_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index 000ded4f..38f8eaae 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -27,7 +27,7 @@ install_gemfile <<-G source :rubygems - gem 'i18n', '~> 0.4' + gem 'i18n', '~> 0.6.0' gem 'activesupport', '~> 3.0' gem 'activerecord', '~> 3.0' gem 'builder', '~> 2.1.2' @@ -61,7 +61,7 @@ install_gemfile <<-G source "https://rubygems.org" - gem "i18n", "~> 0.4" + gem "i18n", "~> 0.6.0" gem "activesupport", "~> 3.0" gem "activerecord", "~> 3.0" gem "builder", "~> 2.1.2" From 110fe4c032df74cae5634449418612c7a3d68f14 Mon Sep 17 00:00:00 2001 From: Smit Shah Date: Mon, 22 Dec 2014 11:41:37 +0530 Subject: [PATCH 266/707] Fixed a broken i18n spec --- bundler/spec/realworld/edgecases_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index 000ded4f..38f8eaae 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -27,7 +27,7 @@ install_gemfile <<-G source :rubygems - gem 'i18n', '~> 0.4' + gem 'i18n', '~> 0.6.0' gem 'activesupport', '~> 3.0' gem 'activerecord', '~> 3.0' gem 'builder', '~> 2.1.2' @@ -61,7 +61,7 @@ install_gemfile <<-G source "https://rubygems.org" - gem "i18n", "~> 0.4" + gem "i18n", "~> 0.6.0" gem "activesupport", "~> 3.0" gem "activerecord", "~> 3.0" gem "builder", "~> 2.1.2" From 4ff99443db270df945b1d128b8b56608063f0f9c Mon Sep 17 00:00:00 2001 From: Smit Shah Date: Mon, 22 Dec 2014 14:05:27 +0530 Subject: [PATCH 267/707] Don't change i18n version of Ruby 1.8 spec --- bundler/spec/realworld/edgecases_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index 38f8eaae..b3d7cf94 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -27,7 +27,7 @@ install_gemfile <<-G source :rubygems - gem 'i18n', '~> 0.6.0' + gem 'i18n', '~> 0.4' gem 'activesupport', '~> 3.0' gem 'activerecord', '~> 3.0' gem 'builder', '~> 2.1.2' From 30765a87f3fc1ad8deb176f785163ef8cf5a9ffa Mon Sep 17 00:00:00 2001 From: Smit Shah Date: Mon, 22 Dec 2014 14:05:27 +0530 Subject: [PATCH 268/707] Don't change i18n version of Ruby 1.8 spec --- bundler/spec/realworld/edgecases_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index 38f8eaae..b3d7cf94 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -27,7 +27,7 @@ install_gemfile <<-G source :rubygems - gem 'i18n', '~> 0.6.0' + gem 'i18n', '~> 0.4' gem 'activesupport', '~> 3.0' gem 'activerecord', '~> 3.0' gem 'builder', '~> 2.1.2' From 9b9a27c57cae3777c44999bdcfcd358d13f48adc Mon Sep 17 00:00:00 2001 From: Tim Moore Date: Mon, 22 Dec 2014 20:46:57 +1100 Subject: [PATCH 269/707] Revert "Don't change i18n version of Ruby 1.8 spec" This reverts commit 7f940849bd0e3ffb1a48433b5d058e51b0d3ae0f. --- bundler/spec/realworld/edgecases_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index b3d7cf94..38f8eaae 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -27,7 +27,7 @@ install_gemfile <<-G source :rubygems - gem 'i18n', '~> 0.4' + gem 'i18n', '~> 0.6.0' gem 'activesupport', '~> 3.0' gem 'activerecord', '~> 3.0' gem 'builder', '~> 2.1.2' From 655ff7c7c2a1f84f3d01aea1edbbb29e1daf8f0d Mon Sep 17 00:00:00 2001 From: Tim Moore Date: Mon, 22 Dec 2014 20:46:57 +1100 Subject: [PATCH 270/707] Revert "Don't change i18n version of Ruby 1.8 spec" This reverts commit 7f940849bd0e3ffb1a48433b5d058e51b0d3ae0f. --- bundler/spec/realworld/edgecases_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index b3d7cf94..38f8eaae 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -27,7 +27,7 @@ install_gemfile <<-G source :rubygems - gem 'i18n', '~> 0.4' + gem 'i18n', '~> 0.6.0' gem 'activesupport', '~> 3.0' gem 'activerecord', '~> 3.0' gem 'builder', '~> 2.1.2' From 18bb1051772796523648ae2b30fd825fb275ec56 Mon Sep 17 00:00:00 2001 From: Eito Katagiri Date: Sun, 18 Jan 2015 00:04:28 +0900 Subject: [PATCH 271/707] fix Gem::Requirement#hash to always compute same hash value When you have: r1 = Gem::Requirement.new('1.0', '2.0') r2 = Gem::Requirement.new('2.0', '1.0') Since `r1 == r2` is `true`, I expect `[r1] - [r2]` returns empty. But, it does not because `r1.hash` and `r2.hash` are different. I think that hash values should be same. `Gem#Requirement#==` returns `true' because `Gem::Requirement#as_list` calls `Array#sort` to sort requirements. I think that `Gem::Requirement#hash` should call `Array#sort` before computing hash value. --- test/rubygems/test_gem_requirement.rb | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/test/rubygems/test_gem_requirement.rb b/test/rubygems/test_gem_requirement.rb index 6974ff08..234edb4e 100644 --- a/test/rubygems/test_gem_requirement.rb +++ b/test/rubygems/test_gem_requirement.rb @@ -347,6 +347,16 @@ def test_bad refute_satisfied_by "1.0.0.1", "= 1.0" end + def test_hash_with_multiple_versions + r1 = req('1.0', '2.0') + r2 = req('2.0', '1.0') + assert_equal r1.hash, r2.hash + + r1 = req('1.0', '2.0').tap { |r| r.concat(['3.0']) } + r2 = req('3.0', '1.0').tap { |r| r.concat(['2.0']) } + assert_equal r1.hash, r2.hash + end + # Assert that two requirements are equal. Handles Gem::Requirements, # strings, arrays, numbers, and versions. From c7ad61c46488a21d767da5dbdc22ce65eee22237 Mon Sep 17 00:00:00 2001 From: Andre Arko Date: Mon, 19 Jan 2015 12:39:03 -0800 Subject: [PATCH 272/707] we can have exitstatus and err at the same time huh, how did I miss this before? --- bundler/spec/realworld/edgecases_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index 38f8eaae..095bbf00 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -206,7 +206,7 @@ activesupport! L - bundle :install, :exitstatus => true + bundle :install expect(exitstatus).to eq(0) end end From 8cb9d8e74800bba682457c2e6f4b1ff8e803c7f9 Mon Sep 17 00:00:00 2001 From: Andre Arko Date: Tue, 20 Jan 2015 22:51:56 -0800 Subject: [PATCH 273/707] =?UTF-8?q?don=E2=80=99t=20test=20exitstatus=20whe?= =?UTF-8?q?n=20it=20is=20unknown?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit apparently on some Ruby 1.8.7 installs, open3 doesn’t return an exit status, and that includes all Travis installs of 1.8.7. :/ these tests all pass (while checking exit status) on my machine, but they shouldn’t fail if the Ruby on Travis isn’t able to provide exitstatuses. --- bundler/spec/realworld/edgecases_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index 095bbf00..15c76975 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -207,6 +207,6 @@ L bundle :install - expect(exitstatus).to eq(0) + expect(exitstatus).to eq(0) if exitstatus end end From 6194731ccbc2d017816e46b923e9cc06b0345c4a Mon Sep 17 00:00:00 2001 From: Andre Arko Date: Thu, 22 Jan 2015 18:37:07 -0800 Subject: [PATCH 274/707] remove obsolete support links --- bundler/README.md | 6 ------ 1 file changed, 6 deletions(-) diff --git a/bundler/README.md b/bundler/README.md index 9fad05e7..1719323a 100644 --- a/bundler/README.md +++ b/bundler/README.md @@ -2,8 +2,6 @@ [![Build Status](https://img.shields.io/travis/bundler/bundler/master.svg?style=flat)](https://travis-ci.org/bundler/bundler) [![Code Climate](https://img.shields.io/codeclimate/github/bundler/bundler.svg?style=flat)](https://codeclimate.com/github/bundler/bundler) [![Inline docs ](http://inch-ci.org/github/bundler/bundler.svg?style=flat)](http://inch-ci.org/github/bundler/bundler) -[![Gittip -](http://img.shields.io/gittip/bundler.svg?style=flat)](http://gittip.com/bundler) # Bundler: a gem to bundle gems @@ -36,7 +34,3 @@ Feel free to chat with the Bundler core team (and many other users) on IRC in th ### Contributing If you'd like to contribute to Bundler, that's awesome, and we <3 you. There's a guide to contributing to Bundler (both code and general help) over in [DEVELOPMENT](https://github.com/bundler/bundler/blob/master/DEVELOPMENT.md) - -### Support work on Bundler - -Bundler is developed entirely by a team of volunteers. If Bundler saves your company time and money, contribute to the [Bundler development fund on Gittip](http://www.gittip.com/bundler). Every dollar goes towards Bundler documentation, outreach, and development. From 5a4a57d7225c9e2c79bdf0cb476257f82735a03f Mon Sep 17 00:00:00 2001 From: Hsing-Hui Hsu Date: Sun, 12 Apr 2015 15:49:20 -0700 Subject: [PATCH 275/707] Make GemDependencyAPI available after .use_gemdeps Previously, the files specified with the `:require` option in a Gemfile were not accesible to plugin authors. Now, the GemDependencyAPI object provides access to them via `Gem.gemdeps.requires`. Fixes #1213 --- test/rubygems/test_gem.rb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 0428bea2..1eb5d296 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1379,9 +1379,12 @@ def test_use_gemdeps io.write 'gem "a"' end + assert_nil Gem.gemdeps + Gem.use_gemdeps gem_deps_file assert spec.activated? + refute_nil Gem.gemdeps end def test_use_gemdeps_ENV From b2a4f5061caf51234acea6ccdeb6d498bf57a019 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Wed, 15 Apr 2015 12:13:49 -0400 Subject: [PATCH 276/707] use the installer to install specs We should use the Installer to install specs. This commit allows the tests to pass without caching all the specs in `@@specs` and gives the tests a more "realistic" view of how gems are installed and used. This means that you must install the specs in the correct order (so that dependencies are met). --- test/rubygems/test_gem.rb | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 1eb5d296..5dd53864 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -37,7 +37,7 @@ def test_self_finish_resolve c1 = new_spec "c", "1" c2 = new_spec "c", "2" - install_specs a1, b1, b2, c1, c2 + install_specs c1, c2, b1, b2, a1 a1.activate @@ -61,7 +61,7 @@ def test_self_finish_resolve_wtf d1 = new_spec "d", "1", { "c" => "< 2" }, "lib/d.rb" d2 = new_spec "d", "2", { "c" => "< 2" }, "lib/d.rb" # this - install_specs a1, b1, b2, c1, c2, d1, d2 + install_specs c1, c2, b1, b2, d1, d2, a1 a1.activate @@ -135,12 +135,12 @@ def test_self_bin_path_no_exec_name end def test_self_bin_path_bin_name - util_exec_gem + install_specs util_exec_gem assert_equal @abin_path, Gem.bin_path('a', 'abin') end def test_self_bin_path_bin_name_version - util_exec_gem + install_specs util_exec_gem assert_equal @abin_path, Gem.bin_path('a', 'abin', '4') end @@ -167,10 +167,11 @@ def test_self_bin_path_not_found end def test_self_bin_path_bin_file_gone_in_latest - util_exec_gem - util_spec 'a', '10' do |s| + install_specs util_exec_gem + spec = util_spec 'a', '10' do |s| s.executables = [] end + install_specs spec # Should not find a-10's non-abin (bug) assert_equal @abin_path, Gem.bin_path('a', 'abin') end @@ -882,8 +883,12 @@ def test_self_sources end def test_self_try_activate_missing_dep + b = util_spec 'b', '1.0' a = util_spec 'a', '1.0', 'b' => '>= 1.0' + install_specs b, a + uninstall_gem b + a_file = File.join a.gem_dir, 'lib', 'a_file.rb' write_file a_file do |io| @@ -944,7 +949,7 @@ def test_self_needs b = util_spec "b", "1", "c" => nil c = util_spec "c", "2" - install_specs a, b, c + install_specs a, c, b Gem.needs do |r| r.gem "a" @@ -966,7 +971,7 @@ def test_self_needs_picks_up_unresolved_deps d = new_spec "d", "1", {'e' => '= 1'}, "lib/d.rb" e = util_spec "e", "1" - install_specs a, b, c, d, e + install_specs a, c, b, e, d Gem.needs do |r| r.gem "a" @@ -1563,6 +1568,7 @@ def util_exec_gem @exec_path = File.join spec.full_gem_path, spec.bindir, 'exec' @abin_path = File.join spec.full_gem_path, spec.bindir, 'abin' + spec end def util_remove_interrupt_command From 0fdbfeeebc23badc89c21f7fe3e0607582c5e5e1 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Mon, 27 Apr 2015 17:21:35 -0700 Subject: [PATCH 277/707] remove calls to add_spec this commit uses the installer for specs that are supposed to be installed rather than mutating the install cache. That way we can just write the files, and reset the cache. This abstracts us from knowing how the cache is built --- test/rubygems/test_gem.rb | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 5dd53864..f2ef0514 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -903,12 +903,17 @@ def test_self_try_activate_missing_dep end def test_self_try_activate_missing_extensions - util_spec 'ext', '1' do |s| + spec = util_spec 'ext', '1' do |s| s.extensions = %w[ext/extconf.rb] s.mark_version s.installed_by_version = v('2.2') end + # write the spec without install to simulate a failed install + write_file spec.spec_file do |io| + io.write spec.to_ruby_for_cache + end + _, err = capture_io do refute Gem.try_activate 'nonexistent' end @@ -1377,7 +1382,9 @@ def test_default_gems_use_full_paths def test_use_gemdeps gem_deps_file = 'gem.deps.rb'.untaint spec = util_spec 'a', 1 + install_specs spec + spec = Gem::Specification.find { |s| s == spec } refute spec.activated? open gem_deps_file, 'w' do |io| @@ -1438,6 +1445,8 @@ def test_use_gemdeps_automatic rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], '-' spec = util_spec 'a', 1 + install_specs spec + spec = Gem::Specification.find { |s| s == spec } refute spec.activated? @@ -1507,7 +1516,9 @@ def test_use_gemdeps_specific rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], 'x' spec = util_spec 'a', 1 + install_specs spec + spec = Gem::Specification.find { |s| s == spec } refute spec.activated? open 'x', 'w' do |io| From ac66134c8ba0983f395510c3be15800bd5531767 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Mon, 4 May 2015 15:20:50 -0700 Subject: [PATCH 278/707] add a test for d3b0914c reverting d3b0914c would not cause any tests to fail, so this commit adds a test surrounding that behavior --- test/rubygems/test_gem.rb | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index f2ef0514..4c83738c 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -882,6 +882,16 @@ def test_self_sources assert_equal %w[http://gems.example.com/], Gem.sources end + def test_try_activate_returns_true_for_activated_specs + b = util_spec 'b', '1.0' do |spec| + spec.files << 'lib/b.rb' + end + install_specs b + + assert Gem.try_activate('b'), 'try_activate should return true' + assert Gem.try_activate('b'), 'try_activate should still return true' + end + def test_self_try_activate_missing_dep b = util_spec 'b', '1.0' a = util_spec 'a', '1.0', 'b' => '>= 1.0' From 525655e80730ee7fc4146030c703de02f1d3fa34 Mon Sep 17 00:00:00 2001 From: Andre Arko Date: Sun, 10 May 2015 20:51:12 -0700 Subject: [PATCH 279/707] run 1.8 specs only on 1.8.x, etc --- bundler/spec/realworld/edgecases_spec.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index 15c76975..85c6784f 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -2,7 +2,7 @@ describe "real world edgecases", :realworld => true do # there is no rbx-relative-require gem that will install on 1.9 - it "ignores extra gems with bad platforms", :ruby => "1.8" do + it "ignores extra gems with bad platforms", :ruby => "~> 1.8" do install_gemfile <<-G source :rubygems gem "linecache", "0.46" @@ -11,7 +11,7 @@ end # https://github.com/bundler/bundler/issues/1202 - it "bundle cache works with rubygems 1.3.7 and pre gems", :ruby => "1.8" do + it "bundle cache works with rubygems 1.3.7 and pre gems", :ruby => "~> 1.8" do install_gemfile <<-G source :rubygems gem "rack", "1.3.0.beta2" @@ -23,7 +23,7 @@ # https://github.com/bundler/bundler/issues/1486 # this is a hash collision that only manifests on 1.8.7 - it "finds the correct child versions", :ruby => "1.8" do + it "finds the correct child versions", :ruby => "~> 1.8" do install_gemfile <<-G source :rubygems From 2d153752e6a18c0e100aec4ddea5c15bf485df4e Mon Sep 17 00:00:00 2001 From: Andre Arko Date: Mon, 18 May 2015 12:48:40 -0700 Subject: [PATCH 280/707] run edge case specs only where it makes sense to --- bundler/spec/realworld/edgecases_spec.rb | 31 ++++++++++++------------ 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index 85c6784f..e492dbc1 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -2,7 +2,7 @@ describe "real world edgecases", :realworld => true do # there is no rbx-relative-require gem that will install on 1.9 - it "ignores extra gems with bad platforms", :ruby => "~> 1.8" do + it "ignores extra gems with bad platforms", :ruby => "~> 1.8.7" do install_gemfile <<-G source :rubygems gem "linecache", "0.46" @@ -11,7 +11,8 @@ end # https://github.com/bundler/bundler/issues/1202 - it "bundle cache works with rubygems 1.3.7 and pre gems", :ruby => "~> 1.8" do + it "bundle cache works with rubygems 1.3.7 and pre gems", + :ruby => "~> 1.8.7", :rubygems => "~> 1.3.7" do install_gemfile <<-G source :rubygems gem "rack", "1.3.0.beta2" @@ -23,7 +24,7 @@ # https://github.com/bundler/bundler/issues/1486 # this is a hash collision that only manifests on 1.8.7 - it "finds the correct child versions", :ruby => "~> 1.8" do + it "finds the correct child versions", :ruby => "~> 1.8.7" do install_gemfile <<-G source :rubygems @@ -37,10 +38,10 @@ it "resolves dependencies correctly", :ruby => "1.9" do install_gemfile <<-G - source "https://rubygems.org" + source "https://rubygems.org" - gem 'rails', '~> 3.0' - gem 'capybara', '~> 2.2.0' + gem 'rails', '~> 3.0' + gem 'capybara', '~> 2.2.0' G expect(out).to include("rails 3.2.21") expect(out).to include("capybara 2.2.1") @@ -48,23 +49,23 @@ it "installs the latest version of gxapi_rails", :ruby => "1.9" do install_gemfile <<-G - source "https://rubygems.org" + source "https://rubygems.org" - gem "sass-rails" - gem "rails", "~> 3" - gem "gxapi_rails" + gem "sass-rails" + gem "rails", "~> 3" + gem "gxapi_rails" G expect(out).to include("gxapi_rails 0.0.6") end it "installs the latest version of i18n" do install_gemfile <<-G - source "https://rubygems.org" + source "https://rubygems.org" - gem "i18n", "~> 0.6.0" - gem "activesupport", "~> 3.0" - gem "activerecord", "~> 3.0" - gem "builder", "~> 2.1.2" + gem "i18n", "~> 0.6.0" + gem "activesupport", "~> 3.0" + gem "activerecord", "~> 3.0" + gem "builder", "~> 2.1.2" G expect(out).to include("i18n 0.6.11") expect(out).to include("activesupport 3.0.5") From bbf3fb37b354802dc9d44c70194f0257aa83f442 Mon Sep 17 00:00:00 2001 From: "Samuel E. Giddins" Date: Sun, 31 May 2015 20:25:15 -0700 Subject: [PATCH 281/707] [EdgecasesSpec] Dont run specs that require i18n on 1.9.2 --- bundler/spec/realworld/edgecases_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index e492dbc1..6ec2719e 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -36,7 +36,7 @@ expect(out).to include("activemodel 3.0.5") end - it "resolves dependencies correctly", :ruby => "1.9" do + it "resolves dependencies correctly", :ruby => "1.9.3" do install_gemfile <<-G source "https://rubygems.org" @@ -47,7 +47,7 @@ expect(out).to include("capybara 2.2.1") end - it "installs the latest version of gxapi_rails", :ruby => "1.9" do + it "installs the latest version of gxapi_rails", :ruby => "1.9.3" do install_gemfile <<-G source "https://rubygems.org" From a2e789ac293ad56a0abed9755de25b3db7887187 Mon Sep 17 00:00:00 2001 From: Waynn Lue Date: Tue, 9 Jun 2015 14:56:29 -0700 Subject: [PATCH 282/707] missing period at end of README --- bundler/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundler/README.md b/bundler/README.md index 1719323a..55eb6e80 100644 --- a/bundler/README.md +++ b/bundler/README.md @@ -33,4 +33,4 @@ Feel free to chat with the Bundler core team (and many other users) on IRC in th ### Contributing -If you'd like to contribute to Bundler, that's awesome, and we <3 you. There's a guide to contributing to Bundler (both code and general help) over in [DEVELOPMENT](https://github.com/bundler/bundler/blob/master/DEVELOPMENT.md) +If you'd like to contribute to Bundler, that's awesome, and we <3 you. There's a guide to contributing to Bundler (both code and general help) over in [DEVELOPMENT](https://github.com/bundler/bundler/blob/master/DEVELOPMENT.md). From 2cbdada8c2cd4be999ccfe76988f600eb665891d Mon Sep 17 00:00:00 2001 From: Patrick Metcalfe Date: Tue, 16 Jun 2015 15:39:48 -0500 Subject: [PATCH 283/707] update rails version in specs https://github.com/rails/rails/releases/tag/v3.2.22 --- bundler/spec/realworld/edgecases_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index 6ec2719e..3e58b477 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -43,7 +43,7 @@ gem 'rails', '~> 3.0' gem 'capybara', '~> 2.2.0' G - expect(out).to include("rails 3.2.21") + expect(out).to include("rails 3.2.22") expect(out).to include("capybara 2.2.1") end From f2d3670de92079656a3ee26b17a44456141200a8 Mon Sep 17 00:00:00 2001 From: "Samuel E. Giddins" Date: Tue, 16 Jun 2015 17:58:03 -0700 Subject: [PATCH 284/707] Merge pull request #3747 from pducks32/update-rails-version update rails version in specs --- bundler/spec/realworld/edgecases_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index 15c76975..c0b2e24f 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -42,7 +42,7 @@ gem 'rails', '~> 3.0' gem 'capybara', '~> 2.2.0' G - expect(out).to include("rails 3.2.21") + expect(out).to include("rails 3.2.22") expect(out).to include("capybara 2.2.1") end From 45863ea160de50e6801b971892a50e4cf25088d2 Mon Sep 17 00:00:00 2001 From: Andre Arko Date: Tue, 23 Jun 2015 22:56:52 -0700 Subject: [PATCH 285/707] link to code of conduct from readme --- bundler/README.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/bundler/README.md b/bundler/README.md index 1719323a..ca49937d 100644 --- a/bundler/README.md +++ b/bundler/README.md @@ -14,9 +14,9 @@ It does this by managing the gems that the application depends on. Given a list ``` gem install bundler bundle init -echo "gem 'rails'" >> Gemfile +echo 'gem "rspec"' >> Gemfile bundle install -bundle exec rails new myapp +bundle exec rspec ``` See [bundler.io](http://bundler.io) for the full documentation. @@ -34,3 +34,7 @@ Feel free to chat with the Bundler core team (and many other users) on IRC in th ### Contributing If you'd like to contribute to Bundler, that's awesome, and we <3 you. There's a guide to contributing to Bundler (both code and general help) over in [DEVELOPMENT](https://github.com/bundler/bundler/blob/master/DEVELOPMENT.md) + +### Code of Conduct + +Everyone interacting in the Bundler project’s codebases, issue trackers, chat rooms, and mailing lists is expected to follow the [Bundler code of conduct](https://github.com/bundler/bundler/blob/master/CODE_OF_CONDUCT.md). \ No newline at end of file From 0011fbf70646319fc02a3fad6c2a71cada6ac0c0 Mon Sep 17 00:00:00 2001 From: "Samuel E. Giddins" Date: Mon, 29 Jun 2015 09:11:54 -0700 Subject: [PATCH 286/707] Add test for being able to Gem.install inside a rescue block --- test/rubygems/test_gem.rb | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 4c83738c..0c5ac51f 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -90,6 +90,23 @@ def test_self_install assert_path_exists File.join(gemhome2, 'gems', 'a-1') end + def test_self_install_in_rescue + spec_fetcher do |f| + f.gem 'a', 1 + f.spec 'a', 2 + end + + gemhome2 = "#{@gemhome}2" + + installed = + begin + raise 'Error' + rescue StandardError + Gem.install 'a', '= 1', :install_dir => gemhome2 + end + assert_equal %w[a-1], installed.map { |spec| spec.full_name } + end + def test_require_missing save_loaded_features do assert_raises ::LoadError do From f422fcb124e3a194a8dc5e6d6677dced023e7476 Mon Sep 17 00:00:00 2001 From: "Samuel E. Giddins" Date: Wed, 15 Jul 2015 20:52:48 -0700 Subject: [PATCH 287/707] [RuboCop] Enable Style/StringLiterals --- bundler/spec/realworld/edgecases_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index 3e58b477..028c30c2 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -1,4 +1,4 @@ -require 'spec_helper' +require "spec_helper" describe "real world edgecases", :realworld => true do # there is no rbx-relative-require gem that will install on 1.9 From c75b8a3240df2b9d37032079d6467cde683da509 Mon Sep 17 00:00:00 2001 From: Erick Sasse Date: Tue, 28 Jul 2015 21:00:30 -0300 Subject: [PATCH 288/707] Fix Style/AlignParameters --- bundler/spec/realworld/edgecases_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index 028c30c2..57d03282 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -12,7 +12,7 @@ # https://github.com/bundler/bundler/issues/1202 it "bundle cache works with rubygems 1.3.7 and pre gems", - :ruby => "~> 1.8.7", :rubygems => "~> 1.3.7" do + :ruby => "~> 1.8.7", :rubygems => "~> 1.3.7" do install_gemfile <<-G source :rubygems gem "rack", "1.3.0.beta2" From b0e7c779748c34e48fb8b354f84463323340979c Mon Sep 17 00:00:00 2001 From: Andre Arko Date: Wed, 29 Jul 2015 21:41:18 -0700 Subject: [PATCH 289/707] retry tests that hit rubygems.org up to 5 times --- bundler/spec/realworld/edgecases_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index 028c30c2..008eab28 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -1,6 +1,6 @@ require "spec_helper" -describe "real world edgecases", :realworld => true do +describe "real world edgecases", :realworld => true, :sometimes => true do # there is no rbx-relative-require gem that will install on 1.9 it "ignores extra gems with bad platforms", :ruby => "~> 1.8.7" do install_gemfile <<-G From c4b6f294fee0cbf6380525a9868cb75b7e85d504 Mon Sep 17 00:00:00 2001 From: "Samuel E. Giddins" Date: Fri, 7 Aug 2015 23:29:21 -0700 Subject: [PATCH 290/707] [RuboCop] Update to 0.33.0 --- bundler/spec/realworld/edgecases_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index 1af311e2..89c313ea 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -47,7 +47,7 @@ expect(out).to include("capybara 2.2.1") end - it "installs the latest version of gxapi_rails", :ruby => "1.9.3" do + it "installs the latest version of gxapi_rails", :ruby => "1.9.3" do install_gemfile <<-G source "https://rubygems.org" From 13ca2da1b667ab9ceb49840216bd620154f360a6 Mon Sep 17 00:00:00 2001 From: Gavin Miller Date: Sun, 16 Aug 2015 19:05:25 -0600 Subject: [PATCH 291/707] Surround LIB_PATH with quotes to prevent directory errors When running tests that has a pwd that includes brackets () these tests will fail. --- test/rubygems/test_gem.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 0c5ac51f..1bcff8c2 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1311,7 +1311,7 @@ def test_looks_for_gemdeps_files_automatically_on_start ENV['GEM_PATH'] = path ENV['RUBYGEMS_GEMDEPS'] = "-" - out = `#{Gem.ruby.dup.untaint} -I #{LIB_PATH.untaint} -rubygems -e "p Gem.loaded_specs.values.map(&:full_name).sort"` + out = `#{Gem.ruby.dup.untaint} -I "#{LIB_PATH.untaint}" -rubygems -e "p Gem.loaded_specs.values.map(&:full_name).sort"` assert_equal '["a-1", "b-1", "c-1"]', out.strip end @@ -1343,7 +1343,7 @@ def test_looks_for_gemdeps_files_automatically_on_start_in_parent_dir Dir.mkdir "sub1" out = Dir.chdir "sub1" do - `#{Gem.ruby.dup.untaint} -I #{LIB_PATH.untaint} -rubygems -e "p Gem.loaded_specs.values.map(&:full_name).sort"` + `#{Gem.ruby.dup.untaint} -I "#{LIB_PATH.untaint}" -rubygems -e "p Gem.loaded_specs.values.map(&:full_name).sort"` end Dir.rmdir "sub1" From b18a8a7ce144c6ff095ea2277694f9156b30a391 Mon Sep 17 00:00:00 2001 From: Andre Arko Date: Tue, 6 Oct 2015 18:36:56 -0700 Subject: [PATCH 292/707] force a rack-cache version that works on ruby 1.9 --- bundler/spec/realworld/edgecases_spec.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index 89c313ea..bff69d1f 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -42,6 +42,7 @@ gem 'rails', '~> 3.0' gem 'capybara', '~> 2.2.0' + gem 'rack-cache', '1.2.0' # last version that works on Ruby 1.9 G expect(out).to include("rails 3.2.22") expect(out).to include("capybara 2.2.1") @@ -54,6 +55,7 @@ gem "sass-rails" gem "rails", "~> 3" gem "gxapi_rails" + gem 'rack-cache', '1.2.0' # last version that works on Ruby 1.9 G expect(out).to include("gxapi_rails 0.0.6") end From 801a8af1372ec1d149837f232312d695316e58c2 Mon Sep 17 00:00:00 2001 From: Andre Arko Date: Tue, 6 Oct 2015 18:37:23 -0700 Subject: [PATCH 293/707] update edge cases to only lock if possible this speeds up these tests by a huge amount, since we stop downloading and installing a crapton of gems live over the internet --- bundler/spec/realworld/edgecases_spec.rb | 38 ++++++++++++++---------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index bff69d1f..8b977f82 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -3,18 +3,20 @@ describe "real world edgecases", :realworld => true, :sometimes => true do # there is no rbx-relative-require gem that will install on 1.9 it "ignores extra gems with bad platforms", :ruby => "~> 1.8.7" do - install_gemfile <<-G - source :rubygems + gemfile <<-G + source "https://rubygems.org" gem "linecache", "0.46" G + bundle :lock expect(err).to eq("") + expect(exitstatus).to eq(0) if exitstatus end # https://github.com/bundler/bundler/issues/1202 it "bundle cache works with rubygems 1.3.7 and pre gems", - :ruby => "~> 1.8.7", :rubygems => "~> 1.3.7" do + :ruby => "~> 1.8.7", "https://rubygems.org" => "~> 1.3.7" do install_gemfile <<-G - source :rubygems + source "https://rubygems.org" gem "rack", "1.3.0.beta2" gem "will_paginate", "3.0.pre2" G @@ -25,27 +27,29 @@ # https://github.com/bundler/bundler/issues/1486 # this is a hash collision that only manifests on 1.8.7 it "finds the correct child versions", :ruby => "~> 1.8.7" do - install_gemfile <<-G - source :rubygems + gemfile <<-G + source "https://rubygems.org" gem 'i18n', '~> 0.6.0' gem 'activesupport', '~> 3.0' gem 'activerecord', '~> 3.0' gem 'builder', '~> 2.1.2' G - expect(out).to include("activemodel 3.0.5") + bundle :lock + expect(lockfile).to include("activemodel (3.0.5)") end it "resolves dependencies correctly", :ruby => "1.9.3" do - install_gemfile <<-G + gemfile <<-G source "https://rubygems.org" gem 'rails', '~> 3.0' gem 'capybara', '~> 2.2.0' gem 'rack-cache', '1.2.0' # last version that works on Ruby 1.9 G - expect(out).to include("rails 3.2.22") - expect(out).to include("capybara 2.2.1") + bundle :lock + expect(lockfile).to include("rails (3.2.22)") + expect(lockfile).to include("capybara (2.2.1)") end it "installs the latest version of gxapi_rails", :ruby => "1.9.3" do @@ -61,7 +65,7 @@ end it "installs the latest version of i18n" do - install_gemfile <<-G + gemfile <<-G source "https://rubygems.org" gem "i18n", "~> 0.6.0" @@ -69,15 +73,16 @@ gem "activerecord", "~> 3.0" gem "builder", "~> 2.1.2" G - expect(out).to include("i18n 0.6.11") - expect(out).to include("activesupport 3.0.5") + bundle :lock + expect(lockfile).to include("i18n (0.6.11)") + expect(lockfile).to include("activesupport (3.0.5)") end # https://github.com/bundler/bundler/issues/1500 it "does not fail install because of gem plugins" do realworld_system_gems("open_gem --version 1.4.2", "rake --version 0.9.2") gemfile <<-G - source :rubygems + source "https://rubygems.org" gem 'rack', '1.0.1' G @@ -89,7 +94,7 @@ it "checks out git repos when the lockfile is corrupted" do gemfile <<-G - source :rubygems + source "https://rubygems.org" gem 'activerecord', :github => 'carlhuda/rails-bundler-test', :branch => 'master' gem 'activesupport', :github => 'carlhuda/rails-bundler-test', :branch => 'master' @@ -209,7 +214,8 @@ activesupport! L - bundle :install + bundle :lock + expect(err).to eq("") expect(exitstatus).to eq(0) if exitstatus end end From 8f7adb05962c420fce29fd88b2bd7b53af753cc1 Mon Sep 17 00:00:00 2001 From: Samuel Giddins Date: Thu, 26 Nov 2015 11:42:51 -0600 Subject: [PATCH 294/707] Fix edgecases spec for new gxapi_rails version --- bundler/spec/realworld/edgecases_spec.rb | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index 8b977f82..6b8d38a4 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -53,15 +53,16 @@ end it "installs the latest version of gxapi_rails", :ruby => "1.9.3" do - install_gemfile <<-G + gemfile <<-G source "https://rubygems.org" gem "sass-rails" gem "rails", "~> 3" - gem "gxapi_rails" + gem "gxapi_rails", "< 0.1.0" # 0.1.0 was released way after the test was written gem 'rack-cache', '1.2.0' # last version that works on Ruby 1.9 G - expect(out).to include("gxapi_rails 0.0.6") + bundle :lock + expect(lockfile).to include("gxapi_rails (0.0.6)") end it "installs the latest version of i18n" do From fb8193080eb36b30aaf5d6949fd0abcbb93ae5d5 Mon Sep 17 00:00:00 2001 From: Samuel Giddins Date: Mon, 25 Jan 2016 16:01:36 -0600 Subject: [PATCH 295/707] Update realworld rails edgecase spec to 3.2.22.1 --- bundler/spec/realworld/edgecases_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index 6b8d38a4..fd82c506 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -48,7 +48,7 @@ gem 'rack-cache', '1.2.0' # last version that works on Ruby 1.9 G bundle :lock - expect(lockfile).to include("rails (3.2.22)") + expect(lockfile).to include("rails (3.2.22.1)") expect(lockfile).to include("capybara (2.2.1)") end From 0f6633049ffcf68eea4337caa5d7176791350435 Mon Sep 17 00:00:00 2001 From: Samuel Giddins Date: Wed, 9 Dec 2015 16:46:31 -0600 Subject: [PATCH 296/707] Support running with frozen string literals --- test/rubygems/test_gem.rb | 2 +- test/rubygems/test_gem_version.rb | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 1bcff8c2..aec9d98c 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1284,7 +1284,7 @@ def test_auto_activation_of_detected_gemdeps_file assert_equal [a,b,c], Gem.detect_gemdeps.sort_by { |s| s.name } end - LIB_PATH = File.expand_path "../../../lib".untaint, __FILE__.untaint + LIB_PATH = File.expand_path "../../../lib".dup.untaint, __FILE__.dup.untaint def test_looks_for_gemdeps_files_automatically_on_start util_clear_gems diff --git a/test/rubygems/test_gem_version.rb b/test/rubygems/test_gem_version.rb index 5a65b5c9..53e2020a 100644 --- a/test/rubygems/test_gem_version.rb +++ b/test/rubygems/test_gem_version.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true require 'rubygems/test_case' require "rubygems/version" From bba8a551aba2feacee6852ca55bf27d4b8623d48 Mon Sep 17 00:00:00 2001 From: Samuel Giddins Date: Wed, 9 Dec 2015 16:46:31 -0600 Subject: [PATCH 297/707] Support running with frozen string literals --- test/rubygems/test_gem_requirement.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/test/rubygems/test_gem_requirement.rb b/test/rubygems/test_gem_requirement.rb index 234edb4e..c1100098 100644 --- a/test/rubygems/test_gem_requirement.rb +++ b/test/rubygems/test_gem_requirement.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true require 'rubygems/test_case' require "rubygems/requirement" From 761292ff53bac0af7cd941f026d7c73621e7cb9f Mon Sep 17 00:00:00 2001 From: Michal Papis Date: Mon, 25 May 2015 14:46:59 +0200 Subject: [PATCH 298/707] find_files only from loaded_gems when using gemdeps --- test/rubygems/test_gem.rb | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 1bcff8c2..f786a888 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -473,6 +473,45 @@ def test_self_find_files assert_equal cwd, $LOAD_PATH.shift end + def test_self_find_files_with_gemfile + # write_file(File.join Dir.pwd, 'Gemfile') fails on travis 1.8.7 with $SAFE=1 + skip if RUBY_VERSION <= "1.8.7" + + cwd = File.expand_path("test/rubygems", @@project_dir) + $LOAD_PATH.unshift cwd + + discover_path = File.join 'lib', 'sff', 'discover.rb' + + foo1, _ = %w(1 2).map { |version| + spec = quick_gem 'sff', version do |s| + s.files << discover_path + end + + write_file(File.join 'gems', spec.full_name, discover_path) do |fp| + fp.puts "# #{spec.full_name}" + end + + spec + } + Gem.refresh + + write_file(File.join Dir.pwd, 'Gemfile') do |fp| + fp.puts "source 'https://rubygems.org'" + fp.puts "gem '#{foo1.name}', '#{foo1.version}'" + end + Gem.use_gemdeps(File.join Dir.pwd, 'Gemfile') + + expected = [ + File.expand_path('test/rubygems/sff/discover.rb', @@project_dir), + File.join(foo1.full_gem_path, discover_path) + ] + + assert_equal expected, Gem.find_files('sff/discover') + assert_equal expected, Gem.find_files('sff/**.rb'), '[ruby-core:31730]' + ensure + assert_equal cwd, $LOAD_PATH.shift unless RUBY_VERSION <= "1.8.7" + end + def test_self_find_latest_files cwd = File.expand_path("test/rubygems", @@project_dir) $LOAD_PATH.unshift cwd From 917f6413c87042a75856bf55d518af6cb2b8dd0c Mon Sep 17 00:00:00 2001 From: Samuel Giddins Date: Sun, 31 Jan 2016 11:29:09 -0600 Subject: [PATCH 299/707] Compatibility with frozen string literals --- bundler/spec/realworld/edgecases_spec.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index fd82c506..8295669d 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -1,3 +1,4 @@ +# frozen_string_literal: true require "spec_helper" describe "real world edgecases", :realworld => true, :sometimes => true do From 5436b1d06738d830355d77ddba49d87f0694ed06 Mon Sep 17 00:00:00 2001 From: Ben Dean Date: Wed, 10 Feb 2016 12:29:52 -0500 Subject: [PATCH 300/707] add failing test to show why `@segments` should be frozen --- test/rubygems/test_gem_version.rb | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/test/rubygems/test_gem_version.rb b/test/rubygems/test_gem_version.rb index 53e2020a..9898669c 100644 --- a/test/rubygems/test_gem_version.rb +++ b/test/rubygems/test_gem_version.rb @@ -146,6 +146,14 @@ def test_semver assert_less_than "1.0.0-1", "1" end + # modifying the segments of a version should not affect the segments of the cached version object + def test_segments + v('9.8.7').segments[2] += 1 + + refute_version_equal "9.8.8", "9.8.7" + assert_equal [9,8,7], v("9.8.7").segments + end + # Asserts that +version+ is a prerelease. def assert_prerelease version From 5bf3a811eebbf3d10bda07636eb55bb508c595b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zolt=C3=A1n=20Heged=C3=BCs?= Date: Thu, 18 Feb 2016 15:53:29 +0100 Subject: [PATCH 301/707] raise error if find_by_name returns with nil --- test/rubygems/test_gem.rb | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index aec9d98c..a910c9e8 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -929,6 +929,26 @@ def test_self_try_activate_missing_dep assert_match %r%Could not find 'b' %, e.message end + def test_self_try_activate_missing_prerelease + b = util_spec 'b', '1.0rc1' + a = util_spec 'a', '1.0rc1', 'b' => '1.0rc1' + + install_specs b, a + uninstall_gem b + + a_file = File.join a.gem_dir, 'lib', 'a_file.rb' + + write_file a_file do |io| + io.puts '# a_file.rb' + end + + e = assert_raises Gem::LoadError do + Gem.try_activate 'a_file' + end + + assert_match %r%Could not find 'b' \(= 1.0rc1\)%, e.message + end + def test_self_try_activate_missing_extensions spec = util_spec 'ext', '1' do |s| s.extensions = %w[ext/extconf.rb] From d5d39b6eeab4e5079b844c302f8c655cc873df08 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Fri, 26 Feb 2016 12:03:08 -0800 Subject: [PATCH 302/707] ensure `default_path` and `home` are set for paths When calling `use_paths` with nil values, `home` should be set to `Gem.default_dir`, and `path` should be the default dir *plus* the home dir. Fixes #1510 --- test/rubygems/test_gem.rb | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 10f637f1..94b1863d 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1010,6 +1010,17 @@ def test_self_try_activate_missing_extensions assert_equal expected, err end + def test_self_use_paths_with_nils + orig_home = ENV.delete 'GEM_HOME' + orig_path = ENV.delete 'GEM_PATH' + Gem.use_paths nil, nil + assert_equal Gem.default_dir, Gem.paths.home + assert_equal (Gem.default_path + [Gem.paths.home]).uniq, Gem.paths.path + ensure + ENV['GEM_HOME'] = orig_home + ENV['GEM_PATH'] = orig_path + end + def test_self_use_paths util_ensure_gem_dirs From fb5d6055d2329a57e3df654682c93a9026869504 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Fri, 26 Feb 2016 16:19:25 -0800 Subject: [PATCH 303/707] restore but deprecate support for Array values on `Gem.paths=` Some users (most notably Spring users with generated bin files) are passing Arrays as values in the hash to `Gem.paths=`. This commit restores support for Array values but issues a deprecation warning. The point is to warn people about their broken code, but allow RubyGems to continue to work, thus reducing "upgrade friction". --- test/rubygems/test_gem.rb | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 94b1863d..aa57261d 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1021,6 +1021,34 @@ def test_self_use_paths_with_nils ENV['GEM_PATH'] = orig_path end + def test_setting_paths_does_not_warn_about_unknown_keys + stdout, stderr = capture_io do + Gem.paths = { 'foo' => [], + 'bar' => Object.new, + 'GEM_HOME' => Gem.paths.home, + 'GEM_PATH' => 'foo' } + end + assert_equal ['foo', Gem.paths.home], Gem.paths.path + assert_equal '', stderr + assert_equal '', stdout + end + + def test_setting_paths_does_not_mutate_parameter_object + Gem.paths = { 'GEM_HOME' => Gem.paths.home, + 'GEM_PATH' => 'foo' }.freeze + assert_equal ['foo', Gem.paths.home], Gem.paths.path + end + + def test_deprecated_paths= + stdout, stderr = capture_io do + Gem.paths = { 'GEM_HOME' => Gem.paths.home, + 'GEM_PATH' => [Gem.paths.home, 'foo'] } + end + assert_equal [Gem.paths.home, 'foo'], Gem.paths.path + assert_match(/Array values in the parameter are deprecated. Please use a String or nil/, stderr) + assert_equal '', stdout + end + def test_self_use_paths util_ensure_gem_dirs From 85957283eb3f348f3dd276f79c0818f0ddfa91c0 Mon Sep 17 00:00:00 2001 From: Samuel Giddins Date: Mon, 29 Feb 2016 21:23:16 -0600 Subject: [PATCH 304/707] [Edgecases] Update for release of Rails 3.2.22.2 --- bundler/spec/realworld/edgecases_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index 8295669d..2f0ba986 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -49,7 +49,7 @@ gem 'rack-cache', '1.2.0' # last version that works on Ruby 1.9 G bundle :lock - expect(lockfile).to include("rails (3.2.22.1)") + expect(lockfile).to include("rails (3.2.22.2)") expect(lockfile).to include("capybara (2.2.1)") end From 60bc1e283974f9d37bb968cc4fb6da857bb1e438 Mon Sep 17 00:00:00 2001 From: Samuel Giddins Date: Thu, 18 Feb 2016 13:12:09 -0600 Subject: [PATCH 305/707] Ensure the env reqs cache is reset by Spec.reset --- test/rubygems/test_gem.rb | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index aa57261d..ab50f12c 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -816,6 +816,22 @@ def test_self_ruby_api_version RbConfig::CONFIG['ruby_version'] = orig_ruby_version end + def test_self_env_requirement + old_env = ENV.to_hash + + ENV.clear + ENV["GEM_REQUIREMENT_FOO"] = '>= 1.2.3' + ENV["GEM_REQUIREMENT_BAR"] = '1.2.3' + ENV["GEM_REQUIREMENT_BAZ"] = 'abcd' + + assert_equal Gem::Requirement.create('>= 1.2.3'), Gem.env_requirement('foo') + assert_equal Gem::Requirement.create('1.2.3'), Gem.env_requirement('bAr') + assert_raises(Gem::Requirement::BadRequirementError) { Gem.env_requirement('baz') } + assert_equal Gem::Requirement.default, Gem.env_requirement('qux') + ensure + ENV.replace(old_env) + end + def test_self_ruby_version_1_8_5 util_set_RUBY_VERSION '1.8.5' From 4cb70f2c456d0d6ea281bf92b47c70557b4d9b00 Mon Sep 17 00:00:00 2001 From: Samuel Giddins Date: Fri, 19 Feb 2016 16:40:46 -0600 Subject: [PATCH 306/707] Fix env req tests to run when $SAFE = 1 --- test/rubygems/test_gem.rb | 5 ----- 1 file changed, 5 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index ab50f12c..e78f874b 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -817,9 +817,6 @@ def test_self_ruby_api_version end def test_self_env_requirement - old_env = ENV.to_hash - - ENV.clear ENV["GEM_REQUIREMENT_FOO"] = '>= 1.2.3' ENV["GEM_REQUIREMENT_BAR"] = '1.2.3' ENV["GEM_REQUIREMENT_BAZ"] = 'abcd' @@ -828,8 +825,6 @@ def test_self_env_requirement assert_equal Gem::Requirement.create('1.2.3'), Gem.env_requirement('bAr') assert_raises(Gem::Requirement::BadRequirementError) { Gem.env_requirement('baz') } assert_equal Gem::Requirement.default, Gem.env_requirement('qux') - ensure - ENV.replace(old_env) end def test_self_ruby_version_1_8_5 From 8d56b7ce0df27113f4e6bfcc9ceea39d843442f4 Mon Sep 17 00:00:00 2001 From: Samuel Giddins Date: Mon, 29 Feb 2016 21:23:16 -0600 Subject: [PATCH 307/707] [Edgecases] Update for release of Rails 3.2.22.2 --- bundler/spec/realworld/edgecases_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index 8295669d..2f0ba986 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -49,7 +49,7 @@ gem 'rack-cache', '1.2.0' # last version that works on Ruby 1.9 G bundle :lock - expect(lockfile).to include("rails (3.2.22.1)") + expect(lockfile).to include("rails (3.2.22.2)") expect(lockfile).to include("capybara (2.2.1)") end From f105fd11af02dee459cf1160510b50bf9ee2f9f1 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Mon, 14 Mar 2016 10:21:30 -0700 Subject: [PATCH 308/707] lazily calculate Gem::LoadError exception messages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `Gem::LoadError` exception messages are expensive to calculate. The more gems you have installed, the more expensive the message is to calculate. This commit lazily calculates the exception message so that the only time the message is ever created is if it's accessed. This speeds up gem activation misses that look like this: ```ruby begin gem 'missing_gem' rescue Gem::LoadError end ``` After this commit, the above pattern is nearly 2x faster: ``` [aaron@TC rubygems (master)]$ cat test.rb require 'benchmark/ips' Benchmark.ips do |x| x.report("fail") do begin gem "doesnotexist" rescue Gem::LoadError end end end [aaron@TC rubygems (master)]$ ruby -I lib test.rb Warming up -------------------------------------- fail 6.395k i/100ms Calculating ------------------------------------- fail 69.572k (± 4.4%) i/s - 351.725k [aaron@TC rubygems (master)]$ git checkout - Switched to branch 'faster_miss' [aaron@TC rubygems (faster_miss)]$ ruby -I lib test.rb Warming up -------------------------------------- fail 11.654k i/100ms Calculating ------------------------------------- fail 128.400k (± 6.7%) i/s - 640.970k ``` The "did_you_mean" gem is loaded in the manner above, so this commit will speed up environments (like mine) that don't have that gem installed. This cuts my boot time about 40%: ``` [aaron@TC rubygems (master)]$ time /Users/aaron/.rbenv/versions/ruby-trunk/bin/ruby -I lib -e' ' real 0m0.094s user 0m0.064s sys 0m0.021s [aaron@TC rubygems (master)]$ git checkout - Switched to branch 'faster_miss' [aaron@TC rubygems (faster_miss)]$ time /Users/aaron/.rbenv/versions/ruby-trunk/bin/ruby -I lib -e' ' real 0m0.059s user 0m0.039s sys 0m0.011s ``` You can see a massive difference in syscalls on boot: ``` [aaron@TC rubygems (master)]$ sudo dtrace -q -n 'syscall:::entry { @num[probefunc] = count(); }' -c`rbenv which ruby`" -Ilib -e'\ '" __semwait_signal 1 access 1 bsdthread_create 1 exit 1 fcntl_nocancel 1 getrlimit 1 getrusage 1 issetugid 1 poll 1 setitimer 1 shm_open 1 __disable_threadsignal 2 __pthread_sigmask 2 bsdthread_terminate 2 gettimeofday 2 madvise 2 pipe 2 select 2 __mac_syscall 3 pread 3 thread_selfid 4 proc_info 5 lseek 7 read_nocancel 9 fstatfs64 10 mmap 10 psynch_cvbroad 10 psynch_cvwait 10 sysctl 13 close_nocancel 15 open_nocancel 15 stat64 15 fgetattrlist 20 bsdthread_ctl 21 getgid 21 getegid 22 sigaction 22 geteuid 24 getuid 24 fcntl 37 getdirentries64 47 workq_kernreturn 70 fstat64 78 getattrlist 82 kevent_qos 125 close 764 read 777 open 852 lstat64 866 ioctl 1478 sigprocmask 1485 sigaltstack 1486 [aaron@TC rubygems (master)]$ git checkout - Switched to branch 'faster_miss' [aaron@TC rubygems (faster_miss)]$ sudo dtrace -q -n 'syscall:::entry { @num[probefunc] = count(); }' -c`rbenv which ruby`" -Ilib -e'\ '" __semwait_signal 1 access 1 bsdthread_create 1 exit 1 fcntl_nocancel 1 getrlimit 1 getrusage 1 issetugid 1 madvise 1 poll 1 setitimer 1 shm_open 1 thread_selfid 1 __pthread_sigmask 2 pipe 2 __disable_threadsignal 3 __mac_syscall 3 bsdthread_terminate 3 pread 3 proc_info 5 sysctl 6 fstatfs64 7 lseek 7 psynch_cvwait 8 read_nocancel 9 mmap 10 psynch_cvbroad 10 open_nocancel 11 close_nocancel 12 bsdthread_ctl 14 fgetattrlist 14 stat64 14 getgid 21 getegid 22 sigaction 22 workq_kernreturn 22 geteuid 23 getuid 24 getdirentries64 32 kevent_qos 35 fcntl 37 ioctl 56 close 57 getattrlist 58 read 70 sigprocmask 71 sigaltstack 72 fstat64 78 open 145 lstat64 159 ``` The differences in system calls at boot time is due to the error message processing all gem specs (in order to give you the "out of N gems" message). This patch introduces two new exception classes, both of which subclass `Gem::LoadError`. That means this patch should be backwards compatible for code that rescues from `Gem::LoadError`, but not code that specifically does "instance_of?" calls. Unfortunately minitest 4 does "instance_of" checks in `assert_raises` which is why I had to change the tests. I think the performance improvement is worth the trade-off, especially since this is done at the boot of every Ruby 2.3+ process. --- test/rubygems/test_gem.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index e78f874b..f9b4b971 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -972,7 +972,7 @@ def test_self_try_activate_missing_dep io.puts '# a_file.rb' end - e = assert_raises Gem::LoadError do + e = assert_raises Gem::MissingSpecError do Gem.try_activate 'a_file' end @@ -992,7 +992,7 @@ def test_self_try_activate_missing_prerelease io.puts '# a_file.rb' end - e = assert_raises Gem::LoadError do + e = assert_raises Gem::MissingSpecError do Gem.try_activate 'a_file' end From 23dcbe29ed6e564164ebe5eebcd497da05673bd5 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Tue, 15 Mar 2016 10:53:37 -0700 Subject: [PATCH 309/707] stub ordering should be consistent regardless of how cache is populated Looks like stub ordering can change depending on how the cache was populated. This commit changes cache population to always order spec stubs consistently: newest first. This fixes a bug where an older spec is activated when the newer spec is expected. --- test/rubygems/test_gem.rb | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index f9b4b971..6585d7b3 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -959,6 +959,19 @@ def test_try_activate_returns_true_for_activated_specs assert Gem.try_activate('b'), 'try_activate should still return true' end + def test_spec_order_is_consistent + b1 = util_spec 'b', '1.0' + b2 = util_spec 'b', '2.0' + b3 = util_spec 'b', '3.0' + + install_specs b1, b2, b3 + + specs1 = Gem::Specification.stubs.find_all { |s| s.name == 'b' } + Gem::Specification.reset + specs2 = Gem::Specification.stubs_for('b') + assert_equal specs1.map(&:version), specs2.map(&:version) + end + def test_self_try_activate_missing_dep b = util_spec 'b', '1.0' a = util_spec 'a', '1.0', 'b' => '>= 1.0' From 0b1c435b2883f40975dc7f47209382063abe81db Mon Sep 17 00:00:00 2001 From: James Wen Date: Thu, 17 Mar 2016 00:19:19 -0400 Subject: [PATCH 310/707] Create invalid gemspec error message spec that runs locally - Move invalid gemspec spec involving resque-scheduler 2.2.0 created in #4283 to realworld specs --- bundler/spec/realworld/edgecases_spec.rb | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index 2f0ba986..89de134c 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -220,4 +220,13 @@ expect(err).to eq("") expect(exitstatus).to eq(0) if exitstatus end + + it "outputs a helpful error message when gems have invalid gemspecs" do + install_gemfile <<-G, :standalone => true + source 'https://rubygems.org' + gem "resque-scheduler", "2.2.0" + G + expect(out).to include("You have one or more invalid gemspecs that need to be fixed.") + expect(out).to include("resque-scheduler 2.2.0 has an invalid gemspec") + end end From 93ebd1646d859c777de5b6376989f1c35897bb28 Mon Sep 17 00:00:00 2001 From: Samuel Giddins Date: Tue, 22 Mar 2016 14:15:38 +0100 Subject: [PATCH 311/707] [RubyGems] Make deprecation message for paths= more helpful --- test/rubygems/test_gem.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 6585d7b3..aae7084e 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1069,7 +1069,7 @@ def test_deprecated_paths= 'GEM_PATH' => [Gem.paths.home, 'foo'] } end assert_equal [Gem.paths.home, 'foo'], Gem.paths.path - assert_match(/Array values in the parameter are deprecated. Please use a String or nil/, stderr) + assert_match(/Array values in the parameter to `Gem.paths=` are deprecated.\nPlease use a String or nil/m, stderr) assert_equal '', stdout end From 5633b64ca91897e15e3089194e109cf3f0973263 Mon Sep 17 00:00:00 2001 From: willnet Date: Sun, 27 Mar 2016 16:02:52 +0900 Subject: [PATCH 312/707] Fix `Gem.find_spec_for_exe` picks oldest gem --- test/rubygems/test_gem.rb | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 6585d7b3..2c85ed03 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -143,6 +143,20 @@ def test_self_bin_path_active assert_match 'a-1/bin/exec', Gem.bin_path('a', 'exec', '>= 0') end + def test_self_bin_path_picking_newest + a1 = util_spec 'a', '1' do |s| + s.executables = ['exec'] + end + + a2 = util_spec 'a', '2' do |s| + s.executables = ['exec'] + end + + install_specs a1, a2 + + assert_match 'a-2/bin/exec', Gem.bin_path('a', 'exec', '>= 0') + end + def test_self_bin_path_no_exec_name e = assert_raises ArgumentError do Gem.bin_path 'a' From daff1dc8b472e6455783e85664e1d9d749099369 Mon Sep 17 00:00:00 2001 From: Ellen Marie Dash Date: Wed, 30 Mar 2016 19:01:56 -0400 Subject: [PATCH 313/707] MAINTAINERS.md isn't actually markdown. --- MAINTAINERS.txt | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 MAINTAINERS.txt diff --git a/MAINTAINERS.txt b/MAINTAINERS.txt new file mode 100644 index 00000000..dbba1a07 --- /dev/null +++ b/MAINTAINERS.txt @@ -0,0 +1,12 @@ +Luis Sagastume (@bronzdoc) +Jeremy Hinegardner (@copiousfreetime) +Daniel Berger (@djberg96) +Ellen Marie Dash (@duckinator) +Evan Phoenix (@evanphx) +SHIBATA Hiroshi (@hsbt) +André Arko (@indirect) +Kurtis Rainbolt-Greene (@krainboltgreene) +Luis Lavena (@luislavena) +Samuel Giddins (@segiddins) +Aaron Patterson (@tenderlove) +Zachary Scott (@zzak) From df06f86aeb39ebc681f09fda494ca89afd3497e7 Mon Sep 17 00:00:00 2001 From: Charles Oliver Nutter Date: Thu, 16 Jun 2016 16:39:45 -0500 Subject: [PATCH 314/707] Add Gem.platform_defaults to allow impls to override defaults. On JRuby, the "install" and "update" commands are modified to, among other things, always use /usr/bin/env shebangs, since our 'jruby' command is often just a bash script. Previously, we had to force config_file.rb to load in order to patch the default value for Gem::ConfigFile::PLATFORM_DEFAULTS, which added a few hundred ms to our base startup time. This change allows us to let the JRuby-specific defaults be lazily queried. --- test/rubygems/test_gem.rb | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 81b2c015..90695b56 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1695,6 +1695,13 @@ def test_use_gemdeps_specific ENV['RUBYGEMS_GEMDEPS'] = rubygems_gemdeps end + def test_platform_defaults + platform_defaults = Gem.platform_defaults + + assert platform_defaults != nil + assert platform_defaults.is_a? Hash + end + def ruby_install_name name orig_RUBY_INSTALL_NAME = RbConfig::CONFIG['ruby_install_name'] RbConfig::CONFIG['ruby_install_name'] = name From edbefd26d6d8cde396f69b1295019dfa7769df3f Mon Sep 17 00:00:00 2001 From: Stefan Lance Date: Fri, 20 Mar 2015 20:09:12 -0500 Subject: [PATCH 315/707] Add Bundler.ui.deprecate --- bundler/spec/realworld/edgecases_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index 89de134c..5c6835ed 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -9,7 +9,7 @@ gem "linecache", "0.46" G bundle :lock - expect(err).to eq("") + expect(err).to lack_errors expect(exitstatus).to eq(0) if exitstatus end @@ -91,7 +91,7 @@ bundle "install --path vendor/bundle", :expect_err => true expect(err).not_to include("Could not find rake") - expect(err).to be_empty + expect(err).to lack_errors end it "checks out git repos when the lockfile is corrupted" do From d238cabc42f5417898b1718359683b7a761e535d Mon Sep 17 00:00:00 2001 From: Samuel Giddins Date: Thu, 14 Jul 2016 21:56:57 -0500 Subject: [PATCH 316/707] Eagerly resolve in activate_bin_path --- test/rubygems/test_gem.rb | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 90695b56..9c7c446d 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -157,6 +157,35 @@ def test_self_bin_path_picking_newest assert_match 'a-2/bin/exec', Gem.bin_path('a', 'exec', '>= 0') end + def test_activate_bin_path_resolves_eagerly + a1 = util_spec 'a', '1' do |s| + s.executables = ['exec'] + s.add_dependency 'b' + end + + b1 = util_spec 'b', '1' do |s| + s.add_dependency 'c', '2' + end + + b2 = util_spec 'b', '2' do |s| + s.add_dependency 'c', '1' + end + + c1 = util_spec 'c', '1' + c2 = util_spec 'c', '2' + + install_specs c1, c2, b1, b2, a1 + + Gem.activate_bin_path("a", "exec", ">= 0") + + # If we didn't eagerly resolve, this would activate c-2 and then the + # finish_resolve would cause a conflict + gem 'c' + Gem.finish_resolve + + assert_equal %w(a-1 b-2 c-1), loaded_spec_names + end + def test_self_bin_path_no_exec_name e = assert_raises ArgumentError do Gem.bin_path 'a' From cd525e69a3ba2e577be09e3452ac08489de4b79a Mon Sep 17 00:00:00 2001 From: Samuel Giddins Date: Sun, 10 Jul 2016 13:09:58 -0300 Subject: [PATCH 317/707] [Version] Make hash based upon canonical segments --- test/rubygems/test_gem_version.rb | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/test/rubygems/test_gem_version.rb b/test/rubygems/test_gem_version.rb index 9898669c..46453cd9 100644 --- a/test/rubygems/test_gem_version.rb +++ b/test/rubygems/test_gem_version.rb @@ -65,7 +65,8 @@ def test_equals2 def test_hash assert_equal v("1.2").hash, v("1.2").hash refute_equal v("1.2").hash, v("1.3").hash - refute_equal v("1.2").hash, v("1.2.0").hash + assert_equal v("1.2").hash, v("1.2.0").hash + assert_equal v("1.2.pre.1").hash, v("1.2.0.pre.1.0").hash end def test_initialize @@ -99,6 +100,9 @@ def test_prerelease assert_prerelease '1.A' + assert_prerelease '1-1' + assert_prerelease '1-a' + refute_prerelease "1.2.0" refute_prerelease "2.9" refute_prerelease "22.1.50.0" @@ -154,6 +158,12 @@ def test_segments assert_equal [9,8,7], v("9.8.7").segments end + def test_canonical_segments + assert_equal [1], v("1.0.0").canonical_segments + assert_equal [1, "a", 1], v("1.0.0.a.1.0").canonical_segments + assert_equal [1, 2, 3, "pre", 1], v("1.2.3-1").canonical_segments + end + # Asserts that +version+ is a prerelease. def assert_prerelease version @@ -183,6 +193,7 @@ def assert_release_equal release, version def assert_version_equal expected, actual assert_equal v(expected), v(actual) + assert_equal v(expected).hash, v(actual).hash, "since #{actual} == #{expected}, they must have the same hash" end # Assert that two versions are eql?. Checks both directions. From 52cd891fcc20572f144a41759289a4c5ea8f2f63 Mon Sep 17 00:00:00 2001 From: Samuel Giddins Date: Sun, 10 Jul 2016 11:10:00 -0300 Subject: [PATCH 318/707] Use Bundler for Gem.use_gemdeps --- test/rubygems/test_gem.rb | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 9c7c446d..ed86fa61 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -374,7 +374,7 @@ def test_self_detect_gemdeps begin Dir.chdir 'detect/a/b' - assert_empty Gem.detect_gemdeps + assert_equal [BUNDLER_FULL_NAME], Gem.detect_gemdeps.map(&:full_name) ensure Dir.chdir @tempdir end @@ -1423,7 +1423,7 @@ def test_auto_activation_of_specific_gemdeps_file Gem.detect_gemdeps - assert_equal %w!a-1 b-1 c-1!, loaded_spec_names + assert_equal %W(a-1 b-1 #{BUNDLER_FULL_NAME} c-1), loaded_spec_names end def test_auto_activation_of_detected_gemdeps_file @@ -1446,10 +1446,12 @@ def test_auto_activation_of_detected_gemdeps_file ENV['RUBYGEMS_GEMDEPS'] = "-" - assert_equal [a,b,c], Gem.detect_gemdeps.sort_by { |s| s.name } + assert_equal [a, b, util_spec("bundler", Bundler::VERSION), c], Gem.detect_gemdeps.sort_by { |s| s.name } end LIB_PATH = File.expand_path "../../../lib".dup.untaint, __FILE__.dup.untaint + BUNDLER_LIB_PATH = File.expand_path("..".dup.untaint, $LOADED_FEATURES.find {|f| f.end_with? "lib/bundler.rb" }.dup.untaint) + BUNDLER_FULL_NAME = "bundler-#{Bundler::VERSION}" def test_looks_for_gemdeps_files_automatically_on_start util_clear_gems @@ -1476,9 +1478,9 @@ def test_looks_for_gemdeps_files_automatically_on_start ENV['GEM_PATH'] = path ENV['RUBYGEMS_GEMDEPS'] = "-" - out = `#{Gem.ruby.dup.untaint} -I "#{LIB_PATH.untaint}" -rubygems -e "p Gem.loaded_specs.values.map(&:full_name).sort"` + out = `#{Gem.ruby.dup.untaint} -I "#{LIB_PATH.untaint}" -I "#{BUNDLER_LIB_PATH.untaint}" -rubygems -e "p Gem.loaded_specs.values.map(&:full_name).sort"` - assert_equal '["a-1", "b-1", "c-1"]', out.strip + assert_equal %W(a-1 b-1 #{BUNDLER_FULL_NAME} c-1).inspect, out.strip end def test_looks_for_gemdeps_files_automatically_on_start_in_parent_dir @@ -1508,12 +1510,12 @@ def test_looks_for_gemdeps_files_automatically_on_start_in_parent_dir Dir.mkdir "sub1" out = Dir.chdir "sub1" do - `#{Gem.ruby.dup.untaint} -I "#{LIB_PATH.untaint}" -rubygems -e "p Gem.loaded_specs.values.map(&:full_name).sort"` + `#{Gem.ruby.dup.untaint} -I "#{LIB_PATH.untaint}" -I "#{BUNDLER_LIB_PATH.untaint}" -rubygems -e "p Gem.loaded_specs.values.map(&:full_name).sort"` end Dir.rmdir "sub1" - assert_equal '["a-1", "b-1", "c-1"]', out.strip + assert_equal %W(a-1 b-1 #{BUNDLER_FULL_NAME} c-1).inspect, out.strip end def test_register_default_spec @@ -1587,7 +1589,7 @@ def test_use_gemdeps Gem.use_gemdeps gem_deps_file - assert spec.activated? + assert_equal %W(a-1 #{BUNDLER_FULL_NAME}), loaded_spec_names refute_nil Gem.gemdeps end @@ -1648,7 +1650,7 @@ def test_use_gemdeps_automatic Gem.use_gemdeps - assert spec.activated? + assert_equal %W(a-1 #{BUNDLER_FULL_NAME}), loaded_spec_names ensure ENV['RUBYGEMS_GEMDEPS'] = rubygems_gemdeps end @@ -1691,7 +1693,7 @@ def test_use_gemdeps_missing_gem end expected = <<-EXPECTED -Unable to resolve dependency: user requested 'a (>= 0)' +Could not find gem 'a' in any of the gem sources listed in your Gemfile or available on this machine. You may need to `gem install -g` to install missing gems EXPECTED @@ -1719,7 +1721,7 @@ def test_use_gemdeps_specific Gem.use_gemdeps - assert spec.activated? + assert_equal %W(a-1 #{BUNDLER_FULL_NAME}), loaded_spec_names ensure ENV['RUBYGEMS_GEMDEPS'] = rubygems_gemdeps end From 9961e16b6cb476bbbf21d21b52664d7b52a49487 Mon Sep 17 00:00:00 2001 From: Samuel Giddins Date: Tue, 12 Jul 2016 00:11:39 -0400 Subject: [PATCH 319/707] Account for LOADED_FEATURES not having full paths on 1.8.7 --- test/rubygems/test_gem.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index ed86fa61..512f3da6 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1450,7 +1450,7 @@ def test_auto_activation_of_detected_gemdeps_file end LIB_PATH = File.expand_path "../../../lib".dup.untaint, __FILE__.dup.untaint - BUNDLER_LIB_PATH = File.expand_path("..".dup.untaint, $LOADED_FEATURES.find {|f| f.end_with? "lib/bundler.rb" }.dup.untaint) + BUNDLER_LIB_PATH = File.expand_path $LOAD_PATH.find {|lp| File.file?(File.join(lp, "bundler.rb")) }.dup.untaint BUNDLER_FULL_NAME = "bundler-#{Bundler::VERSION}" def test_looks_for_gemdeps_files_automatically_on_start From fb9cee267db634d5bcdcc1b77ff5dc92934845b9 Mon Sep 17 00:00:00 2001 From: Samuel Giddins Date: Mon, 25 Jul 2016 16:15:27 -0500 Subject: [PATCH 320/707] Call into the bundler postit trampoline in Gem.use_gemdeps --- test/rubygems/test_gem.rb | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 512f3da6..366af0bc 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1453,6 +1453,34 @@ def test_auto_activation_of_detected_gemdeps_file BUNDLER_LIB_PATH = File.expand_path $LOAD_PATH.find {|lp| File.file?(File.join(lp, "bundler.rb")) }.dup.untaint BUNDLER_FULL_NAME = "bundler-#{Bundler::VERSION}" + def test_use_gemdeps_uses_bundler_postit_trampoline + refute_includes $LOADED_FEATURES, File.join(BUNDLER_LIB_PATH, "bundler/postit_trampoline.rb".dup.untaint) + ENV.delete("BUNDLE_DISABLE_POSTIT") + + a = new_spec "a", "1", nil, "lib/a.rb" + b = new_spec "b", "1", nil, "lib/b.rb" + c = new_spec "c", "1", nil, "lib/c.rb" + + install_specs a, b, c + + path = File.join @tempdir, "gem.deps.rb" + + File.open path, "w" do |f| + f.puts "gem 'a'" + f.puts "gem 'b'" + f.puts "gem 'c'" + end + + ENV['RUBYGEMS_GEMDEPS'] = path + + Gem.detect_gemdeps + + assert_equal %W(a-1 b-1 #{BUNDLER_FULL_NAME} c-1), loaded_spec_names + + trampoline_path = RUBY_VERSION > "1.9" ? File.join(BUNDLER_LIB_PATH, "bundler/postit_trampoline.rb".dup.untaint) : "bundler/postit_trampoline.rb" + assert_includes $LOADED_FEATURES, trampoline_path + end + def test_looks_for_gemdeps_files_automatically_on_start util_clear_gems From 95809855b2220afdcd47586da6a1b2f62e8b2a3a Mon Sep 17 00:00:00 2001 From: Samuel Giddins Date: Mon, 25 Jul 2016 16:24:00 -0500 Subject: [PATCH 321/707] Update test string for running on non-RUBY platforms --- test/rubygems/test_gem.rb | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 366af0bc..0e87729c 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1720,8 +1720,14 @@ def test_use_gemdeps_missing_gem io.write 'gem "a"' end + platform = Bundler::GemHelpers.generic_local_platform + if platform == Gem::Platform::RUBY + platform = '' + else + platform = " #{platform}" + end expected = <<-EXPECTED -Could not find gem 'a' in any of the gem sources listed in your Gemfile or available on this machine. +Could not find gem 'a#{platform}' in any of the gem sources listed in your Gemfile or available on this machine. You may need to `gem install -g` to install missing gems EXPECTED From a1dd424323aa65498a11b4b5ae4c980f5768b30c Mon Sep 17 00:00:00 2001 From: Samuel Giddins Date: Mon, 1 Aug 2016 20:35:31 -0500 Subject: [PATCH 322/707] Remove expect_err from the specs & print all output on a spec failure --- bundler/spec/realworld/edgecases_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index 5c6835ed..f3f6515a 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -89,7 +89,7 @@ gem 'rack', '1.0.1' G - bundle "install --path vendor/bundle", :expect_err => true + bundle "install --path vendor/bundle" expect(err).not_to include("Could not find rake") expect(err).to lack_errors end From 9c6905d88ba451db58859ed5ab309f80625e0bfa Mon Sep 17 00:00:00 2001 From: Samuel Giddins Date: Thu, 11 Aug 2016 13:44:43 -0500 Subject: [PATCH 323/707] Update realworld specs for rails 3.2.22.3 --- bundler/spec/realworld/edgecases_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index f3f6515a..7a78a114 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -49,7 +49,7 @@ gem 'rack-cache', '1.2.0' # last version that works on Ruby 1.9 G bundle :lock - expect(lockfile).to include("rails (3.2.22.2)") + expect(lockfile).to include("rails (3.2.22.4)") expect(lockfile).to include("capybara (2.2.1)") end From df82013ec54ee03c3a79e2ff32c0db2be571571f Mon Sep 17 00:00:00 2001 From: bronzdoc Date: Fri, 26 Aug 2016 10:16:40 -0600 Subject: [PATCH 324/707] Use config sources if available else use default source --- test/rubygems/test_gem.rb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 0e87729c..b9c0337c 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -990,6 +990,9 @@ def test_self_pre_uninstall def test_self_sources assert_equal %w[http://gems.example.com/], Gem.sources + Gem.sources = nil + Gem.configuration.sources = %w[http://test.example.com/] + assert_equal %w[http://test.example.com/], Gem.sources end def test_try_activate_returns_true_for_activated_specs From f17306f5410c1d5cf09a8d71519cee9ba7b598af Mon Sep 17 00:00:00 2001 From: Samuel Giddins Date: Thu, 15 Sep 2016 12:18:23 +0200 Subject: [PATCH 325/707] Dynamically fetch expected rails version --- bundler/spec/realworld/edgecases_spec.rb | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index 7a78a114..06e58804 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -48,8 +48,16 @@ gem 'capybara', '~> 2.2.0' gem 'rack-cache', '1.2.0' # last version that works on Ruby 1.9 G - bundle :lock - expect(lockfile).to include("rails (3.2.22.4)") + bundle! :lock + rails_version = ruby(<<-R) + require 'rubygems' + require 'bundler' + fetcher = Bundler::Fetcher.new(Bundler::Source::Rubygems::Remote.new(URI('https://rubygems.org'))) + index = fetcher.specs(%w(rails), nil) + rails = index.search(Gem::Dependency.new("rails", "~> 3.0")).last + puts rails.version + R + expect(lockfile).to include("rails (#{rails_version})") expect(lockfile).to include("capybara (2.2.1)") end From c24b72640e917b87657b3f456f950900c083dba6 Mon Sep 17 00:00:00 2001 From: Colby Swandale Date: Thu, 15 Sep 2016 22:14:13 +1000 Subject: [PATCH 326/707] link installation issues in README to ISSUES --- bundler/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/bundler/README.md b/bundler/README.md index c4676730..6cf53a92 100644 --- a/bundler/README.md +++ b/bundler/README.md @@ -18,6 +18,7 @@ echo 'gem "rspec"' >> Gemfile bundle install bundle exec rspec ``` +For help with installation issues, see [ISSUES](https://github.com/bundler/bundler/blob/master/ISSUES.md) See [bundler.io](http://bundler.io) for the full documentation. From 77596d8dc7c05dfe18208113c23cf20f03e88c07 Mon Sep 17 00:00:00 2001 From: Colby Swandale Date: Sun, 18 Sep 2016 15:00:18 +1000 Subject: [PATCH 327/707] document formatting feedback [skip ci] --- bundler/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/bundler/README.md b/bundler/README.md index 6cf53a92..a3a9acbf 100644 --- a/bundler/README.md +++ b/bundler/README.md @@ -18,6 +18,7 @@ echo 'gem "rspec"' >> Gemfile bundle install bundle exec rspec ``` + For help with installation issues, see [ISSUES](https://github.com/bundler/bundler/blob/master/ISSUES.md) See [bundler.io](http://bundler.io) for the full documentation. From dfc264338278f40211a3bb38cb1fb47020239214 Mon Sep 17 00:00:00 2001 From: Homu Date: Sat, 27 Aug 2016 06:42:45 +0900 Subject: [PATCH 328/707] Auto merge of #1699 - rubygems:bugfix/gem_sources_load_gemrc, r=bronzdoc Load config in Gem.sources # Description: When calling `Gem.sources` load sources from configuration if present, else use default sources. closes https://github.com/rubygems/rubygems/issues/1613 # Tasks: - [x] Describe the problem / feature - [x] Write tests - [x] Write code to solve the problem - [ ] Get code review from coworkers / friends - [ ] [Squash commits](http://gitready.com/advanced/2009/02/10/squashing-commits-with-rebase.html) I will abide by the [code of conduct](https://github.com/rubygems/rubygems/blob/master/CODE_OF_CONDUCT.md). --- test/rubygems/test_gem.rb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 90695b56..78735072 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -961,6 +961,9 @@ def test_self_pre_uninstall def test_self_sources assert_equal %w[http://gems.example.com/], Gem.sources + Gem.sources = nil + Gem.configuration.sources = %w[http://test.example.com/] + assert_equal %w[http://test.example.com/], Gem.sources end def test_try_activate_returns_true_for_activated_specs From b6c06efc50f623a3bd2acb301e9a47542aabfcdb Mon Sep 17 00:00:00 2001 From: Homu Date: Thu, 15 Sep 2016 23:09:50 +0900 Subject: [PATCH 329/707] Auto merge of #4990 - bundler:seg-realworld-flex, r=segiddins Dynamically fetch expected rails version This way, we don't have to update this expectation every time a new rails version comes out --- bundler/spec/realworld/edgecases_spec.rb | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index 7a78a114..06e58804 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -48,8 +48,16 @@ gem 'capybara', '~> 2.2.0' gem 'rack-cache', '1.2.0' # last version that works on Ruby 1.9 G - bundle :lock - expect(lockfile).to include("rails (3.2.22.4)") + bundle! :lock + rails_version = ruby(<<-R) + require 'rubygems' + require 'bundler' + fetcher = Bundler::Fetcher.new(Bundler::Source::Rubygems::Remote.new(URI('https://rubygems.org'))) + index = fetcher.specs(%w(rails), nil) + rails = index.search(Gem::Dependency.new("rails", "~> 3.0")).last + puts rails.version + R + expect(lockfile).to include("rails (#{rails_version})") expect(lockfile).to include("capybara (2.2.1)") end From 4d9d90f15c1f40c3e9cdd15bcea159d40bcfcaf8 Mon Sep 17 00:00:00 2001 From: Jon Moss Date: Sun, 2 Oct 2016 16:27:53 -0400 Subject: [PATCH 330/707] Add deprecation for Gem#datadir --- test/rubygems/test_gem.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index b9c0337c..5d7f2296 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -281,11 +281,13 @@ def test_self_datadir expected = File.join @gemhome, 'gems', foo.full_name, 'data', 'foo' - assert_equal expected, Gem.datadir('foo') + assert_equal expected, Gem::Specification.find_by_name("foo").datadir end def test_self_datadir_nonexistent_package - assert_nil Gem.datadir('xyzzy') + assert_raises(Gem::MissingSpecError) do + Gem::Specification.find_by_name("xyzzy").datadir + end end def test_self_default_exec_format From 71cb67376fbcd7dcafecab14b3e3d7be8990dc08 Mon Sep 17 00:00:00 2001 From: Andre Arko Date: Wed, 12 Oct 2016 11:59:03 -0700 Subject: [PATCH 331/707] use realworld versions in realworld tests --- bundler/spec/realworld/edgecases_spec.rb | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index 06e58804..6d01675e 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -2,6 +2,14 @@ require "spec_helper" describe "real world edgecases", :realworld => true, :sometimes => true do + def rubygems_version(name, requirement) + source = Bundler::Source::Rubygems::Remote.new(URI('https://rubygems.org')) + fetcher = Bundler::Fetcher.new(source) + index = fetcher.specs([name], nil) + rubygem = index.search(Gem::Dependency.new(name, requirement)).last + "#{name} (#{rubygem.version})" + end + # there is no rbx-relative-require gem that will install on 1.9 it "ignores extra gems with bad platforms", :ruby => "~> 1.8.7" do gemfile <<-G @@ -84,8 +92,8 @@ gem "builder", "~> 2.1.2" G bundle :lock - expect(lockfile).to include("i18n (0.6.11)") - expect(lockfile).to include("activesupport (3.0.5)") + expect(lockfile).to include(rubygems_version("i18n", "~> 0.6.0")) + expect(lockfile).to include(rubygems_version("activesupport", "~> 3.0")) end # https://github.com/bundler/bundler/issues/1500 From ca55e7f30603765a28277d1e42eeb6c5651ea7cb Mon Sep 17 00:00:00 2001 From: Andre Arko Date: Wed, 12 Oct 2016 16:11:00 -0700 Subject: [PATCH 332/707] :cop: --- bundler/spec/realworld/edgecases_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index 6d01675e..cb698ee5 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -3,7 +3,7 @@ describe "real world edgecases", :realworld => true, :sometimes => true do def rubygems_version(name, requirement) - source = Bundler::Source::Rubygems::Remote.new(URI('https://rubygems.org')) + source = Bundler::Source::Rubygems::Remote.new(URI("https://rubygems.org")) fetcher = Bundler::Fetcher.new(source) index = fetcher.specs([name], nil) rubygem = index.search(Gem::Dependency.new(name, requirement)).last From 15aef8dee544e1b7362277c7d7ba37a3bcd6679e Mon Sep 17 00:00:00 2001 From: Andre Arko Date: Wed, 12 Oct 2016 16:13:20 -0700 Subject: [PATCH 333/707] setup that matches the expectations --- bundler/spec/realworld/edgecases_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index cb698ee5..0fcacdeb 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -40,8 +40,8 @@ def rubygems_version(name, requirement) source "https://rubygems.org" gem 'i18n', '~> 0.6.0' - gem 'activesupport', '~> 3.0' - gem 'activerecord', '~> 3.0' + gem 'activesupport', '~> 3.0.5' + gem 'activerecord', '~> 3.0.5' gem 'builder', '~> 2.1.2' G bundle :lock From 1c4e1d9f8ad7c7bf66f2b627339a3d681bc14748 Mon Sep 17 00:00:00 2001 From: Andre Arko Date: Wed, 12 Oct 2016 17:08:12 -0700 Subject: [PATCH 334/707] fix a bad find and replace --- bundler/spec/realworld/edgecases_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index 0fcacdeb..8ef49d43 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -23,7 +23,7 @@ def rubygems_version(name, requirement) # https://github.com/bundler/bundler/issues/1202 it "bundle cache works with rubygems 1.3.7 and pre gems", - :ruby => "~> 1.8.7", "https://rubygems.org" => "~> 1.3.7" do + :ruby => "~> 1.8.7", :rubygems => "~> 1.3.7" do install_gemfile <<-G source "https://rubygems.org" gem "rack", "1.3.0.beta2" From 6849ab1f1206fde1a29c15ede58c9c7a941ae4f7 Mon Sep 17 00:00:00 2001 From: Andre Arko Date: Wed, 12 Oct 2016 17:08:32 -0700 Subject: [PATCH 335/707] use the method now that we have it --- bundler/spec/realworld/edgecases_spec.rb | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index 8ef49d43..a1d44daa 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -57,15 +57,7 @@ def rubygems_version(name, requirement) gem 'rack-cache', '1.2.0' # last version that works on Ruby 1.9 G bundle! :lock - rails_version = ruby(<<-R) - require 'rubygems' - require 'bundler' - fetcher = Bundler::Fetcher.new(Bundler::Source::Rubygems::Remote.new(URI('https://rubygems.org'))) - index = fetcher.specs(%w(rails), nil) - rails = index.search(Gem::Dependency.new("rails", "~> 3.0")).last - puts rails.version - R - expect(lockfile).to include("rails (#{rails_version})") + expect(lockfile).to include(rubygems_version("rails", "~> 3.0")) expect(lockfile).to include("capybara (2.2.1)") end From 4f42c4e96978d6c63872d437122a2992c318be9b Mon Sep 17 00:00:00 2001 From: Andre Arko Date: Wed, 12 Oct 2016 17:29:25 -0700 Subject: [PATCH 336/707] debug info for error on travis --- bundler/spec/realworld/edgecases_spec.rb | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index a1d44daa..81fe3d77 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -3,10 +3,16 @@ describe "real world edgecases", :realworld => true, :sometimes => true do def rubygems_version(name, requirement) + require "bundler/source/rubygems/remote" + require "bundler/fetcher" source = Bundler::Source::Rubygems::Remote.new(URI("https://rubygems.org")) fetcher = Bundler::Fetcher.new(source) index = fetcher.specs([name], nil) rubygem = index.search(Gem::Dependency.new(name, requirement)).last + if rubygem.nil? + raise "Could not find #{name} (#{requirement}) on rubygems.org!\n" \ + "Found specs:\n#{index.send(:specs).inspect}" + end "#{name} (#{rubygem.version})" end From 261fc278726b31638edb342006843c29e27949d5 Mon Sep 17 00:00:00 2001 From: bronzdoc Date: Tue, 1 Nov 2016 20:04:35 -0600 Subject: [PATCH 337/707] Test empty version --- test/rubygems/test_gem_version.rb | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/rubygems/test_gem_version.rb b/test/rubygems/test_gem_version.rb index 46453cd9..42d31fec 100644 --- a/test/rubygems/test_gem_version.rb +++ b/test/rubygems/test_gem_version.rb @@ -92,6 +92,12 @@ def test_initialize_bad end end + def test_empty_version + ["", " ", " "].each do |empty| + assert_equal "0", Gem::Version.new(empty).version + end + end + def test_prerelease assert_prerelease "1.2.0.a" assert_prerelease "2.9.b" From 6c5ce8a3fae70fd5f7c457a29c93ae968649e79d Mon Sep 17 00:00:00 2001 From: John Labovitz Date: Thu, 3 Nov 2016 11:39:41 -0400 Subject: [PATCH 338/707] Update tests to match changes in spacing/capitalization. --- test/rubygems/test_gem.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 5d7f2296..e3585a97 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1076,7 +1076,7 @@ def test_self_try_activate_missing_extensions refute Gem.try_activate 'nonexistent' end - expected = "Ignoring ext-1 because its extensions are not built. " + + expected = "Ignoring ext-1 because its extensions are not built. " + "Try: gem pristine ext --version 1\n" assert_equal expected, err From 702666abbe47f3c822b3db7e34c5161cd4306474 Mon Sep 17 00:00:00 2001 From: mrb Date: Fri, 4 Nov 2016 11:27:24 -0400 Subject: [PATCH 339/707] Add Ruby Together CTA --- bundler/README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/bundler/README.md b/bundler/README.md index a3a9acbf..0c7e1e70 100644 --- a/bundler/README.md +++ b/bundler/README.md @@ -27,6 +27,11 @@ See [bundler.io](http://bundler.io) for the full documentation. For help with common problems, see [ISSUES](https://github.com/bundler/bundler/blob/master/ISSUES.md). +### Supporting + +
+Bundler is maintained by Ruby Together, a grassroots initiative committed to supporting the critical Ruby infrastructure you rely on. Contribute today as an individual or even better, as a company, and ensure that Bundler, RubyGems, and other shared tooling is around for years to come. + ### Other questions To see what has changed in recent versions of Bundler, see the [CHANGELOG](https://github.com/bundler/bundler/blob/master/CHANGELOG.md). From bd929951d085e20a6385326222da4b13c27e236c Mon Sep 17 00:00:00 2001 From: mrb Date: Thu, 10 Nov 2016 13:26:48 -0500 Subject: [PATCH 340/707] Add Ruby Together CTA, rearrange README a bit --- README.md | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 00000000..d20177f8 --- /dev/null +++ b/README.md @@ -0,0 +1,54 @@ +# RubyGems + +RubyGems is a package management framework for Ruby. + +This gem is an update for the RubyGems software. You must have an +installation of RubyGems before this update can be applied. + +See Gem for information on RubyGems (or `ri Gem`) + +To upgrade to the latest RubyGems, run: + +``` + $ gem update --system # you might need to be an administrator or root +``` + +See UPGRADING.rdoc for more details and alternative instructions. + +----- + +If you don't have RubyGems installed, you can still do it manually: + +* Download from: https://rubygems.org/pages/download, unpack, and cd there +* OR clone this repository and cd there (make sure to run `git submodule update -\-init`) +* Install with: ruby setup.rb # you may need admin/root privilege + +For more details and other options, see: + +``` + ruby setup.rb --help +``` + +## SUPPORTING + +
+ RubyGems is maintained by Ruby Together, a grassroots initiative committed to supporting the critical Ruby infrastructure you rely on. Contribute today as an individual or even better, as a company, and ensure that Bundler, RubyGems, and other shared tooling is around for years to come. + +## GETTING HELP + +### Support Requests + +Are you unsure of how to use RubyGems? Do you think you've found a bug and +you're not sure? If that is the case, the best place for you is to file a +support request at {help.rubygems.org}[http://help.rubygems.org]. + +### Filing Tickets + +Got a bug and you're not sure? You're sure you have a bug, but don't know +what to do next? In any case, let us know about it! The best place +for letting the RubyGems team know about bugs or problems you're having is +{on the RubyGems issues page at GitHub}[http://github.com/rubygems/rubygems/issues]. + +### Bundler Compatibility + +See http://bundler.io/compatibility for known issues. From 56000882666a05ce0ade4b083f6524aef036a31f Mon Sep 17 00:00:00 2001 From: Piotr Kuczynski Date: Wed, 30 Nov 2016 11:40:55 +0100 Subject: [PATCH 341/707] Fixing links markdown formatting in README --- README.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index d20177f8..6b9af698 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ To upgrade to the latest RubyGems, run: $ gem update --system # you might need to be an administrator or root ``` -See UPGRADING.rdoc for more details and alternative instructions. +See [UPGRADING.rdoc] for more details and alternative instructions. ----- @@ -31,8 +31,9 @@ For more details and other options, see: ## SUPPORTING -
- RubyGems is maintained by Ruby Together, a grassroots initiative committed to supporting the critical Ruby infrastructure you rely on. Contribute today as an individual or even better, as a company, and ensure that Bundler, RubyGems, and other shared tooling is around for years to come. + + +RubyGems is maintained by [Ruby Together](https://rubytogether.org), a grassroots initiative committed to supporting the critical Ruby infrastructure you rely on. Contribute today [as an individual](https://rubytogether.org/developers) or even better, [as a company](https://rubytogether.org/companies), and ensure that Bundler, RubyGems, and other shared tooling is around for years to come. ## GETTING HELP @@ -40,14 +41,14 @@ For more details and other options, see: Are you unsure of how to use RubyGems? Do you think you've found a bug and you're not sure? If that is the case, the best place for you is to file a -support request at {help.rubygems.org}[http://help.rubygems.org]. +support request at [help.rubygems.org](http://help.rubygems.org). ### Filing Tickets Got a bug and you're not sure? You're sure you have a bug, but don't know what to do next? In any case, let us know about it! The best place for letting the RubyGems team know about bugs or problems you're having is -{on the RubyGems issues page at GitHub}[http://github.com/rubygems/rubygems/issues]. +[on the RubyGems issues page at GitHub](http://github.com/rubygems/rubygems/issues). ### Bundler Compatibility From 0140478ce11dcb8cdb2c6d860bfe5566e1545882 Mon Sep 17 00:00:00 2001 From: Piotr Kuczynski Date: Wed, 30 Nov 2016 16:49:52 +0100 Subject: [PATCH 342/707] Fix link for UPGRADING document --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6b9af698..92a9783b 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ To upgrade to the latest RubyGems, run: $ gem update --system # you might need to be an administrator or root ``` -See [UPGRADING.rdoc] for more details and alternative instructions. +See [UPGRADING](UPGRADING.rdoc) for more details and alternative instructions. ----- From e519a990d21bdac8554638b3c36bef3888ed9a1b Mon Sep 17 00:00:00 2001 From: Samuel Giddins Date: Sun, 25 Dec 2016 06:56:10 -0600 Subject: [PATCH 343/707] Support openssl being a gem in the subprocess tests --- test/rubygems/test_gem.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index e3585a97..b3f524e7 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1512,6 +1512,7 @@ def test_looks_for_gemdeps_files_automatically_on_start ENV['RUBYGEMS_GEMDEPS'] = "-" out = `#{Gem.ruby.dup.untaint} -I "#{LIB_PATH.untaint}" -I "#{BUNDLER_LIB_PATH.untaint}" -rubygems -e "p Gem.loaded_specs.values.map(&:full_name).sort"` + out.sub!(/, "openssl-#{Gem::Version::VERSION_PATTERN}"/, "") assert_equal %W(a-1 b-1 #{BUNDLER_FULL_NAME} c-1).inspect, out.strip end @@ -1545,6 +1546,7 @@ def test_looks_for_gemdeps_files_automatically_on_start_in_parent_dir out = Dir.chdir "sub1" do `#{Gem.ruby.dup.untaint} -I "#{LIB_PATH.untaint}" -I "#{BUNDLER_LIB_PATH.untaint}" -rubygems -e "p Gem.loaded_specs.values.map(&:full_name).sort"` end + out.sub!(/, "openssl-#{Gem::Version::VERSION_PATTERN}"/, "") Dir.rmdir "sub1" From 179678beb5f2b5cc30577c2386b3fd83716365df Mon Sep 17 00:00:00 2001 From: Samuel Giddins Date: Sun, 25 Dec 2016 10:18:03 -0600 Subject: [PATCH 344/707] Update Bundler to have spec fixes for Ruby 2.4 --- test/rubygems/test_gem.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index b3f524e7..6aefac1e 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1734,7 +1734,7 @@ def test_use_gemdeps_missing_gem platform = " #{platform}" end expected = <<-EXPECTED -Could not find gem 'a#{platform}' in any of the gem sources listed in your Gemfile or available on this machine. +Could not find gem 'a#{platform}' in any of the gem sources listed in your Gemfile. You may need to `gem install -g` to install missing gems EXPECTED From 5846f44e9d7d93e2277a839c031e22c6a4251ea2 Mon Sep 17 00:00:00 2001 From: Samuel Giddins Date: Sat, 14 Jan 2017 19:18:35 -0600 Subject: [PATCH 345/707] Add a realworld spec for partial updates failing on locked, shared, transitive children --- bundler/spec/realworld/edgecases_spec.rb | 136 +++++++++++++++++++++++ 1 file changed, 136 insertions(+) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index 81fe3d77..bd7d7937 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -94,6 +94,142 @@ def rubygems_version(name, requirement) expect(lockfile).to include(rubygems_version("activesupport", "~> 3.0")) end + it "is able to update a top-level dependency when there is a conflict on a shared transitive child" do + # from https://github.com/bundler/bundler/issues/5031 + + gemfile <<-G + source "https://rubygems.org" + gem 'rails', '~> 4.2.7.1' + gem 'paperclip', '~> 5.1.0' + G + + lockfile <<-L + GEM + remote: https://rubygems.org/ + specs: + actionmailer (4.2.7.1) + actionpack (= 4.2.7.1) + actionview (= 4.2.7.1) + activejob (= 4.2.7.1) + mail (~> 2.5, >= 2.5.4) + rails-dom-testing (~> 1.0, >= 1.0.5) + actionpack (4.2.7.1) + actionview (= 4.2.7.1) + activesupport (= 4.2.7.1) + rack (~> 1.6) + rack-test (~> 0.6.2) + rails-dom-testing (~> 1.0, >= 1.0.5) + rails-html-sanitizer (~> 1.0, >= 1.0.2) + actionview (4.2.7.1) + activesupport (= 4.2.7.1) + builder (~> 3.1) + erubis (~> 2.7.0) + rails-dom-testing (~> 1.0, >= 1.0.5) + rails-html-sanitizer (~> 1.0, >= 1.0.2) + activejob (4.2.7.1) + activesupport (= 4.2.7.1) + globalid (>= 0.3.0) + activemodel (4.2.7.1) + activesupport (= 4.2.7.1) + builder (~> 3.1) + activerecord (4.2.7.1) + activemodel (= 4.2.7.1) + activesupport (= 4.2.7.1) + arel (~> 6.0) + activesupport (4.2.7.1) + i18n (~> 0.7) + json (~> 1.7, >= 1.7.7) + minitest (~> 5.1) + thread_safe (~> 0.3, >= 0.3.4) + tzinfo (~> 1.1) + arel (6.0.3) + builder (3.2.2) + climate_control (0.0.3) + activesupport (>= 3.0) + cocaine (0.5.8) + climate_control (>= 0.0.3, < 1.0) + concurrent-ruby (1.0.2) + erubis (2.7.0) + globalid (0.3.7) + activesupport (>= 4.1.0) + i18n (0.7.0) + json (1.8.3) + loofah (2.0.3) + nokogiri (>= 1.5.9) + mail (2.6.4) + mime-types (>= 1.16, < 4) + mime-types (3.1) + mime-types-data (~> 3.2015) + mime-types-data (3.2016.0521) + mimemagic (0.3.2) + mini_portile2 (2.1.0) + minitest (5.9.1) + nokogiri (1.6.8) + mini_portile2 (~> 2.1.0) + pkg-config (~> 1.1.7) + paperclip (5.1.0) + activemodel (>= 4.2.0) + activesupport (>= 4.2.0) + cocaine (~> 0.5.5) + mime-types + mimemagic (~> 0.3.0) + pkg-config (1.1.7) + rack (1.6.4) + rack-test (0.6.3) + rack (>= 1.0) + rails (4.2.7.1) + actionmailer (= 4.2.7.1) + actionpack (= 4.2.7.1) + actionview (= 4.2.7.1) + activejob (= 4.2.7.1) + activemodel (= 4.2.7.1) + activerecord (= 4.2.7.1) + activesupport (= 4.2.7.1) + bundler (>= 1.3.0, < 2.0) + railties (= 4.2.7.1) + sprockets-rails + rails-deprecated_sanitizer (1.0.3) + activesupport (>= 4.2.0.alpha) + rails-dom-testing (1.0.7) + activesupport (>= 4.2.0.beta, < 5.0) + nokogiri (~> 1.6.0) + rails-deprecated_sanitizer (>= 1.0.1) + rails-html-sanitizer (1.0.3) + loofah (~> 2.0) + railties (4.2.7.1) + actionpack (= 4.2.7.1) + activesupport (= 4.2.7.1) + rake (>= 0.8.7) + thor (>= 0.18.1, < 2.0) + rake (11.3.0) + sprockets (3.7.0) + concurrent-ruby (~> 1.0) + rack (> 1, < 3) + sprockets-rails (3.2.0) + actionpack (>= 4.0) + activesupport (>= 4.0) + sprockets (>= 3.0.0) + thor (0.19.1) + thread_safe (0.3.5) + tzinfo (1.2.2) + thread_safe (~> 0.1) + + PLATFORMS + ruby + + DEPENDENCIES + paperclip (~> 5.1.0) + rails (~> 4.2.7.1) + + BUNDLED WITH + 1.13.1 + L + + bundle! "lock --update paperclip" + + expect(lockfile).to include(rubygems_version("paperclip", "~> 5.1.0")) + end + # https://github.com/bundler/bundler/issues/1500 it "does not fail install because of gem plugins" do realworld_system_gems("open_gem --version 1.4.2", "rake --version 0.9.2") From 47391a703ec10717e9844ac5d2a7287933fc0c96 Mon Sep 17 00:00:00 2001 From: Samuel Giddins Date: Sat, 14 Jan 2017 20:21:07 -0600 Subject: [PATCH 346/707] Limit edgecases spec to what as 4.2.7 is compatible with --- bundler/spec/realworld/edgecases_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index bd7d7937..96670744 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -94,7 +94,7 @@ def rubygems_version(name, requirement) expect(lockfile).to include(rubygems_version("activesupport", "~> 3.0")) end - it "is able to update a top-level dependency when there is a conflict on a shared transitive child" do + it "is able to update a top-level dependency when there is a conflict on a shared transitive child", :ruby => "2.1" do # from https://github.com/bundler/bundler/issues/5031 gemfile <<-G From 4dd9f8b23eb463fe86f0b2370f3fc2109521869f Mon Sep 17 00:00:00 2001 From: Samuel Giddins Date: Sun, 15 Jan 2017 12:57:54 -0600 Subject: [PATCH 347/707] Disable RSpec monkey patching --- bundler/spec/realworld/edgecases_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index 96670744..302fd57c 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -1,7 +1,7 @@ # frozen_string_literal: true require "spec_helper" -describe "real world edgecases", :realworld => true, :sometimes => true do +RSpec.describe "real world edgecases", :realworld => true, :sometimes => true do def rubygems_version(name, requirement) require "bundler/source/rubygems/remote" require "bundler/fetcher" From 22d377838905a4f6ba369b711eaea707d3f8982c Mon Sep 17 00:00:00 2001 From: Samuel Giddins Date: Mon, 16 Jan 2017 13:00:00 -0600 Subject: [PATCH 348/707] Use Bundler 1.14 postit env var --- test/rubygems/test_gem.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 6aefac1e..c2f1b29b 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1460,7 +1460,7 @@ def test_auto_activation_of_detected_gemdeps_file def test_use_gemdeps_uses_bundler_postit_trampoline refute_includes $LOADED_FEATURES, File.join(BUNDLER_LIB_PATH, "bundler/postit_trampoline.rb".dup.untaint) - ENV.delete("BUNDLE_DISABLE_POSTIT") + ENV.delete("BUNDLE_TRAMPOLINE_DISABLE") a = new_spec "a", "1", nil, "lib/a.rb" b = new_spec "b", "1", nil, "lib/b.rb" From 8011c5739b63ffc41a3c3fc4335deaa6237d1508 Mon Sep 17 00:00:00 2001 From: Homu Date: Fri, 4 Nov 2016 10:48:41 +0900 Subject: [PATCH 349/707] Auto merge of #1767 - rubygems:fix_malformed_version_number, r=segiddins Fix malformed version number error closes https://github.com/rubygems/rubygems/issues/1628 This PR will convert a gem version that is set to an empty string to "0" (cherry picked from commit bb85bfeb58de2751fd87c1f51b0c438226c46ea0) --- test/rubygems/test_gem_version.rb | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/rubygems/test_gem_version.rb b/test/rubygems/test_gem_version.rb index 9898669c..1897d449 100644 --- a/test/rubygems/test_gem_version.rb +++ b/test/rubygems/test_gem_version.rb @@ -91,6 +91,12 @@ def test_initialize_bad end end + def test_empty_version + ["", " ", " "].each do |empty| + assert_equal "0", Gem::Version.new(empty).version + end + end + def test_prerelease assert_prerelease "1.2.0.a" assert_prerelease "2.9.b" From 2b4bd875ba4add0e7581cb82c0ad2e3bf45d52ea Mon Sep 17 00:00:00 2001 From: Homu Date: Tue, 27 Dec 2016 07:02:36 +0900 Subject: [PATCH 350/707] Auto merge of #1805 - rubygems:seg-test-on-2.4, r=indirect [Travis] Test on 2.4.0 # Description: Yay larger test matrices! # Tasks: - [x] Describe the problem / feature - [x] Write tests - [x] Write code to solve the problem - [x] Get code review from coworkers / friends I will abide by the [code of conduct](https://github.com/rubygems/rubygems/blob/master/CODE_OF_CONDUCT.md). (cherry picked from commit 0ef85421bb44ac51f6deddd7bbb00eb3f712751e) # Conflicts: # test/rubygems/test_gem.rb --- test/rubygems/test_gem.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 78735072..e1ebebff 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1451,6 +1451,7 @@ def test_looks_for_gemdeps_files_automatically_on_start ENV['RUBYGEMS_GEMDEPS'] = "-" out = `#{Gem.ruby.dup.untaint} -I "#{LIB_PATH.untaint}" -rubygems -e "p Gem.loaded_specs.values.map(&:full_name).sort"` + out.sub!(/, "openssl-#{Gem::Version::VERSION_PATTERN}"/, "") assert_equal '["a-1", "b-1", "c-1"]', out.strip end @@ -1484,6 +1485,7 @@ def test_looks_for_gemdeps_files_automatically_on_start_in_parent_dir out = Dir.chdir "sub1" do `#{Gem.ruby.dup.untaint} -I "#{LIB_PATH.untaint}" -rubygems -e "p Gem.loaded_specs.values.map(&:full_name).sort"` end + out.sub!(/, "openssl-#{Gem::Version::VERSION_PATTERN}"/, "") Dir.rmdir "sub1" From 906ce1dc7bcc519793148032230b643a45b38749 Mon Sep 17 00:00:00 2001 From: Liz Abinante Date: Sun, 22 Jan 2017 14:39:51 -0800 Subject: [PATCH 351/707] first pass :dash: at breaking up documentation into good chunks --- bundler/README.md | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/bundler/README.md b/bundler/README.md index 0c7e1e70..56ec5c5c 100644 --- a/bundler/README.md +++ b/bundler/README.md @@ -11,21 +11,28 @@ It does this by managing the gems that the application depends on. Given a list ### Installation and usage +To install: + ``` gem install bundler +``` + +Bundler is most commonly used to manage your application's dependencies. To use it for this: + +``` bundle init echo 'gem "rspec"' >> Gemfile bundle install bundle exec rspec ``` -For help with installation issues, see [ISSUES](https://github.com/bundler/bundler/blob/master/ISSUES.md) - See [bundler.io](http://bundler.io) for the full documentation. ### Troubleshooting -For help with common problems, see [ISSUES](https://github.com/bundler/bundler/blob/master/ISSUES.md). +For help with common problems, see [TROUBLESHOOTING](doc/TROUBLESHOOTING.md). + +Still stuck? Try [filing an issue](doc/contributing/ISSUES.md). ### Supporting @@ -34,13 +41,13 @@ Bundler is maintained by Ruby Together, ### Other questions -To see what has changed in recent versions of Bundler, see the [CHANGELOG](https://github.com/bundler/bundler/blob/master/CHANGELOG.md). +To see what has changed in recent versions of Bundler, see the [CHANGELOG](CHANGELOG.md). -Feel free to chat with the Bundler core team (and many other users) on IRC in the [#bundler](irc://irc.freenode.net/bundler) channel on Freenode, or via email on the [Bundler mailing list](http://groups.google.com/group/ruby-bundler). +To get in touch with the Bundler core team and other Bundler users, please see [getting help](doc/contributing/GETTING_HELP.md). ### Contributing -If you'd like to contribute to Bundler, that's awesome, and we <3 you. There's a guide to contributing to Bundler (both code and general help) over in [DEVELOPMENT](https://github.com/bundler/bundler/blob/master/DEVELOPMENT.md). +If you'd like to contribute to Bundler, that's awesome, and we <3 you. There's a guide to contributing to Bundler (both code and general help) over in [our documentation section](doc/README.md). ### Code of Conduct From 42a6b0ee5a5302aca1d08bdc12064352a61b5b41 Mon Sep 17 00:00:00 2001 From: "toru.yagi" Date: Sat, 28 Jan 2017 11:06:55 +0900 Subject: [PATCH 352/707] Add a test case for Gem::Requirement.create --- test/rubygems/test_gem_requirement.rb | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/rubygems/test_gem_requirement.rb b/test/rubygems/test_gem_requirement.rb index c1100098..3af545d9 100644 --- a/test/rubygems/test_gem_requirement.rb +++ b/test/rubygems/test_gem_requirement.rb @@ -30,6 +30,11 @@ def test_initialize assert_requirement_equal "= 2", v(2) end + def test_create + assert_equal req("= 1"), Gem::Requirement.create("= 1") + assert_equal req(">= 1.2", "<= 1.3"), Gem::Requirement.create([">= 1.2", "<= 1.3"]) + end + def test_empty_requirements_is_none r = Gem::Requirement.new assert_equal true, r.none? From 38f737fc0ff52a45aed0c6f9c3159a40fcf03ac0 Mon Sep 17 00:00:00 2001 From: "toru.yagi" Date: Sat, 28 Jan 2017 13:55:02 +0900 Subject: [PATCH 353/707] Gem::Requirement.create treat arguments as variable-length We can write not only `Gem::Requirement.create([">= 1.2", "<= 1.3"])` but also `Gem::Requirement.create(">= 1.2", "<= 1.3")` --- test/rubygems/test_gem_requirement.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/test/rubygems/test_gem_requirement.rb b/test/rubygems/test_gem_requirement.rb index 3af545d9..ea354f7b 100644 --- a/test/rubygems/test_gem_requirement.rb +++ b/test/rubygems/test_gem_requirement.rb @@ -33,6 +33,7 @@ def test_initialize def test_create assert_equal req("= 1"), Gem::Requirement.create("= 1") assert_equal req(">= 1.2", "<= 1.3"), Gem::Requirement.create([">= 1.2", "<= 1.3"]) + assert_equal req(">= 1.2", "<= 1.3"), Gem::Requirement.create(">= 1.2", "<= 1.3") end def test_empty_requirements_is_none From 5a6f4e556c93e658e6be3426c7c3f7957041664f Mon Sep 17 00:00:00 2001 From: SHIBATA Hiroshi Date: Fri, 17 Feb 2017 10:26:07 +0900 Subject: [PATCH 354/707] Backport from https://github.com/ruby/ruby/commit/fbdec8186e96c48c724ba620ec6f64128999aaf2 Ruby trunk extracted some standard libraries. This fix ignored these gems. --- test/rubygems/test_gem.rb | 57 +++++++++++++++++++++++---------------- 1 file changed, 34 insertions(+), 23 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index e1ebebff..0b533c5f 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1434,14 +1434,6 @@ def test_looks_for_gemdeps_files_automatically_on_start install_specs a, b, c - path = File.join @tempdir, "gem.deps.rb" - - File.open path, "w" do |f| - f.puts "gem 'a'" - f.puts "gem 'b'" - f.puts "gem 'c'" - end - path = File.join(@tempdir, "gd-tmp") install_gem a, :install_dir => path install_gem b, :install_dir => path @@ -1450,10 +1442,24 @@ def test_looks_for_gemdeps_files_automatically_on_start ENV['GEM_PATH'] = path ENV['RUBYGEMS_GEMDEPS'] = "-" - out = `#{Gem.ruby.dup.untaint} -I "#{LIB_PATH.untaint}" -rubygems -e "p Gem.loaded_specs.values.map(&:full_name).sort"` - out.sub!(/, "openssl-#{Gem::Version::VERSION_PATTERN}"/, "") + path = File.join @tempdir, "gem.deps.rb" + + File.open path, "w" do |f| + f.puts "gem 'a'" + end + out0 = IO.popen([Gem.ruby.dup.untaint, "-I#{LIB_PATH}", "-rubygems", + "-eputs Gem.loaded_specs.values.map(&:full_name).sort"], + &:read).split(/\n/) + + File.open path, "a" do |f| + f.puts "gem 'b'" + f.puts "gem 'c'" + end + out = IO.popen([Gem.ruby.dup.untaint, "-I#{LIB_PATH}", "-rubygems", + "-eputs Gem.loaded_specs.values.map(&:full_name).sort"], + &:read).split(/\n/) - assert_equal '["a-1", "b-1", "c-1"]', out.strip + assert_equal ["b-1", "c-1"], out - out0 end def test_looks_for_gemdeps_files_automatically_on_start_in_parent_dir @@ -1465,14 +1471,6 @@ def test_looks_for_gemdeps_files_automatically_on_start_in_parent_dir install_specs a, b, c - path = File.join @tempdir, "gem.deps.rb" - - File.open path, "w" do |f| - f.puts "gem 'a'" - f.puts "gem 'b'" - f.puts "gem 'c'" - end - path = File.join(@tempdir, "gd-tmp") install_gem a, :install_dir => path install_gem b, :install_dir => path @@ -1482,14 +1480,27 @@ def test_looks_for_gemdeps_files_automatically_on_start_in_parent_dir ENV['RUBYGEMS_GEMDEPS'] = "-" Dir.mkdir "sub1" - out = Dir.chdir "sub1" do - `#{Gem.ruby.dup.untaint} -I "#{LIB_PATH.untaint}" -rubygems -e "p Gem.loaded_specs.values.map(&:full_name).sort"` + + path = File.join @tempdir, "gem.deps.rb" + + File.open path, "w" do |f| + f.puts "gem 'a'" + end + out0 = IO.popen([Gem.ruby.dup.untaint, "-Csub1", "-I#{LIB_PATH}", "-rubygems", + "-eputs Gem.loaded_specs.values.map(&:full_name).sort"], + &:read).split(/\n/) + + File.open path, "a" do |f| + f.puts "gem 'b'" + f.puts "gem 'c'" end - out.sub!(/, "openssl-#{Gem::Version::VERSION_PATTERN}"/, "") + out = IO.popen([Gem.ruby.dup.untaint, "-Csub1", "-I#{LIB_PATH}", "-rubygems", + "-eputs Gem.loaded_specs.values.map(&:full_name).sort"], + &:read).split(/\n/) Dir.rmdir "sub1" - assert_equal '["a-1", "b-1", "c-1"]', out.strip + assert_equal ["b-1", "c-1"], out - out0 end def test_register_default_spec From 0e64b22ae9efb3c5a1fc250d06a04f7d9ab89203 Mon Sep 17 00:00:00 2001 From: SHIBATA Hiroshi Date: Fri, 17 Feb 2017 11:19:47 +0900 Subject: [PATCH 355/707] Applied patch for default gems on Ruby 2.5. Original patch was provided by https://github.com/ruby/ruby/commit/fbdec8186e96c48c724ba620ec6f64128999aaf2 --- test/rubygems/test_gem.rb | 57 +++++++++++++++++++++++---------------- 1 file changed, 34 insertions(+), 23 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index c2f1b29b..057fd002 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1495,14 +1495,6 @@ def test_looks_for_gemdeps_files_automatically_on_start install_specs a, b, c - path = File.join @tempdir, "gem.deps.rb" - - File.open path, "w" do |f| - f.puts "gem 'a'" - f.puts "gem 'b'" - f.puts "gem 'c'" - end - path = File.join(@tempdir, "gd-tmp") install_gem a, :install_dir => path install_gem b, :install_dir => path @@ -1511,10 +1503,24 @@ def test_looks_for_gemdeps_files_automatically_on_start ENV['GEM_PATH'] = path ENV['RUBYGEMS_GEMDEPS'] = "-" - out = `#{Gem.ruby.dup.untaint} -I "#{LIB_PATH.untaint}" -I "#{BUNDLER_LIB_PATH.untaint}" -rubygems -e "p Gem.loaded_specs.values.map(&:full_name).sort"` - out.sub!(/, "openssl-#{Gem::Version::VERSION_PATTERN}"/, "") + path = File.join @tempdir, "gem.deps.rb" + + File.open path, "w" do |f| + f.puts "gem 'a'" + end + out0 = IO.popen([Gem.ruby.dup.untaint, "-I#{LIB_PATH}", "-rubygems", + "-eputs Gem.loaded_specs.values.map(&:full_name).sort"], + &:read).split(/\n/) + + File.open path, "a" do |f| + f.puts "gem 'b'" + f.puts "gem 'c'" + end + out = IO.popen([Gem.ruby.dup.untaint, "-I#{LIB_PATH}", "-rubygems", + "-eputs Gem.loaded_specs.values.map(&:full_name).sort"], + &:read).split(/\n/) - assert_equal %W(a-1 b-1 #{BUNDLER_FULL_NAME} c-1).inspect, out.strip + assert_equal ["b-1", BUNDLER_FULL_NAME, "c-1"].inspect, out - out0 end def test_looks_for_gemdeps_files_automatically_on_start_in_parent_dir @@ -1526,14 +1532,6 @@ def test_looks_for_gemdeps_files_automatically_on_start_in_parent_dir install_specs a, b, c - path = File.join @tempdir, "gem.deps.rb" - - File.open path, "w" do |f| - f.puts "gem 'a'" - f.puts "gem 'b'" - f.puts "gem 'c'" - end - path = File.join(@tempdir, "gd-tmp") install_gem a, :install_dir => path install_gem b, :install_dir => path @@ -1543,14 +1541,27 @@ def test_looks_for_gemdeps_files_automatically_on_start_in_parent_dir ENV['RUBYGEMS_GEMDEPS'] = "-" Dir.mkdir "sub1" - out = Dir.chdir "sub1" do - `#{Gem.ruby.dup.untaint} -I "#{LIB_PATH.untaint}" -I "#{BUNDLER_LIB_PATH.untaint}" -rubygems -e "p Gem.loaded_specs.values.map(&:full_name).sort"` + + path = File.join @tempdir, "gem.deps.rb" + + File.open path, "w" do |f| + f.puts "gem 'a'" + end + out0 = IO.popen([Gem.ruby.dup.untaint, "-Csub1", "-I#{LIB_PATH}", "-rubygems", + "-eputs Gem.loaded_specs.values.map(&:full_name).sort"], + &:read).split(/\n/) + + File.open path, "a" do |f| + f.puts "gem 'b'" + f.puts "gem 'c'" end - out.sub!(/, "openssl-#{Gem::Version::VERSION_PATTERN}"/, "") + out = IO.popen([Gem.ruby.dup.untaint, "-Csub1", "-I#{LIB_PATH}", "-rubygems", + "-eputs Gem.loaded_specs.values.map(&:full_name).sort"], + &:read).split(/\n/) Dir.rmdir "sub1" - assert_equal %W(a-1 b-1 #{BUNDLER_FULL_NAME} c-1).inspect, out.strip + assert_equal ["b-1", BUNDLER_FULL_NAME, "c-1"].inspect, out - out0 end def test_register_default_spec From 8ad92ca54a2e0322a3151e24f0cc404977547cd6 Mon Sep 17 00:00:00 2001 From: SHIBATA Hiroshi Date: Fri, 17 Feb 2017 11:56:48 +0900 Subject: [PATCH 356/707] Added missing bundler path. --- test/rubygems/test_gem.rb | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 057fd002..734d9408 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1508,7 +1508,8 @@ def test_looks_for_gemdeps_files_automatically_on_start File.open path, "w" do |f| f.puts "gem 'a'" end - out0 = IO.popen([Gem.ruby.dup.untaint, "-I#{LIB_PATH}", "-rubygems", + out0 = IO.popen([Gem.ruby.dup.untaint, "-I#{LIB_PATH}", + "-I#{BUNDLER_LIB_PATH.untaint}", "-rubygems", "-eputs Gem.loaded_specs.values.map(&:full_name).sort"], &:read).split(/\n/) @@ -1516,7 +1517,8 @@ def test_looks_for_gemdeps_files_automatically_on_start f.puts "gem 'b'" f.puts "gem 'c'" end - out = IO.popen([Gem.ruby.dup.untaint, "-I#{LIB_PATH}", "-rubygems", + out = IO.popen([Gem.ruby.dup.untaint, "-I#{LIB_PATH}", + "-I#{BUNDLER_LIB_PATH.untaint}", "-rubygems", "-eputs Gem.loaded_specs.values.map(&:full_name).sort"], &:read).split(/\n/) @@ -1547,7 +1549,8 @@ def test_looks_for_gemdeps_files_automatically_on_start_in_parent_dir File.open path, "w" do |f| f.puts "gem 'a'" end - out0 = IO.popen([Gem.ruby.dup.untaint, "-Csub1", "-I#{LIB_PATH}", "-rubygems", + out0 = IO.popen([Gem.ruby.dup.untaint, "-Csub1", "-I#{LIB_PATH}", + "-I#{BUNDLER_LIB_PATH.untaint}", "-rubygems", "-eputs Gem.loaded_specs.values.map(&:full_name).sort"], &:read).split(/\n/) @@ -1555,7 +1558,8 @@ def test_looks_for_gemdeps_files_automatically_on_start_in_parent_dir f.puts "gem 'b'" f.puts "gem 'c'" end - out = IO.popen([Gem.ruby.dup.untaint, "-Csub1", "-I#{LIB_PATH}", "-rubygems", + out = IO.popen([Gem.ruby.dup.untaint, "-Csub1", "-I#{LIB_PATH}", + "-I#{BUNDLER_LIB_PATH.untaint}", "-rubygems", "-eputs Gem.loaded_specs.values.map(&:full_name).sort"], &:read).split(/\n/) From f41ae096db1eaaefc5c7321fcf4c248b376fa1f0 Mon Sep 17 00:00:00 2001 From: SHIBATA Hiroshi Date: Fri, 17 Feb 2017 13:39:53 +0900 Subject: [PATCH 357/707] assert with Array --- test/rubygems/test_gem.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 734d9408..8690f60b 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1522,7 +1522,7 @@ def test_looks_for_gemdeps_files_automatically_on_start "-eputs Gem.loaded_specs.values.map(&:full_name).sort"], &:read).split(/\n/) - assert_equal ["b-1", BUNDLER_FULL_NAME, "c-1"].inspect, out - out0 + assert_equal ["b-1", BUNDLER_FULL_NAME, "c-1"], out - out0 end def test_looks_for_gemdeps_files_automatically_on_start_in_parent_dir @@ -1565,7 +1565,7 @@ def test_looks_for_gemdeps_files_automatically_on_start_in_parent_dir Dir.rmdir "sub1" - assert_equal ["b-1", BUNDLER_FULL_NAME, "c-1"].inspect, out - out0 + assert_equal ["b-1", BUNDLER_FULL_NAME, "c-1"], out - out0 end def test_register_default_spec From a5aee94a42dcc0d8be31bb517d9313099e0f939f Mon Sep 17 00:00:00 2001 From: SHIBATA Hiroshi Date: Fri, 17 Feb 2017 13:43:46 +0900 Subject: [PATCH 358/707] Removed needless items on gemspec files. We only assert to difference tests object --- test/rubygems/test_gem.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 8690f60b..d9af7076 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1522,7 +1522,7 @@ def test_looks_for_gemdeps_files_automatically_on_start "-eputs Gem.loaded_specs.values.map(&:full_name).sort"], &:read).split(/\n/) - assert_equal ["b-1", BUNDLER_FULL_NAME, "c-1"], out - out0 + assert_equal ["b-1", "c-1"], out - out0 end def test_looks_for_gemdeps_files_automatically_on_start_in_parent_dir @@ -1565,7 +1565,7 @@ def test_looks_for_gemdeps_files_automatically_on_start_in_parent_dir Dir.rmdir "sub1" - assert_equal ["b-1", BUNDLER_FULL_NAME, "c-1"], out - out0 + assert_equal ["b-1", "c-1"], out - out0 end def test_register_default_spec From 429ce2e3687de1bea5fb3c4bcc98d52cc01de205 Mon Sep 17 00:00:00 2001 From: SHIBATA Hiroshi Date: Fri, 17 Feb 2017 22:53:09 +0900 Subject: [PATCH 359/707] untaint LIB_PATH for Ruby 1.8 support --- test/rubygems/test_gem.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index d9af7076..86faccda 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1508,7 +1508,7 @@ def test_looks_for_gemdeps_files_automatically_on_start File.open path, "w" do |f| f.puts "gem 'a'" end - out0 = IO.popen([Gem.ruby.dup.untaint, "-I#{LIB_PATH}", + out0 = IO.popen([Gem.ruby.dup.untaint, "-I#{LIB_PATH.untaint}", "-I#{BUNDLER_LIB_PATH.untaint}", "-rubygems", "-eputs Gem.loaded_specs.values.map(&:full_name).sort"], &:read).split(/\n/) @@ -1517,7 +1517,7 @@ def test_looks_for_gemdeps_files_automatically_on_start f.puts "gem 'b'" f.puts "gem 'c'" end - out = IO.popen([Gem.ruby.dup.untaint, "-I#{LIB_PATH}", + out = IO.popen([Gem.ruby.dup.untaint, "-I#{LIB_PATH.untaint}", "-I#{BUNDLER_LIB_PATH.untaint}", "-rubygems", "-eputs Gem.loaded_specs.values.map(&:full_name).sort"], &:read).split(/\n/) @@ -1549,7 +1549,7 @@ def test_looks_for_gemdeps_files_automatically_on_start_in_parent_dir File.open path, "w" do |f| f.puts "gem 'a'" end - out0 = IO.popen([Gem.ruby.dup.untaint, "-Csub1", "-I#{LIB_PATH}", + out0 = IO.popen([Gem.ruby.dup.untaint, "-Csub1", "-I#{LIB_PATH.untaint}", "-I#{BUNDLER_LIB_PATH.untaint}", "-rubygems", "-eputs Gem.loaded_specs.values.map(&:full_name).sort"], &:read).split(/\n/) @@ -1558,7 +1558,7 @@ def test_looks_for_gemdeps_files_automatically_on_start_in_parent_dir f.puts "gem 'b'" f.puts "gem 'c'" end - out = IO.popen([Gem.ruby.dup.untaint, "-Csub1", "-I#{LIB_PATH}", + out = IO.popen([Gem.ruby.dup.untaint, "-Csub1", "-I#{LIB_PATH.untaint}", "-I#{BUNDLER_LIB_PATH.untaint}", "-rubygems", "-eputs Gem.loaded_specs.values.map(&:full_name).sort"], &:read).split(/\n/) From 126209de4762384b872e7f60d4a5428e0fc73720 Mon Sep 17 00:00:00 2001 From: SHIBATA Hiroshi Date: Fri, 17 Feb 2017 23:03:51 +0900 Subject: [PATCH 360/707] workaround for Ruby 1.8, IO.popen was not support Array argument. --- test/rubygems/test_gem.rb | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 0b533c5f..a605f9cd 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1443,21 +1443,24 @@ def test_looks_for_gemdeps_files_automatically_on_start ENV['RUBYGEMS_GEMDEPS'] = "-" path = File.join @tempdir, "gem.deps.rb" + cmd = [Gem.ruby.dup.untaint, "-I#{LIB_PATH.untaint}", "-rubygems"] + if RUBY_VERSION < '1.9' + cmd << "-e 'puts Gem.loaded_specs.values.map(&:full_name).sort'" + cmd = cmd.join(' ') + else + cmd << "-eputs Gem.loaded_specs.values.map(&:full_name).sort" + end File.open path, "w" do |f| f.puts "gem 'a'" end - out0 = IO.popen([Gem.ruby.dup.untaint, "-I#{LIB_PATH}", "-rubygems", - "-eputs Gem.loaded_specs.values.map(&:full_name).sort"], - &:read).split(/\n/) + out0 = IO.popen(cmd, &:read).split(/\n/) File.open path, "a" do |f| f.puts "gem 'b'" f.puts "gem 'c'" end - out = IO.popen([Gem.ruby.dup.untaint, "-I#{LIB_PATH}", "-rubygems", - "-eputs Gem.loaded_specs.values.map(&:full_name).sort"], - &:read).split(/\n/) + out = IO.popen(cmd, &:read).split(/\n/) assert_equal ["b-1", "c-1"], out - out0 end @@ -1482,21 +1485,24 @@ def test_looks_for_gemdeps_files_automatically_on_start_in_parent_dir Dir.mkdir "sub1" path = File.join @tempdir, "gem.deps.rb" + cmd = [Gem.ruby.dup.untaint, "-Csub1", "-I#{LIB_PATH.untaint}", "-rubygems"] + if RUBY_VERSION < '1.9' + cmd << "-e 'puts Gem.loaded_specs.values.map(&:full_name).sort'" + cmd = cmd.join(' ') + else + cmd << "-eputs Gem.loaded_specs.values.map(&:full_name).sort" + end File.open path, "w" do |f| f.puts "gem 'a'" end - out0 = IO.popen([Gem.ruby.dup.untaint, "-Csub1", "-I#{LIB_PATH}", "-rubygems", - "-eputs Gem.loaded_specs.values.map(&:full_name).sort"], - &:read).split(/\n/) + out0 = IO.popen(cmd, &:read).split(/\n/) File.open path, "a" do |f| f.puts "gem 'b'" f.puts "gem 'c'" end - out = IO.popen([Gem.ruby.dup.untaint, "-Csub1", "-I#{LIB_PATH}", "-rubygems", - "-eputs Gem.loaded_specs.values.map(&:full_name).sort"], - &:read).split(/\n/) + out = IO.popen(cmd, &:read).split(/\n/) Dir.rmdir "sub1" From d803cfddb619e0e77a51bd75ad0d9a374a03a50e Mon Sep 17 00:00:00 2001 From: SHIBATA Hiroshi Date: Fri, 17 Feb 2017 23:00:53 +0900 Subject: [PATCH 361/707] workaround for Ruby 1.8, IO.popen was not support Array argument. --- test/rubygems/test_gem.rb | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 86faccda..c601e76e 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1504,23 +1504,25 @@ def test_looks_for_gemdeps_files_automatically_on_start ENV['RUBYGEMS_GEMDEPS'] = "-" path = File.join @tempdir, "gem.deps.rb" + cmd = [Gem.ruby.dup.untaint, "-I#{LIB_PATH.untaint}", + "-I#{BUNDLER_LIB_PATH.untaint}", "-rubygems"] + if RUBY_VERSION < '1.9' + cmd << "-e 'puts Gem.loaded_specs.values.map(&:full_name).sort'" + cmd = cmd.join(' ') + else + cmd << "-eputs Gem.loaded_specs.values.map(&:full_name).sort" + end File.open path, "w" do |f| f.puts "gem 'a'" end - out0 = IO.popen([Gem.ruby.dup.untaint, "-I#{LIB_PATH.untaint}", - "-I#{BUNDLER_LIB_PATH.untaint}", "-rubygems", - "-eputs Gem.loaded_specs.values.map(&:full_name).sort"], - &:read).split(/\n/) + out0 = IO.popen(cmd, &:read).split(/\n/) File.open path, "a" do |f| f.puts "gem 'b'" f.puts "gem 'c'" end - out = IO.popen([Gem.ruby.dup.untaint, "-I#{LIB_PATH.untaint}", - "-I#{BUNDLER_LIB_PATH.untaint}", "-rubygems", - "-eputs Gem.loaded_specs.values.map(&:full_name).sort"], - &:read).split(/\n/) + out = IO.popen(cmd, &:read).split(/\n/) assert_equal ["b-1", "c-1"], out - out0 end @@ -1545,23 +1547,25 @@ def test_looks_for_gemdeps_files_automatically_on_start_in_parent_dir Dir.mkdir "sub1" path = File.join @tempdir, "gem.deps.rb" + cmd = [Gem.ruby.dup.untaint, "-Csub1", "-I#{LIB_PATH.untaint}", + "-I#{BUNDLER_LIB_PATH.untaint}", "-rubygems"] + if RUBY_VERSION < '1.9' + cmd << "-e 'puts Gem.loaded_specs.values.map(&:full_name).sort'" + cmd = cmd.join(' ') + else + cmd << "-eputs Gem.loaded_specs.values.map(&:full_name).sort" + end File.open path, "w" do |f| f.puts "gem 'a'" end - out0 = IO.popen([Gem.ruby.dup.untaint, "-Csub1", "-I#{LIB_PATH.untaint}", - "-I#{BUNDLER_LIB_PATH.untaint}", "-rubygems", - "-eputs Gem.loaded_specs.values.map(&:full_name).sort"], - &:read).split(/\n/) + out0 = IO.popen(cmd, &:read).split(/\n/) File.open path, "a" do |f| f.puts "gem 'b'" f.puts "gem 'c'" end - out = IO.popen([Gem.ruby.dup.untaint, "-Csub1", "-I#{LIB_PATH.untaint}", - "-I#{BUNDLER_LIB_PATH.untaint}", "-rubygems", - "-eputs Gem.loaded_specs.values.map(&:full_name).sort"], - &:read).split(/\n/) + out = IO.popen(cmd, &:read).split(/\n/) Dir.rmdir "sub1" From 59b8606330875fc3612c641451968cca3e0f3a6e Mon Sep 17 00:00:00 2001 From: Andre Arko Date: Mon, 27 Feb 2017 21:58:28 -0800 Subject: [PATCH 362/707] clearer, more specific wording about sponsorship and contributing --- bundler/README.md | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/bundler/README.md b/bundler/README.md index 56ec5c5c..a9fb3c16 100644 --- a/bundler/README.md +++ b/bundler/README.md @@ -37,18 +37,20 @@ Still stuck? Try [filing an issue](doc/contributing/ISSUES.md). ### Supporting
-Bundler is maintained by Ruby Together, a grassroots initiative committed to supporting the critical Ruby infrastructure you rely on. Contribute today as an individual or even better, as a company, and ensure that Bundler, RubyGems, and other shared tooling is around for years to come. - -### Other questions - -To see what has changed in recent versions of Bundler, see the [CHANGELOG](CHANGELOG.md). - -To get in touch with the Bundler core team and other Bundler users, please see [getting help](doc/contributing/GETTING_HELP.md). +Ongoing maintenance work on Bundler is funded by Ruby Together, a grassroots initiative committed to supporting the critical Ruby infrastructure you rely on. Contribute today as an individual or even better, as a company, and ensure that Bundler, RubyGems, and other shared tooling is around for years to come. ### Contributing If you'd like to contribute to Bundler, that's awesome, and we <3 you. There's a guide to contributing to Bundler (both code and general help) over in [our documentation section](doc/README.md). +We are glad to receive contributions from anyone, whether or not they help fund our work through Ruby Together. We will never reject contributions because they come from non-members. + ### Code of Conduct Everyone interacting in the Bundler project’s codebases, issue trackers, chat rooms, and mailing lists is expected to follow the [Bundler code of conduct](https://github.com/bundler/bundler/blob/master/CODE_OF_CONDUCT.md). + +### Other questions + +To see what has changed in recent versions of Bundler, see the [CHANGELOG](CHANGELOG.md). + +To get in touch with the Bundler core team and other Bundler users, please see [getting help](doc/contributing/GETTING_HELP.md). From 609528b753ed44f38191615d2ec6af572bff8feb Mon Sep 17 00:00:00 2001 From: Andre Arko Date: Mon, 27 Feb 2017 22:05:56 -0800 Subject: [PATCH 363/707] clearer funding message --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 92a9783b..cea61d79 100644 --- a/README.md +++ b/README.md @@ -29,12 +29,6 @@ For more details and other options, see: ruby setup.rb --help ``` -## SUPPORTING - - - -RubyGems is maintained by [Ruby Together](https://rubytogether.org), a grassroots initiative committed to supporting the critical Ruby infrastructure you rely on. Contribute today [as an individual](https://rubytogether.org/developers) or even better, [as a company](https://rubytogether.org/companies), and ensure that Bundler, RubyGems, and other shared tooling is around for years to come. - ## GETTING HELP ### Support Requests @@ -53,3 +47,9 @@ for letting the RubyGems team know about bugs or problems you're having is ### Bundler Compatibility See http://bundler.io/compatibility for known issues. + +### Supporting + + + +Ongoing maintenance work on RubyGems is funded by [Ruby Together](https://rubytogether.org), a grassroots initiative committed to supporting the critical Ruby infrastructure you rely on. Contribute today [as an individual](https://rubytogether.org/developers) or even better, [as a company](https://rubytogether.org/companies), and ensure that Bundler, RubyGems, and other shared tooling is around for years to come. From 864fc92980213a091113bf38f4ef12d74484d55d Mon Sep 17 00:00:00 2001 From: Andre Arko Date: Mon, 27 Feb 2017 22:08:13 -0800 Subject: [PATCH 364/707] explicitly welcoming all contributors --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index cea61d79..6e2a271a 100644 --- a/README.md +++ b/README.md @@ -53,3 +53,9 @@ See http://bundler.io/compatibility for known issues. Ongoing maintenance work on RubyGems is funded by [Ruby Together](https://rubytogether.org), a grassroots initiative committed to supporting the critical Ruby infrastructure you rely on. Contribute today [as an individual](https://rubytogether.org/developers) or even better, [as a company](https://rubytogether.org/companies), and ensure that Bundler, RubyGems, and other shared tooling is around for years to come. + +### Contributing + +If you'd like to contribute to RubyGems, that's awesome, and we <3 you. Check out our [guide to contributing](https://github.com/rubygems/rubygems/blob/master/CONTRIBUTING.rdoc#how-to-contribute) for more information. + +We are glad to receive contributions from anyone, whether or not they help fund our work through Ruby Together. We will never reject contributions because they come from non-members. From cf54d2accbd80aa4f01ec3601f2d277f1996e8e9 Mon Sep 17 00:00:00 2001 From: Andre Arko Date: Mon, 27 Feb 2017 22:08:29 -0800 Subject: [PATCH 365/707] clearly state the code of conduct up front --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 6e2a271a..228f6c94 100644 --- a/README.md +++ b/README.md @@ -59,3 +59,7 @@ Ongoing maintenance work on RubyGems is funded by [Ruby Together](https://rubyto If you'd like to contribute to RubyGems, that's awesome, and we <3 you. Check out our [guide to contributing](https://github.com/rubygems/rubygems/blob/master/CONTRIBUTING.rdoc#how-to-contribute) for more information. We are glad to receive contributions from anyone, whether or not they help fund our work through Ruby Together. We will never reject contributions because they come from non-members. + +### Code of Conduct + +Everyone interacting in the RubyGems project’s codebases, issue trackers, chat rooms, and mailing lists is expected to follow the [contributor code of conduct](https://github.com/rubygems/rubygems/blob/master/CODE_OF_CONDUCT.md). From 95eeb811140a0cbaf1e875a42f0738bca0d41db6 Mon Sep 17 00:00:00 2001 From: Andre Arko Date: Thu, 2 Mar 2017 01:44:26 -0800 Subject: [PATCH 366/707] update wording to be even clearer --- bundler/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bundler/README.md b/bundler/README.md index a9fb3c16..84cde1dd 100644 --- a/bundler/README.md +++ b/bundler/README.md @@ -37,13 +37,13 @@ Still stuck? Try [filing an issue](doc/contributing/ISSUES.md). ### Supporting
-Ongoing maintenance work on Bundler is funded by Ruby Together, a grassroots initiative committed to supporting the critical Ruby infrastructure you rely on. Contribute today as an individual or even better, as a company, and ensure that Bundler, RubyGems, and other shared tooling is around for years to come. +Ruby Together pays some Bundler maintainers for their ongoing work. As a grassroots initiative committed to supporting the critical Ruby infrastructure you rely on, Ruby Together is funded entirely by the Ruby community. Contribute today as an individual or even better, as a company, and ensure that Bundler, RubyGems, and other shared tooling is around for years to come. ### Contributing If you'd like to contribute to Bundler, that's awesome, and we <3 you. There's a guide to contributing to Bundler (both code and general help) over in [our documentation section](doc/README.md). -We are glad to receive contributions from anyone, whether or not they help fund our work through Ruby Together. We will never reject contributions because they come from non-members. +While some Bundler contributors are compensated by Ruby Together, the project maintainers make decisions independent of Ruby Together. As a project, we welcome contributions regardless of the author’s affiliation with Ruby Together. ### Code of Conduct From 20573164d2a960988ed1c66cbd9e455842932f82 Mon Sep 17 00:00:00 2001 From: Andre Arko Date: Thu, 2 Mar 2017 01:46:26 -0800 Subject: [PATCH 367/707] clarify wording further, h/t @segiddins --- README.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 228f6c94..97ec23d4 100644 --- a/README.md +++ b/README.md @@ -50,15 +50,14 @@ See http://bundler.io/compatibility for known issues. ### Supporting - - -Ongoing maintenance work on RubyGems is funded by [Ruby Together](https://rubytogether.org), a grassroots initiative committed to supporting the critical Ruby infrastructure you rely on. Contribute today [as an individual](https://rubytogether.org/developers) or even better, [as a company](https://rubytogether.org/companies), and ensure that Bundler, RubyGems, and other shared tooling is around for years to come. +
+Ruby Together pays some RubyGems maintainers for their ongoing work. As a grassroots initiative committed to supporting the critical Ruby infrastructure you rely on, Ruby Together is funded entirely by the Ruby community. Contribute today as an individual or even better, as a company, and ensure that RubyGems, Bundler, and other shared tooling is around for years to come. ### Contributing If you'd like to contribute to RubyGems, that's awesome, and we <3 you. Check out our [guide to contributing](https://github.com/rubygems/rubygems/blob/master/CONTRIBUTING.rdoc#how-to-contribute) for more information. -We are glad to receive contributions from anyone, whether or not they help fund our work through Ruby Together. We will never reject contributions because they come from non-members. +While some RubyGems contributors are compensated by Ruby Together, the project maintainers make decisions independent of Ruby Together. As a project, we welcome contributions regardless of the author’s affiliation with Ruby Together. ### Code of Conduct From 96a49ce0f632dfa055bb6a0b259f0c7fc75db191 Mon Sep 17 00:00:00 2001 From: Andre Arko Date: Thu, 2 Mar 2017 14:47:37 -0800 Subject: [PATCH 368/707] re-order it to prioritize users looking for info --- bundler/README.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/bundler/README.md b/bundler/README.md index 84cde1dd..60e719db 100644 --- a/bundler/README.md +++ b/bundler/README.md @@ -34,10 +34,11 @@ For help with common problems, see [TROUBLESHOOTING](doc/TROUBLESHOOTING.md). Still stuck? Try [filing an issue](doc/contributing/ISSUES.md). -### Supporting +### Other questions -
-Ruby Together pays some Bundler maintainers for their ongoing work. As a grassroots initiative committed to supporting the critical Ruby infrastructure you rely on, Ruby Together is funded entirely by the Ruby community. Contribute today as an individual or even better, as a company, and ensure that Bundler, RubyGems, and other shared tooling is around for years to come. +To see what has changed in recent versions of Bundler, see the [CHANGELOG](CHANGELOG.md). + +To get in touch with the Bundler core team and other Bundler users, please see [getting help](doc/contributing/GETTING_HELP.md). ### Contributing @@ -45,12 +46,11 @@ If you'd like to contribute to Bundler, that's awesome, and we <3 you. There's a While some Bundler contributors are compensated by Ruby Together, the project maintainers make decisions independent of Ruby Together. As a project, we welcome contributions regardless of the author’s affiliation with Ruby Together. -### Code of Conduct - -Everyone interacting in the Bundler project’s codebases, issue trackers, chat rooms, and mailing lists is expected to follow the [Bundler code of conduct](https://github.com/bundler/bundler/blob/master/CODE_OF_CONDUCT.md). +### Supporting -### Other questions +
+Ruby Together pays some Bundler maintainers for their ongoing work. As a grassroots initiative committed to supporting the critical Ruby infrastructure you rely on, Ruby Together is funded entirely by the Ruby community. Contribute today as an individual or even better, as a company, and ensure that Bundler, RubyGems, and other shared tooling is around for years to come. -To see what has changed in recent versions of Bundler, see the [CHANGELOG](CHANGELOG.md). +### Code of Conduct -To get in touch with the Bundler core team and other Bundler users, please see [getting help](doc/contributing/GETTING_HELP.md). +Everyone interacting in the Bundler project’s codebases, issue trackers, chat rooms, and mailing lists is expected to follow the [Bundler code of conduct](https://github.com/bundler/bundler/blob/master/CODE_OF_CONDUCT.md). From c464f6020043f77b130b0b326cfdf72793ba4922 Mon Sep 17 00:00:00 2001 From: Kazuaki Matsuo Date: Wed, 29 Mar 2017 18:53:37 +0900 Subject: [PATCH 369/707] fix tesself_find_files_with_gemfile since it depends on local environments --- test/rubygems/test_gem.rb | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index c601e76e..d36ea3eb 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -523,7 +523,7 @@ def test_self_find_files_with_gemfile skip if RUBY_VERSION <= "1.8.7" cwd = File.expand_path("test/rubygems", @@project_dir) - $LOAD_PATH.unshift cwd + actual_load_path = $LOAD_PATH.unshift(cwd).dup discover_path = File.join 'lib', 'sff', 'discover.rb' @@ -549,12 +549,12 @@ def test_self_find_files_with_gemfile expected = [ File.expand_path('test/rubygems/sff/discover.rb', @@project_dir), File.join(foo1.full_gem_path, discover_path) - ] + ].sort - assert_equal expected, Gem.find_files('sff/discover') - assert_equal expected, Gem.find_files('sff/**.rb'), '[ruby-core:31730]' + assert_equal expected, Gem.find_files('sff/discover').sort + assert_equal expected, Gem.find_files('sff/**.rb').sort, '[ruby-core:31730]' ensure - assert_equal cwd, $LOAD_PATH.shift unless RUBY_VERSION <= "1.8.7" + assert_equal cwd, actual_load_path.shift unless RUBY_VERSION <= "1.8.7" end def test_self_find_latest_files From b6cab81e76a7239440cdbd520cddc41663b309bd Mon Sep 17 00:00:00 2001 From: Kazuaki Matsuo Date: Thu, 30 Mar 2017 00:11:12 +0900 Subject: [PATCH 370/707] fix tesself_find_files_with_gemfile since it depends on local environments --- test/rubygems/test_gem.rb | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index a605f9cd..a3d1f797 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -492,7 +492,7 @@ def test_self_find_files_with_gemfile skip if RUBY_VERSION <= "1.8.7" cwd = File.expand_path("test/rubygems", @@project_dir) - $LOAD_PATH.unshift cwd + actual_load_path = $LOAD_PATH.unshift(cwd).dup discover_path = File.join 'lib', 'sff', 'discover.rb' @@ -518,12 +518,12 @@ def test_self_find_files_with_gemfile expected = [ File.expand_path('test/rubygems/sff/discover.rb', @@project_dir), File.join(foo1.full_gem_path, discover_path) - ] + ].sort - assert_equal expected, Gem.find_files('sff/discover') - assert_equal expected, Gem.find_files('sff/**.rb'), '[ruby-core:31730]' + assert_equal expected, Gem.find_files('sff/discover').sort + assert_equal expected, Gem.find_files('sff/**.rb').sort, '[ruby-core:31730]' ensure - assert_equal cwd, $LOAD_PATH.shift unless RUBY_VERSION <= "1.8.7" + assert_equal cwd, actual_load_path.shift unless RUBY_VERSION <= "1.8.7" end def test_self_find_latest_files From 27770fb0458566a968db4a993f02b2e7c18da5a5 Mon Sep 17 00:00:00 2001 From: Samuel Giddins Date: Tue, 28 Mar 2017 14:28:30 -0500 Subject: [PATCH 371/707] [VersionRanges] Say that != x, = x is empty --- bundler/spec/bundler/version_ranges_spec.rb | 37 +++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 bundler/spec/bundler/version_ranges_spec.rb diff --git a/bundler/spec/bundler/version_ranges_spec.rb b/bundler/spec/bundler/version_ranges_spec.rb new file mode 100644 index 00000000..f746aa88 --- /dev/null +++ b/bundler/spec/bundler/version_ranges_spec.rb @@ -0,0 +1,37 @@ +# frozen_string_literal: true +require "spec_helper" +require "bundler/version_ranges" + +RSpec.describe Bundler::VersionRanges do + describe ".empty?" do + shared_examples_for "empty?" do |exp, *req| + it "returns #{exp} for #{req}" do + r = Gem::Requirement.new(*req) + ranges = described_class.for(r) + expect(described_class.empty?(*ranges)).to eq(exp), "expected `#{r}` #{exp ? "" : "not "}to be empty" + end + end + + include_examples "empty?", false + include_examples "empty?", false, "!= 1" + include_examples "empty?", false, "!= 1", "= 2" + include_examples "empty?", false, "!= 1", "> 1" + include_examples "empty?", false, "!= 1", ">= 1" + include_examples "empty?", false, "= 1", ">= 0.1", "<= 1.1" + include_examples "empty?", false, "= 1", ">= 1", "<= 1" + include_examples "empty?", false, "= 1", "~> 1" + include_examples "empty?", false, ">= 0.z", "= 0" + include_examples "empty?", false, ">= 0" + include_examples "empty?", false, ">= 1.0.0", "< 2.0.0" + include_examples "empty?", false, "~> 1" + include_examples "empty?", false, "~> 2.0", "~> 2.1" + include_examples "empty?", true, "!= 1", "< 2", "> 2" + include_examples "empty?", true, "!= 1", "<= 1", ">= 1" + include_examples "empty?", true, "< 2", "> 2" + include_examples "empty?", true, "= 1", "!= 1" + include_examples "empty?", true, "= 1", "= 2" + include_examples "empty?", true, "= 1", "~> 2" + include_examples "empty?", true, ">= 0", "<= 0.a" + include_examples "empty?", true, "~> 2.0", "~> 3" + end +end From 038117176a781220e06a30b7cd7344c9b91c5598 Mon Sep 17 00:00:00 2001 From: Andre Arko Date: Fri, 31 Mar 2017 12:05:42 -0700 Subject: [PATCH 372/707] less commas, float the logo left --- bundler/README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/bundler/README.md b/bundler/README.md index 60e719db..7fe9efde 100644 --- a/bundler/README.md +++ b/bundler/README.md @@ -48,8 +48,9 @@ While some Bundler contributors are compensated by Ruby Together, the project ma ### Supporting -
-Ruby Together pays some Bundler maintainers for their ongoing work. As a grassroots initiative committed to supporting the critical Ruby infrastructure you rely on, Ruby Together is funded entirely by the Ruby community. Contribute today as an individual or even better, as a company, and ensure that Bundler, RubyGems, and other shared tooling is around for years to come. + +Ruby Together pays some Bundler maintainers for their ongoing work. As a grassroots initiative committed to supporting the critical Ruby infrastructure you rely on, Ruby Together is funded entirely by the Ruby community. Contribute today as an individual or (better yet) as a company to ensure that Bundler, RubyGems, and other shared tooling is around for years to come. +

### Code of Conduct From e286189da3f86f8e3234abf45968711525cbcb30 Mon Sep 17 00:00:00 2001 From: Andre Arko Date: Fri, 31 Mar 2017 12:07:57 -0700 Subject: [PATCH 373/707] github strips css, never mind --- bundler/README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/bundler/README.md b/bundler/README.md index 7fe9efde..f26e10a7 100644 --- a/bundler/README.md +++ b/bundler/README.md @@ -48,9 +48,8 @@ While some Bundler contributors are compensated by Ruby Together, the project ma ### Supporting - +
Ruby Together pays some Bundler maintainers for their ongoing work. As a grassroots initiative committed to supporting the critical Ruby infrastructure you rely on, Ruby Together is funded entirely by the Ruby community. Contribute today as an individual or (better yet) as a company to ensure that Bundler, RubyGems, and other shared tooling is around for years to come. -

### Code of Conduct From eaae0ddfec940c104ade2031809470c1629f53f7 Mon Sep 17 00:00:00 2001 From: Samuel Giddins Date: Fri, 28 Apr 2017 10:24:43 +0200 Subject: [PATCH 374/707] Allow Gem.finish_resolve to respect already-activated specs --- test/rubygems/test_gem.rb | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index d36ea3eb..5a3c382a 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -75,6 +75,29 @@ def test_self_finish_resolve_wtf end end + def test_self_finish_resolve_respects_loaded_specs + save_loaded_features do + a1 = new_spec "a", "1", "b" => "> 0" + b1 = new_spec "b", "1", "c" => ">= 1" + b2 = new_spec "b", "2", "c" => ">= 2" + c1 = new_spec "c", "1" + c2 = new_spec "c", "2" + + install_specs c1, c2, b1, b2, a1 + + a1.activate + c1.activate + + assert_equal %w(a-1 c-1), loaded_spec_names + assert_equal ["b (> 0)"], unresolved_names + + Gem.finish_resolve + + assert_equal %w(a-1 b-1 c-1), loaded_spec_names + assert_equal [], unresolved_names + end + end + def test_self_install spec_fetcher do |f| f.gem 'a', 1 From 9485849b4f7b785b8b09c4c80e398724e94e4f7a Mon Sep 17 00:00:00 2001 From: Homu Date: Mon, 1 May 2017 03:03:42 +0900 Subject: [PATCH 375/707] Auto merge of #1910 - rubygems:seg-finish-resolve-respects-activated, r=indirect Allow Gem.finish_resolve to respect already-activated specs # Description: Previously, if a gem was already activated, `finish_resolve` wouldn't consider the activated dependency as a requirement, always leading to a hard error. This makes finish_resolve work as you'd respect. # Tasks: - [x] Describe the problem / feature - [x] Write tests - [x] Write code to solve the problem - [ ] Get code review from coworkers / friends I will abide by the [code of conduct](https://github.com/rubygems/rubygems/blob/master/CODE_OF_CONDUCT.md). (cherry picked from commit fd24f01180fbde3716fd1a4225f661bdbb44937d) --- test/rubygems/test_gem.rb | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index a3d1f797..62b36dfd 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -75,6 +75,29 @@ def test_self_finish_resolve_wtf end end + def test_self_finish_resolve_respects_loaded_specs + save_loaded_features do + a1 = new_spec "a", "1", "b" => "> 0" + b1 = new_spec "b", "1", "c" => ">= 1" + b2 = new_spec "b", "2", "c" => ">= 2" + c1 = new_spec "c", "1" + c2 = new_spec "c", "2" + + install_specs c1, c2, b1, b2, a1 + + a1.activate + c1.activate + + assert_equal %w(a-1 c-1), loaded_spec_names + assert_equal ["b (> 0)"], unresolved_names + + Gem.finish_resolve + + assert_equal %w(a-1 b-1 c-1), loaded_spec_names + assert_equal [], unresolved_names + end + end + def test_self_install spec_fetcher do |f| f.gem 'a', 1 From 28859f19547c7457951682ed7c8f93e46831262e Mon Sep 17 00:00:00 2001 From: Koichi ITO Date: Wed, 3 May 2017 14:01:52 +0900 Subject: [PATCH 376/707] Specify `--require spec_helper` in .rspec --- bundler/spec/bundler/version_ranges_spec.rb | 1 - bundler/spec/realworld/edgecases_spec.rb | 1 - 2 files changed, 2 deletions(-) diff --git a/bundler/spec/bundler/version_ranges_spec.rb b/bundler/spec/bundler/version_ranges_spec.rb index f746aa88..a69ab2dc 100644 --- a/bundler/spec/bundler/version_ranges_spec.rb +++ b/bundler/spec/bundler/version_ranges_spec.rb @@ -1,5 +1,4 @@ # frozen_string_literal: true -require "spec_helper" require "bundler/version_ranges" RSpec.describe Bundler::VersionRanges do diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index 302fd57c..6de20798 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -1,5 +1,4 @@ # frozen_string_literal: true -require "spec_helper" RSpec.describe "real world edgecases", :realworld => true, :sometimes => true do def rubygems_version(name, requirement) From 95b26e018535f7968046d0ddd9ef1a652ad9956c Mon Sep 17 00:00:00 2001 From: Tsukuru Tanimichi Date: Sun, 7 May 2017 17:16:02 +0900 Subject: [PATCH 377/707] Modify the return value of Gem::Version.correct? Before: ```ruby Gem::Version.correct?("5.1") # => 0 Gem::Version.correct?("an incorrect version") # => nil ``` After: ```ruby Gem::Version.correct?("5.1") # => true Gem::Version.correct?("an incorrect version") # => false ``` --- test/rubygems/test_gem_version.rb | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/rubygems/test_gem_version.rb b/test/rubygems/test_gem_version.rb index 42d31fec..941094d6 100644 --- a/test/rubygems/test_gem_version.rb +++ b/test/rubygems/test_gem_version.rb @@ -41,6 +41,11 @@ def test_class_create assert_equal v('1.1'), Gem::Version.create(ver) end + def test_class_correct + assert Gem::Version.correct?("5.1") + refute Gem::Version.correct?("an incorrect version") + end + def test_class_new_subclass v1 = Gem::Version.new '1' v2 = V.new '1' From 3de4e1ed6c1e4d54b0a048dc1d791cf043a8bb60 Mon Sep 17 00:00:00 2001 From: Jun Aruga Date: Wed, 10 May 2017 14:48:43 +0200 Subject: [PATCH 378/707] Add Travis and Appveyor build status to README. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 97ec23d4..a3e38b2f 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# RubyGems +# RubyGems [![Travis Build Status](https://secure.travis-ci.org/rubygems/rubygems.svg?branch=master)](http://travis-ci.org/rubygems/rubygems) [![Appveyor Build Status](https://ci.appveyor.com/api/projects/status/github/rubygems/rubygems?branch=master&svg=true)](https://ci.appveyor.com/project/rubygems/rubygems?branch=master) RubyGems is a package management framework for Ruby. From a5de99efb48c8ae969d92b0b777052767150b5c6 Mon Sep 17 00:00:00 2001 From: Tsukuru Tanimichi Date: Thu, 11 May 2017 13:34:14 +0900 Subject: [PATCH 379/707] Use assert_equal instead of assert and refute --- test/rubygems/test_gem_version.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/rubygems/test_gem_version.rb b/test/rubygems/test_gem_version.rb index 941094d6..72b27c08 100644 --- a/test/rubygems/test_gem_version.rb +++ b/test/rubygems/test_gem_version.rb @@ -42,8 +42,8 @@ def test_class_create end def test_class_correct - assert Gem::Version.correct?("5.1") - refute Gem::Version.correct?("an incorrect version") + assert_equal true, Gem::Version.correct?("5.1") + assert_equal false, Gem::Version.correct?("an incorrect version") end def test_class_new_subclass From e3d759302037991b97acc95a4025abd0db38b1f5 Mon Sep 17 00:00:00 2001 From: Samuel Giddins Date: Mon, 23 Jan 2017 14:15:13 -0600 Subject: [PATCH 380/707] Add a test for CVE-2013-4287 See https://github.com/rubygems/rubygems/pull/1126 for context --- test/rubygems/test_gem_version.rb | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/test/rubygems/test_gem_version.rb b/test/rubygems/test_gem_version.rb index 72b27c08..56c81866 100644 --- a/test/rubygems/test_gem_version.rb +++ b/test/rubygems/test_gem_version.rb @@ -82,18 +82,23 @@ def test_initialize assert_version_equal "1", 1 end - def test_initialize_bad - %W[ + def test_initialize_invalid + invalid_versions = %W[ junk 1.0\n2.0 1..2 1.2\ 3.4 - ].each do |bad| - e = assert_raises ArgumentError, bad do - Gem::Version.new bad + ] + + # DON'T TOUCH THIS WITHOUT CHECKING CVE-2013-4287 + invalid_versions << "2.3422222.222.222222222.22222.ads0as.dasd0.ddd2222.2.qd3e." + + invalid_versions.each do |invalid| + e = assert_raises ArgumentError, invalid do + Gem::Version.new invalid end - assert_equal "Malformed version number string #{bad}", e.message, bad + assert_equal "Malformed version number string #{invalid}", e.message, invalid end end From c7ba5bd8afd74d04e82183d07f829439d2c74808 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Suszy=C5=84ski=20Krzysztof?= Date: Tue, 13 Jun 2017 16:51:12 +0200 Subject: [PATCH 381/707] Initial commit From 39581e91f31839769fd0adc68fbedd3625e671fe Mon Sep 17 00:00:00 2001 From: Samuel Giddins Date: Wed, 30 Nov 2016 15:15:30 -0600 Subject: [PATCH 382/707] [Realworld] Use VCR for network requests --- bundler/spec/realworld/edgecases_spec.rb | 27 ++++++++++++++---------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index 6de20798..8787a2d4 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -2,17 +2,22 @@ RSpec.describe "real world edgecases", :realworld => true, :sometimes => true do def rubygems_version(name, requirement) - require "bundler/source/rubygems/remote" - require "bundler/fetcher" - source = Bundler::Source::Rubygems::Remote.new(URI("https://rubygems.org")) - fetcher = Bundler::Fetcher.new(source) - index = fetcher.specs([name], nil) - rubygem = index.search(Gem::Dependency.new(name, requirement)).last - if rubygem.nil? - raise "Could not find #{name} (#{requirement}) on rubygems.org!\n" \ - "Found specs:\n#{index.send(:specs).inspect}" - end - "#{name} (#{rubygem.version})" + ruby! <<-RUBY + ENV["BUNDLER_SPEC_VCR_CASSETTE_NAME"] = #{RSpec.current_example.full_description.dump} + require #{File.expand_path("../../support/artifice/vcr.rb", __FILE__).dump} + require "bundler" + require "bundler/source/rubygems/remote" + require "bundler/fetcher" + source = Bundler::Source::Rubygems::Remote.new(URI("https://rubygems.org")) + fetcher = Bundler::Fetcher.new(source) + index = fetcher.specs([#{name.dump}], nil) + rubygem = index.search(Gem::Dependency.new(#{name.dump}, #{requirement.dump})).last + if rubygem.nil? + raise "Could not find #{name} (#{requirement}) on rubygems.org!\n" \ + "Found specs:\n\#{index.send(:specs).inspect}" + end + "#{name} (\#{rubygem.version})" + RUBY end # there is no rbx-relative-require gem that will install on 1.9 From 2cee69d7a569ada9b3c2ae79e602cb8cfd2bf6fc Mon Sep 17 00:00:00 2001 From: Samuel Giddins Date: Fri, 23 Dec 2016 15:58:46 +0100 Subject: [PATCH 383/707] Use a single cassette for the realworld specs --- bundler/spec/realworld/edgecases_spec.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index 8787a2d4..e91e1b19 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -3,7 +3,6 @@ RSpec.describe "real world edgecases", :realworld => true, :sometimes => true do def rubygems_version(name, requirement) ruby! <<-RUBY - ENV["BUNDLER_SPEC_VCR_CASSETTE_NAME"] = #{RSpec.current_example.full_description.dump} require #{File.expand_path("../../support/artifice/vcr.rb", __FILE__).dump} require "bundler" require "bundler/source/rubygems/remote" From 46d4132127cdb0e65820c46421e9170fcf6290e6 Mon Sep 17 00:00:00 2001 From: Samuel Giddins Date: Wed, 21 Jun 2017 19:22:40 -0500 Subject: [PATCH 384/707] Remove all references to the Bundler postit trampoline It has now been removed from Bundler entirely --- test/rubygems/test_gem.rb | 28 ---------------------------- 1 file changed, 28 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 5a3c382a..cdd3fe3b 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1481,34 +1481,6 @@ def test_auto_activation_of_detected_gemdeps_file BUNDLER_LIB_PATH = File.expand_path $LOAD_PATH.find {|lp| File.file?(File.join(lp, "bundler.rb")) }.dup.untaint BUNDLER_FULL_NAME = "bundler-#{Bundler::VERSION}" - def test_use_gemdeps_uses_bundler_postit_trampoline - refute_includes $LOADED_FEATURES, File.join(BUNDLER_LIB_PATH, "bundler/postit_trampoline.rb".dup.untaint) - ENV.delete("BUNDLE_TRAMPOLINE_DISABLE") - - a = new_spec "a", "1", nil, "lib/a.rb" - b = new_spec "b", "1", nil, "lib/b.rb" - c = new_spec "c", "1", nil, "lib/c.rb" - - install_specs a, b, c - - path = File.join @tempdir, "gem.deps.rb" - - File.open path, "w" do |f| - f.puts "gem 'a'" - f.puts "gem 'b'" - f.puts "gem 'c'" - end - - ENV['RUBYGEMS_GEMDEPS'] = path - - Gem.detect_gemdeps - - assert_equal %W(a-1 b-1 #{BUNDLER_FULL_NAME} c-1), loaded_spec_names - - trampoline_path = RUBY_VERSION > "1.9" ? File.join(BUNDLER_LIB_PATH, "bundler/postit_trampoline.rb".dup.untaint) : "bundler/postit_trampoline.rb" - assert_includes $LOADED_FEATURES, trampoline_path - end - def test_looks_for_gemdeps_files_automatically_on_start util_clear_gems From 4f5f1fa76bad10a79cc653abf2539d0c62a9af77 Mon Sep 17 00:00:00 2001 From: Andre Medeiros Date: Fri, 23 Jun 2017 14:23:59 -0400 Subject: [PATCH 385/707] Add Slack badge to README --- bundler/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/bundler/README.md b/bundler/README.md index f26e10a7..3f8fd13c 100644 --- a/bundler/README.md +++ b/bundler/README.md @@ -2,6 +2,7 @@ [![Build Status](https://img.shields.io/travis/bundler/bundler/master.svg?style=flat)](https://travis-ci.org/bundler/bundler) [![Code Climate](https://img.shields.io/codeclimate/github/bundler/bundler.svg?style=flat)](https://codeclimate.com/github/bundler/bundler) [![Inline docs ](http://inch-ci.org/github/bundler/bundler.svg?style=flat)](http://inch-ci.org/github/bundler/bundler) +[![Slack ](http://bundler-slackin.herokuapp.com/badge.svg)](http://bundler-slackin.herokuapp.com) # Bundler: a gem to bundle gems From 37e97b1289d756331a35e3fe95ad245b51a66674 Mon Sep 17 00:00:00 2001 From: Samuel Giddins Date: Thu, 22 Jun 2017 17:36:20 -0500 Subject: [PATCH 386/707] Improve realworld specs on 2.0 --- bundler/spec/realworld/edgecases_spec.rb | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index e91e1b19..fbf88577 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -79,7 +79,7 @@ def rubygems_version(name, requirement) gem "gxapi_rails", "< 0.1.0" # 0.1.0 was released way after the test was written gem 'rack-cache', '1.2.0' # last version that works on Ruby 1.9 G - bundle :lock + bundle! :lock expect(lockfile).to include("gxapi_rails (0.0.6)") end @@ -92,7 +92,7 @@ def rubygems_version(name, requirement) gem "activerecord", "~> 3.0" gem "builder", "~> 2.1.2" G - bundle :lock + bundle! :lock expect(lockfile).to include(rubygems_version("i18n", "~> 0.6.0")) expect(lockfile).to include(rubygems_version("activesupport", "~> 3.0")) end @@ -223,9 +223,6 @@ def rubygems_version(name, requirement) DEPENDENCIES paperclip (~> 5.1.0) rails (~> 4.2.7.1) - - BUNDLED WITH - 1.13.1 L bundle! "lock --update paperclip" @@ -250,6 +247,7 @@ def rubygems_version(name, requirement) it "checks out git repos when the lockfile is corrupted" do gemfile <<-G source "https://rubygems.org" + git_source(:github) {|repo| "https://github.com/\#{repo}.git" } gem 'activerecord', :github => 'carlhuda/rails-bundler-test', :branch => 'master' gem 'activesupport', :github => 'carlhuda/rails-bundler-test', :branch => 'master' @@ -258,7 +256,7 @@ def rubygems_version(name, requirement) lockfile <<-L GIT - remote: git://github.com/carlhuda/rails-bundler-test.git + remote: https://github.com/carlhuda/rails-bundler-test.git revision: 369e28a87419565f1940815219ea9200474589d4 branch: master specs: @@ -285,7 +283,7 @@ def rubygems_version(name, requirement) multi_json (~> 1.0) GIT - remote: git://github.com/carlhuda/rails-bundler-test.git + remote: https://github.com/carlhuda/rails-bundler-test.git revision: 369e28a87419565f1940815219ea9200474589d4 branch: master specs: @@ -312,7 +310,7 @@ def rubygems_version(name, requirement) multi_json (~> 1.0) GIT - remote: git://github.com/carlhuda/rails-bundler-test.git + remote: https://github.com/carlhuda/rails-bundler-test.git revision: 369e28a87419565f1940815219ea9200474589d4 branch: master specs: @@ -369,9 +367,8 @@ def rubygems_version(name, requirement) activesupport! L - bundle :lock - expect(err).to eq("") - expect(exitstatus).to eq(0) if exitstatus + bundle! :lock + expect(last_command.stderr).to lack_errors end it "outputs a helpful error message when gems have invalid gemspecs" do From 30dfab011276b44c6d49ae18ec3e883b8efd24d7 Mon Sep 17 00:00:00 2001 From: Colby Swandale Date: Sat, 15 Jul 2017 13:01:35 +1000 Subject: [PATCH 387/707] Add documentation section to README and fix a few documentation related issues. * Add a new section in the README covering the RubyGems documentation and RubyGems guides. * Update link to the RubyGems API to rubydoc.info since rubyforce.org has been shutdown * Add link to homepage of the referenced graph gem * fix few small syntax issues --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index a3e38b2f..79e60429 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,14 @@ For more details and other options, see: ruby setup.rb --help ``` +## Documentation + +RubyGems uses [rdoc](https://github.com/rdoc/rdoc) for documentation. A compiled set of the docs +can be viewed online at http://www.rubydoc.info/github/rubygems/rubygems + +RubyGems also provides a comprehensive set of guides which covers numerous topics such as +creating a new gem, security practices and other resources at http://guides.rubygems.org + ## GETTING HELP ### Support Requests From 549a8e497dac14c1b00d75b060d1a02eea284bbb Mon Sep 17 00:00:00 2001 From: Koichi ITO Date: Sat, 15 Jul 2017 19:11:50 +0900 Subject: [PATCH 388/707] [RuboCop] Enable Layout/EmptyLineAfterMagicComment cop --- bundler/spec/bundler/version_ranges_spec.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/bundler/spec/bundler/version_ranges_spec.rb b/bundler/spec/bundler/version_ranges_spec.rb index a69ab2dc..ccbb9285 100644 --- a/bundler/spec/bundler/version_ranges_spec.rb +++ b/bundler/spec/bundler/version_ranges_spec.rb @@ -1,4 +1,5 @@ # frozen_string_literal: true + require "bundler/version_ranges" RSpec.describe Bundler::VersionRanges do From 87fa498e9cbe5665f41ce52bd1d30a3cf6a7d140 Mon Sep 17 00:00:00 2001 From: Samuel Giddins Date: Tue, 11 Jul 2017 15:29:35 -0500 Subject: [PATCH 389/707] Fix the realworld specs under Bundler 2 --- bundler/spec/realworld/edgecases_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index fbf88577..aa60e20b 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -239,7 +239,7 @@ def rubygems_version(name, requirement) gem 'rack', '1.0.1' G - bundle "install --path vendor/bundle" + bundle! :install, forgotten_command_line_options(:path => "vendor/bundle") expect(err).not_to include("Could not find rake") expect(err).to lack_errors end From 7f4b736ae81852f969a6be62b2b0f60e44e36aa4 Mon Sep 17 00:00:00 2001 From: Patricia Arbona Date: Thu, 20 Jul 2017 22:32:25 -0500 Subject: [PATCH 390/707] Add instructions on how to update bundler, install prereleases, and uninstall in README --- bundler/README.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/bundler/README.md b/bundler/README.md index 3f8fd13c..feb41ba7 100644 --- a/bundler/README.md +++ b/bundler/README.md @@ -18,6 +18,22 @@ To install: gem install bundler ``` +To update: + +- Run `gem install bundler` again + +To install prereleases: + +``` +gem install bundler --pre +``` + +To uninstall: + +``` +gem uninstall bundler +``` + Bundler is most commonly used to manage your application's dependencies. To use it for this: ``` From 300077ce79a11aa37880a8109ff4c92b7a3c70d7 Mon Sep 17 00:00:00 2001 From: Andre Arko Date: Thu, 20 Jul 2017 23:23:49 -0700 Subject: [PATCH 391/707] collapse examples where possible --- bundler/README.md | 20 +++----------------- 1 file changed, 3 insertions(+), 17 deletions(-) diff --git a/bundler/README.md b/bundler/README.md index feb41ba7..649b7771 100644 --- a/bundler/README.md +++ b/bundler/README.md @@ -12,29 +12,15 @@ It does this by managing the gems that the application depends on. Given a list ### Installation and usage -To install: +To install (or update to the latest version): ``` gem install bundler ``` -To update: +To install a prerelease version (if one is available), run `gem install bundler --pre`. To uninstall Bundler, run `gem uninstall bundler`. -- Run `gem install bundler` again - -To install prereleases: - -``` -gem install bundler --pre -``` - -To uninstall: - -``` -gem uninstall bundler -``` - -Bundler is most commonly used to manage your application's dependencies. To use it for this: +Bundler is most commonly used to manage your application's dependencies. For example, these commands will allow you to use Bundler to manage the `rspec` gem for your application: ``` bundle init From 78779713c7092b85befa0703ccbe534813a44fe8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Suszy=C5=84ski=20Krzysztof?= Date: Mon, 31 Jul 2017 17:51:07 +0200 Subject: [PATCH 392/707] Adding Gem requirement parser --- puppeter/domain/model/gemrequirement.py | 167 ++++++++++++++++++++++ tests/domain/model/test_gemrequirement.py | 50 +++++++ 2 files changed, 217 insertions(+) create mode 100644 puppeter/domain/model/gemrequirement.py create mode 100644 tests/domain/model/test_gemrequirement.py diff --git a/puppeter/domain/model/gemrequirement.py b/puppeter/domain/model/gemrequirement.py new file mode 100644 index 00000000..32322177 --- /dev/null +++ b/puppeter/domain/model/gemrequirement.py @@ -0,0 +1,167 @@ +import re + +from six import iterkeys, itervalues +from typing import Callable, Sequence, MutableSequence + +from puppeter.domain import default + + +class GemVersion: + VERSION_PATTERN = '[0-9]+(?:\.[0-9a-zA-Z]+)*(-[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?' + ANCHORED_VERSION_PATTERN = re.compile('^\s*({VERSION_PATTERN})?\s*$'.format(VERSION_PATTERN=VERSION_PATTERN)) + + def __init__(self, version): + # If version is an empty string convert it to 0 + version = 0 if re.compile('^\s*$').match(str(version)) else version + + self.__version = str(version).strip().replace('-', '.pre.') + self.__segments = None + self.__bump = None + self.__release = None + + def bump(self): + if not self.__bump: + segments = self.segments() + while any(map(lambda s: isinstance(s, str), segments)): + segments.pop() + if len(segments) > 1: + segments.pop() + segments[-1] = segments[-1] + 1 + segments = list(map(lambda r: str(r), segments)) + self.__bump = GemVersion('.'.join(segments)) + + return self.__bump + + def release(self): + if not self.__release: + segments = self.segments() + while any(map(lambda s: isinstance(s, str), segments)): + segments.pop() + segments = list(map(lambda r: str(r), segments)) + self.__release = GemVersion('.'.join(segments)) + + return self.__release + + def segments(self): + # type: () -> MutableSequence[int|str] + return list(self.__get_segments()) + + def __cmp__(self, other): + # type: (GemVersion) -> int + if self.__version == other.__version: + return 0 + lhsegments = self.__get_segments() + rhsegments = other.__get_segments() + + lhsize = len(lhsegments) + rhsize = len(rhsegments) + limit = (lhsize if lhsize > rhsize else rhsize) - 1 + + i = 0 + + while i <= limit: + lhs = default(lambda: lhsegments[i], IndexError, 0) + rhs = default(lambda: rhsegments[i], IndexError, 0) + i += 1 + + if lhs == rhs: + continue + if isinstance(lhs, str) and isinstance(rhs, int): + return -1 + if isinstance(lhs, int) and isinstance(rhs, str): + return 1 + + return lhs - rhs + return 0 + + def __lt__(self, other): + return self.__cmp__(other) < 0 + + def __le__(self, other): + return self.__cmp__(other) <= 0 + + def __eq__(self, other): + return self.__cmp__(other) == 0 + + def __repr__(self): + return 'GemVersion({segments})'.format(segments=self.segments()) + + def __get_segments(self): + # type: () -> Sequence[int|str] + if not self.__segments: + rex = re.compile('[0-9]+|[a-z]+', re.IGNORECASE) + d_rex = re.compile('^\d+$') + self.__segments = tuple(map(lambda s: int(s) if d_rex.match(s) else s, rex.findall(self.__version))) + return self.__segments + + +class GemRequirement: + OPS = { + '=': lambda v, r: v == r, + '!=': lambda v, r: v != r, + '>': lambda v, r: v > r, + '<': lambda v, r: v < r, + '>=': lambda v, r: v >= r, + '<=': lambda v, r: v <= r, + '~>': lambda v, r: v >= r and v.release() < r.bump() + } + + PATTERN_RAW = "\\s*({quoted})?\\s*({VERSION_PATTERN})\\s*".format( + quoted='|'.join(tuple(map(lambda k: re.escape(k), iterkeys(OPS)))), + VERSION_PATTERN=GemVersion.VERSION_PATTERN + ) + + # A regular expression that matches a requirement + PATTERN = re.compile('^{PATTERN_RAW}$'.format(PATTERN_RAW=PATTERN_RAW)) + + ## + # The default requirement matches any version + + DEFAULT_REQUIREMENT = tuple(['>=', GemVersion(0)]) + + class BadRequirementError(AttributeError): + pass + + def __init__(self, *requirements): + # type: (str) -> None + if len(requirements) == 0: + self.__requirements = tuple([GemRequirement.DEFAULT_REQUIREMENT]) + else: + self.__requirements = tuple(map(lambda req: GemRequirement.parse(req), requirements)) + + @classmethod + def parse(cls, requirement): + if isinstance(requirement, GemVersion): + return tuple(['=', requirement]) + + match = cls.PATTERN.match(str(requirement)) + if not match: + raise cls.BadRequirementError('Illformed requirement [{inspect}]'.format(inspect=repr(requirement))) + + if match.group(1) == '>=' and match.group(2) == '0': + return cls.DEFAULT_REQUIREMENT + else: + op = match.group(1) if match.group(1) else '=' + return tuple([op, GemVersion(match.group(2))]) + + def satified_by(self, version): + gemver = version if isinstance(version, GemVersion) else GemVersion(version) + operation = self.__test_rv(gemver) + return all(map(operation, self.__requirements)) + + @classmethod + def __test_rv(cls, version): + # type: (GemVersion) -> Callable[[str, GemVersion], bool] + def __testing(req): + op, rv = req + callable = cls.__get_operation(op) + return callable(version, rv) + return __testing + + @classmethod + def __get_operation(cls, op): + # type: (str) -> Callable[[GemVersion, GemVersion], bool] + try: + return cls.OPS[op] + except KeyError: + return cls.OPS['='] diff --git a/tests/domain/model/test_gemrequirement.py b/tests/domain/model/test_gemrequirement.py new file mode 100644 index 00000000..9d03a284 --- /dev/null +++ b/tests/domain/model/test_gemrequirement.py @@ -0,0 +1,50 @@ +import pytest +from puppeter.domain.model.gemrequirement import GemVersion, GemRequirement + + +def test_gem_version_release(): + # given + v = GemVersion('1.2.4.beta') + + # when + released = v.release() + + # then + assert GemVersion('1.2.4') == released + + +def test_gem_version_bump(): + # given + v = GemVersion('1.2.4') + + # when + bumped = v.bump() + + # then + assert GemVersion('1.3.0') == bumped + + +def test_gem_version_compare(): + assert GemVersion('1.3.0') == GemVersion('1.3') + assert GemVersion('1.3.0') <= GemVersion('1.3') + assert GemVersion('1.1.3') <= GemVersion('1.3') + assert GemVersion('1.4.pre') >= GemVersion('1.3') + assert GemVersion('1.4.pre') != GemVersion('1.4') + + +@pytest.mark.parametrize('requirement,version', [ + (['3.4'], '3.4.0'), + (['~> 3.4'], '3.4.8'), + (['>= 3.4'], '4.4.8'), + (['>= 3.4', '<4'], '3.45.8') +]) +def test_gem_requirement(requirement, version): + assert GemRequirement(*requirement).satified_by(version) + + +@pytest.mark.parametrize('requirement,version', [ + (['>= 3.4', '<4'], '4.1'), + (['~> 3'], '4.1.0.pre') +]) +def test_gem_requirement_fails(requirement, version): + assert GemRequirement(*requirement).satified_by(version) is False From 27aaeeb86f446a6db7dc12cbb36256d5ff735763 Mon Sep 17 00:00:00 2001 From: Samuel Giddins Date: Fri, 25 Aug 2017 10:39:50 -0400 Subject: [PATCH 393/707] Avoid 1.9.3 warnings --- test/rubygems/test_gem.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index cdd3fe3b..5ca145fc 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1110,7 +1110,8 @@ def test_self_use_paths_with_nils orig_path = ENV.delete 'GEM_PATH' Gem.use_paths nil, nil assert_equal Gem.default_dir, Gem.paths.home - assert_equal (Gem.default_path + [Gem.paths.home]).uniq, Gem.paths.path + path = (Gem.default_path + [Gem.paths.home]).uniq + assert_equal path, Gem.paths.path ensure ENV['GEM_HOME'] = orig_home ENV['GEM_PATH'] = orig_path From 161243ea6302b7fe35ea29eb91bc070f5f20dd17 Mon Sep 17 00:00:00 2001 From: Samuel Giddins Date: Tue, 29 Aug 2017 08:47:09 -0500 Subject: [PATCH 394/707] Temporarily disable Bundler integration --- test/rubygems/test_gem.rb | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 5ca145fc..38c99071 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -399,7 +399,7 @@ def test_self_detect_gemdeps begin Dir.chdir 'detect/a/b' - assert_equal [BUNDLER_FULL_NAME], Gem.detect_gemdeps.map(&:full_name) + assert_equal add_bundler_full_name([]), Gem.detect_gemdeps.map(&:full_name) ensure Dir.chdir @tempdir end @@ -1452,7 +1452,7 @@ def test_auto_activation_of_specific_gemdeps_file Gem.detect_gemdeps - assert_equal %W(a-1 b-1 #{BUNDLER_FULL_NAME} c-1), loaded_spec_names + assert_equal add_bundler_full_name(%W(a-1 b-1 c-1)), loaded_spec_names end def test_auto_activation_of_detected_gemdeps_file @@ -1475,13 +1475,21 @@ def test_auto_activation_of_detected_gemdeps_file ENV['RUBYGEMS_GEMDEPS'] = "-" - assert_equal [a, b, util_spec("bundler", Bundler::VERSION), c], Gem.detect_gemdeps.sort_by { |s| s.name } + expected_specs = [a, b, (Gem::USE_BUNDLER_FOR_GEMDEPS || nil) && util_spec("bundler", Bundler::VERSION), c].compact + assert_equal expected_specs, Gem.detect_gemdeps.sort_by { |s| s.name } end LIB_PATH = File.expand_path "../../../lib".dup.untaint, __FILE__.dup.untaint BUNDLER_LIB_PATH = File.expand_path $LOAD_PATH.find {|lp| File.file?(File.join(lp, "bundler.rb")) }.dup.untaint BUNDLER_FULL_NAME = "bundler-#{Bundler::VERSION}" + def add_bundler_full_name(names) + return names unless Gem::USE_BUNDLER_FOR_GEMDEPS + names << BUNDLER_FULL_NAME + names.sort! + names + end + def test_looks_for_gemdeps_files_automatically_on_start util_clear_gems @@ -1639,7 +1647,7 @@ def test_use_gemdeps Gem.use_gemdeps gem_deps_file - assert_equal %W(a-1 #{BUNDLER_FULL_NAME}), loaded_spec_names + assert_equal add_bundler_full_name(%W(a-1)), loaded_spec_names refute_nil Gem.gemdeps end @@ -1700,7 +1708,7 @@ def test_use_gemdeps_automatic Gem.use_gemdeps - assert_equal %W(a-1 #{BUNDLER_FULL_NAME}), loaded_spec_names + assert_equal add_bundler_full_name(%W(a-1)), loaded_spec_names ensure ENV['RUBYGEMS_GEMDEPS'] = rubygems_gemdeps end @@ -1748,11 +1756,19 @@ def test_use_gemdeps_missing_gem else platform = " #{platform}" end - expected = <<-EXPECTED + expected = if Gem::USE_BUNDLER_FOR_GEMDEPS + <<-EXPECTED Could not find gem 'a#{platform}' in any of the gem sources listed in your Gemfile. You may need to `gem install -g` to install missing gems - EXPECTED + EXPECTED + else + <<-EXPECTED +Unable to resolve dependency: user requested 'a (>= 0)' +You may need to `gem install -g` to install missing gems + + EXPECTED + end assert_output nil, expected do Gem.use_gemdeps @@ -1777,7 +1793,7 @@ def test_use_gemdeps_specific Gem.use_gemdeps - assert_equal %W(a-1 #{BUNDLER_FULL_NAME}), loaded_spec_names + assert_equal add_bundler_full_name(%W(a-1)), loaded_spec_names ensure ENV['RUBYGEMS_GEMDEPS'] = rubygems_gemdeps end From ff74d1b2a920f9d66ff6f0203d8a81b68614f460 Mon Sep 17 00:00:00 2001 From: Jordan Danford Date: Fri, 22 Sep 2017 14:33:32 -0700 Subject: [PATCH 395/707] Fix formatting of installation instructions in README --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 79e60429..c4038a35 100644 --- a/README.md +++ b/README.md @@ -19,9 +19,9 @@ See [UPGRADING](UPGRADING.rdoc) for more details and alternative instructions. If you don't have RubyGems installed, you can still do it manually: -* Download from: https://rubygems.org/pages/download, unpack, and cd there -* OR clone this repository and cd there (make sure to run `git submodule update -\-init`) -* Install with: ruby setup.rb # you may need admin/root privilege +* Download from https://rubygems.org/pages/download, unpack, and `cd` there +* OR clone this repository and `cd` there (make sure to run `git submodule update --init`) +* Install with `ruby setup.rb` (you may need admin/root privilege) For more details and other options, see: From 6afd420ab4a2a1785e4d43bb90e4040096762370 Mon Sep 17 00:00:00 2001 From: SHIBATA Hiroshi Date: Sat, 7 Oct 2017 14:18:58 +0900 Subject: [PATCH 396/707] ubygems.rb is unavailable on Ruby 2.5 --- test/rubygems/test_gem.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 38c99071..ccb4929a 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1509,7 +1509,7 @@ def test_looks_for_gemdeps_files_automatically_on_start path = File.join @tempdir, "gem.deps.rb" cmd = [Gem.ruby.dup.untaint, "-I#{LIB_PATH.untaint}", - "-I#{BUNDLER_LIB_PATH.untaint}", "-rubygems"] + "-I#{BUNDLER_LIB_PATH.untaint}", "-rrubygems"] if RUBY_VERSION < '1.9' cmd << "-e 'puts Gem.loaded_specs.values.map(&:full_name).sort'" cmd = cmd.join(' ') From cec412f75f7aa32371ef555120f3c0c77ca12d10 Mon Sep 17 00:00:00 2001 From: SHIBATA Hiroshi Date: Sat, 7 Oct 2017 18:50:22 +0900 Subject: [PATCH 397/707] More rename ubygems.rb. Follow up d6e654f24894bfce872d0ec7a81d72aaa083da50 --- test/rubygems/test_gem.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index ccb4929a..2ec7044d 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1552,7 +1552,7 @@ def test_looks_for_gemdeps_files_automatically_on_start_in_parent_dir path = File.join @tempdir, "gem.deps.rb" cmd = [Gem.ruby.dup.untaint, "-Csub1", "-I#{LIB_PATH.untaint}", - "-I#{BUNDLER_LIB_PATH.untaint}", "-rubygems"] + "-I#{BUNDLER_LIB_PATH.untaint}", "-rrubygems"] if RUBY_VERSION < '1.9' cmd << "-e 'puts Gem.loaded_specs.values.map(&:full_name).sort'" cmd = cmd.join(' ') From 62597e8c8ed0c7783363757173602b00e908c798 Mon Sep 17 00:00:00 2001 From: SHIBATA Hiroshi Date: Tue, 10 Oct 2017 09:41:21 +0900 Subject: [PATCH 398/707] Remove trailing-whitespaces and append newline at EOF. --- test/rubygems/test_gem.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 2ec7044d..3225a05c 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1756,7 +1756,7 @@ def test_use_gemdeps_missing_gem else platform = " #{platform}" end - expected = if Gem::USE_BUNDLER_FOR_GEMDEPS + expected = if Gem::USE_BUNDLER_FOR_GEMDEPS <<-EXPECTED Could not find gem 'a#{platform}' in any of the gem sources listed in your Gemfile. You may need to `gem install -g` to install missing gems From b3d86aa65b1ce30a9388a9a21cdda88d30f008c2 Mon Sep 17 00:00:00 2001 From: SHIBATA Hiroshi Date: Wed, 6 Dec 2017 12:02:41 +0900 Subject: [PATCH 399/707] Added amatsuda to maintainers list. --- MAINTAINERS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS.txt b/MAINTAINERS.txt index dbba1a07..d7ae6bdb 100644 --- a/MAINTAINERS.txt +++ b/MAINTAINERS.txt @@ -10,3 +10,4 @@ Luis Lavena (@luislavena) Samuel Giddins (@segiddins) Aaron Patterson (@tenderlove) Zachary Scott (@zzak) +Akira Matsuda (@amatsuda) From f22004a1b3efa16ef321f908e09b1c076fe3121e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20Ondruch?= Date: Tue, 19 Dec 2017 14:00:20 +0100 Subject: [PATCH 400/707] Add Gem.operating_system_defaults to allow packagers to override defaults. This change allows Ruby packagers to override defaults and lazily query them. This is very much the same change as #1644 to treat the operating_system defaults the same way as platform defaults. --- test/rubygems/test_gem.rb | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 3225a05c..62b80c49 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1798,6 +1798,13 @@ def test_use_gemdeps_specific ENV['RUBYGEMS_GEMDEPS'] = rubygems_gemdeps end + def test_operating_system_defaults + operating_system_defaults = Gem.operating_system_defaults + + assert operating_system_defaults != nil + assert operating_system_defaults.is_a? Hash + end + def test_platform_defaults platform_defaults = Gem.platform_defaults From b88edfdf169484bee0d5b4ec5b9212a1c826d514 Mon Sep 17 00:00:00 2001 From: MSP-Greg Date: Tue, 19 Dec 2017 18:13:28 -0600 Subject: [PATCH 401/707] Update for compatibilty with new minitest --- test/rubygems/test_gem.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 62b80c49..d23c6b8f 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1587,7 +1587,7 @@ def test_register_default_spec assert_equal old_style, Gem.find_unresolved_default_spec("foo.rb") assert_equal old_style, Gem.find_unresolved_default_spec("bar.rb") - assert_equal nil, Gem.find_unresolved_default_spec("baz.rb") + assert_nil Gem.find_unresolved_default_spec("baz.rb") Gem.clear_default_specs @@ -1600,8 +1600,8 @@ def test_register_default_spec assert_equal new_style, Gem.find_unresolved_default_spec("foo.rb") assert_equal new_style, Gem.find_unresolved_default_spec("bar.rb") - assert_equal nil, Gem.find_unresolved_default_spec("exec") - assert_equal nil, Gem.find_unresolved_default_spec("README") + assert_nil Gem.find_unresolved_default_spec("exec") + assert_nil Gem.find_unresolved_default_spec("README") end def test_default_gems_use_full_paths From 63a09c522c0b6aab0c52f77b63465ab82f8eb460 Mon Sep 17 00:00:00 2001 From: SHIBATA Hiroshi Date: Sat, 23 Dec 2017 18:51:42 +0900 Subject: [PATCH 402/707] Make to use bundler gemdeps with environmental variables. --- test/rubygems/test_gem.rb | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index d23c6b8f..0d71db9d 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1480,8 +1480,11 @@ def test_auto_activation_of_detected_gemdeps_file end LIB_PATH = File.expand_path "../../../lib".dup.untaint, __FILE__.dup.untaint - BUNDLER_LIB_PATH = File.expand_path $LOAD_PATH.find {|lp| File.file?(File.join(lp, "bundler.rb")) }.dup.untaint - BUNDLER_FULL_NAME = "bundler-#{Bundler::VERSION}" + + if Gem::USE_BUNDLER_FOR_GEMDEPS + BUNDLER_LIB_PATH = File.expand_path $LOAD_PATH.find {|lp| File.file?(File.join(lp, "bundler.rb")) }.dup.untaint + BUNDLER_FULL_NAME = "bundler-#{Bundler::VERSION}" + end def add_bundler_full_name(names) return names unless Gem::USE_BUNDLER_FOR_GEMDEPS @@ -1529,7 +1532,7 @@ def test_looks_for_gemdeps_files_automatically_on_start out = IO.popen(cmd, &:read).split(/\n/) assert_equal ["b-1", "c-1"], out - out0 - end + end if Gem::USE_BUNDLER_FOR_GEMDEPS def test_looks_for_gemdeps_files_automatically_on_start_in_parent_dir util_clear_gems @@ -1574,7 +1577,7 @@ def test_looks_for_gemdeps_files_automatically_on_start_in_parent_dir Dir.rmdir "sub1" assert_equal ["b-1", "c-1"], out - out0 - end + end if Gem::USE_BUNDLER_FOR_GEMDEPS def test_register_default_spec Gem.clear_default_specs @@ -1775,7 +1778,7 @@ def test_use_gemdeps_missing_gem end ensure ENV['RUBYGEMS_GEMDEPS'] = rubygems_gemdeps - end + end if Gem::USE_BUNDLER_FOR_GEMDEPS def test_use_gemdeps_specific skip 'Insecure operation - read' if RUBY_VERSION <= "1.8.7" From d6b233fa77bafcb7495774ab60888328b7ffc8c8 Mon Sep 17 00:00:00 2001 From: Ivan Kuchin Date: Sat, 23 Dec 2017 12:16:15 +0100 Subject: [PATCH 403/707] Fix codeclimate badge Old badge shows status unknown, so replace it with new maintainability badge --- bundler/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundler/README.md b/bundler/README.md index 649b7771..4e438ed0 100644 --- a/bundler/README.md +++ b/bundler/README.md @@ -1,6 +1,6 @@ [![Version ](https://img.shields.io/gem/v/bundler.svg?style=flat)](https://rubygems.org/gems/bundler) [![Build Status](https://img.shields.io/travis/bundler/bundler/master.svg?style=flat)](https://travis-ci.org/bundler/bundler) -[![Code Climate](https://img.shields.io/codeclimate/github/bundler/bundler.svg?style=flat)](https://codeclimate.com/github/bundler/bundler) +[![Code Climate](https://img.shields.io/codeclimate/maintainability/bundler/bundler.svg?style=flat)](https://codeclimate.com/github/bundler/bundler) [![Inline docs ](http://inch-ci.org/github/bundler/bundler.svg?style=flat)](http://inch-ci.org/github/bundler/bundler) [![Slack ](http://bundler-slackin.herokuapp.com/badge.svg)](http://bundler-slackin.herokuapp.com) From 7c74913fc5f162550c037b68405720ca9972a4dc Mon Sep 17 00:00:00 2001 From: Colby Swandale Date: Sat, 30 Dec 2017 22:07:45 +1100 Subject: [PATCH 404/707] titleize "GETTING HELP" in readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c4038a35..cd9130be 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ can be viewed online at http://www.rubydoc.info/github/rubygems/rubygems RubyGems also provides a comprehensive set of guides which covers numerous topics such as creating a new gem, security practices and other resources at http://guides.rubygems.org -## GETTING HELP +## Getting Help ### Support Requests From 2f6f36855e1c49ea39f0c36886f226b9cbd23c95 Mon Sep 17 00:00:00 2001 From: ko1 Date: Thu, 28 Dec 2017 20:09:24 +0000 Subject: [PATCH 405/707] `$SAFE` as a process global state. [Feature #14250] * test/rubygems/test_gem.rb: do not set `$SAFE = 1`. * test/rubygems/test_gem_specification.rb: ditto. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@61510 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- test/rubygems/test_gem.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 0d71db9d..80ae8e90 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -7,7 +7,7 @@ require 'tmpdir' # TODO: push this up to test_case.rb once battle tested -$SAFE=1 + $LOAD_PATH.map! do |path| path.dup.untaint end From edb6d8a8519f40ea1b1a6ac5356ab29f88e1fe0f Mon Sep 17 00:00:00 2001 From: SHIBATA Hiroshi Date: Fri, 5 Jan 2018 12:09:06 +0900 Subject: [PATCH 406/707] Use `File.open` instead of `open`. This change is not vulnerability fix. @hsbt and @shugo did audit these usage when CVE-2017-17405 was disclosed. --- test/rubygems/test_gem.rb | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 0d71db9d..20630f31 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -775,7 +775,7 @@ def test_self_prefix_sitelibdir end def test_self_read_binary - open 'test', 'w' do |io| + File.open 'test', 'w' do |io| io.write "\xCF\x80" end @@ -1642,7 +1642,7 @@ def test_use_gemdeps spec = Gem::Specification.find { |s| s == spec } refute spec.activated? - open gem_deps_file, 'w' do |io| + File.open gem_deps_file, 'w' do |io| io.write 'gem "a"' end @@ -1661,7 +1661,7 @@ def test_use_gemdeps_ENV refute spec.activated? - open 'gem.deps.rb', 'w' do |io| + File.open 'gem.deps.rb', 'w' do |io| io.write 'gem "a"' end @@ -1705,7 +1705,7 @@ def test_use_gemdeps_automatic refute spec.activated? - open 'Gemfile', 'w' do |io| + File.open 'Gemfile', 'w' do |io| io.write 'gem "a"' end @@ -1734,7 +1734,7 @@ def test_use_gemdeps_disabled refute spec.activated? - open 'gem.deps.rb', 'w' do |io| + File.open 'gem.deps.rb', 'w' do |io| io.write 'gem "a"' end @@ -1749,7 +1749,7 @@ def test_use_gemdeps_missing_gem skip 'Insecure operation - read' if RUBY_VERSION <= "1.8.7" rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], 'x' - open 'x', 'w' do |io| + File.open 'x', 'w' do |io| io.write 'gem "a"' end @@ -1790,7 +1790,7 @@ def test_use_gemdeps_specific spec = Gem::Specification.find { |s| s == spec } refute spec.activated? - open 'x', 'w' do |io| + File.open 'x', 'w' do |io| io.write 'gem "a"' end From 53554e24543a855618e74dd2fa6c000815369c41 Mon Sep 17 00:00:00 2001 From: SHIBATA Hiroshi Date: Fri, 12 Jan 2018 12:40:36 +0900 Subject: [PATCH 407/707] Added badge of codeclimate --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index cd9130be..e3d9d7a7 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# RubyGems [![Travis Build Status](https://secure.travis-ci.org/rubygems/rubygems.svg?branch=master)](http://travis-ci.org/rubygems/rubygems) [![Appveyor Build Status](https://ci.appveyor.com/api/projects/status/github/rubygems/rubygems?branch=master&svg=true)](https://ci.appveyor.com/project/rubygems/rubygems?branch=master) +# RubyGems [![Travis Build Status](https://secure.travis-ci.org/rubygems/rubygems.svg?branch=master)](http://travis-ci.org/rubygems/rubygems) [![Appveyor Build Status](https://ci.appveyor.com/api/projects/status/github/rubygems/rubygems?branch=master&svg=true)](https://ci.appveyor.com/project/rubygems/rubygems?branch=master) [![Maintainability](https://api.codeclimate.com/v1/badges/30f913e9c2dd932132c1/maintainability)](https://codeclimate.com/github/rubygems/rubygems/maintainability) RubyGems is a package management framework for Ruby. From bb156a5c6ad559f0d019b9a14f119d102891d9c7 Mon Sep 17 00:00:00 2001 From: mame Date: Wed, 10 Jan 2018 10:39:09 +0000 Subject: [PATCH 408/707] skip some tests so that no failure occurs in root privilege Some tests had failed on `sudo make test-all`, mainly because root can access any files regardless of permission. This change adds `skip` guards into such tests. Note that almost all tests in which `skip` guards is added, already have "windows" guard. This is because there is no support to avoid read access by owner on Windows. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@61758 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- test/rubygems/test_gem.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index f276014f..3559b038 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -463,7 +463,7 @@ def test_self_ensure_gem_directories_missing_parents assert File.directory?(util_cache_dir) end - unless win_platform? then # only for FS that support write protection + unless win_platform? || Process.uid == 0 then # only for FS that support write protection def test_self_ensure_gem_directories_write_protected gemdir = File.join @tempdir, "egd" FileUtils.rm_r gemdir rescue nil From 4e222002ff04f6bf7dcb88d879b75f89dca259ed Mon Sep 17 00:00:00 2001 From: The Bundler Bot Date: Tue, 26 Dec 2017 01:17:54 +0000 Subject: [PATCH 409/707] Auto merge of #2126 - rubygems:fix-broken-tests-with-bundler-gemdeps, r=hsbt Set whether bundler is used for gemdeps with an environmental variable If we confirm to work test suite without vendored bundler and `Gem::USE_BUNDLER_FOR_GEMDEPS = false`, We got a `LoadError` of bundler files and `uninitialized constant Bundler` error. It's better to separate test environment until completely merging bundler. --- test/rubygems/test_gem.rb | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 3225a05c..8a11cc2e 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1480,8 +1480,11 @@ def test_auto_activation_of_detected_gemdeps_file end LIB_PATH = File.expand_path "../../../lib".dup.untaint, __FILE__.dup.untaint - BUNDLER_LIB_PATH = File.expand_path $LOAD_PATH.find {|lp| File.file?(File.join(lp, "bundler.rb")) }.dup.untaint - BUNDLER_FULL_NAME = "bundler-#{Bundler::VERSION}" + + if Gem::USE_BUNDLER_FOR_GEMDEPS + BUNDLER_LIB_PATH = File.expand_path $LOAD_PATH.find {|lp| File.file?(File.join(lp, "bundler.rb")) }.dup.untaint + BUNDLER_FULL_NAME = "bundler-#{Bundler::VERSION}" + end def add_bundler_full_name(names) return names unless Gem::USE_BUNDLER_FOR_GEMDEPS @@ -1529,7 +1532,7 @@ def test_looks_for_gemdeps_files_automatically_on_start out = IO.popen(cmd, &:read).split(/\n/) assert_equal ["b-1", "c-1"], out - out0 - end + end if Gem::USE_BUNDLER_FOR_GEMDEPS def test_looks_for_gemdeps_files_automatically_on_start_in_parent_dir util_clear_gems @@ -1574,7 +1577,7 @@ def test_looks_for_gemdeps_files_automatically_on_start_in_parent_dir Dir.rmdir "sub1" assert_equal ["b-1", "c-1"], out - out0 - end + end if Gem::USE_BUNDLER_FOR_GEMDEPS def test_register_default_spec Gem.clear_default_specs @@ -1775,7 +1778,7 @@ def test_use_gemdeps_missing_gem end ensure ENV['RUBYGEMS_GEMDEPS'] = rubygems_gemdeps - end + end if Gem::USE_BUNDLER_FOR_GEMDEPS def test_use_gemdeps_specific skip 'Insecure operation - read' if RUBY_VERSION <= "1.8.7" From 3af7c55b6e28e78cb815a170afc86611ba4ae62f Mon Sep 17 00:00:00 2001 From: The Bundler Bot Date: Fri, 5 Jan 2018 06:28:08 +0000 Subject: [PATCH 410/707] Auto merge of #2141 - rubygems:backport-ruby-core, r=hsbt Backport ruby core changes for test fixes. Ruby 2.6 will change the behavior of `$SAFE` variable. It's part of test fixes by @MSP-Greg like https://github.com/rubygems/rubygems/pull/2139 --- test/rubygems/test_gem.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 8a11cc2e..315aea02 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -7,7 +7,7 @@ require 'tmpdir' # TODO: push this up to test_case.rb once battle tested -$SAFE=1 + $LOAD_PATH.map! do |path| path.dup.untaint end From 5efd4ac3e43cd4041917711c36b7c1ac952e81d8 Mon Sep 17 00:00:00 2001 From: The Bundler Bot Date: Fri, 5 Jan 2018 06:59:04 +0000 Subject: [PATCH 411/707] Auto merge of #2142 - rubygems:use-file-open, r=hsbt Use `File.open` instead of `open`. This change is not vulnerability fix. @hsbt and @shugo did audit this usage when CVE-2017-17405 was disclosed. Because ruby core team will warn to use `Kernel#open` in standard libraries. I will abide by the [code of conduct](https://github.com/rubygems/rubygems/blob/master/CODE_OF_CONDUCT.md). --- test/rubygems/test_gem.rb | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 315aea02..c47e340c 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -775,7 +775,7 @@ def test_self_prefix_sitelibdir end def test_self_read_binary - open 'test', 'w' do |io| + File.open 'test', 'w' do |io| io.write "\xCF\x80" end @@ -1642,7 +1642,7 @@ def test_use_gemdeps spec = Gem::Specification.find { |s| s == spec } refute spec.activated? - open gem_deps_file, 'w' do |io| + File.open gem_deps_file, 'w' do |io| io.write 'gem "a"' end @@ -1661,7 +1661,7 @@ def test_use_gemdeps_ENV refute spec.activated? - open 'gem.deps.rb', 'w' do |io| + File.open 'gem.deps.rb', 'w' do |io| io.write 'gem "a"' end @@ -1705,7 +1705,7 @@ def test_use_gemdeps_automatic refute spec.activated? - open 'Gemfile', 'w' do |io| + File.open 'Gemfile', 'w' do |io| io.write 'gem "a"' end @@ -1734,7 +1734,7 @@ def test_use_gemdeps_disabled refute spec.activated? - open 'gem.deps.rb', 'w' do |io| + File.open 'gem.deps.rb', 'w' do |io| io.write 'gem "a"' end @@ -1749,7 +1749,7 @@ def test_use_gemdeps_missing_gem skip 'Insecure operation - read' if RUBY_VERSION <= "1.8.7" rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], 'x' - open 'x', 'w' do |io| + File.open 'x', 'w' do |io| io.write 'gem "a"' end @@ -1790,7 +1790,7 @@ def test_use_gemdeps_specific spec = Gem::Specification.find { |s| s == spec } refute spec.activated? - open 'x', 'w' do |io| + File.open 'x', 'w' do |io| io.write 'gem "a"' end From 30be4ad94f01a6752a124fb68d6fec6728b4aa2f Mon Sep 17 00:00:00 2001 From: The Bundler Bot Date: Thu, 1 Feb 2018 02:16:06 +0000 Subject: [PATCH 412/707] Auto merge of #2165 - rubygems:backport-ruby-core, r=hsbt Backport ruby core commits for testcase # Description: I backport https://github.com/ruby/ruby/commit/b496220a1f70f8393070ffebcb883c7c5fc036d7 and https://github.com/ruby/ruby/commit/15689ed7780b06ddc14cde4f427de834177283a5 from ruby/ruby. ______________ # Tasks: - [ ] Describe the problem / feature - [ ] Write tests - [ ] Write code to solve the problem - [ ] Get code review from coworkers / friends I will abide by the [code of conduct](https://github.com/rubygems/rubygems/blob/master/CODE_OF_CONDUCT.md). --- test/rubygems/test_gem.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index c47e340c..3edaa6c0 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -463,7 +463,7 @@ def test_self_ensure_gem_directories_missing_parents assert File.directory?(util_cache_dir) end - unless win_platform? then # only for FS that support write protection + unless win_platform? || Process.uid == 0 then # only for FS that support write protection def test_self_ensure_gem_directories_write_protected gemdir = File.join @tempdir, "egd" FileUtils.rm_r gemdir rescue nil From 294f5d2599f4254bd144282d065c08f5e1f094ef Mon Sep 17 00:00:00 2001 From: SHIBATA Hiroshi Date: Fri, 2 Feb 2018 18:39:14 +0900 Subject: [PATCH 413/707] Picked benchmark test from https://github.com/rubygems/rubygems/issues/1940 Fixes #1940 --- test/rubygems/test_gem_version.rb | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/test/rubygems/test_gem_version.rb b/test/rubygems/test_gem_version.rb index 56c81866..653199f8 100644 --- a/test/rubygems/test_gem_version.rb +++ b/test/rubygems/test_gem_version.rb @@ -2,6 +2,8 @@ require 'rubygems/test_case' require "rubygems/version" +require "minitest/benchmark" + class TestGemVersion < Gem::TestCase class V < ::Gem::Version @@ -102,6 +104,13 @@ def test_initialize_invalid end end + def bench_anchored_version_pattern + assert_performance_linear 0.5 do |count| + version_string = count.times.map {|i| "0" * i.succ }.join(".") << "." + version_string =~ Gem::Version::ANCHORED_VERSION_PATTERN + end + end + def test_empty_version ["", " ", " "].each do |empty| assert_equal "0", Gem::Version.new(empty).version From d643847e89d807da00bd7d15d04945293d9acc29 Mon Sep 17 00:00:00 2001 From: Colby Swandale Date: Sat, 3 Feb 2018 18:09:31 +1100 Subject: [PATCH 414/707] Add new sections to the README and explaination of what RubyGems is This commit adds/removes and updates a number of sections in the README to help answer most questions a new person looking at the README needs and also remove sections that are not really relevent anymore. --- README.md | 67 ++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 44 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index e3d9d7a7..90b9207e 100644 --- a/README.md +++ b/README.md @@ -2,49 +2,70 @@ RubyGems is a package management framework for Ruby. -This gem is an update for the RubyGems software. You must have an -installation of RubyGems before this update can be applied. +A package (also known as a library) contains a set of functionality that can be invoked by a Ruby program such as reading and parsing an XML file. +We call these packages "gems" and RubyGems is a tool to install, create, manage and load these packages in your Ruby environment. -See Gem for information on RubyGems (or `ri Gem`) +RubyGems is also a client for [RubyGems.org](https://rubygems.org), a public repository of Gems that allows you to publish a Gem +that can be shared and used by other developers. See our guide on publishing a Gem at [guides.rubygems.org](http://guides.rubygems.org/publishing/) -To upgrade to the latest RubyGems, run: +## Getting Started -``` - $ gem update --system # you might need to be an administrator or root -``` +Installing and managing a Gem is done through the `gem` command. To install a Gem such as [Nokigiri](https://github.com/sparklemotion/nokogiri) which lets +you read and parse XML in Ruby: -See [UPGRADING](UPGRADING.rdoc) for more details and alternative instructions. + $ gem install nokogiri + +RubyGems will download the Nokogiri Gem from RubyGems.org and install it into your Ruby environment. + +Finally, inside your Ruby program, load the Nokogiri gem and start parsing your XML: + + require 'nokogiri' + + Nokogiri.XML('

Hello World

') + +For more information about how to use RubyGems, see our RubyGems basics guide at [guides.rubygems.org](http://guides.rubygems.org/rubygems-basics/) + +## Installation + +RubyGems is likely already installed in your Ruby environment, you can check by running `gem --version` in your terminal emulator. +In some cases your OS's pacakge manager may install RubyGems as a separte packege from Ruby. It's recommended to check +with your OS's package manager before installing RubyGems manually. + +If you would like to manually install RubyGems: ------ +* Download from https://rubygems.org/pages/download, unpack, and `cd` into RubyGems' src +* OR clone this repository and `cd` into the repository (make sure to run `git submodule update --init`) -If you don't have RubyGems installed, you can still do it manually: +Install RubyGems by running: -* Download from https://rubygems.org/pages/download, unpack, and `cd` there -* OR clone this repository and `cd` there (make sure to run `git submodule update --init`) -* Install with `ruby setup.rb` (you may need admin/root privilege) + $ ruby setup.rb + +Note: You may need to run the install script with admin/root privileges. For more details and other options, see: -``` - ruby setup.rb --help -``` + $ ruby setup.rb --help + +## Upgrading RubyGems + +To upgrade to the latest RubyGems, run: + + $ gem update --system + +Note: You might need to run the command as an administrator or root user. + +See [UPGRADING](UPGRADING.rdoc) for more details and alternative instructions. ## Documentation RubyGems uses [rdoc](https://github.com/rdoc/rdoc) for documentation. A compiled set of the docs -can be viewed online at http://www.rubydoc.info/github/rubygems/rubygems +can be viewed online at [rubydoc](http://www.rubydoc.info/github/rubygems/rubygems). RubyGems also provides a comprehensive set of guides which covers numerous topics such as creating a new gem, security practices and other resources at http://guides.rubygems.org ## Getting Help -### Support Requests - -Are you unsure of how to use RubyGems? Do you think you've found a bug and -you're not sure? If that is the case, the best place for you is to file a -support request at [help.rubygems.org](http://help.rubygems.org). - ### Filing Tickets Got a bug and you're not sure? You're sure you have a bug, but don't know From c3084c32a2e46157fece8e53587b0847357dda6c Mon Sep 17 00:00:00 2001 From: SHIBATA Hiroshi Date: Mon, 5 Feb 2018 09:43:35 +0900 Subject: [PATCH 415/707] Prefer to use `Numeric#zero?` instead of `== 0` --- test/rubygems/test_gem.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 3559b038..0910e1d8 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -463,7 +463,7 @@ def test_self_ensure_gem_directories_missing_parents assert File.directory?(util_cache_dir) end - unless win_platform? || Process.uid == 0 then # only for FS that support write protection + unless win_platform? || Process.uid.zero? then # only for FS that support write protection def test_self_ensure_gem_directories_write_protected gemdir = File.join @tempdir, "egd" FileUtils.rm_r gemdir rescue nil From 2057f06f102808b5b7a08ae8b0633839a0acd579 Mon Sep 17 00:00:00 2001 From: The Bundler Bot Date: Fri, 2 Feb 2018 10:14:35 +0000 Subject: [PATCH 416/707] Auto merge of #2172 - rubygems:fix-1940, r=hsbt Picked benchmark test from #1940 # Description: Fixes #1940 ______________ I will abide by the [code of conduct](https://github.com/rubygems/rubygems/blob/master/CODE_OF_CONDUCT.md). --- test/rubygems/test_gem_version.rb | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/test/rubygems/test_gem_version.rb b/test/rubygems/test_gem_version.rb index 56c81866..653199f8 100644 --- a/test/rubygems/test_gem_version.rb +++ b/test/rubygems/test_gem_version.rb @@ -2,6 +2,8 @@ require 'rubygems/test_case' require "rubygems/version" +require "minitest/benchmark" + class TestGemVersion < Gem::TestCase class V < ::Gem::Version @@ -102,6 +104,13 @@ def test_initialize_invalid end end + def bench_anchored_version_pattern + assert_performance_linear 0.5 do |count| + version_string = count.times.map {|i| "0" * i.succ }.join(".") << "." + version_string =~ Gem::Version::ANCHORED_VERSION_PATTERN + end + end + def test_empty_version ["", " ", " "].each do |empty| assert_equal "0", Gem::Version.new(empty).version From 07e9e3536e9ad9a35ad7d1ff4d7bc001da9e1bdf Mon Sep 17 00:00:00 2001 From: The Bundler Bot Date: Mon, 5 Feb 2018 03:08:14 +0000 Subject: [PATCH 417/707] Auto merge of #2176 - rubygems:use-zero-on-testcase, r=hsbt Prefer to use `Numeric#zero?` instead of `== 0` Follow up with https://github.com/rubygems/rubygems/pull/2165#issuecomment-362861991 --- test/rubygems/test_gem.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 3edaa6c0..183771f0 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -463,7 +463,7 @@ def test_self_ensure_gem_directories_missing_parents assert File.directory?(util_cache_dir) end - unless win_platform? || Process.uid == 0 then # only for FS that support write protection + unless win_platform? || Process.uid.zero? then # only for FS that support write protection def test_self_ensure_gem_directories_write_protected gemdir = File.join @tempdir, "egd" FileUtils.rm_r gemdir rescue nil From 5c43c42ebc4df6cab02397cfda0606823f2ba7f0 Mon Sep 17 00:00:00 2001 From: SHIBATA Hiroshi Date: Mon, 5 Feb 2018 19:07:06 +0900 Subject: [PATCH 418/707] Ignore perfomance test of version regexp pattern. Sometimes its test fail with old ruby versions like Ruby 1.9 and 1.8 --- test/rubygems/test_gem_version.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/rubygems/test_gem_version.rb b/test/rubygems/test_gem_version.rb index 653199f8..792ad5f0 100644 --- a/test/rubygems/test_gem_version.rb +++ b/test/rubygems/test_gem_version.rb @@ -109,6 +109,8 @@ def bench_anchored_version_pattern version_string = count.times.map {|i| "0" * i.succ }.join(".") << "." version_string =~ Gem::Version::ANCHORED_VERSION_PATTERN end + rescue RegexpError + skip "It fails to allocate the memory for regex pattern of Gem::Version::ANCHORED_VERSION_PATTERN" end def test_empty_version From 5d889557f4cd179678df977f02d3426278f19a38 Mon Sep 17 00:00:00 2001 From: The Bundler Bot Date: Mon, 5 Feb 2018 11:24:19 +0000 Subject: [PATCH 419/707] Auto merge of #2179 - rubygems:aim-to-test-fail-for-performance-test, r=hsbt Ignore perfomance test of version regexp pattern. # Description: Sometimes its test fail with old ruby versions like Ruby 1.8 * https://ci.appveyor.com/project/segiddins/rubygems/build/1094/job/knb2oiu7jwb4fjp5 * https://travis-ci.org/rubygems/rubygems/jobs/337402882 ______________ # Tasks: - [ ] Describe the problem / feature - [ ] Write tests - [ ] Write code to solve the problem - [ ] Get code review from coworkers / friends I will abide by the [code of conduct](https://github.com/rubygems/rubygems/blob/master/CODE_OF_CONDUCT.md). --- test/rubygems/test_gem_version.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/rubygems/test_gem_version.rb b/test/rubygems/test_gem_version.rb index 653199f8..792ad5f0 100644 --- a/test/rubygems/test_gem_version.rb +++ b/test/rubygems/test_gem_version.rb @@ -109,6 +109,8 @@ def bench_anchored_version_pattern version_string = count.times.map {|i| "0" * i.succ }.join(".") << "." version_string =~ Gem::Version::ANCHORED_VERSION_PATTERN end + rescue RegexpError + skip "It fails to allocate the memory for regex pattern of Gem::Version::ANCHORED_VERSION_PATTERN" end def test_empty_version From 97f541e4c7746d66e3e0805c05273ee4f90a8deb Mon Sep 17 00:00:00 2001 From: Colby Swandale Date: Wed, 14 Feb 2018 07:41:01 +1100 Subject: [PATCH 420/707] fix spelling errors in the README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 90b9207e..ac5c7c66 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ For more information about how to use RubyGems, see our RubyGems basics guide at ## Installation RubyGems is likely already installed in your Ruby environment, you can check by running `gem --version` in your terminal emulator. -In some cases your OS's pacakge manager may install RubyGems as a separte packege from Ruby. It's recommended to check +In some cases your OS's package manager may install RubyGems as a separate package from Ruby. It's recommended to check with your OS's package manager before installing RubyGems manually. If you would like to manually install RubyGems: From d037b8a84b95474bb7fb512fa730180297e43cb4 Mon Sep 17 00:00:00 2001 From: Clifford Heath Date: Thu, 15 Feb 2018 08:33:31 +1100 Subject: [PATCH 421/707] Missing comma creates ambiguous meaning "a Ruby program such as reading and parsing an XML file" needs a comma. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ac5c7c66..d00b5de8 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ RubyGems is a package management framework for Ruby. -A package (also known as a library) contains a set of functionality that can be invoked by a Ruby program such as reading and parsing an XML file. +A package (also known as a library) contains a set of functionality that can be invoked by a Ruby program, such as reading and parsing an XML file. We call these packages "gems" and RubyGems is a tool to install, create, manage and load these packages in your Ruby environment. RubyGems is also a client for [RubyGems.org](https://rubygems.org), a public repository of Gems that allows you to publish a Gem From 819d066877283a519449175a50259de301647ac6 Mon Sep 17 00:00:00 2001 From: m-nakamura145 Date: Thu, 22 Feb 2018 15:13:43 +0900 Subject: [PATCH 422/707] Fix Gem::Version.correct? --- test/rubygems/test_gem_version.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/test/rubygems/test_gem_version.rb b/test/rubygems/test_gem_version.rb index 792ad5f0..bddae7fd 100644 --- a/test/rubygems/test_gem_version.rb +++ b/test/rubygems/test_gem_version.rb @@ -46,6 +46,7 @@ def test_class_create def test_class_correct assert_equal true, Gem::Version.correct?("5.1") assert_equal false, Gem::Version.correct?("an incorrect version") + assert_equal false, Gem::Version.correct?(nil) end def test_class_new_subclass From 1d0b7fa4158fff14b1e5d8dd38a7f54ab7ef57fe Mon Sep 17 00:00:00 2001 From: SHIBATA Hiroshi Date: Thu, 1 Mar 2018 11:29:49 +0900 Subject: [PATCH 423/707] Avoid to warnings for Gem.inflate, Gem.gunzip and Gem.gzip --- test/rubygems/test_gem.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 0910e1d8..26c6cbf3 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1214,7 +1214,7 @@ def test_self_gunzip input = "\x1F\x8B\b\0\xED\xA3\x1AQ\0\x03\xCBH" + "\xCD\xC9\xC9\a\0\x86\xA6\x106\x05\0\0\0" - output = Gem.gunzip input + output = Gem::Util.gunzip input assert_equal 'hello', output @@ -1226,7 +1226,7 @@ def test_self_gunzip def test_self_gzip input = 'hello' - output = Gem.gzip input + output = Gem::Util.gzip input zipped = StringIO.new output From 49b5d587e40d0dd9b58e4e33d65bdafb4f9bc77b Mon Sep 17 00:00:00 2001 From: SHIBATA Hiroshi Date: Thu, 1 Mar 2018 11:55:22 +0900 Subject: [PATCH 424/707] replace use_gemdeps instead of detect_gemdeps --- test/rubygems/test_gem.rb | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 26c6cbf3..6eca4288 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -387,7 +387,7 @@ def test_self_default_sources assert_equal %w[https://rubygems.org/], Gem.default_sources end - def test_self_detect_gemdeps + def test_self_use_gemdeps skip 'Insecure operation - chdir' if RUBY_VERSION <= "1.8.7" rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], '-' @@ -399,7 +399,7 @@ def test_self_detect_gemdeps begin Dir.chdir 'detect/a/b' - assert_equal add_bundler_full_name([]), Gem.detect_gemdeps.map(&:full_name) + assert_equal add_bundler_full_name([]), Gem.use_gemdeps.map(&:full_name) ensure Dir.chdir @tempdir end @@ -1450,12 +1450,12 @@ def test_auto_activation_of_specific_gemdeps_file ENV['RUBYGEMS_GEMDEPS'] = path - Gem.detect_gemdeps + Gem.use_gemdeps assert_equal add_bundler_full_name(%W(a-1 b-1 c-1)), loaded_spec_names end - def test_auto_activation_of_detected_gemdeps_file + def test_auto_activation_of_used_gemdeps_file skip 'Insecure operation - chdir' if RUBY_VERSION <= "1.8.7" util_clear_gems @@ -1476,7 +1476,7 @@ def test_auto_activation_of_detected_gemdeps_file ENV['RUBYGEMS_GEMDEPS'] = "-" expected_specs = [a, b, (Gem::USE_BUNDLER_FOR_GEMDEPS || nil) && util_spec("bundler", Bundler::VERSION), c].compact - assert_equal expected_specs, Gem.detect_gemdeps.sort_by { |s| s.name } + assert_equal expected_specs, Gem.use_gemdeps.sort_by { |s| s.name } end LIB_PATH = File.expand_path "../../../lib".dup.untaint, __FILE__.dup.untaint From 026cb98eb71d90dfe2c9225f4fbe3c1fa6aef266 Mon Sep 17 00:00:00 2001 From: Stephanie Morillo Date: Fri, 2 Mar 2018 13:50:53 -0500 Subject: [PATCH 425/707] Link out directly to contributor guidelines Hey team, The "Contributing" section confusingly sends contributors over to the "Documentation" README, and from there, contributors have to click on "Overview" to actually get to the guidelines. Since it's easier to cut out those two steps, I've rephrased a sentence and provide the direct link to the contributor guidelines here. --- bundler/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bundler/README.md b/bundler/README.md index 4e438ed0..dee020f3 100644 --- a/bundler/README.md +++ b/bundler/README.md @@ -45,7 +45,8 @@ To get in touch with the Bundler core team and other Bundler users, please see [ ### Contributing -If you'd like to contribute to Bundler, that's awesome, and we <3 you. There's a guide to contributing to Bundler (both code and general help) over in [our documentation section](doc/README.md). +If you'd like to contribute to Bundler, that's awesome, and we <3 you. We've put together [the Bundler contributor guide](https://github.com/bundler/bundler/blob/master/doc/contributing/README.md) with all of the information you need to get started. + While some Bundler contributors are compensated by Ruby Together, the project maintainers make decisions independent of Ruby Together. As a project, we welcome contributions regardless of the author’s affiliation with Ruby Together. From e65841bdfc8bb445b3da04ab22d729d74302a829 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Wed, 14 Jan 2015 00:03:44 +0900 Subject: [PATCH 426/707] Test for permission options --- test/rubygems/test_gem.rb | 45 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 6eca4288..c0105b52 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -130,6 +130,51 @@ def test_self_install_in_rescue assert_equal %w[a-1], installed.map { |spec| spec.full_name } end + def test_self_install_permissions + options = { + :dir_mode => 0500, + :prog_mode => 0510, + :data_mode => 0640, + } + Dir.chdir @tempdir do + Dir.mkdir 'bin' + File.open 'bin/foo.rb', 'w' do |fp| + fp.chmod(0755) + fp.puts 'p' + end + + Dir.mkdir 'data' + File.open 'data/foo.txt', 'w' do |fp| + fp.puts 'blah' + end + + spec_fetcher do |f| + f.gem 'foo', 1 do |s| + s.executables = ['foo.rb'] + s.files = %w[bin/foo.rb data/foo.txt] + end + end + Gem.install 'foo', Gem::Requirement.default, options + end + + expected = { + '.' => options[:dir_mode].to_s(8), + 'bin' => options[:dir_mode].to_s(8), + 'data' => options[:dir_mode].to_s(8), + 'bin/foo.rb' => options[:prog_mode].to_s(8), + 'data/foo.txt' => options[:data_mode].to_s(8), + } + result = {} + Dir.chdir File.join(@gemhome, 'gems/foo-1') do + expected.each_key do |n| + result[n] = (File.stat(n).mode & 0777).to_s(8) + end + end + assert_equal(expected, result) + ensure + File.chmod(0700, *Dir.glob(@gemhome+'/gems/**/')) + end + def test_require_missing save_loaded_features do assert_raises ::LoadError do From 833b90cdd0cba6324695de82c19b934e7e1e425d Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Tue, 17 Feb 2015 12:43:57 +0900 Subject: [PATCH 427/707] Untaint globbed path names for tainted mode --- test/rubygems/test_gem.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index c0105b52..79ae7705 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -172,7 +172,7 @@ def test_self_install_permissions end assert_equal(expected, result) ensure - File.chmod(0700, *Dir.glob(@gemhome+'/gems/**/')) + File.chmod(0700, *Dir.glob(@gemhome+'/gems/**/').map {|path| path.untaint}) end def test_require_missing From 9d5f897397f37e9190fd9f39cc6e4791c8572b5c Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Sun, 5 Apr 2015 09:02:58 +0900 Subject: [PATCH 428/707] Permission of wrapper scripts Set permission of wrapper scripts after opened to avoid being affected by umask. --- test/rubygems/test_gem.rb | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 79ae7705..5f8eb07b 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -131,10 +131,29 @@ def test_self_install_in_rescue end def test_self_install_permissions + assert_self_install_permissions + end + + def test_self_install_permissions_umask_0 + umask = File.umask(0) + assert_self_install_permissions + ensure + File.umask(umask) + end + + def test_self_install_permissions_umask_077 + umask = File.umask(077) + assert_self_install_permissions + ensure + File.umask(umask) + end + + def assert_self_install_permissions options = { :dir_mode => 0500, :prog_mode => 0510, :data_mode => 0640, + :wrappers => true, } Dir.chdir @tempdir do Dir.mkdir 'bin' @@ -158,14 +177,15 @@ def test_self_install_permissions end expected = { - '.' => options[:dir_mode].to_s(8), - 'bin' => options[:dir_mode].to_s(8), - 'data' => options[:dir_mode].to_s(8), 'bin/foo.rb' => options[:prog_mode].to_s(8), - 'data/foo.txt' => options[:data_mode].to_s(8), + 'gems/foo-1' => options[:dir_mode].to_s(8), + 'gems/foo-1/bin' => options[:dir_mode].to_s(8), + 'gems/foo-1/data' => options[:dir_mode].to_s(8), + 'gems/foo-1/bin/foo.rb' => options[:prog_mode].to_s(8), + 'gems/foo-1/data/foo.txt' => options[:data_mode].to_s(8), } result = {} - Dir.chdir File.join(@gemhome, 'gems/foo-1') do + Dir.chdir @gemhome do expected.each_key do |n| result[n] = (File.stat(n).mode & 0777).to_s(8) end From 39e29a1960b165cbbc5d4c4ad2df5ebb9745e28d Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Mon, 5 Mar 2018 14:34:38 +0900 Subject: [PATCH 429/707] Fix for Windows On Windows: As file excutable bit is determined by the suffix of the file name, use '.cmd' as the suffix for executable file instead of '.rb'. As only user bits in mode are effective, and are copied to other bits, mask results and expected modes by effective bits. --- test/rubygems/test_gem.rb | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 5f8eb07b..362f6d26 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -149,6 +149,7 @@ def test_self_install_permissions_umask_077 end def assert_self_install_permissions + mask = /mingw|mswin/ =~ RUBY_PLATFORM ? 0700 : 0777 options = { :dir_mode => 0500, :prog_mode => 0510, @@ -157,7 +158,7 @@ def assert_self_install_permissions } Dir.chdir @tempdir do Dir.mkdir 'bin' - File.open 'bin/foo.rb', 'w' do |fp| + File.open 'bin/foo.cmd', 'w' do |fp| fp.chmod(0755) fp.puts 'p' end @@ -169,25 +170,28 @@ def assert_self_install_permissions spec_fetcher do |f| f.gem 'foo', 1 do |s| - s.executables = ['foo.rb'] - s.files = %w[bin/foo.rb data/foo.txt] + s.executables = ['foo.cmd'] + s.files = %w[bin/foo.cmd data/foo.txt] end end Gem.install 'foo', Gem::Requirement.default, options end + prog_mode = (options[:prog_mode] & mask).to_s(8) + dir_mode = (options[:dir_mode] & mask).to_s(8) + data_mode = (options[:data_mode] & mask).to_s(8) expected = { - 'bin/foo.rb' => options[:prog_mode].to_s(8), - 'gems/foo-1' => options[:dir_mode].to_s(8), - 'gems/foo-1/bin' => options[:dir_mode].to_s(8), - 'gems/foo-1/data' => options[:dir_mode].to_s(8), - 'gems/foo-1/bin/foo.rb' => options[:prog_mode].to_s(8), - 'gems/foo-1/data/foo.txt' => options[:data_mode].to_s(8), + 'bin/foo.cmd' => prog_mode, + 'gems/foo-1' => dir_mode, + 'gems/foo-1/bin' => dir_mode, + 'gems/foo-1/data' => dir_mode, + 'gems/foo-1/bin/foo.cmd' => prog_mode, + 'gems/foo-1/data/foo.txt' => data_mode, } result = {} Dir.chdir @gemhome do expected.each_key do |n| - result[n] = (File.stat(n).mode & 0777).to_s(8) + result[n] = (File.stat(n).mode & mask).to_s(8) end end assert_equal(expected, result) From 0964219102214b7a959936aa1b4f2a07b4d1658d Mon Sep 17 00:00:00 2001 From: SHIBATA Hiroshi Date: Wed, 7 Mar 2018 09:25:06 +0900 Subject: [PATCH 430/707] Removed needless condition for Encoding. It's always provided after Ruby 1.9+ --- test/rubygems/test_gem.rb | 6 ------ 1 file changed, 6 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 362f6d26..f6ab0dd6 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1286,9 +1286,6 @@ def test_self_gunzip output = Gem::Util.gunzip input assert_equal 'hello', output - - return unless Object.const_defined? :Encoding - assert_equal Encoding::BINARY, output.encoding end @@ -1300,9 +1297,6 @@ def test_self_gzip zipped = StringIO.new output assert_equal 'hello', Zlib::GzipReader.new(zipped).read - - return unless Object.const_defined? :Encoding - assert_equal Encoding::BINARY, output.encoding end From 831554839e3afd550db8219a2f3f52b38a184860 Mon Sep 17 00:00:00 2001 From: SHIBATA Hiroshi Date: Fri, 9 Mar 2018 14:49:09 +0900 Subject: [PATCH 431/707] To use util_spec instead of new_spec. --- test/rubygems/test_gem.rb | 70 +++++++++++++++++++-------------------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index f6ab0dd6..88cec8fe 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -31,11 +31,11 @@ def setup def test_self_finish_resolve save_loaded_features do - a1 = new_spec "a", "1", "b" => "> 0" - b1 = new_spec "b", "1", "c" => ">= 1" - b2 = new_spec "b", "2", "c" => ">= 2" - c1 = new_spec "c", "1" - c2 = new_spec "c", "2" + a1 = util_spec "a", "1", "b" => "> 0" + b1 = util_spec "b", "1", "c" => ">= 1" + b2 = util_spec "b", "2", "c" => ">= 2" + c1 = util_spec "c", "1" + c2 = util_spec "c", "2" install_specs c1, c2, b1, b2, a1 @@ -53,13 +53,13 @@ def test_self_finish_resolve def test_self_finish_resolve_wtf save_loaded_features do - a1 = new_spec "a", "1", "b" => "> 0", "d" => "> 0" # this - b1 = new_spec "b", "1", { "c" => ">= 1" }, "lib/b.rb" # this - b2 = new_spec "b", "2", { "c" => ">= 2" }, "lib/b.rb" - c1 = new_spec "c", "1" # this - c2 = new_spec "c", "2" - d1 = new_spec "d", "1", { "c" => "< 2" }, "lib/d.rb" - d2 = new_spec "d", "2", { "c" => "< 2" }, "lib/d.rb" # this + a1 = util_spec "a", "1", "b" => "> 0", "d" => "> 0" # this + b1 = util_spec "b", "1", { "c" => ">= 1" }, "lib/b.rb" # this + b2 = util_spec "b", "2", { "c" => ">= 2" }, "lib/b.rb" + c1 = util_spec "c", "1" # this + c2 = util_spec "c", "2" + d1 = util_spec "d", "1", { "c" => "< 2" }, "lib/d.rb" + d2 = util_spec "d", "2", { "c" => "< 2" }, "lib/d.rb" # this install_specs c1, c2, b1, b2, d1, d2, a1 @@ -77,11 +77,11 @@ def test_self_finish_resolve_wtf def test_self_finish_resolve_respects_loaded_specs save_loaded_features do - a1 = new_spec "a", "1", "b" => "> 0" - b1 = new_spec "b", "1", "c" => ">= 1" - b2 = new_spec "b", "2", "c" => ">= 2" - c1 = new_spec "c", "1" - c2 = new_spec "c", "2" + a1 = util_spec "a", "1", "b" => "> 0" + b1 = util_spec "b", "1", "c" => ">= 1" + b2 = util_spec "b", "2", "c" => ">= 2" + c1 = util_spec "c", "1" + c2 = util_spec "c", "2" install_specs c1, c2, b1, b2, a1 @@ -209,7 +209,7 @@ def test_require_missing def test_require_does_not_glob save_loaded_features do - a1 = new_spec "a", "1", nil, "lib/a1.rb" + a1 = util_spec "a", "1", nil, "lib/a1.rb" install_specs a1 @@ -1263,7 +1263,7 @@ def test_self_needs_picks_up_unresolved_deps a = util_spec "a", "1" b = util_spec "b", "1", "c" => nil c = util_spec "c", "2" - d = new_spec "d", "1", {'e' => '= 1'}, "lib/d.rb" + d = util_spec "d", "1", {'e' => '= 1'}, "lib/d.rb" e = util_spec "e", "1" install_specs a, c, b, e, d @@ -1423,8 +1423,8 @@ def test_gem_path_ordering write_file File.join(@tempdir, 'lib', "g.rb") { |fp| fp.puts "" } write_file File.join(@tempdir, 'lib', 'm.rb') { |fp| fp.puts "" } - g = new_spec 'g', '1', nil, "lib/g.rb" - m = new_spec 'm', '1', nil, "lib/m.rb" + g = util_spec 'g', '1', nil, "lib/g.rb" + m = util_spec 'm', '1', nil, "lib/m.rb" install_gem g, :install_dir => Gem.dir m0 = install_gem m, :install_dir => Gem.dir @@ -1479,8 +1479,8 @@ def test_gem_path_ordering_short write_file File.join(@tempdir, 'lib', "g.rb") { |fp| fp.puts "" } write_file File.join(@tempdir, 'lib', 'm.rb') { |fp| fp.puts "" } - g = new_spec 'g', '1', nil, "lib/g.rb" - m = new_spec 'm', '1', nil, "lib/m.rb" + g = util_spec 'g', '1', nil, "lib/g.rb" + m = util_spec 'm', '1', nil, "lib/m.rb" install_gem g, :install_dir => Gem.dir install_gem m, :install_dir => Gem.dir @@ -1497,9 +1497,9 @@ def test_gem_path_ordering_short def test_auto_activation_of_specific_gemdeps_file util_clear_gems - a = new_spec "a", "1", nil, "lib/a.rb" - b = new_spec "b", "1", nil, "lib/b.rb" - c = new_spec "c", "1", nil, "lib/c.rb" + a = util_spec "a", "1", nil, "lib/a.rb" + b = util_spec "b", "1", nil, "lib/b.rb" + c = util_spec "c", "1", nil, "lib/c.rb" install_specs a, b, c @@ -1522,9 +1522,9 @@ def test_auto_activation_of_used_gemdeps_file skip 'Insecure operation - chdir' if RUBY_VERSION <= "1.8.7" util_clear_gems - a = new_spec "a", "1", nil, "lib/a.rb" - b = new_spec "b", "1", nil, "lib/b.rb" - c = new_spec "c", "1", nil, "lib/c.rb" + a = util_spec "a", "1", nil, "lib/a.rb" + b = util_spec "b", "1", nil, "lib/b.rb" + c = util_spec "c", "1", nil, "lib/c.rb" install_specs a, b, c @@ -1559,9 +1559,9 @@ def add_bundler_full_name(names) def test_looks_for_gemdeps_files_automatically_on_start util_clear_gems - a = new_spec "a", "1", nil, "lib/a.rb" - b = new_spec "b", "1", nil, "lib/b.rb" - c = new_spec "c", "1", nil, "lib/c.rb" + a = util_spec "a", "1", nil, "lib/a.rb" + b = util_spec "b", "1", nil, "lib/b.rb" + c = util_spec "c", "1", nil, "lib/c.rb" install_specs a, b, c @@ -1600,9 +1600,9 @@ def test_looks_for_gemdeps_files_automatically_on_start def test_looks_for_gemdeps_files_automatically_on_start_in_parent_dir util_clear_gems - a = new_spec "a", "1", nil, "lib/a.rb" - b = new_spec "b", "1", nil, "lib/b.rb" - c = new_spec "c", "1", nil, "lib/c.rb" + a = util_spec "a", "1", nil, "lib/a.rb" + b = util_spec "b", "1", nil, "lib/b.rb" + c = util_spec "c", "1", nil, "lib/c.rb" install_specs a, b, c From ec386db2e52d0fb58090017bc8eae89094feca9e Mon Sep 17 00:00:00 2001 From: Samuel Giddins Date: Sat, 10 Mar 2018 17:06:25 -0800 Subject: [PATCH 432/707] [Requirement] Treat requirements with == versions as equal MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously, Gem::Requirement.new(“= 1) != Gem::Requirement.new(“= 1.0) We fix that by comparing equality by the (op, version) tuples, rather than string equality on the versions Internally, we now keep requirements sorted by version, so we don’t need to re-sort each time any method that uses a sorted list of requirements is called (such as == or to_s) --- test/rubygems/test_gem_requirement.rb | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/rubygems/test_gem_requirement.rb b/test/rubygems/test_gem_requirement.rb index ea354f7b..974f5891 100644 --- a/test/rubygems/test_gem_requirement.rb +++ b/test/rubygems/test_gem_requirement.rb @@ -28,6 +28,8 @@ def test_initialize assert_requirement_equal "= 2", "2" assert_requirement_equal "= 2", ["2"] assert_requirement_equal "= 2", v(2) + assert_requirement_equal "2.0", "2" + assert_requirement_equal ["= 2", ">= 2"], [">= 2", "= 2"] end def test_create @@ -69,6 +71,7 @@ def test_parse assert_equal ['=', Gem::Version.new(1)], Gem::Requirement.parse('= 1') assert_equal ['>', Gem::Version.new(1)], Gem::Requirement.parse('> 1') assert_equal ['=', Gem::Version.new(1)], Gem::Requirement.parse("=\n1") + assert_equal ['=', Gem::Version.new(1)], Gem::Requirement.parse('1.0') assert_equal ['=', Gem::Version.new(2)], Gem::Requirement.parse(Gem::Version.new('2')) @@ -226,6 +229,8 @@ def test_satisfied_by_eh_good assert_satisfied_by "0.2.33", "= 0.2.33" assert_satisfied_by "0.2.34", "> 0.2.33" assert_satisfied_by "1.0", "= 1.0" + assert_satisfied_by "1.0.0", "= 1.0" + assert_satisfied_by "1.0", "= 1.0.0" assert_satisfied_by "1.0", "1.0" assert_satisfied_by "1.8.2", "> 1.8.0" assert_satisfied_by "1.112", "> 1.111" @@ -313,6 +318,7 @@ def test_satisfied_by_eh_multiple def test_satisfied_by_boxed refute_satisfied_by "1.3", "~> 1.4" assert_satisfied_by "1.4", "~> 1.4" + assert_satisfied_by "1.4.0", "~> 1.4" assert_satisfied_by "1.5", "~> 1.4" refute_satisfied_by "2.0", "~> 1.4" From 28949a6c1cda6d90e8c985e3880f0f1a4008c10d Mon Sep 17 00:00:00 2001 From: SHIBATA Hiroshi Date: Tue, 27 Mar 2018 15:35:59 +0900 Subject: [PATCH 433/707] Removed needless version condition for the old ruby --- test/rubygems/test_gem.rb | 72 ++------------------------------------- 1 file changed, 3 insertions(+), 69 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 88cec8fe..f383d5af 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -457,7 +457,6 @@ def test_self_default_sources end def test_self_use_gemdeps - skip 'Insecure operation - chdir' if RUBY_VERSION <= "1.8.7" rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], '-' FileUtils.mkdir_p 'detect/a/b' @@ -611,9 +610,6 @@ def test_self_find_files end def test_self_find_files_with_gemfile - # write_file(File.join Dir.pwd, 'Gemfile') fails on travis 1.8.7 with $SAFE=1 - skip if RUBY_VERSION <= "1.8.7" - cwd = File.expand_path("test/rubygems", @@project_dir) actual_load_path = $LOAD_PATH.unshift(cwd).dup @@ -646,7 +642,7 @@ def test_self_find_files_with_gemfile assert_equal expected, Gem.find_files('sff/discover').sort assert_equal expected, Gem.find_files('sff/**.rb').sort, '[ruby-core:31730]' ensure - assert_equal cwd, actual_load_path.shift unless RUBY_VERSION <= "1.8.7" + assert_equal cwd, actual_load_path.shift end def test_self_find_latest_files @@ -862,7 +858,6 @@ def test_self_read_binary end def test_self_refresh - skip 'Insecure operation - mkdir' if RUBY_VERSION <= "1.8.7" util_make_gems a1_spec = @a1.spec_file @@ -882,7 +877,6 @@ def test_self_refresh end def test_self_refresh_keeps_loaded_specs_activated - skip 'Insecure operation - mkdir' if RUBY_VERSION <= "1.8.7" util_make_gems a1_spec = @a1.spec_file @@ -1257,7 +1251,6 @@ def test_self_needs end def test_self_needs_picks_up_unresolved_deps - skip 'loading from unsafe file' if RUBY_VERSION <= "1.8.7" save_loaded_features do util_clear_gems a = util_spec "a", "1" @@ -1300,49 +1293,6 @@ def test_self_gzip assert_equal Encoding::BINARY, output.encoding end - if Gem.win_platform? && '1.9' > RUBY_VERSION - # Ruby 1.9 properly handles ~ path expansion, so no need to run such tests. - def test_self_user_home_userprofile - - Gem.clear_paths - - # safe-keep env variables - orig_home, orig_user_profile = ENV['HOME'], ENV['USERPROFILE'] - - # prepare for the test - ENV.delete('HOME') - ENV['USERPROFILE'] = "W:\\Users\\RubyUser" - - assert_equal 'W:/Users/RubyUser', Gem.user_home - - ensure - ENV['HOME'] = orig_home - ENV['USERPROFILE'] = orig_user_profile - end - - def test_self_user_home_user_drive_and_path - Gem.clear_paths - - # safe-keep env variables - orig_home, orig_user_profile = ENV['HOME'], ENV['USERPROFILE'] - orig_home_drive, orig_home_path = ENV['HOMEDRIVE'], ENV['HOMEPATH'] - - # prepare the environment - ENV.delete('HOME') - ENV.delete('USERPROFILE') - ENV['HOMEDRIVE'] = 'Z:' - ENV['HOMEPATH'] = "\\Users\\RubyUser" - - assert_equal 'Z:/Users/RubyUser', Gem.user_home - - ensure - ENV['HOME'] = orig_home - ENV['USERPROFILE'] = orig_user_profile - ENV['HOMEDRIVE'] = orig_home_drive - ENV['HOMEPATH'] = orig_home_path - end - end - def test_self_vendor_dir expected = File.join RbConfig::CONFIG['vendordir'], 'gems', @@ -1368,7 +1318,6 @@ def test_self_vendor_dir_missing end def test_load_plugins - skip 'Insecure operation - chdir' if RUBY_VERSION <= "1.8.7" plugin_path = File.join "lib", "rubygems_plugin.rb" Dir.chdir @tempdir do @@ -1519,7 +1468,6 @@ def test_auto_activation_of_specific_gemdeps_file end def test_auto_activation_of_used_gemdeps_file - skip 'Insecure operation - chdir' if RUBY_VERSION <= "1.8.7" util_clear_gems a = util_spec "a", "1", nil, "lib/a.rb" @@ -1576,12 +1524,7 @@ def test_looks_for_gemdeps_files_automatically_on_start path = File.join @tempdir, "gem.deps.rb" cmd = [Gem.ruby.dup.untaint, "-I#{LIB_PATH.untaint}", "-I#{BUNDLER_LIB_PATH.untaint}", "-rrubygems"] - if RUBY_VERSION < '1.9' - cmd << "-e 'puts Gem.loaded_specs.values.map(&:full_name).sort'" - cmd = cmd.join(' ') - else - cmd << "-eputs Gem.loaded_specs.values.map(&:full_name).sort" - end + cmd << "-eputs Gem.loaded_specs.values.map(&:full_name).sort" File.open path, "w" do |f| f.puts "gem 'a'" @@ -1619,12 +1562,7 @@ def test_looks_for_gemdeps_files_automatically_on_start_in_parent_dir path = File.join @tempdir, "gem.deps.rb" cmd = [Gem.ruby.dup.untaint, "-Csub1", "-I#{LIB_PATH.untaint}", "-I#{BUNDLER_LIB_PATH.untaint}", "-rrubygems"] - if RUBY_VERSION < '1.9' - cmd << "-e 'puts Gem.loaded_specs.values.map(&:full_name).sort'" - cmd = cmd.join(' ') - else - cmd << "-eputs Gem.loaded_specs.values.map(&:full_name).sort" - end + cmd << "-eputs Gem.loaded_specs.values.map(&:full_name).sort" File.open path, "w" do |f| f.puts "gem 'a'" @@ -1759,7 +1697,6 @@ def test_use_gemdeps_argument_missing_match_ENV end def test_use_gemdeps_automatic - skip 'Insecure operation - chdir' if RUBY_VERSION <= "1.8.7" rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], '-' spec = util_spec 'a', 1 @@ -1780,7 +1717,6 @@ def test_use_gemdeps_automatic end def test_use_gemdeps_automatic_missing - skip 'Insecure operation - chdir' if RUBY_VERSION <= "1.8.7" rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], '-' Gem.use_gemdeps @@ -1809,7 +1745,6 @@ def test_use_gemdeps_disabled end def test_use_gemdeps_missing_gem - skip 'Insecure operation - read' if RUBY_VERSION <= "1.8.7" rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], 'x' File.open 'x', 'w' do |io| @@ -1844,7 +1779,6 @@ def test_use_gemdeps_missing_gem end if Gem::USE_BUNDLER_FOR_GEMDEPS def test_use_gemdeps_specific - skip 'Insecure operation - read' if RUBY_VERSION <= "1.8.7" rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], 'x' spec = util_spec 'a', 1 From 79fd7313a3603a83da7af59f9fbfa4131f4cec62 Mon Sep 17 00:00:00 2001 From: Stephanie Morillo Date: Fri, 30 Mar 2018 14:29:36 -0400 Subject: [PATCH 434/707] Added license info Thought about doing this for a while but completely forgot about it. Added a link out to the MIT license from the bottom of the README. (Just considered a general best practice for info to be included in a README.) --- bundler/README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/bundler/README.md b/bundler/README.md index dee020f3..80c70aa1 100644 --- a/bundler/README.md +++ b/bundler/README.md @@ -58,3 +58,7 @@ While some Bundler contributors are compensated by Ruby Together, the project ma ### Code of Conduct Everyone interacting in the Bundler project’s codebases, issue trackers, chat rooms, and mailing lists is expected to follow the [Bundler code of conduct](https://github.com/bundler/bundler/blob/master/CODE_OF_CONDUCT.md). + +###License + +[MIT License](https://github.com/bundler/bundler/blob/master/LICENSE.md) From babaadc1e87184f605302e639aa20369f6f443e2 Mon Sep 17 00:00:00 2001 From: Stephanie Morillo Date: Fri, 30 Mar 2018 20:22:10 -0400 Subject: [PATCH 435/707] Added space --- bundler/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundler/README.md b/bundler/README.md index 80c70aa1..3e00dfd2 100644 --- a/bundler/README.md +++ b/bundler/README.md @@ -59,6 +59,6 @@ While some Bundler contributors are compensated by Ruby Together, the project ma Everyone interacting in the Bundler project’s codebases, issue trackers, chat rooms, and mailing lists is expected to follow the [Bundler code of conduct](https://github.com/bundler/bundler/blob/master/CODE_OF_CONDUCT.md). -###License +### License [MIT License](https://github.com/bundler/bundler/blob/master/LICENSE.md) From 89ec3e3b74b98b792837128ad0533a8d576c7338 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Wed, 11 Apr 2018 08:29:12 -0300 Subject: [PATCH 436/707] Add an explicitly test for "< + ".a" resolution --- test/rubygems/test_gem_requirement.rb | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/test/rubygems/test_gem_requirement.rb b/test/rubygems/test_gem_requirement.rb index 974f5891..7bca00e5 100644 --- a/test/rubygems/test_gem_requirement.rb +++ b/test/rubygems/test_gem_requirement.rb @@ -330,6 +330,20 @@ def test_satisfied_by_boxed refute_satisfied_by "2.0", "~> 1.4.4" end + def test_satisfied_by_explicitly_bounded + req = [">= 1.4.4", "< 1.5"] + + assert_satisfied_by "1.4.5", req + assert_satisfied_by "1.5.0.rc1", req + refute_satisfied_by "1.5.0", req + + req = [">= 1.4.4", "< 1.5.a"] + + assert_satisfied_by "1.4.5", req + refute_satisfied_by "1.5.0.rc1", req + refute_satisfied_by "1.5.0", req + end + def test_specific refute req('> 1') .specific? refute req('>= 1').specific? From 30bfa8643baa87ca65370464d4882840238524a2 Mon Sep 17 00:00:00 2001 From: The Bundler Bot Date: Sat, 31 Mar 2018 06:52:09 +0000 Subject: [PATCH 437/707] Auto merge of #6467 - bundler:rubymorillo-patch-3, r=colby-swandale Added license info to main README Thought about doing this for a while but completely forgot about it. Added a link out to the MIT license from the bottom of the README. (Since it's considered a general best practice for info to be included in a README, and want to make sure the README is as complete as possible.) (cherry picked from commit 257fb54da0003c3a67f6e7b3b5a242a4ba9c45cb) --- bundler/README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/bundler/README.md b/bundler/README.md index 649b7771..db69f55f 100644 --- a/bundler/README.md +++ b/bundler/README.md @@ -57,3 +57,7 @@ While some Bundler contributors are compensated by Ruby Together, the project ma ### Code of Conduct Everyone interacting in the Bundler project’s codebases, issue trackers, chat rooms, and mailing lists is expected to follow the [Bundler code of conduct](https://github.com/bundler/bundler/blob/master/CODE_OF_CONDUCT.md). + +### License + +[MIT License](https://github.com/bundler/bundler/blob/master/LICENSE.md) From f6c6577ebe44f16385195d4b1ca1fb7f96f549d4 Mon Sep 17 00:00:00 2001 From: The Bundler Bot Date: Thu, 22 Feb 2018 07:07:28 +0000 Subject: [PATCH 438/707] Auto merge of #2203 - m-nakamura145:fix_version_correct, r=hsbt Fix Gem::Version.correct? # Description: in ruby 2.5.0. ``` irb(main):001:0> Gem::Version.correct?(nil) => true ``` I think that it was wrong. I think that I should behave as follows. ``` irb(main):001:0> Gem::Version.correct?(nil) => false ``` ______________ # Tasks: - [x] Describe the problem / feature - [x] Write tests - [x] Write code to solve the problem - [ ] Get code review from coworkers / friends I will abide by the [code of conduct](https://github.com/rubygems/rubygems/blob/master/CODE_OF_CONDUCT.md). --- test/rubygems/test_gem_version.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/test/rubygems/test_gem_version.rb b/test/rubygems/test_gem_version.rb index 792ad5f0..bddae7fd 100644 --- a/test/rubygems/test_gem_version.rb +++ b/test/rubygems/test_gem_version.rb @@ -46,6 +46,7 @@ def test_class_create def test_class_correct assert_equal true, Gem::Version.correct?("5.1") assert_equal false, Gem::Version.correct?("an incorrect version") + assert_equal false, Gem::Version.correct?(nil) end def test_class_new_subclass From 77b4264d55c396762fa8d1f3e2dd1fdab37e2c07 Mon Sep 17 00:00:00 2001 From: The Bundler Bot Date: Fri, 2 Mar 2018 21:26:24 +0000 Subject: [PATCH 439/707] Auto merge of #2214 - rubygems:deprecate-for-rubygems3, r=duckinator Deprecate for rubygems3 I've marked deprecated methods without `Gem::Deprecate#deprecate`. We're going to remove it in RubyGems 4(not 3) ______________ - [ ] Describe the problem / feature - [ ] Write tests - [ ] Write code to solve the problem - [ ] Get code review from coworkers / friends I will abide by the [code of conduct](https://github.com/rubygems/rubygems/blob/master/CODE_OF_CONDUCT.md). --- test/rubygems/test_gem.rb | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 183771f0..a6741e02 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -387,7 +387,7 @@ def test_self_default_sources assert_equal %w[https://rubygems.org/], Gem.default_sources end - def test_self_detect_gemdeps + def test_self_use_gemdeps skip 'Insecure operation - chdir' if RUBY_VERSION <= "1.8.7" rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], '-' @@ -399,7 +399,7 @@ def test_self_detect_gemdeps begin Dir.chdir 'detect/a/b' - assert_equal add_bundler_full_name([]), Gem.detect_gemdeps.map(&:full_name) + assert_equal add_bundler_full_name([]), Gem.use_gemdeps.map(&:full_name) ensure Dir.chdir @tempdir end @@ -1214,7 +1214,7 @@ def test_self_gunzip input = "\x1F\x8B\b\0\xED\xA3\x1AQ\0\x03\xCBH" + "\xCD\xC9\xC9\a\0\x86\xA6\x106\x05\0\0\0" - output = Gem.gunzip input + output = Gem::Util.gunzip input assert_equal 'hello', output @@ -1226,7 +1226,7 @@ def test_self_gunzip def test_self_gzip input = 'hello' - output = Gem.gzip input + output = Gem::Util.gzip input zipped = StringIO.new output @@ -1450,12 +1450,12 @@ def test_auto_activation_of_specific_gemdeps_file ENV['RUBYGEMS_GEMDEPS'] = path - Gem.detect_gemdeps + Gem.use_gemdeps assert_equal add_bundler_full_name(%W(a-1 b-1 c-1)), loaded_spec_names end - def test_auto_activation_of_detected_gemdeps_file + def test_auto_activation_of_used_gemdeps_file skip 'Insecure operation - chdir' if RUBY_VERSION <= "1.8.7" util_clear_gems @@ -1476,7 +1476,7 @@ def test_auto_activation_of_detected_gemdeps_file ENV['RUBYGEMS_GEMDEPS'] = "-" expected_specs = [a, b, (Gem::USE_BUNDLER_FOR_GEMDEPS || nil) && util_spec("bundler", Bundler::VERSION), c].compact - assert_equal expected_specs, Gem.detect_gemdeps.sort_by { |s| s.name } + assert_equal expected_specs, Gem.use_gemdeps.sort_by { |s| s.name } end LIB_PATH = File.expand_path "../../../lib".dup.untaint, __FILE__.dup.untaint From 1eaa57c961f6467c48ca8ac23ddc22ff01029763 Mon Sep 17 00:00:00 2001 From: Darshan Baid Date: Mon, 21 May 2018 19:48:10 +0530 Subject: [PATCH 440/707] Minor typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d00b5de8..91bdf3e9 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ that can be shared and used by other developers. See our guide on publishing a G ## Getting Started -Installing and managing a Gem is done through the `gem` command. To install a Gem such as [Nokigiri](https://github.com/sparklemotion/nokogiri) which lets +Installing and managing a Gem is done through the `gem` command. To install a Gem such as [Nokogiri](https://github.com/sparklemotion/nokogiri) which lets you read and parse XML in Ruby: $ gem install nokogiri From b3f56fdfd173ef43b7abe1e320c61574e5df933d Mon Sep 17 00:00:00 2001 From: Hugo David Farji Date: Sat, 30 Jun 2018 11:24:15 -0400 Subject: [PATCH 441/707] Updated 'bundle add' to rspec install guide --- bundler/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundler/README.md b/bundler/README.md index 3e00dfd2..db71b644 100644 --- a/bundler/README.md +++ b/bundler/README.md @@ -24,7 +24,7 @@ Bundler is most commonly used to manage your application's dependencies. For exa ``` bundle init -echo 'gem "rspec"' >> Gemfile +bundle add rspec bundle install bundle exec rspec ``` From 7d208bde45926ba0286900b0f912f46612f711e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Thu, 5 Jul 2018 11:40:10 -0300 Subject: [PATCH 442/707] Fix typo --- test/rubygems/test_gem_version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/rubygems/test_gem_version.rb b/test/rubygems/test_gem_version.rb index bddae7fd..5030dc25 100644 --- a/test/rubygems/test_gem_version.rb +++ b/test/rubygems/test_gem_version.rb @@ -198,7 +198,7 @@ def assert_prerelease version assert v(version).prerelease?, "#{version} is a prerelease" end - # Assert that +expected+ is the "approximate" recommendation for +version". + # Assert that +expected+ is the "approximate" recommendation for +version+. def assert_approximate_equal expected, version assert_equal expected, v(version).approximate_recommendation From c8a46bb006cabf05566bd5848fc9fa6d0895cd2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Thu, 5 Jul 2018 11:52:00 -0300 Subject: [PATCH 443/707] Fix approximate recommendation for prereleases --- test/rubygems/test_gem_version.rb | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/test/rubygems/test_gem_version.rb b/test/rubygems/test_gem_version.rb index 5030dc25..fdee0a37 100644 --- a/test/rubygems/test_gem_version.rb +++ b/test/rubygems/test_gem_version.rb @@ -158,11 +158,25 @@ def test_spaceship def test_approximate_recommendation assert_approximate_equal "~> 1.0", "1" + assert_approximate_satisfies_itself "1" + assert_approximate_equal "~> 1.0", "1.0" + assert_approximate_satisfies_itself "1.0" + assert_approximate_equal "~> 1.2", "1.2" + assert_approximate_satisfies_itself "1.2" + assert_approximate_equal "~> 1.2", "1.2.0" + assert_approximate_satisfies_itself "1.2.0" + assert_approximate_equal "~> 1.2", "1.2.3" - assert_approximate_equal "~> 1.2", "1.2.3.a.4" + assert_approximate_satisfies_itself "1.2.3" + + assert_approximate_equal "~> 1.2.a", "1.2.3.a.4" + assert_approximate_satisfies_itself "1.2.3.a.4" + + assert_approximate_equal "~> 1.9.a", "1.9.0.dev" + assert_approximate_satisfies_itself "1.9.0.dev" end def test_to_s @@ -204,6 +218,14 @@ def assert_approximate_equal expected, version assert_equal expected, v(version).approximate_recommendation end + # Assert that the "approximate" recommendation for +version+ satifies +version+. + + def assert_approximate_satisfies_itself version + gem_version = v(version) + + assert Gem::Requirement.new(gem_version.approximate_recommendation).satisfied_by?(gem_version) + end + # Assert that bumping the +unbumped+ version yields the +expected+. def assert_bumped_version_equal expected, unbumped From 46f2ad56a4ac6c6f8495b505f0cb85de28880d0c Mon Sep 17 00:00:00 2001 From: Stephanie Morillo Date: Sat, 7 Jul 2018 12:23:58 -0400 Subject: [PATCH 444/707] Added RFC to the README --- bundler/README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/bundler/README.md b/bundler/README.md index db71b644..c1598e36 100644 --- a/bundler/README.md +++ b/bundler/README.md @@ -45,8 +45,9 @@ To get in touch with the Bundler core team and other Bundler users, please see [ ### Contributing -If you'd like to contribute to Bundler, that's awesome, and we <3 you. We've put together [the Bundler contributor guide](https://github.com/bundler/bundler/blob/master/doc/contributing/README.md) with all of the information you need to get started. +If you'd like to contribute to Bundler, that's awesome, and we <3 you. We've put together [the Bundler contributor guide](https://github.com/bundler/bundler/blob/master/doc/contributing/README.md) with all of the information you need to get started. +If you'd like to request a substantial change to Bundler or to the Bundler documentation, refer to the [Bundler RFC process](https://github.com/bundler/rfcs) for more information. While some Bundler contributors are compensated by Ruby Together, the project maintainers make decisions independent of Ruby Together. As a project, we welcome contributions regardless of the author’s affiliation with Ruby Together. @@ -61,4 +62,4 @@ Everyone interacting in the Bundler project’s codebases, issue trackers, chat ### License -[MIT License](https://github.com/bundler/bundler/blob/master/LICENSE.md) +Bundler is available under an [MIT License](https://github.com/bundler/bundler/blob/master/LICENSE.md). From c3d44d19f4a3f2cede0ea9db3ac2460392f51d70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Sun, 8 Jul 2018 09:51:32 -0300 Subject: [PATCH 445/707] Normalize indentation width --- test/rubygems/test_gem.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index f383d5af..ddf0f7e0 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1758,7 +1758,7 @@ def test_use_gemdeps_missing_gem platform = " #{platform}" end expected = if Gem::USE_BUNDLER_FOR_GEMDEPS - <<-EXPECTED + <<-EXPECTED Could not find gem 'a#{platform}' in any of the gem sources listed in your Gemfile. You may need to `gem install -g` to install missing gems From 7e8e74baee8a2eb396a2e8ecda580355e16a2dee Mon Sep 17 00:00:00 2001 From: Andre Arko Date: Sun, 8 Jul 2018 21:45:58 -0700 Subject: [PATCH 446/707] get that trailing whitespace --- bundler/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundler/README.md b/bundler/README.md index c1598e36..c596a320 100644 --- a/bundler/README.md +++ b/bundler/README.md @@ -45,7 +45,7 @@ To get in touch with the Bundler core team and other Bundler users, please see [ ### Contributing -If you'd like to contribute to Bundler, that's awesome, and we <3 you. We've put together [the Bundler contributor guide](https://github.com/bundler/bundler/blob/master/doc/contributing/README.md) with all of the information you need to get started. +If you'd like to contribute to Bundler, that's awesome, and we <3 you. We've put together [the Bundler contributor guide](https://github.com/bundler/bundler/blob/master/doc/contributing/README.md) with all of the information you need to get started. If you'd like to request a substantial change to Bundler or to the Bundler documentation, refer to the [Bundler RFC process](https://github.com/bundler/rfcs) for more information. From 409bfc45e8379810288de12adaf60f37dc0dfdee Mon Sep 17 00:00:00 2001 From: Luis Sagastume Date: Fri, 20 Jul 2018 09:25:28 -0600 Subject: [PATCH 447/707] Gem::Version should handle like it used to before --- test/rubygems/test_gem_version.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/test/rubygems/test_gem_version.rb b/test/rubygems/test_gem_version.rb index fdee0a37..d85dcb30 100644 --- a/test/rubygems/test_gem_version.rb +++ b/test/rubygems/test_gem_version.rb @@ -46,7 +46,6 @@ def test_class_create def test_class_correct assert_equal true, Gem::Version.correct?("5.1") assert_equal false, Gem::Version.correct?("an incorrect version") - assert_equal false, Gem::Version.correct?(nil) end def test_class_new_subclass From 74a3e890567ce70982c605ff39ce84b609a27e81 Mon Sep 17 00:00:00 2001 From: Luis Sagastume Date: Tue, 24 Jul 2018 10:52:48 -0600 Subject: [PATCH 448/707] Add deprecation warning --- test/rubygems/test_gem_version.rb | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/rubygems/test_gem_version.rb b/test/rubygems/test_gem_version.rb index d85dcb30..b52a62eb 100644 --- a/test/rubygems/test_gem_version.rb +++ b/test/rubygems/test_gem_version.rb @@ -46,6 +46,11 @@ def test_class_create def test_class_correct assert_equal true, Gem::Version.correct?("5.1") assert_equal false, Gem::Version.correct?("an incorrect version") + + expected = "nil versions are discouraged and will be deprecated in Rubygems 4\n" + assert_output nil, expected do + assert_equal false, Gem::Version.correct?(nil) + end end def test_class_new_subclass From 2baab6c816a8064cd574e610ee42132d2032c09f Mon Sep 17 00:00:00 2001 From: Luis Sagastume Date: Thu, 26 Jul 2018 13:30:56 -0600 Subject: [PATCH 449/707] Revert the actual code to how it was before... --- test/rubygems/test_gem_version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/rubygems/test_gem_version.rb b/test/rubygems/test_gem_version.rb index b52a62eb..a2572fb6 100644 --- a/test/rubygems/test_gem_version.rb +++ b/test/rubygems/test_gem_version.rb @@ -49,7 +49,7 @@ def test_class_correct expected = "nil versions are discouraged and will be deprecated in Rubygems 4\n" assert_output nil, expected do - assert_equal false, Gem::Version.correct?(nil) + Gem::Version.correct?(nil) end end From 96b46d4c88535651647a23284538bd2aa6e44b64 Mon Sep 17 00:00:00 2001 From: Samuel Giddins Date: Wed, 1 Aug 2018 00:25:07 -0700 Subject: [PATCH 450/707] Fix computation of version range emptiness --- bundler/spec/bundler/version_ranges_spec.rb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/bundler/spec/bundler/version_ranges_spec.rb b/bundler/spec/bundler/version_ranges_spec.rb index ccbb9285..bca044b0 100644 --- a/bundler/spec/bundler/version_ranges_spec.rb +++ b/bundler/spec/bundler/version_ranges_spec.rb @@ -25,9 +25,12 @@ include_examples "empty?", false, ">= 1.0.0", "< 2.0.0" include_examples "empty?", false, "~> 1" include_examples "empty?", false, "~> 2.0", "~> 2.1" + include_examples "empty?", true, ">= 4.1.0", "< 5.0", "= 5.2.1" + include_examples "empty?", true, "< 5.0", "< 5.3", "< 6.0", "< 6", "= 5.2.0", "> 2", ">= 3.0", ">= 3.1", ">= 3.2", ">= 4.0.0", ">= 4.1.0", ">= 4.2.0", ">= 4.2", ">= 4" include_examples "empty?", true, "!= 1", "< 2", "> 2" include_examples "empty?", true, "!= 1", "<= 1", ">= 1" include_examples "empty?", true, "< 2", "> 2" + include_examples "empty?", true, "< 2", "> 2", "= 2" include_examples "empty?", true, "= 1", "!= 1" include_examples "empty?", true, "= 1", "= 2" include_examples "empty?", true, "= 1", "~> 2" From 0006a15cf66ebd047556050c46d714c22b1c9e8d Mon Sep 17 00:00:00 2001 From: SHIBATA Hiroshi Date: Wed, 8 Aug 2018 14:46:13 +0900 Subject: [PATCH 451/707] Revert "Auto merge of #2203 - m-nakamura145:fix_version_correct, r=hsbt" This reverts commit f6c6577ebe44f16385195d4b1ca1fb7f96f549d4. --- test/rubygems/test_gem_version.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/test/rubygems/test_gem_version.rb b/test/rubygems/test_gem_version.rb index bddae7fd..792ad5f0 100644 --- a/test/rubygems/test_gem_version.rb +++ b/test/rubygems/test_gem_version.rb @@ -46,7 +46,6 @@ def test_class_create def test_class_correct assert_equal true, Gem::Version.correct?("5.1") assert_equal false, Gem::Version.correct?("an incorrect version") - assert_equal false, Gem::Version.correct?(nil) end def test_class_new_subclass From ad791f0dc8c5fade21b65741d74769f1130af552 Mon Sep 17 00:00:00 2001 From: The Bundler Bot Date: Sun, 1 Jul 2018 04:16:59 +0000 Subject: [PATCH 452/707] Auto merge of #6612 - hdf1986:readme-bundle-add, r=segiddins Updated 'bundle add' to rspec install guide ### What was the end-user problem that led to this PR? There's a new command `bundle add` which is almost unknown ### What was your diagnosis of the problem? We are promoting to use a simple append to the Gemfile when there's a `bundle add` command available ### What is your fix for the problem, implemented in this PR? My fix is just a little readme change :sweat_smile: ### Why did you choose this fix out of the possible options? Because it's a simple fix and provides more exposure to the command (cherry picked from commit 34f909fc351934c00a7dcc3e3ea76771fd3f903f) --- bundler/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundler/README.md b/bundler/README.md index db69f55f..c9b85a7c 100644 --- a/bundler/README.md +++ b/bundler/README.md @@ -24,7 +24,7 @@ Bundler is most commonly used to manage your application's dependencies. For exa ``` bundle init -echo 'gem "rspec"' >> Gemfile +bundle add rspec bundle install bundle exec rspec ``` From 39ec0a4a1358d6ae4387c78300f8432e3e90c9c5 Mon Sep 17 00:00:00 2001 From: Colby Swandale Date: Fri, 5 Oct 2018 14:49:05 +1000 Subject: [PATCH 453/707] freeze all possible constants --- test/rubygems/test_gem.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index ddf0f7e0..a980fdfb 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -14,7 +14,7 @@ class TestGem < Gem::TestCase - PLUGINS_LOADED = [] + PLUGINS_LOADED = [] # rubocop:disable Style/MutableConstant def setup super @@ -1494,7 +1494,7 @@ def test_auto_activation_of_used_gemdeps_file if Gem::USE_BUNDLER_FOR_GEMDEPS BUNDLER_LIB_PATH = File.expand_path $LOAD_PATH.find {|lp| File.file?(File.join(lp, "bundler.rb")) }.dup.untaint - BUNDLER_FULL_NAME = "bundler-#{Bundler::VERSION}" + BUNDLER_FULL_NAME = "bundler-#{Bundler::VERSION}".freeze end def add_bundler_full_name(names) From 8c2088ec738302dd8ba418471fea2d312eff0b5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lafortune?= Date: Fri, 5 Oct 2018 18:08:17 -0400 Subject: [PATCH 454/707] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 91bdf3e9..b909f4d3 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,7 @@ To upgrade to the latest RubyGems, run: Note: You might need to run the command as an administrator or root user. -See [UPGRADING](UPGRADING.rdoc) for more details and alternative instructions. +See [UPGRADING](UPGRADING.md) for more details and alternative instructions. ## Documentation From bac2b0817e685587341953c886ddd18386d2f17a Mon Sep 17 00:00:00 2001 From: The Bundler Bot Date: Sat, 31 Mar 2018 22:05:00 +0000 Subject: [PATCH 455/707] Auto merge of #2230 - rubygems:segiddins/sorted-requirements, r=bronzdoc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [Requirement] Treat requirements with == versions as equal Fixes https://github.com/bundler/bundler/issues/6295 Previously, Gem::Requirement.new(“= 1) != Gem::Requirement.new(“= 1.0) We fix that by comparing equality by the (op, version) tuples, rather than string equality on the versions Internally, we now keep requirements sorted by version, so we don’t need to re-sort each time any method that uses a sorted list of requirements is called (such as == or to_s) - [x] Describe the problem / feature - [x] Write tests - [x] Write code to solve the problem - [ ] Get code review from coworkers / friends I will abide by the [code of conduct](https://github.com/rubygems/rubygems/blob/master/CODE_OF_CONDUCT.md). --- test/rubygems/test_gem_requirement.rb | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/rubygems/test_gem_requirement.rb b/test/rubygems/test_gem_requirement.rb index ea354f7b..974f5891 100644 --- a/test/rubygems/test_gem_requirement.rb +++ b/test/rubygems/test_gem_requirement.rb @@ -28,6 +28,8 @@ def test_initialize assert_requirement_equal "= 2", "2" assert_requirement_equal "= 2", ["2"] assert_requirement_equal "= 2", v(2) + assert_requirement_equal "2.0", "2" + assert_requirement_equal ["= 2", ">= 2"], [">= 2", "= 2"] end def test_create @@ -69,6 +71,7 @@ def test_parse assert_equal ['=', Gem::Version.new(1)], Gem::Requirement.parse('= 1') assert_equal ['>', Gem::Version.new(1)], Gem::Requirement.parse('> 1') assert_equal ['=', Gem::Version.new(1)], Gem::Requirement.parse("=\n1") + assert_equal ['=', Gem::Version.new(1)], Gem::Requirement.parse('1.0') assert_equal ['=', Gem::Version.new(2)], Gem::Requirement.parse(Gem::Version.new('2')) @@ -226,6 +229,8 @@ def test_satisfied_by_eh_good assert_satisfied_by "0.2.33", "= 0.2.33" assert_satisfied_by "0.2.34", "> 0.2.33" assert_satisfied_by "1.0", "= 1.0" + assert_satisfied_by "1.0.0", "= 1.0" + assert_satisfied_by "1.0", "= 1.0.0" assert_satisfied_by "1.0", "1.0" assert_satisfied_by "1.8.2", "> 1.8.0" assert_satisfied_by "1.112", "> 1.111" @@ -313,6 +318,7 @@ def test_satisfied_by_eh_multiple def test_satisfied_by_boxed refute_satisfied_by "1.3", "~> 1.4" assert_satisfied_by "1.4", "~> 1.4" + assert_satisfied_by "1.4.0", "~> 1.4" assert_satisfied_by "1.5", "~> 1.4" refute_satisfied_by "2.0", "~> 1.4" From 0b9481b40c182863d762daa20c6a75311aeeede5 Mon Sep 17 00:00:00 2001 From: The Bundler Bot Date: Mon, 6 Aug 2018 17:42:47 +0000 Subject: [PATCH 456/707] Auto merge of #2363 - rubygems:fix_gem_version_should_handle_nil, r=bronzdoc Gem::Version should handle nil like it used to before closes https://github.com/rubygems/rubygems/issues/2359 reverts https://github.com/rubygems/rubygems/pull/2203 I will abide by the [code of conduct](https://github.com/rubygems/rubygems/blob/master/CODE_OF_CONDUCT.md). --- test/rubygems/test_gem_version.rb | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/rubygems/test_gem_version.rb b/test/rubygems/test_gem_version.rb index 792ad5f0..873258ad 100644 --- a/test/rubygems/test_gem_version.rb +++ b/test/rubygems/test_gem_version.rb @@ -46,6 +46,11 @@ def test_class_create def test_class_correct assert_equal true, Gem::Version.correct?("5.1") assert_equal false, Gem::Version.correct?("an incorrect version") + + expected = "nil versions are discouraged and will be deprecated in Rubygems 4\n" + assert_output nil, expected do + Gem::Version.correct?(nil) + end end def test_class_new_subclass From 5e7ec5706ca8d63b54ddb8194c43cbb1202146ac Mon Sep 17 00:00:00 2001 From: The Bundler Bot Date: Mon, 9 Jul 2018 14:14:03 +0000 Subject: [PATCH 457/707] Auto merge of #2345 - deivid-rodriguez:fix_approximate_recommendation_with_prereleases, r=hsbt Fix approximate recommendation with prereleases # Description: Fixes #1172. Not sure if this is fully correct but it at least seems to fix original @indirect's report. Basically, when we want to find the approximate recomendation for a prerelease, we need to make sure the requirement allows prereleases so that it also satisfies the original prerelease. ______________ # Tasks: - [x] Describe the problem / feature - [x] Write tests - [x] Write code to solve the problem - [ ] Get code review from coworkers / friends I will abide by the [code of conduct](https://github.com/rubygems/rubygems/blob/master/CODE_OF_CONDUCT.md). --- test/rubygems/test_gem_version.rb | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/test/rubygems/test_gem_version.rb b/test/rubygems/test_gem_version.rb index 873258ad..a2572fb6 100644 --- a/test/rubygems/test_gem_version.rb +++ b/test/rubygems/test_gem_version.rb @@ -162,11 +162,25 @@ def test_spaceship def test_approximate_recommendation assert_approximate_equal "~> 1.0", "1" + assert_approximate_satisfies_itself "1" + assert_approximate_equal "~> 1.0", "1.0" + assert_approximate_satisfies_itself "1.0" + assert_approximate_equal "~> 1.2", "1.2" + assert_approximate_satisfies_itself "1.2" + assert_approximate_equal "~> 1.2", "1.2.0" + assert_approximate_satisfies_itself "1.2.0" + assert_approximate_equal "~> 1.2", "1.2.3" - assert_approximate_equal "~> 1.2", "1.2.3.a.4" + assert_approximate_satisfies_itself "1.2.3" + + assert_approximate_equal "~> 1.2.a", "1.2.3.a.4" + assert_approximate_satisfies_itself "1.2.3.a.4" + + assert_approximate_equal "~> 1.9.a", "1.9.0.dev" + assert_approximate_satisfies_itself "1.9.0.dev" end def test_to_s @@ -202,12 +216,20 @@ def assert_prerelease version assert v(version).prerelease?, "#{version} is a prerelease" end - # Assert that +expected+ is the "approximate" recommendation for +version". + # Assert that +expected+ is the "approximate" recommendation for +version+. def assert_approximate_equal expected, version assert_equal expected, v(version).approximate_recommendation end + # Assert that the "approximate" recommendation for +version+ satifies +version+. + + def assert_approximate_satisfies_itself version + gem_version = v(version) + + assert Gem::Requirement.new(gem_version.approximate_recommendation).satisfied_by?(gem_version) + end + # Assert that bumping the +unbumped+ version yields the +expected+. def assert_bumped_version_equal expected, unbumped From a05c30844bfb84c41468270e2deb333b4155e1a9 Mon Sep 17 00:00:00 2001 From: Arlandis Word Date: Mon, 8 Oct 2018 18:33:25 -0400 Subject: [PATCH 458/707] Fix link to CONTRIBUTING.md doc --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b909f4d3..158abc09 100644 --- a/README.md +++ b/README.md @@ -84,7 +84,7 @@ See http://bundler.io/compatibility for known issues. ### Contributing -If you'd like to contribute to RubyGems, that's awesome, and we <3 you. Check out our [guide to contributing](https://github.com/rubygems/rubygems/blob/master/CONTRIBUTING.rdoc#how-to-contribute) for more information. +If you'd like to contribute to RubyGems, that's awesome, and we <3 you. Check out our [guide to contributing](CONTRIBUTING.md) for more information. While some RubyGems contributors are compensated by Ruby Together, the project maintainers make decisions independent of Ruby Together. As a project, we welcome contributions regardless of the author’s affiliation with Ruby Together. From 7f3703663e64cb36b24d44dd89aad7e53f3483fc Mon Sep 17 00:00:00 2001 From: Ellen Marie Dash Date: Fri, 12 Oct 2018 16:44:14 -0400 Subject: [PATCH 459/707] [rubocop] Enable Layout/ElseAlignment. --- test/rubygems/test_gem.rb | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index a980fdfb..ae271d8c 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1757,19 +1757,20 @@ def test_use_gemdeps_missing_gem else platform = " #{platform}" end - expected = if Gem::USE_BUNDLER_FOR_GEMDEPS - <<-EXPECTED + expected = + if Gem::USE_BUNDLER_FOR_GEMDEPS + <<-EXPECTED Could not find gem 'a#{platform}' in any of the gem sources listed in your Gemfile. You may need to `gem install -g` to install missing gems - EXPECTED - else - <<-EXPECTED + EXPECTED + else + <<-EXPECTED Unable to resolve dependency: user requested 'a (>= 0)' You may need to `gem install -g` to install missing gems - EXPECTED - end + EXPECTED + end assert_output nil, expected do Gem.use_gemdeps From 5da723278c374af05a786ce03512a515586df0f2 Mon Sep 17 00:00:00 2001 From: Colby Swandale Date: Mon, 5 Nov 2018 09:43:08 +1100 Subject: [PATCH 460/707] fix breaking specs --- bundler/spec/realworld/edgecases_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index aa60e20b..bbfd0f68 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -57,7 +57,7 @@ def rubygems_version(name, requirement) expect(lockfile).to include("activemodel (3.0.5)") end - it "resolves dependencies correctly", :ruby => "1.9.3" do + it "resolves dependencies correctly", :ruby => "<= 1.9.3" do gemfile <<-G source "https://rubygems.org" @@ -70,7 +70,7 @@ def rubygems_version(name, requirement) expect(lockfile).to include("capybara (2.2.1)") end - it "installs the latest version of gxapi_rails", :ruby => "1.9.3" do + it "installs the latest version of gxapi_rails", :ruby => "<= 1.9.3" do gemfile <<-G source "https://rubygems.org" From 3ba1bfb19940dd459364e382f78eb2f56269eb4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Fri, 5 Oct 2018 17:07:12 -0300 Subject: [PATCH 461/707] Fix bundler rubygems binstub not properly finding bundler --- test/rubygems/test_gem.rb | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index ae271d8c..c6965b68 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -278,6 +278,41 @@ def test_activate_bin_path_resolves_eagerly assert_equal %w(a-1 b-2 c-1), loaded_spec_names end + def test_activate_bin_path_gives_proper_error_for_bundler + bundler = util_spec 'bundler', '2' do |s| + s.executables = ['bundle'] + end + + install_specs bundler + + File.open("Gemfile.lock", "w") do |f| + f.write <<-L.gsub(/ {8}/, "") + GEM + remote: https://rubygems.org/ + specs: + + PLATFORMS + ruby + + DEPENDENCIES + + BUNDLED WITH + 9999 + L + end + + File.open("Gemfile", "w") { |f| f.puts('source "https://rubygems.org"') } + + e = assert_raises Gem::GemNotFoundException do + load Gem.activate_bin_path("bundler", "bundle", ">= 0.a") + end + + assert_includes e.message, "Could not find 'bundler' (9999) required by your #{File.expand_path("Gemfile.lock")}." + assert_includes e.message, "To update to the lastest version installed on your system, run `bundle update --bundler`." + assert_includes e.message, "To install the missing version, run `gem install bundler:9999`" + refute_includes e.message, "can't find gem bundler (>= 0.a) with executable bundle" + end + def test_self_bin_path_no_exec_name e = assert_raises ArgumentError do Gem.bin_path 'a' From a8ac59e9ce689885134c58a6e85c4aefd08eedd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Sun, 21 Oct 2018 15:29:43 -0300 Subject: [PATCH 462/707] s/lastest/latest --- test/rubygems/test_gem.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index c6965b68..e2b573dd 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -308,7 +308,7 @@ def test_activate_bin_path_gives_proper_error_for_bundler end assert_includes e.message, "Could not find 'bundler' (9999) required by your #{File.expand_path("Gemfile.lock")}." - assert_includes e.message, "To update to the lastest version installed on your system, run `bundle update --bundler`." + assert_includes e.message, "To update to the latest version installed on your system, run `bundle update --bundler`." assert_includes e.message, "To install the missing version, run `gem install bundler:9999`" refute_includes e.message, "can't find gem bundler (>= 0.a) with executable bundle" end From 63feaab52dd5d3917d13d472e0ddd96a67984a2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Wed, 4 Jul 2018 20:42:40 -0300 Subject: [PATCH 463/707] Improve ruby_version test descriptions --- test/rubygems/test_gem.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index e2b573dd..3c92e0a1 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -993,7 +993,7 @@ def test_self_env_requirement assert_equal Gem::Requirement.default, Gem.env_requirement('qux') end - def test_self_ruby_version_1_8_5 + def test_self_ruby_version_with_patchlevel_less_ancient_rubies util_set_RUBY_VERSION '1.8.5' assert_equal Gem::Version.new('1.8.5'), Gem.ruby_version @@ -1001,7 +1001,7 @@ def test_self_ruby_version_1_8_5 util_restore_RUBY_VERSION end - def test_self_ruby_version_1_8_6p287 + def test_self_ruby_version_with_release util_set_RUBY_VERSION '1.8.6', 287 assert_equal Gem::Version.new('1.8.6.287'), Gem.ruby_version @@ -1009,7 +1009,7 @@ def test_self_ruby_version_1_8_6p287 util_restore_RUBY_VERSION end - def test_self_ruby_version_1_9_2dev_r23493 + def test_self_ruby_version_with_trunk util_set_RUBY_VERSION '1.9.2', -1, 23493 assert_equal Gem::Version.new('1.9.2.dev.23493'), Gem.ruby_version From 1e60d270c22f1bdcf6c682e2fec48f22e2eeeb51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Wed, 4 Jul 2018 16:56:25 -0300 Subject: [PATCH 464/707] Fix required_ruby_version check with prereleases --- test/rubygems/test_gem.rb | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 3c92e0a1..304b1515 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1009,8 +1009,16 @@ def test_self_ruby_version_with_release util_restore_RUBY_VERSION end + def test_self_ruby_version_with_prerelease + util_set_RUBY_VERSION '2.6.0', -1, 63539, 'ruby 2.6.0preview2 (2018-05-31 trunk 63539) [x86_64-linux]' + + assert_equal Gem::Version.new('2.6.0.preview2.63539'), Gem.ruby_version + ensure + util_restore_RUBY_VERSION + end + def test_self_ruby_version_with_trunk - util_set_RUBY_VERSION '1.9.2', -1, 23493 + util_set_RUBY_VERSION '1.9.2', -1, 23493, 'ruby 1.9.2dev (2009-05-20 trunk 23493) [x86_64-linux]' assert_equal Gem::Version.new('1.9.2.dev.23493'), Gem.ruby_version ensure From d3e661aea033571fc8b0d32e99d9eb8e2b7c83e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Wed, 4 Jul 2018 21:09:41 -0300 Subject: [PATCH 465/707] Drop specific revisions from required_ruby_version We can't really make comparison work with them, they are not documented, and they mess up prerelease comparison (since previously `2.6.0.preview2 < 2.6.0.preview2.63539` when they are really the same thing). --- test/rubygems/test_gem.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 304b1515..6d4075ef 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1012,7 +1012,7 @@ def test_self_ruby_version_with_release def test_self_ruby_version_with_prerelease util_set_RUBY_VERSION '2.6.0', -1, 63539, 'ruby 2.6.0preview2 (2018-05-31 trunk 63539) [x86_64-linux]' - assert_equal Gem::Version.new('2.6.0.preview2.63539'), Gem.ruby_version + assert_equal Gem::Version.new('2.6.0.preview2'), Gem.ruby_version ensure util_restore_RUBY_VERSION end @@ -1020,7 +1020,7 @@ def test_self_ruby_version_with_prerelease def test_self_ruby_version_with_trunk util_set_RUBY_VERSION '1.9.2', -1, 23493, 'ruby 1.9.2dev (2009-05-20 trunk 23493) [x86_64-linux]' - assert_equal Gem::Version.new('1.9.2.dev.23493'), Gem.ruby_version + assert_equal Gem::Version.new('1.9.2.dev'), Gem.ruby_version ensure util_restore_RUBY_VERSION end From 42506723ebf3b332f30979002663e814085a8fe0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Wed, 4 Jul 2018 22:59:58 -0300 Subject: [PATCH 466/707] Add a test for jruby behavior --- test/rubygems/test_gem.rb | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 6d4075ef..014b9215 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1009,6 +1009,14 @@ def test_self_ruby_version_with_release util_restore_RUBY_VERSION end + def test_self_ruby_version_with_non_mri_implementations + util_set_RUBY_VERSION '2.5.0', 0, 60928, 'jruby 9.2.0.0 (2.5.0) 2018-05-24 81156a8 OpenJDK 64-Bit Server VM 25.171-b11 on 1.8.0_171-8u171-b11-0ubuntu0.16.04.1-b11 [linux-x86_64]' + + assert_equal Gem::Version.new('2.5.0'), Gem.ruby_version + ensure + util_restore_RUBY_VERSION + end + def test_self_ruby_version_with_prerelease util_set_RUBY_VERSION '2.6.0', -1, 63539, 'ruby 2.6.0preview2 (2018-05-31 trunk 63539) [x86_64-linux]' From 9420788e2ca52062fc861e8e0511b30c07ba0a7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Thu, 5 Jul 2018 11:19:29 -0300 Subject: [PATCH 467/707] Handle non-mri engines version descriptions --- test/rubygems/test_gem.rb | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 014b9215..c44a1cd6 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1025,6 +1025,14 @@ def test_self_ruby_version_with_prerelease util_restore_RUBY_VERSION end + def test_self_ruby_version_with_non_mri_implementations_with_mri_prerelase_compatibility + util_set_RUBY_VERSION '2.6.0', -1, 63539, 'weirdjruby 9.2.0.0 (2.6.0preview2) 2018-05-24 81156a8 OpenJDK 64-Bit Server VM 25.171-b11 on 1.8.0_171-8u171-b11-0ubuntu0.16.04.1-b11 [linux-x86_64]', 'weirdjruby', '9.2.0.0' + + assert_equal Gem::Version.new('2.6.0.preview2'), Gem.ruby_version + ensure + util_restore_RUBY_VERSION + end + def test_self_ruby_version_with_trunk util_set_RUBY_VERSION '1.9.2', -1, 23493, 'ruby 1.9.2dev (2009-05-20 trunk 23493) [x86_64-linux]' From 5949e80cbee132be946d7aecc390db0220f0632f Mon Sep 17 00:00:00 2001 From: Colby Swandale Date: Mon, 19 Nov 2018 19:54:10 +1100 Subject: [PATCH 468/707] enable Style/MethodDefParentheses in Rubocop --- test/rubygems/test_gem.rb | 2 +- test/rubygems/test_gem_version.rb | 22 +++++++++++----------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index c44a1cd6..7aabca49 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1872,7 +1872,7 @@ def test_platform_defaults assert platform_defaults.is_a? Hash end - def ruby_install_name name + def ruby_install_name(name) orig_RUBY_INSTALL_NAME = RbConfig::CONFIG['ruby_install_name'] RbConfig::CONFIG['ruby_install_name'] = name diff --git a/test/rubygems/test_gem_version.rb b/test/rubygems/test_gem_version.rb index a2572fb6..939360c7 100644 --- a/test/rubygems/test_gem_version.rb +++ b/test/rubygems/test_gem_version.rb @@ -212,19 +212,19 @@ def test_canonical_segments # Asserts that +version+ is a prerelease. - def assert_prerelease version + def assert_prerelease(version) assert v(version).prerelease?, "#{version} is a prerelease" end # Assert that +expected+ is the "approximate" recommendation for +version+. - def assert_approximate_equal expected, version + def assert_approximate_equal(expected, version) assert_equal expected, v(version).approximate_recommendation end # Assert that the "approximate" recommendation for +version+ satifies +version+. - def assert_approximate_satisfies_itself version + def assert_approximate_satisfies_itself(version) gem_version = v(version) assert Gem::Requirement.new(gem_version.approximate_recommendation).satisfied_by?(gem_version) @@ -232,33 +232,33 @@ def assert_approximate_satisfies_itself version # Assert that bumping the +unbumped+ version yields the +expected+. - def assert_bumped_version_equal expected, unbumped + def assert_bumped_version_equal(expected, unbumped) assert_version_equal expected, v(unbumped).bump end # Assert that +release+ is the correct non-prerelease +version+. - def assert_release_equal release, version + def assert_release_equal(release, version) assert_version_equal release, v(version).release end # Assert that two versions are equal. Handles strings or # Gem::Version instances. - def assert_version_equal expected, actual + def assert_version_equal(expected, actual) assert_equal v(expected), v(actual) assert_equal v(expected).hash, v(actual).hash, "since #{actual} == #{expected}, they must have the same hash" end # Assert that two versions are eql?. Checks both directions. - def assert_version_eql first, second + def assert_version_eql(first, second) first, second = v(first), v(second) assert first.eql?(second), "#{first} is eql? #{second}" assert second.eql?(first), "#{second} is eql? #{first}" end - def assert_less_than left, right + def assert_less_than(left, right) l = v(left) r = v(right) assert l < r, "#{left} not less than #{right}" @@ -266,14 +266,14 @@ def assert_less_than left, right # Refute the assumption that +version+ is a prerelease. - def refute_prerelease version + def refute_prerelease(version) refute v(version).prerelease?, "#{version} is NOT a prerelease" end # Refute the assumption that two versions are eql?. Checks both # directions. - def refute_version_eql first, second + def refute_version_eql(first, second) first, second = v(first), v(second) refute first.eql?(second), "#{first} is NOT eql? #{second}" refute second.eql?(first), "#{second} is NOT eql? #{first}" @@ -281,7 +281,7 @@ def refute_version_eql first, second # Refute the assumption that the two versions are equal?. - def refute_version_equal unexpected, actual + def refute_version_equal(unexpected, actual) refute_equal v(unexpected), v(actual) end end From b0d6fdc0ba820c7342357685c6e1b389c84f2cde Mon Sep 17 00:00:00 2001 From: Colby Swandale Date: Mon, 19 Nov 2018 19:54:10 +1100 Subject: [PATCH 469/707] enable Style/MethodDefParentheses in Rubocop --- test/rubygems/test_gem_requirement.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/rubygems/test_gem_requirement.rb b/test/rubygems/test_gem_requirement.rb index 7bca00e5..1564ffb0 100644 --- a/test/rubygems/test_gem_requirement.rb +++ b/test/rubygems/test_gem_requirement.rb @@ -387,26 +387,26 @@ def test_hash_with_multiple_versions # Assert that two requirements are equal. Handles Gem::Requirements, # strings, arrays, numbers, and versions. - def assert_requirement_equal expected, actual + def assert_requirement_equal(expected, actual) assert_equal req(expected), req(actual) end # Assert that +version+ satisfies +requirement+. - def assert_satisfied_by version, requirement + def assert_satisfied_by(version, requirement) assert req(requirement).satisfied_by?(v(version)), "#{requirement} is satisfied by #{version}" end # Refute the assumption that two requirements are equal. - def refute_requirement_equal unexpected, actual + def refute_requirement_equal(unexpected, actual) refute_equal req(unexpected), req(actual) end # Refute the assumption that +version+ satisfies +requirement+. - def refute_satisfied_by version, requirement + def refute_satisfied_by(version, requirement) refute req(requirement).satisfied_by?(v(version)), "#{requirement} is not satisfied by #{version}" end From a07a6cd451525b6108c7c6e4050fa0121aab1c0b Mon Sep 17 00:00:00 2001 From: bronzdoc Date: Mon, 19 Nov 2018 11:55:22 -0600 Subject: [PATCH 470/707] Enable Style/MultilineIfThen in Rubocop --- test/rubygems/test_gem.rb | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 7aabca49..682fa846 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -566,7 +566,7 @@ def test_self_ensure_gem_directories_missing_parents assert File.directory?(util_cache_dir) end - unless win_platform? || Process.uid.zero? then # only for FS that support write protection + unless win_platform? || Process.uid.zero? # only for FS that support write protection def test_self_ensure_gem_directories_write_protected gemdir = File.join @tempdir, "egd" FileUtils.rm_r gemdir rescue nil @@ -1284,7 +1284,7 @@ def test_self_user_dir end def test_self_user_home - if ENV['HOME'] then + if ENV['HOME'] assert_equal ENV['HOME'], Gem.user_home else assert true, 'count this test' @@ -1669,7 +1669,7 @@ def test_register_default_spec def test_default_gems_use_full_paths begin - if defined?(RUBY_ENGINE) then + if defined?(RUBY_ENGINE) engine = RUBY_ENGINE Object.send :remove_const, :RUBY_ENGINE end @@ -1682,7 +1682,7 @@ def test_default_gems_use_full_paths end begin - if defined?(RUBY_ENGINE) then + if defined?(RUBY_ENGINE) engine = RUBY_ENGINE Object.send :remove_const, :RUBY_ENGINE end @@ -1878,7 +1878,7 @@ def ruby_install_name(name) yield ensure - if orig_RUBY_INSTALL_NAME then + if orig_RUBY_INSTALL_NAME RbConfig::CONFIG['ruby_install_name'] = orig_RUBY_INSTALL_NAME else RbConfig::CONFIG.delete 'ruby_install_name' From 89dc0b9c32665421281c8f0a742abd985d599928 Mon Sep 17 00:00:00 2001 From: Colby Swandale Date: Wed, 5 Dec 2018 06:44:01 +1100 Subject: [PATCH 471/707] fix breaking edge case spec --- bundler/spec/realworld/edgecases_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index bbfd0f68..1db5c0f9 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -188,7 +188,7 @@ def rubygems_version(name, requirement) activemodel (= 4.2.7.1) activerecord (= 4.2.7.1) activesupport (= 4.2.7.1) - bundler (>= 1.3.0, < 2.0) + bundler (>= 1.3.0, < 3.0) railties (= 4.2.7.1) sprockets-rails rails-deprecated_sanitizer (1.0.3) From 9eb186252bb99ab49192042ea620451564041cad Mon Sep 17 00:00:00 2001 From: Jeremy Evans Date: Sat, 15 Dec 2018 21:12:23 -0800 Subject: [PATCH 472/707] Fix tests when --program-suffix and similar ruby configure options are used Without this, the tests check for bin/foo.cmd instead of bin/foo.cmd${suffix} and fail with Errno::ENOENT. --- test/rubygems/test_gem.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 682fa846..e062eebb 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -5,6 +5,7 @@ require 'rubygems/installer' require 'pathname' require 'tmpdir' +require 'rbconfig' # TODO: push this up to test_case.rb once battle tested @@ -13,6 +14,7 @@ end class TestGem < Gem::TestCase + RUBY_INSTALL_NAME = RbConfig::CONFIG['RUBY_INSTALL_NAME'] PLUGINS_LOADED = [] # rubocop:disable Style/MutableConstant @@ -181,7 +183,7 @@ def assert_self_install_permissions dir_mode = (options[:dir_mode] & mask).to_s(8) data_mode = (options[:data_mode] & mask).to_s(8) expected = { - 'bin/foo.cmd' => prog_mode, + "bin/#{RUBY_INSTALL_NAME.sub('ruby', 'foo.cmd')}" => prog_mode, 'gems/foo-1' => dir_mode, 'gems/foo-1/bin' => dir_mode, 'gems/foo-1/data' => dir_mode, From 2d508c81af9b8726417329cbea241d5cea44a5a1 Mon Sep 17 00:00:00 2001 From: SHIBATA Hiroshi Date: Sat, 22 Dec 2018 11:34:29 +0900 Subject: [PATCH 473/707] Added permissions to installed files for non-owners. Fixes #2535 Fixes #2541 Fixes #2543 --- test/rubygems/test_gem.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index e062eebb..acf7fa04 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -151,7 +151,7 @@ def test_self_install_permissions_umask_077 end def assert_self_install_permissions - mask = /mingw|mswin/ =~ RUBY_PLATFORM ? 0700 : 0777 + mask = /mingw|mswin/ =~ RUBY_PLATFORM ? 0755 : 0777 options = { :dir_mode => 0500, :prog_mode => 0510, @@ -198,7 +198,7 @@ def assert_self_install_permissions end assert_equal(expected, result) ensure - File.chmod(0700, *Dir.glob(@gemhome+'/gems/**/').map {|path| path.untaint}) + File.chmod(0755, *Dir.glob(@gemhome+'/gems/**/').map {|path| path.untaint}) end def test_require_missing From e8635e7cb1276c5b6cc7d2a6e16fd81c0be39962 Mon Sep 17 00:00:00 2001 From: SHIBATA Hiroshi Date: Sat, 22 Dec 2018 12:56:53 +0900 Subject: [PATCH 474/707] Fixed mswin platforms. --- test/rubygems/test_gem.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index acf7fa04..b6578747 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -151,7 +151,7 @@ def test_self_install_permissions_umask_077 end def assert_self_install_permissions - mask = /mingw|mswin/ =~ RUBY_PLATFORM ? 0755 : 0777 + mask = /mingw|mswin/ =~ RUBY_PLATFORM ? 0700 : 0777 options = { :dir_mode => 0500, :prog_mode => 0510, From 90c53e1b621780a749200f7c89d5e8938aa45e9a Mon Sep 17 00:00:00 2001 From: Bundlerbot Date: Sat, 22 Dec 2018 11:20:27 +0000 Subject: [PATCH 475/707] Merge #2546 2546: Added permissions to installed files for non-owners r=hsbt a=hsbt # Description: https://github.com/rubygems/rubygems/pull/2219 introduced to deny to access files installed rubygems installer. I'm not sure why @nobu choose `700` permission instead of `755`. I will merge this after discussion with @nobu. Fixes #2535 Fixes #2541 Fixes #2543 ______________ # Tasks: - [ ] Describe the problem / feature - [ ] Write tests - [ ] Write code to solve the problem - [ ] Get code review from coworkers / friends I will abide by the [code of conduct](https://github.com/rubygems/rubygems/blob/master/CODE_OF_CONDUCT.md). Co-authored-by: SHIBATA Hiroshi (cherry picked from commit 8984913510e7d857a209a9c4ff597a6f965931f7) --- test/rubygems/test_gem.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index e062eebb..b6578747 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -198,7 +198,7 @@ def assert_self_install_permissions end assert_equal(expected, result) ensure - File.chmod(0700, *Dir.glob(@gemhome+'/gems/**/').map {|path| path.untaint}) + File.chmod(0755, *Dir.glob(@gemhome+'/gems/**/').map {|path| path.untaint}) end def test_require_missing From fa3e2c17e299d127302987eae3f165a7e1933f91 Mon Sep 17 00:00:00 2001 From: Jeremy Evans Date: Wed, 26 Dec 2018 13:06:19 -0800 Subject: [PATCH 476/707] Fix tests when ruby --program-suffix is used without rubygems --format-executable Add a test to check for correct behavior when --format-executable option is used. --- test/rubygems/test_gem.rb | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index b6578747..e740a5ab 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -150,6 +150,11 @@ def test_self_install_permissions_umask_077 File.umask(umask) end + def test_self_install_permissions_with_format_executable + @format_executable = true + assert_self_install_permissions + end + def assert_self_install_permissions mask = /mingw|mswin/ =~ RUBY_PLATFORM ? 0700 : 0777 options = { @@ -157,6 +162,7 @@ def assert_self_install_permissions :prog_mode => 0510, :data_mode => 0640, :wrappers => true, + :format_executable => !!(@format_executable if defined?(@format_executable)) } Dir.chdir @tempdir do Dir.mkdir 'bin' @@ -182,8 +188,10 @@ def assert_self_install_permissions prog_mode = (options[:prog_mode] & mask).to_s(8) dir_mode = (options[:dir_mode] & mask).to_s(8) data_mode = (options[:data_mode] & mask).to_s(8) + prog_name = 'foo.cmd' + prog_name = RUBY_INSTALL_NAME.sub('ruby', 'foo.cmd') if options[:format_executable] expected = { - "bin/#{RUBY_INSTALL_NAME.sub('ruby', 'foo.cmd')}" => prog_mode, + "bin/#{prog_name}" => prog_mode, 'gems/foo-1' => dir_mode, 'gems/foo-1/bin' => dir_mode, 'gems/foo-1/data' => dir_mode, From 8bfd78b26784a11481de0f1d91b2004214ecf438 Mon Sep 17 00:00:00 2001 From: Grey Baker Date: Fri, 28 Dec 2018 12:46:35 +0000 Subject: [PATCH 477/707] Fix Gem::Requirement equality comparison when ~> operator is used --- test/rubygems/test_gem_requirement.rb | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/rubygems/test_gem_requirement.rb b/test/rubygems/test_gem_requirement.rb index 1564ffb0..7a59243b 100644 --- a/test/rubygems/test_gem_requirement.rb +++ b/test/rubygems/test_gem_requirement.rb @@ -20,6 +20,12 @@ def test_equals2 refute_requirement_equal "= 1.2", "= 1.3" refute_requirement_equal "= 1.3", "= 1.2" + refute_requirement_equal "~> 1.3", "~> 1.3.0" + refute_requirement_equal "~> 1.3.0", "~> 1.3" + + assert_requirement_equal ["> 2", "~> 1.3"], ["> 2.0", "~> 1.3"] + assert_requirement_equal ["> 2.0", "~> 1.3"], ["> 2", "~> 1.3"] + refute_equal Object.new, req("= 1.2") refute_equal req("= 1.2"), Object.new end From fe4d7bc90be390698c1857ff9c1f49d2e92c06ed Mon Sep 17 00:00:00 2001 From: Bundlerbot Date: Mon, 31 Dec 2018 22:32:40 +0000 Subject: [PATCH 478/707] Merge #2554 2554: Fix Gem::Requirement equality comparison when ~> operator is used r=hsbt a=greysteil # Description: The logic to compare versions included in a requirement needs to consider precision when a `~>` operator is used, and ignore it when one isn't. Before this patch we had the following bug: ```ruby Gem::Requirement.new("~> 5.2.0") == Gem::Requirement.new("~> 5.2") # => true ``` Fixes https://github.com/bundler/bundler/issues/6858. # Tasks: - [x] Describe the problem / feature - [x] Write tests - [x] Write code to solve the problem - [ ] Get code review from coworkers / friends I will abide by the [code of conduct](https://github.com/rubygems/rubygems/blob/master/CODE_OF_CONDUCT.md). Co-authored-by: Grey Baker (cherry picked from commit bfffb421836160eda736551ac6ae3c4441485533) --- test/rubygems/test_gem_requirement.rb | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/rubygems/test_gem_requirement.rb b/test/rubygems/test_gem_requirement.rb index 1564ffb0..7a59243b 100644 --- a/test/rubygems/test_gem_requirement.rb +++ b/test/rubygems/test_gem_requirement.rb @@ -20,6 +20,12 @@ def test_equals2 refute_requirement_equal "= 1.2", "= 1.3" refute_requirement_equal "= 1.3", "= 1.2" + refute_requirement_equal "~> 1.3", "~> 1.3.0" + refute_requirement_equal "~> 1.3.0", "~> 1.3" + + assert_requirement_equal ["> 2", "~> 1.3"], ["> 2.0", "~> 1.3"] + assert_requirement_equal ["> 2.0", "~> 1.3"], ["> 2", "~> 1.3"] + refute_equal Object.new, req("= 1.2") refute_equal req("= 1.2"), Object.new end From 0ae6d737b327bb69dabcedb693aaf7358424aedb Mon Sep 17 00:00:00 2001 From: Bundlerbot Date: Tue, 1 Jan 2019 01:18:33 +0000 Subject: [PATCH 479/707] Merge #2549 2549: Fix tests when ruby --program-suffix is used without rubygems --format-executable r=hsbt a=jeremyevans Add a test to check for correct behavior when --format-executable option is used. Co-authored-by: Jeremy Evans (cherry picked from commit 7fd4ef4d84f33564eedd288789db5978d059a08d) --- test/rubygems/test_gem.rb | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index b6578747..e740a5ab 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -150,6 +150,11 @@ def test_self_install_permissions_umask_077 File.umask(umask) end + def test_self_install_permissions_with_format_executable + @format_executable = true + assert_self_install_permissions + end + def assert_self_install_permissions mask = /mingw|mswin/ =~ RUBY_PLATFORM ? 0700 : 0777 options = { @@ -157,6 +162,7 @@ def assert_self_install_permissions :prog_mode => 0510, :data_mode => 0640, :wrappers => true, + :format_executable => !!(@format_executable if defined?(@format_executable)) } Dir.chdir @tempdir do Dir.mkdir 'bin' @@ -182,8 +188,10 @@ def assert_self_install_permissions prog_mode = (options[:prog_mode] & mask).to_s(8) dir_mode = (options[:dir_mode] & mask).to_s(8) data_mode = (options[:data_mode] & mask).to_s(8) + prog_name = 'foo.cmd' + prog_name = RUBY_INSTALL_NAME.sub('ruby', 'foo.cmd') if options[:format_executable] expected = { - "bin/#{RUBY_INSTALL_NAME.sub('ruby', 'foo.cmd')}" => prog_mode, + "bin/#{prog_name}" => prog_mode, 'gems/foo-1' => dir_mode, 'gems/foo-1/bin' => dir_mode, 'gems/foo-1/data' => dir_mode, From bd805f31cb7124e4b7b12bf97780853296be1052 Mon Sep 17 00:00:00 2001 From: MSP-Greg Date: Wed, 2 Jan 2019 12:03:52 -0600 Subject: [PATCH 480/707] Fix intermittent test error on Appveyor & Travis --- test/rubygems/test_gem.rb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index e740a5ab..83fae0c6 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -156,7 +156,7 @@ def test_self_install_permissions_with_format_executable end def assert_self_install_permissions - mask = /mingw|mswin/ =~ RUBY_PLATFORM ? 0700 : 0777 + mask = win_platform? ? 0700 : 0777 options = { :dir_mode => 0500, :prog_mode => 0510, @@ -198,6 +198,9 @@ def assert_self_install_permissions 'gems/foo-1/bin/foo.cmd' => prog_mode, 'gems/foo-1/data/foo.txt' => data_mode, } + # below is for intermittent errors on Appveyor & Travis 2019-01, + # see https://github.com/rubygems/rubygems/pull/2568 + sleep 0.1 result = {} Dir.chdir @gemhome do expected.each_key do |n| From 9af5a89622e020b34c9173afdaf9eb03bdd804bd Mon Sep 17 00:00:00 2001 From: SHIBATA Hiroshi Date: Tue, 22 Jan 2019 11:56:55 +0900 Subject: [PATCH 481/707] Extend timeout because it's fragile test --- test/rubygems/test_gem.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 83fae0c6..c913f30e 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -200,7 +200,7 @@ def assert_self_install_permissions } # below is for intermittent errors on Appveyor & Travis 2019-01, # see https://github.com/rubygems/rubygems/pull/2568 - sleep 0.1 + sleep 0.2 result = {} Dir.chdir @gemhome do expected.each_key do |n| From d2514dde54351dc96589a5bcd9e4fcb5efe24136 Mon Sep 17 00:00:00 2001 From: Takumasa Ochi Date: Mon, 28 Jan 2019 16:18:02 +0900 Subject: [PATCH 482/707] Replace unsafe http URLs with https URLs --- bundler/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundler/README.md b/bundler/README.md index c596a320..b06d456d 100644 --- a/bundler/README.md +++ b/bundler/README.md @@ -29,7 +29,7 @@ bundle install bundle exec rspec ``` -See [bundler.io](http://bundler.io) for the full documentation. +See [bundler.io](https://bundler.io) for the full documentation. ### Troubleshooting From 19818a1b53c2608bc0f7190e813a3f0ada83d960 Mon Sep 17 00:00:00 2001 From: MSP-Greg Date: Wed, 30 Jan 2019 16:23:07 -0600 Subject: [PATCH 483/707] test_gem.rb - intermittent failure fix assert_self_install_permissions File.open -> File.write ? --- test/rubygems/test_gem.rb | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index c913f30e..80edfe3c 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -166,15 +166,12 @@ def assert_self_install_permissions } Dir.chdir @tempdir do Dir.mkdir 'bin' - File.open 'bin/foo.cmd', 'w' do |fp| - fp.chmod(0755) - fp.puts 'p' - end - Dir.mkdir 'data' - File.open 'data/foo.txt', 'w' do |fp| - fp.puts 'blah' - end + + File.write 'bin/foo.cmd', "p\n" + File.chmod 0755, 'bin/foo.cmd' + + File.write 'data/foo.txt', "blah\n" spec_fetcher do |f| f.gem 'foo', 1 do |s| From 3227bb221b2c93365a4952d5850a6e02ffbab5fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Wed, 6 Feb 2019 11:14:24 +0100 Subject: [PATCH 484/707] Remove no longer necessary sleep MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: David Rodríguez Co-authored-by: MSP-Greg --- test/rubygems/test_gem.rb | 3 --- 1 file changed, 3 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 80edfe3c..439fbafb 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -195,9 +195,6 @@ def assert_self_install_permissions 'gems/foo-1/bin/foo.cmd' => prog_mode, 'gems/foo-1/data/foo.txt' => data_mode, } - # below is for intermittent errors on Appveyor & Travis 2019-01, - # see https://github.com/rubygems/rubygems/pull/2568 - sleep 0.2 result = {} Dir.chdir @gemhome do expected.each_key do |n| From 24527ace7edd8ad8cf36f5b32d1c8d31342fbd5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Wed, 6 Feb 2019 11:15:48 +0100 Subject: [PATCH 485/707] Remove .cmd suffix from test executables MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The standard way to ship executables in the ruby world is to ship bash style scripts. In the case of Windows, those are not really executable, but rubygems generates an extra .bat file that it's executable for Windows. So, remove the .cmd suffix to test the general case, and add a windows only separate assertion for the bat file generated on Windows. Co-authored-by: David Rodríguez Co-authored-by: MSP-Greg --- test/rubygems/test_gem.rb | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 439fbafb..2bca7117 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -159,7 +159,7 @@ def assert_self_install_permissions mask = win_platform? ? 0700 : 0777 options = { :dir_mode => 0500, - :prog_mode => 0510, + :prog_mode => win_platform? ? 0410 : 0510, :data_mode => 0640, :wrappers => true, :format_executable => !!(@format_executable if defined?(@format_executable)) @@ -168,15 +168,15 @@ def assert_self_install_permissions Dir.mkdir 'bin' Dir.mkdir 'data' - File.write 'bin/foo.cmd', "p\n" - File.chmod 0755, 'bin/foo.cmd' + File.write 'bin/foo', "p\n" + File.chmod 0755, 'bin/foo' File.write 'data/foo.txt', "blah\n" spec_fetcher do |f| f.gem 'foo', 1 do |s| - s.executables = ['foo.cmd'] - s.files = %w[bin/foo.cmd data/foo.txt] + s.executables = ['foo'] + s.files = %w[bin/foo data/foo.txt] end end Gem.install 'foo', Gem::Requirement.default, options @@ -185,16 +185,18 @@ def assert_self_install_permissions prog_mode = (options[:prog_mode] & mask).to_s(8) dir_mode = (options[:dir_mode] & mask).to_s(8) data_mode = (options[:data_mode] & mask).to_s(8) - prog_name = 'foo.cmd' - prog_name = RUBY_INSTALL_NAME.sub('ruby', 'foo.cmd') if options[:format_executable] + prog_name = 'foo' + prog_name = RUBY_INSTALL_NAME.sub('ruby', 'foo') if options[:format_executable] expected = { "bin/#{prog_name}" => prog_mode, 'gems/foo-1' => dir_mode, 'gems/foo-1/bin' => dir_mode, 'gems/foo-1/data' => dir_mode, - 'gems/foo-1/bin/foo.cmd' => prog_mode, + 'gems/foo-1/bin/foo' => prog_mode, 'gems/foo-1/data/foo.txt' => data_mode, } + # add Windows script + expected["bin/#{prog_name}.bat"] = mask.to_s(8) if win_platform? result = {} Dir.chdir @gemhome do expected.each_key do |n| From de4a088aa9b43aaee35c5bd09bc8a7f5e9098589 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Wed, 6 Feb 2019 11:21:54 +0100 Subject: [PATCH 486/707] Use a shebang for the test executable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It's a more real world example, since the executable won't work without the shebang. Co-authored-by: David Rodríguez Co-authored-by: MSP-Greg --- test/rubygems/test_gem.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 2bca7117..3b3b99d9 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -168,7 +168,7 @@ def assert_self_install_permissions Dir.mkdir 'bin' Dir.mkdir 'data' - File.write 'bin/foo', "p\n" + File.write 'bin/foo', "#!/usr/bin/env ruby\n" File.chmod 0755, 'bin/foo' File.write 'data/foo.txt', "blah\n" From 34c41d929e83092c1896a191a442e0449029834f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Wed, 6 Feb 2019 11:24:56 +0100 Subject: [PATCH 487/707] Remove `@format_executable` instance variable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Passing it around is more explicit and easier to understand. Co-authored-by: David Rodríguez Co-authored-by: MSP-Greg --- test/rubygems/test_gem.rb | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 3b3b99d9..412d0b2b 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -151,18 +151,17 @@ def test_self_install_permissions_umask_077 end def test_self_install_permissions_with_format_executable - @format_executable = true - assert_self_install_permissions + assert_self_install_permissions(format_executable: true) end - def assert_self_install_permissions + def assert_self_install_permissions(format_executable: false) mask = win_platform? ? 0700 : 0777 options = { :dir_mode => 0500, :prog_mode => win_platform? ? 0410 : 0510, :data_mode => 0640, :wrappers => true, - :format_executable => !!(@format_executable if defined?(@format_executable)) + :format_executable => format_executable } Dir.chdir @tempdir do Dir.mkdir 'bin' From c7726d096fdb96b6c7087a2fd3a3c3fffdaa9887 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Wed, 6 Feb 2019 12:14:11 +0100 Subject: [PATCH 488/707] Fix case of RbConfig::CONFIG key MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The uppercase one also exists, apparently, but the one checked by rubygems for the format executable option is the lowercase one, so that's the one we need here since that's what the test using this constant is dealing with. Co-authored-by: David Rodríguez Co-authored-by: MSP-Greg --- test/rubygems/test_gem.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 412d0b2b..c9f40000 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -14,7 +14,7 @@ end class TestGem < Gem::TestCase - RUBY_INSTALL_NAME = RbConfig::CONFIG['RUBY_INSTALL_NAME'] + RUBY_INSTALL_NAME = RbConfig::CONFIG['ruby_install_name'] PLUGINS_LOADED = [] # rubocop:disable Style/MutableConstant From b8d49fd60345f3c2ed8cf5ce4f55a992f4bb542e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Wed, 6 Feb 2019 12:16:43 +0100 Subject: [PATCH 489/707] Remove the RUBY_INSTALL_NAME constant MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It's better to pick up the value at runtime, instead of at load time, because if the constant is modified during the test (for example by using the [`ruby_install_name`] utility method, we will pick up the old value and not the one we want. [`ruby_install_name`]: https://github.com/rubygems/rubygems/blob/15a29a7b23f38ae2a4b08f8a6dd7830889414e8b/test/rubygems/test_gem.rb#L1885-L1897 Co-authored-by: David Rodríguez Co-authored-by: MSP-Greg --- test/rubygems/test_gem.rb | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index c9f40000..e9b232d8 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -14,8 +14,6 @@ end class TestGem < Gem::TestCase - RUBY_INSTALL_NAME = RbConfig::CONFIG['ruby_install_name'] - PLUGINS_LOADED = [] # rubocop:disable Style/MutableConstant def setup @@ -185,7 +183,7 @@ def assert_self_install_permissions(format_executable: false) dir_mode = (options[:dir_mode] & mask).to_s(8) data_mode = (options[:data_mode] & mask).to_s(8) prog_name = 'foo' - prog_name = RUBY_INSTALL_NAME.sub('ruby', 'foo') if options[:format_executable] + prog_name = RbConfig::CONFIG['ruby_install_name'].sub('ruby', 'foo') if options[:format_executable] expected = { "bin/#{prog_name}" => prog_mode, 'gems/foo-1' => dir_mode, From 3143fbb4342b497d609a2b60ae38988451d65052 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Wed, 6 Feb 2019 14:41:59 +0100 Subject: [PATCH 490/707] Fix executable formatting on Windows MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When the RbConfig::CONFIG['ruby_install_name'] is non standard. Co-authored-by: David Rodríguez Co-authored-by: MSP-Greg --- test/rubygems/test_gem.rb | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index e9b232d8..786e710e 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -152,6 +152,15 @@ def test_self_install_permissions_with_format_executable assert_self_install_permissions(format_executable: true) end + def test_self_install_permissions_with_format_executable_and_non_standard_ruby_install_name + Gem::Installer.exec_format = nil + ruby_install_name 'ruby27' do + assert_self_install_permissions(format_executable: true) + end + ensure + Gem::Installer.exec_format = nil + end + def assert_self_install_permissions(format_executable: false) mask = win_platform? ? 0700 : 0777 options = { From 5de3211487130525f2845351097532cdd61af26c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Thu, 7 Feb 2019 10:04:24 +0100 Subject: [PATCH 491/707] Enable `Layout/SpaceInsideParens` rubocop cop --- test/rubygems/test_gem_version.rb | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/test/rubygems/test_gem_version.rb b/test/rubygems/test_gem_version.rb index 939360c7..48efe314 100644 --- a/test/rubygems/test_gem_version.rb +++ b/test/rubygems/test_gem_version.rb @@ -148,14 +148,14 @@ def test_release end def test_spaceship - assert_equal( 0, v("1.0") <=> v("1.0.0")) - assert_equal( 1, v("1.0") <=> v("1.0.a")) - assert_equal( 1, v("1.8.2") <=> v("0.0.0")) - assert_equal( 1, v("1.8.2") <=> v("1.8.2.a")) - assert_equal( 1, v("1.8.2.b") <=> v("1.8.2.a")) + assert_equal(0, v("1.0") <=> v("1.0.0")) + assert_equal(1, v("1.0") <=> v("1.0.a")) + assert_equal(1, v("1.8.2") <=> v("0.0.0")) + assert_equal(1, v("1.8.2") <=> v("1.8.2.a")) + assert_equal(1, v("1.8.2.b") <=> v("1.8.2.a")) assert_equal(-1, v("1.8.2.a") <=> v("1.8.2")) - assert_equal( 1, v("1.8.2.a10") <=> v("1.8.2.a9")) - assert_equal( 0, v("") <=> v("0")) + assert_equal(1, v("1.8.2.a10") <=> v("1.8.2.a9")) + assert_equal(0, v("") <=> v("0")) assert_nil v("1.0") <=> "whatever" end From 216e0e8bd6fb0bf0f5f9191480b1269763738d03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Fri, 8 Feb 2019 13:28:13 +0100 Subject: [PATCH 492/707] Enable Style/EmptyLinesAroundClassBody rubocop cop --- test/rubygems/test_gem.rb | 2 ++ test/rubygems/test_gem_version.rb | 1 + 2 files changed, 3 insertions(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 786e710e..0baf5e71 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -14,6 +14,7 @@ end class TestGem < Gem::TestCase + PLUGINS_LOADED = [] # rubocop:disable Style/MutableConstant def setup @@ -1945,4 +1946,5 @@ def util_remove_interrupt_command def util_cache_dir File.join Gem.dir, "cache" end + end diff --git a/test/rubygems/test_gem_version.rb b/test/rubygems/test_gem_version.rb index 48efe314..df3fb9ac 100644 --- a/test/rubygems/test_gem_version.rb +++ b/test/rubygems/test_gem_version.rb @@ -284,4 +284,5 @@ def refute_version_eql(first, second) def refute_version_equal(unexpected, actual) refute_equal v(unexpected), v(actual) end + end From f5c7268404a92918fab0e0dbd4b7f091653d1f10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Fri, 8 Feb 2019 13:28:13 +0100 Subject: [PATCH 493/707] Enable Style/EmptyLinesAroundClassBody rubocop cop --- test/rubygems/test_gem_requirement.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/test/rubygems/test_gem_requirement.rb b/test/rubygems/test_gem_requirement.rb index 7a59243b..96acb247 100644 --- a/test/rubygems/test_gem_requirement.rb +++ b/test/rubygems/test_gem_requirement.rb @@ -416,4 +416,5 @@ def refute_satisfied_by(version, requirement) refute req(requirement).satisfied_by?(v(version)), "#{requirement} is not satisfied by #{version}" end + end From 1a6a00f6e70605fe953e4359cff9e2635884f3a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Tue, 12 Feb 2019 10:20:54 +0100 Subject: [PATCH 494/707] Add Style/Block delimiters cop and auto-correct --- test/rubygems/test_gem.rb | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 0baf5e71..bcac73e8 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -634,7 +634,7 @@ def test_self_find_files discover_path = File.join 'lib', 'sff', 'discover.rb' - foo1, foo2 = %w(1 2).map { |version| + foo1, foo2 = %w(1 2).map do |version| spec = quick_gem 'sff', version do |s| s.files << discover_path end @@ -644,7 +644,7 @@ def test_self_find_files end spec - } + end Gem.refresh @@ -666,7 +666,7 @@ def test_self_find_files_with_gemfile discover_path = File.join 'lib', 'sff', 'discover.rb' - foo1, _ = %w(1 2).map { |version| + foo1, _ = %w(1 2).map do |version| spec = quick_gem 'sff', version do |s| s.files << discover_path end @@ -676,7 +676,7 @@ def test_self_find_files_with_gemfile end spec - } + end Gem.refresh write_file(File.join Dir.pwd, 'Gemfile') do |fp| @@ -702,7 +702,7 @@ def test_self_find_latest_files discover_path = File.join 'lib', 'sff', 'discover.rb' - _, foo2 = %w(1 2).map { |version| + _, foo2 = %w(1 2).map do |version| spec = quick_gem 'sff', version do |s| s.files << discover_path end @@ -712,7 +712,7 @@ def test_self_find_latest_files end spec - } + end Gem.refresh @@ -1090,7 +1090,7 @@ def test_self_paths_eq_nonexistent_home def test_self_post_build assert_equal 1, Gem.post_build_hooks.length - Gem.post_build do |installer| end + Gem.post_build { |installer| } assert_equal 2, Gem.post_build_hooks.length end @@ -1098,7 +1098,7 @@ def test_self_post_build def test_self_post_install assert_equal 1, Gem.post_install_hooks.length - Gem.post_install do |installer| end + Gem.post_install { |installer| } assert_equal 2, Gem.post_install_hooks.length end @@ -1106,7 +1106,7 @@ def test_self_post_install def test_self_done_installing assert_empty Gem.done_installing_hooks - Gem.done_installing do |gems| end + Gem.done_installing { |gems| } assert_equal 1, Gem.done_installing_hooks.length end @@ -1122,7 +1122,7 @@ def test_self_post_reset def test_self_post_uninstall assert_equal 1, Gem.post_uninstall_hooks.length - Gem.post_uninstall do |installer| end + Gem.post_uninstall { |installer| } assert_equal 2, Gem.post_uninstall_hooks.length end @@ -1130,7 +1130,7 @@ def test_self_post_uninstall def test_self_pre_install assert_equal 1, Gem.pre_install_hooks.length - Gem.pre_install do |installer| end + Gem.pre_install { |installer| } assert_equal 2, Gem.pre_install_hooks.length end @@ -1146,7 +1146,7 @@ def test_self_pre_reset def test_self_pre_uninstall assert_equal 1, Gem.pre_uninstall_hooks.length - Gem.pre_uninstall do |installer| end + Gem.pre_uninstall { |installer| } assert_equal 2, Gem.pre_uninstall_hooks.length end From 5d6882d66f39c837b18121ef53844dc9690e4106 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Tue, 12 Feb 2019 10:56:48 +0100 Subject: [PATCH 495/707] Fix the rest of Style/BlockDelimiter offenses --- test/rubygems/test_gem.rb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index bcac73e8..5fc0da58 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -416,7 +416,10 @@ def test_self_datadir fp.puts 'blah' end - foo = util_spec 'foo' do |s| s.files = %w[data/foo.txt] end + foo = util_spec 'foo' do |s| + s.files = %w[data/foo.txt] + end + install_gem foo end From 9cee8f8917df6221bda79a6e85a3da2df3023d31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Thu, 14 Feb 2019 00:41:16 +0100 Subject: [PATCH 496/707] Enable Layout/SpaceAroundOperators rubocop cop --- test/rubygems/test_gem.rb | 4 ++-- test/rubygems/test_gem_version.rb | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 5fc0da58..b2f718bf 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -212,7 +212,7 @@ def assert_self_install_permissions(format_executable: false) end assert_equal(expected, result) ensure - File.chmod(0755, *Dir.glob(@gemhome+'/gems/**/').map {|path| path.untaint}) + File.chmod(0755, *Dir.glob(@gemhome + '/gems/**/').map {|path| path.untaint}) end def test_require_missing @@ -1334,7 +1334,7 @@ def test_self_needs_picks_up_unresolved_deps a = util_spec "a", "1" b = util_spec "b", "1", "c" => nil c = util_spec "c", "2" - d = util_spec "d", "1", {'e' => '= 1'}, "lib/d.rb" + d = util_spec "d", "1", {'e' => '= 1'}, "lib/d.rb" e = util_spec "e", "1" install_specs a, c, b, e, d diff --git a/test/rubygems/test_gem_version.rb b/test/rubygems/test_gem_version.rb index df3fb9ac..6d3893c2 100644 --- a/test/rubygems/test_gem_version.rb +++ b/test/rubygems/test_gem_version.rb @@ -153,7 +153,7 @@ def test_spaceship assert_equal(1, v("1.8.2") <=> v("0.0.0")) assert_equal(1, v("1.8.2") <=> v("1.8.2.a")) assert_equal(1, v("1.8.2.b") <=> v("1.8.2.a")) - assert_equal(-1, v("1.8.2.a") <=> v("1.8.2")) + assert_equal(-1, v("1.8.2.a") <=> v("1.8.2")) assert_equal(1, v("1.8.2.a10") <=> v("1.8.2.a9")) assert_equal(0, v("") <=> v("0")) From c18c8c6ff19f494f2867a566279e4556a93250c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Thu, 7 Feb 2019 14:45:59 +0100 Subject: [PATCH 497/707] Split stderr and stdout in specs --- bundler/spec/realworld/edgecases_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index aa60e20b..7fb23139 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -376,7 +376,7 @@ def rubygems_version(name, requirement) source 'https://rubygems.org' gem "resque-scheduler", "2.2.0" G - expect(out).to include("You have one or more invalid gemspecs that need to be fixed.") - expect(out).to include("resque-scheduler 2.2.0 has an invalid gemspec") + expect(err).to include("You have one or more invalid gemspecs that need to be fixed.") + expect(err).to include("resque-scheduler 2.2.0 has an invalid gemspec") end end From 9eba3128249f2f5cd287f3e79c5e6b2bf04f20dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Mon, 11 Feb 2019 00:14:29 +0100 Subject: [PATCH 498/707] Remove now unnecessary `lack_errors` matcher Since the errors are checked on their own stream, no filtering is needed. --- bundler/spec/realworld/edgecases_spec.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index 7fb23139..ae749746 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -26,7 +26,7 @@ def rubygems_version(name, requirement) gem "linecache", "0.46" G bundle :lock - expect(err).to lack_errors + expect(err).to be_empty expect(exitstatus).to eq(0) if exitstatus end @@ -241,7 +241,7 @@ def rubygems_version(name, requirement) bundle! :install, forgotten_command_line_options(:path => "vendor/bundle") expect(err).not_to include("Could not find rake") - expect(err).to lack_errors + expect(err).to be_empty end it "checks out git repos when the lockfile is corrupted" do @@ -368,7 +368,7 @@ def rubygems_version(name, requirement) L bundle! :lock - expect(last_command.stderr).to lack_errors + expect(last_command.stderr).to be_empty end it "outputs a helpful error message when gems have invalid gemspecs" do From 563cc5ad88ded31361871764dc96e92b100394b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Mon, 11 Feb 2019 00:17:04 +0100 Subject: [PATCH 499/707] Fix 1.x specs --- bundler/spec/realworld/edgecases_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index ae749746..8966c383 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -26,7 +26,7 @@ def rubygems_version(name, requirement) gem "linecache", "0.46" G bundle :lock - expect(err).to be_empty + expect(last_command.stderr).to be_empty expect(exitstatus).to eq(0) if exitstatus end @@ -241,7 +241,7 @@ def rubygems_version(name, requirement) bundle! :install, forgotten_command_line_options(:path => "vendor/bundle") expect(err).not_to include("Could not find rake") - expect(err).to be_empty + expect(last_command.stderr).to be_empty end it "checks out git repos when the lockfile is corrupted" do From b6057306813418536151f48f19011069071795f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Thu, 14 Feb 2019 16:32:59 +0100 Subject: [PATCH 500/707] Improve some assertions about folders --- test/rubygems/test_gem.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index b2f718bf..fa2c6084 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -553,7 +553,7 @@ def test_self_ensure_gem_directories_permissions Gem.ensure_gem_subdirectories @gemhome, 0750 - assert File.directory? File.join(@gemhome, "cache") + assert_directory_exists File.join(@gemhome, "cache") assert_equal 0750, File::Stat.new(@gemhome).mode & 0777 assert_equal 0750, File::Stat.new(File.join(@gemhome, "cache")).mode & 0777 @@ -582,7 +582,7 @@ def test_self_ensure_gem_directories_missing_parents Gem.ensure_gem_subdirectories gemdir - assert File.directory?(util_cache_dir) + assert_directory_exists util_cache_dir end unless win_platform? || Process.uid.zero? # only for FS that support write protection From eb0c58551b89979ee843772dbdb9508956fb7ced Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Sat, 16 Feb 2019 11:06:56 +0100 Subject: [PATCH 501/707] Undo requirement sorting --- test/rubygems/test_gem_requirement.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/test/rubygems/test_gem_requirement.rb b/test/rubygems/test_gem_requirement.rb index 96acb247..a93eea56 100644 --- a/test/rubygems/test_gem_requirement.rb +++ b/test/rubygems/test_gem_requirement.rb @@ -35,7 +35,6 @@ def test_initialize assert_requirement_equal "= 2", ["2"] assert_requirement_equal "= 2", v(2) assert_requirement_equal "2.0", "2" - assert_requirement_equal ["= 2", ">= 2"], [">= 2", "= 2"] end def test_create From da12ba7b779167878b95a4504147b868c9c5245e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Mon, 18 Feb 2019 08:52:50 +0100 Subject: [PATCH 502/707] Extract a `with_clean_path_to_ruby` helper --- test/rubygems/test_gem.rb | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index fa2c6084..e98f8886 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -952,7 +952,6 @@ def test_self_refresh_keeps_loaded_specs_activated end def test_self_ruby_escaping_spaces_in_path - orig_ruby = Gem.ruby orig_bindir = RbConfig::CONFIG['bindir'] orig_ruby_install_name = RbConfig::CONFIG['ruby_install_name'] orig_exe_ext = RbConfig::CONFIG['EXEEXT'] @@ -960,18 +959,17 @@ def test_self_ruby_escaping_spaces_in_path RbConfig::CONFIG['bindir'] = "C:/Ruby 1.8/bin" RbConfig::CONFIG['ruby_install_name'] = "ruby" RbConfig::CONFIG['EXEEXT'] = ".exe" - Gem.instance_variable_set("@ruby", nil) - assert_equal "\"C:/Ruby 1.8/bin/ruby.exe\"", Gem.ruby + with_clean_path_to_ruby do + assert_equal "\"C:/Ruby 1.8/bin/ruby.exe\"", Gem.ruby + end ensure - Gem.instance_variable_set("@ruby", orig_ruby) RbConfig::CONFIG['bindir'] = orig_bindir RbConfig::CONFIG['ruby_install_name'] = orig_ruby_install_name RbConfig::CONFIG['EXEEXT'] = orig_exe_ext end def test_self_ruby_path_without_spaces - orig_ruby = Gem.ruby orig_bindir = RbConfig::CONFIG['bindir'] orig_ruby_install_name = RbConfig::CONFIG['ruby_install_name'] orig_exe_ext = RbConfig::CONFIG['EXEEXT'] @@ -979,11 +977,11 @@ def test_self_ruby_path_without_spaces RbConfig::CONFIG['bindir'] = "C:/Ruby18/bin" RbConfig::CONFIG['ruby_install_name'] = "ruby" RbConfig::CONFIG['EXEEXT'] = ".exe" - Gem.instance_variable_set("@ruby", nil) - assert_equal "C:/Ruby18/bin/ruby.exe", Gem.ruby + with_clean_path_to_ruby do + assert_equal "C:/Ruby18/bin/ruby.exe", Gem.ruby + end ensure - Gem.instance_variable_set("@ruby", orig_ruby) RbConfig::CONFIG['bindir'] = orig_bindir RbConfig::CONFIG['ruby_install_name'] = orig_ruby_install_name RbConfig::CONFIG['EXEEXT'] = orig_exe_ext @@ -1904,6 +1902,16 @@ def ruby_install_name(name) end end + def with_clean_path_to_ruby + orig_ruby = Gem.ruby + + Gem.instance_variable_set :@ruby, nil + + yield + ensure + Gem.instance_variable_set("@ruby", orig_ruby) + end + def with_plugin(path) test_plugin_path = File.expand_path("test/rubygems/plugin/#{path}", @@project_dir) From 6e84ed0cb6c43f36e2c3638dc32e3659f8fe4a0b Mon Sep 17 00:00:00 2001 From: MSP-Greg Date: Sun, 17 Feb 2019 14:37:42 -0600 Subject: [PATCH 503/707] Fix intermittent test Reuse `with_clean_path_to_ruby` to reset state. Fixes ``` SEED=6332 rake TESTOPTS="--name=/test_looks_for_gemdeps_files_automatically_on_start_in_parent_dir\|test_self_install_permissions_with_format_executable_and_non_standard_ruby_install_name/" ``` --- test/rubygems/test_gem.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index e98f8886..414f2501 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -155,8 +155,10 @@ def test_self_install_permissions_with_format_executable def test_self_install_permissions_with_format_executable_and_non_standard_ruby_install_name Gem::Installer.exec_format = nil - ruby_install_name 'ruby27' do - assert_self_install_permissions(format_executable: true) + with_clean_path_to_ruby do + ruby_install_name 'ruby27' do + assert_self_install_permissions(format_executable: true) + end end ensure Gem::Installer.exec_format = nil From aad15a9e3996f9bc92a8fdd0c5bb691986163901 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Mon, 18 Feb 2019 09:01:08 +0100 Subject: [PATCH 504/707] Reuse another state resetting helper `ruby_install_name` in this case. --- test/rubygems/test_gem.rb | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 414f2501..ad802e0f 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -955,37 +955,35 @@ def test_self_refresh_keeps_loaded_specs_activated def test_self_ruby_escaping_spaces_in_path orig_bindir = RbConfig::CONFIG['bindir'] - orig_ruby_install_name = RbConfig::CONFIG['ruby_install_name'] orig_exe_ext = RbConfig::CONFIG['EXEEXT'] RbConfig::CONFIG['bindir'] = "C:/Ruby 1.8/bin" - RbConfig::CONFIG['ruby_install_name'] = "ruby" RbConfig::CONFIG['EXEEXT'] = ".exe" - with_clean_path_to_ruby do - assert_equal "\"C:/Ruby 1.8/bin/ruby.exe\"", Gem.ruby + ruby_install_name "ruby" do + with_clean_path_to_ruby do + assert_equal "\"C:/Ruby 1.8/bin/ruby.exe\"", Gem.ruby + end end ensure RbConfig::CONFIG['bindir'] = orig_bindir - RbConfig::CONFIG['ruby_install_name'] = orig_ruby_install_name RbConfig::CONFIG['EXEEXT'] = orig_exe_ext end def test_self_ruby_path_without_spaces orig_bindir = RbConfig::CONFIG['bindir'] - orig_ruby_install_name = RbConfig::CONFIG['ruby_install_name'] orig_exe_ext = RbConfig::CONFIG['EXEEXT'] RbConfig::CONFIG['bindir'] = "C:/Ruby18/bin" - RbConfig::CONFIG['ruby_install_name'] = "ruby" RbConfig::CONFIG['EXEEXT'] = ".exe" - with_clean_path_to_ruby do - assert_equal "C:/Ruby18/bin/ruby.exe", Gem.ruby + ruby_install_name "ruby" do + with_clean_path_to_ruby do + assert_equal "C:/Ruby18/bin/ruby.exe", Gem.ruby + end end ensure RbConfig::CONFIG['bindir'] = orig_bindir - RbConfig::CONFIG['ruby_install_name'] = orig_ruby_install_name RbConfig::CONFIG['EXEEXT'] = orig_exe_ext end From 616fff66ad9a934660215fbc120d9dee00b906ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Mon, 4 Feb 2019 19:08:14 +0100 Subject: [PATCH 505/707] Downgrade bundler version mismatches to a warning --- test/rubygems/test_gem.rb | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index fa2c6084..a3e79345 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -319,14 +319,14 @@ def test_activate_bin_path_gives_proper_error_for_bundler File.open("Gemfile", "w") { |f| f.puts('source "https://rubygems.org"') } - e = assert_raises Gem::GemNotFoundException do + _, err = capture_io do load Gem.activate_bin_path("bundler", "bundle", ">= 0.a") end - assert_includes e.message, "Could not find 'bundler' (9999) required by your #{File.expand_path("Gemfile.lock")}." - assert_includes e.message, "To update to the latest version installed on your system, run `bundle update --bundler`." - assert_includes e.message, "To install the missing version, run `gem install bundler:9999`" - refute_includes e.message, "can't find gem bundler (>= 0.a) with executable bundle" + assert_includes err, "Could not find 'bundler' (9999) required by your #{File.expand_path("Gemfile.lock")}." + assert_includes err, "To update to the latest version installed on your system, run `bundle update --bundler`." + assert_includes err, "To install the missing version, run `gem install bundler:9999`" + refute_includes err, "can't find gem bundler (>= 0.a) with executable bundle" end def test_self_bin_path_no_exec_name From 34af84e347b9f802202b940089a35ce2793203c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Fri, 22 Feb 2019 11:40:34 +0100 Subject: [PATCH 506/707] Remove unnecessary ruby filters from specs --- bundler/spec/realworld/edgecases_spec.rb | 44 ++---------------------- 1 file changed, 3 insertions(+), 41 deletions(-) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index 8966c383..0189c550 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -19,45 +19,7 @@ def rubygems_version(name, requirement) RUBY end - # there is no rbx-relative-require gem that will install on 1.9 - it "ignores extra gems with bad platforms", :ruby => "~> 1.8.7" do - gemfile <<-G - source "https://rubygems.org" - gem "linecache", "0.46" - G - bundle :lock - expect(last_command.stderr).to be_empty - expect(exitstatus).to eq(0) if exitstatus - end - - # https://github.com/bundler/bundler/issues/1202 - it "bundle cache works with rubygems 1.3.7 and pre gems", - :ruby => "~> 1.8.7", :rubygems => "~> 1.3.7" do - install_gemfile <<-G - source "https://rubygems.org" - gem "rack", "1.3.0.beta2" - gem "will_paginate", "3.0.pre2" - G - bundle :cache - expect(out).not_to include("Removing outdated .gem files from vendor/cache") - end - - # https://github.com/bundler/bundler/issues/1486 - # this is a hash collision that only manifests on 1.8.7 - it "finds the correct child versions", :ruby => "~> 1.8.7" do - gemfile <<-G - source "https://rubygems.org" - - gem 'i18n', '~> 0.6.0' - gem 'activesupport', '~> 3.0.5' - gem 'activerecord', '~> 3.0.5' - gem 'builder', '~> 2.1.2' - G - bundle :lock - expect(lockfile).to include("activemodel (3.0.5)") - end - - it "resolves dependencies correctly", :ruby => "1.9.3" do + it "resolves dependencies correctly" do gemfile <<-G source "https://rubygems.org" @@ -70,7 +32,7 @@ def rubygems_version(name, requirement) expect(lockfile).to include("capybara (2.2.1)") end - it "installs the latest version of gxapi_rails", :ruby => "1.9.3" do + it "installs the latest version of gxapi_rails" do gemfile <<-G source "https://rubygems.org" @@ -97,7 +59,7 @@ def rubygems_version(name, requirement) expect(lockfile).to include(rubygems_version("activesupport", "~> 3.0")) end - it "is able to update a top-level dependency when there is a conflict on a shared transitive child", :ruby => "2.1" do + it "is able to update a top-level dependency when there is a conflict on a shared transitive child" do # from https://github.com/bundler/bundler/issues/5031 gemfile <<-G From 239c167a68d70d215a08577e869ab442217cb6fb Mon Sep 17 00:00:00 2001 From: Bundlerbot Date: Tue, 13 Nov 2018 11:19:47 +0000 Subject: [PATCH 507/707] Merge #2426 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 2426: Fix bundler rubygems binstub not properly looking for bundler r=hsbt a=deivid-rodriguez # Description: The problem is that when running a rubygems bundler binstub with a lock file locked to a non-installed bundler version, one would get the cryptic error message: ``` can't find gem bundler (>= 0.a) with executable bundle (Gem::GemNotFoundException) ``` where one tends to think... What? How is it not found if I just run it?! Partially closes bundler/bundler#6595. Now the message is way more clear, but I guess it'd be better to actually run the command. Not sure if that's possible from a rubygems binstub, though. # Tasks: - [x] Describe the problem / feature - [x] Write tests - [x] ~Write~ Delete code to solve the problem - [ ] Get code review from coworkers / friends I will abide by the [code of conduct](https://github.com/rubygems/rubygems/blob/master/CODE_OF_CONDUCT.md). Co-authored-by: David Rodríguez (cherry picked from commit bae9992e50c24616043f7775b6b96038aad5322e) --- test/rubygems/test_gem.rb | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index a6741e02..80d11974 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -209,6 +209,41 @@ def test_activate_bin_path_resolves_eagerly assert_equal %w(a-1 b-2 c-1), loaded_spec_names end + def test_activate_bin_path_gives_proper_error_for_bundler + bundler = util_spec 'bundler', '2' do |s| + s.executables = ['bundle'] + end + + install_specs bundler + + File.open("Gemfile.lock", "w") do |f| + f.write <<-L.gsub(/ {8}/, "") + GEM + remote: https://rubygems.org/ + specs: + + PLATFORMS + ruby + + DEPENDENCIES + + BUNDLED WITH + 9999 + L + end + + File.open("Gemfile", "w") { |f| f.puts('source "https://rubygems.org"') } + + e = assert_raises Gem::GemNotFoundException do + load Gem.activate_bin_path("bundler", "bundle", ">= 0.a") + end + + assert_includes e.message, "Could not find 'bundler' (9999) required by your #{File.expand_path("Gemfile.lock")}." + assert_includes e.message, "To update to the latest version installed on your system, run `bundle update --bundler`." + assert_includes e.message, "To install the missing version, run `gem install bundler:9999`" + refute_includes e.message, "can't find gem bundler (>= 0.a) with executable bundle" + end + def test_self_bin_path_no_exec_name e = assert_raises ArgumentError do Gem.bin_path 'a' From c2502ca3023d5f40f2848ef5d8f7ebd219eedd80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Sat, 23 Mar 2019 12:31:51 +0100 Subject: [PATCH 508/707] Revert "Merge #2621" This reverts commit 3f6c0ef0e9cd9b7f0899884120990154a20debdf, reversing changes made to b4063c6028fe5f31277ad8b9a4e6f652ca453edd. --- test/rubygems/test_gem.rb | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 20964273..ad802e0f 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -321,14 +321,14 @@ def test_activate_bin_path_gives_proper_error_for_bundler File.open("Gemfile", "w") { |f| f.puts('source "https://rubygems.org"') } - _, err = capture_io do + e = assert_raises Gem::GemNotFoundException do load Gem.activate_bin_path("bundler", "bundle", ">= 0.a") end - assert_includes err, "Could not find 'bundler' (9999) required by your #{File.expand_path("Gemfile.lock")}." - assert_includes err, "To update to the latest version installed on your system, run `bundle update --bundler`." - assert_includes err, "To install the missing version, run `gem install bundler:9999`" - refute_includes err, "can't find gem bundler (>= 0.a) with executable bundle" + assert_includes e.message, "Could not find 'bundler' (9999) required by your #{File.expand_path("Gemfile.lock")}." + assert_includes e.message, "To update to the latest version installed on your system, run `bundle update --bundler`." + assert_includes e.message, "To install the missing version, run `gem install bundler:9999`" + refute_includes e.message, "can't find gem bundler (>= 0.a) with executable bundle" end def test_self_bin_path_no_exec_name From 7d5d4b5cf556df0c1f4484b9541ac53ffafb0ba8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Fri, 29 Mar 2019 11:00:22 +0100 Subject: [PATCH 509/707] Forbid `find_spec_for_exe` without an `exec_name` With this we can make `Gem.bin_path` and `Gem.activate_bin_path` behave exactly the same regarding this parameter, and it allows us to simplify bundler's integration since the current version handles the case where no executable is passed, defaulting to `Gem::Specification.default_executable` in that case, which is a deprecated rubygems method anyways. --- test/rubygems/test_gem.rb | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index ad802e0f..2250a6a4 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -267,6 +267,14 @@ def test_self_bin_path_picking_newest assert_match 'a-2/bin/exec', Gem.bin_path('a', 'exec', '>= 0') end + def test_self_activate_bin_path_no_exec_name + e = assert_raises ArgumentError do + Gem.activate_bin_path 'a' + end + + assert_equal 'you must supply exec_name', e.message + end + def test_activate_bin_path_resolves_eagerly a1 = util_spec 'a', '1' do |s| s.executables = ['exec'] From 7b11c5172fcacf6de5640e66a509e0570044dbf4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Sat, 30 Mar 2019 06:57:19 +0100 Subject: [PATCH 510/707] Extract common logic --- test/rubygems/test_gem.rb | 47 +++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 24 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index ad802e0f..f1b44ece 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -954,37 +954,23 @@ def test_self_refresh_keeps_loaded_specs_activated end def test_self_ruby_escaping_spaces_in_path - orig_bindir = RbConfig::CONFIG['bindir'] - orig_exe_ext = RbConfig::CONFIG['EXEEXT'] - - RbConfig::CONFIG['bindir'] = "C:/Ruby 1.8/bin" - RbConfig::CONFIG['EXEEXT'] = ".exe" - - ruby_install_name "ruby" do - with_clean_path_to_ruby do - assert_equal "\"C:/Ruby 1.8/bin/ruby.exe\"", Gem.ruby + with_bindir_and_exeext("C:/Ruby 1.8/bin", ".exe") do + ruby_install_name "ruby" do + with_clean_path_to_ruby do + assert_equal "\"C:/Ruby 1.8/bin/ruby.exe\"", Gem.ruby + end end end - ensure - RbConfig::CONFIG['bindir'] = orig_bindir - RbConfig::CONFIG['EXEEXT'] = orig_exe_ext end def test_self_ruby_path_without_spaces - orig_bindir = RbConfig::CONFIG['bindir'] - orig_exe_ext = RbConfig::CONFIG['EXEEXT'] - - RbConfig::CONFIG['bindir'] = "C:/Ruby18/bin" - RbConfig::CONFIG['EXEEXT'] = ".exe" - - ruby_install_name "ruby" do - with_clean_path_to_ruby do - assert_equal "C:/Ruby18/bin/ruby.exe", Gem.ruby + with_bindir_and_exeext("C:/Ruby18/bin", ".exe") do + ruby_install_name "ruby" do + with_clean_path_to_ruby do + assert_equal "C:/Ruby18/bin/ruby.exe", Gem.ruby + end end end - ensure - RbConfig::CONFIG['bindir'] = orig_bindir - RbConfig::CONFIG['EXEEXT'] = orig_exe_ext end def test_self_ruby_api_version @@ -1902,6 +1888,19 @@ def ruby_install_name(name) end end + def with_bindir_and_exeext(bindir, exeext) + orig_bindir = RbConfig::CONFIG['bindir'] + orig_exe_ext = RbConfig::CONFIG['EXEEXT'] + + RbConfig::CONFIG['bindir'] = bindir + RbConfig::CONFIG['EXEEXT'] = exeext + + yield + ensure + RbConfig::CONFIG['bindir'] = orig_bindir + RbConfig::CONFIG['EXEEXT'] = orig_exe_ext + end + def with_clean_path_to_ruby orig_ruby = Gem.ruby From ce4c36a472629e28c65b0584dd34f03e806455db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Sat, 30 Mar 2019 06:57:40 +0100 Subject: [PATCH 511/707] Normalize style --- test/rubygems/test_gem.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index f1b44ece..3f6fc367 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1908,7 +1908,7 @@ def with_clean_path_to_ruby yield ensure - Gem.instance_variable_set("@ruby", orig_ruby) + Gem.instance_variable_set :@ruby, orig_ruby end def with_plugin(path) From a10110f138618dce1a1c4e25790395f2619592ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Sat, 30 Mar 2019 06:59:15 +0100 Subject: [PATCH 512/707] Make sure `Gem.ruby` value is properly reset Previously it was saving the original value when the state had already been leaked. --- test/rubygems/test_gem.rb | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 3f6fc367..abf70929 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -954,9 +954,9 @@ def test_self_refresh_keeps_loaded_specs_activated end def test_self_ruby_escaping_spaces_in_path - with_bindir_and_exeext("C:/Ruby 1.8/bin", ".exe") do - ruby_install_name "ruby" do - with_clean_path_to_ruby do + with_clean_path_to_ruby do + with_bindir_and_exeext("C:/Ruby 1.8/bin", ".exe") do + ruby_install_name "ruby" do assert_equal "\"C:/Ruby 1.8/bin/ruby.exe\"", Gem.ruby end end @@ -964,9 +964,9 @@ def test_self_ruby_escaping_spaces_in_path end def test_self_ruby_path_without_spaces - with_bindir_and_exeext("C:/Ruby18/bin", ".exe") do - ruby_install_name "ruby" do - with_clean_path_to_ruby do + with_clean_path_to_ruby do + with_bindir_and_exeext("C:/Ruby18/bin", ".exe") do + ruby_install_name "ruby" do assert_equal "C:/Ruby18/bin/ruby.exe", Gem.ruby end end From b937ac54b3cb50ab8905263e239ac038b6101e27 Mon Sep 17 00:00:00 2001 From: Bundlerbot Date: Mon, 28 Jan 2019 09:36:10 +0000 Subject: [PATCH 513/707] Merge #6935 6935: Make URLs in document consistent and secure r=greysteil a=aeroastro There are 3 documentation problems * End-users experience 301 redirect when visiting http://www.bundler.io and http://bundler.io * End-users might accidentally send email addresses via http version of https://slack.bundler.io, which is not redirected automatically. * Partially fixing this is O.K., but consistent URLs throughout the documentation are easy to use. I have manually visited the Slack invitation URL on https://bundler.io/ and noticed the problem. Following are the simple curl command to explain this problem. ``` $ curl -I http://slack.bundler.io HTTP/1.1 200 OK Server: Cowboy Connection: keep-alive X-Powered-By: Express Content-Type: text/html; charset=utf-8 Content-Length: 3726 Etag: W/"QPm3qygnJrqeFm+KK+VifA==" Date: Mon, 28 Jan 2019 07:32:02 GMT Via: 1.1 vegur ``` ``` $ curl -I http://www.bundler.io HTTP/1.1 301 Moved Permanently Content-Type: text/html; charset=utf-8 Location: https://bundler.io X-Redirector-Version: 84a0a5c Date: Mon, 28 Jan 2019 07:32:28 GMT ``` ``` $ curl -I http://bundler.io HTTP/1.1 301 Moved Permanently Server: GitHub.com Content-Type: text/html Location: https://bundler.io/ X-GitHub-Request-Id: FF7E:37F3:4DD47F:595032:5C4EB012 Content-Length: 178 Accept-Ranges: bytes Date: Mon, 28 Jan 2019 07:32:35 GMT Via: 1.1 varnish Age: 0 Connection: keep-alive X-Served-By: cache-nrt6127-NRT X-Cache: MISS X-Cache-Hits: 0 X-Timer: S1548660755.461639,VS0,VE91 Vary: Accept-Encoding X-Fastly-Request-ID: 8c832766ee3154dc26abd3e1adcd1258a243e4ce ``` My fix is to replace old URLs with new URLs. * Replace Slack invitation URLs with safe https ones * Replace http://www.bundler.io with https://bundler.io * Replace http://bundler.io with https://bundler.io Because rewriting URLs on document is easy and simple. Optionally, if someone could implement 301 redirect on Slack invitation URL, it would further help the issue. Co-authored-by: Takumasa Ochi (cherry picked from commit 2b8015c2aa696209526f5747d09ee41f48553d46) --- bundler/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundler/README.md b/bundler/README.md index c9b85a7c..3a117a9b 100644 --- a/bundler/README.md +++ b/bundler/README.md @@ -29,7 +29,7 @@ bundle install bundle exec rspec ``` -See [bundler.io](http://bundler.io) for the full documentation. +See [bundler.io](https://bundler.io) for the full documentation. ### Troubleshooting From 40af49e6728991fefd282e368619d14ec3d339fd Mon Sep 17 00:00:00 2001 From: SHIBATA Hiroshi Date: Wed, 3 Apr 2019 22:49:46 +0900 Subject: [PATCH 514/707] Removed guard condition with USE_BUNDLER_FOR_GEMDEPS. Because Ruby 2.6+ has RubyGems and Bundler with the standard libraries. We can always activate Bundler in RubyGems. --- test/rubygems/test_gem.rb | 30 +++++++++--------------------- 1 file changed, 9 insertions(+), 21 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index abf70929..e9a7ab64 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1548,19 +1548,15 @@ def test_auto_activation_of_used_gemdeps_file ENV['RUBYGEMS_GEMDEPS'] = "-" - expected_specs = [a, b, (Gem::USE_BUNDLER_FOR_GEMDEPS || nil) && util_spec("bundler", Bundler::VERSION), c].compact + expected_specs = [a, b, util_spec("bundler", Bundler::VERSION), c].compact assert_equal expected_specs, Gem.use_gemdeps.sort_by { |s| s.name } end LIB_PATH = File.expand_path "../../../lib".dup.untaint, __FILE__.dup.untaint - - if Gem::USE_BUNDLER_FOR_GEMDEPS - BUNDLER_LIB_PATH = File.expand_path $LOAD_PATH.find {|lp| File.file?(File.join(lp, "bundler.rb")) }.dup.untaint - BUNDLER_FULL_NAME = "bundler-#{Bundler::VERSION}".freeze - end + BUNDLER_LIB_PATH = File.expand_path $LOAD_PATH.find {|lp| File.file?(File.join(lp, "bundler.rb")) }.dup.untaint + BUNDLER_FULL_NAME = "bundler-#{Bundler::VERSION}".freeze def add_bundler_full_name(names) - return names unless Gem::USE_BUNDLER_FOR_GEMDEPS names << BUNDLER_FULL_NAME names.sort! names @@ -1600,7 +1596,7 @@ def test_looks_for_gemdeps_files_automatically_on_start out = IO.popen(cmd, &:read).split(/\n/) assert_equal ["b-1", "c-1"], out - out0 - end if Gem::USE_BUNDLER_FOR_GEMDEPS + end def test_looks_for_gemdeps_files_automatically_on_start_in_parent_dir util_clear_gems @@ -1640,7 +1636,7 @@ def test_looks_for_gemdeps_files_automatically_on_start_in_parent_dir Dir.rmdir "sub1" assert_equal ["b-1", "c-1"], out - out0 - end if Gem::USE_BUNDLER_FOR_GEMDEPS + end def test_register_default_spec Gem.clear_default_specs @@ -1819,27 +1815,19 @@ def test_use_gemdeps_missing_gem else platform = " #{platform}" end - expected = - if Gem::USE_BUNDLER_FOR_GEMDEPS - <<-EXPECTED + + expected = <<-EXPECTED Could not find gem 'a#{platform}' in any of the gem sources listed in your Gemfile. You may need to `gem install -g` to install missing gems - EXPECTED - else - <<-EXPECTED -Unable to resolve dependency: user requested 'a (>= 0)' -You may need to `gem install -g` to install missing gems - - EXPECTED - end + EXPECTED assert_output nil, expected do Gem.use_gemdeps end ensure ENV['RUBYGEMS_GEMDEPS'] = rubygems_gemdeps - end if Gem::USE_BUNDLER_FOR_GEMDEPS + end def test_use_gemdeps_specific rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], 'x' From 3cb5f0ae8c92ffa4cacbb7cee27ea2a5deefdd47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Thu, 21 Mar 2019 11:12:28 +0100 Subject: [PATCH 515/707] Fix some specs to not rely on remembering flags --- bundler/spec/realworld/edgecases_spec.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index 0189c550..22d94bef 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -201,7 +201,8 @@ def rubygems_version(name, requirement) gem 'rack', '1.0.1' G - bundle! :install, forgotten_command_line_options(:path => "vendor/bundle") + bundle "config set --local path vendor/bundle" + bundle! :install expect(err).not_to include("Could not find rake") expect(last_command.stderr).to be_empty end From aa32ba9489c8373e26ecf1141c8010315aeeb02f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Thu, 4 Apr 2019 22:23:44 +0200 Subject: [PATCH 516/707] Move on to bundler 3 * Drop bundler 1 stuff from tests. * Move all feature flags to bundler 3 (like they are in 2-0-stable) and get them tested. --- bundler/spec/realworld/edgecases_spec.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index 22d94bef..a3662c91 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -23,12 +23,12 @@ def rubygems_version(name, requirement) gemfile <<-G source "https://rubygems.org" - gem 'rails', '~> 3.0' + gem 'rails', '~> 5.0' gem 'capybara', '~> 2.2.0' gem 'rack-cache', '1.2.0' # last version that works on Ruby 1.9 G bundle! :lock - expect(lockfile).to include(rubygems_version("rails", "~> 3.0")) + expect(lockfile).to include(rubygems_version("rails", "~> 5.0")) expect(lockfile).to include("capybara (2.2.1)") end @@ -37,7 +37,7 @@ def rubygems_version(name, requirement) source "https://rubygems.org" gem "sass-rails" - gem "rails", "~> 3" + gem "rails", "~> 5" gem "gxapi_rails", "< 0.1.0" # 0.1.0 was released way after the test was written gem 'rack-cache', '1.2.0' # last version that works on Ruby 1.9 G @@ -150,7 +150,7 @@ def rubygems_version(name, requirement) activemodel (= 4.2.7.1) activerecord (= 4.2.7.1) activesupport (= 4.2.7.1) - bundler (>= 1.3.0, < 2.0) + bundler (>= 1.3.0, < 3.0) railties (= 4.2.7.1) sprockets-rails rails-deprecated_sanitizer (1.0.3) From 1bbe29911fea75225895a28e09aa8f71be8ba6b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Fri, 12 Apr 2019 10:46:15 +0200 Subject: [PATCH 517/707] s/last_command.stderr/err/ --- bundler/spec/realworld/edgecases_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index a3662c91..6468ee7f 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -204,7 +204,7 @@ def rubygems_version(name, requirement) bundle "config set --local path vendor/bundle" bundle! :install expect(err).not_to include("Could not find rake") - expect(last_command.stderr).to be_empty + expect(err).to be_empty end it "checks out git repos when the lockfile is corrupted" do @@ -331,7 +331,7 @@ def rubygems_version(name, requirement) L bundle! :lock - expect(last_command.stderr).to be_empty + expect(err).to be_empty end it "outputs a helpful error message when gems have invalid gemspecs" do From bdb2c19ad7b25e6fab77a29c07fef6b420a01ed7 Mon Sep 17 00:00:00 2001 From: John Hawthorn Date: Tue, 15 Jan 2019 01:10:58 -0800 Subject: [PATCH 518/707] Restore transitiveness of version comparison By comparing canonical versions. --- test/rubygems/test_gem_version.rb | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/test/rubygems/test_gem_version.rb b/test/rubygems/test_gem_version.rb index 6d3893c2..c90648f5 100644 --- a/test/rubygems/test_gem_version.rb +++ b/test/rubygems/test_gem_version.rb @@ -157,6 +157,13 @@ def test_spaceship assert_equal(1, v("1.8.2.a10") <=> v("1.8.2.a9")) assert_equal(0, v("") <=> v("0")) + assert_equal(0, v("0.beta.1") <=> v("0.0.beta.1")) + assert_equal(-1, v("0.0.beta") <=> v("0.0.beta.1")) + assert_equal(-1, v("0.0.beta") <=> v("0.beta.1")) + + assert_equal(-1, v("5.a") <=> v("5.0.0.rc2")) + assert_equal(1, v("5.x") <=> v("5.0.0.rc2")) + assert_nil v("1.0") <=> "whatever" end From 3686db1f947afe004bf9a4f3d4a17834df227132 Mon Sep 17 00:00:00 2001 From: John Hawthorn Date: Tue, 15 Jan 2019 01:10:58 -0800 Subject: [PATCH 519/707] Restore transitiveness of version comparison By comparing canonical versions. --- test/rubygems/test_gem_requirement.rb | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/rubygems/test_gem_requirement.rb b/test/rubygems/test_gem_requirement.rb index a93eea56..3db393e9 100644 --- a/test/rubygems/test_gem_requirement.rb +++ b/test/rubygems/test_gem_requirement.rb @@ -265,6 +265,12 @@ def test_satisfied_by_eh_good assert_satisfied_by "3.0.rc2", "< 3.0.1" assert_satisfied_by "3.0.rc2", "> 0" + + assert_satisfied_by "5.0.0.rc2", "~> 5.a" + refute_satisfied_by "5.0.0.rc2", "~> 5.x" + + assert_satisfied_by "5.0.0", "~> 5.a" + assert_satisfied_by "5.0.0", "~> 5.x" end def test_illformed_requirements From ffbeec2ba425b5bab02384c6de7f4324f265fb67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Wed, 24 Apr 2019 15:24:56 +0200 Subject: [PATCH 520/707] Remove coverage tracking for the time being The current numbers are misleading and coverage tracking doesn't work in most of the places since the current test suite is mostly based on spawning subprocesses, and coverage doesn't get properly tracked there. Let's revisit this in the future. --- bundler/README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/bundler/README.md b/bundler/README.md index b06d456d..da7fd7c2 100644 --- a/bundler/README.md +++ b/bundler/README.md @@ -1,6 +1,5 @@ [![Version ](https://img.shields.io/gem/v/bundler.svg?style=flat)](https://rubygems.org/gems/bundler) [![Build Status](https://img.shields.io/travis/bundler/bundler/master.svg?style=flat)](https://travis-ci.org/bundler/bundler) -[![Code Climate](https://img.shields.io/codeclimate/maintainability/bundler/bundler.svg?style=flat)](https://codeclimate.com/github/bundler/bundler) [![Inline docs ](http://inch-ci.org/github/bundler/bundler.svg?style=flat)](http://inch-ci.org/github/bundler/bundler) [![Slack ](http://bundler-slackin.herokuapp.com/badge.svg)](http://bundler-slackin.herokuapp.com) From 70f53b65b5b0d0eae1b77ac34f69fbfa44ead07d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Mon, 29 Apr 2019 01:43:35 +0200 Subject: [PATCH 521/707] I would actually remove it --- test/rubygems/test_gem.rb | 27 --------------------------- 1 file changed, 27 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index af927ffa..c3a8612b 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1674,33 +1674,6 @@ def test_register_default_spec assert_nil Gem.find_unresolved_default_spec("README") end - def test_default_gems_use_full_paths - begin - if defined?(RUBY_ENGINE) - engine = RUBY_ENGINE - Object.send :remove_const, :RUBY_ENGINE - end - Object.const_set :RUBY_ENGINE, 'ruby' - - refute Gem.default_gems_use_full_paths? - ensure - Object.send :remove_const, :RUBY_ENGINE - Object.const_set :RUBY_ENGINE, engine if engine - end - - begin - if defined?(RUBY_ENGINE) - engine = RUBY_ENGINE - Object.send :remove_const, :RUBY_ENGINE - end - Object.const_set :RUBY_ENGINE, 'jruby' - assert Gem.default_gems_use_full_paths? - ensure - Object.send :remove_const, :RUBY_ENGINE - Object.const_set :RUBY_ENGINE, engine if engine - end - end - def test_use_gemdeps gem_deps_file = 'gem.deps.rb'.untaint spec = util_spec 'a', 1 From 120f5de5b1ae13939ce59f7e96fbeb33087a354d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Mon, 29 Apr 2019 12:57:10 +0200 Subject: [PATCH 522/707] WIP --- test/rubygems/test_gem.rb | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index c3a8612b..413e28db 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -521,6 +521,7 @@ def test_self_default_sources end def test_self_use_gemdeps + skip "Requiring bundler messes things up" if RUBY_PLATFORM == "java" rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], '-' FileUtils.mkdir_p 'detect/a/b' @@ -674,6 +675,7 @@ def test_self_find_files end def test_self_find_files_with_gemfile + skip "Requiring bundler messes things up" if RUBY_PLATFORM == "java" cwd = File.expand_path("test/rubygems", @@project_dir) actual_load_path = $LOAD_PATH.unshift(cwd).dup @@ -706,7 +708,7 @@ def test_self_find_files_with_gemfile assert_equal expected, Gem.find_files('sff/discover').sort assert_equal expected, Gem.find_files('sff/**.rb').sort, '[ruby-core:31730]' ensure - assert_equal cwd, actual_load_path.shift + assert_equal cwd, actual_load_path.shift unless RUBY_PLATFORM == "java" end def test_self_find_latest_files @@ -1232,10 +1234,12 @@ def test_self_try_activate_missing_extensions refute Gem.try_activate 'nonexistent' end - expected = "Ignoring ext-1 because its extensions are not built. " + - "Try: gem pristine ext --version 1\n" + unless RUBY_PLATFORM == "java" + expected = "Ignoring ext-1 because its extensions are not built. " + + "Try: gem pristine ext --version 1\n" - assert_equal expected, err + assert_equal expected, err + end end def test_self_use_paths_with_nils @@ -1364,6 +1368,8 @@ def test_self_gzip end def test_self_vendor_dir + skip "No vendordir by default on jruby" if RUBY_PLATFORM == "java" + expected = File.join RbConfig::CONFIG['vendordir'], 'gems', RbConfig::CONFIG['ruby_version'] @@ -1514,6 +1520,7 @@ def test_gem_path_ordering_short end def test_auto_activation_of_specific_gemdeps_file + skip "Requiring bundler messes things up" if RUBY_PLATFORM == "java" util_clear_gems a = util_spec "a", "1", nil, "lib/a.rb" @@ -1538,6 +1545,7 @@ def test_auto_activation_of_specific_gemdeps_file end def test_auto_activation_of_used_gemdeps_file + skip "Requiring bundler messes things up" if RUBY_PLATFORM == "java" util_clear_gems a = util_spec "a", "1", nil, "lib/a.rb" @@ -1571,6 +1579,7 @@ def add_bundler_full_name(names) end def test_looks_for_gemdeps_files_automatically_on_start + skip "Requiring bundler messes things up" if RUBY_PLATFORM == "java" util_clear_gems a = util_spec "a", "1", nil, "lib/a.rb" @@ -1595,18 +1604,19 @@ def test_looks_for_gemdeps_files_automatically_on_start File.open path, "w" do |f| f.puts "gem 'a'" end - out0 = IO.popen(cmd, &:read).split(/\n/) + out0 = `#{cmd.shelljoin}`.split(/\n/) File.open path, "a" do |f| f.puts "gem 'b'" f.puts "gem 'c'" end - out = IO.popen(cmd, &:read).split(/\n/) + out = `#{cmd.shelljoin}`.split(/\n/) assert_equal ["b-1", "c-1"], out - out0 end def test_looks_for_gemdeps_files_automatically_on_start_in_parent_dir + skip "Requiring bundler messes things up" if RUBY_PLATFORM == "java" util_clear_gems a = util_spec "a", "1", nil, "lib/a.rb" @@ -1633,13 +1643,13 @@ def test_looks_for_gemdeps_files_automatically_on_start_in_parent_dir File.open path, "w" do |f| f.puts "gem 'a'" end - out0 = IO.popen(cmd, &:read).split(/\n/) + out0 = `#{cmd.shelljoin}`.split(/\n/) File.open path, "a" do |f| f.puts "gem 'b'" f.puts "gem 'c'" end - out = IO.popen(cmd, &:read).split(/\n/) + out = `#{cmd.shelljoin}`.split(/\n/) Dir.rmdir "sub1" @@ -1675,6 +1685,7 @@ def test_register_default_spec end def test_use_gemdeps + skip "Requiring bundler messes things up" if RUBY_PLATFORM == "java" gem_deps_file = 'gem.deps.rb'.untaint spec = util_spec 'a', 1 install_specs spec @@ -1736,6 +1747,7 @@ def test_use_gemdeps_argument_missing_match_ENV end def test_use_gemdeps_automatic + skip "Requiring bundler messes things up" if RUBY_PLATFORM == "java" rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], '-' spec = util_spec 'a', 1 @@ -1784,6 +1796,7 @@ def test_use_gemdeps_disabled end def test_use_gemdeps_missing_gem + skip "Requiring bundler messes things up" if RUBY_PLATFORM == "java" rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], 'x' File.open 'x', 'w' do |io| @@ -1811,6 +1824,7 @@ def test_use_gemdeps_missing_gem end def test_use_gemdeps_specific + skip "Requiring bundler messes things up" if RUBY_PLATFORM == "java" rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], 'x' spec = util_spec 'a', 1 From f0f1d5c3cea735935298cc4b506c4a6e4d839ac6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Mon, 29 Apr 2019 15:26:50 +0200 Subject: [PATCH 523/707] Rework vendordir handling --- test/rubygems/test_gem.rb | 73 ++++++++++++++++----------------------- 1 file changed, 29 insertions(+), 44 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 413e28db..e67208fe 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -465,55 +465,43 @@ def test_self_default_exec_format_jruby end def test_default_path - orig_vendordir = RbConfig::CONFIG['vendordir'] - RbConfig::CONFIG['vendordir'] = File.join @tempdir, 'vendor' + vendordir(File.join(@tempdir, 'vendor')) do + FileUtils.rm_rf Gem.user_home - FileUtils.rm_rf Gem.user_home + expected = [Gem.default_dir] - expected = [Gem.default_dir] - - assert_equal expected, Gem.default_path - ensure - RbConfig::CONFIG['vendordir'] = orig_vendordir + assert_equal expected, Gem.default_path + end end def test_default_path_missing_vendor - orig_vendordir = RbConfig::CONFIG['vendordir'] - RbConfig::CONFIG.delete 'vendordir' + vendordir(nil) do + FileUtils.rm_rf Gem.user_home - FileUtils.rm_rf Gem.user_home + expected = [Gem.default_dir] - expected = [Gem.default_dir] - - assert_equal expected, Gem.default_path - ensure - RbConfig::CONFIG['vendordir'] = orig_vendordir + assert_equal expected, Gem.default_path + end end def test_default_path_user_home - orig_vendordir = RbConfig::CONFIG['vendordir'] - RbConfig::CONFIG['vendordir'] = File.join @tempdir, 'vendor' - - expected = [Gem.user_dir, Gem.default_dir] + vendordir(File.join(@tempdir, 'vendor')) do + expected = [Gem.user_dir, Gem.default_dir] - assert_equal expected, Gem.default_path - ensure - RbConfig::CONFIG['vendordir'] = orig_vendordir + assert_equal expected, Gem.default_path + end end def test_default_path_vendor_dir - orig_vendordir = RbConfig::CONFIG['vendordir'] - RbConfig::CONFIG['vendordir'] = File.join @tempdir, 'vendor' + vendordir(File.join(@tempdir, 'vendor')) do + FileUtils.mkdir_p Gem.vendor_dir - FileUtils.mkdir_p Gem.vendor_dir + FileUtils.rm_rf Gem.user_home - FileUtils.rm_rf Gem.user_home + expected = [Gem.default_dir, Gem.vendor_dir] - expected = [Gem.default_dir, Gem.vendor_dir] - - assert_equal expected, Gem.default_path - ensure - RbConfig::CONFIG['vendordir'] = orig_vendordir + assert_equal expected, Gem.default_path + end end def test_self_default_sources @@ -1368,13 +1356,13 @@ def test_self_gzip end def test_self_vendor_dir - skip "No vendordir by default on jruby" if RUBY_PLATFORM == "java" - - expected = - File.join RbConfig::CONFIG['vendordir'], 'gems', - RbConfig::CONFIG['ruby_version'] + vendordir(File.join(@tempdir, 'vendor')) do + expected = + File.join RbConfig::CONFIG['vendordir'], 'gems', + RbConfig::CONFIG['ruby_version'] - assert_equal expected, Gem.vendor_dir + assert_equal expected, Gem.vendor_dir + end end def test_self_vendor_dir_ENV_GEM_VENDOR @@ -1385,12 +1373,9 @@ def test_self_vendor_dir_ENV_GEM_VENDOR end def test_self_vendor_dir_missing - orig_vendordir = RbConfig::CONFIG['vendordir'] - RbConfig::CONFIG.delete 'vendordir' - - assert_nil Gem.vendor_dir - ensure - RbConfig::CONFIG['vendordir'] = orig_vendordir + vendordir(nil) do + assert_nil Gem.vendor_dir + end end def test_load_plugins From f63703d44263c0fc99d16bcc757661af5b425a2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Mon, 29 Apr 2019 16:22:45 +0200 Subject: [PATCH 524/707] Extract helpers analogous to windows ones --- test/rubygems/test_gem.rb | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index e67208fe..59f84704 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -509,7 +509,7 @@ def test_self_default_sources end def test_self_use_gemdeps - skip "Requiring bundler messes things up" if RUBY_PLATFORM == "java" + skip "Requiring bundler messes things up" if Gem.java_platform? rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], '-' FileUtils.mkdir_p 'detect/a/b' @@ -663,7 +663,7 @@ def test_self_find_files end def test_self_find_files_with_gemfile - skip "Requiring bundler messes things up" if RUBY_PLATFORM == "java" + skip "Requiring bundler messes things up" if Gem.java_platform? cwd = File.expand_path("test/rubygems", @@project_dir) actual_load_path = $LOAD_PATH.unshift(cwd).dup @@ -696,7 +696,7 @@ def test_self_find_files_with_gemfile assert_equal expected, Gem.find_files('sff/discover').sort assert_equal expected, Gem.find_files('sff/**.rb').sort, '[ruby-core:31730]' ensure - assert_equal cwd, actual_load_path.shift unless RUBY_PLATFORM == "java" + assert_equal cwd, actual_load_path.shift unless Gem.java_platform? end def test_self_find_latest_files @@ -1222,7 +1222,7 @@ def test_self_try_activate_missing_extensions refute Gem.try_activate 'nonexistent' end - unless RUBY_PLATFORM == "java" + unless Gem.java_platform? expected = "Ignoring ext-1 because its extensions are not built. " + "Try: gem pristine ext --version 1\n" @@ -1505,7 +1505,7 @@ def test_gem_path_ordering_short end def test_auto_activation_of_specific_gemdeps_file - skip "Requiring bundler messes things up" if RUBY_PLATFORM == "java" + skip "Requiring bundler messes things up" if Gem.java_platform? util_clear_gems a = util_spec "a", "1", nil, "lib/a.rb" @@ -1530,7 +1530,7 @@ def test_auto_activation_of_specific_gemdeps_file end def test_auto_activation_of_used_gemdeps_file - skip "Requiring bundler messes things up" if RUBY_PLATFORM == "java" + skip "Requiring bundler messes things up" if Gem.java_platform? util_clear_gems a = util_spec "a", "1", nil, "lib/a.rb" @@ -1564,7 +1564,7 @@ def add_bundler_full_name(names) end def test_looks_for_gemdeps_files_automatically_on_start - skip "Requiring bundler messes things up" if RUBY_PLATFORM == "java" + skip "Requiring bundler messes things up" if Gem.java_platform? util_clear_gems a = util_spec "a", "1", nil, "lib/a.rb" @@ -1601,7 +1601,7 @@ def test_looks_for_gemdeps_files_automatically_on_start end def test_looks_for_gemdeps_files_automatically_on_start_in_parent_dir - skip "Requiring bundler messes things up" if RUBY_PLATFORM == "java" + skip "Requiring bundler messes things up" if Gem.java_platform? util_clear_gems a = util_spec "a", "1", nil, "lib/a.rb" @@ -1670,7 +1670,7 @@ def test_register_default_spec end def test_use_gemdeps - skip "Requiring bundler messes things up" if RUBY_PLATFORM == "java" + skip "Requiring bundler messes things up" if Gem.java_platform? gem_deps_file = 'gem.deps.rb'.untaint spec = util_spec 'a', 1 install_specs spec @@ -1732,7 +1732,7 @@ def test_use_gemdeps_argument_missing_match_ENV end def test_use_gemdeps_automatic - skip "Requiring bundler messes things up" if RUBY_PLATFORM == "java" + skip "Requiring bundler messes things up" if Gem.java_platform? rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], '-' spec = util_spec 'a', 1 @@ -1781,7 +1781,7 @@ def test_use_gemdeps_disabled end def test_use_gemdeps_missing_gem - skip "Requiring bundler messes things up" if RUBY_PLATFORM == "java" + skip "Requiring bundler messes things up" if Gem.java_platform? rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], 'x' File.open 'x', 'w' do |io| @@ -1809,7 +1809,7 @@ def test_use_gemdeps_missing_gem end def test_use_gemdeps_specific - skip "Requiring bundler messes things up" if RUBY_PLATFORM == "java" + skip "Requiring bundler messes things up" if Gem.java_platform? rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], 'x' spec = util_spec 'a', 1 From cbf63602b194a4ef4d8c91862ef2d27368edcc04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Mon, 29 Apr 2019 18:07:29 +0200 Subject: [PATCH 525/707] Undo more stuff --- test/rubygems/test_gem.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 59f84704..9102e551 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1589,13 +1589,13 @@ def test_looks_for_gemdeps_files_automatically_on_start File.open path, "w" do |f| f.puts "gem 'a'" end - out0 = `#{cmd.shelljoin}`.split(/\n/) + out0 = IO.popen(cmd, &:read).split(/\n/) File.open path, "a" do |f| f.puts "gem 'b'" f.puts "gem 'c'" end - out = `#{cmd.shelljoin}`.split(/\n/) + out = IO.popen(cmd, &:read).split(/\n/) assert_equal ["b-1", "c-1"], out - out0 end @@ -1628,13 +1628,13 @@ def test_looks_for_gemdeps_files_automatically_on_start_in_parent_dir File.open path, "w" do |f| f.puts "gem 'a'" end - out0 = `#{cmd.shelljoin}`.split(/\n/) + out0 = IO.popen(cmd, &:read).split(/\n/) File.open path, "a" do |f| f.puts "gem 'b'" f.puts "gem 'c'" end - out = `#{cmd.shelljoin}`.split(/\n/) + out = IO.popen(cmd, &:read).split(/\n/) Dir.rmdir "sub1" From 2b36ad51d5f91959e63377f2e196179cd7fb928b Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Wed, 1 May 2019 07:56:44 +0800 Subject: [PATCH 526/707] Added supported versions of Ruby. Fixes #2586 --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index 158abc09..d38a8bb1 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,12 @@ Finally, inside your Ruby program, load the Nokogiri gem and start parsing your For more information about how to use RubyGems, see our RubyGems basics guide at [guides.rubygems.org](http://guides.rubygems.org/rubygems-basics/) +## Requirements + +* RubyGems 2.6 support Ruby 2.4 or lower version of Ruby. +* RubyGems 2.7 support Ruby 2.5 or lower version of Ruby. +* RubyGems 3.0 support Ruby 2.6 or lower version of Ruby. + ## Installation RubyGems is likely already installed in your Ruby environment, you can check by running `gem --version` in your terminal emulator. From c7829d4817d7ade7147f3df036ad3f83c88400e9 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Wed, 1 May 2019 08:24:19 +0800 Subject: [PATCH 527/707] Update support versions for RG 3.0. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d38a8bb1..ba36e0ec 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ For more information about how to use RubyGems, see our RubyGems basics guide at * RubyGems 2.6 support Ruby 2.4 or lower version of Ruby. * RubyGems 2.7 support Ruby 2.5 or lower version of Ruby. -* RubyGems 3.0 support Ruby 2.6 or lower version of Ruby. +* RubyGems 3.0 support Ruby 2.3+. ## Installation From 5beebc95923006de76c25f4ca3387aec613f43d5 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Thu, 2 May 2019 07:58:02 +0800 Subject: [PATCH 528/707] Update with suggested words. --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index ba36e0ec..2d2c452b 100644 --- a/README.md +++ b/README.md @@ -27,9 +27,9 @@ For more information about how to use RubyGems, see our RubyGems basics guide at ## Requirements -* RubyGems 2.6 support Ruby 2.4 or lower version of Ruby. -* RubyGems 2.7 support Ruby 2.5 or lower version of Ruby. -* RubyGems 3.0 support Ruby 2.3+. +* RubyGems 2.6 supports Ruby 2.4 or lower. +* RubyGems 2.7 supports Ruby 2.5 or lower. +* RubyGems 3.0 supports Ruby 2.3 or later. ## Installation From 9c93467627ab542ee834a65c5302111e6fb17dfc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Tue, 30 Apr 2019 19:19:22 +0200 Subject: [PATCH 529/707] Remove unnecessary state resetting --- test/rubygems/test_gem.rb | 6 ------ 1 file changed, 6 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 9102e551..8b49c52e 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1295,7 +1295,6 @@ def test_self_user_home end def test_self_needs - util_clear_gems a = util_spec "a", "1" b = util_spec "b", "1", "c" => nil c = util_spec "c", "2" @@ -1314,7 +1313,6 @@ def test_self_needs def test_self_needs_picks_up_unresolved_deps save_loaded_features do - util_clear_gems a = util_spec "a", "1" b = util_spec "b", "1", "c" => nil c = util_spec "c", "2" @@ -1506,7 +1504,6 @@ def test_gem_path_ordering_short def test_auto_activation_of_specific_gemdeps_file skip "Requiring bundler messes things up" if Gem.java_platform? - util_clear_gems a = util_spec "a", "1", nil, "lib/a.rb" b = util_spec "b", "1", nil, "lib/b.rb" @@ -1531,7 +1528,6 @@ def test_auto_activation_of_specific_gemdeps_file def test_auto_activation_of_used_gemdeps_file skip "Requiring bundler messes things up" if Gem.java_platform? - util_clear_gems a = util_spec "a", "1", nil, "lib/a.rb" b = util_spec "b", "1", nil, "lib/b.rb" @@ -1565,7 +1561,6 @@ def add_bundler_full_name(names) def test_looks_for_gemdeps_files_automatically_on_start skip "Requiring bundler messes things up" if Gem.java_platform? - util_clear_gems a = util_spec "a", "1", nil, "lib/a.rb" b = util_spec "b", "1", nil, "lib/b.rb" @@ -1602,7 +1597,6 @@ def test_looks_for_gemdeps_files_automatically_on_start def test_looks_for_gemdeps_files_automatically_on_start_in_parent_dir skip "Requiring bundler messes things up" if Gem.java_platform? - util_clear_gems a = util_spec "a", "1", nil, "lib/a.rb" b = util_spec "b", "1", nil, "lib/b.rb" From 4167c6833f375ac0380bc731f21099e6421bfd66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Wed, 1 May 2019 11:54:05 +0200 Subject: [PATCH 530/707] Remove unnecessary jruby skips --- test/rubygems/test_gem.rb | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 8b49c52e..c90ad2d4 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -509,7 +509,6 @@ def test_self_default_sources end def test_self_use_gemdeps - skip "Requiring bundler messes things up" if Gem.java_platform? rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], '-' FileUtils.mkdir_p 'detect/a/b' @@ -663,7 +662,6 @@ def test_self_find_files end def test_self_find_files_with_gemfile - skip "Requiring bundler messes things up" if Gem.java_platform? cwd = File.expand_path("test/rubygems", @@project_dir) actual_load_path = $LOAD_PATH.unshift(cwd).dup @@ -1503,8 +1501,6 @@ def test_gem_path_ordering_short end def test_auto_activation_of_specific_gemdeps_file - skip "Requiring bundler messes things up" if Gem.java_platform? - a = util_spec "a", "1", nil, "lib/a.rb" b = util_spec "b", "1", nil, "lib/b.rb" c = util_spec "c", "1", nil, "lib/c.rb" @@ -1527,8 +1523,6 @@ def test_auto_activation_of_specific_gemdeps_file end def test_auto_activation_of_used_gemdeps_file - skip "Requiring bundler messes things up" if Gem.java_platform? - a = util_spec "a", "1", nil, "lib/a.rb" b = util_spec "b", "1", nil, "lib/b.rb" c = util_spec "c", "1", nil, "lib/c.rb" @@ -1664,7 +1658,6 @@ def test_register_default_spec end def test_use_gemdeps - skip "Requiring bundler messes things up" if Gem.java_platform? gem_deps_file = 'gem.deps.rb'.untaint spec = util_spec 'a', 1 install_specs spec @@ -1726,7 +1719,6 @@ def test_use_gemdeps_argument_missing_match_ENV end def test_use_gemdeps_automatic - skip "Requiring bundler messes things up" if Gem.java_platform? rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], '-' spec = util_spec 'a', 1 @@ -1775,7 +1767,6 @@ def test_use_gemdeps_disabled end def test_use_gemdeps_missing_gem - skip "Requiring bundler messes things up" if Gem.java_platform? rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], 'x' File.open 'x', 'w' do |io| @@ -1803,7 +1794,6 @@ def test_use_gemdeps_missing_gem end def test_use_gemdeps_specific - skip "Requiring bundler messes things up" if Gem.java_platform? rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], 'x' spec = util_spec 'a', 1 From 1e6638546a5e3334d565deb90abcca21618dbe94 Mon Sep 17 00:00:00 2001 From: Andre Arko Date: Wed, 29 May 2019 05:09:00 +0000 Subject: [PATCH 531/707] Try to help GitHub recognize the MIT license It seems like GitHub can't tell what license this is, despite explicitly naming it inside the file. These changes make our license file closer to other license files that GitHub does successfully recognize as MIT. Hopefully it'll work. --- bundler/LICENSE.md | 37 ++++++++++++++++++------------------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/bundler/LICENSE.md b/bundler/LICENSE.md index e356f59f..52b5c213 100644 --- a/bundler/LICENSE.md +++ b/bundler/LICENSE.md @@ -1,23 +1,22 @@ -Portions copyright (c) 2010 Andre Arko -Portions copyright (c) 2009 Engine Yard +The MIT License -MIT License +Portions copyright (c) 2010-2019 André Arko +Portions copyright (c) 2009 Engine Yard -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. From f9e73a388757d122be976c8277d7a5c439390fb2 Mon Sep 17 00:00:00 2001 From: Bundlerbot Date: Thu, 31 Jan 2019 00:40:18 +0000 Subject: [PATCH 532/707] Merge #2613 2613: test_gem.rb - intermittent failure fix r=hsbt a=MSP-Greg # Description: Update assert_self_install_permissions method to hopefully stop intermittent failures File.open -> File.write, move directory creation to top # Tasks: - [X] Describe the problem / feature - [ ] Write tests - [X] Write code to solve the problem - [ ] Get code review from coworkers / friends I will abide by the [code of conduct](https://github.com/rubygems/rubygems/blob/master/CODE_OF_CONDUCT.md). Co-authored-by: MSP-Greg --- test/rubygems/test_gem.rb | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index e740a5ab..a5e4c28d 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -166,15 +166,12 @@ def assert_self_install_permissions } Dir.chdir @tempdir do Dir.mkdir 'bin' - File.open 'bin/foo.cmd', 'w' do |fp| - fp.chmod(0755) - fp.puts 'p' - end - Dir.mkdir 'data' - File.open 'data/foo.txt', 'w' do |fp| - fp.puts 'blah' - end + + File.write 'bin/foo.cmd', "p\n" + File.chmod 0755, 'bin/foo.cmd' + + File.write 'data/foo.txt', "blah\n" spec_fetcher do |f| f.gem 'foo', 1 do |s| From e49e763a892b87e210fee62e40aac90359ae2fc8 Mon Sep 17 00:00:00 2001 From: Bundlerbot Date: Thu, 2 May 2019 10:25:59 +0000 Subject: [PATCH 533/707] Merge #2756 2756: Added supported versions of Ruby. r=hsbt a=hsbt # Description: Fixes #2586 ______________ # Tasks: - [ ] Describe the problem / feature - [ ] Write tests - [ ] Write code to solve the problem - [ ] Get code review from coworkers / friends I will abide by the [code of conduct](https://github.com/rubygems/rubygems/blob/master/CODE_OF_CONDUCT.md). Co-authored-by: Hiroshi SHIBATA --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index 158abc09..2d2c452b 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,12 @@ Finally, inside your Ruby program, load the Nokogiri gem and start parsing your For more information about how to use RubyGems, see our RubyGems basics guide at [guides.rubygems.org](http://guides.rubygems.org/rubygems-basics/) +## Requirements + +* RubyGems 2.6 supports Ruby 2.4 or lower. +* RubyGems 2.7 supports Ruby 2.5 or lower. +* RubyGems 3.0 supports Ruby 2.3 or later. + ## Installation RubyGems is likely already installed in your Ruby environment, you can check by running `gem --version` in your terminal emulator. From cb4ae73b169c911555ae7a04b0ffb196e599ec63 Mon Sep 17 00:00:00 2001 From: MSP-Greg Date: Tue, 19 Dec 2017 18:13:28 -0600 Subject: [PATCH 534/707] Update for compatibilty with new minitest --- test/rubygems/test_gem.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 80d11974..4bb2acc2 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1625,7 +1625,7 @@ def test_register_default_spec assert_equal old_style, Gem.find_unresolved_default_spec("foo.rb") assert_equal old_style, Gem.find_unresolved_default_spec("bar.rb") - assert_equal nil, Gem.find_unresolved_default_spec("baz.rb") + assert_nil Gem.find_unresolved_default_spec("baz.rb") Gem.clear_default_specs @@ -1638,8 +1638,8 @@ def test_register_default_spec assert_equal new_style, Gem.find_unresolved_default_spec("foo.rb") assert_equal new_style, Gem.find_unresolved_default_spec("bar.rb") - assert_equal nil, Gem.find_unresolved_default_spec("exec") - assert_equal nil, Gem.find_unresolved_default_spec("README") + assert_nil Gem.find_unresolved_default_spec("exec") + assert_nil Gem.find_unresolved_default_spec("README") end def test_default_gems_use_full_paths From 9fdda89bbf97ea2cc21e26216f9719d6a30514c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Thu, 20 Jun 2019 13:10:06 +0200 Subject: [PATCH 535/707] Silence deprecations when gemdeps is used in tests Because we can't control 3rd party gems using deprecated rubygems behavior, and thus outputting warnings to the screen. --- test/rubygems/test_gem.rb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index c90ad2d4..d59cedc0 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1786,8 +1786,10 @@ def test_use_gemdeps_missing_gem EXPECTED - assert_output nil, expected do - Gem.use_gemdeps + Gem::Deprecate.skip_during do + assert_output nil, expected do + Gem.use_gemdeps + end end ensure ENV['RUBYGEMS_GEMDEPS'] = rubygems_gemdeps From efe3b4858c34c12334b77b263166127d71d2b0e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Thu, 28 Mar 2019 16:46:13 +0100 Subject: [PATCH 536/707] Check for straneous quotes And use single quotes consistenly. --- bundler/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bundler/README.md b/bundler/README.md index da7fd7c2..13bc8f4f 100644 --- a/bundler/README.md +++ b/bundler/README.md @@ -48,7 +48,7 @@ If you'd like to contribute to Bundler, that's awesome, and we <3 you. We've put If you'd like to request a substantial change to Bundler or to the Bundler documentation, refer to the [Bundler RFC process](https://github.com/bundler/rfcs) for more information. -While some Bundler contributors are compensated by Ruby Together, the project maintainers make decisions independent of Ruby Together. As a project, we welcome contributions regardless of the author’s affiliation with Ruby Together. +While some Bundler contributors are compensated by Ruby Together, the project maintainers make decisions independent of Ruby Together. As a project, we welcome contributions regardless of the author's affiliation with Ruby Together. ### Supporting @@ -57,7 +57,7 @@ While some Bundler contributors are compensated by Ruby Together, the project ma ### Code of Conduct -Everyone interacting in the Bundler project’s codebases, issue trackers, chat rooms, and mailing lists is expected to follow the [Bundler code of conduct](https://github.com/bundler/bundler/blob/master/CODE_OF_CONDUCT.md). +Everyone interacting in the Bundler project's codebases, issue trackers, chat rooms, and mailing lists is expected to follow the [Bundler code of conduct](https://github.com/bundler/bundler/blob/master/CODE_OF_CONDUCT.md). ### License From 39767894c58a8888fe68eb7660a9f5d7da472823 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Wed, 24 Jul 2019 13:24:18 +0900 Subject: [PATCH 537/707] Resolve `@@project_dir` from test file paths `Dir.pwd` may differ from the source path. Test directories and files should be resolved from test file paths. --- test/rubygems/test_gem.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index d59cedc0..b4dfa92d 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -17,6 +17,8 @@ class TestGem < Gem::TestCase PLUGINS_LOADED = [] # rubocop:disable Style/MutableConstant + @@project_dir = File.expand_path('../../..', __FILE__).untaint + def setup super From 0e0229bf10ce4510dd6799df52146c4bffbc3ce7 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Wed, 24 Jul 2019 13:57:59 +0900 Subject: [PATCH 538/707] Make `@@project_dir` constants per files --- test/rubygems/test_gem.rb | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index b4dfa92d..f409453c 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -17,7 +17,7 @@ class TestGem < Gem::TestCase PLUGINS_LOADED = [] # rubocop:disable Style/MutableConstant - @@project_dir = File.expand_path('../../..', __FILE__).untaint + PROJECT_DIR = File.expand_path('../../..', __FILE__).untaint def setup super @@ -632,7 +632,7 @@ def test_self_extension_dir_static end def test_self_find_files - cwd = File.expand_path("test/rubygems", @@project_dir) + cwd = File.expand_path("test/rubygems", PROJECT_DIR) $LOAD_PATH.unshift cwd discover_path = File.join 'lib', 'sff', 'discover.rb' @@ -652,7 +652,7 @@ def test_self_find_files Gem.refresh expected = [ - File.expand_path('test/rubygems/sff/discover.rb', @@project_dir), + File.expand_path('test/rubygems/sff/discover.rb', PROJECT_DIR), File.join(foo2.full_gem_path, discover_path), File.join(foo1.full_gem_path, discover_path), ] @@ -664,7 +664,7 @@ def test_self_find_files end def test_self_find_files_with_gemfile - cwd = File.expand_path("test/rubygems", @@project_dir) + cwd = File.expand_path("test/rubygems", PROJECT_DIR) actual_load_path = $LOAD_PATH.unshift(cwd).dup discover_path = File.join 'lib', 'sff', 'discover.rb' @@ -689,7 +689,7 @@ def test_self_find_files_with_gemfile Gem.use_gemdeps(File.join Dir.pwd, 'Gemfile') expected = [ - File.expand_path('test/rubygems/sff/discover.rb', @@project_dir), + File.expand_path('test/rubygems/sff/discover.rb', PROJECT_DIR), File.join(foo1.full_gem_path, discover_path) ].sort @@ -700,7 +700,7 @@ def test_self_find_files_with_gemfile end def test_self_find_latest_files - cwd = File.expand_path("test/rubygems", @@project_dir) + cwd = File.expand_path("test/rubygems", PROJECT_DIR) $LOAD_PATH.unshift cwd discover_path = File.join 'lib', 'sff', 'discover.rb' @@ -720,7 +720,7 @@ def test_self_find_latest_files Gem.refresh expected = [ - File.expand_path('test/rubygems/sff/discover.rb', @@project_dir), + File.expand_path('test/rubygems/sff/discover.rb', PROJECT_DIR), File.join(foo2.full_gem_path, discover_path), ] @@ -872,12 +872,12 @@ def test_self_platforms end def test_self_prefix - assert_equal @@project_dir, Gem.prefix + assert_equal PROJECT_DIR, Gem.prefix end def test_self_prefix_libdir orig_libdir = RbConfig::CONFIG['libdir'] - RbConfig::CONFIG['libdir'] = @@project_dir + RbConfig::CONFIG['libdir'] = PROJECT_DIR assert_nil Gem.prefix ensure @@ -886,7 +886,7 @@ def test_self_prefix_libdir def test_self_prefix_sitelibdir orig_sitelibdir = RbConfig::CONFIG['sitelibdir'] - RbConfig::CONFIG['sitelibdir'] = @@project_dir + RbConfig::CONFIG['sitelibdir'] = PROJECT_DIR assert_nil Gem.prefix ensure @@ -1869,7 +1869,7 @@ def with_clean_path_to_ruby def with_plugin(path) test_plugin_path = File.expand_path("test/rubygems/plugin/#{path}", - @@project_dir) + PROJECT_DIR) # A single test plugin should get loaded once only, in order to preserve # sane test semantics. From 879e87ef5a79b6021f490ca308445a121451ae5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Mon, 7 Jan 2019 12:00:35 +0100 Subject: [PATCH 539/707] Autoswitch to exact bundler version if present --- test/rubygems/test_gem.rb | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index f409453c..b2506840 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -341,6 +341,40 @@ def test_activate_bin_path_gives_proper_error_for_bundler refute_includes e.message, "can't find gem bundler (>= 0.a) with executable bundle" end + def test_activate_bin_path_selects_exact_bundler_version_if_present + bundler_latest = util_spec 'bundler', '2.0.1' do |s| + s.executables = ['bundle'] + end + + bundler_previous = util_spec 'bundler', '2.0.0' do |s| + s.executables = ['bundle'] + end + + install_specs bundler_latest, bundler_previous + + File.open("Gemfile.lock", "w") do |f| + f.write <<-L.gsub(/ {8}/, "") + GEM + remote: https://rubygems.org/ + specs: + + PLATFORMS + ruby + + DEPENDENCIES + + BUNDLED WITH + 2.0.0 + L + end + + File.open("Gemfile", "w") { |f| f.puts('source "https://rubygems.org"') } + + load Gem.activate_bin_path("bundler", "bundle", ">= 0.a") + + assert_equal %w(bundler-2.0.0), loaded_spec_names + end + def test_self_bin_path_no_exec_name e = assert_raises ArgumentError do Gem.bin_path 'a' From b4e6d67d451630539104151a253df9ee73cb071e Mon Sep 17 00:00:00 2001 From: Takayuki Nakata Date: Fri, 9 Aug 2019 23:08:23 +0900 Subject: [PATCH 540/707] Fix documents to refer to URLs with https --- bundler/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bundler/README.md b/bundler/README.md index 13bc8f4f..cd17cd4c 100644 --- a/bundler/README.md +++ b/bundler/README.md @@ -1,7 +1,7 @@ [![Version ](https://img.shields.io/gem/v/bundler.svg?style=flat)](https://rubygems.org/gems/bundler) [![Build Status](https://img.shields.io/travis/bundler/bundler/master.svg?style=flat)](https://travis-ci.org/bundler/bundler) -[![Inline docs ](http://inch-ci.org/github/bundler/bundler.svg?style=flat)](http://inch-ci.org/github/bundler/bundler) -[![Slack ](http://bundler-slackin.herokuapp.com/badge.svg)](http://bundler-slackin.herokuapp.com) +[![Inline docs ](https://inch-ci.org/github/bundler/bundler.svg?style=flat)](https://inch-ci.org/github/bundler/bundler) +[![Slack ](https://bundler-slackin.herokuapp.com/badge.svg)](https://bundler-slackin.herokuapp.com) # Bundler: a gem to bundle gems From 09e6f9a452ddb49fa1a995025618be066fc7be96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Tue, 10 Sep 2019 11:07:03 +0200 Subject: [PATCH 541/707] Fix underscore version for bundler itself Previously it wouldn't play nice with the bundler version finder. --- test/rubygems/test_gem.rb | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index b2506840..110eef6c 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -375,6 +375,40 @@ def test_activate_bin_path_selects_exact_bundler_version_if_present assert_equal %w(bundler-2.0.0), loaded_spec_names end + def test_activate_bin_path_respects_underscore_selection_if_given + bundler_latest = util_spec 'bundler', '2.0.1' do |s| + s.executables = ['bundle'] + end + + bundler_previous = util_spec 'bundler', '1.17.3' do |s| + s.executables = ['bundle'] + end + + install_specs bundler_latest, bundler_previous + + File.open("Gemfile.lock", "w") do |f| + f.write <<-L.gsub(/ {8}/, "") + GEM + remote: https://rubygems.org/ + specs: + + PLATFORMS + ruby + + DEPENDENCIES + + BUNDLED WITH + 2.0.1 + L + end + + File.open("Gemfile", "w") { |f| f.puts('source "https://rubygems.org"') } + + load Gem.activate_bin_path("bundler", "bundle", "= 1.17.3") + + assert_equal %w(bundler-1.17.3), loaded_spec_names + end + def test_self_bin_path_no_exec_name e = assert_raises ArgumentError do Gem.bin_path 'a' From 359d1ab45b9c2c7a05125289f735cdb46c9cc665 Mon Sep 17 00:00:00 2001 From: bronzdoc Date: Thu, 19 Sep 2019 06:10:03 -0600 Subject: [PATCH 542/707] Update MAINTAINERS.txt --- MAINTAINERS.txt | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/MAINTAINERS.txt b/MAINTAINERS.txt index d7ae6bdb..2cc2acff 100644 --- a/MAINTAINERS.txt +++ b/MAINTAINERS.txt @@ -1,13 +1,8 @@ Luis Sagastume (@bronzdoc) -Jeremy Hinegardner (@copiousfreetime) Daniel Berger (@djberg96) Ellen Marie Dash (@duckinator) Evan Phoenix (@evanphx) SHIBATA Hiroshi (@hsbt) André Arko (@indirect) -Kurtis Rainbolt-Greene (@krainboltgreene) -Luis Lavena (@luislavena) Samuel Giddins (@segiddins) -Aaron Patterson (@tenderlove) -Zachary Scott (@zzak) -Akira Matsuda (@amatsuda) +David Rodríguez (@deivid-rodriguez) From e8c473b76af4432bc97f224e40c93616edb14112 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Wed, 16 Oct 2019 23:00:42 +0900 Subject: [PATCH 543/707] Set up instance variables before freezing Fixes #2948 --- test/rubygems/test_gem_version.rb | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/rubygems/test_gem_version.rb b/test/rubygems/test_gem_version.rb index c90648f5..eb5a25ea 100644 --- a/test/rubygems/test_gem_version.rb +++ b/test/rubygems/test_gem_version.rb @@ -217,6 +217,11 @@ def test_canonical_segments assert_equal [1, 2, 3, "pre", 1], v("1.2.3-1").canonical_segments end + def test_frozen_version + v = v('1.freeze.test').freeze + assert_less_than v, v('1') + end + # Asserts that +version+ is a prerelease. def assert_prerelease(version) From 63098b6bd85444faa8ade5d336a0338b845aa92d Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Wed, 16 Oct 2019 23:01:20 +0900 Subject: [PATCH 544/707] Moved relationship between instances to class variables Fixes #2948 --- test/rubygems/test_gem_version.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/rubygems/test_gem_version.rb b/test/rubygems/test_gem_version.rb index eb5a25ea..1deecc0e 100644 --- a/test/rubygems/test_gem_version.rb +++ b/test/rubygems/test_gem_version.rb @@ -220,6 +220,8 @@ def test_canonical_segments def test_frozen_version v = v('1.freeze.test').freeze assert_less_than v, v('1') + assert_version_equal v('1'), v.release + assert_version_equal v('2'), v.bump end # Asserts that +version+ is a prerelease. From 6eee6c8fa92dd41d4aff9c296fffdca3aacc9fc9 Mon Sep 17 00:00:00 2001 From: Jeremy Evans Date: Fri, 18 Oct 2019 13:08:18 -0700 Subject: [PATCH 545/707] Remove taint usage on Ruby 2.7+ Ruby 2.7 deprecates taint and it no longer has an effect. This attempts to leave the behavior the same on older Ruby versions, but avoid the use of deprecated methods related to taint on Ruby 2.7+. See https://bugs.ruby-lang.org/issues/16131 for details. --- test/rubygems/test_gem.rb | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 110eef6c..f2821705 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -10,14 +10,14 @@ # TODO: push this up to test_case.rb once battle tested $LOAD_PATH.map! do |path| - path.dup.untaint + path.dup.tap(&Gem::UNTAINT) end class TestGem < Gem::TestCase PLUGINS_LOADED = [] # rubocop:disable Style/MutableConstant - PROJECT_DIR = File.expand_path('../../..', __FILE__).untaint + PROJECT_DIR = File.expand_path('../../..', __FILE__).tap(&Gem::UNTAINT) def setup super @@ -216,7 +216,7 @@ def assert_self_install_permissions(format_executable: false) end assert_equal(expected, result) ensure - File.chmod(0755, *Dir.glob(@gemhome + '/gems/**/').map {|path| path.untaint}) + File.chmod(0755, *Dir.glob(@gemhome + '/gems/**/').map {|path| path.tap(&Gem::UNTAINT)}) end def test_require_missing @@ -1613,8 +1613,8 @@ def test_auto_activation_of_used_gemdeps_file assert_equal expected_specs, Gem.use_gemdeps.sort_by { |s| s.name } end - LIB_PATH = File.expand_path "../../../lib".dup.untaint, __FILE__.dup.untaint - BUNDLER_LIB_PATH = File.expand_path $LOAD_PATH.find {|lp| File.file?(File.join(lp, "bundler.rb")) }.dup.untaint + LIB_PATH = File.expand_path "../../../lib".dup.tap(&Gem::UNTAINT), __FILE__.dup.tap(&Gem::UNTAINT) + BUNDLER_LIB_PATH = File.expand_path $LOAD_PATH.find {|lp| File.file?(File.join(lp, "bundler.rb")) }.dup.tap(&Gem::UNTAINT) BUNDLER_FULL_NAME = "bundler-#{Bundler::VERSION}".freeze def add_bundler_full_name(names) @@ -1641,8 +1641,8 @@ def test_looks_for_gemdeps_files_automatically_on_start ENV['RUBYGEMS_GEMDEPS'] = "-" path = File.join @tempdir, "gem.deps.rb" - cmd = [Gem.ruby.dup.untaint, "-I#{LIB_PATH.untaint}", - "-I#{BUNDLER_LIB_PATH.untaint}", "-rrubygems"] + cmd = [Gem.ruby.dup.tap(&Gem::UNTAINT), "-I#{LIB_PATH.tap(&Gem::UNTAINT)}", + "-I#{BUNDLER_LIB_PATH.tap(&Gem::UNTAINT)}", "-rrubygems"] cmd << "-eputs Gem.loaded_specs.values.map(&:full_name).sort" File.open path, "w" do |f| @@ -1679,8 +1679,8 @@ def test_looks_for_gemdeps_files_automatically_on_start_in_parent_dir Dir.mkdir "sub1" path = File.join @tempdir, "gem.deps.rb" - cmd = [Gem.ruby.dup.untaint, "-Csub1", "-I#{LIB_PATH.untaint}", - "-I#{BUNDLER_LIB_PATH.untaint}", "-rrubygems"] + cmd = [Gem.ruby.dup.tap(&Gem::UNTAINT), "-Csub1", "-I#{LIB_PATH.tap(&Gem::UNTAINT)}", + "-I#{BUNDLER_LIB_PATH.tap(&Gem::UNTAINT)}", "-rrubygems"] cmd << "-eputs Gem.loaded_specs.values.map(&:full_name).sort" File.open path, "w" do |f| @@ -1728,7 +1728,7 @@ def test_register_default_spec end def test_use_gemdeps - gem_deps_file = 'gem.deps.rb'.untaint + gem_deps_file = 'gem.deps.rb'.tap(&Gem::UNTAINT) spec = util_spec 'a', 1 install_specs spec From fdc793ae49e915c466d9f6f5410bcbfc057babba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Tue, 22 Oct 2019 17:39:35 +0200 Subject: [PATCH 546/707] Remove CI badges from README One of the points of using bors-ng is that you don't need badges, master should always be green. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2d2c452b..2f5a9ea0 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# RubyGems [![Travis Build Status](https://secure.travis-ci.org/rubygems/rubygems.svg?branch=master)](http://travis-ci.org/rubygems/rubygems) [![Appveyor Build Status](https://ci.appveyor.com/api/projects/status/github/rubygems/rubygems?branch=master&svg=true)](https://ci.appveyor.com/project/rubygems/rubygems?branch=master) [![Maintainability](https://api.codeclimate.com/v1/badges/30f913e9c2dd932132c1/maintainability)](https://codeclimate.com/github/rubygems/rubygems/maintainability) +# RubyGems [![Maintainability](https://api.codeclimate.com/v1/badges/30f913e9c2dd932132c1/maintainability)](https://codeclimate.com/github/rubygems/rubygems/maintainability) RubyGems is a package management framework for Ruby. From ae9b94e51700fd4f16c18dfe4bfc0734c4517a31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Wed, 30 Oct 2019 17:48:16 +0100 Subject: [PATCH 547/707] Fix some realworld specs testing nothing This helper was printing nothing to the standard output, so the specs were just checking if lockfiles contained the empty string, which is obviously true. --- bundler/spec/realworld/edgecases_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index 6468ee7f..d8997fdb 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -15,7 +15,7 @@ def rubygems_version(name, requirement) raise "Could not find #{name} (#{requirement}) on rubygems.org!\n" \ "Found specs:\n\#{index.send(:specs).inspect}" end - "#{name} (\#{rubygem.version})" + puts "#{name} (\#{rubygem.version})" RUBY end From 8a815d29e1ddf98cd401b4c58a1f652982dde2c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Wed, 30 Oct 2019 15:42:08 +0100 Subject: [PATCH 548/707] Don't silence the UI by default --- bundler/spec/realworld/edgecases_spec.rb | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index 6468ee7f..26dd096b 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -7,10 +7,12 @@ def rubygems_version(name, requirement) require "bundler" require "bundler/source/rubygems/remote" require "bundler/fetcher" - source = Bundler::Source::Rubygems::Remote.new(URI("https://rubygems.org")) - fetcher = Bundler::Fetcher.new(source) - index = fetcher.specs([#{name.dump}], nil) - rubygem = index.search(Gem::Dependency.new(#{name.dump}, #{requirement.dump})).last + rubygem = Bundler.ui.silence do + source = Bundler::Source::Rubygems::Remote.new(URI("https://rubygems.org")) + fetcher = Bundler::Fetcher.new(source) + index = fetcher.specs([#{name.dump}], nil) + index.search(Gem::Dependency.new(#{name.dump}, #{requirement.dump})).last + end if rubygem.nil? raise "Could not find #{name} (#{requirement}) on rubygems.org!\n" \ "Found specs:\n\#{index.send(:specs).inspect}" From d321c91dda3602bd6cbf7ae58d22274eceb2dbc9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Wed, 30 Oct 2019 17:46:50 +0100 Subject: [PATCH 549/707] Normalize some test requires --- bundler/spec/realworld/edgecases_spec.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index c7ec814d..5a7d2c57 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -3,10 +3,10 @@ RSpec.describe "real world edgecases", :realworld => true, :sometimes => true do def rubygems_version(name, requirement) ruby! <<-RUBY - require #{File.expand_path("../../support/artifice/vcr.rb", __FILE__).dump} - require "bundler" - require "bundler/source/rubygems/remote" - require "bundler/fetcher" + require "#{spec}/support/artifice/vcr" + require "#{lib}/bundler" + require "#{lib}/bundler/source/rubygems/remote" + require "#{lib}/bundler/fetcher" rubygem = Bundler.ui.silence do source = Bundler::Source::Rubygems::Remote.new(URI("https://rubygems.org")) fetcher = Bundler::Fetcher.new(source) From befe745ae0b9bbc53827c5eaba1d96c230f502ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Wed, 30 Oct 2019 18:06:49 +0100 Subject: [PATCH 550/707] Remove `spec` helper in favor of `spec_dir` The `spec` name is too common inside specs for `Gem::Specification`'s. --- bundler/spec/realworld/edgecases_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index 5a7d2c57..dfddd124 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -3,7 +3,7 @@ RSpec.describe "real world edgecases", :realworld => true, :sometimes => true do def rubygems_version(name, requirement) ruby! <<-RUBY - require "#{spec}/support/artifice/vcr" + require "#{spec_dir}/support/artifice/vcr" require "#{lib}/bundler" require "#{lib}/bundler/source/rubygems/remote" require "#{lib}/bundler/fetcher" From 545aa6cbfc60d1badb91dfd96be580edaa847f54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Wed, 30 Oct 2019 18:23:54 +0100 Subject: [PATCH 551/707] Rename `lib` to `lib_dir` For consistency with `spec_dir`. --- bundler/spec/realworld/edgecases_spec.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index dfddd124..53d9f9a0 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -4,9 +4,9 @@ def rubygems_version(name, requirement) ruby! <<-RUBY require "#{spec_dir}/support/artifice/vcr" - require "#{lib}/bundler" - require "#{lib}/bundler/source/rubygems/remote" - require "#{lib}/bundler/fetcher" + require "#{lib_dir}/bundler" + require "#{lib_dir}/bundler/source/rubygems/remote" + require "#{lib_dir}/bundler/fetcher" rubygem = Bundler.ui.silence do source = Bundler::Source::Rubygems::Remote.new(URI("https://rubygems.org")) fetcher = Bundler::Fetcher.new(source) From d64d2beb9b463eedcfc2453c00554efc6428653f Mon Sep 17 00:00:00 2001 From: Kazuhiro NISHIYAMA Date: Fri, 8 Nov 2019 14:01:07 +0900 Subject: [PATCH 552/707] Fix typos Found by misspell. --- test/rubygems/test_gem_version.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/rubygems/test_gem_version.rb b/test/rubygems/test_gem_version.rb index 1deecc0e..30b9376e 100644 --- a/test/rubygems/test_gem_version.rb +++ b/test/rubygems/test_gem_version.rb @@ -236,7 +236,7 @@ def assert_approximate_equal(expected, version) assert_equal expected, v(version).approximate_recommendation end - # Assert that the "approximate" recommendation for +version+ satifies +version+. + # Assert that the "approximate" recommendation for +version+ satisfies +version+. def assert_approximate_satisfies_itself(version) gem_version = v(version) From 4b5270f795a27fb05d9896668861d2d306e8ee8f Mon Sep 17 00:00:00 2001 From: Yusuke Endoh Date: Tue, 29 Oct 2019 14:34:31 +0900 Subject: [PATCH 553/707] test/rubygems/test_gem.rb: early failure when there is /tmp/Gemfile Some test cases in rubygems assume that /tmp/Gemfile does not exist. If it does, they fail with very difficult-to-understand message: ``` [ 149/2108] TestGemBundlerVersionFinder#test_bundler_version_with_bundle_update_bundler = 0.00 1) Failure: TestGemBundlerVersionFinder#test_bundler_version_with_bundle_update_bundler [/home/mame/work/ruby/test/rubygems/test_gem_bundler_version_finder.rb:38]: Expected Gem::Version.new("2.0.2") to be nil. ``` I spent one hour to debug this issue. To prevent the same accident, this change makes the test suite stop when /tmp/Gemfile explicitly. --- test/rubygems/test_gem.rb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index f2821705..859aba65 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -7,6 +7,10 @@ require 'tmpdir' require 'rbconfig' +if File.exist?(File.join(Dir.tmpdir, "Gemfile")) + raise "rubygems/bundler tests do not work correctly if there is #{ File.join(Dir.tmpdir, "Gemfile") }" +end + # TODO: push this up to test_case.rb once battle tested $LOAD_PATH.map! do |path| From 02eab5cd54d52ed6504a3b38956da497ae04762d Mon Sep 17 00:00:00 2001 From: Lindsay Salisbury Date: Thu, 21 Nov 2019 08:01:26 -0800 Subject: [PATCH 554/707] Add top-level OSS repo contents Summary: Add initial top-level OSS repo contents. More content coming, this is just to get started. Reviewed By: snarkmaster Differential Revision: D18571140 fbshipit-source-id: 28dcc23830d9da41a6e8f2eb3266ee3f5d462251 --- LICENSE | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..b96dcb04 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) Facebook, Inc. and its affiliates. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. From 0c838ff2c7c14c570706c120f6ac6f8e9e5ceb6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Tue, 26 Nov 2019 11:47:43 +0100 Subject: [PATCH 555/707] Use vendorized version of uri library --- bundler/spec/realworld/edgecases_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index 53d9f9a0..a91e6a35 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -8,7 +8,7 @@ def rubygems_version(name, requirement) require "#{lib_dir}/bundler/source/rubygems/remote" require "#{lib_dir}/bundler/fetcher" rubygem = Bundler.ui.silence do - source = Bundler::Source::Rubygems::Remote.new(URI("https://rubygems.org")) + source = Bundler::Source::Rubygems::Remote.new(Bundler::URI("https://rubygems.org")) fetcher = Bundler::Fetcher.new(source) index = fetcher.specs([#{name.dump}], nil) index.search(Gem::Dependency.new(#{name.dump}, #{requirement.dump})).last From c81d59a088d136c6a3a930b64764676404a5fd24 Mon Sep 17 00:00:00 2001 From: Kazuhiro NISHIYAMA Date: Tue, 10 Dec 2019 18:31:01 +0900 Subject: [PATCH 556/707] Do not load files in build directory related https://bugs.ruby-lang.org/issues/16177 --- test/rubygems/test_gem.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 859aba65..47ef8a3a 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1388,7 +1388,7 @@ def test_self_needs_picks_up_unresolved_deps a = util_spec "a", "1" b = util_spec "b", "1", "c" => nil c = util_spec "c", "2" - d = util_spec "d", "1", {'e' => '= 1'}, "lib/d.rb" + d = util_spec "d", "1", {'e' => '= 1'}, "lib/d#{$$}.rb" e = util_spec "e", "1" install_specs a, c, b, e, d @@ -1397,7 +1397,7 @@ def test_self_needs_picks_up_unresolved_deps r.gem "a" r.gem "b", "= 1" - require 'd' + require "d#{$$}" end assert_equal %w!a-1 b-1 c-2 d-1 e-1!, loaded_spec_names From 7ddff0a3cacc3bea874462b208eaaf25a50121d7 Mon Sep 17 00:00:00 2001 From: Kazuhiro NISHIYAMA Date: Tue, 10 Dec 2019 23:01:23 +0900 Subject: [PATCH 557/707] Do not load q.rb in build directory --- test/rubygems/test_gem.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 47ef8a3a..a0debb48 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -226,7 +226,7 @@ def assert_self_install_permissions(format_executable: false) def test_require_missing save_loaded_features do assert_raises ::LoadError do - require "q" + require "test_require_missing" end end end From 71c853151f9097bd9a986196f76ffcda2f104e85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Mon, 16 Dec 2019 14:01:33 +0100 Subject: [PATCH 558/707] Extract a couple of test utility methods --- test/rubygems/test_gem.rb | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index a0debb48..6d223b7d 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1917,16 +1917,11 @@ def ruby_install_name(name) end def with_bindir_and_exeext(bindir, exeext) - orig_bindir = RbConfig::CONFIG['bindir'] - orig_exe_ext = RbConfig::CONFIG['EXEEXT'] - - RbConfig::CONFIG['bindir'] = bindir - RbConfig::CONFIG['EXEEXT'] = exeext - - yield - ensure - RbConfig::CONFIG['bindir'] = orig_bindir - RbConfig::CONFIG['EXEEXT'] = orig_exe_ext + bindir(bindir) do + exeext(exeext) do + yield + end + end end def with_clean_path_to_ruby From eede9cdd327698a02662971d6c4611a18fc49110 Mon Sep 17 00:00:00 2001 From: Yusuke Endoh Date: Mon, 23 Dec 2019 11:15:03 +0900 Subject: [PATCH 559/707] Add tests to check if Gem.ruby_version works with ruby git master --- test/rubygems/test_gem.rb | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 6d223b7d..3beedd33 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1090,7 +1090,7 @@ def test_self_ruby_version_with_non_mri_implementations util_restore_RUBY_VERSION end - def test_self_ruby_version_with_prerelease + def test_self_ruby_version_with_svn_prerelease util_set_RUBY_VERSION '2.6.0', -1, 63539, 'ruby 2.6.0preview2 (2018-05-31 trunk 63539) [x86_64-linux]' assert_equal Gem::Version.new('2.6.0.preview2'), Gem.ruby_version @@ -1098,6 +1098,14 @@ def test_self_ruby_version_with_prerelease util_restore_RUBY_VERSION end + def test_self_ruby_version_with_git_prerelease + util_set_RUBY_VERSION '2.7.0', -1, 'b563439274a402e33541f5695b1bfd4ac1085638', 'ruby 2.7.0preview3 (2019-11-23 master b563439274) [x86_64-linux]' + + assert_equal Gem::Version.new('2.7.0.preview3'), Gem.ruby_version + ensure + util_restore_RUBY_VERSION + end + def test_self_ruby_version_with_non_mri_implementations_with_mri_prerelase_compatibility util_set_RUBY_VERSION '2.6.0', -1, 63539, 'weirdjruby 9.2.0.0 (2.6.0preview2) 2018-05-24 81156a8 OpenJDK 64-Bit Server VM 25.171-b11 on 1.8.0_171-8u171-b11-0ubuntu0.16.04.1-b11 [linux-x86_64]', 'weirdjruby', '9.2.0.0' @@ -1106,7 +1114,7 @@ def test_self_ruby_version_with_non_mri_implementations_with_mri_prerelase_compa util_restore_RUBY_VERSION end - def test_self_ruby_version_with_trunk + def test_self_ruby_version_with_svn_trunk util_set_RUBY_VERSION '1.9.2', -1, 23493, 'ruby 1.9.2dev (2009-05-20 trunk 23493) [x86_64-linux]' assert_equal Gem::Version.new('1.9.2.dev'), Gem.ruby_version @@ -1114,6 +1122,14 @@ def test_self_ruby_version_with_trunk util_restore_RUBY_VERSION end + def test_self_ruby_version_with_git_master + util_set_RUBY_VERSION '2.7.0', -1, '5de284ec78220e75643f89b454ce999da0c1c195', 'ruby 2.7.0dev (2019-12-23T01:37:30Z master 5de284ec78) [x86_64-linux]' + + assert_equal Gem::Version.new('2.7.0.dev'), Gem.ruby_version + ensure + util_restore_RUBY_VERSION + end + def test_self_rubygems_version assert_equal Gem::Version.new(Gem::VERSION), Gem.rubygems_version end From a14a30969f0ec52cdd3a4e236bfb6ad779deaa19 Mon Sep 17 00:00:00 2001 From: Po-Chuan Hsieh Date: Sat, 28 Dec 2019 08:52:26 +0000 Subject: [PATCH 560/707] Update links --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 2f5a9ea0..81d29d77 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ A package (also known as a library) contains a set of functionality that can be We call these packages "gems" and RubyGems is a tool to install, create, manage and load these packages in your Ruby environment. RubyGems is also a client for [RubyGems.org](https://rubygems.org), a public repository of Gems that allows you to publish a Gem -that can be shared and used by other developers. See our guide on publishing a Gem at [guides.rubygems.org](http://guides.rubygems.org/publishing/) +that can be shared and used by other developers. See our guide on publishing a Gem at [guides.rubygems.org](https://guides.rubygems.org/publishing/) ## Getting Started @@ -23,7 +23,7 @@ Finally, inside your Ruby program, load the Nokogiri gem and start parsing your Nokogiri.XML('

Hello World

') -For more information about how to use RubyGems, see our RubyGems basics guide at [guides.rubygems.org](http://guides.rubygems.org/rubygems-basics/) +For more information about how to use RubyGems, see our RubyGems basics guide at [guides.rubygems.org](https://guides.rubygems.org/rubygems-basics/) ## Requirements @@ -65,10 +65,10 @@ See [UPGRADING](UPGRADING.md) for more details and alternative instructions. ## Documentation RubyGems uses [rdoc](https://github.com/rdoc/rdoc) for documentation. A compiled set of the docs -can be viewed online at [rubydoc](http://www.rubydoc.info/github/rubygems/rubygems). +can be viewed online at [rubydoc](https://www.rubydoc.info/github/rubygems/rubygems). RubyGems also provides a comprehensive set of guides which covers numerous topics such as -creating a new gem, security practices and other resources at http://guides.rubygems.org +creating a new gem, security practices and other resources at https://guides.rubygems.org ## Getting Help From 52326eb25f1f0ea5f44aeacdc22919a21352197c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Thu, 9 Jan 2020 13:34:31 +0100 Subject: [PATCH 561/707] Make sure to reset Gem.ruby when changed Every time our specs modify either `RbConfig::CONFIG["ruby_install_name"]` or `RbConfig::CONFIG["bindir"]`, we should save the value of `Gem.ruby` prior to modifying it and restore it afterwards, since the value of `Gem.ruby` is inferred from these values and memoized. --- test/rubygems/test_gem.rb | 52 +++++++++++++++------------------------ 1 file changed, 20 insertions(+), 32 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 3beedd33..a2a23ea9 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -161,10 +161,8 @@ def test_self_install_permissions_with_format_executable def test_self_install_permissions_with_format_executable_and_non_standard_ruby_install_name Gem::Installer.exec_format = nil - with_clean_path_to_ruby do - ruby_install_name 'ruby27' do - assert_self_install_permissions(format_executable: true) - end + ruby_install_name 'ruby27' do + assert_self_install_permissions(format_executable: true) end ensure Gem::Installer.exec_format = nil @@ -1024,21 +1022,17 @@ def test_self_refresh_keeps_loaded_specs_activated end def test_self_ruby_escaping_spaces_in_path - with_clean_path_to_ruby do - with_bindir_and_exeext("C:/Ruby 1.8/bin", ".exe") do - ruby_install_name "ruby" do - assert_equal "\"C:/Ruby 1.8/bin/ruby.exe\"", Gem.ruby - end + with_bindir_and_exeext("C:/Ruby 1.8/bin", ".exe") do + ruby_install_name "ruby" do + assert_equal "\"C:/Ruby 1.8/bin/ruby.exe\"", Gem.ruby end end end def test_self_ruby_path_without_spaces - with_clean_path_to_ruby do - with_bindir_and_exeext("C:/Ruby18/bin", ".exe") do - ruby_install_name "ruby" do - assert_equal "C:/Ruby18/bin/ruby.exe", Gem.ruby - end + with_bindir_and_exeext("C:/Ruby18/bin", ".exe") do + ruby_install_name "ruby" do + assert_equal "C:/Ruby18/bin/ruby.exe", Gem.ruby end end end @@ -1920,15 +1914,19 @@ def test_platform_defaults end def ruby_install_name(name) - orig_RUBY_INSTALL_NAME = RbConfig::CONFIG['ruby_install_name'] - RbConfig::CONFIG['ruby_install_name'] = name + with_clean_path_to_ruby do + orig_RUBY_INSTALL_NAME = RbConfig::CONFIG['ruby_install_name'] + RbConfig::CONFIG['ruby_install_name'] = name - yield - ensure - if orig_RUBY_INSTALL_NAME - RbConfig::CONFIG['ruby_install_name'] = orig_RUBY_INSTALL_NAME - else - RbConfig::CONFIG.delete 'ruby_install_name' + begin + yield + ensure + if orig_RUBY_INSTALL_NAME + RbConfig::CONFIG['ruby_install_name'] = orig_RUBY_INSTALL_NAME + else + RbConfig::CONFIG.delete 'ruby_install_name' + end + end end end @@ -1940,16 +1938,6 @@ def with_bindir_and_exeext(bindir, exeext) end end - def with_clean_path_to_ruby - orig_ruby = Gem.ruby - - Gem.instance_variable_set :@ruby, nil - - yield - ensure - Gem.instance_variable_set :@ruby, orig_ruby - end - def with_plugin(path) test_plugin_path = File.expand_path("test/rubygems/plugin/#{path}", PROJECT_DIR) From 9e69c840697554fc8e94aefcb5357c9d31631bb3 Mon Sep 17 00:00:00 2001 From: teitei-tk Date: Fri, 10 Jan 2020 16:55:38 +0900 Subject: [PATCH 562/707] update travis ci build badge url --- bundler/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundler/README.md b/bundler/README.md index cd17cd4c..9353e3d3 100644 --- a/bundler/README.md +++ b/bundler/README.md @@ -1,5 +1,5 @@ [![Version ](https://img.shields.io/gem/v/bundler.svg?style=flat)](https://rubygems.org/gems/bundler) -[![Build Status](https://img.shields.io/travis/bundler/bundler/master.svg?style=flat)](https://travis-ci.org/bundler/bundler) +[![Build Status](https://img.shields.io/travis/rubygems/bundler/master.svg?style=flat)](https://travis-ci.org/rubygems/bundler) [![Inline docs ](https://inch-ci.org/github/bundler/bundler.svg?style=flat)](https://inch-ci.org/github/bundler/bundler) [![Slack ](https://bundler-slackin.herokuapp.com/badge.svg)](https://bundler-slackin.herokuapp.com) From 3ae301be374e36b6d040a9c5c704c93543f52a9e Mon Sep 17 00:00:00 2001 From: Ellen Marie Dash Date: Thu, 16 Jan 2020 18:08:15 -0500 Subject: [PATCH 563/707] [repo move] Update GitHub URL in CODE_OF_CONDUCT.md + README.md. --- bundler/README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/bundler/README.md b/bundler/README.md index 9353e3d3..406300ae 100644 --- a/bundler/README.md +++ b/bundler/README.md @@ -1,6 +1,6 @@ [![Version ](https://img.shields.io/gem/v/bundler.svg?style=flat)](https://rubygems.org/gems/bundler) [![Build Status](https://img.shields.io/travis/rubygems/bundler/master.svg?style=flat)](https://travis-ci.org/rubygems/bundler) -[![Inline docs ](https://inch-ci.org/github/bundler/bundler.svg?style=flat)](https://inch-ci.org/github/bundler/bundler) +[![Inline docs ](https://inch-ci.org/github/rubygems/bundler.svg?style=flat)](https://inch-ci.org/github/rubygems/bundler) [![Slack ](https://bundler-slackin.herokuapp.com/badge.svg)](https://bundler-slackin.herokuapp.com) # Bundler: a gem to bundle gems @@ -44,7 +44,7 @@ To get in touch with the Bundler core team and other Bundler users, please see [ ### Contributing -If you'd like to contribute to Bundler, that's awesome, and we <3 you. We've put together [the Bundler contributor guide](https://github.com/bundler/bundler/blob/master/doc/contributing/README.md) with all of the information you need to get started. +If you'd like to contribute to Bundler, that's awesome, and we <3 you. We've put together [the Bundler contributor guide](https://github.com/rubygems/bundler/blob/master/doc/contributing/README.md) with all of the information you need to get started. If you'd like to request a substantial change to Bundler or to the Bundler documentation, refer to the [Bundler RFC process](https://github.com/bundler/rfcs) for more information. @@ -57,8 +57,8 @@ While some Bundler contributors are compensated by Ruby Together, the project ma ### Code of Conduct -Everyone interacting in the Bundler project's codebases, issue trackers, chat rooms, and mailing lists is expected to follow the [Bundler code of conduct](https://github.com/bundler/bundler/blob/master/CODE_OF_CONDUCT.md). +Everyone interacting in the Bundler project's codebases, issue trackers, chat rooms, and mailing lists is expected to follow the [Bundler code of conduct](https://github.com/rubygems/bundler/blob/master/CODE_OF_CONDUCT.md). ### License -Bundler is available under an [MIT License](https://github.com/bundler/bundler/blob/master/LICENSE.md). +Bundler is available under an [MIT License](https://github.com/rubygems/bundler/blob/master/LICENSE.md). From 5ddc9c16ae42737a44f901abf43609abd19ebf94 Mon Sep 17 00:00:00 2001 From: Ellen Marie Dash Date: Thu, 16 Jan 2020 18:30:29 -0500 Subject: [PATCH 564/707] [repo move] Update GitHub URL in comments and `skip` messages in spec/ --- bundler/spec/realworld/edgecases_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index a91e6a35..48c37093 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -62,7 +62,7 @@ def rubygems_version(name, requirement) end it "is able to update a top-level dependency when there is a conflict on a shared transitive child" do - # from https://github.com/bundler/bundler/issues/5031 + # from https://github.com/rubygems/bundler/issues/5031 gemfile <<-G source "https://rubygems.org" @@ -194,7 +194,7 @@ def rubygems_version(name, requirement) expect(lockfile).to include(rubygems_version("paperclip", "~> 5.1.0")) end - # https://github.com/bundler/bundler/issues/1500 + # https://github.com/rubygems/bundler/issues/1500 it "does not fail install because of gem plugins" do realworld_system_gems("open_gem --version 1.4.2", "rake --version 0.9.2") gemfile <<-G From ec70d2114e2be683a2b377433b3042a69faa73f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Sun, 26 Jan 2020 20:47:11 +0100 Subject: [PATCH 565/707] Cleanup unneeded stuff --- test/rubygems/test_gem.rb | 7 ------- 1 file changed, 7 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index a2a23ea9..2890e13d 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -11,12 +11,6 @@ raise "rubygems/bundler tests do not work correctly if there is #{ File.join(Dir.tmpdir, "Gemfile") }" end -# TODO: push this up to test_case.rb once battle tested - -$LOAD_PATH.map! do |path| - path.dup.tap(&Gem::UNTAINT) -end - class TestGem < Gem::TestCase PLUGINS_LOADED = [] # rubocop:disable Style/MutableConstant @@ -1480,7 +1474,6 @@ def test_load_plugins install_gem foo2 end - Gem.searcher = nil Gem::Specification.reset gem 'foo' From 66780b0821cb6bdae7daf0eb6860ff4e109f2b1c Mon Sep 17 00:00:00 2001 From: Ellen Marie Dash Date: Fri, 17 Jan 2020 16:58:00 -0500 Subject: [PATCH 566/707] Avoid changing $SOURCE_DATE_EPOCH. - Gem.source_date_epoch no longer sets any environment variables. - Gem::Ext::Builder sets $SOURCE_DATE_EPOCH for subprocesses. - If $SOURCE_DATE_EPOCH is unset while the program is running, it reverts to using the time when `Gem.source_date_epoch_string` was first called. - Added test to confirm that `Gem.source_date_epoch` stays stable over time, even when $SOURCE_DATE_EPOCH is not set. - Updated tests that made now-invalid assumptions. - Add slight kludge to two parts of the test suite so `Gem.source_date_epoch` is regenerated for each test. --- test/rubygems/test_gem.rb | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 2890e13d..b473f1de 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1906,6 +1906,24 @@ def test_platform_defaults assert platform_defaults.is_a? Hash end + # Ensure that `Gem.source_date_epoch` is consistent even if + # $SOURCE_DATE_EPOCH has not been set. + def test_default_source_date_epoch_doesnt_change + old_epoch = ENV['SOURCE_DATE_EPOCH'] + ENV['SOURCE_DATE_EPOCH'] = nil + + # Unfortunately, there is no real way to test this aside from waiting + # enough for `Time.now.to_i` to change -- which is a whole second. + # + # Fortunately, we only need to do this once. + a = Gem.source_date_epoch + sleep 1 + b = Gem.source_date_epoch + assert_equal a, b + ensure + ENV['SOURCE_DATE_EPOCH'] = old_epoch + end + def ruby_install_name(name) with_clean_path_to_ruby do orig_RUBY_INSTALL_NAME = RbConfig::CONFIG['ruby_install_name'] From 600ac466d3833e17b0237295a3ccb2708dcbaed2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Tue, 25 Feb 2020 18:31:46 +0100 Subject: [PATCH 567/707] Properly reset state after `Gem.ruby` tests --- test/rubygems/test_gem.rb | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index b473f1de..fd9b3609 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1016,16 +1016,16 @@ def test_self_refresh_keeps_loaded_specs_activated end def test_self_ruby_escaping_spaces_in_path - with_bindir_and_exeext("C:/Ruby 1.8/bin", ".exe") do - ruby_install_name "ruby" do + with_clean_path_to_ruby do + with_rb_config_ruby("C:/Ruby 1.8/bin/ruby.exe") do assert_equal "\"C:/Ruby 1.8/bin/ruby.exe\"", Gem.ruby end end end def test_self_ruby_path_without_spaces - with_bindir_and_exeext("C:/Ruby18/bin", ".exe") do - ruby_install_name "ruby" do + with_clean_path_to_ruby do + with_rb_config_ruby("C:/Ruby18/bin/ruby.exe") do assert_equal "C:/Ruby18/bin/ruby.exe", Gem.ruby end end @@ -1941,11 +1941,24 @@ def ruby_install_name(name) end end - def with_bindir_and_exeext(bindir, exeext) - bindir(bindir) do - exeext(exeext) do - yield - end + def with_rb_config_ruby(path) + rb_config_singleton_class = class << RbConfig; self; end + orig_path = RbConfig.ruby + + redefine_method(rb_config_singleton_class, :ruby, path) + + yield + ensure + redefine_method(rb_config_singleton_class, :ruby, orig_path) + end + + def redefine_method(base, method, new_result) + if RUBY_VERSION >= "2.5" + base.alias_method(method, method) + base.define_method(method) { new_result } + else + base.send(:alias_method, method, method) + base.send(:define_method, method) { new_result } end end From 5dcdafa0ea5259ce6cebdb9722db274bd008bda8 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Fri, 6 Mar 2020 18:44:13 +0900 Subject: [PATCH 568/707] Use GitHub Actions instead of Travis CI on the doc --- bundler/README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/bundler/README.md b/bundler/README.md index 406300ae..7df7e665 100644 --- a/bundler/README.md +++ b/bundler/README.md @@ -1,5 +1,4 @@ [![Version ](https://img.shields.io/gem/v/bundler.svg?style=flat)](https://rubygems.org/gems/bundler) -[![Build Status](https://img.shields.io/travis/rubygems/bundler/master.svg?style=flat)](https://travis-ci.org/rubygems/bundler) [![Inline docs ](https://inch-ci.org/github/rubygems/bundler.svg?style=flat)](https://inch-ci.org/github/rubygems/bundler) [![Slack ](https://bundler-slackin.herokuapp.com/badge.svg)](https://bundler-slackin.herokuapp.com) From 5dd730288e4279051a49e014c73c165f9a9fe6e7 Mon Sep 17 00:00:00 2001 From: Olle Jonsson Date: Mon, 16 Mar 2020 07:36:41 +0100 Subject: [PATCH 569/707] Autoload name_tuple.rb before use MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Resolver asked Molinillo to resolve-then-activate, which led to using Gem::NameTuple before any require had been passed Co-authored-by: David Rodríguez --- test/rubygems/test_gem.rb | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index fd9b3609..bea88b78 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -302,6 +302,21 @@ def test_activate_bin_path_resolves_eagerly assert_equal %w(a-1 b-2 c-1), loaded_spec_names end + def test_activate_bin_path_in_debug_mode + a1 = util_spec 'a', '1' do |s| + s.executables = ['exec'] + end + + install_specs a1 + + output, status = Open3.capture2e( + { "GEM_HOME" => Gem.paths.home, "DEBUG_RESOLVER" => "1" }, + Gem.ruby, "-I", File.expand_path("../../lib", __dir__), "-e", "\"Gem.activate_bin_path('a', 'exec', '>= 0')\"" + ) + + assert status.success?, output + end + def test_activate_bin_path_gives_proper_error_for_bundler bundler = util_spec 'bundler', '2' do |s| s.executables = ['bundle'] From 94faa32d113bd09294b93528688dc7a5b4b63a80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Thu, 19 Mar 2020 20:35:45 +0100 Subject: [PATCH 570/707] Remove bundler submodule references --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 81d29d77..189b51c1 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,7 @@ with your OS's package manager before installing RubyGems manually. If you would like to manually install RubyGems: * Download from https://rubygems.org/pages/download, unpack, and `cd` into RubyGems' src -* OR clone this repository and `cd` into the repository (make sure to run `git submodule update --init`) +* OR clone this repository and `cd` into the repository Install RubyGems by running: From 7ff7261e0b6ac51cb17f44102156f8654dfea23c Mon Sep 17 00:00:00 2001 From: therealpj Date: Fri, 20 Mar 2020 13:04:16 +0530 Subject: [PATCH 571/707] Replace links directing to the old bundler repo with new ones Link to merged repo Link to merged repo The link goes to the bundler good first issues tab. Replace links to merged repo The old links go to the archived bundler repo. They have been replaced with links to the rubygems repo. Replace links to direct to new merged repo Removed leading '+' from link --- bundler/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundler/README.md b/bundler/README.md index 7df7e665..0598dfc1 100644 --- a/bundler/README.md +++ b/bundler/README.md @@ -43,7 +43,7 @@ To get in touch with the Bundler core team and other Bundler users, please see [ ### Contributing -If you'd like to contribute to Bundler, that's awesome, and we <3 you. We've put together [the Bundler contributor guide](https://github.com/rubygems/bundler/blob/master/doc/contributing/README.md) with all of the information you need to get started. +If you'd like to contribute to Bundler, that's awesome, and we <3 you. We've put together [the Bundler contributor guide](https://github.com/rubygems/rubygems/blob/master/bundler/doc/contributing/README.md) with all of the information you need to get started. If you'd like to request a substantial change to Bundler or to the Bundler documentation, refer to the [Bundler RFC process](https://github.com/bundler/rfcs) for more information. From b475348e5550f934f1dfdfdef343b313a7a50bae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Tue, 24 Mar 2020 19:51:43 +0100 Subject: [PATCH 572/707] Enable Style/PercentLiteralDelimiters cop in rubygems So it matches the style used by bundler. --- test/rubygems/test_gem.rb | 40 +++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index bea88b78..645f10b4 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -42,12 +42,12 @@ def test_self_finish_resolve a1.activate - assert_equal %w(a-1), loaded_spec_names + assert_equal %w[a-1], loaded_spec_names assert_equal ["b (> 0)"], unresolved_names Gem.finish_resolve - assert_equal %w(a-1 b-2 c-2), loaded_spec_names + assert_equal %w[a-1 b-2 c-2], loaded_spec_names assert_equal [], unresolved_names end end @@ -66,12 +66,12 @@ def test_self_finish_resolve_wtf a1.activate - assert_equal %w(a-1), loaded_spec_names + assert_equal %w[a-1], loaded_spec_names assert_equal ["b (> 0)", "d (> 0)"], unresolved_names Gem.finish_resolve - assert_equal %w(a-1 b-1 c-1 d-2), loaded_spec_names + assert_equal %w[a-1 b-1 c-1 d-2], loaded_spec_names assert_equal [], unresolved_names end end @@ -89,12 +89,12 @@ def test_self_finish_resolve_respects_loaded_specs a1.activate c1.activate - assert_equal %w(a-1 c-1), loaded_spec_names + assert_equal %w[a-1 c-1], loaded_spec_names assert_equal ["b (> 0)"], unresolved_names Gem.finish_resolve - assert_equal %w(a-1 b-1 c-1), loaded_spec_names + assert_equal %w[a-1 b-1 c-1], loaded_spec_names assert_equal [], unresolved_names end end @@ -299,7 +299,7 @@ def test_activate_bin_path_resolves_eagerly gem 'c' Gem.finish_resolve - assert_equal %w(a-1 b-2 c-1), loaded_spec_names + assert_equal %w[a-1 b-2 c-1], loaded_spec_names end def test_activate_bin_path_in_debug_mode @@ -383,7 +383,7 @@ def test_activate_bin_path_selects_exact_bundler_version_if_present load Gem.activate_bin_path("bundler", "bundle", ">= 0.a") - assert_equal %w(bundler-2.0.0), loaded_spec_names + assert_equal %w[bundler-2.0.0], loaded_spec_names end def test_activate_bin_path_respects_underscore_selection_if_given @@ -417,7 +417,7 @@ def test_activate_bin_path_respects_underscore_selection_if_given load Gem.activate_bin_path("bundler", "bundle", "= 1.17.3") - assert_equal %w(bundler-1.17.3), loaded_spec_names + assert_equal %w[bundler-1.17.3], loaded_spec_names end def test_self_bin_path_no_exec_name @@ -716,7 +716,7 @@ def test_self_find_files discover_path = File.join 'lib', 'sff', 'discover.rb' - foo1, foo2 = %w(1 2).map do |version| + foo1, foo2 = %w[1 2].map do |version| spec = quick_gem 'sff', version do |s| s.files << discover_path end @@ -748,7 +748,7 @@ def test_self_find_files_with_gemfile discover_path = File.join 'lib', 'sff', 'discover.rb' - foo1, _ = %w(1 2).map do |version| + foo1, _ = %w[1 2].map do |version| spec = quick_gem 'sff', version do |s| s.files << discover_path end @@ -784,7 +784,7 @@ def test_self_find_latest_files discover_path = File.join 'lib', 'sff', 'discover.rb' - _, foo2 = %w(1 2).map do |version| + _, foo2 = %w[1 2].map do |version| spec = quick_gem 'sff', version do |s| s.files << discover_path end @@ -1274,7 +1274,7 @@ def test_self_try_activate_missing_dep Gem.try_activate 'a_file' end - assert_match %r%Could not find 'b' %, e.message + assert_match %r{Could not find 'b' }, e.message end def test_self_try_activate_missing_prerelease @@ -1294,7 +1294,7 @@ def test_self_try_activate_missing_prerelease Gem.try_activate 'a_file' end - assert_match %r%Could not find 'b' \(= 1.0rc1\)%, e.message + assert_match %r{Could not find 'b' \(= 1.0rc1\)}, e.message end def test_self_try_activate_missing_extensions @@ -1399,7 +1399,7 @@ def test_self_needs activated = Gem::Specification.map { |x| x.full_name } - assert_equal %w!a-1 b-1 c-2!, activated.sort + assert_equal %w[a-1 b-1 c-2], activated.sort end def test_self_needs_picks_up_unresolved_deps @@ -1419,7 +1419,7 @@ def test_self_needs_picks_up_unresolved_deps require "d#{$$}" end - assert_equal %w!a-1 b-1 c-2 d-1 e-1!, loaded_spec_names + assert_equal %w[a-1 b-1 c-2 d-1 e-1], loaded_spec_names end end @@ -1611,7 +1611,7 @@ def test_auto_activation_of_specific_gemdeps_file Gem.use_gemdeps - assert_equal add_bundler_full_name(%W(a-1 b-1 c-1)), loaded_spec_names + assert_equal add_bundler_full_name(%W[a-1 b-1 c-1]), loaded_spec_names end def test_auto_activation_of_used_gemdeps_file @@ -1765,7 +1765,7 @@ def test_use_gemdeps Gem.use_gemdeps gem_deps_file - assert_equal add_bundler_full_name(%W(a-1)), loaded_spec_names + assert_equal add_bundler_full_name(%W[a-1]), loaded_spec_names refute_nil Gem.gemdeps end @@ -1825,7 +1825,7 @@ def test_use_gemdeps_automatic Gem.use_gemdeps - assert_equal add_bundler_full_name(%W(a-1)), loaded_spec_names + assert_equal add_bundler_full_name(%W[a-1]), loaded_spec_names ensure ENV['RUBYGEMS_GEMDEPS'] = rubygems_gemdeps end @@ -1902,7 +1902,7 @@ def test_use_gemdeps_specific Gem.use_gemdeps - assert_equal add_bundler_full_name(%W(a-1)), loaded_spec_names + assert_equal add_bundler_full_name(%W[a-1]), loaded_spec_names ensure ENV['RUBYGEMS_GEMDEPS'] = rubygems_gemdeps end From a4b79665aaca71ad16eabaf918e2ca9db6fb7367 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Fri, 3 May 2019 19:56:58 +0200 Subject: [PATCH 573/707] Enable `Style/ExtraSpacing` and auto-correct --- test/rubygems/test_gem.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 645f10b4..f61fee9a 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -664,7 +664,7 @@ def test_self_ensure_gem_directories_missing_parents assert_directory_exists util_cache_dir end - unless win_platform? || Process.uid.zero? # only for FS that support write protection + unless win_platform? || Process.uid.zero? # only for FS that support write protection def test_self_ensure_gem_directories_write_protected gemdir = File.join @tempdir, "egd" FileUtils.rm_r gemdir rescue nil From 410e7e3f460fb43520c96576229bcef4aa1ad6fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Sun, 29 Mar 2020 22:05:40 +0200 Subject: [PATCH 574/707] Require open3 before using it Otherwise if this test file is run in isolation, this test will fail. --- test/rubygems/test_gem.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index f61fee9a..c50853a3 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -309,6 +309,7 @@ def test_activate_bin_path_in_debug_mode install_specs a1 + require "open3" output, status = Open3.capture2e( { "GEM_HOME" => Gem.paths.home, "DEBUG_RESOLVER" => "1" }, Gem.ruby, "-I", File.expand_path("../../lib", __dir__), "-e", "\"Gem.activate_bin_path('a', 'exec', '>= 0')\"" From f8d1bb569e0b9b244b87bf2a1873a76694d4a6b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Sun, 29 Mar 2020 21:45:39 +0200 Subject: [PATCH 575/707] Fix incorrect bundler version being required In ruby 2.7.0, there's a slight change in bundler's default gemspec file where the executable folder of the bundler gem is `libexec` instead of `exe`. I made that change in https://github.com/ruby/ruby/pull/2380 to try to simplify the integration of the `bundler` gem with upstream, minimizing the number of changes that need to be made to the gemspec to adapt to the structure of ruby-core. That worked ok, expected for this issue. The new name of the folder including the executable files uncovered a bug in rubygems, which is the following: * In order to be able to use newer versions of default gems, `rubygems` ships with a customized `require` that has knowledge about which files belong to which default gem. If one of these files is required, `rubygems` will detect that and activate its gem mechanism to choose the newest version of the corresponding default gem present in the system (unless a different version has already been activated). It's this part of the custom require: https://github.com/rubygems/rubygems/blob/ea3e6f194df500b028b52b3b64decbd3df1d5ab0/lib/rubygems/core_ext/kernel_require.rb#L77-L85 * In order to do that, `rubygems` registers a map of default gems and their files when it is first required: https://github.com/rubygems/rubygems/blob/ea3e6f194df500b028b52b3b64decbd3df1d5ab0/lib/rubygems.rb#L1247-L1276 As explained in the method's header, two types of default gem specifications are supported. One of the formats is the style used by some ruby-core gemspec files, where paths inside the `spec.files` array don't include the `spec.require_paths` part. So in this "old style", if a gem ships with a `lib/bundler.rb` file, it will be registered in this array as `spec.files = ["bundler.rb"]`, not as `spec.files = ["lib/bundler.rb"]`. The `Gem.register_default_spec` method "detects" this style by making sure that none of the files in the `spec.files` array start with any of the `spec.require_paths`. * Since in ruby 2.7 the default specification file of the `bundler` gem includes a `libexec/bundle` file, this check would no longer work correctly, because even though the specification file is still "old style", it has one registered file which starts with "lib", one of the "require paths" of the gem. * This means that the gem is incorrectly detected as "new style", but since none of the paths start with "lib/", no files are actually registered, so the gem is not being considered a default gem, and thus the default version is always used with no possibility of being "upgraded". The fix of the problem is simple: check that no files start with `lib/` (or any other require paths), instead of with "lib" which doesn't exclude other potential "non requirable folder" starting with lib, like in the `bundler` case. --- test/rubygems/test_gem.rb | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index c50853a3..0df6e237 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1750,6 +1750,18 @@ def test_register_default_spec assert_nil Gem.find_unresolved_default_spec("README") end + def test_register_default_spec_old_style_with_folder_starting_with_lib + Gem.clear_default_specs + + old_style = Gem::Specification.new do |spec| + spec.files = ["libexec/bundle", "foo.rb", "bar.rb"] + end + + Gem.register_default_spec old_style + + assert_equal old_style, Gem.find_unresolved_default_spec("foo.rb") + end + def test_use_gemdeps gem_deps_file = 'gem.deps.rb'.tap(&Gem::UNTAINT) spec = util_spec 'a', 1 From 35fa64656fce89904246bbf11537f1ee0cc26760 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Thu, 2 Apr 2020 19:45:43 +0200 Subject: [PATCH 576/707] Now `Dir.tmpdir` is fixed and there's never such a folder --- test/rubygems/test_gem.rb | 4 ---- 1 file changed, 4 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 0df6e237..f619c759 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -7,10 +7,6 @@ require 'tmpdir' require 'rbconfig' -if File.exist?(File.join(Dir.tmpdir, "Gemfile")) - raise "rubygems/bundler tests do not work correctly if there is #{ File.join(Dir.tmpdir, "Gemfile") }" -end - class TestGem < Gem::TestCase PLUGINS_LOADED = [] # rubocop:disable Style/MutableConstant From e01114a08fe51bf55c83771d3740b23b3ed08fb6 Mon Sep 17 00:00:00 2001 From: DEVRAJ KUMAR <43830009+devraj-kumar@users.noreply.github.com> Date: Tue, 31 Mar 2020 21:31:04 +0530 Subject: [PATCH 577/707] Improve README readability Co-Authored-By: Reece Dunham --- bundler/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundler/README.md b/bundler/README.md index 0598dfc1..5ca8b067 100644 --- a/bundler/README.md +++ b/bundler/README.md @@ -45,7 +45,7 @@ To get in touch with the Bundler core team and other Bundler users, please see [ If you'd like to contribute to Bundler, that's awesome, and we <3 you. We've put together [the Bundler contributor guide](https://github.com/rubygems/rubygems/blob/master/bundler/doc/contributing/README.md) with all of the information you need to get started. -If you'd like to request a substantial change to Bundler or to the Bundler documentation, refer to the [Bundler RFC process](https://github.com/bundler/rfcs) for more information. +If you'd like to request a substantial change to Bundler or its documentation, refer to the [Bundler RFC process](https://github.com/bundler/rfcs) for more information. While some Bundler contributors are compensated by Ruby Together, the project maintainers make decisions independent of Ruby Together. As a project, we welcome contributions regardless of the author's affiliation with Ruby Together. From 77b3fa37870eab828ed624d092b5bdd02515aefc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Wed, 8 Apr 2020 20:56:29 +0200 Subject: [PATCH 578/707] Remove unneeded untainting --- test/rubygems/test_gem.rb | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index f619c759..883e49d9 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1632,8 +1632,8 @@ def test_auto_activation_of_used_gemdeps_file assert_equal expected_specs, Gem.use_gemdeps.sort_by { |s| s.name } end - LIB_PATH = File.expand_path "../../../lib".dup.tap(&Gem::UNTAINT), __FILE__.dup.tap(&Gem::UNTAINT) - BUNDLER_LIB_PATH = File.expand_path $LOAD_PATH.find {|lp| File.file?(File.join(lp, "bundler.rb")) }.dup.tap(&Gem::UNTAINT) + LIB_PATH = File.expand_path "../../../lib".dup, __FILE__.dup + BUNDLER_LIB_PATH = File.expand_path $LOAD_PATH.find {|lp| File.file?(File.join(lp, "bundler.rb")) }.dup BUNDLER_FULL_NAME = "bundler-#{Bundler::VERSION}".freeze def add_bundler_full_name(names) @@ -1660,8 +1660,8 @@ def test_looks_for_gemdeps_files_automatically_on_start ENV['RUBYGEMS_GEMDEPS'] = "-" path = File.join @tempdir, "gem.deps.rb" - cmd = [Gem.ruby.dup.tap(&Gem::UNTAINT), "-I#{LIB_PATH.tap(&Gem::UNTAINT)}", - "-I#{BUNDLER_LIB_PATH.tap(&Gem::UNTAINT)}", "-rrubygems"] + cmd = [Gem.ruby.dup, "-I#{LIB_PATH}", + "-I#{BUNDLER_LIB_PATH}", "-rrubygems"] cmd << "-eputs Gem.loaded_specs.values.map(&:full_name).sort" File.open path, "w" do |f| @@ -1698,8 +1698,8 @@ def test_looks_for_gemdeps_files_automatically_on_start_in_parent_dir Dir.mkdir "sub1" path = File.join @tempdir, "gem.deps.rb" - cmd = [Gem.ruby.dup.tap(&Gem::UNTAINT), "-Csub1", "-I#{LIB_PATH.tap(&Gem::UNTAINT)}", - "-I#{BUNDLER_LIB_PATH.tap(&Gem::UNTAINT)}", "-rrubygems"] + cmd = [Gem.ruby.dup, "-Csub1", "-I#{LIB_PATH}", + "-I#{BUNDLER_LIB_PATH}", "-rrubygems"] cmd << "-eputs Gem.loaded_specs.values.map(&:full_name).sort" File.open path, "w" do |f| From b0f79712a44120f4c96da250ecc98d5fdef1bfaf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Wed, 8 Apr 2020 20:58:32 +0200 Subject: [PATCH 579/707] Remove unneeded dups --- test/rubygems/test_gem.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 883e49d9..cf0c3a13 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1632,8 +1632,8 @@ def test_auto_activation_of_used_gemdeps_file assert_equal expected_specs, Gem.use_gemdeps.sort_by { |s| s.name } end - LIB_PATH = File.expand_path "../../../lib".dup, __FILE__.dup - BUNDLER_LIB_PATH = File.expand_path $LOAD_PATH.find {|lp| File.file?(File.join(lp, "bundler.rb")) }.dup + LIB_PATH = File.expand_path "../../../lib", __FILE__ + BUNDLER_LIB_PATH = File.expand_path $LOAD_PATH.find {|lp| File.file?(File.join(lp, "bundler.rb")) } BUNDLER_FULL_NAME = "bundler-#{Bundler::VERSION}".freeze def add_bundler_full_name(names) @@ -1660,7 +1660,7 @@ def test_looks_for_gemdeps_files_automatically_on_start ENV['RUBYGEMS_GEMDEPS'] = "-" path = File.join @tempdir, "gem.deps.rb" - cmd = [Gem.ruby.dup, "-I#{LIB_PATH}", + cmd = [Gem.ruby, "-I#{LIB_PATH}", "-I#{BUNDLER_LIB_PATH}", "-rrubygems"] cmd << "-eputs Gem.loaded_specs.values.map(&:full_name).sort" @@ -1698,7 +1698,7 @@ def test_looks_for_gemdeps_files_automatically_on_start_in_parent_dir Dir.mkdir "sub1" path = File.join @tempdir, "gem.deps.rb" - cmd = [Gem.ruby.dup, "-Csub1", "-I#{LIB_PATH}", + cmd = [Gem.ruby, "-Csub1", "-I#{LIB_PATH}", "-I#{BUNDLER_LIB_PATH}", "-rrubygems"] cmd << "-eputs Gem.loaded_specs.values.map(&:full_name).sort" From 49bf523909d047c6a9610ecdd03141778e230062 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Wed, 8 Apr 2020 20:59:24 +0200 Subject: [PATCH 580/707] Remove unneeded explicit requires --- test/rubygems/test_gem.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index cf0c3a13..80bc20b2 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1661,7 +1661,7 @@ def test_looks_for_gemdeps_files_automatically_on_start path = File.join @tempdir, "gem.deps.rb" cmd = [Gem.ruby, "-I#{LIB_PATH}", - "-I#{BUNDLER_LIB_PATH}", "-rrubygems"] + "-I#{BUNDLER_LIB_PATH}"] cmd << "-eputs Gem.loaded_specs.values.map(&:full_name).sort" File.open path, "w" do |f| @@ -1699,7 +1699,7 @@ def test_looks_for_gemdeps_files_automatically_on_start_in_parent_dir path = File.join @tempdir, "gem.deps.rb" cmd = [Gem.ruby, "-Csub1", "-I#{LIB_PATH}", - "-I#{BUNDLER_LIB_PATH}", "-rrubygems"] + "-I#{BUNDLER_LIB_PATH}"] cmd << "-eputs Gem.loaded_specs.values.map(&:full_name).sort" File.open path, "w" do |f| From 6548b8b1ee57a54dfdc716c975407495a4f7eaa6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Wed, 8 Apr 2020 21:14:27 +0200 Subject: [PATCH 581/707] Refactor ruby command line building for tests --- test/rubygems/test_gem.rb | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 80bc20b2..b19fd9ce 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -308,7 +308,7 @@ def test_activate_bin_path_in_debug_mode require "open3" output, status = Open3.capture2e( { "GEM_HOME" => Gem.paths.home, "DEBUG_RESOLVER" => "1" }, - Gem.ruby, "-I", File.expand_path("../../lib", __dir__), "-e", "\"Gem.activate_bin_path('a', 'exec', '>= 0')\"" + *ruby_with_rubygems_in_load_path, "-e", "\"Gem.activate_bin_path('a', 'exec', '>= 0')\"" ) assert status.success?, output @@ -1632,7 +1632,6 @@ def test_auto_activation_of_used_gemdeps_file assert_equal expected_specs, Gem.use_gemdeps.sort_by { |s| s.name } end - LIB_PATH = File.expand_path "../../../lib", __FILE__ BUNDLER_LIB_PATH = File.expand_path $LOAD_PATH.find {|lp| File.file?(File.join(lp, "bundler.rb")) } BUNDLER_FULL_NAME = "bundler-#{Bundler::VERSION}".freeze @@ -1660,7 +1659,7 @@ def test_looks_for_gemdeps_files_automatically_on_start ENV['RUBYGEMS_GEMDEPS'] = "-" path = File.join @tempdir, "gem.deps.rb" - cmd = [Gem.ruby, "-I#{LIB_PATH}", + cmd = [*ruby_with_rubygems_in_load_path, "-I#{BUNDLER_LIB_PATH}"] cmd << "-eputs Gem.loaded_specs.values.map(&:full_name).sort" @@ -1698,7 +1697,7 @@ def test_looks_for_gemdeps_files_automatically_on_start_in_parent_dir Dir.mkdir "sub1" path = File.join @tempdir, "gem.deps.rb" - cmd = [Gem.ruby, "-Csub1", "-I#{LIB_PATH}", + cmd = [*ruby_with_rubygems_in_load_path, "-Csub1", "-I#{BUNDLER_LIB_PATH}"] cmd << "-eputs Gem.loaded_specs.values.map(&:full_name).sort" From c55c53e7e01ad242d2a2006c1eef7fb3724768f3 Mon Sep 17 00:00:00 2001 From: bronzdoc Date: Sun, 26 Apr 2020 11:55:37 -0600 Subject: [PATCH 582/707] Show gemspec location when a Gem::MissingSpecError is raised while trying to activate a gem --- test/rubygems/test_gem.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index b19fd9ce..2763d78d 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1272,6 +1272,7 @@ def test_self_try_activate_missing_dep end assert_match %r{Could not find 'b' }, e.message + assert_match %r{at: #{a.spec_file}}, e.message end def test_self_try_activate_missing_prerelease From 5429c26e994534efe648550a03cf1c63d8e29760 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Thu, 23 Apr 2020 19:16:06 +0900 Subject: [PATCH 583/707] Support XDG specification. https://github.com/ruby/ruby/pull/2174 --- test/rubygems/test_gem.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 2763d78d..57e1f4f1 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1372,6 +1372,8 @@ def test_self_user_dir parts = [@userhome, '.gem', Gem.ruby_engine] parts << RbConfig::CONFIG['ruby_version'] unless RbConfig::CONFIG['ruby_version'].empty? + FileUtils.mkdir_p File.join(parts) + assert_equal File.join(parts), Gem.user_dir end From 9c119c74dec3c98e989a49435006157230d22159 Mon Sep 17 00:00:00 2001 From: Jakob Krigovsky Date: Sun, 10 May 2020 20:47:54 +0200 Subject: [PATCH 584/707] =?UTF-8?q?Remove=20Inch=20CI=20badge=20from=20Bun?= =?UTF-8?q?dler=E2=80=99s=20readme?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bundler/README.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/bundler/README.md b/bundler/README.md index 5ca8b067..0fa45876 100644 --- a/bundler/README.md +++ b/bundler/README.md @@ -1,6 +1,5 @@ -[![Version ](https://img.shields.io/gem/v/bundler.svg?style=flat)](https://rubygems.org/gems/bundler) -[![Inline docs ](https://inch-ci.org/github/rubygems/bundler.svg?style=flat)](https://inch-ci.org/github/rubygems/bundler) -[![Slack ](https://bundler-slackin.herokuapp.com/badge.svg)](https://bundler-slackin.herokuapp.com) +[![Version ](https://img.shields.io/gem/v/bundler.svg?style=flat)](https://rubygems.org/gems/bundler) +[![Slack ](https://bundler-slackin.herokuapp.com/badge.svg)](https://bundler-slackin.herokuapp.com) # Bundler: a gem to bundle gems From 7584d4fae3041bdb107cab4e07a4069d1d0b6272 Mon Sep 17 00:00:00 2001 From: Jakob Krigovsky Date: Thu, 7 May 2020 20:02:21 +0200 Subject: [PATCH 585/707] Update links from rubygems/bundler to rubygems/rubygems --- bundler/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bundler/README.md b/bundler/README.md index 0fa45876..9c65a803 100644 --- a/bundler/README.md +++ b/bundler/README.md @@ -55,8 +55,8 @@ While some Bundler contributors are compensated by Ruby Together, the project ma ### Code of Conduct -Everyone interacting in the Bundler project's codebases, issue trackers, chat rooms, and mailing lists is expected to follow the [Bundler code of conduct](https://github.com/rubygems/bundler/blob/master/CODE_OF_CONDUCT.md). +Everyone interacting in the Bundler project's codebases, issue trackers, chat rooms, and mailing lists is expected to follow the [Bundler code of conduct](https://github.com/rubygems/rubygems/blob/master/CODE_OF_CONDUCT.md). ### License -Bundler is available under an [MIT License](https://github.com/rubygems/bundler/blob/master/LICENSE.md). +Bundler is available under an [MIT License](https://github.com/rubygems/rubygems/blob/master/bundler/LICENSE.md). From 0e8e4b89cb44c164124d2383504ce7214388a810 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Mon, 25 May 2020 19:45:22 +0200 Subject: [PATCH 586/707] Re-record all cassettes I had to pin `redis-namespace` in our spec to 1.6.0 because on ruby 2.3.0 the spec no longer resolved to that version, so the cached `.gem` file was missing there. --- bundler/spec/realworld/edgecases_spec.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index 48c37093..6b418116 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -340,6 +340,7 @@ def rubygems_version(name, requirement) install_gemfile <<-G, :standalone => true source 'https://rubygems.org' gem "resque-scheduler", "2.2.0" + gem "redis-namespace", "1.6.0" # for a consistent resolution including ruby 2.3.0 G expect(err).to include("You have one or more invalid gemspecs that need to be fixed.") expect(err).to include("resque-scheduler 2.2.0 has an invalid gemspec") From 07e3879e570cae0e723da9266cdf7e97c4168f48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Wed, 3 Jun 2020 18:43:17 +0200 Subject: [PATCH 587/707] Make helpers raise by default --- bundler/spec/realworld/edgecases_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index 6b418116..62ee02cf 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -337,7 +337,7 @@ def rubygems_version(name, requirement) end it "outputs a helpful error message when gems have invalid gemspecs" do - install_gemfile <<-G, :standalone => true + install_gemfile <<-G, :standalone => true, :raise_on_error => false source 'https://rubygems.org' gem "resque-scheduler", "2.2.0" gem "redis-namespace", "1.6.0" # for a consistent resolution including ruby 2.3.0 From 7712b1cd23635c3d73f40a2449ff5c503a4f4bf1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Wed, 3 Jun 2020 20:45:36 +0200 Subject: [PATCH 588/707] s/bundle!/bundle --- bundler/spec/realworld/edgecases_spec.rb | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index 62ee02cf..a0828041 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -29,7 +29,7 @@ def rubygems_version(name, requirement) gem 'capybara', '~> 2.2.0' gem 'rack-cache', '1.2.0' # last version that works on Ruby 1.9 G - bundle! :lock + bundle :lock expect(lockfile).to include(rubygems_version("rails", "~> 5.0")) expect(lockfile).to include("capybara (2.2.1)") end @@ -43,7 +43,7 @@ def rubygems_version(name, requirement) gem "gxapi_rails", "< 0.1.0" # 0.1.0 was released way after the test was written gem 'rack-cache', '1.2.0' # last version that works on Ruby 1.9 G - bundle! :lock + bundle :lock expect(lockfile).to include("gxapi_rails (0.0.6)") end @@ -56,7 +56,7 @@ def rubygems_version(name, requirement) gem "activerecord", "~> 3.0" gem "builder", "~> 2.1.2" G - bundle! :lock + bundle :lock expect(lockfile).to include(rubygems_version("i18n", "~> 0.6.0")) expect(lockfile).to include(rubygems_version("activesupport", "~> 3.0")) end @@ -189,7 +189,7 @@ def rubygems_version(name, requirement) rails (~> 4.2.7.1) L - bundle! "lock --update paperclip" + bundle "lock --update paperclip" expect(lockfile).to include(rubygems_version("paperclip", "~> 5.1.0")) end @@ -204,7 +204,7 @@ def rubygems_version(name, requirement) G bundle "config set --local path vendor/bundle" - bundle! :install + bundle :install expect(err).not_to include("Could not find rake") expect(err).to be_empty end @@ -332,7 +332,7 @@ def rubygems_version(name, requirement) activesupport! L - bundle! :lock + bundle :lock expect(err).to be_empty end From 6973ea99b8c1f4dba82f57b15793931976954489 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Wed, 3 Jun 2020 20:47:59 +0200 Subject: [PATCH 589/707] s/ruby!/ruby --- bundler/spec/realworld/edgecases_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index a0828041..e5600bb1 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -2,7 +2,7 @@ RSpec.describe "real world edgecases", :realworld => true, :sometimes => true do def rubygems_version(name, requirement) - ruby! <<-RUBY + ruby <<-RUBY require "#{spec_dir}/support/artifice/vcr" require "#{lib_dir}/bundler" require "#{lib_dir}/bundler/source/rubygems/remote" From cbf8663e336b1cf0fcdce9218960cf67ce5526e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Wed, 10 Jun 2020 19:46:05 +0200 Subject: [PATCH 590/707] Use space inside block braces everywhere To make rubygems code style consistent with bundler. --- test/rubygems/test_gem_requirement.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/rubygems/test_gem_requirement.rb b/test/rubygems/test_gem_requirement.rb index 3db393e9..18ea2a87 100644 --- a/test/rubygems/test_gem_requirement.rb +++ b/test/rubygems/test_gem_requirement.rb @@ -390,8 +390,8 @@ def test_hash_with_multiple_versions r2 = req('2.0', '1.0') assert_equal r1.hash, r2.hash - r1 = req('1.0', '2.0').tap { |r| r.concat(['3.0']) } - r2 = req('3.0', '1.0').tap { |r| r.concat(['2.0']) } + r1 = req('1.0', '2.0').tap {|r| r.concat(['3.0']) } + r2 = req('3.0', '1.0').tap {|r| r.concat(['2.0']) } assert_equal r1.hash, r2.hash end From 952d0d0e726ffc85e0e0a4f87adfb7a0a817fbbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Wed, 10 Jun 2020 19:46:05 +0200 Subject: [PATCH 591/707] Use space inside block braces everywhere To make rubygems code style consistent with bundler. --- test/rubygems/test_gem.rb | 52 +++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 57e1f4f1..aef00cd7 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -21,7 +21,7 @@ def setup common_installer_setup ENV.delete 'RUBYGEMS_GEMDEPS' - @additional = %w[a b].map { |d| File.join @tempdir, d } + @additional = %w[a b].map {|d| File.join @tempdir, d } util_remove_interrupt_command end @@ -105,7 +105,7 @@ def test_self_install installed = Gem.install 'a', '= 1', :install_dir => gemhome2 - assert_equal %w[a-1], installed.map { |spec| spec.full_name } + assert_equal %w[a-1], installed.map {|spec| spec.full_name } assert_path_exists File.join(gemhome2, 'gems', 'a-1') end @@ -124,7 +124,7 @@ def test_self_install_in_rescue rescue StandardError Gem.install 'a', '= 1', :install_dir => gemhome2 end - assert_equal %w[a-1], installed.map { |spec| spec.full_name } + assert_equal %w[a-1], installed.map {|spec| spec.full_name } end def test_self_install_permissions @@ -208,7 +208,7 @@ def assert_self_install_permissions(format_executable: false) end assert_equal(expected, result) ensure - File.chmod(0755, *Dir.glob(@gemhome + '/gems/**/').map {|path| path.tap(&Gem::UNTAINT)}) + File.chmod(0755, *Dir.glob(@gemhome + '/gems/**/').map {|path| path.tap(&Gem::UNTAINT) }) end def test_require_missing @@ -337,7 +337,7 @@ def test_activate_bin_path_gives_proper_error_for_bundler L end - File.open("Gemfile", "w") { |f| f.puts('source "https://rubygems.org"') } + File.open("Gemfile", "w") {|f| f.puts('source "https://rubygems.org"') } e = assert_raises Gem::GemNotFoundException do load Gem.activate_bin_path("bundler", "bundle", ">= 0.a") @@ -376,7 +376,7 @@ def test_activate_bin_path_selects_exact_bundler_version_if_present L end - File.open("Gemfile", "w") { |f| f.puts('source "https://rubygems.org"') } + File.open("Gemfile", "w") {|f| f.puts('source "https://rubygems.org"') } load Gem.activate_bin_path("bundler", "bundle", ">= 0.a") @@ -410,7 +410,7 @@ def test_activate_bin_path_respects_underscore_selection_if_given L end - File.open("Gemfile", "w") { |f| f.puts('source "https://rubygems.org"') } + File.open("Gemfile", "w") {|f| f.puts('source "https://rubygems.org"') } load Gem.activate_bin_path("bundler", "bundle", "= 1.17.3") @@ -1021,7 +1021,7 @@ def test_self_refresh_keeps_loaded_specs_activated Gem.refresh - Gem::Specification.each{|spec| assert spec.activated? if spec == s} + Gem::Specification.each{|spec| assert spec.activated? if spec == s } Gem.loaded_specs.delete(s) Gem.refresh @@ -1163,7 +1163,7 @@ def test_self_paths_eq_nonexistent_home def test_self_post_build assert_equal 1, Gem.post_build_hooks.length - Gem.post_build { |installer| } + Gem.post_build {|installer| } assert_equal 2, Gem.post_build_hooks.length end @@ -1171,7 +1171,7 @@ def test_self_post_build def test_self_post_install assert_equal 1, Gem.post_install_hooks.length - Gem.post_install { |installer| } + Gem.post_install {|installer| } assert_equal 2, Gem.post_install_hooks.length end @@ -1179,7 +1179,7 @@ def test_self_post_install def test_self_done_installing assert_empty Gem.done_installing_hooks - Gem.done_installing { |gems| } + Gem.done_installing {|gems| } assert_equal 1, Gem.done_installing_hooks.length end @@ -1187,7 +1187,7 @@ def test_self_done_installing def test_self_post_reset assert_empty Gem.post_reset_hooks - Gem.post_reset { } + Gem.post_reset {} assert_equal 1, Gem.post_reset_hooks.length end @@ -1195,7 +1195,7 @@ def test_self_post_reset def test_self_post_uninstall assert_equal 1, Gem.post_uninstall_hooks.length - Gem.post_uninstall { |installer| } + Gem.post_uninstall {|installer| } assert_equal 2, Gem.post_uninstall_hooks.length end @@ -1203,7 +1203,7 @@ def test_self_post_uninstall def test_self_pre_install assert_equal 1, Gem.pre_install_hooks.length - Gem.pre_install { |installer| } + Gem.pre_install {|installer| } assert_equal 2, Gem.pre_install_hooks.length end @@ -1211,7 +1211,7 @@ def test_self_pre_install def test_self_pre_reset assert_empty Gem.pre_reset_hooks - Gem.pre_reset { } + Gem.pre_reset {} assert_equal 1, Gem.pre_reset_hooks.length end @@ -1219,7 +1219,7 @@ def test_self_pre_reset def test_self_pre_uninstall assert_equal 1, Gem.pre_uninstall_hooks.length - Gem.pre_uninstall { |installer| } + Gem.pre_uninstall {|installer| } assert_equal 2, Gem.pre_uninstall_hooks.length end @@ -1248,7 +1248,7 @@ def test_spec_order_is_consistent install_specs b1, b2, b3 - specs1 = Gem::Specification.stubs.find_all { |s| s.name == 'b' } + specs1 = Gem::Specification.stubs.find_all {|s| s.name == 'b' } Gem::Specification.reset specs2 = Gem::Specification.stubs_for('b') assert_equal specs1.map(&:version), specs2.map(&:version) @@ -1397,7 +1397,7 @@ def test_self_needs r.gem "b", "= 1" end - activated = Gem::Specification.map { |x| x.full_name } + activated = Gem::Specification.map {|x| x.full_name } assert_equal %w[a-1 b-1 c-2], activated.sort end @@ -1518,8 +1518,8 @@ def test_load_env_plugins def test_gem_path_ordering refute_equal Gem.dir, Gem.user_dir - write_file File.join(@tempdir, 'lib', "g.rb") { |fp| fp.puts "" } - write_file File.join(@tempdir, 'lib', 'm.rb') { |fp| fp.puts "" } + write_file File.join(@tempdir, 'lib', "g.rb") {|fp| fp.puts "" } + write_file File.join(@tempdir, 'lib', 'm.rb') {|fp| fp.puts "" } g = util_spec 'g', '1', nil, "lib/g.rb" m = util_spec 'm', '1', nil, "lib/m.rb" @@ -1574,8 +1574,8 @@ def test_gem_path_ordering end def test_gem_path_ordering_short - write_file File.join(@tempdir, 'lib', "g.rb") { |fp| fp.puts "" } - write_file File.join(@tempdir, 'lib', 'm.rb') { |fp| fp.puts "" } + write_file File.join(@tempdir, 'lib', "g.rb") {|fp| fp.puts "" } + write_file File.join(@tempdir, 'lib', 'm.rb') {|fp| fp.puts "" } g = util_spec 'g', '1', nil, "lib/g.rb" m = util_spec 'm', '1', nil, "lib/m.rb" @@ -1632,7 +1632,7 @@ def test_auto_activation_of_used_gemdeps_file ENV['RUBYGEMS_GEMDEPS'] = "-" expected_specs = [a, b, util_spec("bundler", Bundler::VERSION), c].compact - assert_equal expected_specs, Gem.use_gemdeps.sort_by { |s| s.name } + assert_equal expected_specs, Gem.use_gemdeps.sort_by {|s| s.name } end BUNDLER_LIB_PATH = File.expand_path $LOAD_PATH.find {|lp| File.file?(File.join(lp, "bundler.rb")) } @@ -1765,7 +1765,7 @@ def test_use_gemdeps spec = util_spec 'a', 1 install_specs spec - spec = Gem::Specification.find { |s| s == spec } + spec = Gem::Specification.find {|s| s == spec } refute spec.activated? File.open gem_deps_file, 'w' do |io| @@ -1826,7 +1826,7 @@ def test_use_gemdeps_automatic spec = util_spec 'a', 1 install_specs spec - spec = Gem::Specification.find { |s| s == spec } + spec = Gem::Specification.find {|s| s == spec } refute spec.activated? @@ -1904,7 +1904,7 @@ def test_use_gemdeps_specific spec = util_spec 'a', 1 install_specs spec - spec = Gem::Specification.find { |s| s == spec } + spec = Gem::Specification.find {|s| s == spec } refute spec.activated? File.open 'x', 'w' do |io| From 78550834b61539ebe83e7da404709df0189226c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Mon, 13 Jul 2020 12:01:07 +0200 Subject: [PATCH 592/707] Enforce no empty lines around class body in rubygems To normalize the code style with `bundler`. --- test/rubygems/test_gem_requirement.rb | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/rubygems/test_gem_requirement.rb b/test/rubygems/test_gem_requirement.rb index 18ea2a87..55a902dc 100644 --- a/test/rubygems/test_gem_requirement.rb +++ b/test/rubygems/test_gem_requirement.rb @@ -3,7 +3,6 @@ require "rubygems/requirement" class TestGemRequirement < Gem::TestCase - def test_concat r = req '>= 1' @@ -421,5 +420,4 @@ def refute_satisfied_by(version, requirement) refute req(requirement).satisfied_by?(v(version)), "#{requirement} is not satisfied by #{version}" end - end From ba0580258d0b59cde67d109d6b89bbd86c3638e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Mon, 13 Jul 2020 12:01:07 +0200 Subject: [PATCH 593/707] Enforce no empty lines around class body in rubygems To normalize the code style with `bundler`. --- test/rubygems/test_gem.rb | 2 -- test/rubygems/test_gem_version.rb | 2 -- 2 files changed, 4 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index aef00cd7..cf5c9720 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -8,7 +8,6 @@ require 'rbconfig' class TestGem < Gem::TestCase - PLUGINS_LOADED = [] # rubocop:disable Style/MutableConstant PROJECT_DIR = File.expand_path('../../..', __FILE__).tap(&Gem::UNTAINT) @@ -2033,5 +2032,4 @@ def util_remove_interrupt_command def util_cache_dir File.join Gem.dir, "cache" end - end diff --git a/test/rubygems/test_gem_version.rb b/test/rubygems/test_gem_version.rb index 30b9376e..7b382809 100644 --- a/test/rubygems/test_gem_version.rb +++ b/test/rubygems/test_gem_version.rb @@ -5,7 +5,6 @@ require "minitest/benchmark" class TestGemVersion < Gem::TestCase - class V < ::Gem::Version end @@ -298,5 +297,4 @@ def refute_version_eql(first, second) def refute_version_equal(unexpected, actual) refute_equal v(unexpected), v(actual) end - end From ad4fe66708fdf9c920cef15b67b1a895095d5609 Mon Sep 17 00:00:00 2001 From: Jean Boussier Date: Thu, 23 Jul 2020 15:11:24 +0200 Subject: [PATCH 594/707] Deduplicate the requirement operators in memory --- test/rubygems/test_gem_requirement.rb | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/rubygems/test_gem_requirement.rb b/test/rubygems/test_gem_requirement.rb index 55a902dc..af9d8077 100644 --- a/test/rubygems/test_gem_requirement.rb +++ b/test/rubygems/test_gem_requirement.rb @@ -81,6 +81,12 @@ def test_parse Gem::Requirement.parse(Gem::Version.new('2')) end + if RUBY_VERSION >= '2.5' + def test_parse_deduplication + assert_same '~>', Gem::Requirement.parse('~> 1').first + end + end + def test_parse_bad [ nil, From 4cd2cc282b5f78ab4f939f2c44b714092625a4ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Tue, 14 Jul 2020 17:47:05 +0200 Subject: [PATCH 595/707] Enable using trailing commas in rubygems To make the code style consistent with `bundler`. --- test/rubygems/test_gem.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index cf5c9720..344b03be 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -164,7 +164,7 @@ def assert_self_install_permissions(format_executable: false) :prog_mode => win_platform? ? 0410 : 0510, :data_mode => 0640, :wrappers => true, - :format_executable => format_executable + :format_executable => format_executable, } Dir.chdir @tempdir do Dir.mkdir 'bin' @@ -765,7 +765,7 @@ def test_self_find_files_with_gemfile expected = [ File.expand_path('test/rubygems/sff/discover.rb', PROJECT_DIR), - File.join(foo1.full_gem_path, discover_path) + File.join(foo1.full_gem_path, discover_path), ].sort assert_equal expected, Gem.find_files('sff/discover').sort @@ -1532,7 +1532,7 @@ def test_gem_path_ordering tests = [ [:dir0, [ Gem.dir, Gem.user_dir], m0], - [:dir1, [ Gem.user_dir, Gem.dir], m1] + [:dir1, [ Gem.user_dir, Gem.dir], m1], ] tests.each do |_name, _paths, expected| From 219b513e5d6dbe4188ab13096c48a84ae9ddeeb6 Mon Sep 17 00:00:00 2001 From: Ivan Kuchin Date: Tue, 18 Aug 2020 21:11:32 +0200 Subject: [PATCH 596/707] Sort requirements in Gem::Requirement to succeed comparison with different order --- test/rubygems/test_gem_requirement.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/rubygems/test_gem_requirement.rb b/test/rubygems/test_gem_requirement.rb index af9d8077..5d8c58ca 100644 --- a/test/rubygems/test_gem_requirement.rb +++ b/test/rubygems/test_gem_requirement.rb @@ -22,6 +22,8 @@ def test_equals2 refute_requirement_equal "~> 1.3", "~> 1.3.0" refute_requirement_equal "~> 1.3.0", "~> 1.3" + assert_requirement_equal ["> 2", "~> 1.3"], ["~> 1.3", "> 2"] + assert_requirement_equal ["> 2", "~> 1.3"], ["> 2.0", "~> 1.3"] assert_requirement_equal ["> 2.0", "~> 1.3"], ["> 2", "~> 1.3"] From ec25297ce0d7b7abaaf4d1308d8c179851906056 Mon Sep 17 00:00:00 2001 From: Ivan Kuchin Date: Wed, 2 Sep 2020 23:02:16 +0200 Subject: [PATCH 597/707] Sort requirements only for comparison, preserve the original order otherwise --- test/rubygems/test_gem_requirement.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/rubygems/test_gem_requirement.rb b/test/rubygems/test_gem_requirement.rb index 5d8c58ca..20127a1e 100644 --- a/test/rubygems/test_gem_requirement.rb +++ b/test/rubygems/test_gem_requirement.rb @@ -22,7 +22,7 @@ def test_equals2 refute_requirement_equal "~> 1.3", "~> 1.3.0" refute_requirement_equal "~> 1.3.0", "~> 1.3" - assert_requirement_equal ["> 2", "~> 1.3"], ["~> 1.3", "> 2"] + assert_requirement_equal ["> 2", "~> 1.3", "~> 1.3.1"], ["~> 1.3.1", "~> 1.3", "> 2"] assert_requirement_equal ["> 2", "~> 1.3"], ["> 2.0", "~> 1.3"] assert_requirement_equal ["> 2.0", "~> 1.3"], ["> 2", "~> 1.3"] From add5aed985aef24dbf1bbe0b01d0bc10f37bda31 Mon Sep 17 00:00:00 2001 From: Justin Trudell Date: Tue, 8 Sep 2020 15:36:59 -0700 Subject: [PATCH 598/707] fbshipit-source-id: 2bf3b8cf699979137e3f87eef74151c4ecad0cab --- antlir/rpm/rpm_metadata.py | 235 ++++++++++++++++++++++++++ antlir/rpm/tests/test_rpm_metadata.py | 141 ++++++++++++++++ 2 files changed, 376 insertions(+) create mode 100644 antlir/rpm/rpm_metadata.py create mode 100644 antlir/rpm/tests/test_rpm_metadata.py diff --git a/antlir/rpm/rpm_metadata.py b/antlir/rpm/rpm_metadata.py new file mode 100644 index 00000000..8f7f305e --- /dev/null +++ b/antlir/rpm/rpm_metadata.py @@ -0,0 +1,235 @@ +#!/usr/bin/env python3 +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import os +import re +import subprocess +from typing import NamedTuple + +from antlir.common import get_file_logger +from antlir.fs_utils import Path +from antlir.subvol_utils import Subvol + + +log = get_file_logger(__file__) + + +class RpmMetadata(NamedTuple): + name: str + epoch: int + version: str + release: str + + @classmethod + def from_subvol(cls, subvol: Subvol, package_name: str) -> "RpmMetadata": + db_path = subvol.path("var/lib/rpm") + + # `rpm` always creates a DB when `--dbpath` is an arg. + # We don't want to create one if it does not already exist so check for + # that here. + if not os.path.exists(db_path): + raise ValueError(f"RPM DB path {db_path} does not exist") + + return cls._repo_query(cls, db_path, package_name, None) + + @classmethod + def from_file(cls, package_path: Path) -> "RpmMetadata": + if not package_path.endswith(b".rpm"): + raise ValueError(f"RPM file {package_path} needs to end with .rpm") + + return cls._repo_query(cls, None, None, package_path) + + def _repo_query( + self, db_path: Path, package_name: str, package_path: Path + ) -> "RpmMetadata": + query_args = [ + "rpm", + "--query", + "--queryformat", + "'%{NAME}:%{epochnum}:%{VERSION}:%{RELEASE}'", + ] + + if db_path and package_name and (package_path is None): + query_args += ["--dbpath", db_path, package_name] + elif package_path and (db_path is None and package_name is None): + query_args += ["--package", package_path] + else: + raise ValueError( + "Must pass only (--dbpath and --package_name) or --package" + ) + + try: + result = ( + subprocess.check_output(query_args, stderr=subprocess.PIPE) + .decode() + .strip("'\"") + ) + except subprocess.CalledProcessError as e: + raise RuntimeError(f"Error querying RPM: {e.stdout}, {e.stderr}") + + n, e, v, r = result.split(":") + return RpmMetadata(name=n, epoch=int(e), version=v, release=r) + + +# This comprises a pure python implementation of rpm version comparison. The +# purpose for this is so that the antlir library does not have a dependency +# on a C library that is (for the most part) only distributed as part of rpm +# based distros. Depending on a C library complicates dependency management +# significantly in the OSS space due to the complexity of handling 3rd party C +# libraries with buck. Having this pure python implementation also eases future +# rpm usage/handling for both non-rpm based distros and different arch types. +# +# This implementation is adapted from both this blog post: +# https://blog.jasonantman.com/2014/07/how-yum-and-rpm-compare-versions/ +# and this Apache 2 licensed implementation: +# https://github.com/sassoftware/python-rpm-vercmp/blob/master/rpm_vercmp/vercmp.py +# +# There are extensive test cases in the `test_rpm_metadata.py` test case that +# cover a wide variety of normal and weird version comparsions. +def compare_rpm_versions(a: RpmMetadata, b: RpmMetadata) -> int: + """ + Returns: + 1 if the version of a is newer than b + 0 if the versions match + -1 if the version of a is older than b + """ + + # This is not a rule, but it makes sense that our libs don't want to + # compare versions of different RPMs + if a.name != b.name: + raise ValueError("Cannot compare RPM versions when names do not match") + + # First compare the epoch, if set. If the epoch's are not the same, then + # the higher one wins no matter what the rest of the EVR is. + if a.epoch != b.epoch: + if a.epoch > b.epoch: + return 1 # a > b + else: + return -1 # a < b + + # Epoch is the same, if version + release are the same we have a match + if (a.version == b.version) and (a.release == b.release): + return 0 # a == b + + # Compare version first, if version is equal then compare release + compare_res = _compare_values(a.version, b.version) + if compare_res != 0: # a > b || a < b + return compare_res + else: + return _compare_values(a.release, b.release) + + +R_NON_ALPHA_NUM_TILDE_CARET = re.compile(br"^([^a-zA-Z0-9~\^]*)(.*)$") +R_NUM = re.compile(br"^([\d]+)(.*)$") +R_ALPHA = re.compile(br"^([a-zA-Z]+)(.*)$") + + +def _compare_values(left: str, right: str) -> int: + # Rpm versions can only be ascii, anything else is just + # ignored + left = left.encode("ascii", "ignore") + right = right.encode("ascii", "ignore") + + if left == right: + return 0 + + while left or right: + match_left = R_NON_ALPHA_NUM_TILDE_CARET.match(left) + match_right = R_NON_ALPHA_NUM_TILDE_CARET.match(right) + left_head, left = match_left.group(1), match_left.group(2) + right_head, right = match_right.group(1), match_right.group(2) + + # Ignore anything at the start we don't want + if left_head or right_head: + continue + + # Look at tilde first, it takes precedent over everything else + if left.startswith(b"~"): + if not right.startswith(b"~"): + return -1 # left < right + + # Strip the tilde and start again + left, right = left[1:], right[1:] + continue + + # Tilde always means the version is less + if right.startswith(b"~"): + return 1 # left > right + + # Now look at the caret, which is like the tilde but pointier. + if left.startswith(b"^"): + # left has a caret but right has ended + if not right: + return 1 # left > right + + # left has a caret but right continues on + elif not right.startswith(b"^"): + return -1 # left < right + + # strip the ^ and start again + left, right = left[1:], right[1:] + continue + + # Caret means the version is less... Unless the other version + # has ended, then do the exact opposite. + if right.startswith(b"^"): + return -1 if not left else 1 + + # We've run out of characters to compare. + # Note: we have to do this after we compare the ~ and ^ madness + # because ~'s and ^'s take precedance. + if not left or not right: + break + + # Lets see if we've got numbers + match_left = R_NUM.match(left) + if match_left: + match_right = R_NUM.match(right) + if not match_right: # right is not a num and nums > alphas + return 1 # left > right + isnum = True + else: # match is alpha + match_left = R_ALPHA.match(left) + match_right = R_ALPHA.match(right) + if not match_right: # right is not an alpha and nums > alphas + return -1 # left < right + isnum = False + + # strip off the leading numeric or alpha chars + left_head, left = match_left.group(1), match_left.group(2) + right_head, right = match_right.group(1), match_right.group(2) + + if isnum: + left_head = left_head.lstrip(b"0") + right_head = right_head.lstrip(b"0") + + # Length of contiguous numbers matters + left_head_len = len(left_head) + right_head_len = len(right_head) + if left_head_len < right_head_len: + return -1 # left < right + if left_head_len > right_head_len: + return 1 # left > right + + # Either a number with the same number of chars or + # the leading chars are alpha so lets do a standard compare + if left_head < right_head: + return -1 # left < right + if left_head > right_head: + return 1 # left > right + + # Both header segments are of equal length, keep going with the new + continue # pragma: no cover + + # if both are now zero length they must be equal + if len(left) == len(right) == 0: + return 0 # left == right + + # Longer string is > than shorter string + if len(left) != 0: + return 1 # left > right + + return -1 # left < right diff --git a/antlir/rpm/tests/test_rpm_metadata.py b/antlir/rpm/tests/test_rpm_metadata.py new file mode 100644 index 00000000..8e5bd36d --- /dev/null +++ b/antlir/rpm/tests/test_rpm_metadata.py @@ -0,0 +1,141 @@ +#!/usr/bin/env python3 +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import importlib.resources +import os +import re +import shutil +import unittest + +from antlir.find_built_subvol import find_built_subvol +from antlir.fs_utils import temp_dir + +from ..rpm_metadata import RpmMetadata, _compare_values, compare_rpm_versions +from .temp_repos import Repo, Rpm, get_test_signing_key, temp_repos_steps + + +class RpmMetadataTestCase(unittest.TestCase): + def _load_canonical_tests(self): + STMT = re.compile( + r"(.*)RPMVERCMP\(([^, ]*) *, *([^, ]*) *, *([^\)]*)\).*" + ) + + for line in importlib.resources.open_text( + "antlir.rpm", "version-compare-tests" + ).readlines(): + m = STMT.match(line) + if m: + yield m.group(2), m.group(3), int(m.group(4)) + + def test_rpm_metadata_from_subvol(self): + layer_path = os.path.join(os.path.dirname(__file__), "child-layer") + child_subvol = find_built_subvol(layer_path) + + a = RpmMetadata.from_subvol(child_subvol, "rpm-test-mice") + self.assertEqual(a.name, "rpm-test-mice") + self.assertEqual(a.epoch, 0) + self.assertEqual(a.version, "0.1") + self.assertEqual(a.release, "a") + + # not installed + with self.assertRaises(RuntimeError): + a = RpmMetadata.from_subvol(child_subvol, "rpm-test-carrot") + + # subvol with no RPM DB + layer_path = os.path.join(os.path.dirname(__file__), "hello-layer") + hello_subvol = find_built_subvol(layer_path) + with self.assertRaisesRegex(ValueError, " does not exist$"): + a = RpmMetadata.from_subvol(hello_subvol, "rpm-test-mice") + + def test_rpm_metadata_from_file(self): + with temp_repos_steps( + gpg_signing_key=get_test_signing_key(), + repo_change_steps=[ + { + "repo": Repo( + [Rpm("sheep", "0.3.5.beta", "l33t.deadbeef.777")] + ) + } + ], + ) as repos_root, temp_dir() as td: + src_rpm_path = repos_root / ( + "0/repo/repo-pkgs/" + + "rpm-test-sheep-0.3.5.beta-l33t.deadbeef.777.x86_64.rpm" + ) + dst_rpm_path = td / "arbitrary_unused_name.rpm" + shutil.copy(src_rpm_path, dst_rpm_path) + a = RpmMetadata.from_file(dst_rpm_path) + self.assertEqual(a.name, "rpm-test-sheep") + self.assertEqual(a.epoch, 0) + self.assertEqual(a.version, "0.3.5.beta") + self.assertEqual(a.release, "l33t.deadbeef.777") + + # non-existent file + with self.assertRaisesRegex(RuntimeError, "^Error querying RPM:"): + a = RpmMetadata.from_file(b"idontexist.rpm") + + # missing extension + with self.assertRaisesRegex(ValueError, " needs to end with .rpm$"): + a = RpmMetadata.from_file(b"idontendwithdotrpm") + + def test_rpm_query_arg_check(self): + with self.assertRaisesRegex(ValueError, "^Must pass only "): + RpmMetadata._repo_query(RpmMetadata, b"dbpath", None, b"path") + + def test_rpm_compare_versions(self): + # name mismatch + a = RpmMetadata("test-name1", 1, "2", "3") + b = RpmMetadata("test-name2", 1, "2", "3") + with self.assertRaises(ValueError): + compare_rpm_versions(a, b) + + # Taste data was generated with: + # rpmdev-vercmp + # which also uses the same Python rpm lib. + # + # This number of test cases is excessive but does show how interesting + # RPM version comparisons can be. + test_evr_data = [ + # Non-alphanumeric (except ~) are ignored for equality + ((1, "2", "3"), (1, "2", "3"), 0), # 1:2-3 == 1:2-3 + ((1, ":2>", "3"), (1, "-2-", "3"), 0), # 1::2>-3 == 1:-2--3 + ((1, "2", "3?"), (1, "2", "?3"), 0), # 1:2-?3 == 1:2-3? + # epoch takes precedence no matter what + ((0, "2", "3"), (1, "2", "3"), -1), # 0:2-3 < 1:2-3 + ((1, "1", "3"), (0, "2", "3"), 1), # 1:1-3 > 0:2-3 + # version and release trigger the real comparison rules + ((0, "1", "3"), (0, "2", "3"), -1), # 0:1-3 < 0:2-3 + ((0, "~2", "3"), (0, "1", "3"), -1), # 0:~2-3 < 0:1-3 + ((0, "~", "3"), (0, "1", "3"), -1), # 0:~-3 < 0:1-3 + ((0, "1", "3"), (0, "~", "3"), 1), # 0:1-3 > 0:~-3 + ((0, "^1", "3"), (0, "^", "3"), 1), # 0:^1-3 > 0:^-3 + ((0, "^", "3"), (0, "^1", "3"), -1), # 0:^-3 < 0:^1-3 + ((0, "0333", "b"), (0, "0033", "b"), 1), # 0:0333-b > 0:0033-b + ((0, "0033", "b"), (0, "0333", "b"), -1), # 0:0033-b < 0:0333-b + ((0, "3", "~~"), (0, "3", "~~~"), 1), # 0:3-~~ > 0:3-~~~ + ((0, "3", "~~~"), (0, "3", "~~"), -1), # 0:3-~~~ < 0:3-~~ + ((0, "3", "~~~"), (0, "3", "~~~"), 0), # 0:3-~~~ == 0:3-~~~ + ((0, "a2aa", "b"), (0, "a2a", "b"), 1), # 0:a2aa-b > 0:a2a-b + ((0, "33", "b"), (0, "aaa", "b"), 1), # 0:33-b > 0:aaa-b + ] + + for evr1, evr2, expected in test_evr_data: + a = RpmMetadata("test-name", *evr1) + b = RpmMetadata("test-name", *evr2) + self.assertEqual( + compare_rpm_versions(a, b), + expected, + f"failed: {evr1}, {evr2}, {expected}", + ) + + # Test against some more canonical tests. These are derived from + # actual tests used for rpm itself. + for ver1, ver2, expected in self._load_canonical_tests(): + self.assertEqual( + _compare_values(ver1, ver2), + expected, + f"failed: {ver1}, {ver2}, {expected}", + ) From 095b1c090e21e7248cbd83b958506023f42ca677 Mon Sep 17 00:00:00 2001 From: Justin Trudell Date: Tue, 15 Sep 2020 17:02:24 -0700 Subject: [PATCH 599/707] fbshipit-source-id: 8f0dc1e1c8722c4ffc42064894abe5d0c4dbb736 --- antlir/rpm/allowed_versions/envra.py | 118 +++++++++++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 antlir/rpm/allowed_versions/envra.py diff --git a/antlir/rpm/allowed_versions/envra.py b/antlir/rpm/allowed_versions/envra.py new file mode 100644 index 00000000..0067cc1f --- /dev/null +++ b/antlir/rpm/allowed_versions/envra.py @@ -0,0 +1,118 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from functools import total_ordering +from typing import NamedTuple, Optional + +from antlir.rpm.rpm_metadata import RpmMetadata, compare_rpm_versions + + +@total_ordering +class SortableENVRA(NamedTuple): + """ + Epoch and name can be `None` to represent wildcards (details below). + + The intended application of the sort is for diff-stable serialization of + ENVRA IDs, so it does NOT do what you expect. Namely, it will sort: + - packages with different names or architectures, + - sort unknown (`None`) `.epoch` and `.name` values, so long as we're + not comparing `None` with non-`None`. + + If you want plain `rpm`-compatible comparison of versions, just call + `compare_rpm_versions(a.as_rpm_metadata(), b.as_rpm_metadata())`. + """ + + # Unlike RPM convention, None means "wildcard", it does not mean 0. A + # wildcard must be resolved to a concrete epoch by looking it up in an + # RPM DB. + epoch: Optional[int] + # Set this to `None` to make an EVRA that can be applied to multiple + # packages in a package group. + name: Optional[str] + version: str + release: str + arch: str + + # Use `as_rpm_metadata` for public consumption. The private version + # here allows comparing wildcard epochs because we only use it after + # checking that we're not comparing `None` with non-`None`. + def _as_rpm_metadata(self) -> RpmMetadata: + return RpmMetadata( + # Not used for sorting here, `compare_rpm_versions` refuses to + # compare different names. As a side-effect, `None` vs + # non-`None` comparisons are also prohibited. + name=self.name, + # We check this is not `None` in `as_rpm_metadata`, and check + # for heterogeneous comparisons in `_compare`. + epoch=self.epoch, + version=self.version, + release=self.release, + ) + + # Enables comparison of versions via `compare_rpm_versions`. + def as_rpm_metadata(self) -> RpmMetadata: + # Allowing a `None` vs non-`None` comparison would be wrong. + # + # Future: move the check for these comparisons out of this class + # and into `compare_rpm_versions`. + if self.epoch is None: + raise TypeError( + f"Cannot use `as_rpm_metadata()` with wildcard epoch: {self}" + ) + return self._as_rpm_metadata() + + def _compare(self, other: "SortableENVRA") -> int: + # It makes no sense to compare wildcard with non-wildcard because it + # amounts to comparing different data types. All elements of a + # `SortableENVRA` collections should have wildcards in this field, + # or the field should be concrete throughout. + if (self.name is None) ^ (other.name is None): + raise TypeError( + f"Cannot compare concrete name with wildcard: {self} {other}" + ) + + # Sort lexicographically by name, then architecture + self_key = (self.name, self.arch) + other_key = (other.name, other.arch) + + if self_key > other_key: + return 1 + elif self_key == other_key: + # Same rationale as for the `.name` test above. + if (self.epoch is None) ^ (other.epoch is None): + raise TypeError( + f"Cannot compare int epoch with wildcard: {self} {other}" + ) + return compare_rpm_versions( + self._as_rpm_metadata(), other._as_rpm_metadata() + ) + elif self_key < other_key: + return -1 + + raise AssertionError(f"Bad name/arch keys: {self_key} {other_key}") + + def __eq__(self, other: "SortableENVRA") -> bool: + return self._compare(other) == 0 + + def __lt__(self, other: "SortableENVRA") -> bool: + return self._compare(other) < 0 + + def to_versionlock_line(self) -> str: + if self.epoch is None or self.name is None: + raise ValueError(f"Versionlock needs concrete name & epoch: {self}") + # Our `yum_dnf_versionlock.py` expects TAB-separated ENVRAs. + return "\t".join( + [str(self.epoch), self.name, self.version, self.release, self.arch] + ) + + def __repr__(self) -> str: + epoch = "*" if self.epoch is None else self.epoch + name = "*" if self.name is None else self.name + return f"{epoch}:{name}-{self.version}-{self.release}-{self.arch}" + + +# As a type-hint, this alias represents the fact that the `name` must be +# `None`. Future: should this be a proper, separate type? +SortableEVRA = SortableENVRA From 89ea973936384cfa295a7e8a3c937e435c43f4c6 Mon Sep 17 00:00:00 2001 From: John Reese Date: Wed, 14 Oct 2020 20:19:13 -0700 Subject: [PATCH 600/707] apply black 20.8b1 formatting update Summary: allow-large-files black_any_style Reviewed By: zertosh Differential Revision: D24325133 fbshipit-source-id: b4afe80d1e8b2bc993f4b8e3822c02964df47462 --- antlir/rpm/rpm_metadata.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/antlir/rpm/rpm_metadata.py b/antlir/rpm/rpm_metadata.py index 8f7f305e..f7cd97cc 100644 --- a/antlir/rpm/rpm_metadata.py +++ b/antlir/rpm/rpm_metadata.py @@ -91,10 +91,10 @@ def _repo_query( # cover a wide variety of normal and weird version comparsions. def compare_rpm_versions(a: RpmMetadata, b: RpmMetadata) -> int: """ - Returns: - 1 if the version of a is newer than b - 0 if the versions match - -1 if the version of a is older than b + Returns: + 1 if the version of a is newer than b + 0 if the versions match + -1 if the version of a is older than b """ # This is not a rule, but it makes sense that our libs don't want to From 2bcf82368f92b945871df8ee7c827626d319a396 Mon Sep 17 00:00:00 2001 From: Justin Trudell Date: Tue, 20 Oct 2020 19:49:32 -0700 Subject: [PATCH 601/707] Update logging format Summary: See `antlir/common.py` for changes of interest. I think we can benefit from updating our logging format a bit with a few changes: - Use a single letter for level to shorten length - Add lineno after filename, and strip filename extension (always `.py` in our case) - Print in GLOG-inspired format of `LEVEL TIME FILE:LINE MESSAGE`; importantly this places the columns that can be aligned first, which IMO helps greatly with quickly parsing logs. I also used the inspect module to grab the filename from the calling stack so that we don't have to pass `__file__` every time (cc zeroxoneb we could also potentially incorporate the `__package__` changes we talked about a while ago next). Finally, to get fancy I added colours for various log levels. I think this helps greatly with readability on devservers, but one could argue there would be cases where ANSI colors don't render properly that are hurt by this, so I'm open to debate. For posterity, consider a truncated view of the previous format: {F340854136} and the new format: {F340854669} Reviewed By: snarkmaster Differential Revision: D24428284 fbshipit-source-id: 1a86187156c20686132badc831f9e04cf1239675 --- antlir/rpm/rpm_metadata.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/antlir/rpm/rpm_metadata.py b/antlir/rpm/rpm_metadata.py index f7cd97cc..50563bcc 100644 --- a/antlir/rpm/rpm_metadata.py +++ b/antlir/rpm/rpm_metadata.py @@ -9,12 +9,12 @@ import subprocess from typing import NamedTuple -from antlir.common import get_file_logger +from antlir.common import get_logger from antlir.fs_utils import Path from antlir.subvol_utils import Subvol -log = get_file_logger(__file__) +log = get_logger() class RpmMetadata(NamedTuple): From ff0321c3a838b435555462aa8871290bc1b0fada Mon Sep 17 00:00:00 2001 From: Teppei Fukuda Date: Sat, 7 Nov 2020 21:51:36 +0200 Subject: [PATCH 602/707] Remove duplicate cases --- test/rubygems/test_gem_requirement.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/test/rubygems/test_gem_requirement.rb b/test/rubygems/test_gem_requirement.rb index 20127a1e..670defe3 100644 --- a/test/rubygems/test_gem_requirement.rb +++ b/test/rubygems/test_gem_requirement.rb @@ -253,7 +253,6 @@ def test_satisfied_by_eh_good assert_satisfied_by "1.0.0.0", "= 1.0" assert_satisfied_by "10.3.2", "!= 9.3.4" assert_satisfied_by "10.3.2", "> 9.3.2" - assert_satisfied_by "10.3.2", "> 9.3.2" assert_satisfied_by " 9.3.2", ">= 9.3.2" assert_satisfied_by "9.3.2 ", ">= 9.3.2" assert_satisfied_by "", "= 0" From c9146d7827e7c771eacf0093156517daa2db6228 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Sun, 13 Dec 2020 02:39:10 +0100 Subject: [PATCH 603/707] Eureka With the new platform specific behavior where resolving happens against the specific platform bundler being run from, we no longer need to keep resolving for the generic ruby platform. The specific_platform logic already includes fallback spec groups so that we always default to the generic platform when no more specific variants are found. Resolving both for the generic ruby platform and the specific platform was creating a big overhead in performance to the point where some couldn't be resolved in reasonable time. The ruby platform is no longer added to the lockfile unless we're using the `force_ruby_platform` setting. To play nice with old Gemfiles including the RUBY platform in the list of platforms while running in frozen mode, I added some compatibility code to deal with that. I also added a realworld spec to prove the performance improvements. With these changes, it takes ~10s (around the same as in 2.1.4), without these changes it hangs. --- bundler/spec/realworld/edgecases_spec.rb | 111 +++++++++++++++++++++++ 1 file changed, 111 insertions(+) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index e5600bb1..0f19cc78 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -345,4 +345,115 @@ def rubygems_version(name, requirement) expect(err).to include("You have one or more invalid gemspecs that need to be fixed.") expect(err).to include("resque-scheduler 2.2.0 has an invalid gemspec") end + + it "doesn't hang on big gemfile" do + skip "Only for ruby 2.7.2" if RUBY_VERSION != "2.7.2" + + gemfile <<~G + # frozen_string_literal: true + + source "https://rubygems.org" + + ruby "2.7.2" + + gem "rails" + gem "pg", ">= 0.18", "< 2.0" + gem "goldiloader" + gem "awesome_nested_set" + gem "circuitbox" + gem "passenger" + gem "globalid" + gem "rack-cors" + gem "rails-pg-extras" + gem "linear_regression_trend" + gem "rack-protection" + gem "pundit" + gem "remote_ip_proxy_scrubber" + gem "bcrypt" + gem "searchkick" + gem "excon" + gem "faraday_middleware-aws-sigv4" + gem "typhoeus" + gem "sidekiq" + gem "sidekiq-undertaker" + gem "sidekiq-cron" + gem "storext" + gem "appsignal" + gem "fcm" + gem "business_time" + gem "tzinfo" + gem "holidays" + gem "bigdecimal" + gem "progress_bar" + gem "redis" + gem "hiredis" + gem "state_machines" + gem "state_machines-audit_trail" + gem "state_machines-activerecord" + gem "interactor" + gem "ar_transaction_changes" + gem "redis-rails" + gem "seed_migration" + gem "lograge" + gem "graphiql-rails", group: :development + gem "graphql" + gem "pusher" + gem "rbnacl" + gem "jwt" + gem "json-schema" + gem "discard" + gem "money" + gem "strip_attributes" + gem "validates_email_format_of" + gem "audited" + gem "concurrent-ruby" + gem "with_advisory_lock" + + group :test do + gem "rspec-sidekiq" + gem "simplecov", require: false + end + + group :development, :test do + gem "byebug", platform: :mri + gem "guard" + gem "guard-bundler" + gem "guard-rspec" + gem "rb-fsevent" + gem "rspec_junit_formatter" + gem "rspec-collection_matchers" + gem "rspec-rails" + gem "rspec-retry" + gem "state_machines-rspec" + gem "dotenv-rails" + gem "database_cleaner-active_record" + gem "database_cleaner-redis" + gem "timecop" + end + + gem "factory_bot_rails" + gem "faker" + + group :development do + gem "listen" + gem "sql_queries_count" + gem "rubocop" + gem "rubocop-performance" + gem "rubocop-rspec" + gem "rubocop-rails" + gem "brakeman" + gem "bundler-audit" + gem "solargraph" + gem "annotate" + end + G + + bundle :lock, :env => { "DEBUG_RESOLVER" => "1" } + + if Bundler.feature_flag.bundler_3_mode? + expect(out).to include("BUNDLER: Finished resolution (2492 steps)") + else + expect(out).to include("BUNDLER: Finished resolution (2722 steps)") + end + end end From ca4632dea95cbfe6855440028fc5b39239da8f89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Wed, 6 Jan 2021 13:13:45 +0100 Subject: [PATCH 604/707] Fix performance regression in resolver Only add a fallback ruby specific group if the dependencies for the platform specific spec group different from the ones for the ruby group. --- bundler/spec/realworld/edgecases_spec.rb | 30 ++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index 0f19cc78..fe78517f 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -451,9 +451,35 @@ def rubygems_version(name, requirement) bundle :lock, :env => { "DEBUG_RESOLVER" => "1" } if Bundler.feature_flag.bundler_3_mode? - expect(out).to include("BUNDLER: Finished resolution (2492 steps)") + expect(out).to include("BUNDLER: Finished resolution (1122 steps)") else - expect(out).to include("BUNDLER: Finished resolution (2722 steps)") + expect(out).to include("BUNDLER: Finished resolution (1195 steps)") + end + end + + it "doesn't hang on tricky gemfile" do + skip "Only for ruby 2.7.2" if RUBY_VERSION != "2.7.2" + + gemfile <<~G + source 'https://rubygems.org' + + group :development do + gem "puppet-module-posix-default-r2.7", '~> 0.3' + gem "puppet-module-posix-dev-r2.7", '~> 0.3' + gem "beaker-rspec" + gem "beaker-puppet" + gem "beaker-docker" + gem "beaker-puppet_install_helper" + gem "beaker-module_install_helper" + end + G + + bundle :lock, :env => { "DEBUG_RESOLVER" => "1" } + + if Bundler.feature_flag.bundler_3_mode? + expect(out).to include("BUNDLER: Finished resolution (366 steps)") + else + expect(out).to include("BUNDLER: Finished resolution (372 steps)") end end end From bbe5b1091cffa99422467716b34bdb0b66aa553c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Thu, 7 Jan 2021 15:43:19 +0100 Subject: [PATCH 605/707] Rerecord VCR cassettes --- bundler/spec/realworld/edgecases_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index fe78517f..eb386137 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -451,9 +451,9 @@ def rubygems_version(name, requirement) bundle :lock, :env => { "DEBUG_RESOLVER" => "1" } if Bundler.feature_flag.bundler_3_mode? - expect(out).to include("BUNDLER: Finished resolution (1122 steps)") + expect(out).to include("BUNDLER: Finished resolution (1336 steps)") else - expect(out).to include("BUNDLER: Finished resolution (1195 steps)") + expect(out).to include("BUNDLER: Finished resolution (1395 steps)") end end From e96d54dda07f90374ae0fab67e4c581eb84cf03b Mon Sep 17 00:00:00 2001 From: Lukas Oberhuber Date: Wed, 6 Jan 2021 23:41:56 +0000 Subject: [PATCH 606/707] Fix `Requirement` hashes in the `~>` case The `~>` operator is special because what's on the right side of it doesn't have the same properties as a `Gem::Version`. For example, `~> 2.0.0` is not the same as `~> 2.0` even if `2.0` and `2.0.0` are equivalent as `Gem::Version`'s. --- test/rubygems/test_gem_requirement.rb | 34 +++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/test/rubygems/test_gem_requirement.rb b/test/rubygems/test_gem_requirement.rb index 670defe3..b9351812 100644 --- a/test/rubygems/test_gem_requirement.rb +++ b/test/rubygems/test_gem_requirement.rb @@ -401,6 +401,27 @@ def test_hash_with_multiple_versions assert_equal r1.hash, r2.hash end + def test_hash_returns_equal_hashes_for_equivalent_requirements + refute_requirement_hash_equal "= 1.2", "= 1.3" + refute_requirement_hash_equal "= 1.3", "= 1.2" + + refute_requirement_hash_equal "~> 1.3", "~> 1.3.0" + refute_requirement_hash_equal "~> 1.3.0", "~> 1.3" + + assert_requirement_hash_equal ["> 2", "~> 1.3", "~> 1.3.1"], ["~> 1.3.1", "~> 1.3", "> 2"] + + assert_requirement_hash_equal ["> 2", "~> 1.3"], ["> 2.0", "~> 1.3"] + assert_requirement_hash_equal ["> 2.0", "~> 1.3"], ["> 2", "~> 1.3"] + + assert_requirement_hash_equal "= 1.0", "= 1.0.0" + assert_requirement_hash_equal "= 1.1", "= 1.1.0" + assert_requirement_hash_equal "= 1", "= 1.0.0" + + assert_requirement_hash_equal "1.0", "1.0.0" + assert_requirement_hash_equal "1.1", "1.1.0" + assert_requirement_hash_equal "1", "1.0.0" + end + # Assert that two requirements are equal. Handles Gem::Requirements, # strings, arrays, numbers, and versions. @@ -415,6 +436,13 @@ def assert_satisfied_by(version, requirement) "#{requirement} is satisfied by #{version}" end + # Assert that two requirement hashes are equal. Handles Gem::Requirements, + # strings, arrays, numbers, and versions. + + def assert_requirement_hash_equal(expected, actual) + assert_equal req(expected).hash, req(actual).hash + end + # Refute the assumption that two requirements are equal. def refute_requirement_equal(unexpected, actual) @@ -427,4 +455,10 @@ def refute_satisfied_by(version, requirement) refute req(requirement).satisfied_by?(v(version)), "#{requirement} is not satisfied by #{version}" end + + # Refute the assumption that two requirements hashes are equal. + + def refute_requirement_hash_equal(unexpected, actual) + refute_equal req(unexpected).hash, req(actual).hash + end end From 628d58bab20def73747dd50962dc66d970b6ec1c Mon Sep 17 00:00:00 2001 From: Karol Bucek Date: Fri, 15 Jan 2021 13:48:22 +0100 Subject: [PATCH 607/707] Fix: ensure_gem_subdirs regression in 3.2 JRuby expects the method to not raise with embed paths --- test/rubygems/test_gem.rb | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 344b03be..68e3eccd 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -692,6 +692,11 @@ def test_self_ensure_gem_directories_write_protected_parents ensure FileUtils.chmod 0600, parent end + + def test_self_ensure_gem_directories_non_existent_paths + Gem.ensure_gem_subdirectories '/proc/0123456789/bogus' # should not raise + Gem.ensure_gem_subdirectories 'classpath:/bogus/x' # JRuby embed scenario + end end def test_self_extension_dir_shared From e034017b4f4edcc19850c5c1875e8855154ff774 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Thu, 21 Jan 2021 23:10:14 +0100 Subject: [PATCH 608/707] Cancel the future change in behavior of allowing bundler conflicts I can't see a good reason why it would be a good thing to do it. --- bundler/spec/realworld/edgecases_spec.rb | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index eb386137..42c9f464 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -64,6 +64,8 @@ def rubygems_version(name, requirement) it "is able to update a top-level dependency when there is a conflict on a shared transitive child" do # from https://github.com/rubygems/bundler/issues/5031 + system_gems "bundler-2.99.0" + gemfile <<-G source "https://rubygems.org" gem 'rails', '~> 4.2.7.1' @@ -189,7 +191,7 @@ def rubygems_version(name, requirement) rails (~> 4.2.7.1) L - bundle "lock --update paperclip" + bundle "lock --update paperclip", :env => { "BUNDLER_VERSION" => "2.99.0" } expect(lockfile).to include(rubygems_version("paperclip", "~> 5.1.0")) end @@ -448,11 +450,12 @@ def rubygems_version(name, requirement) end G - bundle :lock, :env => { "DEBUG_RESOLVER" => "1" } - if Bundler.feature_flag.bundler_3_mode? - expect(out).to include("BUNDLER: Finished resolution (1336 steps)") + # Conflicts on bundler version, so fails earlier + bundle :lock, :env => { "DEBUG_RESOLVER" => "1" }, :raise_on_error => false + expect(out).to include("BUNDLER: Finished resolution (211 steps)") else + bundle :lock, :env => { "DEBUG_RESOLVER" => "1" } expect(out).to include("BUNDLER: Finished resolution (1395 steps)") end end @@ -477,7 +480,7 @@ def rubygems_version(name, requirement) bundle :lock, :env => { "DEBUG_RESOLVER" => "1" } if Bundler.feature_flag.bundler_3_mode? - expect(out).to include("BUNDLER: Finished resolution (366 steps)") + expect(out).to include("BUNDLER: Finished resolution (369 steps)") else expect(out).to include("BUNDLER: Finished resolution (372 steps)") end From e84bae545d8f2d3da7355f9f47892ff1e6d1c469 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Thu, 21 Jan 2021 19:29:18 +0100 Subject: [PATCH 609/707] Fix dependency comparison We should unconditionally add fallback ruby groups, and let Molinillo merged them together with the platform specific counterparts and possibily other spec groups if they have the same dependencies. This change make some Gemfiles that wouldn't previously resolve, resolve quickly, and in general reduces the number of steps needed to resolve. In some unlucky cases the number of steps could be increased, since now searches have more associated spec groups, and the number of spec groups a dependency has is used as a criteria for dependency sorting. However, I only found one such case, while all the others I have tried the steps are either reduced or preserved. --- bundler/spec/realworld/edgecases_spec.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index 42c9f464..f4e2ce5a 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -453,10 +453,10 @@ def rubygems_version(name, requirement) if Bundler.feature_flag.bundler_3_mode? # Conflicts on bundler version, so fails earlier bundle :lock, :env => { "DEBUG_RESOLVER" => "1" }, :raise_on_error => false - expect(out).to include("BUNDLER: Finished resolution (211 steps)") + expect(out).to include("BUNDLER: Finished resolution (435 steps)") else bundle :lock, :env => { "DEBUG_RESOLVER" => "1" } - expect(out).to include("BUNDLER: Finished resolution (1395 steps)") + expect(out).to include("BUNDLER: Finished resolution (1019 steps)") end end @@ -480,9 +480,9 @@ def rubygems_version(name, requirement) bundle :lock, :env => { "DEBUG_RESOLVER" => "1" } if Bundler.feature_flag.bundler_3_mode? - expect(out).to include("BUNDLER: Finished resolution (369 steps)") + expect(out).to include("BUNDLER: Finished resolution (870 steps)") else - expect(out).to include("BUNDLER: Finished resolution (372 steps)") + expect(out).to include("BUNDLER: Finished resolution (871 steps)") end end end From 0cafe5ef0d28b5dfc196d8e3705f95ab776258d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Thu, 21 Jan 2021 17:13:29 +0100 Subject: [PATCH 610/707] Realworld spec to prove that nix Gemfile now installs fine --- bundler/spec/realworld/edgecases_spec.rb | 166 +++++++++++++++++++++++ 1 file changed, 166 insertions(+) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index f4e2ce5a..981eef7d 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -485,4 +485,170 @@ def rubygems_version(name, requirement) expect(out).to include("BUNDLER: Finished resolution (871 steps)") end end + + it "doesn't hang on nix gemfile" do + skip "Only for ruby 3.0.0" if RUBY_VERSION != "3.0.0" + + gemfile <<~G + source "https://rubygems.org" do + gem "addressable" + gem "atk" + gem "awesome_print" + gem "bacon" + gem "byebug" + gem "cairo" + gem "cairo-gobject" + gem "camping" + gem "charlock_holmes" + gem "cld3" + gem "cocoapods" + gem "cocoapods-acknowledgements" + gem "cocoapods-art" + gem "cocoapods-bin" + gem "cocoapods-browser" + gem "cocoapods-bugsnag" + gem "cocoapods-check" + gem "cocoapods-clean" + gem "cocoapods-clean_build_phases_scripts" + gem "cocoapods-core" + gem "cocoapods-coverage" + gem "cocoapods-deintegrate" + gem "cocoapods-dependencies" + gem "cocoapods-deploy" + gem "cocoapods-downloader" + gem "cocoapods-expert-difficulty" + gem "cocoapods-fix-react-native" + gem "cocoapods-generate" + gem "cocoapods-git_url_rewriter" + gem "cocoapods-keys" + gem "cocoapods-no-dev-schemes" + gem "cocoapods-open" + gem "cocoapods-packager" + gem "cocoapods-playgrounds" + gem "cocoapods-plugins" + gem "cocoapods-prune-localizations" + gem "cocoapods-rome" + gem "cocoapods-search" + gem "cocoapods-sorted-search" + gem "cocoapods-static-swift-framework" + gem "cocoapods-stats" + gem "cocoapods-tdfire-binary" + gem "cocoapods-testing" + gem "cocoapods-trunk" + gem "cocoapods-try" + gem "cocoapods-try-release-fix" + gem "cocoapods-update-if-you-dare" + gem "cocoapods-whitelist" + gem "cocoapods-wholemodule" + gem "coderay" + gem "concurrent-ruby" + gem "curb" + gem "curses" + gem "daemons" + gem "dep-selector-libgecode" + gem "digest-sha3" + gem "domain_name" + gem "do_sqlite3" + gem "ethon" + gem "eventmachine" + gem "excon" + gem "faraday" + gem "ffi" + gem "ffi-rzmq-core" + gem "fog-dnsimple" + gem "gdk_pixbuf2" + gem "gio2" + gem "gitlab-markup" + gem "glib2" + gem "gpgme" + gem "gtk2" + gem "hashie" + gem "highline" + gem "hike" + gem "hitimes" + gem "hpricot" + gem "httpclient" + gem "http-cookie" + gem "iconv" + gem "idn-ruby" + gem "jbuilder" + gem "jekyll" + gem "jmespath" + gem "jwt" + gem "libv8" + gem "libxml-ruby" + gem "magic" + gem "markaby" + gem "method_source" + gem "mini_magick" + gem "msgpack" + gem "mysql2" + gem "ncursesw" + gem "netrc" + gem "net-scp" + gem "net-ssh" + gem "nokogiri" + gem "opus-ruby" + gem "ovirt-engine-sdk" + gem "pango" + gem "patron" + gem "pcaprub" + gem "pg" + gem "pry" + gem "pry-byebug" + gem "pry-doc" + gem "public_suffix" + gem "puma" + gem "rails" + gem "rainbow" + gem "rbnacl" + gem "rb-readline" + gem "re2" + gem "redis" + gem "redis-rack" + gem "rest-client" + gem "rmagick" + gem "rpam2" + gem "rspec" + gem "rubocop" + gem "rubocop-performance" + gem "ruby-libvirt" + gem "ruby-lxc" + gem "ruby-progressbar" + gem "ruby-terminfo" + gem "ruby-vips" + gem "rubyzip" + gem "rugged" + gem "sassc" + gem "scrypt" + gem "semian" + gem "sequel" + gem "sequel_pg" + gem "simplecov" + gem "sinatra" + gem "slop" + gem "snappy" + gem "sqlite3" + gem "taglib-ruby" + gem "thrift" + gem "tilt" + gem "tiny_tds" + gem "treetop" + gem "typhoeus" + gem "tzinfo" + gem "unf_ext" + gem "uuid4r" + gem "whois" + gem "zookeeper" + end + G + + bundle :lock, :env => { "DEBUG_RESOLVER" => "1" } + + if Bundler.feature_flag.bundler_3_mode? + expect(out).to include("BUNDLER: Finished resolution (1872 steps)") + else + expect(out).to include("BUNDLER: Finished resolution (1918 steps)") + end + end end From 30a1937e1f8fac6c7a4d1edae217e125a4a8c652 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Thu, 14 Jan 2021 21:04:13 +0100 Subject: [PATCH 611/707] Remove :sometimes filter I haven't seen these specs fail for a long time. If they fail, we should make them pass reliably. --- bundler/spec/realworld/edgecases_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index 981eef7d..dbc4c46d 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -RSpec.describe "real world edgecases", :realworld => true, :sometimes => true do +RSpec.describe "real world edgecases", :realworld => true do def rubygems_version(name, requirement) ruby <<-RUBY require "#{spec_dir}/support/artifice/vcr" From ed4fa6e1a5f199a860ceccd6adcf9bca601eca2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Fri, 15 Jan 2021 00:40:13 +0100 Subject: [PATCH 612/707] Use a proper matcher with better errors --- bundler/spec/realworld/edgecases_spec.rb | 26 ++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index dbc4c46d..f8a90fe9 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -453,10 +453,10 @@ def rubygems_version(name, requirement) if Bundler.feature_flag.bundler_3_mode? # Conflicts on bundler version, so fails earlier bundle :lock, :env => { "DEBUG_RESOLVER" => "1" }, :raise_on_error => false - expect(out).to include("BUNDLER: Finished resolution (435 steps)") + expect(out).to display_total_steps_of(435) else bundle :lock, :env => { "DEBUG_RESOLVER" => "1" } - expect(out).to include("BUNDLER: Finished resolution (1019 steps)") + expect(out).to display_total_steps_of(1019) end end @@ -480,9 +480,9 @@ def rubygems_version(name, requirement) bundle :lock, :env => { "DEBUG_RESOLVER" => "1" } if Bundler.feature_flag.bundler_3_mode? - expect(out).to include("BUNDLER: Finished resolution (870 steps)") + expect(out).to display_total_steps_of(870) else - expect(out).to include("BUNDLER: Finished resolution (871 steps)") + expect(out).to display_total_steps_of(871) end end @@ -646,9 +646,23 @@ def rubygems_version(name, requirement) bundle :lock, :env => { "DEBUG_RESOLVER" => "1" } if Bundler.feature_flag.bundler_3_mode? - expect(out).to include("BUNDLER: Finished resolution (1872 steps)") + expect(out).to display_total_steps_of(1872) else - expect(out).to include("BUNDLER: Finished resolution (1918 steps)") + expect(out).to display_total_steps_of(1918) + end + end + + private + + RSpec::Matchers.define :display_total_steps_of do |expected_steps| + match do |out| + out.include?("BUNDLER: Finished resolution (#{expected_steps} steps)") + end + + failure_message do |out| + actual_steps = out.scan(/BUNDLER: Finished resolution \((\d+) steps\)/).first.first + + "Expected resolution to finish in #{expected_steps} steps, but took #{actual_steps}" end end end From 54fbe506763d76b1d7145bca61194f9d269de72f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Fri, 15 Jan 2021 00:47:06 +0100 Subject: [PATCH 613/707] Regenerate cassettes --- bundler/spec/realworld/edgecases_spec.rb | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index f8a90fe9..1925f76c 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -456,7 +456,7 @@ def rubygems_version(name, requirement) expect(out).to display_total_steps_of(435) else bundle :lock, :env => { "DEBUG_RESOLVER" => "1" } - expect(out).to display_total_steps_of(1019) + expect(out).to display_total_steps_of(1025) end end @@ -480,9 +480,9 @@ def rubygems_version(name, requirement) bundle :lock, :env => { "DEBUG_RESOLVER" => "1" } if Bundler.feature_flag.bundler_3_mode? - expect(out).to display_total_steps_of(870) + expect(out).to display_total_steps_of(890) else - expect(out).to display_total_steps_of(871) + expect(out).to display_total_steps_of(891) end end @@ -646,9 +646,9 @@ def rubygems_version(name, requirement) bundle :lock, :env => { "DEBUG_RESOLVER" => "1" } if Bundler.feature_flag.bundler_3_mode? - expect(out).to display_total_steps_of(1872) + expect(out).to display_total_steps_of(1874) else - expect(out).to display_total_steps_of(1918) + expect(out).to display_total_steps_of(1922) end end From 7562f913d682331f18ddc9aaef6c0800cf1ec955 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Wed, 6 Jan 2021 20:56:17 +0100 Subject: [PATCH 614/707] Skip test that doesn't work in `--debug` mode --- test/rubygems/test_gem_requirement.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/rubygems/test_gem_requirement.rb b/test/rubygems/test_gem_requirement.rb index b9351812..13897eae 100644 --- a/test/rubygems/test_gem_requirement.rb +++ b/test/rubygems/test_gem_requirement.rb @@ -83,7 +83,7 @@ def test_parse Gem::Requirement.parse(Gem::Version.new('2')) end - if RUBY_VERSION >= '2.5' + if RUBY_VERSION >= '2.5' && !(Gem.java_platform? && ENV["JRUBY_OPTS"] =~ /--debug/) def test_parse_deduplication assert_same '~>', Gem::Requirement.parse('~> 1').first end From 87e560254acedb023a5dfd983b41943bd06651d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Thu, 4 Feb 2021 19:07:33 +0100 Subject: [PATCH 615/707] Don't error out when activating a binstub unless necessary When activating an executable from a gem, rubygems will find the spec corresponding to the rubygems binstub, it will then activate it, and they it will finish resolving all of its dependencies, and properly setting up the load path and activate them. However, if during this process "orphaned gems" are detected (installed gems without valid dependencies installed), rubygems will crash with a very strange error, even if the orphan gem will not end up being activated and used in the end. The error will look like this: ``` $ rails s [138376, #, #, ["/home/deivid/.rbenv/versions/2.7.2/lib/ruby/site_ruby/2.7.0/rubygems/dependency.rb:309:in `to_specs'", "/home/deivid/.rbenv/versions/2.7.2/lib/ruby/site_ruby/2.7.0/rubygems/specification.rb:2553:in `block in traverse'", "/home/deivid/.rbenv/versions/2.7.2/lib/ruby/site_ruby/2.7.0/rubygems/specification.rb:2551:in `each'", "/home/deivid/.rbenv/versions/2.7.2/lib/ruby/site_ruby/2.7.0/rubygems/specification.rb:2551:in `traverse'", "/home/deivid/.rbenv/versions/2.7.2/lib/ruby/site_ruby/2.7.0/rubygems/specification.rb:1031:in `block in find_in_unresolved_tree'", "/home/deivid/.rbenv/versions/2.7.2/lib/ruby/site_ruby/2.7.0/rubygems/specification.rb:1030:in `each'", "/home/deivid/.rbenv/versions/2.7.2/lib/ruby/site_ruby/2.7.0/rubygems/specification.rb:1030:in `find_in_unresolved_tree'", "/home/deivid/.rbenv/versions/2.7.2/lib/ruby/site_ruby/2.7.0/rubygems/core_ext/kernel_require.rb:114:in `require'", "/home/deivid/.rbenv/versions/2.7.2/lib/ruby/site_ruby/2.7.0/rubygems.rb:236:in `finish_resolve'", "/home/deivid/.rbenv/versions/2.7.2/lib/ruby/site_ruby/2.7.0/rubygems.rb:303:in `block in activate_bin_path'", "/home/deivid/.rbenv/versions/2.7.2/lib/ruby/site_ruby/2.7.0/rubygems.rb:301:in `synchronize'", "/home/deivid/.rbenv/versions/2.7.2/lib/ruby/site_ruby/2.7.0/rubygems.rb:301:in `activate_bin_path'", "/home/deivid/.rbenv/versions/2.7.2/bin/rails:23:in `
'"]] Traceback (most recent call last): 12: from /home/deivid/.rbenv/versions/2.7.2/bin/rails:23:in `
' 11: from /home/deivid/.rbenv/versions/2.7.2/lib/ruby/site_ruby/2.7.0/rubygems.rb:301:in `activate_bin_path' 10: from /home/deivid/.rbenv/versions/2.7.2/lib/ruby/site_ruby/2.7.0/rubygems.rb:301:in `synchronize' 9: from /home/deivid/.rbenv/versions/2.7.2/lib/ruby/site_ruby/2.7.0/rubygems.rb:303:in `block in activate_bin_path' 8: from /home/deivid/.rbenv/versions/2.7.2/lib/ruby/site_ruby/2.7.0/rubygems.rb:236:in `finish_resolve' 7: from /home/deivid/.rbenv/versions/2.7.2/lib/ruby/site_ruby/2.7.0/rubygems/core_ext/kernel_require.rb:114:in `require' 6: from /home/deivid/.rbenv/versions/2.7.2/lib/ruby/site_ruby/2.7.0/rubygems/specification.rb:1030:in `find_in_unresolved_tree' 5: from /home/deivid/.rbenv/versions/2.7.2/lib/ruby/site_ruby/2.7.0/rubygems/specification.rb:1030:in `each' 4: from /home/deivid/.rbenv/versions/2.7.2/lib/ruby/site_ruby/2.7.0/rubygems/specification.rb:1031:in `block in find_in_unresolved_tree' 3: from /home/deivid/.rbenv/versions/2.7.2/lib/ruby/site_ruby/2.7.0/rubygems/specification.rb:2551:in `traverse' 2: from /home/deivid/.rbenv/versions/2.7.2/lib/ruby/site_ruby/2.7.0/rubygems/specification.rb:2551:in `each' 1: from /home/deivid/.rbenv/versions/2.7.2/lib/ruby/site_ruby/2.7.0/rubygems/specification.rb:2553:in `block in traverse' /home/deivid/.rbenv/versions/2.7.2/lib/ruby/site_ruby/2.7.0/rubygems/dependency.rb:309:in `to_specs': Could not find 'mini_portile2' (~> 2.4.0) - did find: [mini_portile2-2.5.0] (Gem::MissingSpecVersionError) Checked in 'GEM_PATH=/home/deivid/.gem/ruby/2.7.0:/home/deivid/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0' , execute `gem env` for more information 6: from /home/deivid/.rbenv/versions/2.7.2/bin/rails:23:in `
' 5: from /home/deivid/.rbenv/versions/2.7.2/lib/ruby/site_ruby/2.7.0/rubygems.rb:301:in `activate_bin_path' 4: from /home/deivid/.rbenv/versions/2.7.2/lib/ruby/site_ruby/2.7.0/rubygems.rb:301:in `synchronize' 3: from /home/deivid/.rbenv/versions/2.7.2/lib/ruby/site_ruby/2.7.0/rubygems.rb:303:in `block in activate_bin_path' 2: from /home/deivid/.rbenv/versions/2.7.2/lib/ruby/site_ruby/2.7.0/rubygems.rb:236:in `finish_resolve' 1: from /home/deivid/.rbenv/versions/2.7.2/lib/ruby/site_ruby/2.7.0/rubygems/core_ext/kernel_require.rb:167:in `require' /home/deivid/.rbenv/versions/2.7.2/lib/ruby/site_ruby/2.7.0/rubygems/core_ext/kernel_require.rb:167:in `ensure in require': CRITICAL: RUBYGEMS_ACTIVATION_MONITOR.owned?: before false -> after true (RuntimeError) ``` In this case, the underlying problem is that I have this list of versions of nokogiri on my system: ``` $ gem list nokogiri *** LOCAL GEMS *** nokogiri (1.11.1 x86_64-linux, 1.11.0 x86_64-linux, 1.10.8, 1.10.1) ``` And one of them, 1.10.8, has orphaned dependencies: ``` $ gem specification nokogiri -v 1.10.8 --ruby|grep runtime_dependency.*mini_portile s.add_runtime_dependency(%q.freeze, ["~> 2.4.0"]) $ gem list mini_portile2 *** LOCAL GEMS *** mini_portile2 (2.5.0) ``` This gem version is irrelevant to this case, since a higher version will be activated, so there's no need to crash with such a weird error. --- test/rubygems/test_gem.rb | 52 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 68e3eccd..9e7581cb 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -297,6 +297,58 @@ def test_activate_bin_path_resolves_eagerly assert_equal %w[a-1 b-2 c-1], loaded_spec_names end + def test_activate_bin_path_does_not_error_if_a_gem_thats_not_finally_activated_has_orphaned_dependencies + a1 = util_spec 'a', '1' do |s| + s.executables = ['exec'] + s.add_dependency 'b' + end + + b1 = util_spec 'b', '1' do |s| + s.add_dependency 'c', '1' + end + + b2 = util_spec 'b', '2' do |s| + s.add_dependency 'c', '2' + end + + c2 = util_spec 'c', '2' + + install_specs c2, b1, b2, a1 + + # c1 is missing, but not needed for activation, so we should not get any errors here + + Gem.activate_bin_path("a", "exec", ">= 0") + + assert_equal %w[a-1 b-2 c-2], loaded_spec_names + end + + def test_activate_bin_path_raises_a_meaningful_error_if_a_gem_thats_finally_activated_has_orphaned_dependencies + a1 = util_spec 'a', '1' do |s| + s.executables = ['exec'] + s.add_dependency 'b' + end + + b1 = util_spec 'b', '1' do |s| + s.add_dependency 'c', '1' + end + + b2 = util_spec 'b', '2' do |s| + s.add_dependency 'c', '2' + end + + c1 = util_spec 'c', '1' + + install_specs c1, b1, b2, a1 + + # c2 is missing, and b2 which has it as a dependency will be activated, so we should get an error about the orphaned dependency + + e = assert_raises Gem::UnsatisfiableDependencyError do + load Gem.activate_bin_path("a", "exec", ">= 0") + end + + assert_equal "Unable to resolve dependency: 'b (>= 0)' requires 'c (= 2)'", e.message + end + def test_activate_bin_path_in_debug_mode a1 = util_spec 'a', '1' do |s| s.executables = ['exec'] From f0c9a12da669cf4998dcfdd0cc34228513b1ee1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Mon, 8 Feb 2021 12:51:05 +0100 Subject: [PATCH 616/707] Fix error message when underscore selection can't find bundler If underscore version selection is given to the gem CLI, like `bundle _2.2.8_ install`, and the given version can't be found, rubygems will erroneously mentioned the `BUNDLED WITH` version in the lockfile if present, rather than the version given in the CLI. --- test/rubygems/test_gem.rb | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 9e7581cb..1c6d790b 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -468,6 +468,32 @@ def test_activate_bin_path_respects_underscore_selection_if_given assert_equal %w[bundler-1.17.3], loaded_spec_names end + def test_activate_bin_path_gives_proper_error_for_bundler_when_underscore_selection_given + File.open("Gemfile.lock", "w") do |f| + f.write <<-L.gsub(/ {8}/, "") + GEM + remote: https://rubygems.org/ + specs: + + PLATFORMS + ruby + + DEPENDENCIES + + BUNDLED WITH + 2.1.4 + L + end + + File.open("Gemfile", "w") {|f| f.puts('source "https://rubygems.org"') } + + e = assert_raises Gem::GemNotFoundException do + load Gem.activate_bin_path("bundler", "bundle", "= 2.2.8") + end + + assert_equal "can't find gem bundler (= 2.2.8) with executable bundle", e.message + end + def test_self_bin_path_no_exec_name e = assert_raises ArgumentError do Gem.bin_path 'a' From be2fb97afae9e5a44ae34db9400db67a49908af6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Tue, 19 Jan 2021 11:35:03 +0100 Subject: [PATCH 617/707] Raise consistent errors when gem not found in source We were raising a slightly different error depending on whether the gem had a specific source requirement (a few lines above) or not. Make it consistent so that starting to enforce specific sources for all requirements doesn't make specs fail. --- test/rubygems/test_gem.rb | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 1c6d790b..2de67a55 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1958,15 +1958,8 @@ def test_use_gemdeps_missing_gem io.write 'gem "a"' end - platform = Bundler::GemHelpers.generic_local_platform - if platform == Gem::Platform::RUBY - platform = '' - else - platform = " #{platform}" - end - expected = <<-EXPECTED -Could not find gem 'a#{platform}' in any of the gem sources listed in your Gemfile. +Could not find gem 'a' in any of the gem sources listed in your Gemfile. You may need to `gem install -g` to install missing gems EXPECTED From 084ac9c8308bd1a54ce7e131c366710d7358347a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Wed, 10 Feb 2021 22:46:15 +0100 Subject: [PATCH 618/707] Enable `disable_multisource` functionality by default We have several source priority bug fixes in master that we have never released because they need the `disable_multisource` setting toggled, and that will only happen by default in Bundler 3. The reason for this is that this setting drops support for multiple global sources in the `gems.rb` file, and also enables separate sections for each rubygems source in the lockfile. We considered this to be backwards incompatible, although I'm not sure that was the right call after looking into this. So this commit enables the functionality by default, and completely removes the `disable_multisource` setting. The only backwards compatible concern I'm having is when some is using a lokfile in the old format in frozen mode. In that case, to not break any workflows, we print a warning and still use that lockfile. Also, plugins still need the previous functionality. I think this can probably be fixed later, but I'm not doing that here. In every other case, we will run in the new secure mode and update the `Gemfile.lock` file with the new format. --- test/rubygems/test_gem.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 2de67a55..8b028d34 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1959,7 +1959,8 @@ def test_use_gemdeps_missing_gem end expected = <<-EXPECTED -Could not find gem 'a' in any of the gem sources listed in your Gemfile. +Could not find gem 'a' in locally installed gems. +The source does not contain any versions of 'a' You may need to `gem install -g` to install missing gems EXPECTED From 45e276efe547ea73e8b4a0007be21fbc4f600c18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Wed, 17 Feb 2021 07:02:01 +0100 Subject: [PATCH 619/707] Revert "Merge pull request #3655 from rubygems/disable_multisource_improvements" This reverts commit c9850f7b80f8ce2902ac2adfc46f79c87b16f9b2, reversing changes made to 22fb661dacc9cd905d43d77bf88399f746e09dda. --- test/rubygems/test_gem.rb | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 8b028d34..1c6d790b 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1958,9 +1958,15 @@ def test_use_gemdeps_missing_gem io.write 'gem "a"' end + platform = Bundler::GemHelpers.generic_local_platform + if platform == Gem::Platform::RUBY + platform = '' + else + platform = " #{platform}" + end + expected = <<-EXPECTED -Could not find gem 'a' in locally installed gems. -The source does not contain any versions of 'a' +Could not find gem 'a#{platform}' in any of the gem sources listed in your Gemfile. You may need to `gem install -g` to install missing gems EXPECTED From f87d089319477fed78254418c0d1e8a86c1f71f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Tue, 19 Jan 2021 11:35:03 +0100 Subject: [PATCH 620/707] Raise consistent errors when gem not found in source We were raising a slightly different error depending on whether the gem had a specific source requirement (a few lines above) or not. Make it consistent so that starting to enforce specific sources for all requirements doesn't make specs fail. --- test/rubygems/test_gem.rb | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 1c6d790b..2de67a55 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1958,15 +1958,8 @@ def test_use_gemdeps_missing_gem io.write 'gem "a"' end - platform = Bundler::GemHelpers.generic_local_platform - if platform == Gem::Platform::RUBY - platform = '' - else - platform = " #{platform}" - end - expected = <<-EXPECTED -Could not find gem 'a#{platform}' in any of the gem sources listed in your Gemfile. +Could not find gem 'a' in any of the gem sources listed in your Gemfile. You may need to `gem install -g` to install missing gems EXPECTED From 8421d385be5c902816aad30b623138e61f730648 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Thu, 18 Feb 2021 20:24:06 +0100 Subject: [PATCH 621/707] Fix issue with source requirements Make sure there's always a global source, and make sure all direct dependencies always have an explicit source. Previously, top level dependencies without a block or explicit source could be picked up from any unrelated sources in the Gemfile. Now they give a "Not found" error unless they exist in the default source. As a consequence, error messages are now more specific too. --- test/rubygems/test_gem.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 2de67a55..8b028d34 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1959,7 +1959,8 @@ def test_use_gemdeps_missing_gem end expected = <<-EXPECTED -Could not find gem 'a' in any of the gem sources listed in your Gemfile. +Could not find gem 'a' in locally installed gems. +The source does not contain any versions of 'a' You may need to `gem install -g` to install missing gems EXPECTED From 0e76e85944779c2685478fc81f987d2fce634964 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Wed, 7 Apr 2021 15:45:35 +0200 Subject: [PATCH 622/707] Bump patch level versions of ruby Also bump parser development dependency to be compatible with the new patch levels. --- bundler/spec/realworld/edgecases_spec.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index 1925f76c..9f6ae399 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -349,14 +349,14 @@ def rubygems_version(name, requirement) end it "doesn't hang on big gemfile" do - skip "Only for ruby 2.7.2" if RUBY_VERSION != "2.7.2" + skip "Only for ruby 2.7.3" if RUBY_VERSION != "2.7.3" gemfile <<~G # frozen_string_literal: true source "https://rubygems.org" - ruby "2.7.2" + ruby "2.7.3" gem "rails" gem "pg", ">= 0.18", "< 2.0" @@ -461,7 +461,7 @@ def rubygems_version(name, requirement) end it "doesn't hang on tricky gemfile" do - skip "Only for ruby 2.7.2" if RUBY_VERSION != "2.7.2" + skip "Only for ruby 2.7.3" if RUBY_VERSION != "2.7.3" gemfile <<~G source 'https://rubygems.org' @@ -487,7 +487,7 @@ def rubygems_version(name, requirement) end it "doesn't hang on nix gemfile" do - skip "Only for ruby 3.0.0" if RUBY_VERSION != "3.0.0" + skip "Only for ruby 3.0.1" if RUBY_VERSION != "3.0.1" gemfile <<~G source "https://rubygems.org" do From b56a79058d4e64392797b931386adddfbca997bf Mon Sep 17 00:00:00 2001 From: Maxim Patlasov Date: Wed, 5 May 2021 10:13:30 -0700 Subject: [PATCH 623/707] Add unit tests for envra.py Summary: The diff only adds tests. Reviewed By: snarkmaster Differential Revision: D28208931 fbshipit-source-id: ef024766c18ca49d980b160d23a6f8b2b1efdef6 --- .../rpm/allowed_versions/tests/test_envra.py | 140 ++++++++++++++++++ 1 file changed, 140 insertions(+) create mode 100644 antlir/rpm/allowed_versions/tests/test_envra.py diff --git a/antlir/rpm/allowed_versions/tests/test_envra.py b/antlir/rpm/allowed_versions/tests/test_envra.py new file mode 100644 index 00000000..7fdde92e --- /dev/null +++ b/antlir/rpm/allowed_versions/tests/test_envra.py @@ -0,0 +1,140 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +from functools import total_ordering +from unittest import TestCase + +from antlir.rpm.rpm_metadata import RpmMetadata + +from ..envra import SortableEVRA, SortableENVRA + + +class EnvraTestCase(TestCase): + def test_evra_is_envra(self): + self.assertIs(SortableEVRA, SortableENVRA) + + def test_eq(self): + e = SortableENVRA(epoch=0, name="n", version="v", release="r", arch="a") + self.assertEqual(e, e) + + def test_lt(self): + e0 = SortableENVRA( + epoch=0, name="n", version="v", release="r", arch="a" + ) + e1 = SortableENVRA( + epoch=1, name="n", version="v", release="r", arch="a" + ) + self.assertTrue(e0 < e1) + + def test_repr(self): + e = SortableENVRA(epoch=0, name="n", version="v", release="r", arch="a") + self.assertEqual(str(e), "0:n-v-r-a") + epoch_none = SortableENVRA( + epoch=None, name="n", version="v", release="r", arch="a" + ) + self.assertEqual(str(epoch_none), "*:n-v-r-a") + name_none = SortableENVRA( + epoch=0, name=None, version="v", release="r", arch="a" + ) + self.assertEqual(str(name_none), "0:*-v-r-a") + + def test_to_versionlock_line_raise(self): + epoch_none = SortableENVRA( + epoch=None, name="n", version="v", release="r", arch="a" + ) + with self.assertRaises(ValueError): + epoch_none.to_versionlock_line() + name_none = SortableENVRA( + epoch=0, name=None, version="v", release="r", arch="a" + ) + with self.assertRaises(ValueError): + name_none.to_versionlock_line() + + def test_to_versionlock_line_returns(self): + e = SortableENVRA(epoch=0, name="n", version="v", release="r", arch="a") + self.assertEqual(e.to_versionlock_line(), "0\tn\tv\tr\ta") + + def test_compare_returns_negative(self): + e0 = SortableENVRA( + epoch=0, name="m", version="v", release="r", arch="a" + ) + e1 = SortableENVRA( + epoch=0, name="n", version="v", release="r", arch="a" + ) + self.assertTrue(e0 < e1) + + def test_compare_raise(self): + @total_ordering + class Crazy: + def __eq__(self, other): + return False + + def __lt__(self, other): + return False + + def __gt__(self, other): + return False + + e0 = SortableENVRA( + epoch=0, name=Crazy(), version="v", release="r", arch="a" + ) + e1 = SortableENVRA( + epoch=0, name=Crazy(), version="v", release="r", arch="a" + ) + with self.assertRaises(AssertionError): + self.assertTrue(e0 < e1) + + def test_compare_both_epochs_wildcard(self): + e = SortableENVRA( + epoch=None, name="n", version="v", release="r", arch="a" + ) + self.assertEqual(e, e) + + def test_compare_one_epoch_wildcard(self): + e0 = SortableENVRA( + epoch=None, name="n", version="v", release="r", arch="a" + ) + e1 = SortableENVRA( + epoch=0, name="n", version="v", release="r", arch="a" + ) + with self.assertRaises(TypeError): + self.assertEqual(e0, e1) + + def test_compare_self_greater_than_other(self): + e0 = SortableENVRA( + epoch=0, name="n", version="v", release="r", arch="a" + ) + e1 = SortableENVRA( + epoch=0, name="m", version="v", release="r", arch="a" + ) + self.assertFalse(e0 < e1) + + def test_compare_both_names_wildcard(self): + e = SortableENVRA( + epoch=0, name=None, version="v", release="r", arch="a" + ) + self.assertEqual(e, e) + + def test_compare_one_name_wildcard(self): + e0 = SortableENVRA( + epoch=0, name=None, version="v", release="r", arch="a" + ) + e1 = SortableENVRA( + epoch=0, name="n", version="v", release="r", arch="a" + ) + with self.assertRaises(TypeError): + self.assertEqual(e0, e1) + + def test_as_rpm_metadata_returns(self): + e = SortableENVRA(epoch=0, name="n", version="v", release="r", arch="a") + rpm_metadata = RpmMetadata(name="n", epoch=0, version="v", release="r") + self.assertEqual(e.as_rpm_metadata(), rpm_metadata) + + def test_as_rpm_metadata_raise(self): + e = SortableENVRA( + epoch=None, name="n", version="v", release="r", arch="a" + ) + with self.assertRaises(TypeError): + e.as_rpm_metadata() From 278f75e4a723062da8a8e92824c93772c1c4d722 Mon Sep 17 00:00:00 2001 From: Maxim Patlasov Date: Wed, 5 May 2021 10:13:30 -0700 Subject: [PATCH 624/707] Support wildcard arch in envra.py Summary: Wildcard arch is useful for version policy which does not define arch. Reviewed By: zeroxoneb Differential Revision: D28209995 fbshipit-source-id: 2f5c748fa37d2275456977d685142586fcda3266 --- antlir/rpm/allowed_versions/envra.py | 14 +++++++++----- .../rpm/allowed_versions/tests/test_envra.py | 18 ++++++++++++++++-- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/antlir/rpm/allowed_versions/envra.py b/antlir/rpm/allowed_versions/envra.py index 0067cc1f..d9473842 100644 --- a/antlir/rpm/allowed_versions/envra.py +++ b/antlir/rpm/allowed_versions/envra.py @@ -57,9 +57,10 @@ def as_rpm_metadata(self) -> RpmMetadata: # # Future: move the check for these comparisons out of this class # and into `compare_rpm_versions`. - if self.epoch is None: + if self.epoch is None or self.arch is None: raise TypeError( - f"Cannot use `as_rpm_metadata()` with wildcard epoch: {self}" + "Cannot use `as_rpm_metadata()` with wildcard epoch or arch: " + f"{self}" ) return self._as_rpm_metadata() @@ -100,8 +101,10 @@ def __lt__(self, other: "SortableENVRA") -> bool: return self._compare(other) < 0 def to_versionlock_line(self) -> str: - if self.epoch is None or self.name is None: - raise ValueError(f"Versionlock needs concrete name & epoch: {self}") + if self.epoch is None or self.name is None or self.arch is None: + raise ValueError( + f"Versionlock needs concrete name & epoch & arch: {self}" + ) # Our `yum_dnf_versionlock.py` expects TAB-separated ENVRAs. return "\t".join( [str(self.epoch), self.name, self.version, self.release, self.arch] @@ -110,7 +113,8 @@ def to_versionlock_line(self) -> str: def __repr__(self) -> str: epoch = "*" if self.epoch is None else self.epoch name = "*" if self.name is None else self.name - return f"{epoch}:{name}-{self.version}-{self.release}-{self.arch}" + arch = "*" if self.arch is None else self.arch + return f"{epoch}:{name}-{self.version}-{self.release}-{arch}" # As a type-hint, this alias represents the fact that the `name` must be diff --git a/antlir/rpm/allowed_versions/tests/test_envra.py b/antlir/rpm/allowed_versions/tests/test_envra.py index 7fdde92e..147e326a 100644 --- a/antlir/rpm/allowed_versions/tests/test_envra.py +++ b/antlir/rpm/allowed_versions/tests/test_envra.py @@ -39,6 +39,10 @@ def test_repr(self): epoch=0, name=None, version="v", release="r", arch="a" ) self.assertEqual(str(name_none), "0:*-v-r-a") + arch_none = SortableENVRA( + epoch=0, name="n", version="v", release="r", arch=None + ) + self.assertEqual(str(arch_none), "0:n-v-r-*") def test_to_versionlock_line_raise(self): epoch_none = SortableENVRA( @@ -51,6 +55,11 @@ def test_to_versionlock_line_raise(self): ) with self.assertRaises(ValueError): name_none.to_versionlock_line() + arch_none = SortableENVRA( + epoch=0, name="n", version="v", release="r", arch=None + ) + with self.assertRaises(ValueError): + arch_none.to_versionlock_line() def test_to_versionlock_line_returns(self): e = SortableENVRA(epoch=0, name="n", version="v", release="r", arch="a") @@ -133,8 +142,13 @@ def test_as_rpm_metadata_returns(self): self.assertEqual(e.as_rpm_metadata(), rpm_metadata) def test_as_rpm_metadata_raise(self): - e = SortableENVRA( + epoch_none = SortableENVRA( epoch=None, name="n", version="v", release="r", arch="a" ) with self.assertRaises(TypeError): - e.as_rpm_metadata() + epoch_none.as_rpm_metadata() + arch_none = SortableENVRA( + epoch=0, name="n", version="v", release="r", arch=None + ) + with self.assertRaises(TypeError): + arch_none.as_rpm_metadata() From cf664078ab704e2cfaa429b44449f9eb3eadc080 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Sat, 29 Jun 2019 20:16:49 +0900 Subject: [PATCH 625/707] Use capture_output instead of capture_io. --- test/rubygems/test_gem.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 8b028d34..4f99bc8e 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1389,7 +1389,7 @@ def test_self_try_activate_missing_extensions io.write spec.to_ruby_for_cache end - _, err = capture_io do + _, err = capture_output do refute Gem.try_activate 'nonexistent' end @@ -1414,7 +1414,7 @@ def test_self_use_paths_with_nils end def test_setting_paths_does_not_warn_about_unknown_keys - stdout, stderr = capture_io do + stdout, stderr = capture_output do Gem.paths = { 'foo' => [], 'bar' => Object.new, 'GEM_HOME' => Gem.paths.home, @@ -1432,7 +1432,7 @@ def test_setting_paths_does_not_mutate_parameter_object end def test_deprecated_paths= - stdout, stderr = capture_io do + stdout, stderr = capture_output do Gem.paths = { 'GEM_HOME' => Gem.paths.home, 'GEM_PATH' => [Gem.paths.home, 'foo'] } end @@ -2073,7 +2073,7 @@ def with_plugin(path) refute_includes $LOAD_PATH, test_plugin_path $LOAD_PATH.unshift test_plugin_path - capture_io do + capture_output do yield end ensure From fdde916523274db0a07094fae999ceca93a996b6 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Wed, 18 Mar 2020 17:56:41 +0900 Subject: [PATCH 626/707] Extract assert_output to assert_empty and assert_equal with capture_output --- test/rubygems/test_gem.rb | 4 +++- test/rubygems/test_gem_version.rb | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 4f99bc8e..b3c8a7ab 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1966,9 +1966,11 @@ def test_use_gemdeps_missing_gem EXPECTED Gem::Deprecate.skip_during do - assert_output nil, expected do + actual_stdout, actual_stderr = capture_output do Gem.use_gemdeps end + assert_empty actual_stdout + assert_equal(expected, actual_stderr) end ensure ENV['RUBYGEMS_GEMDEPS'] = rubygems_gemdeps diff --git a/test/rubygems/test_gem_version.rb b/test/rubygems/test_gem_version.rb index 7b382809..af37434d 100644 --- a/test/rubygems/test_gem_version.rb +++ b/test/rubygems/test_gem_version.rb @@ -47,9 +47,11 @@ def test_class_correct assert_equal false, Gem::Version.correct?("an incorrect version") expected = "nil versions are discouraged and will be deprecated in Rubygems 4\n" - assert_output nil, expected do + actual_stdout, actual_stderr = capture_output do Gem::Version.correct?(nil) end + assert_empty actual_stdout + assert_equal(expected, actual_stderr) end def test_class_new_subclass From aa3ba51d0ba8fcc823557b380b59544042ae7f6e Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Mon, 25 May 2020 21:05:45 +0900 Subject: [PATCH 627/707] Use assert_path_exist and assert_path_not_exist instead of assert_path_exists and refute_path_exists --- test/rubygems/test_gem.rb | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index b3c8a7ab..2b39301a 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -106,7 +106,7 @@ def test_self_install assert_equal %w[a-1], installed.map {|spec| spec.full_name } - assert_path_exists File.join(gemhome2, 'gems', 'a-1') + assert_path_exist File.join(gemhome2, 'gems', 'a-1') end def test_self_install_in_rescue @@ -692,12 +692,12 @@ def test_self_ensure_gem_directories Gem.ensure_gem_subdirectories @gemhome - assert_path_exists File.join @gemhome, 'build_info' - assert_path_exists File.join @gemhome, 'cache' - assert_path_exists File.join @gemhome, 'doc' - assert_path_exists File.join @gemhome, 'extensions' - assert_path_exists File.join @gemhome, 'gems' - assert_path_exists File.join @gemhome, 'specifications' + assert_path_exist File.join @gemhome, 'build_info' + assert_path_exist File.join @gemhome, 'cache' + assert_path_exist File.join @gemhome, 'doc' + assert_path_exist File.join @gemhome, 'extensions' + assert_path_exist File.join @gemhome, 'gems' + assert_path_exist File.join @gemhome, 'specifications' end def test_self_ensure_gem_directories_permissions From 761a6ed598db65dbf5a70393d87dd22a976ca222 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Tue, 11 May 2021 12:25:46 +0900 Subject: [PATCH 628/707] Use assert_raise instead of assert_raises --- test/rubygems/test_gem.rb | 32 +++++++++++++++---------------- test/rubygems/test_gem_version.rb | 2 +- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 2b39301a..5192b975 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -212,7 +212,7 @@ def assert_self_install_permissions(format_executable: false) def test_require_missing save_loaded_features do - assert_raises ::LoadError do + assert_raise ::LoadError do require "test_require_missing" end end @@ -224,7 +224,7 @@ def test_require_does_not_glob install_specs a1 - assert_raises ::LoadError do + assert_raise ::LoadError do require "a*" end @@ -261,7 +261,7 @@ def test_self_bin_path_picking_newest end def test_self_activate_bin_path_no_exec_name - e = assert_raises ArgumentError do + e = assert_raise ArgumentError do Gem.activate_bin_path 'a' end @@ -342,7 +342,7 @@ def test_activate_bin_path_raises_a_meaningful_error_if_a_gem_thats_finally_acti # c2 is missing, and b2 which has it as a dependency will be activated, so we should get an error about the orphaned dependency - e = assert_raises Gem::UnsatisfiableDependencyError do + e = assert_raise Gem::UnsatisfiableDependencyError do load Gem.activate_bin_path("a", "exec", ">= 0") end @@ -390,7 +390,7 @@ def test_activate_bin_path_gives_proper_error_for_bundler File.open("Gemfile", "w") {|f| f.puts('source "https://rubygems.org"') } - e = assert_raises Gem::GemNotFoundException do + e = assert_raise Gem::GemNotFoundException do load Gem.activate_bin_path("bundler", "bundle", ">= 0.a") end @@ -487,7 +487,7 @@ def test_activate_bin_path_gives_proper_error_for_bundler_when_underscore_select File.open("Gemfile", "w") {|f| f.puts('source "https://rubygems.org"') } - e = assert_raises Gem::GemNotFoundException do + e = assert_raise Gem::GemNotFoundException do load Gem.activate_bin_path("bundler", "bundle", "= 2.2.8") end @@ -495,7 +495,7 @@ def test_activate_bin_path_gives_proper_error_for_bundler_when_underscore_select end def test_self_bin_path_no_exec_name - e = assert_raises ArgumentError do + e = assert_raise ArgumentError do Gem.bin_path 'a' end @@ -516,20 +516,20 @@ def test_self_bin_path_nonexistent_binfile util_spec 'a', '2' do |s| s.executables = ['exec'] end - assert_raises(Gem::GemNotFoundException) do + assert_raise(Gem::GemNotFoundException) do Gem.bin_path('a', 'other', '2') end end def test_self_bin_path_no_bin_file util_spec 'a', '1' - assert_raises(ArgumentError) do + assert_raise(ArgumentError) do Gem.bin_path('a', nil, '1') end end def test_self_bin_path_not_found - assert_raises(Gem::GemNotFoundException) do + assert_raise(Gem::GemNotFoundException) do Gem.bin_path('non-existent', 'blah') end end @@ -596,7 +596,7 @@ def test_self_datadir end def test_self_datadir_nonexistent_package - assert_raises(Gem::MissingSpecError) do + assert_raise(Gem::MissingSpecError) do Gem::Specification.find_by_name("xyzzy").datadir end end @@ -1144,7 +1144,7 @@ def test_self_env_requirement assert_equal Gem::Requirement.create('>= 1.2.3'), Gem.env_requirement('foo') assert_equal Gem::Requirement.create('1.2.3'), Gem.env_requirement('bAr') - assert_raises(Gem::Requirement::BadRequirementError) { Gem.env_requirement('baz') } + assert_raise(Gem::Requirement::BadRequirementError) { Gem.env_requirement('baz') } assert_equal Gem::Requirement.default, Gem.env_requirement('qux') end @@ -1349,7 +1349,7 @@ def test_self_try_activate_missing_dep io.puts '# a_file.rb' end - e = assert_raises Gem::MissingSpecError do + e = assert_raise Gem::MissingSpecError do Gem.try_activate 'a_file' end @@ -1370,7 +1370,7 @@ def test_self_try_activate_missing_prerelease io.puts '# a_file.rb' end - e = assert_raises Gem::MissingSpecError do + e = assert_raise Gem::MissingSpecError do Gem.try_activate 'a_file' end @@ -1881,7 +1881,7 @@ def test_use_gemdeps_ENV end def test_use_gemdeps_argument_missing - e = assert_raises ArgumentError do + e = assert_raise ArgumentError do Gem.use_gemdeps 'gem.deps.rb' end @@ -1893,7 +1893,7 @@ def test_use_gemdeps_argument_missing_match_ENV rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], 'gem.deps.rb' - e = assert_raises ArgumentError do + e = assert_raise ArgumentError do Gem.use_gemdeps 'gem.deps.rb' end diff --git a/test/rubygems/test_gem_version.rb b/test/rubygems/test_gem_version.rb index af37434d..f57aa104 100644 --- a/test/rubygems/test_gem_version.rb +++ b/test/rubygems/test_gem_version.rb @@ -102,7 +102,7 @@ def test_initialize_invalid invalid_versions << "2.3422222.222.222222222.22222.ads0as.dasd0.ddd2222.2.qd3e." invalid_versions.each do |invalid| - e = assert_raises ArgumentError, invalid do + e = assert_raise ArgumentError, invalid do Gem::Version.new invalid end From 938eeed7c93e17c205977e523eb6a689eed3193d Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Tue, 11 May 2021 12:27:07 +0900 Subject: [PATCH 629/707] Use pend instead of skip --- test/rubygems/test_gem.rb | 6 +++--- test/rubygems/test_gem_version.rb | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 5192b975..d548e95f 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1058,7 +1058,7 @@ def test_self_read_binary assert_equal ["\xCF", "\x80"], Gem.read_binary('test').chars.to_a - skip 'chmod not supported' if Gem.win_platform? + pend 'chmod not supported' if Gem.win_platform? begin File.chmod 0444, 'test' @@ -1727,7 +1727,7 @@ def add_bundler_full_name(names) end def test_looks_for_gemdeps_files_automatically_on_start - skip "Requiring bundler messes things up" if Gem.java_platform? + pend "Requiring bundler messes things up" if Gem.java_platform? a = util_spec "a", "1", nil, "lib/a.rb" b = util_spec "b", "1", nil, "lib/b.rb" @@ -1763,7 +1763,7 @@ def test_looks_for_gemdeps_files_automatically_on_start end def test_looks_for_gemdeps_files_automatically_on_start_in_parent_dir - skip "Requiring bundler messes things up" if Gem.java_platform? + pend "Requiring bundler messes things up" if Gem.java_platform? a = util_spec "a", "1", nil, "lib/a.rb" b = util_spec "b", "1", nil, "lib/b.rb" diff --git a/test/rubygems/test_gem_version.rb b/test/rubygems/test_gem_version.rb index f57aa104..47c8b058 100644 --- a/test/rubygems/test_gem_version.rb +++ b/test/rubygems/test_gem_version.rb @@ -116,7 +116,7 @@ def bench_anchored_version_pattern version_string =~ Gem::Version::ANCHORED_VERSION_PATTERN end rescue RegexpError - skip "It fails to allocate the memory for regex pattern of Gem::Version::ANCHORED_VERSION_PATTERN" + pend "It fails to allocate the memory for regex pattern of Gem::Version::ANCHORED_VERSION_PATTERN" end def test_empty_version From 8f12e6904dd13a0d8722f37bbf4a727b1a609221 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Tue, 11 May 2021 12:25:46 +0900 Subject: [PATCH 630/707] Use assert_raise instead of assert_raises --- test/rubygems/test_gem_requirement.rb | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/test/rubygems/test_gem_requirement.rb b/test/rubygems/test_gem_requirement.rb index 13897eae..c4f05342 100644 --- a/test/rubygems/test_gem_requirement.rb +++ b/test/rubygems/test_gem_requirement.rb @@ -97,7 +97,7 @@ def test_parse_bad '= junk', '1..2', ].each do |bad| - e = assert_raises Gem::Requirement::BadRequirementError do + e = assert_raise Gem::Requirement::BadRequirementError do Gem::Requirement.parse bad end @@ -128,7 +128,7 @@ def test_satisfied_by_eh_bang_equal refute_satisfied_by "1.2", r assert_satisfied_by "1.3", r - assert_raises ArgumentError do + assert_raise ArgumentError do assert_satisfied_by nil, r end end @@ -140,7 +140,7 @@ def test_satisfied_by_eh_blank assert_satisfied_by "1.2", r refute_satisfied_by "1.3", r - assert_raises ArgumentError do + assert_raise ArgumentError do assert_satisfied_by nil, r end end @@ -152,7 +152,7 @@ def test_satisfied_by_eh_equal assert_satisfied_by "1.2", r refute_satisfied_by "1.3", r - assert_raises ArgumentError do + assert_raise ArgumentError do assert_satisfied_by nil, r end end @@ -164,7 +164,7 @@ def test_satisfied_by_eh_gt refute_satisfied_by "1.2", r assert_satisfied_by "1.3", r - assert_raises ArgumentError do + assert_raise ArgumentError do r.satisfied_by? nil end end @@ -176,7 +176,7 @@ def test_satisfied_by_eh_gte assert_satisfied_by "1.2", r assert_satisfied_by "1.3", r - assert_raises ArgumentError do + assert_raise ArgumentError do r.satisfied_by? nil end end @@ -188,7 +188,7 @@ def test_satisfied_by_eh_list assert_satisfied_by "1.2", r refute_satisfied_by "1.3", r - assert_raises ArgumentError do + assert_raise ArgumentError do r.satisfied_by? nil end end @@ -200,7 +200,7 @@ def test_satisfied_by_eh_lt refute_satisfied_by "1.2", r refute_satisfied_by "1.3", r - assert_raises ArgumentError do + assert_raise ArgumentError do r.satisfied_by? nil end end @@ -212,7 +212,7 @@ def test_satisfied_by_eh_lte assert_satisfied_by "1.2", r refute_satisfied_by "1.3", r - assert_raises ArgumentError do + assert_raise ArgumentError do r.satisfied_by? nil end end @@ -224,7 +224,7 @@ def test_satisfied_by_eh_tilde_gt assert_satisfied_by "1.2", r assert_satisfied_by "1.3", r - assert_raises ArgumentError do + assert_raise ArgumentError do r.satisfied_by? nil end end @@ -281,18 +281,18 @@ def test_satisfied_by_eh_good def test_illformed_requirements [ ">>> 1.3.5", "> blah" ].each do |rq| - assert_raises Gem::Requirement::BadRequirementError, "req [#{rq}] should fail" do + assert_raise Gem::Requirement::BadRequirementError, "req [#{rq}] should fail" do Gem::Requirement.new rq end end end def test_satisfied_by_eh_non_versions - assert_raises ArgumentError do + assert_raise ArgumentError do req(">= 0").satisfied_by? Object.new end - assert_raises ArgumentError do + assert_raise ArgumentError do req(">= 0").satisfied_by? Gem::Requirement.default end end From bf2cc780135f300b124a55386be3eff811368302 Mon Sep 17 00:00:00 2001 From: Hiroshi SHIBATA Date: Tue, 11 May 2021 13:48:16 +0900 Subject: [PATCH 631/707] Revert 294f5d2599f4254bd144282d065c08f5e1f094ef Because test-unit didn't provide the benchman test. And This test is fragile with the several environments. --- test/rubygems/test_gem_version.rb | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/test/rubygems/test_gem_version.rb b/test/rubygems/test_gem_version.rb index 47c8b058..91325c22 100644 --- a/test/rubygems/test_gem_version.rb +++ b/test/rubygems/test_gem_version.rb @@ -2,8 +2,6 @@ require 'rubygems/test_case' require "rubygems/version" -require "minitest/benchmark" - class TestGemVersion < Gem::TestCase class V < ::Gem::Version end @@ -110,15 +108,6 @@ def test_initialize_invalid end end - def bench_anchored_version_pattern - assert_performance_linear 0.5 do |count| - version_string = count.times.map {|i| "0" * i.succ }.join(".") << "." - version_string =~ Gem::Version::ANCHORED_VERSION_PATTERN - end - rescue RegexpError - pend "It fails to allocate the memory for regex pattern of Gem::Version::ANCHORED_VERSION_PATTERN" - end - def test_empty_version ["", " ", " "].each do |empty| assert_equal "0", Gem::Version.new(empty).version From 78de3ee50fc4ce1f4aaebae6948e2da59bd3cbbb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Mon, 10 May 2021 19:41:58 +0200 Subject: [PATCH 632/707] Make specs more realistic In real life, bundler is never required with an absolute path. Make our specs require bundler the way it's required in real life so that the bundler activation code present in rubygems is also tested. --- bundler/spec/realworld/edgecases_spec.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index 9f6ae399..e0844bbe 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -4,9 +4,9 @@ def rubygems_version(name, requirement) ruby <<-RUBY require "#{spec_dir}/support/artifice/vcr" - require "#{lib_dir}/bundler" - require "#{lib_dir}/bundler/source/rubygems/remote" - require "#{lib_dir}/bundler/fetcher" + require "#{entrypoint}" + require "#{entrypoint}/source/rubygems/remote" + require "#{entrypoint}/fetcher" rubygem = Bundler.ui.silence do source = Bundler::Source::Rubygems::Remote.new(Bundler::URI("https://rubygems.org")) fetcher = Bundler::Fetcher.new(source) From b99b32131b8b2a959c4d852e8dd82d04fcd9eb5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Wed, 12 May 2021 11:41:32 +0200 Subject: [PATCH 633/707] Require the new files in `test/` relatively --- test/rubygems/test_gem.rb | 2 +- test/rubygems/test_gem_version.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index d548e95f..ae161701 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1,5 +1,5 @@ # coding: US-ASCII -require 'rubygems/test_case' +require_relative 'test_case' require 'rubygems' require 'rubygems/command' require 'rubygems/installer' diff --git a/test/rubygems/test_gem_version.rb b/test/rubygems/test_gem_version.rb index 91325c22..aa7c4c92 100644 --- a/test/rubygems/test_gem_version.rb +++ b/test/rubygems/test_gem_version.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'test_case' require "rubygems/version" class TestGemVersion < Gem::TestCase From c91327a195a0a3afc086c96a201d613160e171fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Wed, 12 May 2021 11:41:32 +0200 Subject: [PATCH 634/707] Require the new files in `test/` relatively --- test/rubygems/test_gem_requirement.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/rubygems/test_gem_requirement.rb b/test/rubygems/test_gem_requirement.rb index c4f05342..577bcef2 100644 --- a/test/rubygems/test_gem_requirement.rb +++ b/test/rubygems/test_gem_requirement.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true -require 'rubygems/test_case' +require_relative 'test_case' require "rubygems/requirement" class TestGemRequirement < Gem::TestCase From 4e56cbad4c2824bf1c111aec36e96cff6b1bf6a6 Mon Sep 17 00:00:00 2001 From: Yusuke Endoh Date: Wed, 2 Jun 2021 12:32:47 +0900 Subject: [PATCH 635/707] Rename test/rubygems/test_{case,utilities}.rb to avoid "test_" prefix This changes "test/rubygems/test_case.rb" to "test/rubygems/helper.rb", and "test/rubygems/test_utilities.rb" to "test/rubygems/utilities.rb". The two files are a helper for tests, not test files. However, a file starting with "test_" prefix is handled as a test file directly loaded by test-unit because Rakefile specifies: ``` t.test_files = FileList['test/**/test_*.rb'] ``` Directly loading test/rubygems/test_utilities.rb caused "uninitialized constant Gem::TestCase". This issue was fixed by 59c682097197fee4052b47e4b4ab86562f3eaa9b, but the fix caused a "circular require" warning because test_utilities.rb and test_case.rb are now requiring each other. Anyway, adding "test_" prefix to a test helper file is confusing, so this changeset reverts the fix and solve the issue by renaming them. --- test/rubygems/test_gem.rb | 2 +- test/rubygems/test_gem_version.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index ae161701..79ea89e2 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1,5 +1,5 @@ # coding: US-ASCII -require_relative 'test_case' +require_relative 'helper' require 'rubygems' require 'rubygems/command' require 'rubygems/installer' diff --git a/test/rubygems/test_gem_version.rb b/test/rubygems/test_gem_version.rb index aa7c4c92..422e1ee8 100644 --- a/test/rubygems/test_gem_version.rb +++ b/test/rubygems/test_gem_version.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true -require_relative 'test_case' +require_relative 'helper' require "rubygems/version" class TestGemVersion < Gem::TestCase From 53a24d522b3e8caab2e3daa4d3973e494eb180d6 Mon Sep 17 00:00:00 2001 From: Yusuke Endoh Date: Wed, 2 Jun 2021 12:32:47 +0900 Subject: [PATCH 636/707] Rename test/rubygems/test_{case,utilities}.rb to avoid "test_" prefix This changes "test/rubygems/test_case.rb" to "test/rubygems/helper.rb", and "test/rubygems/test_utilities.rb" to "test/rubygems/utilities.rb". The two files are a helper for tests, not test files. However, a file starting with "test_" prefix is handled as a test file directly loaded by test-unit because Rakefile specifies: ``` t.test_files = FileList['test/**/test_*.rb'] ``` Directly loading test/rubygems/test_utilities.rb caused "uninitialized constant Gem::TestCase". This issue was fixed by 59c682097197fee4052b47e4b4ab86562f3eaa9b, but the fix caused a "circular require" warning because test_utilities.rb and test_case.rb are now requiring each other. Anyway, adding "test_" prefix to a test helper file is confusing, so this changeset reverts the fix and solve the issue by renaming them. --- test/rubygems/test_gem_requirement.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/rubygems/test_gem_requirement.rb b/test/rubygems/test_gem_requirement.rb index 577bcef2..f32d13f3 100644 --- a/test/rubygems/test_gem_requirement.rb +++ b/test/rubygems/test_gem_requirement.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true -require_relative 'test_case' +require_relative 'helper' require "rubygems/requirement" class TestGemRequirement < Gem::TestCase From 036a1a572e3762959f6e86ff9b148b9f67bc2dec Mon Sep 17 00:00:00 2001 From: Alexey Spiridonov Date: Tue, 8 Jun 2021 10:20:20 -0700 Subject: [PATCH 637/707] `subvol_rpm_compare` finds RPMs added/removed between two layers Summary: The high-level goal is to be get a precise list of `.rpm` files, and an installation order, so that `rpm -i` can be used to reproduce the descendant layer from the parent. This is a very specific form of incremental replay allowing "image-like" deployment semantics at the level of an RPM package. The advantage of this over e.g. btrfs incremental sendstreams is that the unit of incrementality is understandable, cacheable, and (when needed) hotfixable. The `subvol_rpm_compare()` docblock has specific implementation details. Reviewed By: justintrudell Differential Revision: D28802922 fbshipit-source-id: 2531e5a0b258a904983068eb31483fa356b8943b --- antlir/rpm/replay/subvol_rpm_compare.py | 360 ++++++++++++++++++++++++ 1 file changed, 360 insertions(+) create mode 100644 antlir/rpm/replay/subvol_rpm_compare.py diff --git a/antlir/rpm/replay/subvol_rpm_compare.py b/antlir/rpm/replay/subvol_rpm_compare.py new file mode 100644 index 00000000..502c0d76 --- /dev/null +++ b/antlir/rpm/replay/subvol_rpm_compare.py @@ -0,0 +1,360 @@ +#!/usr/bin/env python3 +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +""" See `subvol_rpm_compare` for the entry point. """ + +import pwd +import re +import shlex +import subprocess +from contextlib import contextmanager +from typing import Iterator, List, NamedTuple, Optional, Set, Tuple + +from antlir.common import get_logger +from antlir.fs_utils import Path +from antlir.nspawn_in_subvol.args import ( + NspawnPluginArgs, + PopenArgs, + new_nspawn_opts, +) +from antlir.nspawn_in_subvol.nspawn import run_nspawn +from antlir.nspawn_in_subvol.plugins.rpm import rpm_nspawn_plugins +from antlir.rpm.yum_dnf_conf import YumDnf +from antlir.subvol_utils import Subvol, TempSubvolumes + +log = get_logger() + + +class SubvolsToCompare(NamedTuple): + root: Subvol + leaf: Subvol + ba: Subvol + rpm_installer: YumDnf + rpm_repo_snapshot: Path # under `ba` + + +class NEVRA(NamedTuple): + name: str + epoch: str # it's really an int, but we never convert from string + version: str + release: str + arch: str + + def download_path(self): + "Path under `rpm_download_subvol`" + return f"{self.name}-{self.version}-{self.release}.{self.arch}.rpm" + + +class RpmDiff(NamedTuple): + added_in_order: List[NEVRA] + removed: Set[NEVRA] + + +def _gen_nevras_in_subvol(ba_subvol: Subvol, subvol: Subvol) -> Iterator[NEVRA]: + delim = "<:>" + # This won't tell us the exact install order within a transaction + # because `rpm` does not record it in the DB (see `dbAdd` in `psm.c`). + # And installtid + installtime don't have enough granularity. For this + # reason, we have to do some extra work elsewhere to get the install + # order out of `dnf`'s output. + # + # This currently doesn't group by `installtid` because TW agent will + # just lump all RPMs into a single `rpm` command-line. This avoids + # needing to tell it the transaction boundaries. If we later needed + # this, we'd just need to grab `installtid` here, and pass it to + # the agent. Context: https://fburl.com/xqok460n + opts = new_nspawn_opts( + # We don't want to nspawn into `subvol` directly since it might have + # mounts specified in `/.meta`, and it would be a pain to wire those + # up to be `.bzl` dependencies to make that work. An alternative + # would be to add a `skip_meta_mounts` option to `nspawn_in_subvol`, + # but this ugliness here is more local. + bindmount_ro=[(subvol.path(), "/i")], + cmd=[ + "rpm", + "--root=/i", + "--query", + "--all", + "--queryformat", + delim.join( + ("%{" + key + "}") + for key in ["name", "epochnum", "version", "release", "arch"] + ) + + "\n", + ], + layer=ba_subvol, + ) + rpm_cp, _ = run_nspawn(opts, PopenArgs(stdout=subprocess.PIPE)) + for nevra_str in rpm_cp.stdout.decode().split(): + n, e, v, r, a = nevra_str.split(delim) + yield NEVRA(n, e, v, r, a) + + +def _gen_nevras_from_installer_output( + rpm_installer: YumDnf, + stdout: bytes, + requested_nevras: Set[NEVRA], +) -> Iterator[NEVRA]: + # `yum` and `dnf` differ in how they format the "progress" part + installing_re = re.compile(r"^ +Installing +: +([^ ]+) ") + nvra_re = re.compile(r"^([a-zA-Z0-9._+-]+)-([^-]+)-([^-]+)\.([^.]+)$") + nevra_re = re.compile( + r"^([a-zA-Z0-9._+-]+)-([0-9]+):([^-]+)-([^-]+)\.([^.]+)$" + ) + envra_re = re.compile( + r"^([0-9]+):([a-zA-Z0-9._+-]+)-([^-]+)-([^-]+)\.([^.]+)$" + ) + + just_yielded = None + installed_nevras = set() + for line in re.split("[\n\r]", stdout.decode()): + m = installing_re.match(line) + if not m: + continue + + pkg_spec = m.group(1) + if ":" not in pkg_spec: # Both `yum` and `dnf` omit epoch if 0 + m = nvra_re.match(pkg_spec) + assert m, f"Could not parse {rpm_installer} output: {line}" + nevra = NEVRA(m.group(1), "0", m.group(2), m.group(3), m.group(4)) + elif rpm_installer == YumDnf.dnf: # NEVRA + m = nevra_re.match(pkg_spec) + assert m, f"Could not parse {rpm_installer} output: {line}" + nevra = NEVRA(*m.groups()) + elif rpm_installer == YumDnf.yum: # ENVRA + m = envra_re.match(pkg_spec) + assert m, f"Could not parse {rpm_installer} output: {line}" + nevra = NEVRA( + m.group(2), m.group(1), m.group(3), m.group(4), m.group(5) + ) + else: + raise NotImplementedError(rpm_installer) + + # The installer can print multiple "Installing" lines per NEVRA + if nevra == just_yielded: + continue + just_yielded = nevra + + assert nevra not in installed_nevras, f"{nevra} was installed twice" + installed_nevras.add(nevra) + + assert nevra in requested_nevras, ( + f"Tried to install {nevra}, which was not added between " + f"the root subvol, and the final subvol: {requested_nevras}" + ) + + yield nevra + + # An assert above already checked that installed_nevras < requested_nevras. + assert ( + installed_nevras == requested_nevras + ), f"{requested_nevras - installed_nevras} were never installed" + + +def _cmd_to_quoted_bash(cmd): + return " ".join( + c.shell_quote() if isinstance(c, Path) else shlex.quote(c) for c in cmd + ) + + +def _gen_yum_dnf_install_order( + *, + fake_pty: Path, + subvols: SubvolsToCompare, # this won't use `leaf` or `root` + install_subvol: Subvol, + added_nevras: Set[NEVRA], + rpm_download_subvol: Subvol, +) -> Iterator[NEVRA]: + """ + Sort `added_nevras` in the order that `subvols.rpm_installer` from + `subvols.ba` would install them into `install_subvol`. + + Since there's no "plumbing" API to capture the correct install order + from `yum` or `dnf`, we determine this order by parsing the installer's + stdout. We need `fake_pty` because `dnf` truncates "Installing : " + lines to 80 characters when the output is not going to a TTY. + + NB: We could optionalize `justdb` and check whether the resulting + `install_subvol` is "effectively identical" to the original child + subvolume. However, this is not a very useful idea since in production + we use `rpm` to install the downloaded & sorted RPMs. + + TODO: Play with increasing the download parallelism? On the `dnf` side, + `max_parallel_downloads`, and can add more repo servers in the BA. + """ + prog_name = subvols.rpm_installer.value + # Future(per @malmond): Provide a custom `yum/dnf.conf` to avoid the + # fact that `--setopt` is known to be buggy. + + common_cmd_prefix = [ + "/fake_pty", + subvols.rpm_repo_snapshot / prog_name / "bin" / prog_name, + "install", + "--installroot=/i", + "--assumeyes", + # Do not install weak deps since we want to order **precisely** + # the packages that actually got installed between the "root" + # and "destination" subvol -- and that installation could easily + # have avoided installing some of the weak dependencies. + "--setopt=install_weak_deps=False", + ] + # Unfortunately, `dnf install --setopt=tsflags=justdb` downloads the + # *.rpm files even if it will not need them. So, we have to pay the + # RPM download cost, whether or not we want to use a particular file + # as part of packaging this layer. + # + # This explicit download step makes sure that the RPM files are fetched + # to a location we control, making them available "almost for free". + # This is slightly more expensive than a single `dnf install` call, + # since we pay startup & depsolving twice (~1 sec). + # + # If we didn't do this two-step dance, and just used `keepcache`, + # we would be at the mercy of the yum / dnf cache layout, which is + # both messier, and likely more fragile. + download_cmd = common_cmd_prefix + [ + "--downloadonly", + "--downloaddir=/d", + *( + f"{r.name}-{r.epoch}:{r.version}-{r.release}.{r.arch}" + for r in added_nevras + ), + ] + install_cmd = common_cmd_prefix + [ + # Avoid the IO of actually unpacking the RPMs + "--setopt=tsflags=justdb", + # `dnf` (but not `yum`) has a horrendous bug, wherein doing this + # here sequence of "install --downloadonly" and "install + # /downloaddir/*.rpm", with the SAME `--installroot`, will result in + # all the content of `/downloaddir` being deleted. This avoids it. + "--setopt=keepcache=True", + # NB: The last word should NOT be quoted, and is therefore added below. + ] + opts = new_nspawn_opts( + bindmount_ro=[(fake_pty, "/fake_pty")], + bindmount_rw=[ + (install_subvol.path(), "/i"), + (rpm_download_subvol.path(), "/d"), + ], + user=pwd.getpwnam("root"), + cmd=[ + "/bin/bash", + "-uec", + f""" +set -o pipefail +{_cmd_to_quoted_bash(download_cmd)} +{_cmd_to_quoted_bash(install_cmd)} /d/*.rpm +""", + ], + layer=subvols.ba, + ) + res, _ = run_nspawn( + opts, + PopenArgs(stdout=subprocess.PIPE), + plugins=rpm_nspawn_plugins( + opts=opts, + plugin_args=NspawnPluginArgs( + serve_rpm_snapshots=[subvols.rpm_repo_snapshot], + shadow_proxied_binaries=False, # Just serve the 1 snapshot + ), + ), + ) + yield from _gen_nevras_from_installer_output( + subvols.rpm_installer, + res.stdout, + added_nevras, + ) + + +def subvol_rpm_compare( + *, + subvols: SubvolsToCompare, + # If you want the downloaded RPMs, use `subvol_rpm_compare_and_download()`. + # + # If this subvol is set, populate it with the downloaded RPMs corresponding + # to `RpmDiff.added_nevras` -- each file named `NEVRA.download_path`. + rpm_download_subvol: Optional[Subvol] = None, +) -> RpmDiff: + """ + Finds what RPMs were added / removed between `.root` and `.leaf`. + + Then, use `.ba` to determine that precise installation order that would + be used by `.rpm_installer` to install the added NEVRAs from + `.rpm_repo_snapshot`. + + It **should** true that `RpmDiff.added_in_order` can be `rpm --install`ed + into `.root` in order to reproduce `.leaf`. + + IMPORTANT: this function exercises `yum` / `dnf` in a way that is + necessarily somewhat different from how `subvols.leaf` was actually + constructed. Therefore, it is important to verify that installing + `RpmDiff.added_in_order` in `subvols.root` will produce the same output. + Therefore, typical usage of this function should be followed by using + the `rpm_diff` module, e.g. `replay_rpms_and_compiler_items` followed + by `subvol_diff`. + + Future: Eventually, `RpmActionItem` ought to become self-aware enough to + record precisely which RPMs installed, in which order -- and perhaps we + can even switch its actual install method to `rpm -i` for full + consistency with prod. At that point, this function should be able to + use that authoritative changelog instead, only falling back to the + current "best effort" method when a `genrule_layer` installs RPMs by + other means. + """ + root_nevras = set(_gen_nevras_in_subvol(subvols.ba, subvols.root)) + my_nevras = set(_gen_nevras_in_subvol(subvols.ba, subvols.leaf)) + removed_nevras = root_nevras - my_nevras + added_nevras = my_nevras - root_nevras + + # Shell out to `yum` or `dnf` in the BA to find the correct install + # order for the new RPMs. Per the comment on P410145489, this matters. + # + # `fake_pty` is a separate binary because handling PTY signals in the + # same process would be insanity, and I don't want to risk `fork()` in a + # process that's liable to have random FB infra threads. + with Path.resource( + __package__, "fake_pty", exe=True + ) as fake_pty, TempSubvolumes() as tmp_subvols: + if not rpm_download_subvol: + rpm_download_subvol = tmp_subvols.create("rpm_compare_download") + added_in_order = list( + _gen_yum_dnf_install_order( + fake_pty=fake_pty, + subvols=subvols, + install_subvol=tmp_subvols.snapshot( + subvols.root, "subvol_rpm_compare" + ), + added_nevras=added_nevras, + rpm_download_subvol=rpm_download_subvol, + ), + ) + # Check that the set of downloaded RPMs is exactly what we requested + actual_downloaded = { + f"{p}" for p in rpm_download_subvol.path().listdir() + } + expected_downloaded = {r.download_path() for r in added_in_order} + assert expected_downloaded == actual_downloaded, ( + expected_downloaded, + actual_downloaded, + ) + return RpmDiff(removed=removed_nevras, added_in_order=added_in_order) + + +@contextmanager +def subvol_rpm_compare_and_download( + subvols: SubvolsToCompare, +) -> Iterator[Tuple[RpmDiff, Subvol]]: + """ + Runs `subvol_rpm_compare` and yields the resulting `RpmDiff` together + with a temporary subvolume that contains all the added RPM files, + accessible via `NEVRA.download_path()`. + """ + with TempSubvolumes() as tmp_subvols: + rpm_download_subvol = tmp_subvols.create("subvol_rpm_compare_download") + rd = subvol_rpm_compare( + subvols=subvols, + rpm_download_subvol=rpm_download_subvol, + ) + yield rd, rpm_download_subvol From dcb2feba630793cf0527b70bd1aa574dafb4d888 Mon Sep 17 00:00:00 2001 From: Maxim Patlasov Date: Wed, 9 Jun 2021 19:44:56 -0700 Subject: [PATCH 638/707] Improve support for wildcard arch in `update_allowed_versions` Summary: The diff fixes three issues: * we don't have to let to compare concrete arch with the wildcard * when we look for versions available (_resolve_envras_for_package_group) and arch is specified as the wildcard, we have to adjust sql query accordingly * let manual version_policy plugin specify wildcard arch Reviewed By: snarkmaster Differential Revision: D28858047 fbshipit-source-id: ca68d6aff495fb2c1a2f70c29deda2c25058c589 --- antlir/rpm/allowed_versions/envra.py | 4 ++++ antlir/rpm/allowed_versions/tests/test_envra.py | 16 ++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/antlir/rpm/allowed_versions/envra.py b/antlir/rpm/allowed_versions/envra.py index d9473842..8ac4528c 100644 --- a/antlir/rpm/allowed_versions/envra.py +++ b/antlir/rpm/allowed_versions/envra.py @@ -73,6 +73,10 @@ def _compare(self, other: "SortableENVRA") -> int: raise TypeError( f"Cannot compare concrete name with wildcard: {self} {other}" ) + if (self.arch is None) ^ (other.arch is None): + raise TypeError( + f"Cannot compare concrete arch with wildcard: {self} {other}" + ) # Sort lexicographically by name, then architecture self_key = (self.name, self.arch) diff --git a/antlir/rpm/allowed_versions/tests/test_envra.py b/antlir/rpm/allowed_versions/tests/test_envra.py index 147e326a..cf9a6378 100644 --- a/antlir/rpm/allowed_versions/tests/test_envra.py +++ b/antlir/rpm/allowed_versions/tests/test_envra.py @@ -111,6 +111,22 @@ def test_compare_one_epoch_wildcard(self): with self.assertRaises(TypeError): self.assertEqual(e0, e1) + def test_compare_both_archs_wildcard(self): + e = SortableENVRA( + epoch=0, name="n", version="v", release="r", arch=None + ) + self.assertEqual(e, e) + + def test_compare_one_arch_wildcard(self): + e0 = SortableENVRA( + epoch=0, name="n", version="v", release="r", arch=None + ) + e1 = SortableENVRA( + epoch=0, name="n", version="v", release="r", arch="a" + ) + with self.assertRaises(TypeError): + self.assertEqual(e0, e1) + def test_compare_self_greater_than_other(self): e0 = SortableENVRA( epoch=0, name="n", version="v", release="r", arch="a" From d5172584e3cfe3805a87e19d6d895589c1f56d90 Mon Sep 17 00:00:00 2001 From: Alexey Spiridonov Date: Mon, 14 Jun 2021 11:31:00 -0700 Subject: [PATCH 639/707] Back out "Don't use `/usr/libexec/platform-python`, it is not available on all distros" Summary: ... but do so without breaking tests on Github, hopefully :D The first `test-fake-pty` did not work work on Ubuntu (which runs our OSS tests on Github) or Fedora since both lack `platform-python`. So, the revertee D29040759 (https://github.com/facebookincubator/antlir/commit/5a3338a0abd4f5d1c3cb2b8d1f7d5ce380d03d05) switched to `python3` to fix the tests. But, all CentOS flavors use `platform-python` and do NOT provide a system Python by default. To paper over these distro differences, I add `fake_pty_wrapper.py` that picks "whatever Python it can get". Another option would be to rewrite this in C, in the style of `clonecaps.c` or `rename_shadowed.c`. I didn't do this primarily because this would negatively impact build speed. But that's the right backstop if we need this to work on Python-free OSes. Reviewed By: zeroxoneb Differential Revision: D29088667 fbshipit-source-id: 78cc060342f1f7ba8681ee2770aa26ea10ff95d0 --- antlir/rpm/replay/subvol_rpm_compare.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/antlir/rpm/replay/subvol_rpm_compare.py b/antlir/rpm/replay/subvol_rpm_compare.py index 502c0d76..f6b6657c 100644 --- a/antlir/rpm/replay/subvol_rpm_compare.py +++ b/antlir/rpm/replay/subvol_rpm_compare.py @@ -25,6 +25,8 @@ from antlir.rpm.yum_dnf_conf import YumDnf from antlir.subvol_utils import Subvol, TempSubvolumes +from .fake_pty_wrapper import fake_pty_cmd, fake_pty_resource + log = get_logger() @@ -188,9 +190,8 @@ def _gen_yum_dnf_install_order( prog_name = subvols.rpm_installer.value # Future(per @malmond): Provide a custom `yum/dnf.conf` to avoid the # fact that `--setopt` is known to be buggy. - common_cmd_prefix = [ - "/fake_pty", + *fake_pty_cmd(subvols.ba.path(), "/fake_pty.py"), subvols.rpm_repo_snapshot / prog_name / "bin" / prog_name, "install", "--installroot=/i", @@ -233,7 +234,7 @@ def _gen_yum_dnf_install_order( # NB: The last word should NOT be quoted, and is therefore added below. ] opts = new_nspawn_opts( - bindmount_ro=[(fake_pty, "/fake_pty")], + bindmount_ro=[(fake_pty, "/fake_pty.py")], bindmount_rw=[ (install_subvol.path(), "/i"), (rpm_download_subvol.path(), "/d"), @@ -314,9 +315,7 @@ def subvol_rpm_compare( # `fake_pty` is a separate binary because handling PTY signals in the # same process would be insanity, and I don't want to risk `fork()` in a # process that's liable to have random FB infra threads. - with Path.resource( - __package__, "fake_pty", exe=True - ) as fake_pty, TempSubvolumes() as tmp_subvols: + with fake_pty_resource() as fake_pty, TempSubvolumes() as tmp_subvols: if not rpm_download_subvol: rpm_download_subvol = tmp_subvols.create("rpm_compare_download") added_in_order = list( From 78a779b7596deae2943c4bbebe3013d821410f61 Mon Sep 17 00:00:00 2001 From: Naveed Golafshani Date: Mon, 14 Jun 2021 13:02:01 -0700 Subject: [PATCH 640/707] Add tests for subvol-rpm-compare Summary: - Introduce a new test snapshot repo with a set of test rpms - Add unit tests that test subvol-rpm-compare with above repo+rpms to test for dependency parsing+ordering, rpm downloading, rpm diffing - Add epoch field to RPM test class and spec to be used in tests Reviewed By: snarkmaster Differential Revision: D28613639 fbshipit-source-id: 8a65db8bc6b0aade40bbdd488ce87dd4c992e7f3 --- antlir/rpm/replay/subvol_rpm_compare.py | 2 +- .../replay/tests/test_subvol_rpm_compare.py | 100 ++++++++++++++++++ 2 files changed, 101 insertions(+), 1 deletion(-) create mode 100644 antlir/rpm/replay/tests/test_subvol_rpm_compare.py diff --git a/antlir/rpm/replay/subvol_rpm_compare.py b/antlir/rpm/replay/subvol_rpm_compare.py index f6b6657c..5e8fe80d 100644 --- a/antlir/rpm/replay/subvol_rpm_compare.py +++ b/antlir/rpm/replay/subvol_rpm_compare.py @@ -132,7 +132,7 @@ def _gen_nevras_from_installer_output( nevra = NEVRA( m.group(2), m.group(1), m.group(3), m.group(4), m.group(5) ) - else: + else: # pragma: no cover raise NotImplementedError(rpm_installer) # The installer can print multiple "Installing" lines per NEVRA diff --git a/antlir/rpm/replay/tests/test_subvol_rpm_compare.py b/antlir/rpm/replay/tests/test_subvol_rpm_compare.py new file mode 100644 index 00000000..f3fa4e79 --- /dev/null +++ b/antlir/rpm/replay/tests/test_subvol_rpm_compare.py @@ -0,0 +1,100 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +import unittest + +from antlir.rpm.find_snapshot import snapshot_install_dir +from antlir.rpm.yum_dnf_conf import YumDnf +from antlir.subvol_utils import Subvol +from antlir.tests.layer_resource import layer_resource_subvol + +from ..subvol_rpm_compare import ( + subvol_rpm_compare, + SubvolsToCompare, + subvol_rpm_compare_and_download, +) + + +class SubvolRpmCompareTestImpl: + def construct_subvols_to_compare( + self, root: Subvol = None, leaf: Subvol = None, ba: Subvol = None + ) -> SubvolsToCompare: + root = root or layer_resource_subvol(__package__, "root_subvol") + leaf = leaf or layer_resource_subvol(__package__, "leaf_subvol") + ba = ba or layer_resource_subvol(__package__, "ba_subvol") + + return SubvolsToCompare( + ba=ba, + root=root, + leaf=leaf, + rpm_installer=self._YUM_DNF, + rpm_repo_snapshot=snapshot_install_dir( + "//antlir/rpm:subvol-rpm-compare-repo-snapshot-for-tests" + ), + ) + + def test_subvol_rpm_compare_identical_subvols(self): + root_subvol = layer_resource_subvol(__package__, "root_subvol") + + subvols = self.construct_subvols_to_compare( + root=root_subvol, leaf=root_subvol + ) + rd = subvol_rpm_compare(subvols=subvols) + + # if root == leaf then no rpms should added/removed + self.assertEqual(len(rd.added_in_order), 0) + self.assertEqual(len(rd.removed), 0) + + def test_subvol_rpm_compare_added_order(self): + subvols = self.construct_subvols_to_compare() + rd = subvol_rpm_compare(subvols=subvols) + rpms_added_names = [nevra.name for nevra in rd.added_in_order] + rpms_removed_names = [nevra.name for nevra in rd.removed] + rpms_with_deps = [ + "rpm-test-first", + "rpm-test-second", + "rpm-test-third", + "rpm-test-fourth", + "rpm-test-fifth", + ] + self.assertIn( + rpms_added_names, + [ + # Since `has-epoch` has no deps or dependents, it could + # go in either order + [*rpms_with_deps, "rpm-test-has-epoch"], + ["rpm-test-has-epoch", *rpms_with_deps], + ], + ) + self.assertEqual(["rpm-test-cake"], rpms_removed_names) + + def test_subvol_rpm_compare_and_download(self): + subvols = self.construct_subvols_to_compare() + with subvol_rpm_compare_and_download(subvols) as ( + rpm_diff, + rpm_download_subvol, + ): + downloaded_rpms = { + f"{rpm}" for rpm in rpm_download_subvol.path().listdir() + } + self.assertEqual( + { + "rpm-test-has-epoch-0-0.x86_64.rpm", + "rpm-test-first-0-0.x86_64.rpm", + "rpm-test-second-0-0.x86_64.rpm", + "rpm-test-third-0-0.x86_64.rpm", + "rpm-test-fourth-0-0.x86_64.rpm", + "rpm-test-fifth-0-0.x86_64.rpm", + }, + downloaded_rpms, + ) + + +class YumSubvolRpmCompareTestCase(SubvolRpmCompareTestImpl, unittest.TestCase): + _YUM_DNF = YumDnf.yum + + +class DnfSubvolRpmCompareTestCase(SubvolRpmCompareTestImpl, unittest.TestCase): + _YUM_DNF = YumDnf.dnf From e6ce06e763e279218a2af9b58131866734bd23bd Mon Sep 17 00:00:00 2001 From: Justin Trudell Date: Mon, 28 Jun 2021 10:48:13 -0700 Subject: [PATCH 641/707] Add project-wide Pyre config, apply fixes Summary: Currently, we have various nested Pyre configurations spattered throughout subdirectories in Antlir, which makes them tricky to maintain and blocks us from type-checking files directly under `antlir/`, as Pyre doesn't allow nested configs. To remediate this, let's remove these nested configs, and move them to one top-level config. This has the side effect of raising many typing errors because it incorporates dependencies for any of the specified targets, so I've gone ahead and added temporary `# pyre-fixme` comments for those to keep the project lint-clean. Reviewed By: snarkmaster Differential Revision: D29369449 fbshipit-source-id: b1edade498903f0fa53ea18db4ddb34e75135003 --- antlir/rpm/rpm_metadata.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/antlir/rpm/rpm_metadata.py b/antlir/rpm/rpm_metadata.py index 50563bcc..c99ca709 100644 --- a/antlir/rpm/rpm_metadata.py +++ b/antlir/rpm/rpm_metadata.py @@ -33,6 +33,8 @@ def from_subvol(cls, subvol: Subvol, package_name: str) -> "RpmMetadata": if not os.path.exists(db_path): raise ValueError(f"RPM DB path {db_path} does not exist") + # pyre-fixme[6]: Expected `RpmMetadata` for 1st param but got + # `Type[RpmMetadata]`. return cls._repo_query(cls, db_path, package_name, None) @classmethod @@ -40,6 +42,8 @@ def from_file(cls, package_path: Path) -> "RpmMetadata": if not package_path.endswith(b".rpm"): raise ValueError(f"RPM file {package_path} needs to end with .rpm") + # pyre-fixme[6]: Expected `RpmMetadata` for 1st param but got + # `Type[RpmMetadata]`. return cls._repo_query(cls, None, None, package_path) def _repo_query( @@ -53,8 +57,12 @@ def _repo_query( ] if db_path and package_name and (package_path is None): + # pyre-fixme[6]: Expected `Iterable[str]` for 1st param but got + # `Iterable[typing.Union[Path, str]]`. query_args += ["--dbpath", db_path, package_name] elif package_path and (db_path is None and package_name is None): + # pyre-fixme[6]: Expected `Iterable[str]` for 1st param but got + # `Iterable[typing.Union[Path, str]]`. query_args += ["--package", package_path] else: raise ValueError( @@ -130,7 +138,9 @@ def compare_rpm_versions(a: RpmMetadata, b: RpmMetadata) -> int: def _compare_values(left: str, right: str) -> int: # Rpm versions can only be ascii, anything else is just # ignored + # pyre-fixme[9]: left has type `str`; used as `bytes`. left = left.encode("ascii", "ignore") + # pyre-fixme[9]: right has type `str`; used as `bytes`. right = right.encode("ascii", "ignore") if left == right: From 61abe0d2f55d6c71466b4849c74818dbee2f7889 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Wed, 6 Jan 2021 18:00:18 +0100 Subject: [PATCH 642/707] Remove legacy stuff from a long time ago In particular, revert https://github.com/rubygems/bundler/commit/e31a1c7b24d3dfbce7ed39b6a723dd20f7d08c95 and https://github.com/rubygems/bundler/commit/b8d0a414067f08b7a57b11b295034f5b88db9fc9. Just taking the chance to do it now because the relevant specs fail on MacOS. --- bundler/spec/realworld/edgecases_spec.rb | 127 ----------------------- 1 file changed, 127 deletions(-) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index e0844bbe..5342482f 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -211,133 +211,6 @@ def rubygems_version(name, requirement) expect(err).to be_empty end - it "checks out git repos when the lockfile is corrupted" do - gemfile <<-G - source "https://rubygems.org" - git_source(:github) {|repo| "https://github.com/\#{repo}.git" } - - gem 'activerecord', :github => 'carlhuda/rails-bundler-test', :branch => 'master' - gem 'activesupport', :github => 'carlhuda/rails-bundler-test', :branch => 'master' - gem 'actionpack', :github => 'carlhuda/rails-bundler-test', :branch => 'master' - G - - lockfile <<-L - GIT - remote: https://github.com/carlhuda/rails-bundler-test.git - revision: 369e28a87419565f1940815219ea9200474589d4 - branch: master - specs: - actionpack (3.2.2) - activemodel (= 3.2.2) - activesupport (= 3.2.2) - builder (~> 3.0.0) - erubis (~> 2.7.0) - journey (~> 1.0.1) - rack (~> 1.4.0) - rack-cache (~> 1.2) - rack-test (~> 0.6.1) - sprockets (~> 2.1.2) - activemodel (3.2.2) - activesupport (= 3.2.2) - builder (~> 3.0.0) - activerecord (3.2.2) - activemodel (= 3.2.2) - activesupport (= 3.2.2) - arel (~> 3.0.2) - tzinfo (~> 0.3.29) - activesupport (3.2.2) - i18n (~> 0.6) - multi_json (~> 1.0) - - GIT - remote: https://github.com/carlhuda/rails-bundler-test.git - revision: 369e28a87419565f1940815219ea9200474589d4 - branch: master - specs: - actionpack (3.2.2) - activemodel (= 3.2.2) - activesupport (= 3.2.2) - builder (~> 3.0.0) - erubis (~> 2.7.0) - journey (~> 1.0.1) - rack (~> 1.4.0) - rack-cache (~> 1.2) - rack-test (~> 0.6.1) - sprockets (~> 2.1.2) - activemodel (3.2.2) - activesupport (= 3.2.2) - builder (~> 3.0.0) - activerecord (3.2.2) - activemodel (= 3.2.2) - activesupport (= 3.2.2) - arel (~> 3.0.2) - tzinfo (~> 0.3.29) - activesupport (3.2.2) - i18n (~> 0.6) - multi_json (~> 1.0) - - GIT - remote: https://github.com/carlhuda/rails-bundler-test.git - revision: 369e28a87419565f1940815219ea9200474589d4 - branch: master - specs: - actionpack (3.2.2) - activemodel (= 3.2.2) - activesupport (= 3.2.2) - builder (~> 3.0.0) - erubis (~> 2.7.0) - journey (~> 1.0.1) - rack (~> 1.4.0) - rack-cache (~> 1.2) - rack-test (~> 0.6.1) - sprockets (~> 2.1.2) - activemodel (3.2.2) - activesupport (= 3.2.2) - builder (~> 3.0.0) - activerecord (3.2.2) - activemodel (= 3.2.2) - activesupport (= 3.2.2) - arel (~> 3.0.2) - tzinfo (~> 0.3.29) - activesupport (3.2.2) - i18n (~> 0.6) - multi_json (~> 1.0) - - GEM - remote: https://rubygems.org/ - specs: - arel (3.0.2) - builder (3.0.0) - erubis (2.7.0) - hike (1.2.1) - i18n (0.6.0) - journey (1.0.3) - multi_json (1.1.0) - rack (1.4.1) - rack-cache (1.2) - rack (>= 0.4) - rack-test (0.6.1) - rack (>= 1.0) - sprockets (2.1.2) - hike (~> 1.2) - rack (~> 1.0) - tilt (~> 1.1, != 1.3.0) - tilt (1.3.3) - tzinfo (0.3.32) - - PLATFORMS - ruby - - DEPENDENCIES - actionpack! - activerecord! - activesupport! - L - - bundle :lock - expect(err).to be_empty - end - it "outputs a helpful error message when gems have invalid gemspecs" do install_gemfile <<-G, :standalone => true, :raise_on_error => false source 'https://rubygems.org' From 181d8831e10d900b9f0a8f78ac8f09184bab31e6 Mon Sep 17 00:00:00 2001 From: Justin Trudell Date: Mon, 28 Jun 2021 13:23:39 -0700 Subject: [PATCH 643/707] Apply Pyre to all of Antlir Summary: Applying Pyre Antlir-wide is tricky because many of our tests build image layers that: - Are not buildable by Pyre because it uses a separate Buck daemon and runs into cross-device link issues when interacting with our artifacts dir - (for fb) Are doubly not buildable because they require root, which the Sandcastle Pyre job does not have To get around this, I put a query into our Pyre config: ``` "'//antlir/...' - attrfilter(labels, 'image_layer', '//antlir/...') - rdeps('//antlir/...', attrfilter(labels, 'image_layer', '//antlir/...'))" ``` which essentially says "all targets in antlir that are not layers and do not take dependencies on layers". This seems to have worked, and I was able to successfully run Pyre locally, so let's give it a shot. Reviewed By: snarkmaster Differential Revision: D29403804 fbshipit-source-id: 6958a1fbf78eeec979b8b0a8514fa577df492fe0 --- antlir/rpm/allowed_versions/envra.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/antlir/rpm/allowed_versions/envra.py b/antlir/rpm/allowed_versions/envra.py index 8ac4528c..5d086991 100644 --- a/antlir/rpm/allowed_versions/envra.py +++ b/antlir/rpm/allowed_versions/envra.py @@ -41,8 +41,11 @@ class SortableENVRA(NamedTuple): def _as_rpm_metadata(self) -> RpmMetadata: return RpmMetadata( # Not used for sorting here, `compare_rpm_versions` refuses to - # compare different names. As a side-effect, `None` vs - # non-`None` comparisons are also prohibited. + # compare different names. As a side-effect, `None` vs non-`None` + # comparisons are also prohibited. + # + # pyre-fixme[6]: Expected `str` for 1st param but got + # `Optional[str]`. name=self.name, # We check this is not `None` in `as_rpm_metadata`, and check # for heterogeneous comparisons in `_compare`. @@ -101,6 +104,8 @@ def _compare(self, other: "SortableENVRA") -> int: def __eq__(self, other: "SortableENVRA") -> bool: return self._compare(other) == 0 + # pyre-fixme[14]: `__lt__` overrides method defined in `tuple` + # inconsistently. def __lt__(self, other: "SortableENVRA") -> bool: return self._compare(other) < 0 From e20be5fd98db120b2732489b7156e89982ba1fb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Wed, 6 Jan 2021 15:29:59 +0100 Subject: [PATCH 644/707] Add MacOS to bundler's CI * It can help us catch MacOS specific issues. * It aligns bundler specs with rubygems which already run on MacOS. * It allows bundler developers using MacOS to have a green suite. * It can reduce friction with ruby-core by catching CI issues that will be detected later by them otherwise. --- bundler/spec/realworld/edgecases_spec.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index 5342482f..556a11d2 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -222,7 +222,7 @@ def rubygems_version(name, requirement) end it "doesn't hang on big gemfile" do - skip "Only for ruby 2.7.3" if RUBY_VERSION != "2.7.3" + skip "Only for ruby 2.7.3" if RUBY_VERSION != "2.7.3" || RUBY_PLATFORM =~ /darwin/ gemfile <<~G # frozen_string_literal: true @@ -334,7 +334,7 @@ def rubygems_version(name, requirement) end it "doesn't hang on tricky gemfile" do - skip "Only for ruby 2.7.3" if RUBY_VERSION != "2.7.3" + skip "Only for ruby 2.7.3" if RUBY_VERSION != "2.7.3" || RUBY_PLATFORM =~ /darwin/ gemfile <<~G source 'https://rubygems.org' @@ -360,7 +360,7 @@ def rubygems_version(name, requirement) end it "doesn't hang on nix gemfile" do - skip "Only for ruby 3.0.1" if RUBY_VERSION != "3.0.1" + skip "Only for ruby 3.0.1" if RUBY_VERSION != "3.0.1" || RUBY_PLATFORM =~ /darwin/ gemfile <<~G source "https://rubygems.org" do From 0ce7ba47a122afefd6539c5f8b2a2ba53588b91e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Thu, 8 Jul 2021 11:17:13 +0200 Subject: [PATCH 645/707] Remove ineffective spec This is a very old spec added when trying to fix issues when loading rubygems plugins from bundler. Nowadays, we have made fixes in this area and covered them with further specs, and this particular specs doesn't seem to be preventing any regression, since even removing all code related to loading rubygems plugins doesn't make it fail. Since it's the only realworld spec touching the network without going through our VCR mocking, I'm removing it. --- bundler/spec/realworld/edgecases_spec.rb | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index 556a11d2..f031e2f3 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -196,21 +196,6 @@ def rubygems_version(name, requirement) expect(lockfile).to include(rubygems_version("paperclip", "~> 5.1.0")) end - # https://github.com/rubygems/bundler/issues/1500 - it "does not fail install because of gem plugins" do - realworld_system_gems("open_gem --version 1.4.2", "rake --version 0.9.2") - gemfile <<-G - source "https://rubygems.org" - - gem 'rack', '1.0.1' - G - - bundle "config set --local path vendor/bundle" - bundle :install - expect(err).not_to include("Could not find rake") - expect(err).to be_empty - end - it "outputs a helpful error message when gems have invalid gemspecs" do install_gemfile <<-G, :standalone => true, :raise_on_error => false source 'https://rubygems.org' From bfba907c1b5383a3b67bcee677b9a5c293b0857e Mon Sep 17 00:00:00 2001 From: Alexey Spiridonov Date: Mon, 12 Jul 2021 15:46:45 -0700 Subject: [PATCH 646/707] Short-circuit "subvol rpm diff" when no RPMs are added Reviewed By: naveedgol Differential Revision: D29663166 fbshipit-source-id: 2c0d6d6b0597c835e3bdd0ef6ad8961587e0ed5f --- antlir/rpm/replay/subvol_rpm_compare.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/antlir/rpm/replay/subvol_rpm_compare.py b/antlir/rpm/replay/subvol_rpm_compare.py index 5e8fe80d..ebbe928e 100644 --- a/antlir/rpm/replay/subvol_rpm_compare.py +++ b/antlir/rpm/replay/subvol_rpm_compare.py @@ -308,6 +308,11 @@ def subvol_rpm_compare( my_nevras = set(_gen_nevras_in_subvol(subvols.ba, subvols.leaf)) removed_nevras = root_nevras - my_nevras added_nevras = my_nevras - root_nevras + # The "sort & download" step is fairly expensive (~25s) even when + # there are no RPMs to sort. Instead of debugging why this is, + # just short-circuit it. + if not added_nevras: + return RpmDiff(removed=removed_nevras, added_in_order=[]) # Shell out to `yum` or `dnf` in the BA to find the correct install # order for the new RPMs. Per the comment on P410145489, this matters. From 8d63a689952b0480f29b20b616cad269c7b41abe Mon Sep 17 00:00:00 2001 From: Naveed Golafshani Date: Tue, 13 Jul 2021 11:36:53 -0700 Subject: [PATCH 647/707] Refactor rpm replay related test layers Summary: - Rename the rpm test repo from `subvol-rpm-compare-repo-snapshot-for-tests` to `rpm-replay-repo-snapshot-for-tests` since it is used in more places then just `subvol-rpm-compare` now. - Delete the custom `root` layer, instead use the existing `base` - Requires adding a `rpm_install`, see accompanying comment - Share the custom `leaf` layer across rpm replay related tests Reviewed By: snarkmaster Differential Revision: D29614913 fbshipit-source-id: 786646f089efa39e5933cfb4031a960c422dba42 --- antlir/rpm/replay/tests/test_subvol_rpm_compare.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/antlir/rpm/replay/tests/test_subvol_rpm_compare.py b/antlir/rpm/replay/tests/test_subvol_rpm_compare.py index f3fa4e79..22394830 100644 --- a/antlir/rpm/replay/tests/test_subvol_rpm_compare.py +++ b/antlir/rpm/replay/tests/test_subvol_rpm_compare.py @@ -31,7 +31,7 @@ def construct_subvols_to_compare( leaf=leaf, rpm_installer=self._YUM_DNF, rpm_repo_snapshot=snapshot_install_dir( - "//antlir/rpm:subvol-rpm-compare-repo-snapshot-for-tests" + "//antlir/rpm:rpm-replay-repo-snapshot-for-tests" ), ) @@ -68,7 +68,7 @@ def test_subvol_rpm_compare_added_order(self): ["rpm-test-has-epoch", *rpms_with_deps], ], ) - self.assertEqual(["rpm-test-cake"], rpms_removed_names) + self.assertEqual(["rpm-test-milk"], rpms_removed_names) def test_subvol_rpm_compare_and_download(self): subvols = self.construct_subvols_to_compare() From 27f703b3ff3141f1c15bd1559275a96d29e3c0c7 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Fri, 4 Jun 2021 10:38:43 +0900 Subject: [PATCH 648/707] Check requirements classes Mitigate the security risk: https://devcraft.io/2021/01/07/universal-deserialisation-gadget-for-ruby-2-x-3-x.html --- test/rubygems/test_gem_requirement.rb | 34 +++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/test/rubygems/test_gem_requirement.rb b/test/rubygems/test_gem_requirement.rb index f32d13f3..b4367681 100644 --- a/test/rubygems/test_gem_requirement.rb +++ b/test/rubygems/test_gem_requirement.rb @@ -422,6 +422,40 @@ def test_hash_returns_equal_hashes_for_equivalent_requirements assert_requirement_hash_equal "1", "1.0.0" end + class Exploit < RuntimeError + end + + def self.exploit(arg) + raise Exploit, "arg = #{arg}" + end + + def test_marshal_load_attack + wa = Net::WriteAdapter.allocate + wa.instance_variable_set(:@socket, self.class) + wa.instance_variable_set(:@method_id, :exploit) + request_set = Gem::RequestSet.allocate + request_set.instance_variable_set(:@git_set, "id") + request_set.instance_variable_set(:@sets, wa) + wa = Net::WriteAdapter.allocate + wa.instance_variable_set(:@socket, request_set) + wa.instance_variable_set(:@method_id, :resolve) + ent = Gem::Package::TarReader::Entry.allocate + ent.instance_variable_set(:@read, 0) + ent.instance_variable_set(:@header, "aaa") + io = Net::BufferedIO.allocate + io.instance_variable_set(:@io, ent) + io.instance_variable_set(:@debug_output, wa) + reader = Gem::Package::TarReader.allocate + reader.instance_variable_set(:@io, io) + requirement = Gem::Requirement.allocate + requirement.instance_variable_set(:@requirements, reader) + m = [Gem::SpecFetcher, Gem::Installer, requirement] + e = assert_raise(TypeError) do + Marshal.load(Marshal.dump(m)) + end + assert_equal(e.message, "wrong @requirements") + end + # Assert that two requirements are equal. Handles Gem::Requirements, # strings, arrays, numbers, and versions. From 2bd1009d524c56582df7c6db3770b4a9f3e20f4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Sat, 31 Jul 2021 12:57:57 +0200 Subject: [PATCH 649/707] Remove redundant part of error message It doesn't really add much, in my opinion. We want to be helpful, but also concise when possible. --- test/rubygems/test_gem.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 79ea89e2..12612bd7 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1960,7 +1960,6 @@ def test_use_gemdeps_missing_gem expected = <<-EXPECTED Could not find gem 'a' in locally installed gems. -The source does not contain any versions of 'a' You may need to `gem install -g` to install missing gems EXPECTED From b0f81975532f7eb71323cbae9150589f0af66c55 Mon Sep 17 00:00:00 2001 From: Pyre Bot Jr <> Date: Tue, 3 Aug 2021 16:22:20 -0700 Subject: [PATCH 650/707] suppress errors in `fbcode/antlir` - batch 1 Differential Revision: D30071016 fbshipit-source-id: 810399e3d6105d4210b3c1648f970b421b33b103 --- antlir/rpm/allowed_versions/envra.py | 1 + 1 file changed, 1 insertion(+) diff --git a/antlir/rpm/allowed_versions/envra.py b/antlir/rpm/allowed_versions/envra.py index 5d086991..6ba1be7a 100644 --- a/antlir/rpm/allowed_versions/envra.py +++ b/antlir/rpm/allowed_versions/envra.py @@ -49,6 +49,7 @@ def _as_rpm_metadata(self) -> RpmMetadata: name=self.name, # We check this is not `None` in `as_rpm_metadata`, and check # for heterogeneous comparisons in `_compare`. + # pyre-fixme[6]: Expected `int` for 2nd param but got `Optional[int]`. epoch=self.epoch, version=self.version, release=self.release, From 8a147d728691181d0a2b667452f0bc0c6f783e11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Mon, 28 Oct 2019 18:08:07 +0100 Subject: [PATCH 651/707] Remove unnecessary spec manipulation --- test/rubygems/test_gem.rb | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 12612bd7..608c6bac 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -674,7 +674,9 @@ def test_self_use_gemdeps begin Dir.chdir 'detect/a/b' - assert_equal add_bundler_full_name([]), Gem.use_gemdeps.map(&:full_name) + Gem.use_gemdeps + + assert_equal add_bundler_full_name([]), loaded_spec_names ensure Dir.chdir @tempdir end @@ -1713,8 +1715,11 @@ def test_auto_activation_of_used_gemdeps_file ENV['RUBYGEMS_GEMDEPS'] = "-" - expected_specs = [a, b, util_spec("bundler", Bundler::VERSION), c].compact - assert_equal expected_specs, Gem.use_gemdeps.sort_by {|s| s.name } + expected_specs = [a, b, util_spec("bundler", Bundler::VERSION), c].compact.map(&:full_name) + + Gem.use_gemdeps + + assert_equal expected_specs, loaded_spec_names end BUNDLER_LIB_PATH = File.expand_path $LOAD_PATH.find {|lp| File.file?(File.join(lp, "bundler.rb")) } From 0782b2a33def04312bd5b918cac86efd6655befe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Mon, 28 Oct 2019 18:52:23 +0100 Subject: [PATCH 652/707] Remove misleading comment When I read, I thought the assertion was incorrect. It's doing the right thing, though. --- test/rubygems/test_gem.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 608c6bac..6ab55373 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -540,7 +540,6 @@ def test_self_bin_path_bin_file_gone_in_latest s.executables = [] end install_specs spec - # Should not find a-10's non-abin (bug) assert_equal @abin_path, Gem.bin_path('a', 'abin') end From e0c720c235709974e32506d05e455e7f762de3d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Mon, 28 Oct 2019 19:11:57 +0100 Subject: [PATCH 653/707] Use `Gem.use_gemdeps` only from binstubs The previous behavior was to automatically require `bundler/setup` everytime `rubygems` was required, which I think was too much. --- test/rubygems/test_gem.rb | 62 ++++++++++++++++++++++++++++++--------- 1 file changed, 48 insertions(+), 14 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 6ab55373..98cad546 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1730,10 +1730,18 @@ def add_bundler_full_name(names) names end - def test_looks_for_gemdeps_files_automatically_on_start + def test_looks_for_gemdeps_files_automatically_from_binstubs pend "Requiring bundler messes things up" if Gem.java_platform? - a = util_spec "a", "1", nil, "lib/a.rb" + a = util_spec "a", "1" do |s| + s.executables = %w[foo] + s.bindir = "exe" + end + + write_file File.join(@tempdir, 'exe', 'foo') do |fp| + fp.puts "puts Gem.loaded_specs.values.map(&:full_name).sort" + end + b = util_spec "b", "1", nil, "lib/b.rb" c = util_spec "c", "1", nil, "lib/c.rb" @@ -1747,29 +1755,41 @@ def test_looks_for_gemdeps_files_automatically_on_start ENV['GEM_PATH'] = path ENV['RUBYGEMS_GEMDEPS'] = "-" + new_PATH = [File.join(path, "bin"), ENV["PATH"]].join(File::PATH_SEPARATOR) + new_RUBYOPT = "-I#{rubygems_path} -I#{BUNDLER_LIB_PATH}" + path = File.join @tempdir, "gem.deps.rb" - cmd = [*ruby_with_rubygems_in_load_path, - "-I#{BUNDLER_LIB_PATH}"] - cmd << "-eputs Gem.loaded_specs.values.map(&:full_name).sort" File.open path, "w" do |f| f.puts "gem 'a'" end - out0 = IO.popen(cmd, &:read).split(/\n/) + out0 = with_path_and_rubyopt(new_PATH, new_RUBYOPT) do + IO.popen("foo", &:read).split(/\n/) + end File.open path, "a" do |f| f.puts "gem 'b'" f.puts "gem 'c'" end - out = IO.popen(cmd, &:read).split(/\n/) + out = with_path_and_rubyopt(new_PATH, new_RUBYOPT) do + IO.popen("foo", &:read).split(/\n/) + end assert_equal ["b-1", "c-1"], out - out0 end - def test_looks_for_gemdeps_files_automatically_on_start_in_parent_dir + def test_looks_for_gemdeps_files_automatically_from_binstubs_in_parent_dir pend "Requiring bundler messes things up" if Gem.java_platform? - a = util_spec "a", "1", nil, "lib/a.rb" + a = util_spec "a", "1" do |s| + s.executables = %w[foo] + s.bindir = "exe" + end + + write_file File.join(@tempdir, 'exe', 'foo') do |fp| + fp.puts "puts Gem.loaded_specs.values.map(&:full_name).sort" + end + b = util_spec "b", "1", nil, "lib/b.rb" c = util_spec "c", "1", nil, "lib/c.rb" @@ -1785,21 +1805,25 @@ def test_looks_for_gemdeps_files_automatically_on_start_in_parent_dir Dir.mkdir "sub1" + new_PATH = [File.join(path, "bin"), ENV["PATH"]].join(File::PATH_SEPARATOR) + new_RUBYOPT = "-I#{rubygems_path} -I#{BUNDLER_LIB_PATH}" + path = File.join @tempdir, "gem.deps.rb" - cmd = [*ruby_with_rubygems_in_load_path, "-Csub1", - "-I#{BUNDLER_LIB_PATH}"] - cmd << "-eputs Gem.loaded_specs.values.map(&:full_name).sort" File.open path, "w" do |f| f.puts "gem 'a'" end - out0 = IO.popen(cmd, &:read).split(/\n/) + out0 = with_path_and_rubyopt(new_PATH, new_RUBYOPT) do + IO.popen("foo", :chdir => "sub1", &:read).split(/\n/) + end File.open path, "a" do |f| f.puts "gem 'b'" f.puts "gem 'c'" end - out = IO.popen(cmd, &:read).split(/\n/) + out = with_path_and_rubyopt(new_PATH, new_RUBYOPT) do + IO.popen("foo", :chdir => "sub1", &:read).split(/\n/) + end Dir.rmdir "sub1" @@ -2114,4 +2138,14 @@ def util_remove_interrupt_command def util_cache_dir File.join Gem.dir, "cache" end + + def with_path_and_rubyopt(path_value, rubyopt_value) + path, ENV['PATH'] = ENV['PATH'], path_value + rubyopt, ENV['RUBYOPT'] = ENV['RUBYOPT'], rubyopt_value + + yield + ensure + ENV['PATH'] = path + ENV['RUBYOPT'] = rubyopt + end end From d727fa87afb6725da51031d9c54e44e107f4782b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Wed, 30 Oct 2019 16:51:38 +0100 Subject: [PATCH 654/707] Refactor reseting `RUBYGEMS_GEMDEPS` in tests --- test/rubygems/test_gem.rb | 268 ++++++++++++++++++-------------------- 1 file changed, 130 insertions(+), 138 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 98cad546..d34aad78 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -19,7 +19,6 @@ def setup common_installer_setup - ENV.delete 'RUBYGEMS_GEMDEPS' @additional = %w[a b].map {|d| File.join @tempdir, d } util_remove_interrupt_command @@ -663,24 +662,22 @@ def test_self_default_sources end def test_self_use_gemdeps - rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], '-' + with_rubygems_gemdeps('-') do + FileUtils.mkdir_p 'detect/a/b' + FileUtils.mkdir_p 'detect/a/Isolate' - FileUtils.mkdir_p 'detect/a/b' - FileUtils.mkdir_p 'detect/a/Isolate' + FileUtils.touch 'detect/Isolate' - FileUtils.touch 'detect/Isolate' - - begin - Dir.chdir 'detect/a/b' + begin + Dir.chdir 'detect/a/b' - Gem.use_gemdeps + Gem.use_gemdeps - assert_equal add_bundler_full_name([]), loaded_spec_names - ensure - Dir.chdir @tempdir + assert_equal add_bundler_full_name([]), loaded_spec_names + ensure + Dir.chdir @tempdir + end end - ensure - ENV['RUBYGEMS_GEMDEPS'] = rubygems_gemdeps end def test_self_dir @@ -1690,11 +1687,11 @@ def test_auto_activation_of_specific_gemdeps_file f.puts "gem 'c'" end - ENV['RUBYGEMS_GEMDEPS'] = path - - Gem.use_gemdeps + with_rubygems_gemdeps(path) do + Gem.use_gemdeps - assert_equal add_bundler_full_name(%W[a-1 b-1 c-1]), loaded_spec_names + assert_equal add_bundler_full_name(%W[a-1 b-1 c-1]), loaded_spec_names + end end def test_auto_activation_of_used_gemdeps_file @@ -1712,13 +1709,13 @@ def test_auto_activation_of_used_gemdeps_file f.puts "gem 'c'" end - ENV['RUBYGEMS_GEMDEPS'] = "-" - - expected_specs = [a, b, util_spec("bundler", Bundler::VERSION), c].compact.map(&:full_name) + with_rubygems_gemdeps("-") do + expected_specs = [a, b, util_spec("bundler", Bundler::VERSION), c].compact.map(&:full_name) - Gem.use_gemdeps + Gem.use_gemdeps - assert_equal expected_specs, loaded_spec_names + assert_equal expected_specs, loaded_spec_names + end end BUNDLER_LIB_PATH = File.expand_path $LOAD_PATH.find {|lp| File.file?(File.join(lp, "bundler.rb")) } @@ -1753,29 +1750,30 @@ def test_looks_for_gemdeps_files_automatically_from_binstubs install_gem c, :install_dir => path ENV['GEM_PATH'] = path - ENV['RUBYGEMS_GEMDEPS'] = "-" - new_PATH = [File.join(path, "bin"), ENV["PATH"]].join(File::PATH_SEPARATOR) - new_RUBYOPT = "-I#{rubygems_path} -I#{BUNDLER_LIB_PATH}" + with_rubygems_gemdeps("-") do + new_PATH = [File.join(path, "bin"), ENV["PATH"]].join(File::PATH_SEPARATOR) + new_RUBYOPT = "-I#{rubygems_path} -I#{BUNDLER_LIB_PATH}" - path = File.join @tempdir, "gem.deps.rb" + path = File.join @tempdir, "gem.deps.rb" - File.open path, "w" do |f| - f.puts "gem 'a'" - end - out0 = with_path_and_rubyopt(new_PATH, new_RUBYOPT) do - IO.popen("foo", &:read).split(/\n/) - end + File.open path, "w" do |f| + f.puts "gem 'a'" + end + out0 = with_path_and_rubyopt(new_PATH, new_RUBYOPT) do + IO.popen("foo", &:read).split(/\n/) + end - File.open path, "a" do |f| - f.puts "gem 'b'" - f.puts "gem 'c'" - end - out = with_path_and_rubyopt(new_PATH, new_RUBYOPT) do - IO.popen("foo", &:read).split(/\n/) - end + File.open path, "a" do |f| + f.puts "gem 'b'" + f.puts "gem 'c'" + end + out = with_path_and_rubyopt(new_PATH, new_RUBYOPT) do + IO.popen("foo", &:read).split(/\n/) + end - assert_equal ["b-1", "c-1"], out - out0 + assert_equal ["b-1", "c-1"], out - out0 + end end def test_looks_for_gemdeps_files_automatically_from_binstubs_in_parent_dir @@ -1801,33 +1799,34 @@ def test_looks_for_gemdeps_files_automatically_from_binstubs_in_parent_dir install_gem c, :install_dir => path ENV['GEM_PATH'] = path - ENV['RUBYGEMS_GEMDEPS'] = "-" - Dir.mkdir "sub1" + with_rubygems_gemdeps("-") do + Dir.mkdir "sub1" - new_PATH = [File.join(path, "bin"), ENV["PATH"]].join(File::PATH_SEPARATOR) - new_RUBYOPT = "-I#{rubygems_path} -I#{BUNDLER_LIB_PATH}" + new_PATH = [File.join(path, "bin"), ENV["PATH"]].join(File::PATH_SEPARATOR) + new_RUBYOPT = "-I#{rubygems_path} -I#{BUNDLER_LIB_PATH}" - path = File.join @tempdir, "gem.deps.rb" + path = File.join @tempdir, "gem.deps.rb" - File.open path, "w" do |f| - f.puts "gem 'a'" - end - out0 = with_path_and_rubyopt(new_PATH, new_RUBYOPT) do - IO.popen("foo", :chdir => "sub1", &:read).split(/\n/) - end + File.open path, "w" do |f| + f.puts "gem 'a'" + end + out0 = with_path_and_rubyopt(new_PATH, new_RUBYOPT) do + IO.popen("foo", :chdir => "sub1", &:read).split(/\n/) + end - File.open path, "a" do |f| - f.puts "gem 'b'" - f.puts "gem 'c'" - end - out = with_path_and_rubyopt(new_PATH, new_RUBYOPT) do - IO.popen("foo", :chdir => "sub1", &:read).split(/\n/) - end + File.open path, "a" do |f| + f.puts "gem 'b'" + f.puts "gem 'c'" + end + out = with_path_and_rubyopt(new_PATH, new_RUBYOPT) do + IO.popen("foo", :chdir => "sub1", &:read).split(/\n/) + end - Dir.rmdir "sub1" + Dir.rmdir "sub1" - assert_equal ["b-1", "c-1"], out - out0 + assert_equal ["b-1", "c-1"], out - out0 + end end def test_register_default_spec @@ -1891,21 +1890,19 @@ def test_use_gemdeps end def test_use_gemdeps_ENV - rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], nil - - spec = util_spec 'a', 1 + with_rubygems_gemdeps(nil) do + spec = util_spec 'a', 1 - refute spec.activated? + refute spec.activated? - File.open 'gem.deps.rb', 'w' do |io| - io.write 'gem "a"' - end + File.open 'gem.deps.rb', 'w' do |io| + io.write 'gem "a"' + end - Gem.use_gemdeps + Gem.use_gemdeps - refute spec.activated? - ensure - ENV['RUBYGEMS_GEMDEPS'] = rubygems_gemdeps + refute spec.activated? + end end def test_use_gemdeps_argument_missing @@ -1918,109 +1915,96 @@ def test_use_gemdeps_argument_missing end def test_use_gemdeps_argument_missing_match_ENV - rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = - ENV['RUBYGEMS_GEMDEPS'], 'gem.deps.rb' + with_rubygems_gemdeps('gem.deps.rb') do + e = assert_raise ArgumentError do + Gem.use_gemdeps 'gem.deps.rb' + end - e = assert_raise ArgumentError do - Gem.use_gemdeps 'gem.deps.rb' + assert_equal 'Unable to find gem dependencies file at gem.deps.rb', + e.message end - - assert_equal 'Unable to find gem dependencies file at gem.deps.rb', - e.message - ensure - ENV['RUBYGEMS_GEMDEPS'] = rubygems_gemdeps end def test_use_gemdeps_automatic - rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], '-' - - spec = util_spec 'a', 1 - install_specs spec - spec = Gem::Specification.find {|s| s == spec } + with_rubygems_gemdeps('-') do + spec = util_spec 'a', 1 + install_specs spec + spec = Gem::Specification.find {|s| s == spec } - refute spec.activated? + refute spec.activated? - File.open 'Gemfile', 'w' do |io| - io.write 'gem "a"' - end + File.open 'Gemfile', 'w' do |io| + io.write 'gem "a"' + end - Gem.use_gemdeps + Gem.use_gemdeps - assert_equal add_bundler_full_name(%W[a-1]), loaded_spec_names - ensure - ENV['RUBYGEMS_GEMDEPS'] = rubygems_gemdeps + assert_equal add_bundler_full_name(%W[a-1]), loaded_spec_names + end end def test_use_gemdeps_automatic_missing - rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], '-' - - Gem.use_gemdeps + with_rubygems_gemdeps('-') do + Gem.use_gemdeps - assert true # count - ensure - ENV['RUBYGEMS_GEMDEPS'] = rubygems_gemdeps + assert true # count + end end def test_use_gemdeps_disabled - rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], '' + with_rubygems_gemdeps('') do + spec = util_spec 'a', 1 - spec = util_spec 'a', 1 + refute spec.activated? - refute spec.activated? - - File.open 'gem.deps.rb', 'w' do |io| - io.write 'gem "a"' - end + File.open 'gem.deps.rb', 'w' do |io| + io.write 'gem "a"' + end - Gem.use_gemdeps + Gem.use_gemdeps - refute spec.activated? - ensure - ENV['RUBYGEMS_GEMDEPS'] = rubygems_gemdeps + refute spec.activated? + end end def test_use_gemdeps_missing_gem - rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], 'x' - - File.open 'x', 'w' do |io| - io.write 'gem "a"' - end + with_rubygems_gemdeps('x') do + File.open 'x', 'w' do |io| + io.write 'gem "a"' + end - expected = <<-EXPECTED + expected = <<-EXPECTED Could not find gem 'a' in locally installed gems. You may need to `gem install -g` to install missing gems - EXPECTED + EXPECTED - Gem::Deprecate.skip_during do - actual_stdout, actual_stderr = capture_output do - Gem.use_gemdeps + Gem::Deprecate.skip_during do + actual_stdout, actual_stderr = capture_output do + Gem.use_gemdeps + end + assert_empty actual_stdout + assert_equal(expected, actual_stderr) end - assert_empty actual_stdout - assert_equal(expected, actual_stderr) end - ensure - ENV['RUBYGEMS_GEMDEPS'] = rubygems_gemdeps end def test_use_gemdeps_specific - rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], 'x' + with_rubygems_gemdeps('x') do + spec = util_spec 'a', 1 + install_specs spec - spec = util_spec 'a', 1 - install_specs spec - - spec = Gem::Specification.find {|s| s == spec } - refute spec.activated? + spec = Gem::Specification.find {|s| s == spec } + refute spec.activated? - File.open 'x', 'w' do |io| - io.write 'gem "a"' - end + File.open 'x', 'w' do |io| + io.write 'gem "a"' + end - Gem.use_gemdeps + Gem.use_gemdeps - assert_equal add_bundler_full_name(%W[a-1]), loaded_spec_names - ensure - ENV['RUBYGEMS_GEMDEPS'] = rubygems_gemdeps + assert_equal add_bundler_full_name(%W[a-1]), loaded_spec_names + end end def test_operating_system_defaults @@ -2148,4 +2132,12 @@ def with_path_and_rubyopt(path_value, rubyopt_value) ENV['PATH'] = path ENV['RUBYOPT'] = rubyopt end + + def with_rubygems_gemdeps(value) + rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], value + + yield + ensure + ENV['RUBYGEMS_GEMDEPS'] = rubygems_gemdeps + end end From 1da72785c0f4f64a4caa867b7493354e48ddcd96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Tue, 13 Apr 2021 13:03:59 +0200 Subject: [PATCH 655/707] Recommend `bundle install` rather than `gem install -g` --- test/rubygems/test_gem.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index d34aad78..0d4b1571 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1975,7 +1975,7 @@ def test_use_gemdeps_missing_gem expected = <<-EXPECTED Could not find gem 'a' in locally installed gems. -You may need to `gem install -g` to install missing gems +You may need to `bundle install` to install missing gems EXPECTED From dc05158e8475b2f8b259ea5052f9485f308492d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Wed, 4 Aug 2021 18:43:37 +0200 Subject: [PATCH 656/707] Remove sudo notes from README --- README.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/README.md b/README.md index 189b51c1..dcca2844 100644 --- a/README.md +++ b/README.md @@ -46,8 +46,6 @@ Install RubyGems by running: $ ruby setup.rb -Note: You may need to run the install script with admin/root privileges. - For more details and other options, see: $ ruby setup.rb --help @@ -58,8 +56,6 @@ To upgrade to the latest RubyGems, run: $ gem update --system -Note: You might need to run the command as an administrator or root user. - See [UPGRADING](UPGRADING.md) for more details and alternative instructions. ## Documentation From 124da9641c2465f09f12d6843d29940ab931a5a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Wed, 4 Aug 2021 18:45:08 +0200 Subject: [PATCH 657/707] Rubygems always comes with Ruby now --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index dcca2844..07042423 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ For more information about how to use RubyGems, see our RubyGems basics guide at ## Installation -RubyGems is likely already installed in your Ruby environment, you can check by running `gem --version` in your terminal emulator. +RubyGems is already installed in your Ruby environment, you can check the version you have installed by running `gem --version` in your terminal emulator. In some cases your OS's package manager may install RubyGems as a separate package from Ruby. It's recommended to check with your OS's package manager before installing RubyGems manually. From 446451efc05576b2b659a5e30bb1311073190e0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Wed, 4 Aug 2021 18:54:17 +0200 Subject: [PATCH 658/707] Improve paragraph about RubyGems provided by OS --- README.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 07042423..1f973c73 100644 --- a/README.md +++ b/README.md @@ -34,8 +34,14 @@ For more information about how to use RubyGems, see our RubyGems basics guide at ## Installation RubyGems is already installed in your Ruby environment, you can check the version you have installed by running `gem --version` in your terminal emulator. -In some cases your OS's package manager may install RubyGems as a separate package from Ruby. It's recommended to check -with your OS's package manager before installing RubyGems manually. + +In some cases Ruby & RubyGems may be provided as OS packages. This is not a +recommended way to use Ruby & RubyGems. It's better to use a Ruby Version +Manager, such as [rbenv](https://github.com/rbenv/rbenv) or +[chruby](https://github.com/postmodern/chruby). If you still want to use the +version provided by your OS package manager, please also use your OS package +manager to upgrade rubygems, and disregard any other installation instructions +given below. If you would like to manually install RubyGems: From ab76b5037e1025bf933d8ec84e1ce0ff0c3d3732 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Fri, 6 Aug 2021 12:21:23 +0200 Subject: [PATCH 659/707] Also load user installed rubygems plugins --- test/rubygems/test_gem.rb | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 0d4b1571..da154dac 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -1578,6 +1578,31 @@ def test_load_plugins assert_equal %w[plugin], PLUGINS_LOADED end + def test_load_user_installed_plugins + plugin_path = File.join "lib", "rubygems_plugin.rb" + + Dir.chdir @tempdir do + FileUtils.mkdir_p 'lib' + File.open plugin_path, "w" do |fp| + fp.puts "class TestGem; PLUGINS_LOADED << 'plugin'; end" + end + + foo = util_spec 'foo', '1' do |s| + s.files << plugin_path + end + + install_gem_user foo + end + + Gem.paths = { "GEM_PATH" => [Gem.dir, Gem.user_dir].join(File::PATH_SEPARATOR) } + + gem 'foo' + + Gem.load_plugins + + assert_equal %w[plugin], PLUGINS_LOADED + end + def test_load_env_plugins with_plugin('load') { Gem.load_env_plugins } assert_equal :loaded, TEST_PLUGIN_LOAD rescue nil From bf0535007e05e1734b4b30ef4628b45a74de1c17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Sun, 8 Aug 2021 10:40:11 +0200 Subject: [PATCH 660/707] Remove MacOS specific extra GEM_PATH They should properly configure `GEM_PATH` instead. --- test/rubygems/test_gem.rb | 35 ----------------------------------- 1 file changed, 35 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index da154dac..013daa06 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -943,44 +943,9 @@ def test_self_path def test_self_path_default util_path - if defined?(APPLE_GEM_HOME) - orig_APPLE_GEM_HOME = APPLE_GEM_HOME - Object.send :remove_const, :APPLE_GEM_HOME - end - Gem.instance_variable_set :@paths, nil assert_equal [Gem.default_path, Gem.dir].flatten.uniq, Gem.path - ensure - Object.const_set :APPLE_GEM_HOME, orig_APPLE_GEM_HOME if orig_APPLE_GEM_HOME - end - - unless win_platform? - def test_self_path_APPLE_GEM_HOME - util_path - - Gem.clear_paths - apple_gem_home = File.join @tempdir, 'apple_gem_home' - - old, $-w = $-w, nil - Object.const_set :APPLE_GEM_HOME, apple_gem_home - $-w = old - - assert_includes Gem.path, apple_gem_home - ensure - Object.send :remove_const, :APPLE_GEM_HOME - end - - def test_self_path_APPLE_GEM_HOME_GEM_PATH - Gem.clear_paths - ENV['GEM_PATH'] = @gemhome - apple_gem_home = File.join @tempdir, 'apple_gem_home' - Gem.const_set :APPLE_GEM_HOME, apple_gem_home - - refute Gem.path.include?(apple_gem_home) - ensure - Gem.send :remove_const, :APPLE_GEM_HOME - end end def test_self_path_ENV_PATH From b236bfe10c0b28dca3a2824a9f27485733a25c40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20Rodr=C3=ADguez?= Date: Sun, 8 Aug 2021 10:43:38 +0200 Subject: [PATCH 661/707] Remove helper method not buying us much --- test/rubygems/test_gem.rb | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index 013daa06..da6fdc54 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -931,17 +931,13 @@ def test_self_loaded_specs assert_equal true, Gem.loaded_specs.keys.include?('foo') end - def util_path - ENV.delete "GEM_HOME" - ENV.delete "GEM_PATH" - end - def test_self_path assert_equal [Gem.dir], Gem.path end def test_self_path_default - util_path + ENV.delete "GEM_HOME" + ENV.delete "GEM_PATH" Gem.instance_variable_set :@paths, nil From e5616e72dac703b51f635a8c395dba2c89045758 Mon Sep 17 00:00:00 2001 From: Alexey Spiridonov Date: Mon, 23 Aug 2021 15:09:30 -0700 Subject: [PATCH 662/707] Fix parsing of `dnf` output Summary: `dnf` will apparently sometimes print "Installing" and other times "Upgrading". For RPM replay purposes, these are identical. Reviewed By: naveedgol Differential Revision: D30487107 fbshipit-source-id: 78011602bc25ecb1bf369395cf9d6b2dd13e4e49 --- antlir/rpm/replay/subvol_rpm_compare.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/antlir/rpm/replay/subvol_rpm_compare.py b/antlir/rpm/replay/subvol_rpm_compare.py index ebbe928e..d0df428c 100644 --- a/antlir/rpm/replay/subvol_rpm_compare.py +++ b/antlir/rpm/replay/subvol_rpm_compare.py @@ -101,7 +101,7 @@ def _gen_nevras_from_installer_output( requested_nevras: Set[NEVRA], ) -> Iterator[NEVRA]: # `yum` and `dnf` differ in how they format the "progress" part - installing_re = re.compile(r"^ +Installing +: +([^ ]+) ") + installing_re = re.compile(r"^ +(Upgrading|Installing) +: +([^ ]+) ") nvra_re = re.compile(r"^([a-zA-Z0-9._+-]+)-([^-]+)-([^-]+)\.([^.]+)$") nevra_re = re.compile( r"^([a-zA-Z0-9._+-]+)-([0-9]+):([^-]+)-([^-]+)\.([^.]+)$" @@ -117,7 +117,7 @@ def _gen_nevras_from_installer_output( if not m: continue - pkg_spec = m.group(1) + pkg_spec = m.group(2) if ":" not in pkg_spec: # Both `yum` and `dnf` omit epoch if 0 m = nvra_re.match(pkg_spec) assert m, f"Could not parse {rpm_installer} output: {line}" From f6a6866b561444becfebff7cc853a444b8f87735 Mon Sep 17 00:00:00 2001 From: Naveed Golafshani Date: Thu, 26 Aug 2021 10:16:25 -0700 Subject: [PATCH 663/707] Unit test for parsing upgrade/update output for dnf/yum Summary: - Unit test - Add regex matching for yum updates Sample "upgrading" dnf output produced by running below: P452213369 ``` buck run tupperware/image/base:base.c8=container -- --user=root ./__antlir__/rpm/repo-snapshot/fb_centos8__6jCFX9ui_4h-3ji8xSKE/dnf/bin/dnf downgrade --assumeyes glibc ./__antlir__/rpm/repo-snapshot/fb_centos8__6jCFX9ui_4h-3ji8xSKE/dnf/bin/dnf install --assumeyes glibc-0:2.28-158.el8.x86_64 ``` Sample "updating" yum output produced by running below: P452212102 ``` buck run tupperware/image/base:base=container -- --user=root ./__antlir__/rpm/repo-snapshot/fb_centos7__leSKShneTV4rGfQk_DF2/yum/bin/yum downgrade --assumeyes curl ./__antlir__/rpm/repo-snapshot/fb_centos7__leSKShneTV4rGfQk_DF2/yum/bin/yum install --assumeyes curl-7.59.0-3.fb1.el7.centos.x86_64 ``` Reviewed By: snarkmaster Differential Revision: D30489326 fbshipit-source-id: be0bbef1394c303a751b265428a3bd438d4099c4 --- antlir/rpm/replay/subvol_rpm_compare.py | 4 ++- .../replay/tests/test_subvol_rpm_compare.py | 30 +++++++++++++++---- 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/antlir/rpm/replay/subvol_rpm_compare.py b/antlir/rpm/replay/subvol_rpm_compare.py index d0df428c..37338a23 100644 --- a/antlir/rpm/replay/subvol_rpm_compare.py +++ b/antlir/rpm/replay/subvol_rpm_compare.py @@ -101,7 +101,9 @@ def _gen_nevras_from_installer_output( requested_nevras: Set[NEVRA], ) -> Iterator[NEVRA]: # `yum` and `dnf` differ in how they format the "progress" part - installing_re = re.compile(r"^ +(Upgrading|Installing) +: +([^ ]+) ") + installing_re = re.compile( + r"^ +(Upgrading|Updating|Installing) +: +([^ ]+) " + ) nvra_re = re.compile(r"^([a-zA-Z0-9._+-]+)-([^-]+)-([^-]+)\.([^.]+)$") nevra_re = re.compile( r"^([a-zA-Z0-9._+-]+)-([0-9]+):([^-]+)-([^-]+)\.([^.]+)$" diff --git a/antlir/rpm/replay/tests/test_subvol_rpm_compare.py b/antlir/rpm/replay/tests/test_subvol_rpm_compare.py index 22394830..1860081b 100644 --- a/antlir/rpm/replay/tests/test_subvol_rpm_compare.py +++ b/antlir/rpm/replay/tests/test_subvol_rpm_compare.py @@ -14,6 +14,7 @@ subvol_rpm_compare, SubvolsToCompare, subvol_rpm_compare_and_download, + NEVRA, ) @@ -51,7 +52,6 @@ def test_subvol_rpm_compare_added_order(self): subvols = self.construct_subvols_to_compare() rd = subvol_rpm_compare(subvols=subvols) rpms_added_names = [nevra.name for nevra in rd.added_in_order] - rpms_removed_names = [nevra.name for nevra in rd.removed] rpms_with_deps = [ "rpm-test-first", "rpm-test-second", @@ -62,13 +62,30 @@ def test_subvol_rpm_compare_added_order(self): self.assertIn( rpms_added_names, [ - # Since `has-epoch` has no deps or dependents, it could - # go in either order - [*rpms_with_deps, "rpm-test-has-epoch"], - ["rpm-test-has-epoch", *rpms_with_deps], + # Since `has-epoch` and `mice` has no deps or dependents, + # it could go in any order + [*rpms_with_deps, "rpm-test-mice", "rpm-test-has-epoch"], + [*rpms_with_deps, "rpm-test-has-epoch", "rpm-test-mice"], + ["rpm-test-mice", "rpm-test-has-epoch", *rpms_with_deps], + ["rpm-test-has-epoch", "rpm-test-mice", *rpms_with_deps], + ["rpm-test-has-epoch", *rpms_with_deps, "rpm-test-mice"], + ["rpm-test-mice", *rpms_with_deps, "rpm-test-has-epoch"], ], ) - self.assertEqual(["rpm-test-milk"], rpms_removed_names) + + # mice should be upgraded to 0.2 version + self.assertIn( + NEVRA("rpm-test-mice", "0", "0.2", "a", "x86_64"), rd.added_in_order + ) + + self.assertEqual( + { + # mice upgrade causes 0.1 version to be removed + NEVRA("rpm-test-mice", "0", "0.1", "a", "x86_64"), + NEVRA("rpm-test-milk", "0", "2.71", "8", "x86_64"), + }, + rd.removed, + ) def test_subvol_rpm_compare_and_download(self): subvols = self.construct_subvols_to_compare() @@ -87,6 +104,7 @@ def test_subvol_rpm_compare_and_download(self): "rpm-test-third-0-0.x86_64.rpm", "rpm-test-fourth-0-0.x86_64.rpm", "rpm-test-fifth-0-0.x86_64.rpm", + "rpm-test-mice-0.2-a.x86_64.rpm", }, downloaded_rpms, ) From 74eb47670a4aef9f7fdc5b7709c34417dd6a2a43 Mon Sep 17 00:00:00 2001 From: Alexey Spiridonov Date: Tue, 31 Aug 2021 08:04:05 -0700 Subject: [PATCH 664/707] `RpmMetadata` queries must use the BA when accesing a subvol Summary: The `rpm` version on some CI hosts was newer than that inside a build appliance. The net result is that when `RpmMetadata` would this host `rpm` against an image-under-construction, it would upgrade its RPM DB. That would, in turn, make it unreadable to the older version of `rpm` that was supplied by the BA, causing build failures. Fix this by using the BA version of `rpm`. Reviewed By: zeroxoneb Differential Revision: D30640692 fbshipit-source-id: 20822f20a2eabe12e3f2ce12956d0e511b3de44a --- antlir/rpm/rpm_metadata.py | 121 +++++++++++++++----------- antlir/rpm/tests/test_rpm_metadata.py | 28 ++++-- 2 files changed, 90 insertions(+), 59 deletions(-) diff --git a/antlir/rpm/rpm_metadata.py b/antlir/rpm/rpm_metadata.py index c99ca709..3961f083 100644 --- a/antlir/rpm/rpm_metadata.py +++ b/antlir/rpm/rpm_metadata.py @@ -7,10 +7,12 @@ import os import re import subprocess -from typing import NamedTuple +from typing import List, NamedTuple, Optional from antlir.common import get_logger -from antlir.fs_utils import Path +from antlir.fs_utils import generate_work_dir, MehStr, Path +from antlir.nspawn_in_subvol.args import PopenArgs, new_nspawn_opts +from antlir.nspawn_in_subvol.nspawn import run_nspawn from antlir.subvol_utils import Subvol @@ -24,62 +26,75 @@ class RpmMetadata(NamedTuple): release: str @classmethod - def from_subvol(cls, subvol: Subvol, package_name: str) -> "RpmMetadata": - db_path = subvol.path("var/lib/rpm") - - # `rpm` always creates a DB when `--dbpath` is an arg. - # We don't want to create one if it does not already exist so check for - # that here. - if not os.path.exists(db_path): - raise ValueError(f"RPM DB path {db_path} does not exist") - - # pyre-fixme[6]: Expected `RpmMetadata` for 1st param but got - # `Type[RpmMetadata]`. - return cls._repo_query(cls, db_path, package_name, None) + def from_subvol( + cls, subvol: Subvol, ba_subvol: Subvol, package_name: str + ) -> "RpmMetadata": + db_path_src = subvol.path("var/lib/rpm") + if not os.path.exists(db_path_src): + # If we didn't check for this, `bindmount_ro` would fail. + raise ValueError(f"RPM DB path {db_path_src} does not exist") + # Rpm query will write to and update rpm database files if it can. + # We must use the BA here because using the host `rpm` can cause the + # image RPM to become unreadable to the `rpm` from the BA. + db_path_dst = generate_work_dir() + return _repo_query( + db_path=db_path_dst, + package_name=package_name, + check_output_fn=lambda cmd: run_nspawn( + new_nspawn_opts( + cmd=cmd, + layer=ba_subvol, + # Read-only so that `rpm` does not modify the DB or + # create one when it does not already exist. + bindmount_ro=[(db_path_src, db_path_dst)], + ), + PopenArgs(stdout=subprocess.PIPE), + )[0].stdout, + ) @classmethod def from_file(cls, package_path: Path) -> "RpmMetadata": if not package_path.endswith(b".rpm"): raise ValueError(f"RPM file {package_path} needs to end with .rpm") - - # pyre-fixme[6]: Expected `RpmMetadata` for 1st param but got - # `Type[RpmMetadata]`. - return cls._repo_query(cls, None, None, package_path) - - def _repo_query( - self, db_path: Path, package_name: str, package_path: Path - ) -> "RpmMetadata": - query_args = [ - "rpm", - "--query", - "--queryformat", - "'%{NAME}:%{epochnum}:%{VERSION}:%{RELEASE}'", - ] - - if db_path and package_name and (package_path is None): - # pyre-fixme[6]: Expected `Iterable[str]` for 1st param but got - # `Iterable[typing.Union[Path, str]]`. - query_args += ["--dbpath", db_path, package_name] - elif package_path and (db_path is None and package_name is None): - # pyre-fixme[6]: Expected `Iterable[str]` for 1st param but got - # `Iterable[typing.Union[Path, str]]`. - query_args += ["--package", package_path] - else: - raise ValueError( - "Must pass only (--dbpath and --package_name) or --package" - ) - - try: - result = ( - subprocess.check_output(query_args, stderr=subprocess.PIPE) - .decode() - .strip("'\"") - ) - except subprocess.CalledProcessError as e: - raise RuntimeError(f"Error querying RPM: {e.stdout}, {e.stderr}") - - n, e, v, r = result.split(":") - return RpmMetadata(name=n, epoch=int(e), version=v, release=r) + return _repo_query( + package_path=package_path, + check_output_fn=subprocess.check_output, + ) + + +def _repo_query( + *, + db_path: Optional[Path] = None, + package_name: Optional[str] = None, + package_path: Optional[Path] = None, + check_output_fn, +) -> "RpmMetadata": + query_args: List[MehStr] = [ + "rpm", + "--query", + "--queryformat", + "'%{NAME}:%{epochnum}:%{VERSION}:%{RELEASE}'", + ] + + if db_path and package_name and (package_path is None): + query_args += ["--dbpath", db_path, package_name] + elif package_path and (db_path is None and package_name is None): + query_args += ["--package", package_path] + else: + raise ValueError( + "Must pass only (--dbpath and --package_name) or --package" + ) + + try: + result = check_output_fn(query_args).decode().strip("'\"") + log.debug(f"RPM query {query_args} returned {result}") + except subprocess.CalledProcessError as e: + raise RuntimeError( + f"Error querying RPM: {query_args}, {e.stdout}, {e.stderr}" + ) + + n, e, v, r = result.split(":") + return RpmMetadata(name=n, epoch=int(e), version=v, release=r) # This comprises a pure python implementation of rpm version comparison. The diff --git a/antlir/rpm/tests/test_rpm_metadata.py b/antlir/rpm/tests/test_rpm_metadata.py index 8e5bd36d..1c61b272 100644 --- a/antlir/rpm/tests/test_rpm_metadata.py +++ b/antlir/rpm/tests/test_rpm_metadata.py @@ -12,8 +12,14 @@ from antlir.find_built_subvol import find_built_subvol from antlir.fs_utils import temp_dir - -from ..rpm_metadata import RpmMetadata, _compare_values, compare_rpm_versions +from antlir.tests.layer_resource import layer_resource_subvol + +from ..rpm_metadata import ( + RpmMetadata, + _compare_values, + compare_rpm_versions, + _repo_query, +) from .temp_repos import Repo, Rpm, get_test_signing_key, temp_repos_steps @@ -33,8 +39,9 @@ def _load_canonical_tests(self): def test_rpm_metadata_from_subvol(self): layer_path = os.path.join(os.path.dirname(__file__), "child-layer") child_subvol = find_built_subvol(layer_path) + ba_subvol = layer_resource_subvol(__package__, "test-build-appliance") - a = RpmMetadata.from_subvol(child_subvol, "rpm-test-mice") + a = RpmMetadata.from_subvol(child_subvol, ba_subvol, "rpm-test-mice") self.assertEqual(a.name, "rpm-test-mice") self.assertEqual(a.epoch, 0) self.assertEqual(a.version, "0.1") @@ -42,13 +49,17 @@ def test_rpm_metadata_from_subvol(self): # not installed with self.assertRaises(RuntimeError): - a = RpmMetadata.from_subvol(child_subvol, "rpm-test-carrot") + a = RpmMetadata.from_subvol( + child_subvol, ba_subvol, "rpm-test-carrot" + ) # subvol with no RPM DB layer_path = os.path.join(os.path.dirname(__file__), "hello-layer") hello_subvol = find_built_subvol(layer_path) with self.assertRaisesRegex(ValueError, " does not exist$"): - a = RpmMetadata.from_subvol(hello_subvol, "rpm-test-mice") + a = RpmMetadata.from_subvol( + hello_subvol, ba_subvol, "rpm-test-mice" + ) def test_rpm_metadata_from_file(self): with temp_repos_steps( @@ -83,7 +94,12 @@ def test_rpm_metadata_from_file(self): def test_rpm_query_arg_check(self): with self.assertRaisesRegex(ValueError, "^Must pass only "): - RpmMetadata._repo_query(RpmMetadata, b"dbpath", None, b"path") + _repo_query( + db_path=b"dbpath", + package_name=None, + package_path=b"path", + check_output_fn="unused", + ) def test_rpm_compare_versions(self): # name mismatch From 1274d0fad886ed8ca22a928f8bc51db26359738c Mon Sep 17 00:00:00 2001 From: David Rodriguez Date: Mon, 11 Oct 2021 15:42:39 +0200 Subject: [PATCH 665/707] Unify issue template and ISSUES.md document Some crucial information to ease maintainers work, like the advice of upgrading rubygems and bundler, was one step away from the issue template, making it easier for some users to miss. Now all relevant information is written directly in the bug report template. --- bundler/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundler/README.md b/bundler/README.md index 9c65a803..ca0ab2d8 100644 --- a/bundler/README.md +++ b/bundler/README.md @@ -32,7 +32,7 @@ See [bundler.io](https://bundler.io) for the full documentation. For help with common problems, see [TROUBLESHOOTING](doc/TROUBLESHOOTING.md). -Still stuck? Try [filing an issue](doc/contributing/ISSUES.md). +Still stuck? Try [filing an issue](https://github.com/rubygems/rubygems/issues/new?labels=Bundler&template=bundler-related-issue.md). ### Other questions From 880c6ce5a5d0846395b40d5aab4ca9a5924a9934 Mon Sep 17 00:00:00 2001 From: Nobuyoshi Nakada Date: Thu, 14 Oct 2021 00:17:35 +0900 Subject: [PATCH 666/707] Remove save_loaded_features --- test/rubygems/test_gem.rb | 130 +++++++++++++++++--------------------- 1 file changed, 59 insertions(+), 71 deletions(-) diff --git a/test/rubygems/test_gem.rb b/test/rubygems/test_gem.rb index da6fdc54..3c95982d 100644 --- a/test/rubygems/test_gem.rb +++ b/test/rubygems/test_gem.rb @@ -25,72 +25,66 @@ def setup end def test_self_finish_resolve - save_loaded_features do - a1 = util_spec "a", "1", "b" => "> 0" - b1 = util_spec "b", "1", "c" => ">= 1" - b2 = util_spec "b", "2", "c" => ">= 2" - c1 = util_spec "c", "1" - c2 = util_spec "c", "2" + a1 = util_spec "a", "1", "b" => "> 0" + b1 = util_spec "b", "1", "c" => ">= 1" + b2 = util_spec "b", "2", "c" => ">= 2" + c1 = util_spec "c", "1" + c2 = util_spec "c", "2" - install_specs c1, c2, b1, b2, a1 + install_specs c1, c2, b1, b2, a1 - a1.activate + a1.activate - assert_equal %w[a-1], loaded_spec_names - assert_equal ["b (> 0)"], unresolved_names + assert_equal %w[a-1], loaded_spec_names + assert_equal ["b (> 0)"], unresolved_names - Gem.finish_resolve + Gem.finish_resolve - assert_equal %w[a-1 b-2 c-2], loaded_spec_names - assert_equal [], unresolved_names - end + assert_equal %w[a-1 b-2 c-2], loaded_spec_names + assert_equal [], unresolved_names end def test_self_finish_resolve_wtf - save_loaded_features do - a1 = util_spec "a", "1", "b" => "> 0", "d" => "> 0" # this - b1 = util_spec "b", "1", { "c" => ">= 1" }, "lib/b.rb" # this - b2 = util_spec "b", "2", { "c" => ">= 2" }, "lib/b.rb" - c1 = util_spec "c", "1" # this - c2 = util_spec "c", "2" - d1 = util_spec "d", "1", { "c" => "< 2" }, "lib/d.rb" - d2 = util_spec "d", "2", { "c" => "< 2" }, "lib/d.rb" # this + a1 = util_spec "a", "1", "b" => "> 0", "d" => "> 0" # this + b1 = util_spec "b", "1", { "c" => ">= 1" }, "lib/b.rb" # this + b2 = util_spec "b", "2", { "c" => ">= 2" }, "lib/b.rb" + c1 = util_spec "c", "1" # this + c2 = util_spec "c", "2" + d1 = util_spec "d", "1", { "c" => "< 2" }, "lib/d.rb" + d2 = util_spec "d", "2", { "c" => "< 2" }, "lib/d.rb" # this - install_specs c1, c2, b1, b2, d1, d2, a1 + install_specs c1, c2, b1, b2, d1, d2, a1 - a1.activate + a1.activate - assert_equal %w[a-1], loaded_spec_names - assert_equal ["b (> 0)", "d (> 0)"], unresolved_names + assert_equal %w[a-1], loaded_spec_names + assert_equal ["b (> 0)", "d (> 0)"], unresolved_names - Gem.finish_resolve + Gem.finish_resolve - assert_equal %w[a-1 b-1 c-1 d-2], loaded_spec_names - assert_equal [], unresolved_names - end + assert_equal %w[a-1 b-1 c-1 d-2], loaded_spec_names + assert_equal [], unresolved_names end def test_self_finish_resolve_respects_loaded_specs - save_loaded_features do - a1 = util_spec "a", "1", "b" => "> 0" - b1 = util_spec "b", "1", "c" => ">= 1" - b2 = util_spec "b", "2", "c" => ">= 2" - c1 = util_spec "c", "1" - c2 = util_spec "c", "2" + a1 = util_spec "a", "1", "b" => "> 0" + b1 = util_spec "b", "1", "c" => ">= 1" + b2 = util_spec "b", "2", "c" => ">= 2" + c1 = util_spec "c", "1" + c2 = util_spec "c", "2" - install_specs c1, c2, b1, b2, a1 + install_specs c1, c2, b1, b2, a1 - a1.activate - c1.activate + a1.activate + c1.activate - assert_equal %w[a-1 c-1], loaded_spec_names - assert_equal ["b (> 0)"], unresolved_names + assert_equal %w[a-1 c-1], loaded_spec_names + assert_equal ["b (> 0)"], unresolved_names - Gem.finish_resolve + Gem.finish_resolve - assert_equal %w[a-1 b-1 c-1], loaded_spec_names - assert_equal [], unresolved_names - end + assert_equal %w[a-1 b-1 c-1], loaded_spec_names + assert_equal [], unresolved_names end def test_self_install @@ -210,25 +204,21 @@ def assert_self_install_permissions(format_executable: false) end def test_require_missing - save_loaded_features do - assert_raise ::LoadError do - require "test_require_missing" - end + assert_raise ::LoadError do + require "test_require_missing" end end def test_require_does_not_glob - save_loaded_features do - a1 = util_spec "a", "1", nil, "lib/a1.rb" + a1 = util_spec "a", "1", nil, "lib/a1.rb" - install_specs a1 - - assert_raise ::LoadError do - require "a*" - end + install_specs a1 - assert_equal [], loaded_spec_names + assert_raise ::LoadError do + require "a*" end + + assert_equal [], loaded_spec_names end def test_self_bin_path_active @@ -1444,24 +1434,22 @@ def test_self_needs end def test_self_needs_picks_up_unresolved_deps - save_loaded_features do - a = util_spec "a", "1" - b = util_spec "b", "1", "c" => nil - c = util_spec "c", "2" - d = util_spec "d", "1", {'e' => '= 1'}, "lib/d#{$$}.rb" - e = util_spec "e", "1" - - install_specs a, c, b, e, d + a = util_spec "a", "1" + b = util_spec "b", "1", "c" => nil + c = util_spec "c", "2" + d = util_spec "d", "1", {'e' => '= 1'}, "lib/d#{$$}.rb" + e = util_spec "e", "1" - Gem.needs do |r| - r.gem "a" - r.gem "b", "= 1" + install_specs a, c, b, e, d - require "d#{$$}" - end + Gem.needs do |r| + r.gem "a" + r.gem "b", "= 1" - assert_equal %w[a-1 b-1 c-2 d-1 e-1], loaded_spec_names + require "d#{$$}" end + + assert_equal %w[a-1 b-1 c-2 d-1 e-1], loaded_spec_names end def test_self_gunzip From b4456dee63ab63e725a01922aa561dec4bd21d8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josef=20=C5=A0im=C3=A1nek?= Date: Tue, 26 Oct 2021 01:20:12 +0200 Subject: [PATCH 667/707] Enforce bundler platform (and default gem) to keep invalid gemspec test compatible with ruby-trunk. --- bundler/spec/realworld/edgecases_spec.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bundler/spec/realworld/edgecases_spec.rb b/bundler/spec/realworld/edgecases_spec.rb index f031e2f3..df5eeda9 100644 --- a/bundler/spec/realworld/edgecases_spec.rb +++ b/bundler/spec/realworld/edgecases_spec.rb @@ -197,10 +197,11 @@ def rubygems_version(name, requirement) end it "outputs a helpful error message when gems have invalid gemspecs" do - install_gemfile <<-G, :standalone => true, :raise_on_error => false + install_gemfile <<-G, :standalone => true, :raise_on_error => false, :env => { "BUNDLE_FORCE_RUBY_PLATFORM" => "1" } source 'https://rubygems.org' gem "resque-scheduler", "2.2.0" gem "redis-namespace", "1.6.0" # for a consistent resolution including ruby 2.3.0 + gem "ruby2_keywords", "0.0.5" G expect(err).to include("You have one or more invalid gemspecs that need to be fixed.") expect(err).to include("resque-scheduler 2.2.0 has an invalid gemspec") From 7429c6fac30333e83b65975f951364ce08e90d76 Mon Sep 17 00:00:00 2001 From: Lindsay Salisbury Date: Fri, 5 Nov 2021 20:01:21 -0700 Subject: [PATCH 668/707] Support cross-cell use of Antlir (#172) Summary: Pull Request resolved: https://github.com/facebookincubator/antlir/pull/172 This diff is the final step in enabling Antlir to be useable cross-cell. It makes the following changes to support this: - Adds the `antlir_cell_name` to the `repo_config` so that it can be usable in python/other code. - Adds an `antlir_dep` helper in python that mirrors the one in `bzl/target_helpers.bzl` - Adds a `repository_name` shim so that we can retrieve the current "cell" being used from .bzl code. Unfortunately, `native.repository_name` does not work the way it should. - Fixes up the places where an `antlir_dep` is needed (ie: anywhere a naked `//antlir/...` is used) Reviewed By: vmagro Differential Revision: D31852138 fbshipit-source-id: a5a9cf7605b4c08aa6dde25502edbc39c43bb1ab --- antlir/rpm/replay/tests/test_subvol_rpm_compare.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/antlir/rpm/replay/tests/test_subvol_rpm_compare.py b/antlir/rpm/replay/tests/test_subvol_rpm_compare.py index 1860081b..d04c39e3 100644 --- a/antlir/rpm/replay/tests/test_subvol_rpm_compare.py +++ b/antlir/rpm/replay/tests/test_subvol_rpm_compare.py @@ -5,6 +5,7 @@ import unittest +from antlir.config import antlir_dep from antlir.rpm.find_snapshot import snapshot_install_dir from antlir.rpm.yum_dnf_conf import YumDnf from antlir.subvol_utils import Subvol @@ -32,7 +33,7 @@ def construct_subvols_to_compare( leaf=leaf, rpm_installer=self._YUM_DNF, rpm_repo_snapshot=snapshot_install_dir( - "//antlir/rpm:rpm-replay-repo-snapshot-for-tests" + antlir_dep("rpm:rpm-replay-repo-snapshot-for-tests") ), ) From 6a73d2a2edc32978c18f255fa0d7bd9e3ec2f358 Mon Sep 17 00:00:00 2001 From: Philippe Ombredanne Date: Tue, 23 Nov 2021 14:52:36 +0100 Subject: [PATCH 669/707] Move code for univers integration Move methid from init in module Add original license notices to code Rename paths to match univers Signed-off-by: Philippe Ombredanne --- .../gemrequirement.py => src/univers/gem.py | 26 ++++++++++++++++++- .../test_gemrequirement.py => test_gem.py} | 14 ++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) rename puppeter/domain/model/gemrequirement.py => src/univers/gem.py (87%) rename tests/{domain/model/test_gemrequirement.py => test_gem.py} (67%) diff --git a/puppeter/domain/model/gemrequirement.py b/src/univers/gem.py similarity index 87% rename from puppeter/domain/model/gemrequirement.py rename to src/univers/gem.py index 32322177..dfa96a96 100644 --- a/puppeter/domain/model/gemrequirement.py +++ b/src/univers/gem.py @@ -1,9 +1,33 @@ +# Copyright 2017 Center for Information Technology +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + import re from six import iterkeys, itervalues +from typing import Type, TypeVar from typing import Callable, Sequence, MutableSequence -from puppeter.domain import default + +T = TypeVar('T') + + +def default(x, e, y): + # type: (Callable[[], T], Type[Exception], T) -> T + try: + return x() + except e: + return y class GemVersion: diff --git a/tests/domain/model/test_gemrequirement.py b/tests/test_gem.py similarity index 67% rename from tests/domain/model/test_gemrequirement.py rename to tests/test_gem.py index 9d03a284..ac5a5650 100644 --- a/tests/domain/model/test_gemrequirement.py +++ b/tests/test_gem.py @@ -1,3 +1,17 @@ +# Copyright 2017 Center for Information Technology +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + import pytest from puppeter.domain.model.gemrequirement import GemVersion, GemRequirement From 431ab19193a08872f88dce6af57771dd5d83ff86 Mon Sep 17 00:00:00 2001 From: Philippe Ombredanne Date: Tue, 23 Nov 2021 15:11:12 +0100 Subject: [PATCH 670/707] Add docstring to Maven ranges Signed-off-by: Philippe Ombredanne --- src/univers/version_range.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/univers/version_range.py b/src/univers/version_range.py index 5604b1aa..c29af8b8 100644 --- a/src/univers/version_range.py +++ b/src/univers/version_range.py @@ -304,6 +304,10 @@ def from_native(cls, string): class MavenVersionRange(VersionRange): + """ + Maven version range as documented at + https://maven.apache.org/enforcer/enforcer-rules/versionRanges.html + """ scheme = "maven" version_class = versions.MavenVersion @@ -321,6 +325,7 @@ class ComposerVersionRange(VersionRange): class RpmVersionRange(VersionRange): + # https://twiki.cern.ch/twiki/bin/view/Main/RPMAndDebVersioning scheme = "rpm" version_class = versions.RpmVersion From a094fd3404180b89b486e2c248c3d93057b97bc2 Mon Sep 17 00:00:00 2001 From: Philippe Ombredanne Date: Tue, 23 Nov 2021 15:14:50 +0100 Subject: [PATCH 671/707] Format code Signed-off-by: Philippe Ombredanne --- src/univers/gem.py | 67 ++++++++++++++++++++---------------- src/univers/version_range.py | 1 + tests/test_gem.py | 46 +++++++++++++------------ 3 files changed, 62 insertions(+), 52 deletions(-) diff --git a/src/univers/gem.py b/src/univers/gem.py index dfa96a96..3fe5c88f 100644 --- a/src/univers/gem.py +++ b/src/univers/gem.py @@ -1,11 +1,11 @@ # Copyright 2017 Center for Information Technology -# +# # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -19,7 +19,7 @@ from typing import Callable, Sequence, MutableSequence -T = TypeVar('T') +T = TypeVar("T") def default(x, e, y): @@ -31,14 +31,16 @@ def default(x, e, y): class GemVersion: - VERSION_PATTERN = '[0-9]+(?:\.[0-9a-zA-Z]+)*(-[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?' - ANCHORED_VERSION_PATTERN = re.compile('^\s*({VERSION_PATTERN})?\s*$'.format(VERSION_PATTERN=VERSION_PATTERN)) + VERSION_PATTERN = "[0-9]+(?:\.[0-9a-zA-Z]+)*(-[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?" + ANCHORED_VERSION_PATTERN = re.compile( + "^\s*({VERSION_PATTERN})?\s*$".format(VERSION_PATTERN=VERSION_PATTERN) + ) def __init__(self, version): # If version is an empty string convert it to 0 - version = 0 if re.compile('^\s*$').match(str(version)) else version + version = 0 if re.compile("^\s*$").match(str(version)) else version - self.__version = str(version).strip().replace('-', '.pre.') + self.__version = str(version).strip().replace("-", ".pre.") self.__segments = None self.__bump = None self.__release = None @@ -52,7 +54,7 @@ def bump(self): segments.pop() segments[-1] = segments[-1] + 1 segments = list(map(lambda r: str(r), segments)) - self.__bump = GemVersion('.'.join(segments)) + self.__bump = GemVersion(".".join(segments)) return self.__bump @@ -62,7 +64,7 @@ def release(self): while any(map(lambda s: isinstance(s, str), segments)): segments.pop() segments = list(map(lambda r: str(r), segments)) - self.__release = GemVersion('.'.join(segments)) + self.__release = GemVersion(".".join(segments)) return self.__release @@ -108,40 +110,42 @@ def __eq__(self, other): return self.__cmp__(other) == 0 def __repr__(self): - return 'GemVersion({segments})'.format(segments=self.segments()) + return "GemVersion({segments})".format(segments=self.segments()) def __get_segments(self): # type: () -> Sequence[int|str] if not self.__segments: - rex = re.compile('[0-9]+|[a-z]+', re.IGNORECASE) - d_rex = re.compile('^\d+$') - self.__segments = tuple(map(lambda s: int(s) if d_rex.match(s) else s, rex.findall(self.__version))) + rex = re.compile("[0-9]+|[a-z]+", re.IGNORECASE) + d_rex = re.compile("^\d+$") + self.__segments = tuple( + map(lambda s: int(s) if d_rex.match(s) else s, rex.findall(self.__version)) + ) return self.__segments class GemRequirement: OPS = { - '=': lambda v, r: v == r, - '!=': lambda v, r: v != r, - '>': lambda v, r: v > r, - '<': lambda v, r: v < r, - '>=': lambda v, r: v >= r, - '<=': lambda v, r: v <= r, - '~>': lambda v, r: v >= r and v.release() < r.bump() + "=": lambda v, r: v == r, + "!=": lambda v, r: v != r, + ">": lambda v, r: v > r, + "<": lambda v, r: v < r, + ">=": lambda v, r: v >= r, + "<=": lambda v, r: v <= r, + "~>": lambda v, r: v >= r and v.release() < r.bump(), } PATTERN_RAW = "\\s*({quoted})?\\s*({VERSION_PATTERN})\\s*".format( - quoted='|'.join(tuple(map(lambda k: re.escape(k), iterkeys(OPS)))), - VERSION_PATTERN=GemVersion.VERSION_PATTERN + quoted="|".join(tuple(map(lambda k: re.escape(k), iterkeys(OPS)))), + VERSION_PATTERN=GemVersion.VERSION_PATTERN, ) # A regular expression that matches a requirement - PATTERN = re.compile('^{PATTERN_RAW}$'.format(PATTERN_RAW=PATTERN_RAW)) + PATTERN = re.compile("^{PATTERN_RAW}$".format(PATTERN_RAW=PATTERN_RAW)) ## # The default requirement matches any version - DEFAULT_REQUIREMENT = tuple(['>=', GemVersion(0)]) + DEFAULT_REQUIREMENT = tuple([">=", GemVersion(0)]) class BadRequirementError(AttributeError): pass @@ -156,16 +160,18 @@ def __init__(self, *requirements): @classmethod def parse(cls, requirement): if isinstance(requirement, GemVersion): - return tuple(['=', requirement]) + return tuple(["=", requirement]) match = cls.PATTERN.match(str(requirement)) if not match: - raise cls.BadRequirementError('Illformed requirement [{inspect}]'.format(inspect=repr(requirement))) + raise cls.BadRequirementError( + "Illformed requirement [{inspect}]".format(inspect=repr(requirement)) + ) - if match.group(1) == '>=' and match.group(2) == '0': + if match.group(1) == ">=" and match.group(2) == "0": return cls.DEFAULT_REQUIREMENT else: - op = match.group(1) if match.group(1) else '=' + op = match.group(1) if match.group(1) else "=" return tuple([op, GemVersion(match.group(2))]) def satified_by(self, version): @@ -180,6 +186,7 @@ def __testing(req): op, rv = req callable = cls.__get_operation(op) return callable(version, rv) + return __testing @classmethod @@ -188,4 +195,4 @@ def __get_operation(cls, op): try: return cls.OPS[op] except KeyError: - return cls.OPS['='] + return cls.OPS["="] diff --git a/src/univers/version_range.py b/src/univers/version_range.py index c29af8b8..90372543 100644 --- a/src/univers/version_range.py +++ b/src/univers/version_range.py @@ -308,6 +308,7 @@ class MavenVersionRange(VersionRange): Maven version range as documented at https://maven.apache.org/enforcer/enforcer-rules/versionRanges.html """ + scheme = "maven" version_class = versions.MavenVersion diff --git a/tests/test_gem.py b/tests/test_gem.py index ac5a5650..8d2aaafc 100644 --- a/tests/test_gem.py +++ b/tests/test_gem.py @@ -1,11 +1,11 @@ # Copyright 2017 Center for Information Technology -# +# # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -18,47 +18,49 @@ def test_gem_version_release(): # given - v = GemVersion('1.2.4.beta') + v = GemVersion("1.2.4.beta") # when released = v.release() # then - assert GemVersion('1.2.4') == released + assert GemVersion("1.2.4") == released def test_gem_version_bump(): # given - v = GemVersion('1.2.4') + v = GemVersion("1.2.4") # when bumped = v.bump() # then - assert GemVersion('1.3.0') == bumped + assert GemVersion("1.3.0") == bumped def test_gem_version_compare(): - assert GemVersion('1.3.0') == GemVersion('1.3') - assert GemVersion('1.3.0') <= GemVersion('1.3') - assert GemVersion('1.1.3') <= GemVersion('1.3') - assert GemVersion('1.4.pre') >= GemVersion('1.3') - assert GemVersion('1.4.pre') != GemVersion('1.4') + assert GemVersion("1.3.0") == GemVersion("1.3") + assert GemVersion("1.3.0") <= GemVersion("1.3") + assert GemVersion("1.1.3") <= GemVersion("1.3") + assert GemVersion("1.4.pre") >= GemVersion("1.3") + assert GemVersion("1.4.pre") != GemVersion("1.4") -@pytest.mark.parametrize('requirement,version', [ - (['3.4'], '3.4.0'), - (['~> 3.4'], '3.4.8'), - (['>= 3.4'], '4.4.8'), - (['>= 3.4', '<4'], '3.45.8') -]) +@pytest.mark.parametrize( + "requirement,version", + [ + (["3.4"], "3.4.0"), + (["~> 3.4"], "3.4.8"), + ([">= 3.4"], "4.4.8"), + ([">= 3.4", "<4"], "3.45.8"), + ], +) def test_gem_requirement(requirement, version): assert GemRequirement(*requirement).satified_by(version) -@pytest.mark.parametrize('requirement,version', [ - (['>= 3.4', '<4'], '4.1'), - (['~> 3'], '4.1.0.pre') -]) +@pytest.mark.parametrize( + "requirement,version", [([">= 3.4", "<4"], "4.1"), (["~> 3"], "4.1.0.pre")] +) def test_gem_requirement_fails(requirement, version): assert GemRequirement(*requirement).satified_by(version) is False From 5e873830139b1a9301cd823cc20c3a8fb9fd5465 Mon Sep 17 00:00:00 2001 From: Philippe Ombredanne Date: Wed, 24 Nov 2021 01:11:51 +0100 Subject: [PATCH 672/707] Add ABOUt files for gem code Signed-off-by: Philippe Ombredanne --- src/univers/gem.py.ABOUT | 8 ++++++++ src/univers/gem.py.NOTICE | 13 +++++++++++++ tests/test_gem.py.ABOUT | 8 ++++++++ tests/test_gem.py.NOTICE | 13 +++++++++++++ 4 files changed, 42 insertions(+) create mode 100644 src/univers/gem.py.ABOUT create mode 100644 src/univers/gem.py.NOTICE create mode 100644 tests/test_gem.py.ABOUT create mode 100644 tests/test_gem.py.NOTICE diff --git a/src/univers/gem.py.ABOUT b/src/univers/gem.py.ABOUT new file mode 100644 index 00000000..37a00fb6 --- /dev/null +++ b/src/univers/gem.py.ABOUT @@ -0,0 +1,8 @@ +about_resource: gem.py +license_expression: apache-2.0 +download_url: https://raw.githubusercontent.com/coi-gov-pl/puppeter/04e2a2008bd89a0429b734fdde6da83813688865/puppeter/domain/model/gemrequirement.py +copyright: Copyright (c) Center for Information Technology http://coi.gov.pl +package_url: pkg:pypi/puppeter@0.8.3#src/domain/model/gemrequirement.py +notes: This is a subset of the code modified for univers +homepage_url: https://github.com/coi-gov-pl/puppeter +notice_file: gem.py.NOTICE diff --git a/src/univers/gem.py.NOTICE b/src/univers/gem.py.NOTICE new file mode 100644 index 00000000..6616bc4d --- /dev/null +++ b/src/univers/gem.py.NOTICE @@ -0,0 +1,13 @@ +# Copyright 2017 Center for Information Technology +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. \ No newline at end of file diff --git a/tests/test_gem.py.ABOUT b/tests/test_gem.py.ABOUT new file mode 100644 index 00000000..4e8a5d2e --- /dev/null +++ b/tests/test_gem.py.ABOUT @@ -0,0 +1,8 @@ +about_resource: test_gem.py +license_expression: apache-2.0 +download_url: https://raw.githubusercontent.com/coi-gov-pl/puppeter/develop/tests/domain/model/test_gemrequirement.py +copyright: Copyright (c) Center for Information Technology http://coi.gov.pl +package_url: pkg:pypi/puppeter@0.8.3#tests/domain/model/test_gemrequirement.py +notes: this subset of tests has been modified to tests version comparison and parsing +homepage_url: https://github.com/coi-gov-pl/puppeter +notice_file: test_gem.py.NOTICE diff --git a/tests/test_gem.py.NOTICE b/tests/test_gem.py.NOTICE new file mode 100644 index 00000000..6616bc4d --- /dev/null +++ b/tests/test_gem.py.NOTICE @@ -0,0 +1,13 @@ +# Copyright 2017 Center for Information Technology +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. \ No newline at end of file From e90eac3dbcac8bd6e1d4038dbc1e493e549fc557 Mon Sep 17 00:00:00 2001 From: Philippe Ombredanne Date: Wed, 24 Nov 2021 01:12:13 +0100 Subject: [PATCH 673/707] Clean gem code and tests Signed-off-by: Philippe Ombredanne --- src/univers/gem.py | 76 +++++++++++++++++++++++++++++++--------------- tests/test_gem.py | 22 ++++++-------- 2 files changed, 61 insertions(+), 37 deletions(-) diff --git a/src/univers/gem.py b/src/univers/gem.py index 3fe5c88f..35ddc84f 100644 --- a/src/univers/gem.py +++ b/src/univers/gem.py @@ -1,29 +1,17 @@ -# Copyright 2017 Center for Information Technology +# Copyright (c) Center for Information Technology, http://coi.gov.pl +# SPDX-License-Identifier: Apache-2.0 +# this has been significantly modified from the original # -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import re +# Visit https://aboutcode.org and https://github.com/nexB/univers for support and download. -from six import iterkeys, itervalues -from typing import Type, TypeVar -from typing import Callable, Sequence, MutableSequence +# notes: This has been substantially modified and enhanced from the original +# puppeteer code to extract the Ruby version hanlding code. -T = TypeVar("T") +import re def default(x, e, y): - # type: (Callable[[], T], Type[Exception], T) -> T try: return x() except e: @@ -37,6 +25,9 @@ class GemVersion: ) def __init__(self, version): + + self.original = version + # If version is an empty string convert it to 0 version = 0 if re.compile("^\s*$").match(str(version)) else version @@ -45,7 +36,14 @@ def __init__(self, version): self.__bump = None self.__release = None + def __str__(self): + return self.original + def bump(self): + """ + Return a new GemVersion built from incrementing this GemVersion last + numeric segment. + """ if not self.__bump: segments = self.segments() while any(map(lambda s: isinstance(s, str), segments)): @@ -59,6 +57,9 @@ def bump(self): return self.__bump def release(self): + """ + Return a new GemVersion composed only of release, numeric segments. + """ if not self.__release: segments = self.segments() while any(map(lambda s: isinstance(s, str), segments)): @@ -69,11 +70,16 @@ def release(self): return self.__release def segments(self): - # type: () -> MutableSequence[int|str] + """ + Return a list of version segments. + """ return list(self.__get_segments()) def __cmp__(self, other): - # type: (GemVersion) -> int + """ + Compare the ``other`` GemVersion with this GemVersion according to the + legacy "cmp()" function semantics. Return 0, 1, or -1. + """ if self.__version == other.__version: return 0 lhsegments = self.__get_segments() @@ -113,6 +119,10 @@ def __repr__(self): return "GemVersion({segments})".format(segments=self.segments()) def __get_segments(self): + """ + Return a sequence of ints and strings segments parsed from the original + version string. + """ # type: () -> Sequence[int|str] if not self.__segments: rex = re.compile("[0-9]+|[a-z]+", re.IGNORECASE) @@ -124,6 +134,9 @@ def __get_segments(self): class GemRequirement: + """ + A gem requirement using the Gem notation. + """ OPS = { "=": lambda v, r: v == r, "!=": lambda v, r: v != r, @@ -135,7 +148,7 @@ class GemRequirement: } PATTERN_RAW = "\\s*({quoted})?\\s*({VERSION_PATTERN})\\s*".format( - quoted="|".join(tuple(map(lambda k: re.escape(k), iterkeys(OPS)))), + quoted="|".join(tuple(map(lambda k: re.escape(k), iter(OPS)))), VERSION_PATTERN=GemVersion.VERSION_PATTERN, ) @@ -159,6 +172,10 @@ def __init__(self, *requirements): @classmethod def parse(cls, requirement): + """ + Return a tuple of (operator string, GemVersion object) parsed from a + ``requirements`` string. + """ if isinstance(requirement, GemVersion): return tuple(["=", requirement]) @@ -175,22 +192,33 @@ def parse(cls, requirement): return tuple([op, GemVersion(match.group(2))]) def satified_by(self, version): + """ + Return True if the ``version`` GemVersion or string satisfied this + requirement. + """ gemver = version if isinstance(version, GemVersion) else GemVersion(version) operation = self.__test_rv(gemver) return all(map(operation, self.__requirements)) @classmethod def __test_rv(cls, version): + """ + Return a callable function that can check if a ``version`` satisfies the + operation of a single (op, version) requirement. + """ # type: (GemVersion) -> Callable[[str, GemVersion], bool] def __testing(req): op, rv = req - callable = cls.__get_operation(op) - return callable(version, rv) + callble = cls.__get_operation(op) + return callble(version, rv) return __testing @classmethod def __get_operation(cls, op): + """ + Return a callable operator given an ``op`` operator string. + """ # type: (str) -> Callable[[GemVersion, GemVersion], bool] try: return cls.OPS[op] diff --git a/tests/test_gem.py b/tests/test_gem.py index 8d2aaafc..e2ff06fc 100644 --- a/tests/test_gem.py +++ b/tests/test_gem.py @@ -1,19 +1,15 @@ -# Copyright 2017 Center for Information Technology +# Copyright (c) Center for Information Technology, http://coi.gov.pl +# SPDX-License-Identifier: Apache-2.0 +# this has been significantly modified from the original # -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. +# Visit https://aboutcode.org and https://github.com/nexB/univers for support and download. + +# notes: This has been substantially modified and enhanced from the original +# puppeteer code to extract the Ruby version hanlding code. import pytest -from puppeter.domain.model.gemrequirement import GemVersion, GemRequirement +from univers.gem import GemVersion +from univers.gem import GemRequirement def test_gem_version_release(): From c5449d959e55c50fdac016fd60437df80a107bbc Mon Sep 17 00:00:00 2001 From: Philippe Ombredanne Date: Wed, 24 Nov 2021 01:14:56 +0100 Subject: [PATCH 674/707] Add genm details to README.rst Signed-off-by: Philippe Ombredanne --- README.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.rst b/README.rst index c9d968c4..972f3e47 100644 --- a/README.rst +++ b/README.rst @@ -85,6 +85,8 @@ include: different operators and slightly different semantics: for instance it uses "~>" as a pessimistic operator and supports exclusion with != and does not support "OR" between constraints (that it call requirements). + Gem are handled by Python port of the Rubygems requirements and version + handling code from the `puppeteer tool `_ - debian: handled by the `debian-inspector `_ library. From 8cd3b27cd09ff9779959a4f70c464c717e80856b Mon Sep 17 00:00:00 2001 From: Philippe Ombredanne Date: Wed, 24 Nov 2021 13:41:15 +0100 Subject: [PATCH 675/707] Format code Signed-off-by: Philippe Ombredanne --- src/univers/gem.py | 3 ++- tests/test_gem.py | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/univers/gem.py b/src/univers/gem.py index 35ddc84f..5264222f 100644 --- a/src/univers/gem.py +++ b/src/univers/gem.py @@ -4,7 +4,7 @@ # # Visit https://aboutcode.org and https://github.com/nexB/univers for support and download. -# notes: This has been substantially modified and enhanced from the original +# notes: This has been substantially modified and enhanced from the original # puppeteer code to extract the Ruby version hanlding code. @@ -137,6 +137,7 @@ class GemRequirement: """ A gem requirement using the Gem notation. """ + OPS = { "=": lambda v, r: v == r, "!=": lambda v, r: v != r, diff --git a/tests/test_gem.py b/tests/test_gem.py index e2ff06fc..61256463 100644 --- a/tests/test_gem.py +++ b/tests/test_gem.py @@ -4,7 +4,7 @@ # # Visit https://aboutcode.org and https://github.com/nexB/univers for support and download. -# notes: This has been substantially modified and enhanced from the original +# notes: This has been substantially modified and enhanced from the original # puppeteer code to extract the Ruby version hanlding code. import pytest From c62c05c45383e1d82e20ff9662a651ea4ce2da02 Mon Sep 17 00:00:00 2001 From: Philippe Ombredanne Date: Sun, 5 Dec 2021 18:49:01 +0100 Subject: [PATCH 676/707] Move files to univers directories Signed-off-by: Philippe Ombredanne --- antlir/rpm/allowed_versions/envra.py | 132 ------- .../rpm/allowed_versions/tests/test_envra.py | 170 -------- antlir/rpm/replay/subvol_rpm_compare.py | 366 ------------------ .../replay/tests/test_subvol_rpm_compare.py | 119 ------ {antlir/rpm => src/univers}/rpm_metadata.py | 0 .../rpm/tests => tests}/test_rpm_metadata.py | 0 6 files changed, 787 deletions(-) delete mode 100644 antlir/rpm/allowed_versions/envra.py delete mode 100644 antlir/rpm/allowed_versions/tests/test_envra.py delete mode 100644 antlir/rpm/replay/subvol_rpm_compare.py delete mode 100644 antlir/rpm/replay/tests/test_subvol_rpm_compare.py rename {antlir/rpm => src/univers}/rpm_metadata.py (100%) rename {antlir/rpm/tests => tests}/test_rpm_metadata.py (100%) diff --git a/antlir/rpm/allowed_versions/envra.py b/antlir/rpm/allowed_versions/envra.py deleted file mode 100644 index 6ba1be7a..00000000 --- a/antlir/rpm/allowed_versions/envra.py +++ /dev/null @@ -1,132 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. -# -# This source code is licensed under the MIT license found in the -# LICENSE file in the root directory of this source tree. - -from functools import total_ordering -from typing import NamedTuple, Optional - -from antlir.rpm.rpm_metadata import RpmMetadata, compare_rpm_versions - - -@total_ordering -class SortableENVRA(NamedTuple): - """ - Epoch and name can be `None` to represent wildcards (details below). - - The intended application of the sort is for diff-stable serialization of - ENVRA IDs, so it does NOT do what you expect. Namely, it will sort: - - packages with different names or architectures, - - sort unknown (`None`) `.epoch` and `.name` values, so long as we're - not comparing `None` with non-`None`. - - If you want plain `rpm`-compatible comparison of versions, just call - `compare_rpm_versions(a.as_rpm_metadata(), b.as_rpm_metadata())`. - """ - - # Unlike RPM convention, None means "wildcard", it does not mean 0. A - # wildcard must be resolved to a concrete epoch by looking it up in an - # RPM DB. - epoch: Optional[int] - # Set this to `None` to make an EVRA that can be applied to multiple - # packages in a package group. - name: Optional[str] - version: str - release: str - arch: str - - # Use `as_rpm_metadata` for public consumption. The private version - # here allows comparing wildcard epochs because we only use it after - # checking that we're not comparing `None` with non-`None`. - def _as_rpm_metadata(self) -> RpmMetadata: - return RpmMetadata( - # Not used for sorting here, `compare_rpm_versions` refuses to - # compare different names. As a side-effect, `None` vs non-`None` - # comparisons are also prohibited. - # - # pyre-fixme[6]: Expected `str` for 1st param but got - # `Optional[str]`. - name=self.name, - # We check this is not `None` in `as_rpm_metadata`, and check - # for heterogeneous comparisons in `_compare`. - # pyre-fixme[6]: Expected `int` for 2nd param but got `Optional[int]`. - epoch=self.epoch, - version=self.version, - release=self.release, - ) - - # Enables comparison of versions via `compare_rpm_versions`. - def as_rpm_metadata(self) -> RpmMetadata: - # Allowing a `None` vs non-`None` comparison would be wrong. - # - # Future: move the check for these comparisons out of this class - # and into `compare_rpm_versions`. - if self.epoch is None or self.arch is None: - raise TypeError( - "Cannot use `as_rpm_metadata()` with wildcard epoch or arch: " - f"{self}" - ) - return self._as_rpm_metadata() - - def _compare(self, other: "SortableENVRA") -> int: - # It makes no sense to compare wildcard with non-wildcard because it - # amounts to comparing different data types. All elements of a - # `SortableENVRA` collections should have wildcards in this field, - # or the field should be concrete throughout. - if (self.name is None) ^ (other.name is None): - raise TypeError( - f"Cannot compare concrete name with wildcard: {self} {other}" - ) - if (self.arch is None) ^ (other.arch is None): - raise TypeError( - f"Cannot compare concrete arch with wildcard: {self} {other}" - ) - - # Sort lexicographically by name, then architecture - self_key = (self.name, self.arch) - other_key = (other.name, other.arch) - - if self_key > other_key: - return 1 - elif self_key == other_key: - # Same rationale as for the `.name` test above. - if (self.epoch is None) ^ (other.epoch is None): - raise TypeError( - f"Cannot compare int epoch with wildcard: {self} {other}" - ) - return compare_rpm_versions( - self._as_rpm_metadata(), other._as_rpm_metadata() - ) - elif self_key < other_key: - return -1 - - raise AssertionError(f"Bad name/arch keys: {self_key} {other_key}") - - def __eq__(self, other: "SortableENVRA") -> bool: - return self._compare(other) == 0 - - # pyre-fixme[14]: `__lt__` overrides method defined in `tuple` - # inconsistently. - def __lt__(self, other: "SortableENVRA") -> bool: - return self._compare(other) < 0 - - def to_versionlock_line(self) -> str: - if self.epoch is None or self.name is None or self.arch is None: - raise ValueError( - f"Versionlock needs concrete name & epoch & arch: {self}" - ) - # Our `yum_dnf_versionlock.py` expects TAB-separated ENVRAs. - return "\t".join( - [str(self.epoch), self.name, self.version, self.release, self.arch] - ) - - def __repr__(self) -> str: - epoch = "*" if self.epoch is None else self.epoch - name = "*" if self.name is None else self.name - arch = "*" if self.arch is None else self.arch - return f"{epoch}:{name}-{self.version}-{self.release}-{arch}" - - -# As a type-hint, this alias represents the fact that the `name` must be -# `None`. Future: should this be a proper, separate type? -SortableEVRA = SortableENVRA diff --git a/antlir/rpm/allowed_versions/tests/test_envra.py b/antlir/rpm/allowed_versions/tests/test_envra.py deleted file mode 100644 index cf9a6378..00000000 --- a/antlir/rpm/allowed_versions/tests/test_envra.py +++ /dev/null @@ -1,170 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. -# -# This source code is licensed under the MIT license found in the -# LICENSE file in the root directory of this source tree. - -from functools import total_ordering -from unittest import TestCase - -from antlir.rpm.rpm_metadata import RpmMetadata - -from ..envra import SortableEVRA, SortableENVRA - - -class EnvraTestCase(TestCase): - def test_evra_is_envra(self): - self.assertIs(SortableEVRA, SortableENVRA) - - def test_eq(self): - e = SortableENVRA(epoch=0, name="n", version="v", release="r", arch="a") - self.assertEqual(e, e) - - def test_lt(self): - e0 = SortableENVRA( - epoch=0, name="n", version="v", release="r", arch="a" - ) - e1 = SortableENVRA( - epoch=1, name="n", version="v", release="r", arch="a" - ) - self.assertTrue(e0 < e1) - - def test_repr(self): - e = SortableENVRA(epoch=0, name="n", version="v", release="r", arch="a") - self.assertEqual(str(e), "0:n-v-r-a") - epoch_none = SortableENVRA( - epoch=None, name="n", version="v", release="r", arch="a" - ) - self.assertEqual(str(epoch_none), "*:n-v-r-a") - name_none = SortableENVRA( - epoch=0, name=None, version="v", release="r", arch="a" - ) - self.assertEqual(str(name_none), "0:*-v-r-a") - arch_none = SortableENVRA( - epoch=0, name="n", version="v", release="r", arch=None - ) - self.assertEqual(str(arch_none), "0:n-v-r-*") - - def test_to_versionlock_line_raise(self): - epoch_none = SortableENVRA( - epoch=None, name="n", version="v", release="r", arch="a" - ) - with self.assertRaises(ValueError): - epoch_none.to_versionlock_line() - name_none = SortableENVRA( - epoch=0, name=None, version="v", release="r", arch="a" - ) - with self.assertRaises(ValueError): - name_none.to_versionlock_line() - arch_none = SortableENVRA( - epoch=0, name="n", version="v", release="r", arch=None - ) - with self.assertRaises(ValueError): - arch_none.to_versionlock_line() - - def test_to_versionlock_line_returns(self): - e = SortableENVRA(epoch=0, name="n", version="v", release="r", arch="a") - self.assertEqual(e.to_versionlock_line(), "0\tn\tv\tr\ta") - - def test_compare_returns_negative(self): - e0 = SortableENVRA( - epoch=0, name="m", version="v", release="r", arch="a" - ) - e1 = SortableENVRA( - epoch=0, name="n", version="v", release="r", arch="a" - ) - self.assertTrue(e0 < e1) - - def test_compare_raise(self): - @total_ordering - class Crazy: - def __eq__(self, other): - return False - - def __lt__(self, other): - return False - - def __gt__(self, other): - return False - - e0 = SortableENVRA( - epoch=0, name=Crazy(), version="v", release="r", arch="a" - ) - e1 = SortableENVRA( - epoch=0, name=Crazy(), version="v", release="r", arch="a" - ) - with self.assertRaises(AssertionError): - self.assertTrue(e0 < e1) - - def test_compare_both_epochs_wildcard(self): - e = SortableENVRA( - epoch=None, name="n", version="v", release="r", arch="a" - ) - self.assertEqual(e, e) - - def test_compare_one_epoch_wildcard(self): - e0 = SortableENVRA( - epoch=None, name="n", version="v", release="r", arch="a" - ) - e1 = SortableENVRA( - epoch=0, name="n", version="v", release="r", arch="a" - ) - with self.assertRaises(TypeError): - self.assertEqual(e0, e1) - - def test_compare_both_archs_wildcard(self): - e = SortableENVRA( - epoch=0, name="n", version="v", release="r", arch=None - ) - self.assertEqual(e, e) - - def test_compare_one_arch_wildcard(self): - e0 = SortableENVRA( - epoch=0, name="n", version="v", release="r", arch=None - ) - e1 = SortableENVRA( - epoch=0, name="n", version="v", release="r", arch="a" - ) - with self.assertRaises(TypeError): - self.assertEqual(e0, e1) - - def test_compare_self_greater_than_other(self): - e0 = SortableENVRA( - epoch=0, name="n", version="v", release="r", arch="a" - ) - e1 = SortableENVRA( - epoch=0, name="m", version="v", release="r", arch="a" - ) - self.assertFalse(e0 < e1) - - def test_compare_both_names_wildcard(self): - e = SortableENVRA( - epoch=0, name=None, version="v", release="r", arch="a" - ) - self.assertEqual(e, e) - - def test_compare_one_name_wildcard(self): - e0 = SortableENVRA( - epoch=0, name=None, version="v", release="r", arch="a" - ) - e1 = SortableENVRA( - epoch=0, name="n", version="v", release="r", arch="a" - ) - with self.assertRaises(TypeError): - self.assertEqual(e0, e1) - - def test_as_rpm_metadata_returns(self): - e = SortableENVRA(epoch=0, name="n", version="v", release="r", arch="a") - rpm_metadata = RpmMetadata(name="n", epoch=0, version="v", release="r") - self.assertEqual(e.as_rpm_metadata(), rpm_metadata) - - def test_as_rpm_metadata_raise(self): - epoch_none = SortableENVRA( - epoch=None, name="n", version="v", release="r", arch="a" - ) - with self.assertRaises(TypeError): - epoch_none.as_rpm_metadata() - arch_none = SortableENVRA( - epoch=0, name="n", version="v", release="r", arch=None - ) - with self.assertRaises(TypeError): - arch_none.as_rpm_metadata() diff --git a/antlir/rpm/replay/subvol_rpm_compare.py b/antlir/rpm/replay/subvol_rpm_compare.py deleted file mode 100644 index 37338a23..00000000 --- a/antlir/rpm/replay/subvol_rpm_compare.py +++ /dev/null @@ -1,366 +0,0 @@ -#!/usr/bin/env python3 -# Copyright (c) Facebook, Inc. and its affiliates. -# -# This source code is licensed under the MIT license found in the -# LICENSE file in the root directory of this source tree. - -""" See `subvol_rpm_compare` for the entry point. """ - -import pwd -import re -import shlex -import subprocess -from contextlib import contextmanager -from typing import Iterator, List, NamedTuple, Optional, Set, Tuple - -from antlir.common import get_logger -from antlir.fs_utils import Path -from antlir.nspawn_in_subvol.args import ( - NspawnPluginArgs, - PopenArgs, - new_nspawn_opts, -) -from antlir.nspawn_in_subvol.nspawn import run_nspawn -from antlir.nspawn_in_subvol.plugins.rpm import rpm_nspawn_plugins -from antlir.rpm.yum_dnf_conf import YumDnf -from antlir.subvol_utils import Subvol, TempSubvolumes - -from .fake_pty_wrapper import fake_pty_cmd, fake_pty_resource - -log = get_logger() - - -class SubvolsToCompare(NamedTuple): - root: Subvol - leaf: Subvol - ba: Subvol - rpm_installer: YumDnf - rpm_repo_snapshot: Path # under `ba` - - -class NEVRA(NamedTuple): - name: str - epoch: str # it's really an int, but we never convert from string - version: str - release: str - arch: str - - def download_path(self): - "Path under `rpm_download_subvol`" - return f"{self.name}-{self.version}-{self.release}.{self.arch}.rpm" - - -class RpmDiff(NamedTuple): - added_in_order: List[NEVRA] - removed: Set[NEVRA] - - -def _gen_nevras_in_subvol(ba_subvol: Subvol, subvol: Subvol) -> Iterator[NEVRA]: - delim = "<:>" - # This won't tell us the exact install order within a transaction - # because `rpm` does not record it in the DB (see `dbAdd` in `psm.c`). - # And installtid + installtime don't have enough granularity. For this - # reason, we have to do some extra work elsewhere to get the install - # order out of `dnf`'s output. - # - # This currently doesn't group by `installtid` because TW agent will - # just lump all RPMs into a single `rpm` command-line. This avoids - # needing to tell it the transaction boundaries. If we later needed - # this, we'd just need to grab `installtid` here, and pass it to - # the agent. Context: https://fburl.com/xqok460n - opts = new_nspawn_opts( - # We don't want to nspawn into `subvol` directly since it might have - # mounts specified in `/.meta`, and it would be a pain to wire those - # up to be `.bzl` dependencies to make that work. An alternative - # would be to add a `skip_meta_mounts` option to `nspawn_in_subvol`, - # but this ugliness here is more local. - bindmount_ro=[(subvol.path(), "/i")], - cmd=[ - "rpm", - "--root=/i", - "--query", - "--all", - "--queryformat", - delim.join( - ("%{" + key + "}") - for key in ["name", "epochnum", "version", "release", "arch"] - ) - + "\n", - ], - layer=ba_subvol, - ) - rpm_cp, _ = run_nspawn(opts, PopenArgs(stdout=subprocess.PIPE)) - for nevra_str in rpm_cp.stdout.decode().split(): - n, e, v, r, a = nevra_str.split(delim) - yield NEVRA(n, e, v, r, a) - - -def _gen_nevras_from_installer_output( - rpm_installer: YumDnf, - stdout: bytes, - requested_nevras: Set[NEVRA], -) -> Iterator[NEVRA]: - # `yum` and `dnf` differ in how they format the "progress" part - installing_re = re.compile( - r"^ +(Upgrading|Updating|Installing) +: +([^ ]+) " - ) - nvra_re = re.compile(r"^([a-zA-Z0-9._+-]+)-([^-]+)-([^-]+)\.([^.]+)$") - nevra_re = re.compile( - r"^([a-zA-Z0-9._+-]+)-([0-9]+):([^-]+)-([^-]+)\.([^.]+)$" - ) - envra_re = re.compile( - r"^([0-9]+):([a-zA-Z0-9._+-]+)-([^-]+)-([^-]+)\.([^.]+)$" - ) - - just_yielded = None - installed_nevras = set() - for line in re.split("[\n\r]", stdout.decode()): - m = installing_re.match(line) - if not m: - continue - - pkg_spec = m.group(2) - if ":" not in pkg_spec: # Both `yum` and `dnf` omit epoch if 0 - m = nvra_re.match(pkg_spec) - assert m, f"Could not parse {rpm_installer} output: {line}" - nevra = NEVRA(m.group(1), "0", m.group(2), m.group(3), m.group(4)) - elif rpm_installer == YumDnf.dnf: # NEVRA - m = nevra_re.match(pkg_spec) - assert m, f"Could not parse {rpm_installer} output: {line}" - nevra = NEVRA(*m.groups()) - elif rpm_installer == YumDnf.yum: # ENVRA - m = envra_re.match(pkg_spec) - assert m, f"Could not parse {rpm_installer} output: {line}" - nevra = NEVRA( - m.group(2), m.group(1), m.group(3), m.group(4), m.group(5) - ) - else: # pragma: no cover - raise NotImplementedError(rpm_installer) - - # The installer can print multiple "Installing" lines per NEVRA - if nevra == just_yielded: - continue - just_yielded = nevra - - assert nevra not in installed_nevras, f"{nevra} was installed twice" - installed_nevras.add(nevra) - - assert nevra in requested_nevras, ( - f"Tried to install {nevra}, which was not added between " - f"the root subvol, and the final subvol: {requested_nevras}" - ) - - yield nevra - - # An assert above already checked that installed_nevras < requested_nevras. - assert ( - installed_nevras == requested_nevras - ), f"{requested_nevras - installed_nevras} were never installed" - - -def _cmd_to_quoted_bash(cmd): - return " ".join( - c.shell_quote() if isinstance(c, Path) else shlex.quote(c) for c in cmd - ) - - -def _gen_yum_dnf_install_order( - *, - fake_pty: Path, - subvols: SubvolsToCompare, # this won't use `leaf` or `root` - install_subvol: Subvol, - added_nevras: Set[NEVRA], - rpm_download_subvol: Subvol, -) -> Iterator[NEVRA]: - """ - Sort `added_nevras` in the order that `subvols.rpm_installer` from - `subvols.ba` would install them into `install_subvol`. - - Since there's no "plumbing" API to capture the correct install order - from `yum` or `dnf`, we determine this order by parsing the installer's - stdout. We need `fake_pty` because `dnf` truncates "Installing : " - lines to 80 characters when the output is not going to a TTY. - - NB: We could optionalize `justdb` and check whether the resulting - `install_subvol` is "effectively identical" to the original child - subvolume. However, this is not a very useful idea since in production - we use `rpm` to install the downloaded & sorted RPMs. - - TODO: Play with increasing the download parallelism? On the `dnf` side, - `max_parallel_downloads`, and can add more repo servers in the BA. - """ - prog_name = subvols.rpm_installer.value - # Future(per @malmond): Provide a custom `yum/dnf.conf` to avoid the - # fact that `--setopt` is known to be buggy. - common_cmd_prefix = [ - *fake_pty_cmd(subvols.ba.path(), "/fake_pty.py"), - subvols.rpm_repo_snapshot / prog_name / "bin" / prog_name, - "install", - "--installroot=/i", - "--assumeyes", - # Do not install weak deps since we want to order **precisely** - # the packages that actually got installed between the "root" - # and "destination" subvol -- and that installation could easily - # have avoided installing some of the weak dependencies. - "--setopt=install_weak_deps=False", - ] - # Unfortunately, `dnf install --setopt=tsflags=justdb` downloads the - # *.rpm files even if it will not need them. So, we have to pay the - # RPM download cost, whether or not we want to use a particular file - # as part of packaging this layer. - # - # This explicit download step makes sure that the RPM files are fetched - # to a location we control, making them available "almost for free". - # This is slightly more expensive than a single `dnf install` call, - # since we pay startup & depsolving twice (~1 sec). - # - # If we didn't do this two-step dance, and just used `keepcache`, - # we would be at the mercy of the yum / dnf cache layout, which is - # both messier, and likely more fragile. - download_cmd = common_cmd_prefix + [ - "--downloadonly", - "--downloaddir=/d", - *( - f"{r.name}-{r.epoch}:{r.version}-{r.release}.{r.arch}" - for r in added_nevras - ), - ] - install_cmd = common_cmd_prefix + [ - # Avoid the IO of actually unpacking the RPMs - "--setopt=tsflags=justdb", - # `dnf` (but not `yum`) has a horrendous bug, wherein doing this - # here sequence of "install --downloadonly" and "install - # /downloaddir/*.rpm", with the SAME `--installroot`, will result in - # all the content of `/downloaddir` being deleted. This avoids it. - "--setopt=keepcache=True", - # NB: The last word should NOT be quoted, and is therefore added below. - ] - opts = new_nspawn_opts( - bindmount_ro=[(fake_pty, "/fake_pty.py")], - bindmount_rw=[ - (install_subvol.path(), "/i"), - (rpm_download_subvol.path(), "/d"), - ], - user=pwd.getpwnam("root"), - cmd=[ - "/bin/bash", - "-uec", - f""" -set -o pipefail -{_cmd_to_quoted_bash(download_cmd)} -{_cmd_to_quoted_bash(install_cmd)} /d/*.rpm -""", - ], - layer=subvols.ba, - ) - res, _ = run_nspawn( - opts, - PopenArgs(stdout=subprocess.PIPE), - plugins=rpm_nspawn_plugins( - opts=opts, - plugin_args=NspawnPluginArgs( - serve_rpm_snapshots=[subvols.rpm_repo_snapshot], - shadow_proxied_binaries=False, # Just serve the 1 snapshot - ), - ), - ) - yield from _gen_nevras_from_installer_output( - subvols.rpm_installer, - res.stdout, - added_nevras, - ) - - -def subvol_rpm_compare( - *, - subvols: SubvolsToCompare, - # If you want the downloaded RPMs, use `subvol_rpm_compare_and_download()`. - # - # If this subvol is set, populate it with the downloaded RPMs corresponding - # to `RpmDiff.added_nevras` -- each file named `NEVRA.download_path`. - rpm_download_subvol: Optional[Subvol] = None, -) -> RpmDiff: - """ - Finds what RPMs were added / removed between `.root` and `.leaf`. - - Then, use `.ba` to determine that precise installation order that would - be used by `.rpm_installer` to install the added NEVRAs from - `.rpm_repo_snapshot`. - - It **should** true that `RpmDiff.added_in_order` can be `rpm --install`ed - into `.root` in order to reproduce `.leaf`. - - IMPORTANT: this function exercises `yum` / `dnf` in a way that is - necessarily somewhat different from how `subvols.leaf` was actually - constructed. Therefore, it is important to verify that installing - `RpmDiff.added_in_order` in `subvols.root` will produce the same output. - Therefore, typical usage of this function should be followed by using - the `rpm_diff` module, e.g. `replay_rpms_and_compiler_items` followed - by `subvol_diff`. - - Future: Eventually, `RpmActionItem` ought to become self-aware enough to - record precisely which RPMs installed, in which order -- and perhaps we - can even switch its actual install method to `rpm -i` for full - consistency with prod. At that point, this function should be able to - use that authoritative changelog instead, only falling back to the - current "best effort" method when a `genrule_layer` installs RPMs by - other means. - """ - root_nevras = set(_gen_nevras_in_subvol(subvols.ba, subvols.root)) - my_nevras = set(_gen_nevras_in_subvol(subvols.ba, subvols.leaf)) - removed_nevras = root_nevras - my_nevras - added_nevras = my_nevras - root_nevras - # The "sort & download" step is fairly expensive (~25s) even when - # there are no RPMs to sort. Instead of debugging why this is, - # just short-circuit it. - if not added_nevras: - return RpmDiff(removed=removed_nevras, added_in_order=[]) - - # Shell out to `yum` or `dnf` in the BA to find the correct install - # order for the new RPMs. Per the comment on P410145489, this matters. - # - # `fake_pty` is a separate binary because handling PTY signals in the - # same process would be insanity, and I don't want to risk `fork()` in a - # process that's liable to have random FB infra threads. - with fake_pty_resource() as fake_pty, TempSubvolumes() as tmp_subvols: - if not rpm_download_subvol: - rpm_download_subvol = tmp_subvols.create("rpm_compare_download") - added_in_order = list( - _gen_yum_dnf_install_order( - fake_pty=fake_pty, - subvols=subvols, - install_subvol=tmp_subvols.snapshot( - subvols.root, "subvol_rpm_compare" - ), - added_nevras=added_nevras, - rpm_download_subvol=rpm_download_subvol, - ), - ) - # Check that the set of downloaded RPMs is exactly what we requested - actual_downloaded = { - f"{p}" for p in rpm_download_subvol.path().listdir() - } - expected_downloaded = {r.download_path() for r in added_in_order} - assert expected_downloaded == actual_downloaded, ( - expected_downloaded, - actual_downloaded, - ) - return RpmDiff(removed=removed_nevras, added_in_order=added_in_order) - - -@contextmanager -def subvol_rpm_compare_and_download( - subvols: SubvolsToCompare, -) -> Iterator[Tuple[RpmDiff, Subvol]]: - """ - Runs `subvol_rpm_compare` and yields the resulting `RpmDiff` together - with a temporary subvolume that contains all the added RPM files, - accessible via `NEVRA.download_path()`. - """ - with TempSubvolumes() as tmp_subvols: - rpm_download_subvol = tmp_subvols.create("subvol_rpm_compare_download") - rd = subvol_rpm_compare( - subvols=subvols, - rpm_download_subvol=rpm_download_subvol, - ) - yield rd, rpm_download_subvol diff --git a/antlir/rpm/replay/tests/test_subvol_rpm_compare.py b/antlir/rpm/replay/tests/test_subvol_rpm_compare.py deleted file mode 100644 index d04c39e3..00000000 --- a/antlir/rpm/replay/tests/test_subvol_rpm_compare.py +++ /dev/null @@ -1,119 +0,0 @@ -# Copyright (c) Facebook, Inc. and its affiliates. -# -# This source code is licensed under the MIT license found in the -# LICENSE file in the root directory of this source tree. - -import unittest - -from antlir.config import antlir_dep -from antlir.rpm.find_snapshot import snapshot_install_dir -from antlir.rpm.yum_dnf_conf import YumDnf -from antlir.subvol_utils import Subvol -from antlir.tests.layer_resource import layer_resource_subvol - -from ..subvol_rpm_compare import ( - subvol_rpm_compare, - SubvolsToCompare, - subvol_rpm_compare_and_download, - NEVRA, -) - - -class SubvolRpmCompareTestImpl: - def construct_subvols_to_compare( - self, root: Subvol = None, leaf: Subvol = None, ba: Subvol = None - ) -> SubvolsToCompare: - root = root or layer_resource_subvol(__package__, "root_subvol") - leaf = leaf or layer_resource_subvol(__package__, "leaf_subvol") - ba = ba or layer_resource_subvol(__package__, "ba_subvol") - - return SubvolsToCompare( - ba=ba, - root=root, - leaf=leaf, - rpm_installer=self._YUM_DNF, - rpm_repo_snapshot=snapshot_install_dir( - antlir_dep("rpm:rpm-replay-repo-snapshot-for-tests") - ), - ) - - def test_subvol_rpm_compare_identical_subvols(self): - root_subvol = layer_resource_subvol(__package__, "root_subvol") - - subvols = self.construct_subvols_to_compare( - root=root_subvol, leaf=root_subvol - ) - rd = subvol_rpm_compare(subvols=subvols) - - # if root == leaf then no rpms should added/removed - self.assertEqual(len(rd.added_in_order), 0) - self.assertEqual(len(rd.removed), 0) - - def test_subvol_rpm_compare_added_order(self): - subvols = self.construct_subvols_to_compare() - rd = subvol_rpm_compare(subvols=subvols) - rpms_added_names = [nevra.name for nevra in rd.added_in_order] - rpms_with_deps = [ - "rpm-test-first", - "rpm-test-second", - "rpm-test-third", - "rpm-test-fourth", - "rpm-test-fifth", - ] - self.assertIn( - rpms_added_names, - [ - # Since `has-epoch` and `mice` has no deps or dependents, - # it could go in any order - [*rpms_with_deps, "rpm-test-mice", "rpm-test-has-epoch"], - [*rpms_with_deps, "rpm-test-has-epoch", "rpm-test-mice"], - ["rpm-test-mice", "rpm-test-has-epoch", *rpms_with_deps], - ["rpm-test-has-epoch", "rpm-test-mice", *rpms_with_deps], - ["rpm-test-has-epoch", *rpms_with_deps, "rpm-test-mice"], - ["rpm-test-mice", *rpms_with_deps, "rpm-test-has-epoch"], - ], - ) - - # mice should be upgraded to 0.2 version - self.assertIn( - NEVRA("rpm-test-mice", "0", "0.2", "a", "x86_64"), rd.added_in_order - ) - - self.assertEqual( - { - # mice upgrade causes 0.1 version to be removed - NEVRA("rpm-test-mice", "0", "0.1", "a", "x86_64"), - NEVRA("rpm-test-milk", "0", "2.71", "8", "x86_64"), - }, - rd.removed, - ) - - def test_subvol_rpm_compare_and_download(self): - subvols = self.construct_subvols_to_compare() - with subvol_rpm_compare_and_download(subvols) as ( - rpm_diff, - rpm_download_subvol, - ): - downloaded_rpms = { - f"{rpm}" for rpm in rpm_download_subvol.path().listdir() - } - self.assertEqual( - { - "rpm-test-has-epoch-0-0.x86_64.rpm", - "rpm-test-first-0-0.x86_64.rpm", - "rpm-test-second-0-0.x86_64.rpm", - "rpm-test-third-0-0.x86_64.rpm", - "rpm-test-fourth-0-0.x86_64.rpm", - "rpm-test-fifth-0-0.x86_64.rpm", - "rpm-test-mice-0.2-a.x86_64.rpm", - }, - downloaded_rpms, - ) - - -class YumSubvolRpmCompareTestCase(SubvolRpmCompareTestImpl, unittest.TestCase): - _YUM_DNF = YumDnf.yum - - -class DnfSubvolRpmCompareTestCase(SubvolRpmCompareTestImpl, unittest.TestCase): - _YUM_DNF = YumDnf.dnf diff --git a/antlir/rpm/rpm_metadata.py b/src/univers/rpm_metadata.py similarity index 100% rename from antlir/rpm/rpm_metadata.py rename to src/univers/rpm_metadata.py diff --git a/antlir/rpm/tests/test_rpm_metadata.py b/tests/test_rpm_metadata.py similarity index 100% rename from antlir/rpm/tests/test_rpm_metadata.py rename to tests/test_rpm_metadata.py From 98116dbac933aa0374ff44c8f808003a97c6f31f Mon Sep 17 00:00:00 2001 From: Philippe Ombredanne Date: Sun, 5 Dec 2021 19:11:41 +0100 Subject: [PATCH 677/707] Remove unused code and adjust imports Signed-off-by: Philippe Ombredanne --- src/univers/rpm_metadata.py | 84 +------------------------------- tests/test_rpm_metadata.py | 95 ++----------------------------------- 2 files changed, 4 insertions(+), 175 deletions(-) diff --git a/src/univers/rpm_metadata.py b/src/univers/rpm_metadata.py index 3961f083..dea6b3b5 100644 --- a/src/univers/rpm_metadata.py +++ b/src/univers/rpm_metadata.py @@ -4,19 +4,8 @@ # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. -import os import re -import subprocess -from typing import List, NamedTuple, Optional - -from antlir.common import get_logger -from antlir.fs_utils import generate_work_dir, MehStr, Path -from antlir.nspawn_in_subvol.args import PopenArgs, new_nspawn_opts -from antlir.nspawn_in_subvol.nspawn import run_nspawn -from antlir.subvol_utils import Subvol - - -log = get_logger() +from typing import NamedTuple class RpmMetadata(NamedTuple): @@ -25,77 +14,6 @@ class RpmMetadata(NamedTuple): version: str release: str - @classmethod - def from_subvol( - cls, subvol: Subvol, ba_subvol: Subvol, package_name: str - ) -> "RpmMetadata": - db_path_src = subvol.path("var/lib/rpm") - if not os.path.exists(db_path_src): - # If we didn't check for this, `bindmount_ro` would fail. - raise ValueError(f"RPM DB path {db_path_src} does not exist") - # Rpm query will write to and update rpm database files if it can. - # We must use the BA here because using the host `rpm` can cause the - # image RPM to become unreadable to the `rpm` from the BA. - db_path_dst = generate_work_dir() - return _repo_query( - db_path=db_path_dst, - package_name=package_name, - check_output_fn=lambda cmd: run_nspawn( - new_nspawn_opts( - cmd=cmd, - layer=ba_subvol, - # Read-only so that `rpm` does not modify the DB or - # create one when it does not already exist. - bindmount_ro=[(db_path_src, db_path_dst)], - ), - PopenArgs(stdout=subprocess.PIPE), - )[0].stdout, - ) - - @classmethod - def from_file(cls, package_path: Path) -> "RpmMetadata": - if not package_path.endswith(b".rpm"): - raise ValueError(f"RPM file {package_path} needs to end with .rpm") - return _repo_query( - package_path=package_path, - check_output_fn=subprocess.check_output, - ) - - -def _repo_query( - *, - db_path: Optional[Path] = None, - package_name: Optional[str] = None, - package_path: Optional[Path] = None, - check_output_fn, -) -> "RpmMetadata": - query_args: List[MehStr] = [ - "rpm", - "--query", - "--queryformat", - "'%{NAME}:%{epochnum}:%{VERSION}:%{RELEASE}'", - ] - - if db_path and package_name and (package_path is None): - query_args += ["--dbpath", db_path, package_name] - elif package_path and (db_path is None and package_name is None): - query_args += ["--package", package_path] - else: - raise ValueError( - "Must pass only (--dbpath and --package_name) or --package" - ) - - try: - result = check_output_fn(query_args).decode().strip("'\"") - log.debug(f"RPM query {query_args} returned {result}") - except subprocess.CalledProcessError as e: - raise RuntimeError( - f"Error querying RPM: {query_args}, {e.stdout}, {e.stderr}" - ) - - n, e, v, r = result.split(":") - return RpmMetadata(name=n, epoch=int(e), version=v, release=r) - # This comprises a pure python implementation of rpm version comparison. The # purpose for this is so that the antlir library does not have a dependency diff --git a/tests/test_rpm_metadata.py b/tests/test_rpm_metadata.py index 1c61b272..34088480 100644 --- a/tests/test_rpm_metadata.py +++ b/tests/test_rpm_metadata.py @@ -4,103 +4,14 @@ # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. -import importlib.resources -import os -import re -import shutil import unittest -from antlir.find_built_subvol import find_built_subvol -from antlir.fs_utils import temp_dir -from antlir.tests.layer_resource import layer_resource_subvol - -from ..rpm_metadata import ( - RpmMetadata, - _compare_values, - compare_rpm_versions, - _repo_query, -) -from .temp_repos import Repo, Rpm, get_test_signing_key, temp_repos_steps +from univers.rpm_metadata import RpmMetadata +from univers.rpm_metadata import _compare_values +from univers.rpm_metadata import compare_rpm_versions class RpmMetadataTestCase(unittest.TestCase): - def _load_canonical_tests(self): - STMT = re.compile( - r"(.*)RPMVERCMP\(([^, ]*) *, *([^, ]*) *, *([^\)]*)\).*" - ) - - for line in importlib.resources.open_text( - "antlir.rpm", "version-compare-tests" - ).readlines(): - m = STMT.match(line) - if m: - yield m.group(2), m.group(3), int(m.group(4)) - - def test_rpm_metadata_from_subvol(self): - layer_path = os.path.join(os.path.dirname(__file__), "child-layer") - child_subvol = find_built_subvol(layer_path) - ba_subvol = layer_resource_subvol(__package__, "test-build-appliance") - - a = RpmMetadata.from_subvol(child_subvol, ba_subvol, "rpm-test-mice") - self.assertEqual(a.name, "rpm-test-mice") - self.assertEqual(a.epoch, 0) - self.assertEqual(a.version, "0.1") - self.assertEqual(a.release, "a") - - # not installed - with self.assertRaises(RuntimeError): - a = RpmMetadata.from_subvol( - child_subvol, ba_subvol, "rpm-test-carrot" - ) - - # subvol with no RPM DB - layer_path = os.path.join(os.path.dirname(__file__), "hello-layer") - hello_subvol = find_built_subvol(layer_path) - with self.assertRaisesRegex(ValueError, " does not exist$"): - a = RpmMetadata.from_subvol( - hello_subvol, ba_subvol, "rpm-test-mice" - ) - - def test_rpm_metadata_from_file(self): - with temp_repos_steps( - gpg_signing_key=get_test_signing_key(), - repo_change_steps=[ - { - "repo": Repo( - [Rpm("sheep", "0.3.5.beta", "l33t.deadbeef.777")] - ) - } - ], - ) as repos_root, temp_dir() as td: - src_rpm_path = repos_root / ( - "0/repo/repo-pkgs/" - + "rpm-test-sheep-0.3.5.beta-l33t.deadbeef.777.x86_64.rpm" - ) - dst_rpm_path = td / "arbitrary_unused_name.rpm" - shutil.copy(src_rpm_path, dst_rpm_path) - a = RpmMetadata.from_file(dst_rpm_path) - self.assertEqual(a.name, "rpm-test-sheep") - self.assertEqual(a.epoch, 0) - self.assertEqual(a.version, "0.3.5.beta") - self.assertEqual(a.release, "l33t.deadbeef.777") - - # non-existent file - with self.assertRaisesRegex(RuntimeError, "^Error querying RPM:"): - a = RpmMetadata.from_file(b"idontexist.rpm") - - # missing extension - with self.assertRaisesRegex(ValueError, " needs to end with .rpm$"): - a = RpmMetadata.from_file(b"idontendwithdotrpm") - - def test_rpm_query_arg_check(self): - with self.assertRaisesRegex(ValueError, "^Must pass only "): - _repo_query( - db_path=b"dbpath", - package_name=None, - package_path=b"path", - check_output_fn="unused", - ) - def test_rpm_compare_versions(self): # name mismatch a = RpmMetadata("test-name1", 1, "2", "3") From db28036b5c20b7f2458af567c21e5539085de317 Mon Sep 17 00:00:00 2001 From: Philippe Ombredanne Date: Sun, 5 Dec 2021 19:47:59 +0100 Subject: [PATCH 678/707] Remove comment Signed-off-by: Philippe Ombredanne --- src/univers/rpm_metadata.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/univers/rpm_metadata.py b/src/univers/rpm_metadata.py index dea6b3b5..516df58d 100644 --- a/src/univers/rpm_metadata.py +++ b/src/univers/rpm_metadata.py @@ -70,10 +70,7 @@ def compare_rpm_versions(a: RpmMetadata, b: RpmMetadata) -> int: def _compare_values(left: str, right: str) -> int: # Rpm versions can only be ascii, anything else is just - # ignored - # pyre-fixme[9]: left has type `str`; used as `bytes`. left = left.encode("ascii", "ignore") - # pyre-fixme[9]: right has type `str`; used as `bytes`. right = right.encode("ascii", "ignore") if left == right: From eb5c9b0f31d7c681e20d2070cd2b38351736c8df Mon Sep 17 00:00:00 2001 From: Philippe Ombredanne Date: Sun, 5 Dec 2021 23:11:09 +0100 Subject: [PATCH 679/707] Align code with SAS original. Rename to rpm Add back missing Apache license notice and copyrights Remove extra comments and typing Rename to rpm as named in univers Signed-off-by: Philippe Ombredanne --- src/univers/rpm.py | 181 ++++++++++++++++++++ src/univers/rpm_metadata.py | 175 ------------------- tests/{test_rpm_metadata.py => test_rpm.py} | 14 +- 3 files changed, 188 insertions(+), 182 deletions(-) create mode 100644 src/univers/rpm.py delete mode 100644 src/univers/rpm_metadata.py rename tests/{test_rpm_metadata.py => test_rpm.py} (88%) diff --git a/src/univers/rpm.py b/src/univers/rpm.py new file mode 100644 index 00000000..6877f10b --- /dev/null +++ b/src/univers/rpm.py @@ -0,0 +1,181 @@ +# Copyright (c) Facebook, Inc. and its affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +# +# Copyright (c) SAS Institute Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import re +from typing import NamedTuple + + +class RpmVersion(NamedTuple): + epoch: int + version: str + release: str + + +# This comprises a pure python implementation of rpm version comparison. The +# purpose for this is so that the antlir library does not have a dependency +# on a C library that is (for the most part) only distributed as part of rpm +# based distros. Depending on a C library complicates dependency management +# significantly in the OSS space due to the complexity of handling 3rd party C +# libraries with buck. Having this pure python implementation also eases future +# rpm usage/handling for both non-rpm based distros and different arch types. +# +# This implementation is adapted from both this blog post: +# https://blog.jasonantman.com/2014/07/how-yum-and-rpm-compare-versions/ +# and this Apache 2 licensed implementation: +# https://github.com/sassoftware/python-rpm-vercmp/blob/master/rpm_vercmp/vercmp.py +# +# There are extensive test cases in the `test_rpm_metadata.py` test case that +# cover a wide variety of normal and weird version comparsions. +def compare_rpm_versions(a: RpmVersion, b: RpmVersion) -> int: + """ + Returns: + 1 if the version of a is newer than b + 0 if the versions match + -1 if the version of a is older than b + """ + + # First compare the epoch, if set. If the epoch's are not the same, then + # the higher one wins no matter what the rest of the EVR is. + if a.epoch != b.epoch: + if a.epoch > b.epoch: + return 1 # a > b + else: + return -1 # a < b + + # Epoch is the same, if version + release are the same we have a match + if (a.version == b.version) and (a.release == b.release): + return 0 # a == b + + # Compare version first, if version is equal then compare release + compare_res = vercmp(a.version, b.version) + if compare_res != 0: # a > b || a < b + return compare_res + else: + return vercmp(a.release, b.release) + + +class Vercmp: + R_NONALNUMTILDE_CARET = re.compile(br"^([^a-zA-Z0-9~\^]*)(.*)$") + R_NUM = re.compile(br"^([\d]+)(.*)$") + R_ALPHA = re.compile(br"^([a-zA-Z]+)(.*)$") + + @classmethod + def compare(cls, first, second): + # Rpm versions can only be ascii, anything else is just ignored + first = first.encode("ascii", "ignore") + second = second.encode("ascii", "ignore") + + if first == second: + return 0 + + while first or second: + m1 = cls.R_NONALNUMTILDE_CARET.match(first) + m2 = cls.R_NONALNUMTILDE_CARET.match(second) + m1_head, first = m1.group(1), m1.group(2) + m2_head, second = m2.group(1), m2.group(2) + if m1_head or m2_head: + # Ignore junk at the beginning + continue + + # handle the tilde separator, it sorts before everything else + if first.startswith(b"~"): + if not second.startswith(b"~"): + return -1 + first, second = first[1:], second[1:] + continue + if second.startswith(b"~"): + return 1 + + # Now look at the caret, which is like the tilde but pointier. + if first.startswith(b"^"): + # first has a caret but second has ended + if not second: + return 1 # first > second + + # first has a caret but second continues on + elif not second.startswith(b"^"): + return -1 # first < second + + # strip the ^ and start again + first, second = first[1:], second[1:] + continue + + # Caret means the version is less... Unless the other version + # has ended, then do the exact opposite. + if second.startswith(b"^"): + return -1 if not first else 1 + + # We've run out of characters to compare. + # Note: we have to do this after we compare the ~ and ^ madness + # because ~'s and ^'s take precedance. + # If we ran to the end of either, we are finished with the loop + if not first or not second: + break + + # grab first completely alpha or completely numeric segment + m1 = cls.R_NUM.match(first) + if m1: + m2 = cls.R_NUM.match(second) + if not m2: + # numeric segments are always newer than alpha segments + return 1 + isnum = True + else: + m1 = cls.R_ALPHA.match(first) + m2 = cls.R_ALPHA.match(second) + if not m2: + return -1 + isnum = False + + m1_head, first = m1.group(1), m1.group(2) + m2_head, second = m2.group(1), m2.group(2) + + if isnum: + # throw away any leading zeros - it's a number, right? + m1_head = m1_head.lstrip(b"0") + m2_head = m2_head.lstrip(b"0") + + # whichever number has more digits wins + m1hlen = len(m1_head) + m2hlen = len(m2_head) + if m1hlen < m2hlen: + return -1 + if m1hlen > m2hlen: + return 1 + + # Same number of chars + if m1_head < m2_head: + return -1 + if m1_head > m2_head: + return 1 + # Both segments equal + continue + + m1len = len(first) + m2len = len(second) + if m1len == m2len == 0: + return 0 + if m1len != 0: + return 1 + return -1 + + +def vercmp(first, second): + return Vercmp.compare(first, second) diff --git a/src/univers/rpm_metadata.py b/src/univers/rpm_metadata.py deleted file mode 100644 index 516df58d..00000000 --- a/src/univers/rpm_metadata.py +++ /dev/null @@ -1,175 +0,0 @@ -#!/usr/bin/env python3 -# Copyright (c) Facebook, Inc. and its affiliates. -# -# This source code is licensed under the MIT license found in the -# LICENSE file in the root directory of this source tree. - -import re -from typing import NamedTuple - - -class RpmMetadata(NamedTuple): - name: str - epoch: int - version: str - release: str - - -# This comprises a pure python implementation of rpm version comparison. The -# purpose for this is so that the antlir library does not have a dependency -# on a C library that is (for the most part) only distributed as part of rpm -# based distros. Depending on a C library complicates dependency management -# significantly in the OSS space due to the complexity of handling 3rd party C -# libraries with buck. Having this pure python implementation also eases future -# rpm usage/handling for both non-rpm based distros and different arch types. -# -# This implementation is adapted from both this blog post: -# https://blog.jasonantman.com/2014/07/how-yum-and-rpm-compare-versions/ -# and this Apache 2 licensed implementation: -# https://github.com/sassoftware/python-rpm-vercmp/blob/master/rpm_vercmp/vercmp.py -# -# There are extensive test cases in the `test_rpm_metadata.py` test case that -# cover a wide variety of normal and weird version comparsions. -def compare_rpm_versions(a: RpmMetadata, b: RpmMetadata) -> int: - """ - Returns: - 1 if the version of a is newer than b - 0 if the versions match - -1 if the version of a is older than b - """ - - # This is not a rule, but it makes sense that our libs don't want to - # compare versions of different RPMs - if a.name != b.name: - raise ValueError("Cannot compare RPM versions when names do not match") - - # First compare the epoch, if set. If the epoch's are not the same, then - # the higher one wins no matter what the rest of the EVR is. - if a.epoch != b.epoch: - if a.epoch > b.epoch: - return 1 # a > b - else: - return -1 # a < b - - # Epoch is the same, if version + release are the same we have a match - if (a.version == b.version) and (a.release == b.release): - return 0 # a == b - - # Compare version first, if version is equal then compare release - compare_res = _compare_values(a.version, b.version) - if compare_res != 0: # a > b || a < b - return compare_res - else: - return _compare_values(a.release, b.release) - - -R_NON_ALPHA_NUM_TILDE_CARET = re.compile(br"^([^a-zA-Z0-9~\^]*)(.*)$") -R_NUM = re.compile(br"^([\d]+)(.*)$") -R_ALPHA = re.compile(br"^([a-zA-Z]+)(.*)$") - - -def _compare_values(left: str, right: str) -> int: - # Rpm versions can only be ascii, anything else is just - left = left.encode("ascii", "ignore") - right = right.encode("ascii", "ignore") - - if left == right: - return 0 - - while left or right: - match_left = R_NON_ALPHA_NUM_TILDE_CARET.match(left) - match_right = R_NON_ALPHA_NUM_TILDE_CARET.match(right) - left_head, left = match_left.group(1), match_left.group(2) - right_head, right = match_right.group(1), match_right.group(2) - - # Ignore anything at the start we don't want - if left_head or right_head: - continue - - # Look at tilde first, it takes precedent over everything else - if left.startswith(b"~"): - if not right.startswith(b"~"): - return -1 # left < right - - # Strip the tilde and start again - left, right = left[1:], right[1:] - continue - - # Tilde always means the version is less - if right.startswith(b"~"): - return 1 # left > right - - # Now look at the caret, which is like the tilde but pointier. - if left.startswith(b"^"): - # left has a caret but right has ended - if not right: - return 1 # left > right - - # left has a caret but right continues on - elif not right.startswith(b"^"): - return -1 # left < right - - # strip the ^ and start again - left, right = left[1:], right[1:] - continue - - # Caret means the version is less... Unless the other version - # has ended, then do the exact opposite. - if right.startswith(b"^"): - return -1 if not left else 1 - - # We've run out of characters to compare. - # Note: we have to do this after we compare the ~ and ^ madness - # because ~'s and ^'s take precedance. - if not left or not right: - break - - # Lets see if we've got numbers - match_left = R_NUM.match(left) - if match_left: - match_right = R_NUM.match(right) - if not match_right: # right is not a num and nums > alphas - return 1 # left > right - isnum = True - else: # match is alpha - match_left = R_ALPHA.match(left) - match_right = R_ALPHA.match(right) - if not match_right: # right is not an alpha and nums > alphas - return -1 # left < right - isnum = False - - # strip off the leading numeric or alpha chars - left_head, left = match_left.group(1), match_left.group(2) - right_head, right = match_right.group(1), match_right.group(2) - - if isnum: - left_head = left_head.lstrip(b"0") - right_head = right_head.lstrip(b"0") - - # Length of contiguous numbers matters - left_head_len = len(left_head) - right_head_len = len(right_head) - if left_head_len < right_head_len: - return -1 # left < right - if left_head_len > right_head_len: - return 1 # left > right - - # Either a number with the same number of chars or - # the leading chars are alpha so lets do a standard compare - if left_head < right_head: - return -1 # left < right - if left_head > right_head: - return 1 # left > right - - # Both header segments are of equal length, keep going with the new - continue # pragma: no cover - - # if both are now zero length they must be equal - if len(left) == len(right) == 0: - return 0 # left == right - - # Longer string is > than shorter string - if len(left) != 0: - return 1 # left > right - - return -1 # left < right diff --git a/tests/test_rpm_metadata.py b/tests/test_rpm.py similarity index 88% rename from tests/test_rpm_metadata.py rename to tests/test_rpm.py index 34088480..edc67b58 100644 --- a/tests/test_rpm_metadata.py +++ b/tests/test_rpm.py @@ -6,16 +6,16 @@ import unittest -from univers.rpm_metadata import RpmMetadata -from univers.rpm_metadata import _compare_values -from univers.rpm_metadata import compare_rpm_versions +from univers.rpm import RpmVersion +from univers.rpm import _compare_values +from univers.rpm import compare_rpm_versions class RpmMetadataTestCase(unittest.TestCase): def test_rpm_compare_versions(self): # name mismatch - a = RpmMetadata("test-name1", 1, "2", "3") - b = RpmMetadata("test-name2", 1, "2", "3") + a = RpmVersion("test-name1", 1, "2", "3") + b = RpmVersion("test-name2", 1, "2", "3") with self.assertRaises(ValueError): compare_rpm_versions(a, b) @@ -50,8 +50,8 @@ def test_rpm_compare_versions(self): ] for evr1, evr2, expected in test_evr_data: - a = RpmMetadata("test-name", *evr1) - b = RpmMetadata("test-name", *evr2) + a = RpmVersion("test-name", *evr1) + b = RpmVersion("test-name", *evr2) self.assertEqual( compare_rpm_versions(a, b), expected, From 89eb6840b5859a6983d190aa84a0e9e56bb869c4 Mon Sep 17 00:00:00 2001 From: Philippe Ombredanne Date: Mon, 6 Dec 2021 00:28:58 +0100 Subject: [PATCH 680/707] Add from_evr() function and doctests Also ensure that all tests pass. Signed-off-by: Philippe Ombredanne --- src/univers/rpm.py | 45 +++++++++++++++++++++++++++++++++++++++++++-- tests/test_rpm.py | 20 ++------------------ 2 files changed, 45 insertions(+), 20 deletions(-) diff --git a/src/univers/rpm.py b/src/univers/rpm.py index 6877f10b..d60e83df 100644 --- a/src/univers/rpm.py +++ b/src/univers/rpm.py @@ -20,6 +20,7 @@ import re from typing import NamedTuple +from typing import Union class RpmVersion(NamedTuple): @@ -27,6 +28,36 @@ class RpmVersion(NamedTuple): version: str release: str + @classmethod + def from_string(cls, s): + e, v, r = from_evr(s) + return cls(e, v, r) + + +def from_evr(s): + """ + Return an (E, V, R) tuple given a string by splitting + [e:]version-release into the three possible subcomponents. + Default epoch to 0, version and release to empty string if not specified. + + >>> assert from_evr("1:11.13.2.0-1") == (1, "11.13.2.0", "1") + >>> assert from_evr("11.13.2.0-1") == (0, "11.13.2.0", "1") + """ + if ":" in s: + e, _, vr = s.partition(":") + else: + e = "0" + vr = s + + e = int(e) + + if "-" in vr: + v, _, r = vr.partition("-") + else: + v = vr + r = "" + return e, v, r + # This comprises a pure python implementation of rpm version comparison. The # purpose for this is so that the antlir library does not have a dependency @@ -43,14 +74,24 @@ class RpmVersion(NamedTuple): # # There are extensive test cases in the `test_rpm_metadata.py` test case that # cover a wide variety of normal and weird version comparsions. -def compare_rpm_versions(a: RpmVersion, b: RpmVersion) -> int: + + +def compare_rpm_versions(a: Union[RpmVersion, str], b: Union[RpmVersion, str]) -> int: """ Returns: 1 if the version of a is newer than b 0 if the versions match -1 if the version of a is older than b - """ + >>> assert compare_rpm_versions("1.0", "1.1") == -1 + >>> assert compare_rpm_versions("1.1", "1.0") == 1 + >>> assert compare_rpm_versions("11.13.2-1", "11.13.2.0-1") == -1 + >>> assert compare_rpm_versions("11.13.2.0-1", "11.13.2-1") == 1 + """ + if isinstance(a, str): + a = RpmVersion.from_string(a) + if isinstance(b, str): + b = RpmVersion.from_string(b) # First compare the epoch, if set. If the epoch's are not the same, then # the higher one wins no matter what the rest of the EVR is. if a.epoch != b.epoch: diff --git a/tests/test_rpm.py b/tests/test_rpm.py index edc67b58..5ad4714d 100644 --- a/tests/test_rpm.py +++ b/tests/test_rpm.py @@ -7,18 +7,11 @@ import unittest from univers.rpm import RpmVersion -from univers.rpm import _compare_values from univers.rpm import compare_rpm_versions class RpmMetadataTestCase(unittest.TestCase): def test_rpm_compare_versions(self): - # name mismatch - a = RpmVersion("test-name1", 1, "2", "3") - b = RpmVersion("test-name2", 1, "2", "3") - with self.assertRaises(ValueError): - compare_rpm_versions(a, b) - # Taste data was generated with: # rpmdev-vercmp # which also uses the same Python rpm lib. @@ -50,19 +43,10 @@ def test_rpm_compare_versions(self): ] for evr1, evr2, expected in test_evr_data: - a = RpmVersion("test-name", *evr1) - b = RpmVersion("test-name", *evr2) + a = RpmVersion(*evr1) + b = RpmVersion(*evr2) self.assertEqual( compare_rpm_versions(a, b), expected, f"failed: {evr1}, {evr2}, {expected}", ) - - # Test against some more canonical tests. These are derived from - # actual tests used for rpm itself. - for ver1, ver2, expected in self._load_canonical_tests(): - self.assertEqual( - _compare_values(ver1, ver2), - expected, - f"failed: {ver1}, {ver2}, {expected}", - ) From c6656ae2ec1437e9d47c59fa9b3a7e50ba8d3279 Mon Sep 17 00:00:00 2001 From: Philippe Ombredanne Date: Mon, 6 Dec 2021 09:44:26 +0100 Subject: [PATCH 681/707] Add ABOUT files, document origin and license Signed-off-by: Philippe Ombredanne --- src/univers/rpm.py | 51 ++--- src/univers/rpm.py.antlir.ABOUT | 16 ++ src/univers/rpm.py.antlir.LICENSE | 239 ++++++++++++++++++++++++ src/univers/rpm.py.antlir.NOTICE | 17 ++ tests/test_rpm.py | 5 +- tests/test_rpm.py.antlir.ABOUT | 12 ++ LICENSE => tests/test_rpm.py.mit.NOTICE | 0 7 files changed, 299 insertions(+), 41 deletions(-) create mode 100644 src/univers/rpm.py.antlir.ABOUT create mode 100644 src/univers/rpm.py.antlir.LICENSE create mode 100644 src/univers/rpm.py.antlir.NOTICE create mode 100644 tests/test_rpm.py.antlir.ABOUT rename LICENSE => tests/test_rpm.py.mit.NOTICE (100%) diff --git a/src/univers/rpm.py b/src/univers/rpm.py index d60e83df..ab100157 100644 --- a/src/univers/rpm.py +++ b/src/univers/rpm.py @@ -1,23 +1,9 @@ -# Copyright (c) Facebook, Inc. and its affiliates. -# -# This source code is licensed under the MIT license found in the -# LICENSE file in the root directory of this source tree. - # +# Copyright (c) Facebook, Inc. and its affiliates. # Copyright (c) SAS Institute Inc. # -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 +# SPDX-License-Identifier: MIT AND Apache-2.0 # -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - import re from typing import NamedTuple from typing import Union @@ -59,30 +45,21 @@ def from_evr(s): return e, v, r -# This comprises a pure python implementation of rpm version comparison. The -# purpose for this is so that the antlir library does not have a dependency -# on a C library that is (for the most part) only distributed as part of rpm -# based distros. Depending on a C library complicates dependency management -# significantly in the OSS space due to the complexity of handling 3rd party C -# libraries with buck. Having this pure python implementation also eases future -# rpm usage/handling for both non-rpm based distros and different arch types. -# -# This implementation is adapted from both this blog post: -# https://blog.jasonantman.com/2014/07/how-yum-and-rpm-compare-versions/ -# and this Apache 2 licensed implementation: -# https://github.com/sassoftware/python-rpm-vercmp/blob/master/rpm_vercmp/vercmp.py -# -# There are extensive test cases in the `test_rpm_metadata.py` test case that -# cover a wide variety of normal and weird version comparsions. - - def compare_rpm_versions(a: Union[RpmVersion, str], b: Union[RpmVersion, str]) -> int: """ - Returns: - 1 if the version of a is newer than b - 0 if the versions match - -1 if the version of a is older than b + Compare to RPM versions ``a`` and ``b`` and return: + - 1 if the version of a is newer than b + - 0 if the versions match + - -1 if the version of a is older than b + + These are the legacy "cmp()" function semantics. + + This implementation is adapted from both this blog post: + https://blog.jasonantman.com/2014/07/how-yum-and-rpm-compare-versions/ + and this Apache 2 licensed implementation: + https://github.com/sassoftware/python-rpm-vercmp/blob/master/rpm_vercmp/vercmp.py + For example:: >>> assert compare_rpm_versions("1.0", "1.1") == -1 >>> assert compare_rpm_versions("1.1", "1.0") == 1 >>> assert compare_rpm_versions("11.13.2-1", "11.13.2.0-1") == -1 diff --git a/src/univers/rpm.py.antlir.ABOUT b/src/univers/rpm.py.antlir.ABOUT new file mode 100644 index 00000000..d016f150 --- /dev/null +++ b/src/univers/rpm.py.antlir.ABOUT @@ -0,0 +1,16 @@ +about_resource: rpm.py +package_url: pkg:github/facebookincubator/antlir@120b20de91c55244ceacf61f82c5154a28446590#antlir/rpm/rpm_metadata.py +copyright: | + Copyright (c) Facebook, Inc. and its affiliates. + Copyright (c) SAS Institute Inc. + +license_expression: mit AND Apache-2.0 +homepage_url: https://github.com/facebookincubator/antlir/ + +notes: | + This has been substantially modified and enhanced from the original code + at https://github.com/facebookincubator/antlir/blob/120b20de91c55244ceacf61f82c5154a28446590/antlir/rpm/rpm_metadata.py + itself taken from + itself originally derived from the Apache-licensed + +notice_file: rpm.py.antlir.NOTICE \ No newline at end of file diff --git a/src/univers/rpm.py.antlir.LICENSE b/src/univers/rpm.py.antlir.LICENSE new file mode 100644 index 00000000..f710a76e --- /dev/null +++ b/src/univers/rpm.py.antlir.LICENSE @@ -0,0 +1,239 @@ + +MIT License + +Copyright (c) Facebook, Inc. and its affiliates. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + +Copyright (c) SAS Institute Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/src/univers/rpm.py.antlir.NOTICE b/src/univers/rpm.py.antlir.NOTICE new file mode 100644 index 00000000..0d734aef --- /dev/null +++ b/src/univers/rpm.py.antlir.NOTICE @@ -0,0 +1,17 @@ + +SPDX-License-Identifier: MIT AND Apache-2.0 + +Copyright (c) Facebook, Inc. and its affiliates. +Copyright (c) SAS Institute Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/tests/test_rpm.py b/tests/test_rpm.py index 5ad4714d..4b0a23e7 100644 --- a/tests/test_rpm.py +++ b/tests/test_rpm.py @@ -1,8 +1,5 @@ -#!/usr/bin/env python3 # Copyright (c) Facebook, Inc. and its affiliates. -# -# This source code is licensed under the MIT license found in the -# LICENSE file in the root directory of this source tree. +# SPDX-License-Identifier: MIT import unittest diff --git a/tests/test_rpm.py.antlir.ABOUT b/tests/test_rpm.py.antlir.ABOUT new file mode 100644 index 00000000..b0abb98b --- /dev/null +++ b/tests/test_rpm.py.antlir.ABOUT @@ -0,0 +1,12 @@ +about_resource: test_rpm.py +package_url: pkg:github/facebookincubator/antlir@120b20de91c55244ceacf61f82c5154a28446590#antlir/rpm/tests/test_rpm_metadata.py +copyright: | + Copyright (c) Facebook, Inc. and its affiliates. + +license_expression: mit +homepage_url: https://github.com/facebookincubator/antlir/ + +notes: | + This has been substantially modified and enhanced from the original code + +notice_file: test_rpm.py.antlir.NOTICE \ No newline at end of file diff --git a/LICENSE b/tests/test_rpm.py.mit.NOTICE similarity index 100% rename from LICENSE rename to tests/test_rpm.py.mit.NOTICE From 7e4816552e07861c31ceaa3063840c43511f96d9 Mon Sep 17 00:00:00 2001 From: Philippe Ombredanne Date: Mon, 6 Dec 2021 10:17:15 +0100 Subject: [PATCH 682/707] Rename all scripts to their target names Signed-off-by: Philippe Ombredanne --- bundler/LICENSE.md => tests/univers/test_bundler.LICENSE | 0 bundler/README.md => tests/univers/test_bundler.README | 0 .../univers/test_bundler_edgecases_spec.py | 0 .../univers/test_bundler_version_ranges_spec.py | 0 LICENSE.txt => tests/univers/test_gem.LICENSE | 0 MAINTAINERS.txt => tests/univers/test_gem.MAINTAINERS | 0 MIT.txt => tests/univers/test_gem.MIT | 0 README.md => tests/univers/test_gem.README | 0 test/rubygems/test_gem.rb => tests/univers/test_gem.py | 0 .../test_gem_version.rb => tests/univers/test_gem_version.py | 0 10 files changed, 0 insertions(+), 0 deletions(-) rename bundler/LICENSE.md => tests/univers/test_bundler.LICENSE (100%) rename bundler/README.md => tests/univers/test_bundler.README (100%) rename bundler/spec/realworld/edgecases_spec.rb => tests/univers/test_bundler_edgecases_spec.py (100%) rename bundler/spec/bundler/version_ranges_spec.rb => tests/univers/test_bundler_version_ranges_spec.py (100%) rename LICENSE.txt => tests/univers/test_gem.LICENSE (100%) rename MAINTAINERS.txt => tests/univers/test_gem.MAINTAINERS (100%) rename MIT.txt => tests/univers/test_gem.MIT (100%) rename README.md => tests/univers/test_gem.README (100%) rename test/rubygems/test_gem.rb => tests/univers/test_gem.py (100%) rename test/rubygems/test_gem_version.rb => tests/univers/test_gem_version.py (100%) diff --git a/bundler/LICENSE.md b/tests/univers/test_bundler.LICENSE similarity index 100% rename from bundler/LICENSE.md rename to tests/univers/test_bundler.LICENSE diff --git a/bundler/README.md b/tests/univers/test_bundler.README similarity index 100% rename from bundler/README.md rename to tests/univers/test_bundler.README diff --git a/bundler/spec/realworld/edgecases_spec.rb b/tests/univers/test_bundler_edgecases_spec.py similarity index 100% rename from bundler/spec/realworld/edgecases_spec.rb rename to tests/univers/test_bundler_edgecases_spec.py diff --git a/bundler/spec/bundler/version_ranges_spec.rb b/tests/univers/test_bundler_version_ranges_spec.py similarity index 100% rename from bundler/spec/bundler/version_ranges_spec.rb rename to tests/univers/test_bundler_version_ranges_spec.py diff --git a/LICENSE.txt b/tests/univers/test_gem.LICENSE similarity index 100% rename from LICENSE.txt rename to tests/univers/test_gem.LICENSE diff --git a/MAINTAINERS.txt b/tests/univers/test_gem.MAINTAINERS similarity index 100% rename from MAINTAINERS.txt rename to tests/univers/test_gem.MAINTAINERS diff --git a/MIT.txt b/tests/univers/test_gem.MIT similarity index 100% rename from MIT.txt rename to tests/univers/test_gem.MIT diff --git a/README.md b/tests/univers/test_gem.README similarity index 100% rename from README.md rename to tests/univers/test_gem.README diff --git a/test/rubygems/test_gem.rb b/tests/univers/test_gem.py similarity index 100% rename from test/rubygems/test_gem.rb rename to tests/univers/test_gem.py diff --git a/test/rubygems/test_gem_version.rb b/tests/univers/test_gem_version.py similarity index 100% rename from test/rubygems/test_gem_version.rb rename to tests/univers/test_gem_version.py From be6fddd405dbcd214328b419da1ed868efecb0d3 Mon Sep 17 00:00:00 2001 From: Philippe Ombredanne Date: Mon, 6 Dec 2021 10:40:46 +0100 Subject: [PATCH 683/707] Rename and add ABOUT and license documentation Signed-off-by: Philippe Ombredanne --- .../test_bundler_version_ranges_spec.py | 0 .../test_bundler_version_ranges_spec.py.ABOUT | 13 + ...est_bundler_version_ranges_spec.py.NOTICE} | 0 ...ersion.py => test_rubygems_gem_version.py} | 0 tests/test_rubygems_gem_version.py.ABOUT | 14 + ...IT => test_rubygems_gem_version.py.NOTICE} | 0 tests/univers/test_bundler.README | 62 - tests/univers/test_bundler_edgecases_spec.py | 527 ---- tests/univers/test_gem.LICENSE | 54 - tests/univers/test_gem.MAINTAINERS | 8 - tests/univers/test_gem.README | 101 - tests/univers/test_gem.py | 2117 ----------------- 12 files changed, 27 insertions(+), 2869 deletions(-) rename tests/{univers => }/test_bundler_version_ranges_spec.py (100%) create mode 100644 tests/test_bundler_version_ranges_spec.py.ABOUT rename tests/{univers/test_bundler.LICENSE => test_bundler_version_ranges_spec.py.NOTICE} (100%) rename tests/{univers/test_gem_version.py => test_rubygems_gem_version.py} (100%) create mode 100644 tests/test_rubygems_gem_version.py.ABOUT rename tests/{univers/test_gem.MIT => test_rubygems_gem_version.py.NOTICE} (100%) delete mode 100644 tests/univers/test_bundler.README delete mode 100644 tests/univers/test_bundler_edgecases_spec.py delete mode 100644 tests/univers/test_gem.LICENSE delete mode 100644 tests/univers/test_gem.MAINTAINERS delete mode 100644 tests/univers/test_gem.README delete mode 100644 tests/univers/test_gem.py diff --git a/tests/univers/test_bundler_version_ranges_spec.py b/tests/test_bundler_version_ranges_spec.py similarity index 100% rename from tests/univers/test_bundler_version_ranges_spec.py rename to tests/test_bundler_version_ranges_spec.py diff --git a/tests/test_bundler_version_ranges_spec.py.ABOUT b/tests/test_bundler_version_ranges_spec.py.ABOUT new file mode 100644 index 00000000..86df2182 --- /dev/null +++ b/tests/test_bundler_version_ranges_spec.py.ABOUT @@ -0,0 +1,13 @@ +about_resource: test_bundler_version_ranges_spec.py +package_url: pkg:github.com/rubygems/rubygems@5768c2bc5542ce05466d379981a433ba1ee1e10a +copyright: | + Portions copyright (c) André Arko + Portions copyright (c) Engine Yard + +license_expression: mit +homepage_url: https://github.com/rubygems/rubygems + +notes: This has been substantially modified and enhanced from the original code + to port tests cases to Python + +notice_file: test_bundler_edgecases_spec.py.NOTICE \ No newline at end of file diff --git a/tests/univers/test_bundler.LICENSE b/tests/test_bundler_version_ranges_spec.py.NOTICE similarity index 100% rename from tests/univers/test_bundler.LICENSE rename to tests/test_bundler_version_ranges_spec.py.NOTICE diff --git a/tests/univers/test_gem_version.py b/tests/test_rubygems_gem_version.py similarity index 100% rename from tests/univers/test_gem_version.py rename to tests/test_rubygems_gem_version.py diff --git a/tests/test_rubygems_gem_version.py.ABOUT b/tests/test_rubygems_gem_version.py.ABOUT new file mode 100644 index 00000000..4f5a2aeb --- /dev/null +++ b/tests/test_rubygems_gem_version.py.ABOUT @@ -0,0 +1,14 @@ +about_resource: test_rubygems_gem_version.py +package_url: pkg:github.com/rubygems/rubygems@5768c2bc5542ce05466d379981a433ba1ee1e10a +copyright: | + Copyright (c) Chad Fowler, Rich Kilmer, Jim Weirich and others. + Portions copyright (c) Engine Yard and Andre Arko + +license_expression: mit +homepage_url: https://github.com/rubygems/rubygems + +notes: This has been substantially modified and enhanced from the original code + to port tests cases to Python. The original license is a choice of MIT or Ruby + license. We selected to use the MIT license here. + +notice_file: test_rubygems_gem_version.py.NOTICE \ No newline at end of file diff --git a/tests/univers/test_gem.MIT b/tests/test_rubygems_gem_version.py.NOTICE similarity index 100% rename from tests/univers/test_gem.MIT rename to tests/test_rubygems_gem_version.py.NOTICE diff --git a/tests/univers/test_bundler.README b/tests/univers/test_bundler.README deleted file mode 100644 index ca0ab2d8..00000000 --- a/tests/univers/test_bundler.README +++ /dev/null @@ -1,62 +0,0 @@ -[![Version ](https://img.shields.io/gem/v/bundler.svg?style=flat)](https://rubygems.org/gems/bundler) -[![Slack ](https://bundler-slackin.herokuapp.com/badge.svg)](https://bundler-slackin.herokuapp.com) - -# Bundler: a gem to bundle gems - -Bundler makes sure Ruby applications run the same code on every machine. - -It does this by managing the gems that the application depends on. Given a list of gems, it can automatically download and install those gems, as well as any other gems needed by the gems that are listed. Before installing gems, it checks the versions of every gem to make sure that they are compatible, and can all be loaded at the same time. After the gems have been installed, Bundler can help you update some or all of them when new versions become available. Finally, it records the exact versions that have been installed, so that others can install the exact same gems. - -### Installation and usage - -To install (or update to the latest version): - -``` -gem install bundler -``` - -To install a prerelease version (if one is available), run `gem install bundler --pre`. To uninstall Bundler, run `gem uninstall bundler`. - -Bundler is most commonly used to manage your application's dependencies. For example, these commands will allow you to use Bundler to manage the `rspec` gem for your application: - -``` -bundle init -bundle add rspec -bundle install -bundle exec rspec -``` - -See [bundler.io](https://bundler.io) for the full documentation. - -### Troubleshooting - -For help with common problems, see [TROUBLESHOOTING](doc/TROUBLESHOOTING.md). - -Still stuck? Try [filing an issue](https://github.com/rubygems/rubygems/issues/new?labels=Bundler&template=bundler-related-issue.md). - -### Other questions - -To see what has changed in recent versions of Bundler, see the [CHANGELOG](CHANGELOG.md). - -To get in touch with the Bundler core team and other Bundler users, please see [getting help](doc/contributing/GETTING_HELP.md). - -### Contributing - -If you'd like to contribute to Bundler, that's awesome, and we <3 you. We've put together [the Bundler contributor guide](https://github.com/rubygems/rubygems/blob/master/bundler/doc/contributing/README.md) with all of the information you need to get started. - -If you'd like to request a substantial change to Bundler or its documentation, refer to the [Bundler RFC process](https://github.com/bundler/rfcs) for more information. - -While some Bundler contributors are compensated by Ruby Together, the project maintainers make decisions independent of Ruby Together. As a project, we welcome contributions regardless of the author's affiliation with Ruby Together. - -### Supporting - -
-Ruby Together pays some Bundler maintainers for their ongoing work. As a grassroots initiative committed to supporting the critical Ruby infrastructure you rely on, Ruby Together is funded entirely by the Ruby community. Contribute today as an individual or (better yet) as a company to ensure that Bundler, RubyGems, and other shared tooling is around for years to come. - -### Code of Conduct - -Everyone interacting in the Bundler project's codebases, issue trackers, chat rooms, and mailing lists is expected to follow the [Bundler code of conduct](https://github.com/rubygems/rubygems/blob/master/CODE_OF_CONDUCT.md). - -### License - -Bundler is available under an [MIT License](https://github.com/rubygems/rubygems/blob/master/bundler/LICENSE.md). diff --git a/tests/univers/test_bundler_edgecases_spec.py b/tests/univers/test_bundler_edgecases_spec.py deleted file mode 100644 index df5eeda9..00000000 --- a/tests/univers/test_bundler_edgecases_spec.py +++ /dev/null @@ -1,527 +0,0 @@ -# frozen_string_literal: true - -RSpec.describe "real world edgecases", :realworld => true do - def rubygems_version(name, requirement) - ruby <<-RUBY - require "#{spec_dir}/support/artifice/vcr" - require "#{entrypoint}" - require "#{entrypoint}/source/rubygems/remote" - require "#{entrypoint}/fetcher" - rubygem = Bundler.ui.silence do - source = Bundler::Source::Rubygems::Remote.new(Bundler::URI("https://rubygems.org")) - fetcher = Bundler::Fetcher.new(source) - index = fetcher.specs([#{name.dump}], nil) - index.search(Gem::Dependency.new(#{name.dump}, #{requirement.dump})).last - end - if rubygem.nil? - raise "Could not find #{name} (#{requirement}) on rubygems.org!\n" \ - "Found specs:\n\#{index.send(:specs).inspect}" - end - puts "#{name} (\#{rubygem.version})" - RUBY - end - - it "resolves dependencies correctly" do - gemfile <<-G - source "https://rubygems.org" - - gem 'rails', '~> 5.0' - gem 'capybara', '~> 2.2.0' - gem 'rack-cache', '1.2.0' # last version that works on Ruby 1.9 - G - bundle :lock - expect(lockfile).to include(rubygems_version("rails", "~> 5.0")) - expect(lockfile).to include("capybara (2.2.1)") - end - - it "installs the latest version of gxapi_rails" do - gemfile <<-G - source "https://rubygems.org" - - gem "sass-rails" - gem "rails", "~> 5" - gem "gxapi_rails", "< 0.1.0" # 0.1.0 was released way after the test was written - gem 'rack-cache', '1.2.0' # last version that works on Ruby 1.9 - G - bundle :lock - expect(lockfile).to include("gxapi_rails (0.0.6)") - end - - it "installs the latest version of i18n" do - gemfile <<-G - source "https://rubygems.org" - - gem "i18n", "~> 0.6.0" - gem "activesupport", "~> 3.0" - gem "activerecord", "~> 3.0" - gem "builder", "~> 2.1.2" - G - bundle :lock - expect(lockfile).to include(rubygems_version("i18n", "~> 0.6.0")) - expect(lockfile).to include(rubygems_version("activesupport", "~> 3.0")) - end - - it "is able to update a top-level dependency when there is a conflict on a shared transitive child" do - # from https://github.com/rubygems/bundler/issues/5031 - - system_gems "bundler-2.99.0" - - gemfile <<-G - source "https://rubygems.org" - gem 'rails', '~> 4.2.7.1' - gem 'paperclip', '~> 5.1.0' - G - - lockfile <<-L - GEM - remote: https://rubygems.org/ - specs: - actionmailer (4.2.7.1) - actionpack (= 4.2.7.1) - actionview (= 4.2.7.1) - activejob (= 4.2.7.1) - mail (~> 2.5, >= 2.5.4) - rails-dom-testing (~> 1.0, >= 1.0.5) - actionpack (4.2.7.1) - actionview (= 4.2.7.1) - activesupport (= 4.2.7.1) - rack (~> 1.6) - rack-test (~> 0.6.2) - rails-dom-testing (~> 1.0, >= 1.0.5) - rails-html-sanitizer (~> 1.0, >= 1.0.2) - actionview (4.2.7.1) - activesupport (= 4.2.7.1) - builder (~> 3.1) - erubis (~> 2.7.0) - rails-dom-testing (~> 1.0, >= 1.0.5) - rails-html-sanitizer (~> 1.0, >= 1.0.2) - activejob (4.2.7.1) - activesupport (= 4.2.7.1) - globalid (>= 0.3.0) - activemodel (4.2.7.1) - activesupport (= 4.2.7.1) - builder (~> 3.1) - activerecord (4.2.7.1) - activemodel (= 4.2.7.1) - activesupport (= 4.2.7.1) - arel (~> 6.0) - activesupport (4.2.7.1) - i18n (~> 0.7) - json (~> 1.7, >= 1.7.7) - minitest (~> 5.1) - thread_safe (~> 0.3, >= 0.3.4) - tzinfo (~> 1.1) - arel (6.0.3) - builder (3.2.2) - climate_control (0.0.3) - activesupport (>= 3.0) - cocaine (0.5.8) - climate_control (>= 0.0.3, < 1.0) - concurrent-ruby (1.0.2) - erubis (2.7.0) - globalid (0.3.7) - activesupport (>= 4.1.0) - i18n (0.7.0) - json (1.8.3) - loofah (2.0.3) - nokogiri (>= 1.5.9) - mail (2.6.4) - mime-types (>= 1.16, < 4) - mime-types (3.1) - mime-types-data (~> 3.2015) - mime-types-data (3.2016.0521) - mimemagic (0.3.2) - mini_portile2 (2.1.0) - minitest (5.9.1) - nokogiri (1.6.8) - mini_portile2 (~> 2.1.0) - pkg-config (~> 1.1.7) - paperclip (5.1.0) - activemodel (>= 4.2.0) - activesupport (>= 4.2.0) - cocaine (~> 0.5.5) - mime-types - mimemagic (~> 0.3.0) - pkg-config (1.1.7) - rack (1.6.4) - rack-test (0.6.3) - rack (>= 1.0) - rails (4.2.7.1) - actionmailer (= 4.2.7.1) - actionpack (= 4.2.7.1) - actionview (= 4.2.7.1) - activejob (= 4.2.7.1) - activemodel (= 4.2.7.1) - activerecord (= 4.2.7.1) - activesupport (= 4.2.7.1) - bundler (>= 1.3.0, < 3.0) - railties (= 4.2.7.1) - sprockets-rails - rails-deprecated_sanitizer (1.0.3) - activesupport (>= 4.2.0.alpha) - rails-dom-testing (1.0.7) - activesupport (>= 4.2.0.beta, < 5.0) - nokogiri (~> 1.6.0) - rails-deprecated_sanitizer (>= 1.0.1) - rails-html-sanitizer (1.0.3) - loofah (~> 2.0) - railties (4.2.7.1) - actionpack (= 4.2.7.1) - activesupport (= 4.2.7.1) - rake (>= 0.8.7) - thor (>= 0.18.1, < 2.0) - rake (11.3.0) - sprockets (3.7.0) - concurrent-ruby (~> 1.0) - rack (> 1, < 3) - sprockets-rails (3.2.0) - actionpack (>= 4.0) - activesupport (>= 4.0) - sprockets (>= 3.0.0) - thor (0.19.1) - thread_safe (0.3.5) - tzinfo (1.2.2) - thread_safe (~> 0.1) - - PLATFORMS - ruby - - DEPENDENCIES - paperclip (~> 5.1.0) - rails (~> 4.2.7.1) - L - - bundle "lock --update paperclip", :env => { "BUNDLER_VERSION" => "2.99.0" } - - expect(lockfile).to include(rubygems_version("paperclip", "~> 5.1.0")) - end - - it "outputs a helpful error message when gems have invalid gemspecs" do - install_gemfile <<-G, :standalone => true, :raise_on_error => false, :env => { "BUNDLE_FORCE_RUBY_PLATFORM" => "1" } - source 'https://rubygems.org' - gem "resque-scheduler", "2.2.0" - gem "redis-namespace", "1.6.0" # for a consistent resolution including ruby 2.3.0 - gem "ruby2_keywords", "0.0.5" - G - expect(err).to include("You have one or more invalid gemspecs that need to be fixed.") - expect(err).to include("resque-scheduler 2.2.0 has an invalid gemspec") - end - - it "doesn't hang on big gemfile" do - skip "Only for ruby 2.7.3" if RUBY_VERSION != "2.7.3" || RUBY_PLATFORM =~ /darwin/ - - gemfile <<~G - # frozen_string_literal: true - - source "https://rubygems.org" - - ruby "2.7.3" - - gem "rails" - gem "pg", ">= 0.18", "< 2.0" - gem "goldiloader" - gem "awesome_nested_set" - gem "circuitbox" - gem "passenger" - gem "globalid" - gem "rack-cors" - gem "rails-pg-extras" - gem "linear_regression_trend" - gem "rack-protection" - gem "pundit" - gem "remote_ip_proxy_scrubber" - gem "bcrypt" - gem "searchkick" - gem "excon" - gem "faraday_middleware-aws-sigv4" - gem "typhoeus" - gem "sidekiq" - gem "sidekiq-undertaker" - gem "sidekiq-cron" - gem "storext" - gem "appsignal" - gem "fcm" - gem "business_time" - gem "tzinfo" - gem "holidays" - gem "bigdecimal" - gem "progress_bar" - gem "redis" - gem "hiredis" - gem "state_machines" - gem "state_machines-audit_trail" - gem "state_machines-activerecord" - gem "interactor" - gem "ar_transaction_changes" - gem "redis-rails" - gem "seed_migration" - gem "lograge" - gem "graphiql-rails", group: :development - gem "graphql" - gem "pusher" - gem "rbnacl" - gem "jwt" - gem "json-schema" - gem "discard" - gem "money" - gem "strip_attributes" - gem "validates_email_format_of" - gem "audited" - gem "concurrent-ruby" - gem "with_advisory_lock" - - group :test do - gem "rspec-sidekiq" - gem "simplecov", require: false - end - - group :development, :test do - gem "byebug", platform: :mri - gem "guard" - gem "guard-bundler" - gem "guard-rspec" - gem "rb-fsevent" - gem "rspec_junit_formatter" - gem "rspec-collection_matchers" - gem "rspec-rails" - gem "rspec-retry" - gem "state_machines-rspec" - gem "dotenv-rails" - gem "database_cleaner-active_record" - gem "database_cleaner-redis" - gem "timecop" - end - - gem "factory_bot_rails" - gem "faker" - - group :development do - gem "listen" - gem "sql_queries_count" - gem "rubocop" - gem "rubocop-performance" - gem "rubocop-rspec" - gem "rubocop-rails" - gem "brakeman" - gem "bundler-audit" - gem "solargraph" - gem "annotate" - end - G - - if Bundler.feature_flag.bundler_3_mode? - # Conflicts on bundler version, so fails earlier - bundle :lock, :env => { "DEBUG_RESOLVER" => "1" }, :raise_on_error => false - expect(out).to display_total_steps_of(435) - else - bundle :lock, :env => { "DEBUG_RESOLVER" => "1" } - expect(out).to display_total_steps_of(1025) - end - end - - it "doesn't hang on tricky gemfile" do - skip "Only for ruby 2.7.3" if RUBY_VERSION != "2.7.3" || RUBY_PLATFORM =~ /darwin/ - - gemfile <<~G - source 'https://rubygems.org' - - group :development do - gem "puppet-module-posix-default-r2.7", '~> 0.3' - gem "puppet-module-posix-dev-r2.7", '~> 0.3' - gem "beaker-rspec" - gem "beaker-puppet" - gem "beaker-docker" - gem "beaker-puppet_install_helper" - gem "beaker-module_install_helper" - end - G - - bundle :lock, :env => { "DEBUG_RESOLVER" => "1" } - - if Bundler.feature_flag.bundler_3_mode? - expect(out).to display_total_steps_of(890) - else - expect(out).to display_total_steps_of(891) - end - end - - it "doesn't hang on nix gemfile" do - skip "Only for ruby 3.0.1" if RUBY_VERSION != "3.0.1" || RUBY_PLATFORM =~ /darwin/ - - gemfile <<~G - source "https://rubygems.org" do - gem "addressable" - gem "atk" - gem "awesome_print" - gem "bacon" - gem "byebug" - gem "cairo" - gem "cairo-gobject" - gem "camping" - gem "charlock_holmes" - gem "cld3" - gem "cocoapods" - gem "cocoapods-acknowledgements" - gem "cocoapods-art" - gem "cocoapods-bin" - gem "cocoapods-browser" - gem "cocoapods-bugsnag" - gem "cocoapods-check" - gem "cocoapods-clean" - gem "cocoapods-clean_build_phases_scripts" - gem "cocoapods-core" - gem "cocoapods-coverage" - gem "cocoapods-deintegrate" - gem "cocoapods-dependencies" - gem "cocoapods-deploy" - gem "cocoapods-downloader" - gem "cocoapods-expert-difficulty" - gem "cocoapods-fix-react-native" - gem "cocoapods-generate" - gem "cocoapods-git_url_rewriter" - gem "cocoapods-keys" - gem "cocoapods-no-dev-schemes" - gem "cocoapods-open" - gem "cocoapods-packager" - gem "cocoapods-playgrounds" - gem "cocoapods-plugins" - gem "cocoapods-prune-localizations" - gem "cocoapods-rome" - gem "cocoapods-search" - gem "cocoapods-sorted-search" - gem "cocoapods-static-swift-framework" - gem "cocoapods-stats" - gem "cocoapods-tdfire-binary" - gem "cocoapods-testing" - gem "cocoapods-trunk" - gem "cocoapods-try" - gem "cocoapods-try-release-fix" - gem "cocoapods-update-if-you-dare" - gem "cocoapods-whitelist" - gem "cocoapods-wholemodule" - gem "coderay" - gem "concurrent-ruby" - gem "curb" - gem "curses" - gem "daemons" - gem "dep-selector-libgecode" - gem "digest-sha3" - gem "domain_name" - gem "do_sqlite3" - gem "ethon" - gem "eventmachine" - gem "excon" - gem "faraday" - gem "ffi" - gem "ffi-rzmq-core" - gem "fog-dnsimple" - gem "gdk_pixbuf2" - gem "gio2" - gem "gitlab-markup" - gem "glib2" - gem "gpgme" - gem "gtk2" - gem "hashie" - gem "highline" - gem "hike" - gem "hitimes" - gem "hpricot" - gem "httpclient" - gem "http-cookie" - gem "iconv" - gem "idn-ruby" - gem "jbuilder" - gem "jekyll" - gem "jmespath" - gem "jwt" - gem "libv8" - gem "libxml-ruby" - gem "magic" - gem "markaby" - gem "method_source" - gem "mini_magick" - gem "msgpack" - gem "mysql2" - gem "ncursesw" - gem "netrc" - gem "net-scp" - gem "net-ssh" - gem "nokogiri" - gem "opus-ruby" - gem "ovirt-engine-sdk" - gem "pango" - gem "patron" - gem "pcaprub" - gem "pg" - gem "pry" - gem "pry-byebug" - gem "pry-doc" - gem "public_suffix" - gem "puma" - gem "rails" - gem "rainbow" - gem "rbnacl" - gem "rb-readline" - gem "re2" - gem "redis" - gem "redis-rack" - gem "rest-client" - gem "rmagick" - gem "rpam2" - gem "rspec" - gem "rubocop" - gem "rubocop-performance" - gem "ruby-libvirt" - gem "ruby-lxc" - gem "ruby-progressbar" - gem "ruby-terminfo" - gem "ruby-vips" - gem "rubyzip" - gem "rugged" - gem "sassc" - gem "scrypt" - gem "semian" - gem "sequel" - gem "sequel_pg" - gem "simplecov" - gem "sinatra" - gem "slop" - gem "snappy" - gem "sqlite3" - gem "taglib-ruby" - gem "thrift" - gem "tilt" - gem "tiny_tds" - gem "treetop" - gem "typhoeus" - gem "tzinfo" - gem "unf_ext" - gem "uuid4r" - gem "whois" - gem "zookeeper" - end - G - - bundle :lock, :env => { "DEBUG_RESOLVER" => "1" } - - if Bundler.feature_flag.bundler_3_mode? - expect(out).to display_total_steps_of(1874) - else - expect(out).to display_total_steps_of(1922) - end - end - - private - - RSpec::Matchers.define :display_total_steps_of do |expected_steps| - match do |out| - out.include?("BUNDLER: Finished resolution (#{expected_steps} steps)") - end - - failure_message do |out| - actual_steps = out.scan(/BUNDLER: Finished resolution \((\d+) steps\)/).first.first - - "Expected resolution to finish in #{expected_steps} steps, but took #{actual_steps}" - end - end -end diff --git a/tests/univers/test_gem.LICENSE b/tests/univers/test_gem.LICENSE deleted file mode 100644 index 8a0a51de..00000000 --- a/tests/univers/test_gem.LICENSE +++ /dev/null @@ -1,54 +0,0 @@ -RubyGems is copyrighted free software by Chad Fowler, Rich Kilmer, Jim -Weirich and others. You can redistribute it and/or modify it under -either the terms of the MIT license (see the file MIT.txt), or the -conditions below: - -1. You may make and give away verbatim copies of the source form of the - software without restriction, provided that you duplicate all of the - original copyright notices and associated disclaimers. - -2. You may modify your copy of the software in any way, provided that - you do at least ONE of the following: - - a. place your modifications in the Public Domain or otherwise - make them Freely Available, such as by posting said - modifications to Usenet or an equivalent medium, or by allowing - the author to include your modifications in the software. - - b. use the modified software only within your corporation or - organization. - - c. give non-standard executables non-standard names, with - instructions on where to get the original software distribution. - - d. make other distribution arrangements with the author. - -3. You may distribute the software in object code or executable - form, provided that you do at least ONE of the following: - - a. distribute the executables and library files of the software, - together with instructions (in the manual page or equivalent) - on where to get the original distribution. - - b. accompany the distribution with the machine-readable source of - the software. - - c. give non-standard executables non-standard names, with - instructions on where to get the original software distribution. - - d. make other distribution arrangements with the author. - -4. You may modify and include the part of the software into any other - software (possibly commercial). - -5. The scripts and library files supplied as input to or produced as - output from the software do not automatically fall under the - copyright of the software, but belong to whomever generated them, - and may be sold commercially, and may be aggregated with this - software. - -6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR - IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - PURPOSE. - diff --git a/tests/univers/test_gem.MAINTAINERS b/tests/univers/test_gem.MAINTAINERS deleted file mode 100644 index 2cc2acff..00000000 --- a/tests/univers/test_gem.MAINTAINERS +++ /dev/null @@ -1,8 +0,0 @@ -Luis Sagastume (@bronzdoc) -Daniel Berger (@djberg96) -Ellen Marie Dash (@duckinator) -Evan Phoenix (@evanphx) -SHIBATA Hiroshi (@hsbt) -André Arko (@indirect) -Samuel Giddins (@segiddins) -David Rodríguez (@deivid-rodriguez) diff --git a/tests/univers/test_gem.README b/tests/univers/test_gem.README deleted file mode 100644 index 1f973c73..00000000 --- a/tests/univers/test_gem.README +++ /dev/null @@ -1,101 +0,0 @@ -# RubyGems [![Maintainability](https://api.codeclimate.com/v1/badges/30f913e9c2dd932132c1/maintainability)](https://codeclimate.com/github/rubygems/rubygems/maintainability) - -RubyGems is a package management framework for Ruby. - -A package (also known as a library) contains a set of functionality that can be invoked by a Ruby program, such as reading and parsing an XML file. -We call these packages "gems" and RubyGems is a tool to install, create, manage and load these packages in your Ruby environment. - -RubyGems is also a client for [RubyGems.org](https://rubygems.org), a public repository of Gems that allows you to publish a Gem -that can be shared and used by other developers. See our guide on publishing a Gem at [guides.rubygems.org](https://guides.rubygems.org/publishing/) - -## Getting Started - -Installing and managing a Gem is done through the `gem` command. To install a Gem such as [Nokogiri](https://github.com/sparklemotion/nokogiri) which lets -you read and parse XML in Ruby: - - $ gem install nokogiri - -RubyGems will download the Nokogiri Gem from RubyGems.org and install it into your Ruby environment. - -Finally, inside your Ruby program, load the Nokogiri gem and start parsing your XML: - - require 'nokogiri' - - Nokogiri.XML('

Hello World

') - -For more information about how to use RubyGems, see our RubyGems basics guide at [guides.rubygems.org](https://guides.rubygems.org/rubygems-basics/) - -## Requirements - -* RubyGems 2.6 supports Ruby 2.4 or lower. -* RubyGems 2.7 supports Ruby 2.5 or lower. -* RubyGems 3.0 supports Ruby 2.3 or later. - -## Installation - -RubyGems is already installed in your Ruby environment, you can check the version you have installed by running `gem --version` in your terminal emulator. - -In some cases Ruby & RubyGems may be provided as OS packages. This is not a -recommended way to use Ruby & RubyGems. It's better to use a Ruby Version -Manager, such as [rbenv](https://github.com/rbenv/rbenv) or -[chruby](https://github.com/postmodern/chruby). If you still want to use the -version provided by your OS package manager, please also use your OS package -manager to upgrade rubygems, and disregard any other installation instructions -given below. - -If you would like to manually install RubyGems: - -* Download from https://rubygems.org/pages/download, unpack, and `cd` into RubyGems' src -* OR clone this repository and `cd` into the repository - -Install RubyGems by running: - - $ ruby setup.rb - -For more details and other options, see: - - $ ruby setup.rb --help - -## Upgrading RubyGems - -To upgrade to the latest RubyGems, run: - - $ gem update --system - -See [UPGRADING](UPGRADING.md) for more details and alternative instructions. - -## Documentation - -RubyGems uses [rdoc](https://github.com/rdoc/rdoc) for documentation. A compiled set of the docs -can be viewed online at [rubydoc](https://www.rubydoc.info/github/rubygems/rubygems). - -RubyGems also provides a comprehensive set of guides which covers numerous topics such as -creating a new gem, security practices and other resources at https://guides.rubygems.org - -## Getting Help - -### Filing Tickets - -Got a bug and you're not sure? You're sure you have a bug, but don't know -what to do next? In any case, let us know about it! The best place -for letting the RubyGems team know about bugs or problems you're having is -[on the RubyGems issues page at GitHub](http://github.com/rubygems/rubygems/issues). - -### Bundler Compatibility - -See http://bundler.io/compatibility for known issues. - -### Supporting - -
-Ruby Together pays some RubyGems maintainers for their ongoing work. As a grassroots initiative committed to supporting the critical Ruby infrastructure you rely on, Ruby Together is funded entirely by the Ruby community. Contribute today as an individual or even better, as a company, and ensure that RubyGems, Bundler, and other shared tooling is around for years to come. - -### Contributing - -If you'd like to contribute to RubyGems, that's awesome, and we <3 you. Check out our [guide to contributing](CONTRIBUTING.md) for more information. - -While some RubyGems contributors are compensated by Ruby Together, the project maintainers make decisions independent of Ruby Together. As a project, we welcome contributions regardless of the author’s affiliation with Ruby Together. - -### Code of Conduct - -Everyone interacting in the RubyGems project’s codebases, issue trackers, chat rooms, and mailing lists is expected to follow the [contributor code of conduct](https://github.com/rubygems/rubygems/blob/master/CODE_OF_CONDUCT.md). diff --git a/tests/univers/test_gem.py b/tests/univers/test_gem.py deleted file mode 100644 index 3c95982d..00000000 --- a/tests/univers/test_gem.py +++ /dev/null @@ -1,2117 +0,0 @@ -# coding: US-ASCII -require_relative 'helper' -require 'rubygems' -require 'rubygems/command' -require 'rubygems/installer' -require 'pathname' -require 'tmpdir' -require 'rbconfig' - -class TestGem < Gem::TestCase - PLUGINS_LOADED = [] # rubocop:disable Style/MutableConstant - - PROJECT_DIR = File.expand_path('../../..', __FILE__).tap(&Gem::UNTAINT) - - def setup - super - - PLUGINS_LOADED.clear - - common_installer_setup - - @additional = %w[a b].map {|d| File.join @tempdir, d } - - util_remove_interrupt_command - end - - def test_self_finish_resolve - a1 = util_spec "a", "1", "b" => "> 0" - b1 = util_spec "b", "1", "c" => ">= 1" - b2 = util_spec "b", "2", "c" => ">= 2" - c1 = util_spec "c", "1" - c2 = util_spec "c", "2" - - install_specs c1, c2, b1, b2, a1 - - a1.activate - - assert_equal %w[a-1], loaded_spec_names - assert_equal ["b (> 0)"], unresolved_names - - Gem.finish_resolve - - assert_equal %w[a-1 b-2 c-2], loaded_spec_names - assert_equal [], unresolved_names - end - - def test_self_finish_resolve_wtf - a1 = util_spec "a", "1", "b" => "> 0", "d" => "> 0" # this - b1 = util_spec "b", "1", { "c" => ">= 1" }, "lib/b.rb" # this - b2 = util_spec "b", "2", { "c" => ">= 2" }, "lib/b.rb" - c1 = util_spec "c", "1" # this - c2 = util_spec "c", "2" - d1 = util_spec "d", "1", { "c" => "< 2" }, "lib/d.rb" - d2 = util_spec "d", "2", { "c" => "< 2" }, "lib/d.rb" # this - - install_specs c1, c2, b1, b2, d1, d2, a1 - - a1.activate - - assert_equal %w[a-1], loaded_spec_names - assert_equal ["b (> 0)", "d (> 0)"], unresolved_names - - Gem.finish_resolve - - assert_equal %w[a-1 b-1 c-1 d-2], loaded_spec_names - assert_equal [], unresolved_names - end - - def test_self_finish_resolve_respects_loaded_specs - a1 = util_spec "a", "1", "b" => "> 0" - b1 = util_spec "b", "1", "c" => ">= 1" - b2 = util_spec "b", "2", "c" => ">= 2" - c1 = util_spec "c", "1" - c2 = util_spec "c", "2" - - install_specs c1, c2, b1, b2, a1 - - a1.activate - c1.activate - - assert_equal %w[a-1 c-1], loaded_spec_names - assert_equal ["b (> 0)"], unresolved_names - - Gem.finish_resolve - - assert_equal %w[a-1 b-1 c-1], loaded_spec_names - assert_equal [], unresolved_names - end - - def test_self_install - spec_fetcher do |f| - f.gem 'a', 1 - f.spec 'a', 2 - end - - gemhome2 = "#{@gemhome}2" - - installed = Gem.install 'a', '= 1', :install_dir => gemhome2 - - assert_equal %w[a-1], installed.map {|spec| spec.full_name } - - assert_path_exist File.join(gemhome2, 'gems', 'a-1') - end - - def test_self_install_in_rescue - spec_fetcher do |f| - f.gem 'a', 1 - f.spec 'a', 2 - end - - gemhome2 = "#{@gemhome}2" - - installed = - begin - raise 'Error' - rescue StandardError - Gem.install 'a', '= 1', :install_dir => gemhome2 - end - assert_equal %w[a-1], installed.map {|spec| spec.full_name } - end - - def test_self_install_permissions - assert_self_install_permissions - end - - def test_self_install_permissions_umask_0 - umask = File.umask(0) - assert_self_install_permissions - ensure - File.umask(umask) - end - - def test_self_install_permissions_umask_077 - umask = File.umask(077) - assert_self_install_permissions - ensure - File.umask(umask) - end - - def test_self_install_permissions_with_format_executable - assert_self_install_permissions(format_executable: true) - end - - def test_self_install_permissions_with_format_executable_and_non_standard_ruby_install_name - Gem::Installer.exec_format = nil - ruby_install_name 'ruby27' do - assert_self_install_permissions(format_executable: true) - end - ensure - Gem::Installer.exec_format = nil - end - - def assert_self_install_permissions(format_executable: false) - mask = win_platform? ? 0700 : 0777 - options = { - :dir_mode => 0500, - :prog_mode => win_platform? ? 0410 : 0510, - :data_mode => 0640, - :wrappers => true, - :format_executable => format_executable, - } - Dir.chdir @tempdir do - Dir.mkdir 'bin' - Dir.mkdir 'data' - - File.write 'bin/foo', "#!/usr/bin/env ruby\n" - File.chmod 0755, 'bin/foo' - - File.write 'data/foo.txt', "blah\n" - - spec_fetcher do |f| - f.gem 'foo', 1 do |s| - s.executables = ['foo'] - s.files = %w[bin/foo data/foo.txt] - end - end - Gem.install 'foo', Gem::Requirement.default, options - end - - prog_mode = (options[:prog_mode] & mask).to_s(8) - dir_mode = (options[:dir_mode] & mask).to_s(8) - data_mode = (options[:data_mode] & mask).to_s(8) - prog_name = 'foo' - prog_name = RbConfig::CONFIG['ruby_install_name'].sub('ruby', 'foo') if options[:format_executable] - expected = { - "bin/#{prog_name}" => prog_mode, - 'gems/foo-1' => dir_mode, - 'gems/foo-1/bin' => dir_mode, - 'gems/foo-1/data' => dir_mode, - 'gems/foo-1/bin/foo' => prog_mode, - 'gems/foo-1/data/foo.txt' => data_mode, - } - # add Windows script - expected["bin/#{prog_name}.bat"] = mask.to_s(8) if win_platform? - result = {} - Dir.chdir @gemhome do - expected.each_key do |n| - result[n] = (File.stat(n).mode & mask).to_s(8) - end - end - assert_equal(expected, result) - ensure - File.chmod(0755, *Dir.glob(@gemhome + '/gems/**/').map {|path| path.tap(&Gem::UNTAINT) }) - end - - def test_require_missing - assert_raise ::LoadError do - require "test_require_missing" - end - end - - def test_require_does_not_glob - a1 = util_spec "a", "1", nil, "lib/a1.rb" - - install_specs a1 - - assert_raise ::LoadError do - require "a*" - end - - assert_equal [], loaded_spec_names - end - - def test_self_bin_path_active - a1 = util_spec 'a', '1' do |s| - s.executables = ['exec'] - end - - util_spec 'a', '2' do |s| - s.executables = ['exec'] - end - - a1.activate - - assert_match 'a-1/bin/exec', Gem.bin_path('a', 'exec', '>= 0') - end - - def test_self_bin_path_picking_newest - a1 = util_spec 'a', '1' do |s| - s.executables = ['exec'] - end - - a2 = util_spec 'a', '2' do |s| - s.executables = ['exec'] - end - - install_specs a1, a2 - - assert_match 'a-2/bin/exec', Gem.bin_path('a', 'exec', '>= 0') - end - - def test_self_activate_bin_path_no_exec_name - e = assert_raise ArgumentError do - Gem.activate_bin_path 'a' - end - - assert_equal 'you must supply exec_name', e.message - end - - def test_activate_bin_path_resolves_eagerly - a1 = util_spec 'a', '1' do |s| - s.executables = ['exec'] - s.add_dependency 'b' - end - - b1 = util_spec 'b', '1' do |s| - s.add_dependency 'c', '2' - end - - b2 = util_spec 'b', '2' do |s| - s.add_dependency 'c', '1' - end - - c1 = util_spec 'c', '1' - c2 = util_spec 'c', '2' - - install_specs c1, c2, b1, b2, a1 - - Gem.activate_bin_path("a", "exec", ">= 0") - - # If we didn't eagerly resolve, this would activate c-2 and then the - # finish_resolve would cause a conflict - gem 'c' - Gem.finish_resolve - - assert_equal %w[a-1 b-2 c-1], loaded_spec_names - end - - def test_activate_bin_path_does_not_error_if_a_gem_thats_not_finally_activated_has_orphaned_dependencies - a1 = util_spec 'a', '1' do |s| - s.executables = ['exec'] - s.add_dependency 'b' - end - - b1 = util_spec 'b', '1' do |s| - s.add_dependency 'c', '1' - end - - b2 = util_spec 'b', '2' do |s| - s.add_dependency 'c', '2' - end - - c2 = util_spec 'c', '2' - - install_specs c2, b1, b2, a1 - - # c1 is missing, but not needed for activation, so we should not get any errors here - - Gem.activate_bin_path("a", "exec", ">= 0") - - assert_equal %w[a-1 b-2 c-2], loaded_spec_names - end - - def test_activate_bin_path_raises_a_meaningful_error_if_a_gem_thats_finally_activated_has_orphaned_dependencies - a1 = util_spec 'a', '1' do |s| - s.executables = ['exec'] - s.add_dependency 'b' - end - - b1 = util_spec 'b', '1' do |s| - s.add_dependency 'c', '1' - end - - b2 = util_spec 'b', '2' do |s| - s.add_dependency 'c', '2' - end - - c1 = util_spec 'c', '1' - - install_specs c1, b1, b2, a1 - - # c2 is missing, and b2 which has it as a dependency will be activated, so we should get an error about the orphaned dependency - - e = assert_raise Gem::UnsatisfiableDependencyError do - load Gem.activate_bin_path("a", "exec", ">= 0") - end - - assert_equal "Unable to resolve dependency: 'b (>= 0)' requires 'c (= 2)'", e.message - end - - def test_activate_bin_path_in_debug_mode - a1 = util_spec 'a', '1' do |s| - s.executables = ['exec'] - end - - install_specs a1 - - require "open3" - output, status = Open3.capture2e( - { "GEM_HOME" => Gem.paths.home, "DEBUG_RESOLVER" => "1" }, - *ruby_with_rubygems_in_load_path, "-e", "\"Gem.activate_bin_path('a', 'exec', '>= 0')\"" - ) - - assert status.success?, output - end - - def test_activate_bin_path_gives_proper_error_for_bundler - bundler = util_spec 'bundler', '2' do |s| - s.executables = ['bundle'] - end - - install_specs bundler - - File.open("Gemfile.lock", "w") do |f| - f.write <<-L.gsub(/ {8}/, "") - GEM - remote: https://rubygems.org/ - specs: - - PLATFORMS - ruby - - DEPENDENCIES - - BUNDLED WITH - 9999 - L - end - - File.open("Gemfile", "w") {|f| f.puts('source "https://rubygems.org"') } - - e = assert_raise Gem::GemNotFoundException do - load Gem.activate_bin_path("bundler", "bundle", ">= 0.a") - end - - assert_includes e.message, "Could not find 'bundler' (9999) required by your #{File.expand_path("Gemfile.lock")}." - assert_includes e.message, "To update to the latest version installed on your system, run `bundle update --bundler`." - assert_includes e.message, "To install the missing version, run `gem install bundler:9999`" - refute_includes e.message, "can't find gem bundler (>= 0.a) with executable bundle" - end - - def test_activate_bin_path_selects_exact_bundler_version_if_present - bundler_latest = util_spec 'bundler', '2.0.1' do |s| - s.executables = ['bundle'] - end - - bundler_previous = util_spec 'bundler', '2.0.0' do |s| - s.executables = ['bundle'] - end - - install_specs bundler_latest, bundler_previous - - File.open("Gemfile.lock", "w") do |f| - f.write <<-L.gsub(/ {8}/, "") - GEM - remote: https://rubygems.org/ - specs: - - PLATFORMS - ruby - - DEPENDENCIES - - BUNDLED WITH - 2.0.0 - L - end - - File.open("Gemfile", "w") {|f| f.puts('source "https://rubygems.org"') } - - load Gem.activate_bin_path("bundler", "bundle", ">= 0.a") - - assert_equal %w[bundler-2.0.0], loaded_spec_names - end - - def test_activate_bin_path_respects_underscore_selection_if_given - bundler_latest = util_spec 'bundler', '2.0.1' do |s| - s.executables = ['bundle'] - end - - bundler_previous = util_spec 'bundler', '1.17.3' do |s| - s.executables = ['bundle'] - end - - install_specs bundler_latest, bundler_previous - - File.open("Gemfile.lock", "w") do |f| - f.write <<-L.gsub(/ {8}/, "") - GEM - remote: https://rubygems.org/ - specs: - - PLATFORMS - ruby - - DEPENDENCIES - - BUNDLED WITH - 2.0.1 - L - end - - File.open("Gemfile", "w") {|f| f.puts('source "https://rubygems.org"') } - - load Gem.activate_bin_path("bundler", "bundle", "= 1.17.3") - - assert_equal %w[bundler-1.17.3], loaded_spec_names - end - - def test_activate_bin_path_gives_proper_error_for_bundler_when_underscore_selection_given - File.open("Gemfile.lock", "w") do |f| - f.write <<-L.gsub(/ {8}/, "") - GEM - remote: https://rubygems.org/ - specs: - - PLATFORMS - ruby - - DEPENDENCIES - - BUNDLED WITH - 2.1.4 - L - end - - File.open("Gemfile", "w") {|f| f.puts('source "https://rubygems.org"') } - - e = assert_raise Gem::GemNotFoundException do - load Gem.activate_bin_path("bundler", "bundle", "= 2.2.8") - end - - assert_equal "can't find gem bundler (= 2.2.8) with executable bundle", e.message - end - - def test_self_bin_path_no_exec_name - e = assert_raise ArgumentError do - Gem.bin_path 'a' - end - - assert_equal 'you must supply exec_name', e.message - end - - def test_self_bin_path_bin_name - install_specs util_exec_gem - assert_equal @abin_path, Gem.bin_path('a', 'abin') - end - - def test_self_bin_path_bin_name_version - install_specs util_exec_gem - assert_equal @abin_path, Gem.bin_path('a', 'abin', '4') - end - - def test_self_bin_path_nonexistent_binfile - util_spec 'a', '2' do |s| - s.executables = ['exec'] - end - assert_raise(Gem::GemNotFoundException) do - Gem.bin_path('a', 'other', '2') - end - end - - def test_self_bin_path_no_bin_file - util_spec 'a', '1' - assert_raise(ArgumentError) do - Gem.bin_path('a', nil, '1') - end - end - - def test_self_bin_path_not_found - assert_raise(Gem::GemNotFoundException) do - Gem.bin_path('non-existent', 'blah') - end - end - - def test_self_bin_path_bin_file_gone_in_latest - install_specs util_exec_gem - spec = util_spec 'a', '10' do |s| - s.executables = [] - end - install_specs spec - assert_equal @abin_path, Gem.bin_path('a', 'abin') - end - - def test_self_bindir - assert_equal File.join(@gemhome, 'bin'), Gem.bindir - assert_equal File.join(@gemhome, 'bin'), Gem.bindir(Gem.dir) - assert_equal File.join(@gemhome, 'bin'), Gem.bindir(Pathname.new(Gem.dir)) - end - - def test_self_bindir_default_dir - default = Gem.default_dir - - assert_equal Gem.default_bindir, Gem.bindir(default) - end - - def test_self_clear_paths - assert_match(/gemhome$/, Gem.dir) - assert_match(/gemhome$/, Gem.path.first) - - Gem.clear_paths - - assert_nil Gem::Specification.send(:class_variable_get, :@@all) - end - - def test_self_configuration - expected = Gem::ConfigFile.new [] - Gem.configuration = nil - - assert_equal expected, Gem.configuration - end - - def test_self_datadir - foo = nil - - Dir.chdir @tempdir do - FileUtils.mkdir_p 'data' - File.open File.join('data', 'foo.txt'), 'w' do |fp| - fp.puts 'blah' - end - - foo = util_spec 'foo' do |s| - s.files = %w[data/foo.txt] - end - - install_gem foo - end - - gem 'foo' - - expected = File.join @gemhome, 'gems', foo.full_name, 'data', 'foo' - - assert_equal expected, Gem::Specification.find_by_name("foo").datadir - end - - def test_self_datadir_nonexistent_package - assert_raise(Gem::MissingSpecError) do - Gem::Specification.find_by_name("xyzzy").datadir - end - end - - def test_self_default_exec_format - ruby_install_name 'ruby' do - assert_equal '%s', Gem.default_exec_format - end - end - - def test_self_default_exec_format_18 - ruby_install_name 'ruby18' do - assert_equal '%s18', Gem.default_exec_format - end - end - - def test_self_default_exec_format_jruby - ruby_install_name 'jruby' do - assert_equal 'j%s', Gem.default_exec_format - end - end - - def test_default_path - vendordir(File.join(@tempdir, 'vendor')) do - FileUtils.rm_rf Gem.user_home - - expected = [Gem.default_dir] - - assert_equal expected, Gem.default_path - end - end - - def test_default_path_missing_vendor - vendordir(nil) do - FileUtils.rm_rf Gem.user_home - - expected = [Gem.default_dir] - - assert_equal expected, Gem.default_path - end - end - - def test_default_path_user_home - vendordir(File.join(@tempdir, 'vendor')) do - expected = [Gem.user_dir, Gem.default_dir] - - assert_equal expected, Gem.default_path - end - end - - def test_default_path_vendor_dir - vendordir(File.join(@tempdir, 'vendor')) do - FileUtils.mkdir_p Gem.vendor_dir - - FileUtils.rm_rf Gem.user_home - - expected = [Gem.default_dir, Gem.vendor_dir] - - assert_equal expected, Gem.default_path - end - end - - def test_self_default_sources - assert_equal %w[https://rubygems.org/], Gem.default_sources - end - - def test_self_use_gemdeps - with_rubygems_gemdeps('-') do - FileUtils.mkdir_p 'detect/a/b' - FileUtils.mkdir_p 'detect/a/Isolate' - - FileUtils.touch 'detect/Isolate' - - begin - Dir.chdir 'detect/a/b' - - Gem.use_gemdeps - - assert_equal add_bundler_full_name([]), loaded_spec_names - ensure - Dir.chdir @tempdir - end - end - end - - def test_self_dir - assert_equal @gemhome, Gem.dir - end - - def test_self_ensure_gem_directories - FileUtils.rm_r @gemhome - Gem.use_paths @gemhome - - Gem.ensure_gem_subdirectories @gemhome - - assert_path_exist File.join @gemhome, 'build_info' - assert_path_exist File.join @gemhome, 'cache' - assert_path_exist File.join @gemhome, 'doc' - assert_path_exist File.join @gemhome, 'extensions' - assert_path_exist File.join @gemhome, 'gems' - assert_path_exist File.join @gemhome, 'specifications' - end - - def test_self_ensure_gem_directories_permissions - FileUtils.rm_r @gemhome - Gem.use_paths @gemhome - - Gem.ensure_gem_subdirectories @gemhome, 0750 - - assert_directory_exists File.join(@gemhome, "cache") - - assert_equal 0750, File::Stat.new(@gemhome).mode & 0777 - assert_equal 0750, File::Stat.new(File.join(@gemhome, "cache")).mode & 0777 - end unless win_platform? - - def test_self_ensure_gem_directories_safe_permissions - FileUtils.rm_r @gemhome - Gem.use_paths @gemhome - - old_umask = File.umask - File.umask 0 - Gem.ensure_gem_subdirectories @gemhome - - assert_equal 0, File::Stat.new(@gemhome).mode & 002 - assert_equal 0, File::Stat.new(File.join(@gemhome, "cache")).mode & 002 - ensure - File.umask old_umask - end unless win_platform? - - def test_self_ensure_gem_directories_missing_parents - gemdir = File.join @tempdir, 'a/b/c/gemdir' - FileUtils.rm_rf File.join(@tempdir, 'a') rescue nil - refute File.exist?(File.join(@tempdir, 'a')), - "manually remove #{File.join @tempdir, 'a'}, tests are broken" - Gem.use_paths gemdir - - Gem.ensure_gem_subdirectories gemdir - - assert_directory_exists util_cache_dir - end - - unless win_platform? || Process.uid.zero? # only for FS that support write protection - def test_self_ensure_gem_directories_write_protected - gemdir = File.join @tempdir, "egd" - FileUtils.rm_r gemdir rescue nil - refute File.exist?(gemdir), "manually remove #{gemdir}, tests are broken" - FileUtils.mkdir_p gemdir - FileUtils.chmod 0400, gemdir - Gem.use_paths gemdir - - Gem.ensure_gem_subdirectories gemdir - - refute File.exist?(util_cache_dir) - ensure - FileUtils.chmod 0600, gemdir - end - - def test_self_ensure_gem_directories_write_protected_parents - parent = File.join(@tempdir, "egd") - gemdir = "#{parent}/a/b/c" - - FileUtils.rm_r parent rescue nil - refute File.exist?(parent), "manually remove #{parent}, tests are broken" - FileUtils.mkdir_p parent - FileUtils.chmod 0400, parent - Gem.use_paths(gemdir) - - Gem.ensure_gem_subdirectories gemdir - - refute File.exist? File.join(gemdir, "gems") - ensure - FileUtils.chmod 0600, parent - end - - def test_self_ensure_gem_directories_non_existent_paths - Gem.ensure_gem_subdirectories '/proc/0123456789/bogus' # should not raise - Gem.ensure_gem_subdirectories 'classpath:/bogus/x' # JRuby embed scenario - end - end - - def test_self_extension_dir_shared - enable_shared 'yes' do - assert_equal Gem.ruby_api_version, Gem.extension_api_version - end - end - - def test_self_extension_dir_static - enable_shared 'no' do - assert_equal "#{Gem.ruby_api_version}-static", Gem.extension_api_version - end - end - - def test_self_find_files - cwd = File.expand_path("test/rubygems", PROJECT_DIR) - $LOAD_PATH.unshift cwd - - discover_path = File.join 'lib', 'sff', 'discover.rb' - - foo1, foo2 = %w[1 2].map do |version| - spec = quick_gem 'sff', version do |s| - s.files << discover_path - end - - write_file(File.join 'gems', spec.full_name, discover_path) do |fp| - fp.puts "# #{spec.full_name}" - end - - spec - end - - Gem.refresh - - expected = [ - File.expand_path('test/rubygems/sff/discover.rb', PROJECT_DIR), - File.join(foo2.full_gem_path, discover_path), - File.join(foo1.full_gem_path, discover_path), - ] - - assert_equal expected, Gem.find_files('sff/discover') - assert_equal expected, Gem.find_files('sff/**.rb'), '[ruby-core:31730]' - ensure - assert_equal cwd, $LOAD_PATH.shift - end - - def test_self_find_files_with_gemfile - cwd = File.expand_path("test/rubygems", PROJECT_DIR) - actual_load_path = $LOAD_PATH.unshift(cwd).dup - - discover_path = File.join 'lib', 'sff', 'discover.rb' - - foo1, _ = %w[1 2].map do |version| - spec = quick_gem 'sff', version do |s| - s.files << discover_path - end - - write_file(File.join 'gems', spec.full_name, discover_path) do |fp| - fp.puts "# #{spec.full_name}" - end - - spec - end - Gem.refresh - - write_file(File.join Dir.pwd, 'Gemfile') do |fp| - fp.puts "source 'https://rubygems.org'" - fp.puts "gem '#{foo1.name}', '#{foo1.version}'" - end - Gem.use_gemdeps(File.join Dir.pwd, 'Gemfile') - - expected = [ - File.expand_path('test/rubygems/sff/discover.rb', PROJECT_DIR), - File.join(foo1.full_gem_path, discover_path), - ].sort - - assert_equal expected, Gem.find_files('sff/discover').sort - assert_equal expected, Gem.find_files('sff/**.rb').sort, '[ruby-core:31730]' - ensure - assert_equal cwd, actual_load_path.shift unless Gem.java_platform? - end - - def test_self_find_latest_files - cwd = File.expand_path("test/rubygems", PROJECT_DIR) - $LOAD_PATH.unshift cwd - - discover_path = File.join 'lib', 'sff', 'discover.rb' - - _, foo2 = %w[1 2].map do |version| - spec = quick_gem 'sff', version do |s| - s.files << discover_path - end - - write_file(File.join 'gems', spec.full_name, discover_path) do |fp| - fp.puts "# #{spec.full_name}" - end - - spec - end - - Gem.refresh - - expected = [ - File.expand_path('test/rubygems/sff/discover.rb', PROJECT_DIR), - File.join(foo2.full_gem_path, discover_path), - ] - - assert_equal expected, Gem.find_latest_files('sff/discover') - assert_equal expected, Gem.find_latest_files('sff/**.rb'), '[ruby-core:31730]' - ensure - assert_equal cwd, $LOAD_PATH.shift - end - - def test_self_latest_spec_for - gems = spec_fetcher do |fetcher| - fetcher.spec 'a', 1 - fetcher.spec 'a', '3.a' - fetcher.spec 'a', 2 - end - - spec = Gem.latest_spec_for 'a' - - assert_equal gems['a-2'], spec - end - - def test_self_latest_rubygems_version - spec_fetcher do |fetcher| - fetcher.spec 'rubygems-update', '1.8.23' - fetcher.spec 'rubygems-update', '1.8.24' - fetcher.spec 'rubygems-update', '2.0.0.preview3' - end - - version = Gem.latest_rubygems_version - - assert_equal Gem::Version.new('1.8.24'), version - end - - def test_self_latest_version_for - spec_fetcher do |fetcher| - fetcher.spec 'a', 1 - fetcher.spec 'a', 2 - fetcher.spec 'a', '3.a' - end - - version = Gem.latest_version_for 'a' - - assert_equal Gem::Version.new(2), version - end - - def test_self_loaded_specs - foo = util_spec 'foo' - install_gem foo - - foo.activate - - assert_equal true, Gem.loaded_specs.keys.include?('foo') - end - - def test_self_path - assert_equal [Gem.dir], Gem.path - end - - def test_self_path_default - ENV.delete "GEM_HOME" - ENV.delete "GEM_PATH" - - Gem.instance_variable_set :@paths, nil - - assert_equal [Gem.default_path, Gem.dir].flatten.uniq, Gem.path - end - - def test_self_path_ENV_PATH - path_count = Gem.path.size - Gem.clear_paths - - ENV['GEM_PATH'] = @additional.join(File::PATH_SEPARATOR) - - assert_equal @additional, Gem.path[0,2] - - assert_equal path_count + @additional.size, Gem.path.size, - "extra path components: #{Gem.path[2..-1].inspect}" - assert_equal Gem.dir, Gem.path.last - end - - def test_self_path_duplicate - Gem.clear_paths - util_ensure_gem_dirs - dirs = @additional + [@gemhome] + [File.join(@tempdir, 'a')] - - ENV['GEM_HOME'] = @gemhome - ENV['GEM_PATH'] = dirs.join File::PATH_SEPARATOR - - assert_equal @gemhome, Gem.dir - - paths = [Gem.dir] - assert_equal @additional + paths, Gem.path - end - - def test_self_path_overlap - Gem.clear_paths - - util_ensure_gem_dirs - ENV['GEM_HOME'] = @gemhome - ENV['GEM_PATH'] = @additional.join(File::PATH_SEPARATOR) - - assert_equal @gemhome, Gem.dir - - paths = [Gem.dir] - assert_equal @additional + paths, Gem.path - end - - def test_self_platforms - assert_equal [Gem::Platform::RUBY, Gem::Platform.local], Gem.platforms - end - - def test_self_prefix - assert_equal PROJECT_DIR, Gem.prefix - end - - def test_self_prefix_libdir - orig_libdir = RbConfig::CONFIG['libdir'] - RbConfig::CONFIG['libdir'] = PROJECT_DIR - - assert_nil Gem.prefix - ensure - RbConfig::CONFIG['libdir'] = orig_libdir - end - - def test_self_prefix_sitelibdir - orig_sitelibdir = RbConfig::CONFIG['sitelibdir'] - RbConfig::CONFIG['sitelibdir'] = PROJECT_DIR - - assert_nil Gem.prefix - ensure - RbConfig::CONFIG['sitelibdir'] = orig_sitelibdir - end - - def test_self_read_binary - File.open 'test', 'w' do |io| - io.write "\xCF\x80" - end - - assert_equal ["\xCF", "\x80"], Gem.read_binary('test').chars.to_a - - pend 'chmod not supported' if Gem.win_platform? - - begin - File.chmod 0444, 'test' - - assert_equal ["\xCF", "\x80"], Gem.read_binary('test').chars.to_a - ensure - File.chmod 0644, 'test' - end - end - - def test_self_refresh - util_make_gems - - a1_spec = @a1.spec_file - moved_path = File.join @tempdir, File.basename(a1_spec) - - FileUtils.mv a1_spec, moved_path - - Gem.refresh - - refute_includes Gem::Specification.all_names, @a1.full_name - - FileUtils.mv moved_path, a1_spec - - Gem.refresh - - assert_includes Gem::Specification.all_names, @a1.full_name - end - - def test_self_refresh_keeps_loaded_specs_activated - util_make_gems - - a1_spec = @a1.spec_file - moved_path = File.join @tempdir, File.basename(a1_spec) - - FileUtils.mv a1_spec, moved_path - - Gem.refresh - - s = Gem::Specification.first - s.activate - - Gem.refresh - - Gem::Specification.each{|spec| assert spec.activated? if spec == s } - - Gem.loaded_specs.delete(s) - Gem.refresh - end - - def test_self_ruby_escaping_spaces_in_path - with_clean_path_to_ruby do - with_rb_config_ruby("C:/Ruby 1.8/bin/ruby.exe") do - assert_equal "\"C:/Ruby 1.8/bin/ruby.exe\"", Gem.ruby - end - end - end - - def test_self_ruby_path_without_spaces - with_clean_path_to_ruby do - with_rb_config_ruby("C:/Ruby18/bin/ruby.exe") do - assert_equal "C:/Ruby18/bin/ruby.exe", Gem.ruby - end - end - end - - def test_self_ruby_api_version - orig_ruby_version, RbConfig::CONFIG['ruby_version'] = RbConfig::CONFIG['ruby_version'], '1.2.3' - - Gem.instance_variable_set :@ruby_api_version, nil - - assert_equal '1.2.3', Gem.ruby_api_version - ensure - Gem.instance_variable_set :@ruby_api_version, nil - - RbConfig::CONFIG['ruby_version'] = orig_ruby_version - end - - def test_self_env_requirement - ENV["GEM_REQUIREMENT_FOO"] = '>= 1.2.3' - ENV["GEM_REQUIREMENT_BAR"] = '1.2.3' - ENV["GEM_REQUIREMENT_BAZ"] = 'abcd' - - assert_equal Gem::Requirement.create('>= 1.2.3'), Gem.env_requirement('foo') - assert_equal Gem::Requirement.create('1.2.3'), Gem.env_requirement('bAr') - assert_raise(Gem::Requirement::BadRequirementError) { Gem.env_requirement('baz') } - assert_equal Gem::Requirement.default, Gem.env_requirement('qux') - end - - def test_self_ruby_version_with_patchlevel_less_ancient_rubies - util_set_RUBY_VERSION '1.8.5' - - assert_equal Gem::Version.new('1.8.5'), Gem.ruby_version - ensure - util_restore_RUBY_VERSION - end - - def test_self_ruby_version_with_release - util_set_RUBY_VERSION '1.8.6', 287 - - assert_equal Gem::Version.new('1.8.6.287'), Gem.ruby_version - ensure - util_restore_RUBY_VERSION - end - - def test_self_ruby_version_with_non_mri_implementations - util_set_RUBY_VERSION '2.5.0', 0, 60928, 'jruby 9.2.0.0 (2.5.0) 2018-05-24 81156a8 OpenJDK 64-Bit Server VM 25.171-b11 on 1.8.0_171-8u171-b11-0ubuntu0.16.04.1-b11 [linux-x86_64]' - - assert_equal Gem::Version.new('2.5.0'), Gem.ruby_version - ensure - util_restore_RUBY_VERSION - end - - def test_self_ruby_version_with_svn_prerelease - util_set_RUBY_VERSION '2.6.0', -1, 63539, 'ruby 2.6.0preview2 (2018-05-31 trunk 63539) [x86_64-linux]' - - assert_equal Gem::Version.new('2.6.0.preview2'), Gem.ruby_version - ensure - util_restore_RUBY_VERSION - end - - def test_self_ruby_version_with_git_prerelease - util_set_RUBY_VERSION '2.7.0', -1, 'b563439274a402e33541f5695b1bfd4ac1085638', 'ruby 2.7.0preview3 (2019-11-23 master b563439274) [x86_64-linux]' - - assert_equal Gem::Version.new('2.7.0.preview3'), Gem.ruby_version - ensure - util_restore_RUBY_VERSION - end - - def test_self_ruby_version_with_non_mri_implementations_with_mri_prerelase_compatibility - util_set_RUBY_VERSION '2.6.0', -1, 63539, 'weirdjruby 9.2.0.0 (2.6.0preview2) 2018-05-24 81156a8 OpenJDK 64-Bit Server VM 25.171-b11 on 1.8.0_171-8u171-b11-0ubuntu0.16.04.1-b11 [linux-x86_64]', 'weirdjruby', '9.2.0.0' - - assert_equal Gem::Version.new('2.6.0.preview2'), Gem.ruby_version - ensure - util_restore_RUBY_VERSION - end - - def test_self_ruby_version_with_svn_trunk - util_set_RUBY_VERSION '1.9.2', -1, 23493, 'ruby 1.9.2dev (2009-05-20 trunk 23493) [x86_64-linux]' - - assert_equal Gem::Version.new('1.9.2.dev'), Gem.ruby_version - ensure - util_restore_RUBY_VERSION - end - - def test_self_ruby_version_with_git_master - util_set_RUBY_VERSION '2.7.0', -1, '5de284ec78220e75643f89b454ce999da0c1c195', 'ruby 2.7.0dev (2019-12-23T01:37:30Z master 5de284ec78) [x86_64-linux]' - - assert_equal Gem::Version.new('2.7.0.dev'), Gem.ruby_version - ensure - util_restore_RUBY_VERSION - end - - def test_self_rubygems_version - assert_equal Gem::Version.new(Gem::VERSION), Gem.rubygems_version - end - - def test_self_paths_eq - other = File.join @tempdir, 'other' - path = [@userhome, other].join File::PATH_SEPARATOR - - # - # FIXME remove after fixing test_case - # - ENV["GEM_HOME"] = @gemhome - Gem.paths = { "GEM_PATH" => path } - - assert_equal [@userhome, other, @gemhome], Gem.path - end - - def test_self_paths_eq_nonexistent_home - ENV['GEM_HOME'] = @gemhome - Gem.clear_paths - - other = File.join @tempdir, 'other' - - ENV['HOME'] = other - - Gem.paths = { "GEM_PATH" => other } - - assert_equal [other, @gemhome], Gem.path - end - - def test_self_post_build - assert_equal 1, Gem.post_build_hooks.length - - Gem.post_build {|installer| } - - assert_equal 2, Gem.post_build_hooks.length - end - - def test_self_post_install - assert_equal 1, Gem.post_install_hooks.length - - Gem.post_install {|installer| } - - assert_equal 2, Gem.post_install_hooks.length - end - - def test_self_done_installing - assert_empty Gem.done_installing_hooks - - Gem.done_installing {|gems| } - - assert_equal 1, Gem.done_installing_hooks.length - end - - def test_self_post_reset - assert_empty Gem.post_reset_hooks - - Gem.post_reset {} - - assert_equal 1, Gem.post_reset_hooks.length - end - - def test_self_post_uninstall - assert_equal 1, Gem.post_uninstall_hooks.length - - Gem.post_uninstall {|installer| } - - assert_equal 2, Gem.post_uninstall_hooks.length - end - - def test_self_pre_install - assert_equal 1, Gem.pre_install_hooks.length - - Gem.pre_install {|installer| } - - assert_equal 2, Gem.pre_install_hooks.length - end - - def test_self_pre_reset - assert_empty Gem.pre_reset_hooks - - Gem.pre_reset {} - - assert_equal 1, Gem.pre_reset_hooks.length - end - - def test_self_pre_uninstall - assert_equal 1, Gem.pre_uninstall_hooks.length - - Gem.pre_uninstall {|installer| } - - assert_equal 2, Gem.pre_uninstall_hooks.length - end - - def test_self_sources - assert_equal %w[http://gems.example.com/], Gem.sources - Gem.sources = nil - Gem.configuration.sources = %w[http://test.example.com/] - assert_equal %w[http://test.example.com/], Gem.sources - end - - def test_try_activate_returns_true_for_activated_specs - b = util_spec 'b', '1.0' do |spec| - spec.files << 'lib/b.rb' - end - install_specs b - - assert Gem.try_activate('b'), 'try_activate should return true' - assert Gem.try_activate('b'), 'try_activate should still return true' - end - - def test_spec_order_is_consistent - b1 = util_spec 'b', '1.0' - b2 = util_spec 'b', '2.0' - b3 = util_spec 'b', '3.0' - - install_specs b1, b2, b3 - - specs1 = Gem::Specification.stubs.find_all {|s| s.name == 'b' } - Gem::Specification.reset - specs2 = Gem::Specification.stubs_for('b') - assert_equal specs1.map(&:version), specs2.map(&:version) - end - - def test_self_try_activate_missing_dep - b = util_spec 'b', '1.0' - a = util_spec 'a', '1.0', 'b' => '>= 1.0' - - install_specs b, a - uninstall_gem b - - a_file = File.join a.gem_dir, 'lib', 'a_file.rb' - - write_file a_file do |io| - io.puts '# a_file.rb' - end - - e = assert_raise Gem::MissingSpecError do - Gem.try_activate 'a_file' - end - - assert_match %r{Could not find 'b' }, e.message - assert_match %r{at: #{a.spec_file}}, e.message - end - - def test_self_try_activate_missing_prerelease - b = util_spec 'b', '1.0rc1' - a = util_spec 'a', '1.0rc1', 'b' => '1.0rc1' - - install_specs b, a - uninstall_gem b - - a_file = File.join a.gem_dir, 'lib', 'a_file.rb' - - write_file a_file do |io| - io.puts '# a_file.rb' - end - - e = assert_raise Gem::MissingSpecError do - Gem.try_activate 'a_file' - end - - assert_match %r{Could not find 'b' \(= 1.0rc1\)}, e.message - end - - def test_self_try_activate_missing_extensions - spec = util_spec 'ext', '1' do |s| - s.extensions = %w[ext/extconf.rb] - s.mark_version - s.installed_by_version = v('2.2') - end - - # write the spec without install to simulate a failed install - write_file spec.spec_file do |io| - io.write spec.to_ruby_for_cache - end - - _, err = capture_output do - refute Gem.try_activate 'nonexistent' - end - - unless Gem.java_platform? - expected = "Ignoring ext-1 because its extensions are not built. " + - "Try: gem pristine ext --version 1\n" - - assert_equal expected, err - end - end - - def test_self_use_paths_with_nils - orig_home = ENV.delete 'GEM_HOME' - orig_path = ENV.delete 'GEM_PATH' - Gem.use_paths nil, nil - assert_equal Gem.default_dir, Gem.paths.home - path = (Gem.default_path + [Gem.paths.home]).uniq - assert_equal path, Gem.paths.path - ensure - ENV['GEM_HOME'] = orig_home - ENV['GEM_PATH'] = orig_path - end - - def test_setting_paths_does_not_warn_about_unknown_keys - stdout, stderr = capture_output do - Gem.paths = { 'foo' => [], - 'bar' => Object.new, - 'GEM_HOME' => Gem.paths.home, - 'GEM_PATH' => 'foo' } - end - assert_equal ['foo', Gem.paths.home], Gem.paths.path - assert_equal '', stderr - assert_equal '', stdout - end - - def test_setting_paths_does_not_mutate_parameter_object - Gem.paths = { 'GEM_HOME' => Gem.paths.home, - 'GEM_PATH' => 'foo' }.freeze - assert_equal ['foo', Gem.paths.home], Gem.paths.path - end - - def test_deprecated_paths= - stdout, stderr = capture_output do - Gem.paths = { 'GEM_HOME' => Gem.paths.home, - 'GEM_PATH' => [Gem.paths.home, 'foo'] } - end - assert_equal [Gem.paths.home, 'foo'], Gem.paths.path - assert_match(/Array values in the parameter to `Gem.paths=` are deprecated.\nPlease use a String or nil/m, stderr) - assert_equal '', stdout - end - - def test_self_use_paths - util_ensure_gem_dirs - - Gem.use_paths @gemhome, @additional - - assert_equal @gemhome, Gem.dir - assert_equal @additional + [Gem.dir], Gem.path - end - - def test_self_user_dir - parts = [@userhome, '.gem', Gem.ruby_engine] - parts << RbConfig::CONFIG['ruby_version'] unless RbConfig::CONFIG['ruby_version'].empty? - - FileUtils.mkdir_p File.join(parts) - - assert_equal File.join(parts), Gem.user_dir - end - - def test_self_user_home - if ENV['HOME'] - assert_equal ENV['HOME'], Gem.user_home - else - assert true, 'count this test' - end - end - - def test_self_needs - a = util_spec "a", "1" - b = util_spec "b", "1", "c" => nil - c = util_spec "c", "2" - - install_specs a, c, b - - Gem.needs do |r| - r.gem "a" - r.gem "b", "= 1" - end - - activated = Gem::Specification.map {|x| x.full_name } - - assert_equal %w[a-1 b-1 c-2], activated.sort - end - - def test_self_needs_picks_up_unresolved_deps - a = util_spec "a", "1" - b = util_spec "b", "1", "c" => nil - c = util_spec "c", "2" - d = util_spec "d", "1", {'e' => '= 1'}, "lib/d#{$$}.rb" - e = util_spec "e", "1" - - install_specs a, c, b, e, d - - Gem.needs do |r| - r.gem "a" - r.gem "b", "= 1" - - require "d#{$$}" - end - - assert_equal %w[a-1 b-1 c-2 d-1 e-1], loaded_spec_names - end - - def test_self_gunzip - input = "\x1F\x8B\b\0\xED\xA3\x1AQ\0\x03\xCBH" + - "\xCD\xC9\xC9\a\0\x86\xA6\x106\x05\0\0\0" - - output = Gem::Util.gunzip input - - assert_equal 'hello', output - assert_equal Encoding::BINARY, output.encoding - end - - def test_self_gzip - input = 'hello' - - output = Gem::Util.gzip input - - zipped = StringIO.new output - - assert_equal 'hello', Zlib::GzipReader.new(zipped).read - assert_equal Encoding::BINARY, output.encoding - end - - def test_self_vendor_dir - vendordir(File.join(@tempdir, 'vendor')) do - expected = - File.join RbConfig::CONFIG['vendordir'], 'gems', - RbConfig::CONFIG['ruby_version'] - - assert_equal expected, Gem.vendor_dir - end - end - - def test_self_vendor_dir_ENV_GEM_VENDOR - ENV['GEM_VENDOR'] = File.join @tempdir, 'vendor', 'gems' - - assert_equal ENV['GEM_VENDOR'], Gem.vendor_dir - refute Gem.vendor_dir.frozen? - end - - def test_self_vendor_dir_missing - vendordir(nil) do - assert_nil Gem.vendor_dir - end - end - - def test_load_plugins - plugin_path = File.join "lib", "rubygems_plugin.rb" - - Dir.chdir @tempdir do - FileUtils.mkdir_p 'lib' - File.open plugin_path, "w" do |fp| - fp.puts "class TestGem; PLUGINS_LOADED << 'plugin'; end" - end - - foo1 = util_spec 'foo', '1' do |s| - s.files << plugin_path - end - - install_gem foo1 - - foo2 = util_spec 'foo', '2' do |s| - s.files << plugin_path - end - - install_gem foo2 - end - - Gem::Specification.reset - - gem 'foo' - - Gem.load_plugins - - assert_equal %w[plugin], PLUGINS_LOADED - end - - def test_load_user_installed_plugins - plugin_path = File.join "lib", "rubygems_plugin.rb" - - Dir.chdir @tempdir do - FileUtils.mkdir_p 'lib' - File.open plugin_path, "w" do |fp| - fp.puts "class TestGem; PLUGINS_LOADED << 'plugin'; end" - end - - foo = util_spec 'foo', '1' do |s| - s.files << plugin_path - end - - install_gem_user foo - end - - Gem.paths = { "GEM_PATH" => [Gem.dir, Gem.user_dir].join(File::PATH_SEPARATOR) } - - gem 'foo' - - Gem.load_plugins - - assert_equal %w[plugin], PLUGINS_LOADED - end - - def test_load_env_plugins - with_plugin('load') { Gem.load_env_plugins } - assert_equal :loaded, TEST_PLUGIN_LOAD rescue nil - - util_remove_interrupt_command - - # Should attempt to cause a StandardError - with_plugin('standarderror') { Gem.load_env_plugins } - assert_equal :loaded, TEST_PLUGIN_STANDARDERROR rescue nil - - util_remove_interrupt_command - - # Should attempt to cause an Exception - with_plugin('exception') { Gem.load_env_plugins } - assert_equal :loaded, TEST_PLUGIN_EXCEPTION rescue nil - end - - def test_gem_path_ordering - refute_equal Gem.dir, Gem.user_dir - - write_file File.join(@tempdir, 'lib', "g.rb") {|fp| fp.puts "" } - write_file File.join(@tempdir, 'lib', 'm.rb') {|fp| fp.puts "" } - - g = util_spec 'g', '1', nil, "lib/g.rb" - m = util_spec 'm', '1', nil, "lib/m.rb" - - install_gem g, :install_dir => Gem.dir - m0 = install_gem m, :install_dir => Gem.dir - m1 = install_gem m, :install_dir => Gem.user_dir - - assert_equal m0.gem_dir, File.join(Gem.dir, "gems", "m-1") - assert_equal m1.gem_dir, File.join(Gem.user_dir, "gems", "m-1") - - tests = [ - [:dir0, [ Gem.dir, Gem.user_dir], m0], - [:dir1, [ Gem.user_dir, Gem.dir], m1], - ] - - tests.each do |_name, _paths, expected| - Gem.use_paths _paths.first, _paths - Gem::Specification.reset - Gem.searcher = nil - - assert_equal Gem::Dependency.new('m','1').to_specs, - Gem::Dependency.new('m','1').to_specs.sort - - assert_equal \ - [expected.gem_dir], - Gem::Dependency.new('m','1').to_specs.map(&:gem_dir).sort, - "Wrong specs for #{_name}" - - spec = Gem::Dependency.new('m','1').to_spec - - assert_equal \ - File.join(_paths.first, "gems", "m-1"), - spec.gem_dir, - "Wrong spec before require for #{_name}" - refute spec.activated?, "dependency already activated for #{_name}" - - gem "m" - - spec = Gem::Dependency.new('m','1').to_spec - assert spec.activated?, "dependency not activated for #{_name}" - - assert_equal \ - File.join(_paths.first, "gems", "m-1"), - spec.gem_dir, - "Wrong spec after require for #{_name}" - - spec.instance_variable_set :@activated, false - Gem.loaded_specs.delete(spec.name) - $:.delete(File.join(spec.gem_dir, "lib")) - end - end - - def test_gem_path_ordering_short - write_file File.join(@tempdir, 'lib', "g.rb") {|fp| fp.puts "" } - write_file File.join(@tempdir, 'lib', 'm.rb') {|fp| fp.puts "" } - - g = util_spec 'g', '1', nil, "lib/g.rb" - m = util_spec 'm', '1', nil, "lib/m.rb" - - install_gem g, :install_dir => Gem.dir - install_gem m, :install_dir => Gem.dir - install_gem m, :install_dir => Gem.user_dir - - Gem.use_paths Gem.dir, [ Gem.dir, Gem.user_dir] - - assert_equal \ - File.join(Gem.dir, "gems", "m-1"), - Gem::Dependency.new('m','1').to_spec.gem_dir, - "Wrong spec selected" - end - - def test_auto_activation_of_specific_gemdeps_file - a = util_spec "a", "1", nil, "lib/a.rb" - b = util_spec "b", "1", nil, "lib/b.rb" - c = util_spec "c", "1", nil, "lib/c.rb" - - install_specs a, b, c - - path = File.join @tempdir, "gem.deps.rb" - - File.open path, "w" do |f| - f.puts "gem 'a'" - f.puts "gem 'b'" - f.puts "gem 'c'" - end - - with_rubygems_gemdeps(path) do - Gem.use_gemdeps - - assert_equal add_bundler_full_name(%W[a-1 b-1 c-1]), loaded_spec_names - end - end - - def test_auto_activation_of_used_gemdeps_file - a = util_spec "a", "1", nil, "lib/a.rb" - b = util_spec "b", "1", nil, "lib/b.rb" - c = util_spec "c", "1", nil, "lib/c.rb" - - install_specs a, b, c - - path = File.join @tempdir, "gem.deps.rb" - - File.open path, "w" do |f| - f.puts "gem 'a'" - f.puts "gem 'b'" - f.puts "gem 'c'" - end - - with_rubygems_gemdeps("-") do - expected_specs = [a, b, util_spec("bundler", Bundler::VERSION), c].compact.map(&:full_name) - - Gem.use_gemdeps - - assert_equal expected_specs, loaded_spec_names - end - end - - BUNDLER_LIB_PATH = File.expand_path $LOAD_PATH.find {|lp| File.file?(File.join(lp, "bundler.rb")) } - BUNDLER_FULL_NAME = "bundler-#{Bundler::VERSION}".freeze - - def add_bundler_full_name(names) - names << BUNDLER_FULL_NAME - names.sort! - names - end - - def test_looks_for_gemdeps_files_automatically_from_binstubs - pend "Requiring bundler messes things up" if Gem.java_platform? - - a = util_spec "a", "1" do |s| - s.executables = %w[foo] - s.bindir = "exe" - end - - write_file File.join(@tempdir, 'exe', 'foo') do |fp| - fp.puts "puts Gem.loaded_specs.values.map(&:full_name).sort" - end - - b = util_spec "b", "1", nil, "lib/b.rb" - c = util_spec "c", "1", nil, "lib/c.rb" - - install_specs a, b, c - - path = File.join(@tempdir, "gd-tmp") - install_gem a, :install_dir => path - install_gem b, :install_dir => path - install_gem c, :install_dir => path - - ENV['GEM_PATH'] = path - - with_rubygems_gemdeps("-") do - new_PATH = [File.join(path, "bin"), ENV["PATH"]].join(File::PATH_SEPARATOR) - new_RUBYOPT = "-I#{rubygems_path} -I#{BUNDLER_LIB_PATH}" - - path = File.join @tempdir, "gem.deps.rb" - - File.open path, "w" do |f| - f.puts "gem 'a'" - end - out0 = with_path_and_rubyopt(new_PATH, new_RUBYOPT) do - IO.popen("foo", &:read).split(/\n/) - end - - File.open path, "a" do |f| - f.puts "gem 'b'" - f.puts "gem 'c'" - end - out = with_path_and_rubyopt(new_PATH, new_RUBYOPT) do - IO.popen("foo", &:read).split(/\n/) - end - - assert_equal ["b-1", "c-1"], out - out0 - end - end - - def test_looks_for_gemdeps_files_automatically_from_binstubs_in_parent_dir - pend "Requiring bundler messes things up" if Gem.java_platform? - - a = util_spec "a", "1" do |s| - s.executables = %w[foo] - s.bindir = "exe" - end - - write_file File.join(@tempdir, 'exe', 'foo') do |fp| - fp.puts "puts Gem.loaded_specs.values.map(&:full_name).sort" - end - - b = util_spec "b", "1", nil, "lib/b.rb" - c = util_spec "c", "1", nil, "lib/c.rb" - - install_specs a, b, c - - path = File.join(@tempdir, "gd-tmp") - install_gem a, :install_dir => path - install_gem b, :install_dir => path - install_gem c, :install_dir => path - - ENV['GEM_PATH'] = path - - with_rubygems_gemdeps("-") do - Dir.mkdir "sub1" - - new_PATH = [File.join(path, "bin"), ENV["PATH"]].join(File::PATH_SEPARATOR) - new_RUBYOPT = "-I#{rubygems_path} -I#{BUNDLER_LIB_PATH}" - - path = File.join @tempdir, "gem.deps.rb" - - File.open path, "w" do |f| - f.puts "gem 'a'" - end - out0 = with_path_and_rubyopt(new_PATH, new_RUBYOPT) do - IO.popen("foo", :chdir => "sub1", &:read).split(/\n/) - end - - File.open path, "a" do |f| - f.puts "gem 'b'" - f.puts "gem 'c'" - end - out = with_path_and_rubyopt(new_PATH, new_RUBYOPT) do - IO.popen("foo", :chdir => "sub1", &:read).split(/\n/) - end - - Dir.rmdir "sub1" - - assert_equal ["b-1", "c-1"], out - out0 - end - end - - def test_register_default_spec - Gem.clear_default_specs - - old_style = Gem::Specification.new do |spec| - spec.files = ["foo.rb", "bar.rb"] - end - - Gem.register_default_spec old_style - - assert_equal old_style, Gem.find_unresolved_default_spec("foo.rb") - assert_equal old_style, Gem.find_unresolved_default_spec("bar.rb") - assert_nil Gem.find_unresolved_default_spec("baz.rb") - - Gem.clear_default_specs - - new_style = Gem::Specification.new do |spec| - spec.files = ["lib/foo.rb", "ext/bar.rb", "bin/exec", "README"] - spec.require_paths = ["lib", "ext"] - end - - Gem.register_default_spec new_style - - assert_equal new_style, Gem.find_unresolved_default_spec("foo.rb") - assert_equal new_style, Gem.find_unresolved_default_spec("bar.rb") - assert_nil Gem.find_unresolved_default_spec("exec") - assert_nil Gem.find_unresolved_default_spec("README") - end - - def test_register_default_spec_old_style_with_folder_starting_with_lib - Gem.clear_default_specs - - old_style = Gem::Specification.new do |spec| - spec.files = ["libexec/bundle", "foo.rb", "bar.rb"] - end - - Gem.register_default_spec old_style - - assert_equal old_style, Gem.find_unresolved_default_spec("foo.rb") - end - - def test_use_gemdeps - gem_deps_file = 'gem.deps.rb'.tap(&Gem::UNTAINT) - spec = util_spec 'a', 1 - install_specs spec - - spec = Gem::Specification.find {|s| s == spec } - refute spec.activated? - - File.open gem_deps_file, 'w' do |io| - io.write 'gem "a"' - end - - assert_nil Gem.gemdeps - - Gem.use_gemdeps gem_deps_file - - assert_equal add_bundler_full_name(%W[a-1]), loaded_spec_names - refute_nil Gem.gemdeps - end - - def test_use_gemdeps_ENV - with_rubygems_gemdeps(nil) do - spec = util_spec 'a', 1 - - refute spec.activated? - - File.open 'gem.deps.rb', 'w' do |io| - io.write 'gem "a"' - end - - Gem.use_gemdeps - - refute spec.activated? - end - end - - def test_use_gemdeps_argument_missing - e = assert_raise ArgumentError do - Gem.use_gemdeps 'gem.deps.rb' - end - - assert_equal 'Unable to find gem dependencies file at gem.deps.rb', - e.message - end - - def test_use_gemdeps_argument_missing_match_ENV - with_rubygems_gemdeps('gem.deps.rb') do - e = assert_raise ArgumentError do - Gem.use_gemdeps 'gem.deps.rb' - end - - assert_equal 'Unable to find gem dependencies file at gem.deps.rb', - e.message - end - end - - def test_use_gemdeps_automatic - with_rubygems_gemdeps('-') do - spec = util_spec 'a', 1 - install_specs spec - spec = Gem::Specification.find {|s| s == spec } - - refute spec.activated? - - File.open 'Gemfile', 'w' do |io| - io.write 'gem "a"' - end - - Gem.use_gemdeps - - assert_equal add_bundler_full_name(%W[a-1]), loaded_spec_names - end - end - - def test_use_gemdeps_automatic_missing - with_rubygems_gemdeps('-') do - Gem.use_gemdeps - - assert true # count - end - end - - def test_use_gemdeps_disabled - with_rubygems_gemdeps('') do - spec = util_spec 'a', 1 - - refute spec.activated? - - File.open 'gem.deps.rb', 'w' do |io| - io.write 'gem "a"' - end - - Gem.use_gemdeps - - refute spec.activated? - end - end - - def test_use_gemdeps_missing_gem - with_rubygems_gemdeps('x') do - File.open 'x', 'w' do |io| - io.write 'gem "a"' - end - - expected = <<-EXPECTED -Could not find gem 'a' in locally installed gems. -You may need to `bundle install` to install missing gems - - EXPECTED - - Gem::Deprecate.skip_during do - actual_stdout, actual_stderr = capture_output do - Gem.use_gemdeps - end - assert_empty actual_stdout - assert_equal(expected, actual_stderr) - end - end - end - - def test_use_gemdeps_specific - with_rubygems_gemdeps('x') do - spec = util_spec 'a', 1 - install_specs spec - - spec = Gem::Specification.find {|s| s == spec } - refute spec.activated? - - File.open 'x', 'w' do |io| - io.write 'gem "a"' - end - - Gem.use_gemdeps - - assert_equal add_bundler_full_name(%W[a-1]), loaded_spec_names - end - end - - def test_operating_system_defaults - operating_system_defaults = Gem.operating_system_defaults - - assert operating_system_defaults != nil - assert operating_system_defaults.is_a? Hash - end - - def test_platform_defaults - platform_defaults = Gem.platform_defaults - - assert platform_defaults != nil - assert platform_defaults.is_a? Hash - end - - # Ensure that `Gem.source_date_epoch` is consistent even if - # $SOURCE_DATE_EPOCH has not been set. - def test_default_source_date_epoch_doesnt_change - old_epoch = ENV['SOURCE_DATE_EPOCH'] - ENV['SOURCE_DATE_EPOCH'] = nil - - # Unfortunately, there is no real way to test this aside from waiting - # enough for `Time.now.to_i` to change -- which is a whole second. - # - # Fortunately, we only need to do this once. - a = Gem.source_date_epoch - sleep 1 - b = Gem.source_date_epoch - assert_equal a, b - ensure - ENV['SOURCE_DATE_EPOCH'] = old_epoch - end - - def ruby_install_name(name) - with_clean_path_to_ruby do - orig_RUBY_INSTALL_NAME = RbConfig::CONFIG['ruby_install_name'] - RbConfig::CONFIG['ruby_install_name'] = name - - begin - yield - ensure - if orig_RUBY_INSTALL_NAME - RbConfig::CONFIG['ruby_install_name'] = orig_RUBY_INSTALL_NAME - else - RbConfig::CONFIG.delete 'ruby_install_name' - end - end - end - end - - def with_rb_config_ruby(path) - rb_config_singleton_class = class << RbConfig; self; end - orig_path = RbConfig.ruby - - redefine_method(rb_config_singleton_class, :ruby, path) - - yield - ensure - redefine_method(rb_config_singleton_class, :ruby, orig_path) - end - - def redefine_method(base, method, new_result) - if RUBY_VERSION >= "2.5" - base.alias_method(method, method) - base.define_method(method) { new_result } - else - base.send(:alias_method, method, method) - base.send(:define_method, method) { new_result } - end - end - - def with_plugin(path) - test_plugin_path = File.expand_path("test/rubygems/plugin/#{path}", - PROJECT_DIR) - - # A single test plugin should get loaded once only, in order to preserve - # sane test semantics. - refute_includes $LOAD_PATH, test_plugin_path - $LOAD_PATH.unshift test_plugin_path - - capture_output do - yield - end - ensure - $LOAD_PATH.delete test_plugin_path - end - - def util_ensure_gem_dirs - Gem.ensure_gem_subdirectories @gemhome - - # - # FIXME what does this solve precisely? -ebh - # - @additional.each do |dir| - Gem.ensure_gem_subdirectories @gemhome - end - end - - def util_exec_gem - spec, _ = util_spec 'a', '4' do |s| - s.executables = ['exec', 'abin'] - end - - @exec_path = File.join spec.full_gem_path, spec.bindir, 'exec' - @abin_path = File.join spec.full_gem_path, spec.bindir, 'abin' - spec - end - - def util_remove_interrupt_command - Gem::Commands.send :remove_const, :InterruptCommand if - Gem::Commands.const_defined? :InterruptCommand - end - - def util_cache_dir - File.join Gem.dir, "cache" - end - - def with_path_and_rubyopt(path_value, rubyopt_value) - path, ENV['PATH'] = ENV['PATH'], path_value - rubyopt, ENV['RUBYOPT'] = ENV['RUBYOPT'], rubyopt_value - - yield - ensure - ENV['PATH'] = path - ENV['RUBYOPT'] = rubyopt - end - - def with_rubygems_gemdeps(value) - rubygems_gemdeps, ENV['RUBYGEMS_GEMDEPS'] = ENV['RUBYGEMS_GEMDEPS'], value - - yield - ensure - ENV['RUBYGEMS_GEMDEPS'] = rubygems_gemdeps - end -end From 099f1b77f0b74f34a6ddd72d71fe9be305c9e7d9 Mon Sep 17 00:00:00 2001 From: Philippe Ombredanne Date: Mon, 6 Dec 2021 10:48:03 +0100 Subject: [PATCH 684/707] Add license and copyright notice Signed-off-by: Philippe Ombredanne --- tests/test_bundler_version_ranges_spec.py | 10 +++++++++- tests/test_rubygems_gem_version.py | 10 +++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/tests/test_bundler_version_ranges_spec.py b/tests/test_bundler_version_ranges_spec.py index bca044b0..aa84a391 100644 --- a/tests/test_bundler_version_ranges_spec.py +++ b/tests/test_bundler_version_ranges_spec.py @@ -1,4 +1,12 @@ -# frozen_string_literal: true + +# +# Copyright (c) Chad Fowler, Rich Kilmer, Jim Weirich and others. +# Portions copyright (c) Engine Yard and Andre ArkoFacebook, Inc. and its affiliates. +# +# SPDX-License-Identifier: MIT +# +# Originally from https://github.com/rubygems/rubygems + require "bundler/version_ranges" diff --git a/tests/test_rubygems_gem_version.py b/tests/test_rubygems_gem_version.py index 422e1ee8..084377a6 100644 --- a/tests/test_rubygems_gem_version.py +++ b/tests/test_rubygems_gem_version.py @@ -1,4 +1,12 @@ -# frozen_string_literal: true + +# +# Copyright (c) Chad Fowler, Rich Kilmer, Jim Weirich and others. +# Portions copyright (c) Engine Yard and Andre ArkoFacebook, Inc. and its affiliates. +# +# SPDX-License-Identifier: MIT +# +# Originally from https://github.com/rubygems/rubygems + require_relative 'helper' require "rubygems/version" From f4397172b1f05b57bb05bc30427e78409f8664c4 Mon Sep 17 00:00:00 2001 From: Philippe Ombredanne Date: Mon, 6 Dec 2021 11:35:48 +0100 Subject: [PATCH 685/707] Port to Python Signed-off-by: Philippe Ombredanne --- tests/test_rubygems_gem_version.py | 472 +++++++++++++---------------- 1 file changed, 215 insertions(+), 257 deletions(-) diff --git a/tests/test_rubygems_gem_version.py b/tests/test_rubygems_gem_version.py index 084377a6..62d4113a 100644 --- a/tests/test_rubygems_gem_version.py +++ b/tests/test_rubygems_gem_version.py @@ -7,293 +7,251 @@ # # Originally from https://github.com/rubygems/rubygems -require_relative 'helper' -require "rubygems/version" - -class TestGemVersion < Gem::TestCase - class V < ::Gem::Version - end - - def test_bump - assert_bumped_version_equal "5.3", "5.2.4" - end - - def test_bump_alpha - assert_bumped_version_equal "5.3", "5.2.4.a" - end - - def test_bump_alphanumeric - assert_bumped_version_equal "5.3", "5.2.4.a10" - end - - def test_bump_trailing_zeros - assert_bumped_version_equal "5.1", "5.0.0" - end - - def test_bump_one_level - assert_bumped_version_equal "6", "5" - end - - # A Gem::Version is already a Gem::Version and therefore not transformed by - # Gem::Version.create - - def test_class_create - real = Gem::Version.new(1.0) - - assert_same real, Gem::Version.create(real) - assert_nil Gem::Version.create(nil) - assert_equal v("5.1"), Gem::Version.create("5.1") - - ver = '1.1'.freeze - assert_equal v('1.1'), Gem::Version.create(ver) - end - - def test_class_correct - assert_equal true, Gem::Version.correct?("5.1") - assert_equal false, Gem::Version.correct?("an incorrect version") - - expected = "nil versions are discouraged and will be deprecated in Rubygems 4\n" - actual_stdout, actual_stderr = capture_output do - Gem::Version.correct?(nil) - end - assert_empty actual_stdout - assert_equal(expected, actual_stderr) - end - - def test_class_new_subclass - v1 = Gem::Version.new '1' - v2 = V.new '1' - - refute_same v1, v2 - end - - def test_eql_eh - assert_version_eql "1.2", "1.2" - refute_version_eql "1.2", "1.2.0" - refute_version_eql "1.2", "1.3" - refute_version_eql "1.2.b1", "1.2.b.1" - end - - def test_equals2 - assert_version_equal "1.2", "1.2" - refute_version_equal "1.2", "1.3" - assert_version_equal "1.2.b1", "1.2.b.1" - end +from univers.gem import GemVersion + + +def assert_equal(expected, result): + assert result == expected + + +def assert_bumped_version_equal(expected, unbumped): + # Assert that bumping the +unbumped+ version yields the +expected+. + + assert_version_equal(expected, GemVersion(unbumped).bump()) + + +def test_bump(): + assert_bumped_version_equal("5.3", "5.2.4") + + +def test_bump_alpha(): + assert_bumped_version_equal("5.3", "5.2.4.a") + + +def test_bump_alphanumeric(): + assert_bumped_version_equal("5.3", "5.2.4.a10") + + +def test_bump_trailing_zeros(): + assert_bumped_version_equal("5.1", "5.0.0") + + +def test_bump_one_level(): + assert_bumped_version_equal("6", "5") + + +def test_eql_eh(): + assert_version_eql("1.2", "1.2") + refute_version_eql("1.2", "1.2.0") + refute_version_eql("1.2", "1.3") + refute_version_eql("1.2.b1", "1.2.b.1") + + +def test_equals2(): + assert_version_equal("1.2", "1.2") + refute_version_equal("1.2", "1.3") + assert_version_equal("1.2.b1", "1.2.b.1") + # REVISIT: consider removing as too impl-bound - def test_hash - assert_equal v("1.2").hash, v("1.2").hash - refute_equal v("1.2").hash, v("1.3").hash - assert_equal v("1.2").hash, v("1.2.0").hash - assert_equal v("1.2.pre.1").hash, v("1.2.0.pre.1.0").hash - end - - def test_initialize - ["1.0", "1.0 ", " 1.0 ", "1.0\n", "\n1.0\n", "1.0".freeze].each do |good| - assert_version_equal "1.0", good - end - - assert_version_equal "1", 1 - end - - def test_initialize_invalid - invalid_versions = %W[ - junk - 1.0\n2.0 - 1..2 - 1.2\ 3.4 - ] - - # DON'T TOUCH THIS WITHOUT CHECKING CVE-2013-4287 - invalid_versions << "2.3422222.222.222222222.22222.ads0as.dasd0.ddd2222.2.qd3e." - - invalid_versions.each do |invalid| - e = assert_raise ArgumentError, invalid do - Gem::Version.new invalid - end - - assert_equal "Malformed version number string #{invalid}", e.message, invalid - end - end - - def test_empty_version - ["", " ", " "].each do |empty| - assert_equal "0", Gem::Version.new(empty).version - end - end - - def test_prerelease - assert_prerelease "1.2.0.a" - assert_prerelease "2.9.b" - assert_prerelease "22.1.50.0.d" - assert_prerelease "1.2.d.42" - - assert_prerelease '1.A' - - assert_prerelease '1-1' - assert_prerelease '1-a' - - refute_prerelease "1.2.0" - refute_prerelease "2.9" - refute_prerelease "22.1.50.0" - end - - def test_release - assert_release_equal "1.2.0", "1.2.0.a" - assert_release_equal "1.1", "1.1.rc10" - assert_release_equal "1.9.3", "1.9.3.alpha.5" - assert_release_equal "1.9.3", "1.9.3" - end - - def test_spaceship - assert_equal(0, v("1.0") <=> v("1.0.0")) - assert_equal(1, v("1.0") <=> v("1.0.a")) - assert_equal(1, v("1.8.2") <=> v("0.0.0")) - assert_equal(1, v("1.8.2") <=> v("1.8.2.a")) - assert_equal(1, v("1.8.2.b") <=> v("1.8.2.a")) - assert_equal(-1, v("1.8.2.a") <=> v("1.8.2")) - assert_equal(1, v("1.8.2.a10") <=> v("1.8.2.a9")) - assert_equal(0, v("") <=> v("0")) - - assert_equal(0, v("0.beta.1") <=> v("0.0.beta.1")) - assert_equal(-1, v("0.0.beta") <=> v("0.0.beta.1")) - assert_equal(-1, v("0.0.beta") <=> v("0.beta.1")) - - assert_equal(-1, v("5.a") <=> v("5.0.0.rc2")) - assert_equal(1, v("5.x") <=> v("5.0.0.rc2")) - - assert_nil v("1.0") <=> "whatever" - end - - def test_approximate_recommendation - assert_approximate_equal "~> 1.0", "1" - assert_approximate_satisfies_itself "1" - - assert_approximate_equal "~> 1.0", "1.0" - assert_approximate_satisfies_itself "1.0" - - assert_approximate_equal "~> 1.2", "1.2" - assert_approximate_satisfies_itself "1.2" - - assert_approximate_equal "~> 1.2", "1.2.0" - assert_approximate_satisfies_itself "1.2.0" - - assert_approximate_equal "~> 1.2", "1.2.3" - assert_approximate_satisfies_itself "1.2.3" - - assert_approximate_equal "~> 1.2.a", "1.2.3.a.4" - assert_approximate_satisfies_itself "1.2.3.a.4" - - assert_approximate_equal "~> 1.9.a", "1.9.0.dev" - assert_approximate_satisfies_itself "1.9.0.dev" - end - - def test_to_s - assert_equal "5.2.4", v("5.2.4").to_s - end - - def test_semver - assert_less_than "1.0.0-alpha", "1.0.0-alpha.1" - assert_less_than "1.0.0-alpha.1", "1.0.0-beta.2" - assert_less_than "1.0.0-beta.2", "1.0.0-beta.11" - assert_less_than "1.0.0-beta.11", "1.0.0-rc.1" - assert_less_than "1.0.0-rc1", "1.0.0" - assert_less_than "1.0.0-1", "1" - end +def test_hash(): + assert GemVersion("1.2").hash == GemVersion("1.2").hash + assert GemVersion("1.2").hash != GemVersion("1.3").hash + assert GemVersion("1.2").hash == GemVersion("1.2.0").hash + assert GemVersion("1.2.pre.1").hash == GemVersion("1.2.0.pre.1.0").hash + + +def test_initialize(): + for good in ["1.0", "1.0 ", " 1.0 ", "1.0\n", "\n1.0\n", "1.0"]: + assert_version_equal("1.0", good) + + assert_version_equal("1", 1) + + +def test_initialize_invalid(): + invalid_versions = [ + "junk", + "1.0\n2.0" + "1..2", + "1.2\ 3.4", + ] + + # DON'T TOUCH THIS WITHOUT CHECKING CVE-2013-4287 + invalid_versions += ["2.3422222.222.222222222.22222.ads0as.dasd0.ddd2222.2.qd3e."] + + for invalid in invalid_versions: + try: + GemVersion(invalid) + raise Exception("exception not raised") + except ValueError: + pass + + +def test_empty_version(): + for empty in ["", " ", " "]: + assert_equal("0", GemVersion(empty).version) + + +def test_prerelease(): + assert_prerelease("1.2.0.a") + assert_prerelease("2.9.b") + assert_prerelease("22.1.50.0.d") + assert_prerelease("1.2.d.42") + + assert_prerelease('1.A') + + assert_prerelease('1-1') + assert_prerelease('1-a') + + refute_prerelease("1.2.0") + refute_prerelease("2.9") + refute_prerelease("22.1.50.0") + +def test_release(): + assert_release_equal("1.2.0", "1.2.0.a") + assert_release_equal("1.1", "1.1.rc10") + assert_release_equal("1.9.3", "1.9.3.alpha.5") + assert_release_equal("1.9.3", "1.9.3") + + +def test_spaceship(): + + def cmp(a, b): + return a.__cmp__(b) + + # Ruby spaceship <=> is the same as Python legacy cmp() + assert_equal(0, cmp(GemVersion("1.0") , GemVersion("1.0.0"))) + assert_equal(1, cmp(GemVersion("1.0") , GemVersion("1.0.a"))) + assert_equal(1, cmp(GemVersion("1.8.2") , GemVersion("0.0.0"))) + assert_equal(1, cmp(GemVersion("1.8.2") , GemVersion("1.8.2.a"))) + assert_equal(1, cmp(GemVersion("1.8.2.b") , GemVersion("1.8.2.a"))) + assert_equal(-1, cmp(GemVersion("1.8.2.a") , GemVersion("1.8.2"))) + assert_equal(1, cmp(GemVersion("1.8.2.a10") , GemVersion("1.8.2.a9"))) + assert_equal(0, cmp(GemVersion("") , GemVersion("0"))) + + assert_equal(0, cmp(GemVersion("0.beta.1") , GemVersion("0.0.beta.1"))) + assert_equal(-1, cmp(GemVersion("0.0.beta") , GemVersion("0.0.beta.1"))) + assert_equal(-1, cmp(GemVersion("0.0.beta") , GemVersion("0.beta.1"))) + + assert_equal(-1, cmp(GemVersion("5.a") , GemVersion("5.0.0.rc2"))) + assert_equal(1, cmp(GemVersion("5.x") , GemVersion("5.0.0.rc2"))) + + assert_nil(cmp(GemVersion("1.0") , "whatever")) + + +def test_approximate_recommendation(): + assert_approximate_equal("~> 1.0", "1") + assert_approximate_satisfies_itself("1") + + assert_approximate_equal("~> 1.0", "1.0") + assert_approximate_satisfies_itself("1.0") + + assert_approximate_equal("~> 1.2", "1.2") + assert_approximate_satisfies_itself("1.2") + + assert_approximate_equal("~> 1.2", "1.2.0") + assert_approximate_satisfies_itself("1.2.0") + + assert_approximate_equal("~> 1.2", "1.2.3") + assert_approximate_satisfies_itself("1.2.3") + + assert_approximate_equal("~> 1.2.a", "1.2.3.a.4") + assert_approximate_satisfies_itself("1.2.3.a.4") + + assert_approximate_equal("~> 1.9.a", "1.9.0.dev") + assert_approximate_satisfies_itself("1.9.0.dev") + + +def test_to_s(): + assert GemVersion("5.2.4").to_string() == "5.2.4" + + +def test_semver(): + assert_less_than("1.0.0-alpha", "1.0.0-alpha.1") + assert_less_than("1.0.0-alpha.1", "1.0.0-beta.2") + assert_less_than("1.0.0-beta.2", "1.0.0-beta.11") + assert_less_than("1.0.0-beta.11", "1.0.0-rc.1") + assert_less_than("1.0.0-rc1", "1.0.0") + assert_less_than("1.0.0-1", "1") + + +def test_segments(): # modifying the segments of a version should not affect the segments of the cached version object - def test_segments - v('9.8.7').segments[2] += 1 - - refute_version_equal "9.8.8", "9.8.7" - assert_equal [9,8,7], v("9.8.7").segments - end - - def test_canonical_segments - assert_equal [1], v("1.0.0").canonical_segments - assert_equal [1, "a", 1], v("1.0.0.a.1.0").canonical_segments - assert_equal [1, 2, 3, "pre", 1], v("1.2.3-1").canonical_segments - end - - def test_frozen_version - v = v('1.freeze.test').freeze - assert_less_than v, v('1') - assert_version_equal v('1'), v.release - assert_version_equal v('2'), v.bump - end + ver = GemVersion('9.8.7') + secondseg = ver.segments[2] + secondseg += 1 - # Asserts that +version+ is a prerelease. + refute_version_equal("9.8.8", "9.8.7") + assert_equal([9, 8, 7], GemVersion("9.8.7").segments) - def assert_prerelease(version) - assert v(version).prerelease?, "#{version} is a prerelease" - end - # Assert that +expected+ is the "approximate" recommendation for +version+. +def test_canonical_segments(): + assert_equal([1], GemVersion("1.0.0").canonical_segments) + assert_equal([1, "a", 1], GemVersion("1.0.0.a.1.0").canonical_segments) + assert_equal([1, 2, 3, "pre", 1], GemVersion("1.2.3-1").canonical_segments) - def assert_approximate_equal(expected, version) - assert_equal expected, v(version).approximate_recommendation - end - # Assert that the "approximate" recommendation for +version+ satisfies +version+. +def test_frozen_version(): + ver = GemVersion('1.test') + assert_less_than(ver, GemVersion('1')) + assert_version_equal(GemVersion('1'), v.release) + assert_version_equal(GemVersion('2'), v.bump) - def assert_approximate_satisfies_itself(version) - gem_version = v(version) - assert Gem::Requirement.new(gem_version.approximate_recommendation).satisfied_by?(gem_version) - end +def assert_prerelease(version): + # Asserts that +version+ is a prerelease. + assert GemVersion(version).prerelease(), "#{version} is a prerelease" + + +def assert_approximate_equal(expected, version): + # Assert that +expected+ is the "approximate" recommendation for +version+. + assert GemVersion(version).approximate_recommendation() == expected - # Assert that bumping the +unbumped+ version yields the +expected+. - def assert_bumped_version_equal(expected, unbumped) - assert_version_equal expected, v(unbumped).bump - end +def assert_approximate_satisfies_itself(version): + # Assert that the "approximate" recommendation for +version+ satisfies +version+. + gem_version = GemVersion(version) + req = GemRequirement(gem_version.approximate_recommendation()) + assert req.satisfied_by(gem_version) + +def assert_release_equal(release, version): # Assert that +release+ is the correct non-prerelease +version+. + assert_version_equal(release, GemVersion(version).release) - def assert_release_equal(release, version) - assert_version_equal release, v(version).release - end +def assert_version_equal(expected, actual): # Assert that two versions are equal. Handles strings or # Gem::Version instances. + assert GemVersion(expected) == GemVersion(actual) - def assert_version_equal(expected, actual) - assert_equal v(expected), v(actual) - assert_equal v(expected).hash, v(actual).hash, "since #{actual} == #{expected}, they must have the same hash" - end +def assert_version_eql(first, second): # Assert that two versions are eql?. Checks both directions. + first, second = GemVersion(first), GemVersion(second) + assert first == second, "#{first} is eql? #{second}" + assert second == first, "#{second} is eql? #{first}" - def assert_version_eql(first, second) - first, second = v(first), v(second) - assert first.eql?(second), "#{first} is eql? #{second}" - assert second.eql?(first), "#{second} is eql? #{first}" - end - def assert_less_than(left, right) - l = v(left) - r = v(right) - assert l < r, "#{left} not less than #{right}" - end +def assert_less_than(left, right): + assert GemVersion(left) < GemVersion(right) + +def refute_prerelease(version): # Refute the assumption that +version+ is a prerelease. + assert not GemVersion(version).prerelease() - def refute_prerelease(version) - refute v(version).prerelease?, "#{version} is NOT a prerelease" - end +def refute_version_eql(first, second): # Refute the assumption that two versions are eql?. Checks both # directions. + first = GemVersion(first) + second = GemVersion(second) + assert first != second + assert second != first - def refute_version_eql(first, second) - first, second = v(first), v(second) - refute first.eql?(second), "#{first} is NOT eql? #{second}" - refute second.eql?(first), "#{second} is NOT eql? #{first}" - end +def refute_version_equal(unexpected, actual): # Refute the assumption that the two versions are equal?. - - def refute_version_equal(unexpected, actual) - refute_equal v(unexpected), v(actual) - end -end + assert GemVersion(unexpected) != GemVersion(actual) From d7a655909be703c5422e053e0d0b5909d8d8be98 Mon Sep 17 00:00:00 2001 From: Philippe Ombredanne Date: Mon, 6 Dec 2021 11:53:47 +0100 Subject: [PATCH 686/707] Rename, move and add ABOUT license and origin Signed-off-by: Philippe Ombredanne --- .../test_gem_requirement.py | 10 ++++++++- tests/test_gem_requirement.py.ABOUT | 14 +++++++++++++ tests/test_gem_requirement.py.NOTICE | 21 +++++++++++++++++++ 3 files changed, 44 insertions(+), 1 deletion(-) rename test/rubygems/test_gem_requirement.rb => tests/test_gem_requirement.py (98%) create mode 100644 tests/test_gem_requirement.py.ABOUT create mode 100644 tests/test_gem_requirement.py.NOTICE diff --git a/test/rubygems/test_gem_requirement.rb b/tests/test_gem_requirement.py similarity index 98% rename from test/rubygems/test_gem_requirement.rb rename to tests/test_gem_requirement.py index b4367681..4b9ac500 100644 --- a/test/rubygems/test_gem_requirement.rb +++ b/tests/test_gem_requirement.py @@ -1,4 +1,12 @@ -# frozen_string_literal: true + +# +# Copyright (c) Chad Fowler, Rich Kilmer, Jim Weirich and others. +# Portions copyright (c) Engine Yard and Andre ArkoFacebook, Inc. and its affiliates. +# +# SPDX-License-Identifier: MIT +# +# Originally from https://github.com/rubygems/rubygems + require_relative 'helper' require "rubygems/requirement" diff --git a/tests/test_gem_requirement.py.ABOUT b/tests/test_gem_requirement.py.ABOUT new file mode 100644 index 00000000..b1648601 --- /dev/null +++ b/tests/test_gem_requirement.py.ABOUT @@ -0,0 +1,14 @@ +about_resource: test_gem_requirement.py +package_url: pkg:github.com/rubygems/rubygems@5768c2bc5542ce05466d379981a433ba1ee1e10a +copyright: | + Copyright (c) Chad Fowler, Rich Kilmer, Jim Weirich and others. + Portions copyright (c) Engine Yard and Andre Arko + +license_expression: mit +homepage_url: https://github.com/rubygems/rubygems + +notes: This has been substantially modified and enhanced from the original code + to port tests cases to Python. The original license is a choice of MIT or Ruby + license. We selected to use the MIT license here. + +notice_file: test_gem_requirement.py.NOTICE \ No newline at end of file diff --git a/tests/test_gem_requirement.py.NOTICE b/tests/test_gem_requirement.py.NOTICE new file mode 100644 index 00000000..a90b9bb2 --- /dev/null +++ b/tests/test_gem_requirement.py.NOTICE @@ -0,0 +1,21 @@ +Copyright (c) Chad Fowler, Rich Kilmer, Jim Weirich and others. +Portions copyright (c) Engine Yard and Andre Arko + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +'Software'), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. From 09affebd49aa0d16a628f5091f6fe25932ce2227 Mon Sep 17 00:00:00 2001 From: Philippe Ombredanne Date: Mon, 6 Dec 2021 11:56:43 +0100 Subject: [PATCH 687/707] Port to Python Signed-off-by: Philippe Ombredanne --- tests/test_bundler_version_ranges_spec.py | 77 ++++++++++++----------- 1 file changed, 40 insertions(+), 37 deletions(-) diff --git a/tests/test_bundler_version_ranges_spec.py b/tests/test_bundler_version_ranges_spec.py index aa84a391..0f928e59 100644 --- a/tests/test_bundler_version_ranges_spec.py +++ b/tests/test_bundler_version_ranges_spec.py @@ -1,4 +1,3 @@ - # # Copyright (c) Chad Fowler, Rich Kilmer, Jim Weirich and others. # Portions copyright (c) Engine Yard and Andre ArkoFacebook, Inc. and its affiliates. @@ -8,41 +7,45 @@ # Originally from https://github.com/rubygems/rubygems -require "bundler/version_ranges" +from univers.gem import GemRequirement -RSpec.describe Bundler::VersionRanges do - describe ".empty?" do - shared_examples_for "empty?" do |exp, *req| - it "returns #{exp} for #{req}" do - r = Gem::Requirement.new(*req) - ranges = described_class.for(r) - expect(described_class.empty?(*ranges)).to eq(exp), "expected `#{r}` #{exp ? "" : "not "}to be empty" - end - end - include_examples "empty?", false - include_examples "empty?", false, "!= 1" - include_examples "empty?", false, "!= 1", "= 2" - include_examples "empty?", false, "!= 1", "> 1" - include_examples "empty?", false, "!= 1", ">= 1" - include_examples "empty?", false, "= 1", ">= 0.1", "<= 1.1" - include_examples "empty?", false, "= 1", ">= 1", "<= 1" - include_examples "empty?", false, "= 1", "~> 1" - include_examples "empty?", false, ">= 0.z", "= 0" - include_examples "empty?", false, ">= 0" - include_examples "empty?", false, ">= 1.0.0", "< 2.0.0" - include_examples "empty?", false, "~> 1" - include_examples "empty?", false, "~> 2.0", "~> 2.1" - include_examples "empty?", true, ">= 4.1.0", "< 5.0", "= 5.2.1" - include_examples "empty?", true, "< 5.0", "< 5.3", "< 6.0", "< 6", "= 5.2.0", "> 2", ">= 3.0", ">= 3.1", ">= 3.2", ">= 4.0.0", ">= 4.1.0", ">= 4.2.0", ">= 4.2", ">= 4" - include_examples "empty?", true, "!= 1", "< 2", "> 2" - include_examples "empty?", true, "!= 1", "<= 1", ">= 1" - include_examples "empty?", true, "< 2", "> 2" - include_examples "empty?", true, "< 2", "> 2", "= 2" - include_examples "empty?", true, "= 1", "!= 1" - include_examples "empty?", true, "= 1", "= 2" - include_examples "empty?", true, "= 1", "~> 2" - include_examples "empty?", true, ">= 0", "<= 0.a" - include_examples "empty?", true, "~> 2.0", "~> 3" - end -end +def test_is_empty(): + assert not GemRequirement("!= 1").is_empty() + assert not GemRequirement("!= 1", "= 2").is_empty() + assert not GemRequirement("!= 1", "> 1").is_empty() + assert not GemRequirement("!= 1", ">= 1").is_empty() + assert not GemRequirement("= 1", ">= 0.1", "<= 1.1").is_empty() + assert not GemRequirement("= 1", ">= 1", "<= 1").is_empty() + assert not GemRequirement("= 1", "~> 1").is_empty() + assert not GemRequirement(">= 0.z", "= 0").is_empty() + assert not GemRequirement(">= 0").is_empty() + assert not GemRequirement(">= 1.0.0", "< 2.0.0").is_empty() + assert not GemRequirement("~> 1").is_empty() + assert not GemRequirement("~> 2.0", "~> 2.1").is_empty() + assert GemRequirement(">= 4.1.0", "< 5.0", "= 5.2.1").is_empty() + assert GemRequirement( + "< 5.0", + "< 5.3", + "< 6.0", + "< 6", + "= 5.2.0", + "> 2", + ">= 3.0", + ">= 3.1", + ">= 3.2", + ">= 4.0.0", + ">= 4.1.0", + ">= 4.2.0", + ">= 4.2", + ">= 4", + ).is_empty() + assert GemRequirement("!= 1", "< 2", "> 2").is_empty() + assert GemRequirement("!= 1", "<= 1", ">= 1").is_empty() + assert GemRequirement("< 2", "> 2").is_empty() + assert GemRequirement("< 2", "> 2", "= 2").is_empty() + assert GemRequirement("= 1", "!= 1").is_empty() + assert GemRequirement("= 1", "= 2").is_empty() + assert GemRequirement("= 1", "~> 2").is_empty() + assert GemRequirement(">= 0", "<= 0.a").is_empty() + assert GemRequirement("~> 2.0", "~> 3").is_empty() From 700a3ddc69cf04085da7c270c8e24b1c0b675309 Mon Sep 17 00:00:00 2001 From: Philippe Ombredanne Date: Mon, 6 Dec 2021 11:57:04 +0100 Subject: [PATCH 688/707] Format code Signed-off-by: Philippe Ombredanne --- tests/test_rubygems_gem_version.py | 264 ++++++++++++++--------------- 1 file changed, 131 insertions(+), 133 deletions(-) diff --git a/tests/test_rubygems_gem_version.py b/tests/test_rubygems_gem_version.py index 62d4113a..756c1a2a 100644 --- a/tests/test_rubygems_gem_version.py +++ b/tests/test_rubygems_gem_version.py @@ -1,4 +1,3 @@ - # # Copyright (c) Chad Fowler, Rich Kilmer, Jim Weirich and others. # Portions copyright (c) Engine Yard and Andre ArkoFacebook, Inc. and its affiliates. @@ -15,243 +14,242 @@ def assert_equal(expected, result): def assert_bumped_version_equal(expected, unbumped): - # Assert that bumping the +unbumped+ version yields the +expected+. + # Assert that bumping the +unbumped+ version yields the +expected+. - assert_version_equal(expected, GemVersion(unbumped).bump()) + assert_version_equal(expected, GemVersion(unbumped).bump()) def test_bump(): - assert_bumped_version_equal("5.3", "5.2.4") + assert_bumped_version_equal("5.3", "5.2.4") def test_bump_alpha(): - assert_bumped_version_equal("5.3", "5.2.4.a") + assert_bumped_version_equal("5.3", "5.2.4.a") def test_bump_alphanumeric(): - assert_bumped_version_equal("5.3", "5.2.4.a10") + assert_bumped_version_equal("5.3", "5.2.4.a10") def test_bump_trailing_zeros(): - assert_bumped_version_equal("5.1", "5.0.0") + assert_bumped_version_equal("5.1", "5.0.0") def test_bump_one_level(): - assert_bumped_version_equal("6", "5") + assert_bumped_version_equal("6", "5") def test_eql_eh(): - assert_version_eql("1.2", "1.2") - refute_version_eql("1.2", "1.2.0") - refute_version_eql("1.2", "1.3") - refute_version_eql("1.2.b1", "1.2.b.1") + assert_version_eql("1.2", "1.2") + refute_version_eql("1.2", "1.2.0") + refute_version_eql("1.2", "1.3") + refute_version_eql("1.2.b1", "1.2.b.1") def test_equals2(): - assert_version_equal("1.2", "1.2") - refute_version_equal("1.2", "1.3") - assert_version_equal("1.2.b1", "1.2.b.1") + assert_version_equal("1.2", "1.2") + refute_version_equal("1.2", "1.3") + assert_version_equal("1.2.b1", "1.2.b.1") + + # REVISIT: consider removing as too impl-bound - # REVISIT: consider removing as too impl-bound def test_hash(): - assert GemVersion("1.2").hash == GemVersion("1.2").hash - assert GemVersion("1.2").hash != GemVersion("1.3").hash - assert GemVersion("1.2").hash == GemVersion("1.2.0").hash - assert GemVersion("1.2.pre.1").hash == GemVersion("1.2.0.pre.1.0").hash + assert GemVersion("1.2").hash == GemVersion("1.2").hash + assert GemVersion("1.2").hash != GemVersion("1.3").hash + assert GemVersion("1.2").hash == GemVersion("1.2.0").hash + assert GemVersion("1.2.pre.1").hash == GemVersion("1.2.0.pre.1.0").hash def test_initialize(): - for good in ["1.0", "1.0 ", " 1.0 ", "1.0\n", "\n1.0\n", "1.0"]: - assert_version_equal("1.0", good) + for good in ["1.0", "1.0 ", " 1.0 ", "1.0\n", "\n1.0\n", "1.0"]: + assert_version_equal("1.0", good) - assert_version_equal("1", 1) + assert_version_equal("1", 1) def test_initialize_invalid(): - invalid_versions = [ - "junk", - "1.0\n2.0" - "1..2", - "1.2\ 3.4", - ] + invalid_versions = [ + "junk", + "1.0\n2.0" "1..2", + "1.2\ 3.4", + ] - # DON'T TOUCH THIS WITHOUT CHECKING CVE-2013-4287 - invalid_versions += ["2.3422222.222.222222222.22222.ads0as.dasd0.ddd2222.2.qd3e."] + # DON'T TOUCH THIS WITHOUT CHECKING CVE-2013-4287 + invalid_versions += ["2.3422222.222.222222222.22222.ads0as.dasd0.ddd2222.2.qd3e."] - for invalid in invalid_versions: - try: - GemVersion(invalid) - raise Exception("exception not raised") - except ValueError: - pass + for invalid in invalid_versions: + try: + GemVersion(invalid) + raise Exception("exception not raised") + except ValueError: + pass def test_empty_version(): - for empty in ["", " ", " "]: - assert_equal("0", GemVersion(empty).version) + for empty in ["", " ", " "]: + assert_equal("0", GemVersion(empty).version) def test_prerelease(): - assert_prerelease("1.2.0.a") - assert_prerelease("2.9.b") - assert_prerelease("22.1.50.0.d") - assert_prerelease("1.2.d.42") + assert_prerelease("1.2.0.a") + assert_prerelease("2.9.b") + assert_prerelease("22.1.50.0.d") + assert_prerelease("1.2.d.42") - assert_prerelease('1.A') + assert_prerelease("1.A") - assert_prerelease('1-1') - assert_prerelease('1-a') + assert_prerelease("1-1") + assert_prerelease("1-a") - refute_prerelease("1.2.0") - refute_prerelease("2.9") - refute_prerelease("22.1.50.0") + refute_prerelease("1.2.0") + refute_prerelease("2.9") + refute_prerelease("22.1.50.0") def test_release(): - assert_release_equal("1.2.0", "1.2.0.a") - assert_release_equal("1.1", "1.1.rc10") - assert_release_equal("1.9.3", "1.9.3.alpha.5") - assert_release_equal("1.9.3", "1.9.3") + assert_release_equal("1.2.0", "1.2.0.a") + assert_release_equal("1.1", "1.1.rc10") + assert_release_equal("1.9.3", "1.9.3.alpha.5") + assert_release_equal("1.9.3", "1.9.3") def test_spaceship(): + def cmp(a, b): + return a.__cmp__(b) - def cmp(a, b): - return a.__cmp__(b) - - # Ruby spaceship <=> is the same as Python legacy cmp() - assert_equal(0, cmp(GemVersion("1.0") , GemVersion("1.0.0"))) - assert_equal(1, cmp(GemVersion("1.0") , GemVersion("1.0.a"))) - assert_equal(1, cmp(GemVersion("1.8.2") , GemVersion("0.0.0"))) - assert_equal(1, cmp(GemVersion("1.8.2") , GemVersion("1.8.2.a"))) - assert_equal(1, cmp(GemVersion("1.8.2.b") , GemVersion("1.8.2.a"))) - assert_equal(-1, cmp(GemVersion("1.8.2.a") , GemVersion("1.8.2"))) - assert_equal(1, cmp(GemVersion("1.8.2.a10") , GemVersion("1.8.2.a9"))) - assert_equal(0, cmp(GemVersion("") , GemVersion("0"))) + # Ruby spaceship <=> is the same as Python legacy cmp() + assert_equal(0, cmp(GemVersion("1.0"), GemVersion("1.0.0"))) + assert_equal(1, cmp(GemVersion("1.0"), GemVersion("1.0.a"))) + assert_equal(1, cmp(GemVersion("1.8.2"), GemVersion("0.0.0"))) + assert_equal(1, cmp(GemVersion("1.8.2"), GemVersion("1.8.2.a"))) + assert_equal(1, cmp(GemVersion("1.8.2.b"), GemVersion("1.8.2.a"))) + assert_equal(-1, cmp(GemVersion("1.8.2.a"), GemVersion("1.8.2"))) + assert_equal(1, cmp(GemVersion("1.8.2.a10"), GemVersion("1.8.2.a9"))) + assert_equal(0, cmp(GemVersion(""), GemVersion("0"))) - assert_equal(0, cmp(GemVersion("0.beta.1") , GemVersion("0.0.beta.1"))) - assert_equal(-1, cmp(GemVersion("0.0.beta") , GemVersion("0.0.beta.1"))) - assert_equal(-1, cmp(GemVersion("0.0.beta") , GemVersion("0.beta.1"))) + assert_equal(0, cmp(GemVersion("0.beta.1"), GemVersion("0.0.beta.1"))) + assert_equal(-1, cmp(GemVersion("0.0.beta"), GemVersion("0.0.beta.1"))) + assert_equal(-1, cmp(GemVersion("0.0.beta"), GemVersion("0.beta.1"))) - assert_equal(-1, cmp(GemVersion("5.a") , GemVersion("5.0.0.rc2"))) - assert_equal(1, cmp(GemVersion("5.x") , GemVersion("5.0.0.rc2"))) + assert_equal(-1, cmp(GemVersion("5.a"), GemVersion("5.0.0.rc2"))) + assert_equal(1, cmp(GemVersion("5.x"), GemVersion("5.0.0.rc2"))) - assert_nil(cmp(GemVersion("1.0") , "whatever")) + assert_nil(cmp(GemVersion("1.0"), "whatever")) def test_approximate_recommendation(): - assert_approximate_equal("~> 1.0", "1") - assert_approximate_satisfies_itself("1") + assert_approximate_equal("~> 1.0", "1") + assert_approximate_satisfies_itself("1") - assert_approximate_equal("~> 1.0", "1.0") - assert_approximate_satisfies_itself("1.0") + assert_approximate_equal("~> 1.0", "1.0") + assert_approximate_satisfies_itself("1.0") - assert_approximate_equal("~> 1.2", "1.2") - assert_approximate_satisfies_itself("1.2") + assert_approximate_equal("~> 1.2", "1.2") + assert_approximate_satisfies_itself("1.2") - assert_approximate_equal("~> 1.2", "1.2.0") - assert_approximate_satisfies_itself("1.2.0") + assert_approximate_equal("~> 1.2", "1.2.0") + assert_approximate_satisfies_itself("1.2.0") - assert_approximate_equal("~> 1.2", "1.2.3") - assert_approximate_satisfies_itself("1.2.3") + assert_approximate_equal("~> 1.2", "1.2.3") + assert_approximate_satisfies_itself("1.2.3") - assert_approximate_equal("~> 1.2.a", "1.2.3.a.4") - assert_approximate_satisfies_itself("1.2.3.a.4") + assert_approximate_equal("~> 1.2.a", "1.2.3.a.4") + assert_approximate_satisfies_itself("1.2.3.a.4") - assert_approximate_equal("~> 1.9.a", "1.9.0.dev") - assert_approximate_satisfies_itself("1.9.0.dev") + assert_approximate_equal("~> 1.9.a", "1.9.0.dev") + assert_approximate_satisfies_itself("1.9.0.dev") def test_to_s(): - assert GemVersion("5.2.4").to_string() == "5.2.4" + assert GemVersion("5.2.4").to_string() == "5.2.4" def test_semver(): - assert_less_than("1.0.0-alpha", "1.0.0-alpha.1") - assert_less_than("1.0.0-alpha.1", "1.0.0-beta.2") - assert_less_than("1.0.0-beta.2", "1.0.0-beta.11") - assert_less_than("1.0.0-beta.11", "1.0.0-rc.1") - assert_less_than("1.0.0-rc1", "1.0.0") - assert_less_than("1.0.0-1", "1") + assert_less_than("1.0.0-alpha", "1.0.0-alpha.1") + assert_less_than("1.0.0-alpha.1", "1.0.0-beta.2") + assert_less_than("1.0.0-beta.2", "1.0.0-beta.11") + assert_less_than("1.0.0-beta.11", "1.0.0-rc.1") + assert_less_than("1.0.0-rc1", "1.0.0") + assert_less_than("1.0.0-1", "1") def test_segments(): - # modifying the segments of a version should not affect the segments of the cached version object - ver = GemVersion('9.8.7') - secondseg = ver.segments[2] - secondseg += 1 + # modifying the segments of a version should not affect the segments of the cached version object + ver = GemVersion("9.8.7") + secondseg = ver.segments[2] + secondseg += 1 - refute_version_equal("9.8.8", "9.8.7") - assert_equal([9, 8, 7], GemVersion("9.8.7").segments) + refute_version_equal("9.8.8", "9.8.7") + assert_equal([9, 8, 7], GemVersion("9.8.7").segments) def test_canonical_segments(): - assert_equal([1], GemVersion("1.0.0").canonical_segments) - assert_equal([1, "a", 1], GemVersion("1.0.0.a.1.0").canonical_segments) - assert_equal([1, 2, 3, "pre", 1], GemVersion("1.2.3-1").canonical_segments) + assert_equal([1], GemVersion("1.0.0").canonical_segments) + assert_equal([1, "a", 1], GemVersion("1.0.0.a.1.0").canonical_segments) + assert_equal([1, 2, 3, "pre", 1], GemVersion("1.2.3-1").canonical_segments) def test_frozen_version(): - ver = GemVersion('1.test') - assert_less_than(ver, GemVersion('1')) - assert_version_equal(GemVersion('1'), v.release) - assert_version_equal(GemVersion('2'), v.bump) + ver = GemVersion("1.test") + assert_less_than(ver, GemVersion("1")) + assert_version_equal(GemVersion("1"), v.release) + assert_version_equal(GemVersion("2"), v.bump) def assert_prerelease(version): - # Asserts that +version+ is a prerelease. - assert GemVersion(version).prerelease(), "#{version} is a prerelease" + # Asserts that +version+ is a prerelease. + assert GemVersion(version).prerelease(), "#{version} is a prerelease" def assert_approximate_equal(expected, version): - # Assert that +expected+ is the "approximate" recommendation for +version+. - assert GemVersion(version).approximate_recommendation() == expected + # Assert that +expected+ is the "approximate" recommendation for +version+. + assert GemVersion(version).approximate_recommendation() == expected def assert_approximate_satisfies_itself(version): - # Assert that the "approximate" recommendation for +version+ satisfies +version+. - gem_version = GemVersion(version) - req = GemRequirement(gem_version.approximate_recommendation()) - assert req.satisfied_by(gem_version) + # Assert that the "approximate" recommendation for +version+ satisfies +version+. + gem_version = GemVersion(version) + req = GemRequirement(gem_version.approximate_recommendation()) + assert req.satisfied_by(gem_version) def assert_release_equal(release, version): - # Assert that +release+ is the correct non-prerelease +version+. - assert_version_equal(release, GemVersion(version).release) + # Assert that +release+ is the correct non-prerelease +version+. + assert_version_equal(release, GemVersion(version).release) def assert_version_equal(expected, actual): - # Assert that two versions are equal. Handles strings or - # Gem::Version instances. - assert GemVersion(expected) == GemVersion(actual) + # Assert that two versions are equal. Handles strings or + # Gem::Version instances. + assert GemVersion(expected) == GemVersion(actual) def assert_version_eql(first, second): - # Assert that two versions are eql?. Checks both directions. - first, second = GemVersion(first), GemVersion(second) - assert first == second, "#{first} is eql? #{second}" - assert second == first, "#{second} is eql? #{first}" + # Assert that two versions are eql?. Checks both directions. + first, second = GemVersion(first), GemVersion(second) + assert first == second, "#{first} is eql? #{second}" + assert second == first, "#{second} is eql? #{first}" def assert_less_than(left, right): - assert GemVersion(left) < GemVersion(right) + assert GemVersion(left) < GemVersion(right) def refute_prerelease(version): - # Refute the assumption that +version+ is a prerelease. - assert not GemVersion(version).prerelease() + # Refute the assumption that +version+ is a prerelease. + assert not GemVersion(version).prerelease() def refute_version_eql(first, second): - # Refute the assumption that two versions are eql?. Checks both - # directions. - first = GemVersion(first) - second = GemVersion(second) - assert first != second - assert second != first + # Refute the assumption that two versions are eql?. Checks both + # directions. + first = GemVersion(first) + second = GemVersion(second) + assert first != second + assert second != first def refute_version_equal(unexpected, actual): - # Refute the assumption that the two versions are equal?. - assert GemVersion(unexpected) != GemVersion(actual) + # Refute the assumption that the two versions are equal?. + assert GemVersion(unexpected) != GemVersion(actual) From 954498ec50967664e5271b18b7e41aba6dcb44cf Mon Sep 17 00:00:00 2001 From: Philippe Ombredanne Date: Mon, 6 Dec 2021 11:58:05 +0100 Subject: [PATCH 689/707] Rename to unique name Signed-off-by: Philippe Ombredanne --- ...st_gem_requirement.py => test_rubygems_gem_requirement.py} | 0 ...rement.py.ABOUT => test_rubygems_gem_requirement.py.ABOUT} | 4 ++-- ...ment.py.NOTICE => test_rubygems_gem_requirement.py.NOTICE} | 0 3 files changed, 2 insertions(+), 2 deletions(-) rename tests/{test_gem_requirement.py => test_rubygems_gem_requirement.py} (100%) rename tests/{test_gem_requirement.py.ABOUT => test_rubygems_gem_requirement.py.ABOUT} (83%) rename tests/{test_gem_requirement.py.NOTICE => test_rubygems_gem_requirement.py.NOTICE} (100%) diff --git a/tests/test_gem_requirement.py b/tests/test_rubygems_gem_requirement.py similarity index 100% rename from tests/test_gem_requirement.py rename to tests/test_rubygems_gem_requirement.py diff --git a/tests/test_gem_requirement.py.ABOUT b/tests/test_rubygems_gem_requirement.py.ABOUT similarity index 83% rename from tests/test_gem_requirement.py.ABOUT rename to tests/test_rubygems_gem_requirement.py.ABOUT index b1648601..88863578 100644 --- a/tests/test_gem_requirement.py.ABOUT +++ b/tests/test_rubygems_gem_requirement.py.ABOUT @@ -1,4 +1,4 @@ -about_resource: test_gem_requirement.py +about_resource: test_rubygems_gem_requirement.py package_url: pkg:github.com/rubygems/rubygems@5768c2bc5542ce05466d379981a433ba1ee1e10a copyright: | Copyright (c) Chad Fowler, Rich Kilmer, Jim Weirich and others. @@ -11,4 +11,4 @@ notes: This has been substantially modified and enhanced from the original code to port tests cases to Python. The original license is a choice of MIT or Ruby license. We selected to use the MIT license here. -notice_file: test_gem_requirement.py.NOTICE \ No newline at end of file +notice_file: test_rubygems_gem_requirement.py.NOTICE \ No newline at end of file diff --git a/tests/test_gem_requirement.py.NOTICE b/tests/test_rubygems_gem_requirement.py.NOTICE similarity index 100% rename from tests/test_gem_requirement.py.NOTICE rename to tests/test_rubygems_gem_requirement.py.NOTICE From 7c7efb8f8a94375fc17e6c0c08c24fea9fd423d4 Mon Sep 17 00:00:00 2001 From: Philippe Ombredanne Date: Mon, 6 Dec 2021 13:30:57 +0100 Subject: [PATCH 690/707] Port to Python Signed-off-by: Philippe Ombredanne --- tests/test_rubygems_gem_requirement.py | 778 ++++++++++--------------- 1 file changed, 321 insertions(+), 457 deletions(-) diff --git a/tests/test_rubygems_gem_requirement.py b/tests/test_rubygems_gem_requirement.py index 4b9ac500..844cec8a 100644 --- a/tests/test_rubygems_gem_requirement.py +++ b/tests/test_rubygems_gem_requirement.py @@ -1,4 +1,3 @@ - # # Copyright (c) Chad Fowler, Rich Kilmer, Jim Weirich and others. # Portions copyright (c) Engine Yard and Andre ArkoFacebook, Inc. and its affiliates. @@ -7,500 +6,365 @@ # # Originally from https://github.com/rubygems/rubygems -require_relative 'helper' -require "rubygems/requirement" - -class TestGemRequirement < Gem::TestCase - def test_concat - r = req '>= 1' - - r.concat ['< 2'] +from univers.gem import GemRequirement +from univers.gem import GemVersion + + +def test_equals(): + refute_requirement_equal("= 1.2", "= 1.3") + refute_requirement_equal("= 1.3", "= 1.2") + + refute_requirement_equal("~> 1.3", "~> 1.3.0") + refute_requirement_equal("~> 1.3.0", "~> 1.3") + + assert_requirement_equal(["> 2", "~> 1.3", "~> 1.3.1"], ["~> 1.3.1", "~> 1.3", "> 2"]) + + assert_requirement_equal(["> 2", "~> 1.3"], ["> 2.0", "~> 1.3"]) + assert_requirement_equal(["> 2.0", "~> 1.3"], ["> 2", "~> 1.3"]) + + +def test_initialize(): + assert_requirement_equal("= 2", "2") + assert_requirement_equal("= 2", ["2"]) + assert_requirement_equal("= 2", GemVersion(2)) + assert_requirement_equal("2.0", "2") + + +def test_create(): + r = GemRequirement(">= 1", "< 2") + assert r.requirements == [[">=", GemVersion(1)], ["<", GemVersion(2)]] + assert GemRequirement("= 1") == GemRequirement("= 1") + assert GemRequirement(">= 1.2", "<= 1.3") == GemRequirement("<= 1.3", ">= 1.2") + + +def test_empty_requirements_is_none(): + r = GemRequirement() + assert r is None + + +def test_explicit_default_is_none(): + r = GemRequirement(">= 0") + assert r + + +def test_basic_non_none(): + r = GemRequirement("= 1") + assert r + + +def test_for_lockfile(): + assertGemRequirement("~> 1.0").for_lockfile() == " (~> 1.0)" + assert GemRequirement(">= 1.0.1", "~> 1.0").for_lockfile() == " (~> 1.0, >= 1.0.1)" + duped = GemRequirement("= 1.0", ["=", GemVersion("1.0")]) + assert duped.for_lockfile() == " (= 1.0)" + + +def test_parse(): + assert GemRequirement.parse(" 1") == ["=", GemVersion(1)] + assert GemRequirement.parse("= 1") == ["=", GemVersion(1)] + assert GemRequirement.parse("> 1") == [">", GemVersion(1)] + assert GemRequirement.parse("=\n1" == ["=", GemVersion(1)]) + assert GemRequirement.parse("1.0") == ["=", GemVersion(1)] + + assert GemRequirement.parse(GemVersion("2")) == ["=", GemVersion(2)] + + +def test_parse_deduplication(): + assert GemRequirement.parse("~> 1")[0] == "~>" + + +def test_parse_bad(): + bads = [ + nil, + "", + "! 1", + "= junk", + "1..2", + ] + for bad in bads: + try: + GemRequirement.parse(bad) + raise Exception("exception not raised") + except GemRequirement.BadRequirementError: + pass + + +def test_prerelease_eh(): + r = GemRequirement("= 1") + assert not r.prerelease + + r = GemRequirement("= 1.a") + assert r.prerelease + + r = GemRequirement("> 1.a", "< 2") + assert r.prerelease + + +def test_satisfied_by_eh_bang_equal(): + r = GemRequirement("!= 1.2") + + assert_satisfied_by("1.1", r) + refute_satisfied_by("1.2", r) + assert_satisfied_by("1.3", r) + - assert_equal [['>=', v(1)], ['<', v(2)]], r.requirements - end +def test_satisfied_by_eh_blank(): + r = GemRequirement("1.2") - def test_equals2 - r = req "= 1.2" - assert_equal r, r.dup - assert_equal r.dup, r + refute_satisfied_by("1.1", r) + assert_satisfied_by("1.2", r) + refute_satisfied_by("1.3", r) - refute_requirement_equal "= 1.2", "= 1.3" - refute_requirement_equal "= 1.3", "= 1.2" - refute_requirement_equal "~> 1.3", "~> 1.3.0" - refute_requirement_equal "~> 1.3.0", "~> 1.3" +def test_satisfied_by_eh_equal(): + r = GemRequirement("= 1.2") - assert_requirement_equal ["> 2", "~> 1.3", "~> 1.3.1"], ["~> 1.3.1", "~> 1.3", "> 2"] + refute_satisfied_by("1.1", r) + assert_satisfied_by("1.2", r) + refute_satisfied_by("1.3", r) - assert_requirement_equal ["> 2", "~> 1.3"], ["> 2.0", "~> 1.3"] - assert_requirement_equal ["> 2.0", "~> 1.3"], ["> 2", "~> 1.3"] - refute_equal Object.new, req("= 1.2") - refute_equal req("= 1.2"), Object.new - end +def test_satisfied_by_eh_gt(): + r = GemRequirement("> 1.2") - def test_initialize - assert_requirement_equal "= 2", "2" - assert_requirement_equal "= 2", ["2"] - assert_requirement_equal "= 2", v(2) - assert_requirement_equal "2.0", "2" - end + refute_satisfied_by("1.1", r) + refute_satisfied_by("1.2", r) + assert_satisfied_by("1.3", r) - def test_create - assert_equal req("= 1"), Gem::Requirement.create("= 1") - assert_equal req(">= 1.2", "<= 1.3"), Gem::Requirement.create([">= 1.2", "<= 1.3"]) - assert_equal req(">= 1.2", "<= 1.3"), Gem::Requirement.create(">= 1.2", "<= 1.3") - end - def test_empty_requirements_is_none - r = Gem::Requirement.new - assert_equal true, r.none? - end +def test_satisfied_by_eh_gte(): + r = GemRequirement(">= 1.2") - def test_explicit_default_is_none - r = Gem::Requirement.new ">= 0" - assert_equal true, r.none? - end + refute_satisfied_by("1.1", r) + assert_satisfied_by("1.2", r) + assert_satisfied_by("1.3", r) - def test_basic_non_none - r = Gem::Requirement.new "= 1" - assert_equal false, r.none? - end - def test_for_lockfile - assert_equal ' (~> 1.0)', req('~> 1.0').for_lockfile +def test_satisfied_by_eh_list(): + r = GemRequirement("> 1.1", "< 1.3") - assert_equal ' (~> 1.0, >= 1.0.1)', req('>= 1.0.1', '~> 1.0').for_lockfile + refute_satisfied_by("1.1", r) + assert_satisfied_by("1.2", r) + refute_satisfied_by("1.3", r) - duped = req '= 1.0' - duped.requirements << ['=', v('1.0')] - assert_equal ' (= 1.0)', duped.for_lockfile +def test_satisfied_by_eh_lt(): + r = GemRequirement("< 1.2") - assert_nil Gem::Requirement.default.for_lockfile - end + assert_satisfied_by("1.1", r) + refute_satisfied_by("1.2", r) + refute_satisfied_by("1.3", r) - def test_parse - assert_equal ['=', Gem::Version.new(1)], Gem::Requirement.parse(' 1') - assert_equal ['=', Gem::Version.new(1)], Gem::Requirement.parse('= 1') - assert_equal ['>', Gem::Version.new(1)], Gem::Requirement.parse('> 1') - assert_equal ['=', Gem::Version.new(1)], Gem::Requirement.parse("=\n1") - assert_equal ['=', Gem::Version.new(1)], Gem::Requirement.parse('1.0') - assert_equal ['=', Gem::Version.new(2)], - Gem::Requirement.parse(Gem::Version.new('2')) - end +def test_satisfied_by_eh_lte(): + r = GemRequirement("<= 1.2") - if RUBY_VERSION >= '2.5' && !(Gem.java_platform? && ENV["JRUBY_OPTS"] =~ /--debug/) - def test_parse_deduplication - assert_same '~>', Gem::Requirement.parse('~> 1').first - end - end + assert_satisfied_by("1.1", r) + assert_satisfied_by("1.2", r) + refute_satisfied_by("1.3", r) - def test_parse_bad - [ - nil, - '', - '! 1', - '= junk', - '1..2', - ].each do |bad| - e = assert_raise Gem::Requirement::BadRequirementError do - Gem::Requirement.parse bad - end - assert_equal "Illformed requirement [#{bad.inspect}]", e.message - end +def test_satisfied_by_eh_tilde_gt(): + r = GemRequirement("~> 1.2") - assert_equal Gem::Requirement::BadRequirementError.superclass, ArgumentError - end + refute_satisfied_by("1.1", r) + assert_satisfied_by("1.2", r) + assert_satisfied_by("1.3", r) - def test_prerelease_eh - r = req '= 1' - refute r.prerelease? +def test_satisfied_by_eh_tilde_gt_v0(): + r = GemRequirement("~> 0.0.1") - r = req '= 1.a' + refute_satisfied_by("0.1.1", r) + assert_satisfied_by("0.0.2", r) + assert_satisfied_by("0.0.1", r) - assert r.prerelease? - r = req '> 1.a', '< 2' +def test_satisfied_by_eh_good(): + assert_satisfied_by("0.2.33", "= 0.2.33") + assert_satisfied_by("0.2.34", "> 0.2.33") + assert_satisfied_by("1.0", "= 1.0") + assert_satisfied_by("1.0.0", "= 1.0") + assert_satisfied_by("1.0", "= 1.0.0") + assert_satisfied_by("1.0", "1.0") + assert_satisfied_by("1.8.2", "> 1.8.0") + assert_satisfied_by("1.112", "> 1.111") + assert_satisfied_by("0.2", "> 0.0.0") + assert_satisfied_by("0.0.0.0.0.2", "> 0.0.0") + assert_satisfied_by("0.0.1.0", "> 0.0.0.1") + assert_satisfied_by("10.3.2", "> 9.3.2") + assert_satisfied_by("1.0.0.0", "= 1.0") + assert_satisfied_by("10.3.2", "!= 9.3.4") + assert_satisfied_by("10.3.2", "> 9.3.2") + assert_satisfied_by(" 9.3.2", ">= 9.3.2") + assert_satisfied_by("9.3.2 ", ">= 9.3.2") + assert_satisfied_by("", "= 0") + assert_satisfied_by("", "< 0.1") + assert_satisfied_by(" ", "< 0.1 ") + assert_satisfied_by("", " < 0.1") + assert_satisfied_by(" ", "> 0.a ") + assert_satisfied_by("", " > 0.a") + assert_satisfied_by("3.1", "< 3.2.rc1") - assert r.prerelease? - end + assert_satisfied_by("3.2.0", "> 3.2.0.rc1") + assert_satisfied_by("3.2.0.rc2", "> 3.2.0.rc1") - def test_satisfied_by_eh_bang_equal - r = req '!= 1.2' + assert_satisfied_by("3.0.rc2", "< 3.0") + assert_satisfied_by("3.0.rc2", "< 3.0.0") + assert_satisfied_by("3.0.rc2", "< 3.0.1") - assert_satisfied_by "1.1", r - refute_satisfied_by "1.2", r - assert_satisfied_by "1.3", r - - assert_raise ArgumentError do - assert_satisfied_by nil, r - end - end + assert_satisfied_by("3.0.rc2", "> 0") - def test_satisfied_by_eh_blank - r = req "1.2" + assert_satisfied_by("5.0.0.rc2", "~> 5.a") + refute_satisfied_by("5.0.0.rc2", "~> 5.x") - refute_satisfied_by "1.1", r - assert_satisfied_by "1.2", r - refute_satisfied_by "1.3", r + assert_satisfied_by("5.0.0", "~> 5.a") + assert_satisfied_by("5.0.0", "~> 5.x") - assert_raise ArgumentError do - assert_satisfied_by nil, r - end - end - - def test_satisfied_by_eh_equal - r = req "= 1.2" - - refute_satisfied_by "1.1", r - assert_satisfied_by "1.2", r - refute_satisfied_by "1.3", r - - assert_raise ArgumentError do - assert_satisfied_by nil, r - end - end - - def test_satisfied_by_eh_gt - r = req "> 1.2" - - refute_satisfied_by "1.1", r - refute_satisfied_by "1.2", r - assert_satisfied_by "1.3", r - - assert_raise ArgumentError do - r.satisfied_by? nil - end - end - - def test_satisfied_by_eh_gte - r = req ">= 1.2" - - refute_satisfied_by "1.1", r - assert_satisfied_by "1.2", r - assert_satisfied_by "1.3", r - - assert_raise ArgumentError do - r.satisfied_by? nil - end - end - - def test_satisfied_by_eh_list - r = req "> 1.1", "< 1.3" - - refute_satisfied_by "1.1", r - assert_satisfied_by "1.2", r - refute_satisfied_by "1.3", r - - assert_raise ArgumentError do - r.satisfied_by? nil - end - end - - def test_satisfied_by_eh_lt - r = req "< 1.2" - - assert_satisfied_by "1.1", r - refute_satisfied_by "1.2", r - refute_satisfied_by "1.3", r - - assert_raise ArgumentError do - r.satisfied_by? nil - end - end - - def test_satisfied_by_eh_lte - r = req "<= 1.2" - - assert_satisfied_by "1.1", r - assert_satisfied_by "1.2", r - refute_satisfied_by "1.3", r - - assert_raise ArgumentError do - r.satisfied_by? nil - end - end - - def test_satisfied_by_eh_tilde_gt - r = req "~> 1.2" - - refute_satisfied_by "1.1", r - assert_satisfied_by "1.2", r - assert_satisfied_by "1.3", r - - assert_raise ArgumentError do - r.satisfied_by? nil - end - end - - def test_satisfied_by_eh_tilde_gt_v0 - r = req "~> 0.0.1" - - refute_satisfied_by "0.1.1", r - assert_satisfied_by "0.0.2", r - assert_satisfied_by "0.0.1", r - end - - def test_satisfied_by_eh_good - assert_satisfied_by "0.2.33", "= 0.2.33" - assert_satisfied_by "0.2.34", "> 0.2.33" - assert_satisfied_by "1.0", "= 1.0" - assert_satisfied_by "1.0.0", "= 1.0" - assert_satisfied_by "1.0", "= 1.0.0" - assert_satisfied_by "1.0", "1.0" - assert_satisfied_by "1.8.2", "> 1.8.0" - assert_satisfied_by "1.112", "> 1.111" - assert_satisfied_by "0.2", "> 0.0.0" - assert_satisfied_by "0.0.0.0.0.2", "> 0.0.0" - assert_satisfied_by "0.0.1.0", "> 0.0.0.1" - assert_satisfied_by "10.3.2", "> 9.3.2" - assert_satisfied_by "1.0.0.0", "= 1.0" - assert_satisfied_by "10.3.2", "!= 9.3.4" - assert_satisfied_by "10.3.2", "> 9.3.2" - assert_satisfied_by " 9.3.2", ">= 9.3.2" - assert_satisfied_by "9.3.2 ", ">= 9.3.2" - assert_satisfied_by "", "= 0" - assert_satisfied_by "", "< 0.1" - assert_satisfied_by " ", "< 0.1 " - assert_satisfied_by "", " < 0.1" - assert_satisfied_by " ", "> 0.a " - assert_satisfied_by "", " > 0.a" - assert_satisfied_by "3.1", "< 3.2.rc1" - - assert_satisfied_by "3.2.0", "> 3.2.0.rc1" - assert_satisfied_by "3.2.0.rc2", "> 3.2.0.rc1" - - assert_satisfied_by "3.0.rc2", "< 3.0" - assert_satisfied_by "3.0.rc2", "< 3.0.0" - assert_satisfied_by "3.0.rc2", "< 3.0.1" - - assert_satisfied_by "3.0.rc2", "> 0" - - assert_satisfied_by "5.0.0.rc2", "~> 5.a" - refute_satisfied_by "5.0.0.rc2", "~> 5.x" - - assert_satisfied_by "5.0.0", "~> 5.a" - assert_satisfied_by "5.0.0", "~> 5.x" - end - - def test_illformed_requirements - [ ">>> 1.3.5", "> blah" ].each do |rq| - assert_raise Gem::Requirement::BadRequirementError, "req [#{rq}] should fail" do - Gem::Requirement.new rq - end - end - end - - def test_satisfied_by_eh_non_versions - assert_raise ArgumentError do - req(">= 0").satisfied_by? Object.new - end - - assert_raise ArgumentError do - req(">= 0").satisfied_by? Gem::Requirement.default - end - end - - def test_satisfied_by_eh_boxed - refute_satisfied_by "1.3", "~> 1.4" - assert_satisfied_by "1.4", "~> 1.4" - assert_satisfied_by "1.5", "~> 1.4" - refute_satisfied_by "2.0", "~> 1.4" - - refute_satisfied_by "1.3", "~> 1.4.4" - refute_satisfied_by "1.4", "~> 1.4.4" - assert_satisfied_by "1.4.4", "~> 1.4.4" - assert_satisfied_by "1.4.5", "~> 1.4.4" - refute_satisfied_by "1.5", "~> 1.4.4" - refute_satisfied_by "2.0", "~> 1.4.4" - - refute_satisfied_by "1.1.pre", "~> 1.0.0" - refute_satisfied_by "1.1.pre", "~> 1.1" - refute_satisfied_by "2.0.a", "~> 1.0" - refute_satisfied_by "2.0.a", "~> 2.0" - - refute_satisfied_by "0.9", "~> 1" - assert_satisfied_by "1.0", "~> 1" - assert_satisfied_by "1.1", "~> 1" - refute_satisfied_by "2.0", "~> 1" - end - - def test_satisfied_by_eh_multiple + +def test_illformed_requirements(): + bads = [">>> 1.3.5", "> blah"] + for bad in bads: + try: + GemRequirement.parse(bad) + raise Exception("exception not raised") + except GemRequirement.BadRequirementError: + pass + + +def test_satisfied_by_eh_boxed(): + refute_satisfied_by("1.3", "~> 1.4") + assert_satisfied_by("1.4", "~> 1.4") + assert_satisfied_by("1.5", "~> 1.4") + refute_satisfied_by("2.0", "~> 1.4") + + refute_satisfied_by("1.3", "~> 1.4.4") + refute_satisfied_by("1.4", "~> 1.4.4") + assert_satisfied_by("1.4.4", "~> 1.4.4") + assert_satisfied_by("1.4.5", "~> 1.4.4") + refute_satisfied_by("1.5", "~> 1.4.4") + refute_satisfied_by("2.0", "~> 1.4.4") + + refute_satisfied_by("1.1.pre", "~> 1.0.0") + refute_satisfied_by("1.1.pre", "~> 1.1") + refute_satisfied_by("2.0.a", "~> 1.0") + refute_satisfied_by("2.0.a", "~> 2.0") + + refute_satisfied_by("0.9", "~> 1") + assert_satisfied_by("1.0", "~> 1") + assert_satisfied_by("1.1", "~> 1") + refute_satisfied_by("2.0", "~> 1") + + +def test_satisfied_by_eh_multiple(): req = [">= 1.4", "<= 1.6", "!= 1.5"] - refute_satisfied_by "1.3", req - assert_satisfied_by "1.4", req - refute_satisfied_by "1.5", req - assert_satisfied_by "1.6", req - refute_satisfied_by "1.7", req - refute_satisfied_by "2.0", req - end - - def test_satisfied_by_boxed - refute_satisfied_by "1.3", "~> 1.4" - assert_satisfied_by "1.4", "~> 1.4" - assert_satisfied_by "1.4.0", "~> 1.4" - assert_satisfied_by "1.5", "~> 1.4" - refute_satisfied_by "2.0", "~> 1.4" - - refute_satisfied_by "1.3", "~> 1.4.4" - refute_satisfied_by "1.4", "~> 1.4.4" - assert_satisfied_by "1.4.4", "~> 1.4.4" - assert_satisfied_by "1.4.5", "~> 1.4.4" - refute_satisfied_by "1.5", "~> 1.4.4" - refute_satisfied_by "2.0", "~> 1.4.4" - end - - def test_satisfied_by_explicitly_bounded + refute_satisfied_by("1.3", req) + assert_satisfied_by("1.4", req) + refute_satisfied_by("1.5", req) + assert_satisfied_by("1.6", req) + refute_satisfied_by("1.7", req) + refute_satisfied_by("2.0", req) + + +def test_satisfied_by_boxed(): + refute_satisfied_by("1.3", "~> 1.4") + assert_satisfied_by("1.4", "~> 1.4") + assert_satisfied_by("1.4.0", "~> 1.4") + assert_satisfied_by("1.5", "~> 1.4") + refute_satisfied_by("2.0", "~> 1.4") + + refute_satisfied_by("1.3", "~> 1.4.4") + refute_satisfied_by("1.4", "~> 1.4.4") + assert_satisfied_by("1.4.4", "~> 1.4.4") + assert_satisfied_by("1.4.5", "~> 1.4.4") + refute_satisfied_by("1.5", "~> 1.4.4") + refute_satisfied_by("2.0", "~> 1.4.4") + + +def test_satisfied_by_explicitly_bounded(): req = [">= 1.4.4", "< 1.5"] - assert_satisfied_by "1.4.5", req - assert_satisfied_by "1.5.0.rc1", req - refute_satisfied_by "1.5.0", req + assert_satisfied_by("1.4.5", req) + assert_satisfied_by("1.5.0.rc1", req) + refute_satisfied_by("1.5.0", req) req = [">= 1.4.4", "< 1.5.a"] - assert_satisfied_by "1.4.5", req - refute_satisfied_by "1.5.0.rc1", req - refute_satisfied_by "1.5.0", req - end - - def test_specific - refute req('> 1') .specific? - refute req('>= 1').specific? - - assert req('!= 1').specific? - assert req('< 1') .specific? - assert req('<= 1').specific? - assert req('= 1') .specific? - assert req('~> 1').specific? - - assert req('> 1', '> 2').specific? # GIGO - end - - def test_bad - refute_satisfied_by "", "> 0.1" - refute_satisfied_by "1.2.3", "!= 1.2.3" - refute_satisfied_by "1.2.003.0.0", "!= 1.02.3" - refute_satisfied_by "4.5.6", "< 1.2.3" - refute_satisfied_by "1.0", "> 1.1" - refute_satisfied_by "", "= 0.1" - refute_satisfied_by "1.1.1", "> 1.1.1" - refute_satisfied_by "1.2", "= 1.1" - refute_satisfied_by "1.40", "= 1.1" - refute_satisfied_by "1.3", "= 1.40" - refute_satisfied_by "9.3.3", "<= 9.3.2" - refute_satisfied_by "9.3.1", ">= 9.3.2" - refute_satisfied_by "9.3.03", "<= 9.3.2" - refute_satisfied_by "1.0.0.1", "= 1.0" - end - - def test_hash_with_multiple_versions - r1 = req('1.0', '2.0') - r2 = req('2.0', '1.0') - assert_equal r1.hash, r2.hash - - r1 = req('1.0', '2.0').tap {|r| r.concat(['3.0']) } - r2 = req('3.0', '1.0').tap {|r| r.concat(['2.0']) } - assert_equal r1.hash, r2.hash - end - - def test_hash_returns_equal_hashes_for_equivalent_requirements - refute_requirement_hash_equal "= 1.2", "= 1.3" - refute_requirement_hash_equal "= 1.3", "= 1.2" - - refute_requirement_hash_equal "~> 1.3", "~> 1.3.0" - refute_requirement_hash_equal "~> 1.3.0", "~> 1.3" - - assert_requirement_hash_equal ["> 2", "~> 1.3", "~> 1.3.1"], ["~> 1.3.1", "~> 1.3", "> 2"] - - assert_requirement_hash_equal ["> 2", "~> 1.3"], ["> 2.0", "~> 1.3"] - assert_requirement_hash_equal ["> 2.0", "~> 1.3"], ["> 2", "~> 1.3"] - - assert_requirement_hash_equal "= 1.0", "= 1.0.0" - assert_requirement_hash_equal "= 1.1", "= 1.1.0" - assert_requirement_hash_equal "= 1", "= 1.0.0" - - assert_requirement_hash_equal "1.0", "1.0.0" - assert_requirement_hash_equal "1.1", "1.1.0" - assert_requirement_hash_equal "1", "1.0.0" - end - - class Exploit < RuntimeError - end - - def self.exploit(arg) - raise Exploit, "arg = #{arg}" - end - - def test_marshal_load_attack - wa = Net::WriteAdapter.allocate - wa.instance_variable_set(:@socket, self.class) - wa.instance_variable_set(:@method_id, :exploit) - request_set = Gem::RequestSet.allocate - request_set.instance_variable_set(:@git_set, "id") - request_set.instance_variable_set(:@sets, wa) - wa = Net::WriteAdapter.allocate - wa.instance_variable_set(:@socket, request_set) - wa.instance_variable_set(:@method_id, :resolve) - ent = Gem::Package::TarReader::Entry.allocate - ent.instance_variable_set(:@read, 0) - ent.instance_variable_set(:@header, "aaa") - io = Net::BufferedIO.allocate - io.instance_variable_set(:@io, ent) - io.instance_variable_set(:@debug_output, wa) - reader = Gem::Package::TarReader.allocate - reader.instance_variable_set(:@io, io) - requirement = Gem::Requirement.allocate - requirement.instance_variable_set(:@requirements, reader) - m = [Gem::SpecFetcher, Gem::Installer, requirement] - e = assert_raise(TypeError) do - Marshal.load(Marshal.dump(m)) - end - assert_equal(e.message, "wrong @requirements") - end - - # Assert that two requirements are equal. Handles Gem::Requirements, - # strings, arrays, numbers, and versions. - - def assert_requirement_equal(expected, actual) - assert_equal req(expected), req(actual) - end - - # Assert that +version+ satisfies +requirement+. - - def assert_satisfied_by(version, requirement) - assert req(requirement).satisfied_by?(v(version)), - "#{requirement} is satisfied by #{version}" - end - - # Assert that two requirement hashes are equal. Handles Gem::Requirements, - # strings, arrays, numbers, and versions. - - def assert_requirement_hash_equal(expected, actual) - assert_equal req(expected).hash, req(actual).hash - end - - # Refute the assumption that two requirements are equal. - - def refute_requirement_equal(unexpected, actual) - refute_equal req(unexpected), req(actual) - end - - # Refute the assumption that +version+ satisfies +requirement+. - - def refute_satisfied_by(version, requirement) - refute req(requirement).satisfied_by?(v(version)), - "#{requirement} is not satisfied by #{version}" - end - - # Refute the assumption that two requirements hashes are equal. - - def refute_requirement_hash_equal(unexpected, actual) - refute_equal req(unexpected).hash, req(actual).hash - end -end + assert_satisfied_by("1.4.5", req) + refute_satisfied_by("1.5.0.rc1", req) + refute_satisfied_by("1.5.0", req) + + +def test_bad(): + refute_satisfied_by("", "> 0.1") + refute_satisfied_by("1.2.3", "!= 1.2.3") + refute_satisfied_by("1.2.003.0.0", "!= 1.02.3") + refute_satisfied_by("4.5.6", "< 1.2.3") + refute_satisfied_by("1.0", "> 1.1") + refute_satisfied_by("", "= 0.1") + refute_satisfied_by("1.1.1", "> 1.1.1") + refute_satisfied_by("1.2", "= 1.1") + refute_satisfied_by("1.40", "= 1.1") + refute_satisfied_by("1.3", "= 1.40") + refute_satisfied_by("9.3.3", "<= 9.3.2") + refute_satisfied_by("9.3.1", ">= 9.3.2") + refute_satisfied_by("9.3.03", "<= 9.3.2") + refute_satisfied_by("1.0.0.1", "= 1.0") + + +def test_equal_with_multiple_versions(): + r1 = GemRequirement("1.0", "2.0") + r2 = GemRequirement("2.0", "1.0") + assert r1 == r2 + + r1 = GemRequirement("1.0", "2.0", "3.0") + r2 = GemRequirement("3.0", "1.0", "2.0") + assert r1 == r2 + + +def test_equivalent_requirements_are_equal(): + refute_requirement_equal("= 1.2", "= 1.3") + refute_requirement_equal("= 1.3", "= 1.2") + + refute_requirement_equal("~> 1.3", "~> 1.3.0") + refute_requirement_equal("~> 1.3.0", "~> 1.3") + + assert_requirement_equal(["> 2", "~> 1.3", "~> 1.3.1"], ["~> 1.3.1", "~> 1.3", "> 2"]) + + assert_requirement_equal(["> 2", "~> 1.3"], ["> 2.0", "~> 1.3"]) + assert_requirement_equal(["> 2.0", "~> 1.3"], ["> 2", "~> 1.3"]) + + assert_requirement_equal("= 1.0", "= 1.0.0") + assert_requirement_equal("= 1.1", "= 1.1.0") + assert_requirement_equal("= 1", "= 1.0.0") + + assert_requirement_equal("1.0", "1.0.0") + assert_requirement_equal("1.1", "1.1.0") + assert_requirement_equal("1", "1.0.0") + + +def assert_requirement_equal(expected, actual): + # Assert that two requirements are equal. Handles GemRequirements, + # strings, arrays, numbers, and versions. + assert GemRequirement.create(actual) == GemRequirement.create(expected) + + +def assert_satisfied_by(version, requirement): + # Assert that +version+ satisfies +requirement+. + assert GemRequirement.create(requirement).satisfied_by(GemVersion(version)) + + +def refute_requirement_equal(unexpected, actual): + # Refute the assumption that two requirements are equal. + assert GemRequirement.create(actual) != GemRequirement.create(unexpected) + + +def refute_satisfied_by(version, requirement): + # Refute the assumption that +version+ satisfies +requirement+. + assert not GemRequirement.create(requirement).satisfied_by(GemVersion(version)) + + +def refute_requirement_equal(unexpected, actual): + # Refute the assumption that two requirements hashes are equal. + assert GemRequirement.create(actual) != GemRequirement.create(unexpected) From 73cd1827244445b0e5b52e2c7f57d2aedf159922 Mon Sep 17 00:00:00 2001 From: Philippe Ombredanne Date: Mon, 6 Dec 2021 13:42:03 +0100 Subject: [PATCH 691/707] Add GemRequirement.create() and for_lockfile() These functions are helping with the upcoming Rubygems tests port. Signed-off-by: Philippe Ombredanne --- src/univers/gem.py | 52 +++++++++++++++++++++++++++++++++++++++------- 1 file changed, 45 insertions(+), 7 deletions(-) diff --git a/src/univers/gem.py b/src/univers/gem.py index 5264222f..4d74235a 100644 --- a/src/univers/gem.py +++ b/src/univers/gem.py @@ -9,6 +9,7 @@ import re +from collections import namedtuple def default(x, e, y): @@ -133,6 +134,14 @@ def __get_segments(self): return self.__segments +GemConstraint = namedtuple("GemConstraint", ["op", "version"]) +GemConstraint.to_string = lambda gc: f"{gc.op} {gc.version}" + + +def sorted_constraints(constraints): + return sorted(constraints, key=lambda gc: gc.version) + + class GemRequirement: """ A gem requirement using the Gem notation. @@ -156,7 +165,7 @@ class GemRequirement: # A regular expression that matches a requirement PATTERN = re.compile("^{PATTERN_RAW}$".format(PATTERN_RAW=PATTERN_RAW)) - ## + # # # The default requirement matches any version DEFAULT_REQUIREMENT = tuple([">=", GemVersion(0)]) @@ -165,17 +174,45 @@ class BadRequirementError(AttributeError): pass def __init__(self, *requirements): - # type: (str) -> None - if len(requirements) == 0: - self.__requirements = tuple([GemRequirement.DEFAULT_REQUIREMENT]) + + if not requirements: + self.requirements = tuple([GemRequirement.DEFAULT_REQUIREMENT]) + else: - self.__requirements = tuple(map(lambda req: GemRequirement.parse(req), requirements)) + self.requirements = tuple(map(GemRequirement.parse, requirements)) + + def for_lockfile(self): + """ + Return a string representing this list of requirements suitable for use + in a lockfile. + + For example:: + >>> gr = GemRequirement(">= 1.0.1", "~> 1.0") + >>> gf_flf = gr.for_lockfile() + >>> assert gf_flf == " (~> 1.0, >= 1.0.1)", gf_flf + """ + + gcs = [GemConstraint(*r) for r in self.requirements] + gcs = [gc.to_string() for gc in sorted_constraints(gcs)] + reqss = ", ".join(gcs) + return f" ({reqss})" + + @classmethod + def create(cls, reqs): + """ + Return a GemRequirement built from a single requirement string or a list + of requirement strings. + """ + if isinstance(reqs, list): + return GemRequirement(*reqs) + else: + return GemRequirement(reqs) @classmethod def parse(cls, requirement): """ Return a tuple of (operator string, GemVersion object) parsed from a - ``requirements`` string. + saingle ``requirement`` string. """ if isinstance(requirement, GemVersion): return tuple(["=", requirement]) @@ -199,7 +236,7 @@ def satified_by(self, version): """ gemver = version if isinstance(version, GemVersion) else GemVersion(version) operation = self.__test_rv(gemver) - return all(map(operation, self.__requirements)) + return all(map(operation, self.requirements)) @classmethod def __test_rv(cls, version): @@ -207,6 +244,7 @@ def __test_rv(cls, version): Return a callable function that can check if a ``version`` satisfies the operation of a single (op, version) requirement. """ + # type: (GemVersion) -> Callable[[str, GemVersion], bool] def __testing(req): op, rv = req From c44f29e7bc02f0794983e9d70aab8bd2bbc21792 Mon Sep 17 00:00:00 2001 From: Philippe Ombredanne Date: Tue, 7 Dec 2021 17:36:33 +0100 Subject: [PATCH 692/707] Implement proper Rubygems version support Reference: https://github.com/nexB/univers/issues/5 Reported-by: Oliver Chang @oliverchang Signed-off-by: Philippe Ombredanne --- src/univers/gem.py | 719 +++++++++++++++++----- src/univers/gem.py.ABOUT | 21 +- src/univers/utils.py | 6 +- src/univers/versions.py | 2 +- tests/test_bundler_version_ranges_spec.py | 83 ++- tests/test_gem.py | 52 +- tests/test_rubygems_gem_requirement.py | 81 ++- tests/test_rubygems_gem_version.py | 209 +++---- 8 files changed, 810 insertions(+), 363 deletions(-) diff --git a/src/univers/gem.py b/src/univers/gem.py index 4d74235a..310df864 100644 --- a/src/univers/gem.py +++ b/src/univers/gem.py @@ -1,145 +1,490 @@ +# Copyright (c) nexB, Inc. and others. # Copyright (c) Center for Information Technology, http://coi.gov.pl -# SPDX-License-Identifier: Apache-2.0 -# this has been significantly modified from the original +# Copyright (c) Chad Fowler, Rich Kilmer, Jim Weirich and others. +# Copyright (c) Engine Yard and Andre Arko, Facebook, Inc. and its affiliates. +# +# SPDX-License-Identifier: Apache-2.0 AND MIT +# This has been significantly modified from the original # # Visit https://aboutcode.org and https://github.com/nexB/univers for support and download. # notes: This has been substantially modified and enhanced from the original # puppeteer code to extract the Ruby version hanlding code. +# This code is in turn originally based and updated from the Rubygems code +# Originally from https://github.com/rubygems/rubygems and +# https://github.com/coi-gov-pl/puppeter - +import operator import re from collections import namedtuple +from itertools import dropwhile + + +class InvalidRequirementError(AttributeError): + pass -def default(x, e, y): - try: - return x() - except e: - return y +class InvalidVersionError(ValueError): + pass class GemVersion: - VERSION_PATTERN = "[0-9]+(?:\.[0-9a-zA-Z]+)*(-[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?" - ANCHORED_VERSION_PATTERN = re.compile( - "^\s*({VERSION_PATTERN})?\s*$".format(VERSION_PATTERN=VERSION_PATTERN) - ) + """ + The Rubygems version.rb has this documentation + The Version class processes string versions into comparable + values. A version string should normally be a series of numbers + separated by periods. Each part (digits separated by periods) is + considered its own number, and these are used for sorting. So for + instance, 3.10 sorts higher than 3.2 because ten is greater than + two. + + If any part contains letters (currently only a-z are supported) then + that version is considered prerelease. Versions with a prerelease + part in the Nth part sort less than versions with N-1 + parts. Prerelease parts are sorted alphabetically using the normal + Ruby string sorting rules. If a prerelease part contains both + letters and numbers, it will be broken into multiple parts to + provide expected sort behavior (1.0.a10 becomes 1.0.a.10, and is + greater than 1.0.a9). + + Prereleases sort between real releases (newest to oldest): + + 1. 1.0 + 2. 1.0.b1 + 3. 1.0.a.2 + 4. 0.9 + + If you want to specify a version restriction that includes both prereleases + and regular releases of the 1.x series this is the best way: + + s.add_dependency 'example', '>= 1.0.0.a', '< 2.0.0' + + == How Software Changes + + Users expect to be able to specify a version constraint that gives them + some reasonable expectation that new versions of a library will work with + their software if the version constraint is true, and not work with their + software if the version constraint is false. In other words, the perfect + system will accept all compatible versions of the library and reject all + incompatible versions. + + Libraries change in 3 ways (well, more than 3, but stay focused here!). + + 1. The change may be an implementation detail only and have no effect on + the client software. + 2. The change may add new features, but do so in a way that client software + written to an earlier version is still compatible. + 3. The change may change the public interface of the library in such a way + that old software is no longer compatible. + + Some examples are appropriate at this point. Suppose I have a Stack class + that supports a push and a pop method. + + === Examples of Category 1 changes: + + * Switch from an array based implementation to a linked-list based + implementation. + * Provide an automatic (and transparent) backing store for large stacks. + + === Examples of Category 2 changes might be: + + * Add a depth method to return the current depth of the stack. + * Add a top method that returns the current top of stack (without + changing the stack). + * Change push so that it returns the item pushed (previously it + had no usable return value). + + === Examples of Category 3 changes might be: + + * Changes pop so that it no longer returns a value (you must use + top to get the top of the stack). + * Rename the methods to push_item and pop_item. + + == RubyGems Rational Versioning + + * Versions shall be represented by three non-negative integers, separated + by periods (e.g. 3.1.4). The first integers is the "major" version + number, the second integer is the "minor" version number, and the third + integer is the "build" number. + + * A category 1 change (implementation detail) will increment the build + number. + + * A category 2 change (backwards compatible) will increment the minor + version number and reset the build number. + + * A category 3 change (incompatible) will increment the major build number + and reset the minor and build numbers. + + * Any "public" release of a gem should have a different version. Normally + that means incrementing the build number. This means a developer can + generate builds all day long, but as soon as they make a public release, + the version must be updated. + + === Examples + + Let's work through a project lifecycle using our Stack example from above. + + Version 0.0.1:: The initial Stack class is release. + Version 0.0.2:: Switched to a linked=list implementation because it is + cooler. + Version 0.1.0:: Added a depth method. + Version 1.0.0:: Added top and made pop return nil + (pop used to return the old top item). + Version 1.1.0:: push now returns the value pushed (it used it + return nil). + Version 1.1.1:: Fixed a bug in the linked list implementation. + Version 1.1.2:: Fixed a bug introduced in the last fix. + + Client A needs a stack with basic push/pop capability. They write to the + original interface (no top), so their version constraint looks like: + + gem 'stack', '>= 0.0' + + Essentially, any version is OK with Client A. An incompatible change to + the library will cause them grief, but they are willing to take the chance + (we call Client A optimistic). + + Client B is just like Client A except for two things: (1) They use the + depth method and (2) they are worried about future + incompatibilities, so they write their version constraint like this: + + gem 'stack', '~> 0.1' + + The depth method was introduced in version 0.1.0, so that version + or anything later is fine, as long as the version stays below version 1.0 + where incompatibilities are introduced. We call Client B pessimistic + because they are worried about incompatible future changes (it is OK to be + pessimistic!). + + == Preventing Version Catastrophe: + + From: http://blog.zenspider.com/2008/10/rubygems-howto-preventing-cata.html + + Let's say you're depending on the fnord gem version 2.y.z. If you + specify your dependency as ">= 2.0.0" then, you're good, right? What + happens if fnord 3.0 comes out and it isn't backwards compatible + with 2.y.z? Your stuff will break as a result of using ">=". The + better route is to specify your dependency with an "approximate" version + specifier ("~>"). They're a tad confusing, so here is how the dependency + specifiers work: + + Specification From ... To (exclusive) + ">= 3.0" 3.0 ... ∞ + "~> 3.0" 3.0 ... 4.0 + "~> 3.0.0" 3.0.0 ... 3.1 + "~> 3.5" 3.5 ... 4.0 + "~> 3.5.0" 3.5.0 ... 3.6 + "~> 3" 3.0 ... 4.0 + + For the last example, single-digit versions are automatically extended with + a zero to give a sensible result. + """ + + VERSION_PATTERN = r"[0-9]+(?:\.[0-9a-zA-Z]+)*(-[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?" + is_correct = re.compile(rf"^\s*({VERSION_PATTERN})?\s*$").match def __init__(self, version): + """ + Construct a Version from the ``version`` string. A version string is a + series of digits or ASCII letters separated by dots and may contain dash + "-". + """ + if isinstance(version, (int, GemVersion)): + version = str(version) - self.original = version + if not isinstance(version, str): + raise InvalidVersionError(version) + + if not self.is_correct(version): + raise InvalidVersionError(version) # If version is an empty string convert it to 0 - version = 0 if re.compile("^\s*$").match(str(version)) else version + version = str(version).strip() + + self.original = version + + if not version: + version = "0" - self.__version = str(version).strip().replace("-", ".pre.") - self.__segments = None - self.__bump = None - self.__release = None + self.version = version.replace("-", ".pre.") + self._segments = () + self._canonical_segments = () + self._bump = None + self._release = None def __str__(self): return self.original + to_string = __str__ + + def __repr__(self): + return f"GemVersion({self.original!r})" + + def equal_strictly(self, other): + return self.version == other.version + + def __hash__(self): + return hash(self.canonical_segments) + + def __eq__(self, other): + return self.canonical_segments == other.canonical_segments + + def __lt__(self, other): + return self.__cmp__(other) < 0 + + def __le__(self, other): + return self.__cmp__(other) <= 0 + + def __gt__(self, other): + return self.__cmp__(other) > 0 + + def __ge__(self, other): + return self.__cmp__(other) >= 0 + def bump(self): """ - Return a new GemVersion built from incrementing this GemVersion last - numeric segment. + Return a new version object where the next to the last revision number + is one greater (e.g., 5.3.1 => 5.4) i.e., incrementing this GemVersion + last numeric segment. + + For example:: + >>> assert GemVersion("5.3.1").bump() == GemVersion("5.4"), repr(GemVersion("5.3.1").bump()) + >>> assert GemVersion("5.3.1.4-2").bump() == GemVersion("5.3.2"), GemVersion("5.3.1.4-2").bump() """ - if not self.__bump: - segments = self.segments() - while any(map(lambda s: isinstance(s, str), segments)): - segments.pop() + if not self._bump: + segments = [] + for seg in self.segments: + if isinstance(seg, str): + break + else: + segments.append(seg) + if len(segments) > 1: segments.pop() - segments[-1] = segments[-1] + 1 - segments = list(map(lambda r: str(r), segments)) - self.__bump = GemVersion(".".join(segments)) - return self.__bump + segments[-1] += 1 + segments = [str(r) for r in segments] + self._bump = GemVersion(".".join(segments)) + + return self._bump def release(self): """ - Return a new GemVersion composed only of release, numeric segments. + Return a new GemVersion which is the release for this version (e.g., + 1.2.0.a -> 1.2.0). Non-prerelease versions return themselves. A release + is composed only of numeric segments. """ - if not self.__release: - segments = self.segments() - while any(map(lambda s: isinstance(s, str), segments)): - segments.pop() - segments = list(map(lambda r: str(r), segments)) - self.__release = GemVersion(".".join(segments)) - - return self.__release + if not self._release: + if self.prerelease(): + segments = self.segments + while any(isinstance(s, str) for s in segments): + segments.pop() + segments = (str(s) for s in segments) + self._release = GemVersion(".".join(segments)) + else: + self._release = self + + return self._release + + def prerelease(self): + """ + Return True if this is considered as a prerelease version. + A version is considered a prerelease if it contains a letter. + """ + return any(not str(s).isdigit() for s in self.segments) + @property def segments(self): """ - Return a list of version segments. + Return a new sequence of segments for this version where segments are + ints or strings parsed from the original version string. """ - return list(self.__get_segments()) + if not self._segments: + self._segments = self.get_segments() + return list(self._segments) - def __cmp__(self, other): + def get_segments(self): + """ + Return a sequence of segments for this version where segments are ints + or strings parsed from the original version string. + """ + find_segments = re.compile(r"[0-9]+|[a-z]+", re.IGNORECASE).findall + segments = [] + for seg in find_segments(self.version): + if seg.isdigit(): + seg = int(seg) + segments.append(seg) + return tuple(segments) + + @property + def canonical_segments(self): + if not self._canonical_segments: + self._canonical_segments = self.get_canonical_segments() + return list(self._canonical_segments) + + def get_canonical_segments(self): + """ + Return a new sequence of "canonical segments" for this version using + the Rubygems way. + """ + canonical_segments = [] + for segments in self.split_segments(): + segs = list(dropwhile(lambda s: s == 0, reversed(segments))) + segs = reversed(segs) + canonical_segments.extend(segs) + return tuple(canonical_segments) + + def split_segments(self): + """ + Return a two-tuple of segments: + - the first is a list of numeric-only segments starting from the left + - the second is a list of alpha or numericsegments starting with the + first alpha segment from the left. + """ + numeric_segments = [] + string_segments = [] + for seg in self.segments: + is_numeric = isinstance(seg, int) # or (isinstance(seg, str) and seg.isdigit()) + if is_numeric: + if string_segments: + string_segments.append(seg) + else: + numeric_segments.append(seg) + else: + string_segments.append(seg) + return numeric_segments, string_segments + + def __cmp__(self, other, trace=False): """ - Compare the ``other`` GemVersion with this GemVersion according to the - legacy "cmp()" function semantics. Return 0, 1, or -1. + Compare this version with ``other`` returning -1, 0, or 1 if the + other version is larger, the same, or smaller than this + one. Attempts to compare to something that's not a + ``GemVersion raises an exception. + + The comparison results have the same semantics as the legacy "cmp()" + built-in function. """ - if self.__version == other.__version: + if trace: + print(f"\nComparing: {self!r} with {other!r}") + if isinstance(other, str): + other = GemVersion(other) + if trace: + print(f" Converted to GemVersion: {other!r}") + + if not isinstance(other, GemVersion): + if trace: + print(f" Not a GemVersion: {other!r}") + return + + if self.version == other.version: + return 0 + + lhsegments = self.canonical_segments + if trace: + print(f" lhsegments: canonical_segments: {lhsegments!r}") + + rhsegments = other.canonical_segments + if trace: + print(f" rhsegments: canonical_segments: {rhsegments!r}") + + if lhsegments == rhsegments: + if trace: + print(f" lhsegments == rhsegments: returning 0") return 0 - lhsegments = self.__get_segments() - rhsegments = other.__get_segments() lhsize = len(lhsegments) rhsize = len(rhsegments) - limit = (lhsize if lhsize > rhsize else rhsize) - 1 + if trace: + print(f" lhsize: {lhsize!r}") + if trace: + print(f" rhsize: {rhsize!r}") + + if lhsize > rhsize: + if trace: + print(f" lhsize > rhsize: limit = lhsize: {lhsize!r}") + limit = lhsize + else: + if trace: + print(f" lhsize <= rhsize: limit = rhsize: {rhsize!r}") + limit = rhsize + + limit -= 1 i = 0 + if trace: + print(f" limit: {limit!r}, i: {i!r}") + while i <= limit: - lhs = default(lambda: lhsegments[i], IndexError, 0) - rhs = default(lambda: rhsegments[i], IndexError, 0) + if trace: + print(f" limit: {limit!r}, i: {i!r}") + + try: + lhs = lhsegments[i] + except IndexError: + lhs = 0 + + try: + rhs = rhsegments[i] + except IndexError: + rhs = 0 + i += 1 + if trace: + print(f" lhs: {lhs} rhs: {rhs} i: {i!r}") + if lhs == rhs: + if trace: + print(f" lhs == rhs: continue") continue + if isinstance(lhs, str) and isinstance(rhs, int): + if trace: + print(f" isinstance(lhs, str): {type(lhs)!r}") + print(f" isinstance(rhs, int): {type(rhs)!r}") + print(f" return -1") return -1 + if isinstance(lhs, int) and isinstance(rhs, str): + if trace: + print(f" isinstance(lhs, int): {type(lhs)!r}") + print(f" isinstance(rhs, str): {type(rhs)!r}") + print(f" return 1") return 1 - return lhs - rhs - return 0 - - def __lt__(self, other): - return self.__cmp__(other) < 0 - - def __le__(self, other): - return self.__cmp__(other) <= 0 - - def __eq__(self, other): - return self.__cmp__(other) == 0 + result = (lhs > rhs) - (lhs < rhs) + if trace: + print(f" (lhs > rhs) - (lhs < rhs):{result!r}") + print(f" return {result}") - def __repr__(self): - return "GemVersion({segments})".format(segments=self.segments()) + return result - def __get_segments(self): - """ - Return a sequence of ints and strings segments parsed from the original - version string. - """ - # type: () -> Sequence[int|str] - if not self.__segments: - rex = re.compile("[0-9]+|[a-z]+", re.IGNORECASE) - d_rex = re.compile("^\d+$") - self.__segments = tuple( - map(lambda s: int(s) if d_rex.match(s) else s, rex.findall(self.__version)) - ) - return self.__segments + if trace: + print(f" all options evaluated: return 0") + return 0 GemConstraint = namedtuple("GemConstraint", ["op", "version"]) GemConstraint.to_string = lambda gc: f"{gc.op} {gc.version}" -def sorted_constraints(constraints): - return sorted(constraints, key=lambda gc: gc.version) +def tilde_comparator(version, requirement, trace=False): + """ + Return True if ``version`` GemVersion satisfies ``requirement`` GemVersion + according to the Rubygems tilde semantics. + """ + if trace: + print(f" tilde_comparator: version: {version!r}, requirement: {requirement!r}") + print(f" version >= requirement: {version >= requirement!r}") + print() + print( + f" version.release() < requirement.bump(): {version.release()!r} " + f"< {requirement.bump()!r}: {version.release() < requirement.bump()!r}" + ) + + return version >= requirement and version.release() < requirement.bump() class GemRequirement: @@ -147,39 +492,59 @@ class GemRequirement: A gem requirement using the Gem notation. """ - OPS = { - "=": lambda v, r: v == r, - "!=": lambda v, r: v != r, - ">": lambda v, r: v > r, - "<": lambda v, r: v < r, - ">=": lambda v, r: v >= r, - "<=": lambda v, r: v <= r, - "~>": lambda v, r: v >= r and v.release() < r.bump(), + equal_op = operator.eq + comparators_by_op = { + "=": equal_op, + "!=": operator.ne, + ">": operator.gt, + "<": operator.lt, + ">=": operator.ge, + "<=": operator.le, + "~>": tilde_comparator, } - PATTERN_RAW = "\\s*({quoted})?\\s*({VERSION_PATTERN})\\s*".format( - quoted="|".join(tuple(map(lambda k: re.escape(k), iter(OPS)))), - VERSION_PATTERN=GemVersion.VERSION_PATTERN, - ) + quoted = "|".join(re.escape(op) for op in comparators_by_op) + + PATTERN_RAW = f"\\s*({quoted})?\\s*({GemVersion.VERSION_PATTERN})\\s*" # A regular expression that matches a requirement - PATTERN = re.compile("^{PATTERN_RAW}$".format(PATTERN_RAW=PATTERN_RAW)) + PATTERN = re.compile(f"^{PATTERN_RAW}$") - # # # The default requirement matches any version + DEFAULT_CONSTRAINT = GemConstraint(">=", GemVersion(0)) - DEFAULT_REQUIREMENT = tuple([">=", GemVersion(0)]) + def __init__(self, *requirements): + """ + Initialize a GemRequirement from a sequence of ``requirements`` + converted to a constraints sequence of GemConstraint. + """ + if not requirements: + self.constraints = (GemRequirement.DEFAULT_CONSTRAINT,) + else: + self.constraints = tuple([GemRequirement.parse(r) for r in requirements]) - class BadRequirementError(AttributeError): - pass + def __str__(self): + gcs = [gc.to_string() for gc in self.as_constraints(sort=True)] + return ", ".join(gcs) - def __init__(self, *requirements): + def __repr__(self): + gcs = ", ".join(repr(gc.to_string()) for gc in self.as_constraints(sort=True)) + return f"GemRequirement({gcs})" - if not requirements: - self.requirements = tuple([GemRequirement.DEFAULT_REQUIREMENT]) + @classmethod + def from_lockfile(cls, requirements): + """ + Return a GemRequirement build from a lockfile-style ``requirements`` + string. - else: - self.requirements = tuple(map(GemRequirement.parse, requirements)) + For example:: + >>> gr1 = GemRequirement(">= 1.0.1", "~> 1.0") + >>> gr2 = GemRequirement.from_lockfile(" (>= 1.0.1, ~> 1.0)") + >>> assert gr1 == gr2, (gr1, gr2) + """ + reqs = requirements.strip().strip("()") + reqs = [r.strip() for r in reqs.split(",")] + return cls(*reqs) def for_lockfile(self): """ @@ -191,11 +556,70 @@ def for_lockfile(self): >>> gf_flf = gr.for_lockfile() >>> assert gf_flf == " (~> 1.0, >= 1.0.1)", gf_flf """ + gcs = [gc.to_string() for gc in self.as_constraints(sort=True, unique=True)] + gcs = ", ".join(gcs) + return f" ({gcs})" + + def dedupe(self): + """ + Return a new GemRequirement with sorted and unique constraints. + """ + return GemRequirement(*self.as_constraints(sort=True, unique=True)) - gcs = [GemConstraint(*r) for r in self.requirements] - gcs = [gc.to_string() for gc in sorted_constraints(gcs)] - reqss = ", ".join(gcs) - return f" ({reqss})" + def __eq__(self, other): + if not isinstance(other, self.__class__): + return False + + # An == check is always necessary + if self.as_constraints(sort=True, unique=True) == other.as_constraints( + sort=True, unique=True + ): + stilde = self.tilde_requirements() + if not stilde: + # An == check is sufficient unless any requirements use ~> + return True + else: + # If any requirements use ~> we use the stricter `#eql?` that + # also checks that version precision is the same + otilde = other.tilde_requirements() + if len(stilde) != len(otilde): + return False + for st, ot in zip(stilde, otilde): + if st.op != ot.op or not st.version.equal_strictly(ot.version): + return False + return True + return False + + def exact(self): + """ + Return True if the requirement is for only an exact version. + + For example: + >>> GemRequirement(">= 1.0.1", "~> 1.0").exact() + False + >>> GemRequirement("= 1.0.1", "~> 1.0").exact() + False + >>> GemRequirement("= 1.0.1").exact() + True + """ + return len(self.constraints) == 1 and self.constraints[0].op == "=" + + def as_constraints(self, sort=False, unique=False): + """ + Return a sequence of GemConstraints optionally sorted and deduplicated. + """ + constraints = self.constraints[:] + if sort: + constraints = sorted(constraints, key=lambda gc: (gc.version, gc.op)) + if unique: + consts = [] + for gc in constraints: + if gc in consts: + continue + consts.append(gc) + constraints = consts + + return constraints @classmethod def create(cls, reqs): @@ -204,62 +628,73 @@ def create(cls, reqs): of requirement strings. """ if isinstance(reqs, list): - return GemRequirement(*reqs) + return cls(*reqs) else: - return GemRequirement(reqs) + return cls(reqs) @classmethod def parse(cls, requirement): """ - Return a tuple of (operator string, GemVersion object) parsed from a - saingle ``requirement`` string. + Return a GemConstraint tuple of (operator string, GemVersion object) + parsed from a single ``requirement`` string such as "> 3.0". Also + accepts a two-tuple or list of ("op", "version") or a single GemVersion or a + GemConstraint). """ if isinstance(requirement, GemVersion): - return tuple(["=", requirement]) + return GemConstraint("=", requirement) + + if isinstance(requirement, (tuple, list, GemConstraint)): + return GemConstraint(*requirement) + + if not isinstance(requirement, str): + raise InvalidRequirementError("Illformed requirement {requirement!r}") match = cls.PATTERN.match(str(requirement)) if not match: - raise cls.BadRequirementError( - "Illformed requirement [{inspect}]".format(inspect=repr(requirement)) - ) + raise InvalidRequirementError("Illformed requirement {requirement!r}") if match.group(1) == ">=" and match.group(2) == "0": - return cls.DEFAULT_REQUIREMENT + return cls.DEFAULT_CONSTRAINT else: op = match.group(1) if match.group(1) else "=" - return tuple([op, GemVersion(match.group(2))]) + return GemConstraint(op, GemVersion(match.group(2))) - def satified_by(self, version): + def satisfied_by(self, version, trace=False): """ - Return True if the ``version`` GemVersion or string satisfied this - requirement. + Return True if the ``version`` GemVersion or version string or int + satisfies all the constraints of this requirement. Raise an + InvalidVersionError with an invalid ``version``. """ - gemver = version if isinstance(version, GemVersion) else GemVersion(version) - operation = self.__test_rv(gemver) - return all(map(operation, self.requirements)) - - @classmethod - def __test_rv(cls, version): - """ - Return a callable function that can check if a ``version`` satisfies the - operation of a single (op, version) requirement. - """ - - # type: (GemVersion) -> Callable[[str, GemVersion], bool] - def __testing(req): - op, rv = req - callble = cls.__get_operation(op) - return callble(version, rv) - - return __testing - - @classmethod - def __get_operation(cls, op): + if trace: + print(f"\nis {self!r} satisfied_by: {version!r} ?") + if not isinstance(version, GemVersion): + version = GemVersion(version) + if trace: + print(f" converting version to GemVersion: {version!r}") + + if not self.constraints: + raise InvalidRequirementError(self) + + for constraint in self.constraints: + if trace: + print(f" processing: {constraint!r}") + + op = constraint.op + comparator = self.comparators_by_op[op] + if trace: + print(f" got comparator: {comparator!r}") + satisfying = comparator(version, constraint.version) + if trace: + print(f" {self!r} is satisfied by: {version!r}: {satisfying!r}") + print(f" {version!r} {op} {constraint.version!r}: {satisfying!r}") + if not satisfying: + return False + + return True + + def tilde_requirements(self): """ - Return a callable operator given an ``op`` operator string. + Return a sorted sequence of all pessimistic "~>" GemConstraint. """ - # type: (str) -> Callable[[GemVersion, GemVersion], bool] - try: - return cls.OPS[op] - except KeyError: - return cls.OPS["="] + constraints = self.as_constraints(sort=True, unique=True) + return [gc for gc in constraints if gc.op == "~>"] diff --git a/src/univers/gem.py.ABOUT b/src/univers/gem.py.ABOUT index 37a00fb6..d2e8542f 100644 --- a/src/univers/gem.py.ABOUT +++ b/src/univers/gem.py.ABOUT @@ -1,8 +1,23 @@ about_resource: gem.py -license_expression: apache-2.0 +license_expression: apache-2.0 AND mit download_url: https://raw.githubusercontent.com/coi-gov-pl/puppeter/04e2a2008bd89a0429b734fdde6da83813688865/puppeter/domain/model/gemrequirement.py -copyright: Copyright (c) Center for Information Technology http://coi.gov.pl +copyright: | + Copyright (c) nexB, Inc. and others. + Copyright (c) Center for Information Technology, http://coi.gov.pl + Copyright (c) Chad Fowler, Rich Kilmer, Jim Weirich and others. + Copyright (c) Engine Yard and Andre Arko, Facebook, Inc. and its affiliates. + package_url: pkg:pypi/puppeter@0.8.3#src/domain/model/gemrequirement.py -notes: This is a subset of the code modified for univers homepage_url: https://github.com/coi-gov-pl/puppeter notice_file: gem.py.NOTICE + +notes: This file started as a subset of the coi.gov/pl code modified for + use in univers. The original Apache-licensed puppeteer code was used as a base, + extracting the Ruby version handling code. That coi code was in turn + originally based on MIT-licensed Rubygems code ported to Python. + This has been substantially modified and enhanced to pass correctly all the + upstream Rubygems tests and work with univers. This mixed code has been further + updated from the Rubygems ruby code from + https://github.com/rubygems/rubygems specifically + lib/rubygems/version.rb and lib/rubygems/requirement.rb + diff --git a/src/univers/utils.py b/src/univers/utils.py index 0327087f..b283d983 100644 --- a/src/univers/utils.py +++ b/src/univers/utils.py @@ -21,13 +21,9 @@ def cmp(x, y): if x == y: return 0 elif x is None: - if y is None: - return 0 - else: - return -1 + return -1 elif y is None: return 1 else: - # TODO: consider casting the values to string or int or floats? # note that this is the minimal replacement function return (x > y) - (x < y) diff --git a/src/univers/versions.py b/src/univers/versions.py index 51373839..c61846a6 100644 --- a/src/univers/versions.py +++ b/src/univers/versions.py @@ -101,7 +101,7 @@ def satisfies(self, constraint): """ return self in constraint - def satisfies_all(self, constraints, explain=True): + def satisfies_all(self, constraints, explain=False): """ Return True is this version satifies all the ``constraints`` list of VersionConstraint. diff --git a/tests/test_bundler_version_ranges_spec.py b/tests/test_bundler_version_ranges_spec.py index 0f928e59..82ee5838 100644 --- a/tests/test_bundler_version_ranges_spec.py +++ b/tests/test_bundler_version_ranges_spec.py @@ -6,25 +6,56 @@ # # Originally from https://github.com/rubygems/rubygems - from univers.gem import GemRequirement -def test_is_empty(): - assert not GemRequirement("!= 1").is_empty() - assert not GemRequirement("!= 1", "= 2").is_empty() - assert not GemRequirement("!= 1", "> 1").is_empty() - assert not GemRequirement("!= 1", ">= 1").is_empty() - assert not GemRequirement("= 1", ">= 0.1", "<= 1.1").is_empty() - assert not GemRequirement("= 1", ">= 1", "<= 1").is_empty() - assert not GemRequirement("= 1", "~> 1").is_empty() - assert not GemRequirement(">= 0.z", "= 0").is_empty() - assert not GemRequirement(">= 0").is_empty() - assert not GemRequirement(">= 1.0.0", "< 2.0.0").is_empty() - assert not GemRequirement("~> 1").is_empty() - assert not GemRequirement("~> 2.0", "~> 2.1").is_empty() - assert GemRequirement(">= 4.1.0", "< 5.0", "= 5.2.1").is_empty() - assert GemRequirement( +def test_satisfied_by(): + + assert not GemRequirement("!= 1").satisfied_by("1") + assert GemRequirement("!= 1").satisfied_by("2") + + assert not GemRequirement("!= 1", "= 2").satisfied_by("1") + assert GemRequirement("!= 1", "= 2").satisfied_by("2") + + assert not GemRequirement("!= 1", "> 1").satisfied_by("1") + assert GemRequirement("!= 1", "> 1").satisfied_by("2") + + assert not GemRequirement("!= 1", ">= 1").satisfied_by("1") + assert GemRequirement("!= 1", ">= 1").satisfied_by("2") + + assert not GemRequirement("= 1", ">= 0.1", "<= 1.1").satisfied_by("0.2") + assert GemRequirement("= 1", ">= 0.1", "<= 1.1").satisfied_by("1") + assert not GemRequirement("= 1", ">= 0.1", "<= 1.1").satisfied_by("3") + + assert GemRequirement("= 1", ">= 1", "<= 1").satisfied_by("1") + assert not GemRequirement("= 1", ">= 1", "<= 1").satisfied_by("2") + assert not GemRequirement("= 1", ">= 1", "<= 1").satisfied_by("0.1") + + assert GemRequirement("= 1", "~> 1").satisfied_by("1") + assert not GemRequirement("= 1", "~> 1").satisfied_by("1.1") + + assert GemRequirement(">= 0.z", "= 0").satisfied_by("0") + assert not GemRequirement(">= 0.z", "= 0").satisfied_by("1") + assert not GemRequirement(">= 0.z", "= 0").satisfied_by("0.1") + assert not GemRequirement(">= 0.z", "= 0").satisfied_by("0.z") + + assert GemRequirement(">= 0").satisfied_by("1") + assert GemRequirement(">= 0").satisfied_by("2") + assert GemRequirement(">= 0").satisfied_by("0") + + assert not GemRequirement(">= 1.0.0", "< 2.0.0").satisfied_by("3") + assert GemRequirement(">= 1.0.0", "< 2.0.0").satisfied_by("1.5.1") + + assert GemRequirement("~> 1").satisfied_by("1") + assert GemRequirement("~> 1").satisfied_by("1.1") + assert not GemRequirement("~> 1").satisfied_by("2") + + assert not GemRequirement("~> 2.0", "~> 2.1").satisfied_by("1") + assert GemRequirement("~> 2.0", "~> 2.1").satisfied_by("2.1.2") + + assert not GemRequirement(">= 4.1.0", "< 5.0", "= 5.2.1").satisfied_by("1") + assert not GemRequirement(">= 4.1.0", "< 5.0", "= 5.2.1").satisfied_by("5.2.1") + assert not GemRequirement( "< 5.0", "< 5.3", "< 6.0", @@ -39,13 +70,13 @@ def test_is_empty(): ">= 4.2.0", ">= 4.2", ">= 4", - ).is_empty() - assert GemRequirement("!= 1", "< 2", "> 2").is_empty() - assert GemRequirement("!= 1", "<= 1", ">= 1").is_empty() - assert GemRequirement("< 2", "> 2").is_empty() - assert GemRequirement("< 2", "> 2", "= 2").is_empty() - assert GemRequirement("= 1", "!= 1").is_empty() - assert GemRequirement("= 1", "= 2").is_empty() - assert GemRequirement("= 1", "~> 2").is_empty() - assert GemRequirement(">= 0", "<= 0.a").is_empty() - assert GemRequirement("~> 2.0", "~> 3").is_empty() + ).satisfied_by("5.2.0") + assert not GemRequirement("!= 1", "< 2", "> 2").satisfied_by("1") + assert not GemRequirement("!= 1", "<= 1", ">= 1").satisfied_by("1") + assert not GemRequirement("< 2", "> 2").satisfied_by("1") + assert not GemRequirement("< 2", "> 2", "= 2").satisfied_by("1") + assert not GemRequirement("= 1", "!= 1").satisfied_by("1") + assert not GemRequirement("= 1", "= 2").satisfied_by("1") + assert not GemRequirement("= 1", "~> 2").satisfied_by("1") + assert not GemRequirement(">= 0", "<= 0.a").satisfied_by("1") + assert not GemRequirement("~> 2.0", "~> 3").satisfied_by("1") diff --git a/tests/test_gem.py b/tests/test_gem.py index 61256463..5065bbd8 100644 --- a/tests/test_gem.py +++ b/tests/test_gem.py @@ -7,31 +7,16 @@ # notes: This has been substantially modified and enhanced from the original # puppeteer code to extract the Ruby version hanlding code. -import pytest -from univers.gem import GemVersion from univers.gem import GemRequirement +from univers.gem import GemVersion def test_gem_version_release(): - # given - v = GemVersion("1.2.4.beta") - - # when - released = v.release() - - # then - assert GemVersion("1.2.4") == released + assert GemVersion("1.2.4.beta").release() == GemVersion("1.2.4") def test_gem_version_bump(): - # given - v = GemVersion("1.2.4") - - # when - bumped = v.bump() - - # then - assert GemVersion("1.3.0") == bumped + assert GemVersion("1.2.4").bump() == GemVersion("1.3.0") def test_gem_version_compare(): @@ -42,21 +27,16 @@ def test_gem_version_compare(): assert GemVersion("1.4.pre") != GemVersion("1.4") -@pytest.mark.parametrize( - "requirement,version", - [ - (["3.4"], "3.4.0"), - (["~> 3.4"], "3.4.8"), - ([">= 3.4"], "4.4.8"), - ([">= 3.4", "<4"], "3.45.8"), - ], -) -def test_gem_requirement(requirement, version): - assert GemRequirement(*requirement).satified_by(version) - - -@pytest.mark.parametrize( - "requirement,version", [([">= 3.4", "<4"], "4.1"), (["~> 3"], "4.1.0.pre")] -) -def test_gem_requirement_fails(requirement, version): - assert GemRequirement(*requirement).satified_by(version) is False +def test_gem_requirement(): + assert GemRequirement("3.4").satisfied_by("3.4.0") + assert GemRequirement("~> 3.4").satisfied_by("3.4.8") + assert GemRequirement(">= 3.4").satisfied_by("4.4.8") + assert GemRequirement(">= 3.4", "<4").satisfied_by("3.45.8") + + +def test_gem_requirement_fails1(): + assert GemRequirement(">= 3.4", "<4").satisfied_by("4.1") is False + + +def test_gem_requirement_fails2(): + assert GemRequirement("~> 3").satisfied_by("4.1.0.pre") is False diff --git a/tests/test_rubygems_gem_requirement.py b/tests/test_rubygems_gem_requirement.py index 844cec8a..6ccb4a5f 100644 --- a/tests/test_rubygems_gem_requirement.py +++ b/tests/test_rubygems_gem_requirement.py @@ -6,21 +6,17 @@ # # Originally from https://github.com/rubygems/rubygems +from univers.gem import GemConstraint from univers.gem import GemRequirement from univers.gem import GemVersion +from univers.gem import InvalidRequirementError def test_equals(): refute_requirement_equal("= 1.2", "= 1.3") - refute_requirement_equal("= 1.3", "= 1.2") - refute_requirement_equal("~> 1.3", "~> 1.3.0") - refute_requirement_equal("~> 1.3.0", "~> 1.3") - assert_requirement_equal(["> 2", "~> 1.3", "~> 1.3.1"], ["~> 1.3.1", "~> 1.3", "> 2"]) - assert_requirement_equal(["> 2", "~> 1.3"], ["> 2.0", "~> 1.3"]) - assert_requirement_equal(["> 2.0", "~> 1.3"], ["> 2", "~> 1.3"]) def test_initialize(): @@ -32,17 +28,15 @@ def test_initialize(): def test_create(): r = GemRequirement(">= 1", "< 2") - assert r.requirements == [[">=", GemVersion(1)], ["<", GemVersion(2)]] + assert r.constraints == ( + GemConstraint(">=", GemVersion(1)), + GemConstraint("<", GemVersion(2)), + ) assert GemRequirement("= 1") == GemRequirement("= 1") assert GemRequirement(">= 1.2", "<= 1.3") == GemRequirement("<= 1.3", ">= 1.2") -def test_empty_requirements_is_none(): - r = GemRequirement() - assert r is None - - -def test_explicit_default_is_none(): +def test_explicit_default_is_not_none(): r = GemRequirement(">= 0") assert r @@ -53,29 +47,29 @@ def test_basic_non_none(): def test_for_lockfile(): - assertGemRequirement("~> 1.0").for_lockfile() == " (~> 1.0)" + assert GemRequirement("~> 1.0").for_lockfile() == " (~> 1.0)" assert GemRequirement(">= 1.0.1", "~> 1.0").for_lockfile() == " (~> 1.0, >= 1.0.1)" duped = GemRequirement("= 1.0", ["=", GemVersion("1.0")]) assert duped.for_lockfile() == " (= 1.0)" def test_parse(): - assert GemRequirement.parse(" 1") == ["=", GemVersion(1)] - assert GemRequirement.parse("= 1") == ["=", GemVersion(1)] - assert GemRequirement.parse("> 1") == [">", GemVersion(1)] - assert GemRequirement.parse("=\n1" == ["=", GemVersion(1)]) - assert GemRequirement.parse("1.0") == ["=", GemVersion(1)] + assert GemRequirement.parse(" 1") == GemConstraint("=", GemVersion(1)) + assert GemRequirement.parse("= 1") == GemConstraint("=", GemVersion(1)) + assert GemRequirement.parse("> 1") == GemConstraint(">", GemVersion(1)) + assert GemRequirement.parse("=\n1") == GemConstraint("=", GemVersion(1)) + assert GemRequirement.parse("1.0") == GemConstraint("=", GemVersion(1)) - assert GemRequirement.parse(GemVersion("2")) == ["=", GemVersion(2)] + assert GemRequirement.parse(GemVersion("2")) == GemConstraint("=", GemVersion(2)) def test_parse_deduplication(): - assert GemRequirement.parse("~> 1")[0] == "~>" + assert GemRequirement.parse("~> 1") == GemConstraint("~>", GemVersion("1")) def test_parse_bad(): bads = [ - nil, + None, "", "! 1", "= junk", @@ -85,19 +79,19 @@ def test_parse_bad(): try: GemRequirement.parse(bad) raise Exception("exception not raised") - except GemRequirement.BadRequirementError: + except InvalidRequirementError: pass def test_prerelease_eh(): - r = GemRequirement("= 1") - assert not r.prerelease + r = GemVersion("1") + assert not r.prerelease() - r = GemRequirement("= 1.a") - assert r.prerelease + r = GemVersion("1.a") + assert r.prerelease() - r = GemRequirement("> 1.a", "< 2") - assert r.prerelease + r = GemVersion("1.x") + assert r.prerelease() def test_satisfied_by_eh_bang_equal(): @@ -180,6 +174,10 @@ def test_satisfied_by_eh_tilde_gt_v0(): assert_satisfied_by("0.0.1", r) +def test_satisfied_by_eh_good_problematic(): + assert_satisfied_by("0.0.1.0", "> 0.0.0.1") + + def test_satisfied_by_eh_good(): assert_satisfied_by("0.2.33", "= 0.2.33") assert_satisfied_by("0.2.34", "> 0.2.33") @@ -191,7 +189,6 @@ def test_satisfied_by_eh_good(): assert_satisfied_by("1.112", "> 1.111") assert_satisfied_by("0.2", "> 0.0.0") assert_satisfied_by("0.0.0.0.0.2", "> 0.0.0") - assert_satisfied_by("0.0.1.0", "> 0.0.0.1") assert_satisfied_by("10.3.2", "> 9.3.2") assert_satisfied_by("1.0.0.0", "= 1.0") assert_satisfied_by("10.3.2", "!= 9.3.4") @@ -228,7 +225,7 @@ def test_illformed_requirements(): try: GemRequirement.parse(bad) raise Exception("exception not raised") - except GemRequirement.BadRequirementError: + except InvalidRequirementError: pass @@ -350,21 +347,21 @@ def assert_requirement_equal(expected, actual): assert GemRequirement.create(actual) == GemRequirement.create(expected) -def assert_satisfied_by(version, requirement): - # Assert that +version+ satisfies +requirement+. - assert GemRequirement.create(requirement).satisfied_by(GemVersion(version)) - - def refute_requirement_equal(unexpected, actual): # Refute the assumption that two requirements are equal. assert GemRequirement.create(actual) != GemRequirement.create(unexpected) + assert GemRequirement.create(unexpected) != GemRequirement.create(actual) -def refute_satisfied_by(version, requirement): - # Refute the assumption that +version+ satisfies +requirement+. - assert not GemRequirement.create(requirement).satisfied_by(GemVersion(version)) +def assert_satisfied_by(version, requirement): + # Assert that +version+ satisfies +requirement+. + if not isinstance(requirement, GemRequirement): + requirement = GemRequirement.create(requirement) + assert requirement.satisfied_by(GemVersion(version)) -def refute_requirement_equal(unexpected, actual): - # Refute the assumption that two requirements hashes are equal. - assert GemRequirement.create(actual) != GemRequirement.create(unexpected) +def refute_satisfied_by(version, requirement): + # Refute the assumption that +version+ satisfies +requirement+. + if not isinstance(requirement, GemRequirement): + requirement = GemRequirement.create(requirement) + assert not requirement.satisfied_by(GemVersion(version)) diff --git a/tests/test_rubygems_gem_version.py b/tests/test_rubygems_gem_version.py index 756c1a2a..6c14a00d 100644 --- a/tests/test_rubygems_gem_version.py +++ b/tests/test_rubygems_gem_version.py @@ -6,17 +6,15 @@ # # Originally from https://github.com/rubygems/rubygems +from univers.gem import GemRequirement from univers.gem import GemVersion - - -def assert_equal(expected, result): - assert result == expected +from univers.gem import InvalidVersionError def assert_bumped_version_equal(expected, unbumped): # Assert that bumping the +unbumped+ version yields the +expected+. - assert_version_equal(expected, GemVersion(unbumped).bump()) + assert_version_eql(expected, GemVersion(unbumped).bump()) def test_bump(): @@ -39,37 +37,33 @@ def test_bump_one_level(): assert_bumped_version_equal("6", "5") -def test_eql_eh(): +def test_eql_is_same(): assert_version_eql("1.2", "1.2") - refute_version_eql("1.2", "1.2.0") - refute_version_eql("1.2", "1.3") - refute_version_eql("1.2.b1", "1.2.b.1") - + assert_version_strict_equal("1.2", "1.2") -def test_equals2(): - assert_version_equal("1.2", "1.2") - refute_version_equal("1.2", "1.3") - assert_version_equal("1.2.b1", "1.2.b.1") + refute_version_eql("1.2", "1.3") + refute_version_strict_equal("1.2", "1.3") - # REVISIT: consider removing as too impl-bound + refute_version_strict_equal("1.2", "1.2.0") + assert_version_eql("1.2", "1.2.0") + assert_version_eql("1.2.b1", "1.2.b.1") + refute_version_strict_equal("1.2.b1", "1.2.b.1") -def test_hash(): - assert GemVersion("1.2").hash == GemVersion("1.2").hash - assert GemVersion("1.2").hash != GemVersion("1.3").hash - assert GemVersion("1.2").hash == GemVersion("1.2.0").hash - assert GemVersion("1.2.pre.1").hash == GemVersion("1.2.0.pre.1.0").hash + refute_version_strict_equal("1.2.pre.1", "1.2.0.pre.1.0") + assert_version_eql("1.2.pre.1", "1.2.0.pre.1.0") def test_initialize(): for good in ["1.0", "1.0 ", " 1.0 ", "1.0\n", "\n1.0\n", "1.0"]: - assert_version_equal("1.0", good) + assert_version_eql("1.0", good) - assert_version_equal("1", 1) + assert_version_eql("1", 1) def test_initialize_invalid(): invalid_versions = [ + "whatever", "junk", "1.0\n2.0" "1..2", "1.2\ 3.4", @@ -81,14 +75,15 @@ def test_initialize_invalid(): for invalid in invalid_versions: try: GemVersion(invalid) - raise Exception("exception not raised") - except ValueError: + raise Exception(f"exception not raised for: {invalid!r}") + except InvalidVersionError: pass def test_empty_version(): - for empty in ["", " ", " "]: - assert_equal("0", GemVersion(empty).version) + assert GemVersion("").version == "0" + assert GemVersion(" ").version == "0" + assert GemVersion(" ").version == "0" def test_prerelease(): @@ -114,57 +109,54 @@ def test_release(): assert_release_equal("1.9.3", "1.9.3") -def test_spaceship(): +def test_spaceship_cmp(): def cmp(a, b): return a.__cmp__(b) # Ruby spaceship <=> is the same as Python legacy cmp() - assert_equal(0, cmp(GemVersion("1.0"), GemVersion("1.0.0"))) - assert_equal(1, cmp(GemVersion("1.0"), GemVersion("1.0.a"))) - assert_equal(1, cmp(GemVersion("1.8.2"), GemVersion("0.0.0"))) - assert_equal(1, cmp(GemVersion("1.8.2"), GemVersion("1.8.2.a"))) - assert_equal(1, cmp(GemVersion("1.8.2.b"), GemVersion("1.8.2.a"))) - assert_equal(-1, cmp(GemVersion("1.8.2.a"), GemVersion("1.8.2"))) - assert_equal(1, cmp(GemVersion("1.8.2.a10"), GemVersion("1.8.2.a9"))) - assert_equal(0, cmp(GemVersion(""), GemVersion("0"))) - - assert_equal(0, cmp(GemVersion("0.beta.1"), GemVersion("0.0.beta.1"))) - assert_equal(-1, cmp(GemVersion("0.0.beta"), GemVersion("0.0.beta.1"))) - assert_equal(-1, cmp(GemVersion("0.0.beta"), GemVersion("0.beta.1"))) - - assert_equal(-1, cmp(GemVersion("5.a"), GemVersion("5.0.0.rc2"))) - assert_equal(1, cmp(GemVersion("5.x"), GemVersion("5.0.0.rc2"))) - - assert_nil(cmp(GemVersion("1.0"), "whatever")) - - -def test_approximate_recommendation(): - assert_approximate_equal("~> 1.0", "1") - assert_approximate_satisfies_itself("1") - - assert_approximate_equal("~> 1.0", "1.0") - assert_approximate_satisfies_itself("1.0") - - assert_approximate_equal("~> 1.2", "1.2") - assert_approximate_satisfies_itself("1.2") - - assert_approximate_equal("~> 1.2", "1.2.0") - assert_approximate_satisfies_itself("1.2.0") - - assert_approximate_equal("~> 1.2", "1.2.3") - assert_approximate_satisfies_itself("1.2.3") - - assert_approximate_equal("~> 1.2.a", "1.2.3.a.4") - assert_approximate_satisfies_itself("1.2.3.a.4") - - assert_approximate_equal("~> 1.9.a", "1.9.0.dev") - assert_approximate_satisfies_itself("1.9.0.dev") + assert cmp(GemVersion("1.0"), GemVersion("1.0.0")) == 0 + assert cmp(GemVersion("1.0"), GemVersion("1.0.a")) == 1 + assert cmp(GemVersion("1.8.2"), GemVersion("0.0.0")) == 1 + assert cmp(GemVersion("1.8.2"), GemVersion("1.8.2.a")) == 1 + assert cmp(GemVersion("1.8.2.b"), GemVersion("1.8.2.a")) == 1 + assert cmp(GemVersion("1.8.2.a"), GemVersion("1.8.2")) == -1 + assert cmp(GemVersion("1.8.2.a10"), GemVersion("1.8.2.a9")) == 1 + assert cmp(GemVersion(""), GemVersion("0")) == 0 + assert cmp(GemVersion("0.beta.1"), GemVersion("0.0.beta.1")) == 0 + assert cmp(GemVersion("0.0.beta"), GemVersion("0.0.beta.1")) == -1 + assert cmp(GemVersion("0.0.beta"), GemVersion("0.beta.1")) == -1 + assert cmp(GemVersion("5.a"), GemVersion("5.0.0.rc2")) == -1 + assert cmp(GemVersion("5.x"), GemVersion("5.0.0.rc2")) == 1 + + +def assert_version_satisfies_requirement(requirement, version): + # Assert that +version+ satisfies the "approximate" ~> +requirement+. + req = GemRequirement.create(requirement) + ver = GemVersion(version) + assert req.satisfied_by(ver) + + +def test_satisfies_requirement(): + assert_version_satisfies_requirement("~> 1.0", "1") + assert_version_satisfies_requirement("~> 1.0", "1.0") + assert_version_satisfies_requirement("~> 1.2", "1.2") + assert_version_satisfies_requirement("~> 1.2", "1.2.0") + assert_version_satisfies_requirement("~> 1.2", "1.2.3") + assert_version_satisfies_requirement("~> 1.2.a", "1.2.3.a.4") + assert_version_satisfies_requirement("~> 1.9.a", "1.9.0.dev") def test_to_s(): assert GemVersion("5.2.4").to_string() == "5.2.4" +def test_compare(): + assert GemVersion("0.0.1.0") > GemVersion("0.0.0.1") + assert not GemVersion("0.0.1.0") < GemVersion("0.0.0.1") + assert GemVersion("0.0.1.0") >= GemVersion("0.0.0.1") + assert not GemVersion("0.0.1.0") <= GemVersion("0.0.0.1") + + def test_semver(): assert_less_than("1.0.0-alpha", "1.0.0-alpha.1") assert_less_than("1.0.0-alpha.1", "1.0.0-beta.2") @@ -180,21 +172,25 @@ def test_segments(): secondseg = ver.segments[2] secondseg += 1 - refute_version_equal("9.8.8", "9.8.7") - assert_equal([9, 8, 7], GemVersion("9.8.7").segments) + refute_version_eql("9.8.8", "9.8.7") + assert GemVersion("9.8.7").segments == [9, 8, 7] + + +def test_split_segments(): + assert GemVersion("3.2.4-2").split_segments() == ([3, 2, 4], ["pre", 2]) def test_canonical_segments(): - assert_equal([1], GemVersion("1.0.0").canonical_segments) - assert_equal([1, "a", 1], GemVersion("1.0.0.a.1.0").canonical_segments) - assert_equal([1, 2, 3, "pre", 1], GemVersion("1.2.3-1").canonical_segments) + assert GemVersion("1.0.0").canonical_segments == [1] + assert GemVersion("1.0.0.a.1.0").canonical_segments == [1, "a", 1] + assert GemVersion("1.2.3-1").canonical_segments == [1, 2, 3, "pre", 1] def test_frozen_version(): ver = GemVersion("1.test") assert_less_than(ver, GemVersion("1")) - assert_version_equal(GemVersion("1"), v.release) - assert_version_equal(GemVersion("2"), v.bump) + assert_version_eql(GemVersion("1"), ver.release()) + assert_version_eql(GemVersion("2"), ver.bump()) def assert_prerelease(version): @@ -202,43 +198,18 @@ def assert_prerelease(version): assert GemVersion(version).prerelease(), "#{version} is a prerelease" -def assert_approximate_equal(expected, version): - # Assert that +expected+ is the "approximate" recommendation for +version+. - assert GemVersion(version).approximate_recommendation() == expected - - -def assert_approximate_satisfies_itself(version): - # Assert that the "approximate" recommendation for +version+ satisfies +version+. - gem_version = GemVersion(version) - req = GemRequirement(gem_version.approximate_recommendation()) - assert req.satisfied_by(gem_version) - - def assert_release_equal(release, version): # Assert that +release+ is the correct non-prerelease +version+. - assert_version_equal(release, GemVersion(version).release) - - -def assert_version_equal(expected, actual): - # Assert that two versions are equal. Handles strings or - # Gem::Version instances. - assert GemVersion(expected) == GemVersion(actual) + assert_version_eql(release, GemVersion(version).release()) def assert_version_eql(first, second): # Assert that two versions are eql?. Checks both directions. - first, second = GemVersion(first), GemVersion(second) - assert first == second, "#{first} is eql? #{second}" - assert second == first, "#{second} is eql? #{first}" - - -def assert_less_than(left, right): - assert GemVersion(left) < GemVersion(right) - - -def refute_prerelease(version): - # Refute the assumption that +version+ is a prerelease. - assert not GemVersion(version).prerelease() + first = GemVersion(first) + second = GemVersion(second) + assert first is not second + assert first == second + assert second == first def refute_version_eql(first, second): @@ -246,10 +217,32 @@ def refute_version_eql(first, second): # directions. first = GemVersion(first) second = GemVersion(second) + assert first is not second assert first != second assert second != first -def refute_version_equal(unexpected, actual): - # Refute the assumption that the two versions are equal?. - assert GemVersion(unexpected) != GemVersion(actual) +def assert_version_strict_equal(first, second): + # Assert that two versions are strictly equal + first = GemVersion(first) + second = GemVersion(second) + assert first is not second + assert first.equal_strictly(second) + assert second.equal_strictly(first) + + +def refute_version_strict_equal(first, second): + first = GemVersion(first) + second = GemVersion(second) + assert first is not second + assert not first.equal_strictly(second) + assert not second.equal_strictly(first) + + +def assert_less_than(left, right): + assert GemVersion(left) < GemVersion(right) + + +def refute_prerelease(version): + # Refute the assumption that +version+ is a prerelease. + assert not GemVersion(version).prerelease() From b7f5145366d36a5edb15ea8ff8ab6ab4c91f668f Mon Sep 17 00:00:00 2001 From: Philippe Ombredanne Date: Tue, 7 Dec 2021 18:22:35 +0100 Subject: [PATCH 693/707] Implement gem version ranges This is a vers wrapper on the gem.py Rubygems version implmentation. Reference: https://github.com/nexB/univers/issues/5 Reported-by: Oliver Chang @oliverchang Signed-off-by: Philippe Ombredanne --- src/univers/gem.py | 89 +++++++++++++++++++++++++----------- src/univers/semver.py | 1 - src/univers/version_range.py | 50 ++++++++++---------- src/univers/versions.py | 18 +++----- tests/test_version_range.py | 8 ++-- 5 files changed, 98 insertions(+), 68 deletions(-) diff --git a/src/univers/gem.py b/src/univers/gem.py index 310df864..36eb2a68 100644 --- a/src/univers/gem.py +++ b/src/univers/gem.py @@ -470,6 +470,19 @@ def __cmp__(self, other, trace=False): GemConstraint.to_string = lambda gc: f"{gc.op} {gc.version}" +def sort_constraints(constraints): + """ + Return a sorted sequence of unique GemConstraints. + """ + constraints = sorted(constraints, key=lambda gc: (gc.version, gc.op)) + consts = [] + for gc in constraints: + if gc in consts: + continue + consts.append(gc) + return consts + + def tilde_comparator(version, requirement, trace=False): """ Return True if ``version`` GemVersion satisfies ``requirement`` GemVersion @@ -524,22 +537,22 @@ def __init__(self, *requirements): self.constraints = tuple([GemRequirement.parse(r) for r in requirements]) def __str__(self): - gcs = [gc.to_string() for gc in self.as_constraints(sort=True)] + gcs = [gc.to_string() for gc in sort_constraints(self.constraints)] return ", ".join(gcs) def __repr__(self): - gcs = ", ".join(repr(gc.to_string()) for gc in self.as_constraints(sort=True)) + gcs = ", ".join(repr(gc.to_string()) for gc in sort_constraints(self.constraints)) return f"GemRequirement({gcs})" @classmethod - def from_lockfile(cls, requirements): + def from_string(cls, requirements): """ Return a GemRequirement build from a lockfile-style ``requirements`` string. For example:: >>> gr1 = GemRequirement(">= 1.0.1", "~> 1.0") - >>> gr2 = GemRequirement.from_lockfile(" (>= 1.0.1, ~> 1.0)") + >>> gr2 = GemRequirement.from_string(" (>= 1.0.1, ~> 1.0)") >>> assert gr1 == gr2, (gr1, gr2) """ reqs = requirements.strip().strip("()") @@ -556,7 +569,7 @@ def for_lockfile(self): >>> gf_flf = gr.for_lockfile() >>> assert gf_flf == " (~> 1.0, >= 1.0.1)", gf_flf """ - gcs = [gc.to_string() for gc in self.as_constraints(sort=True, unique=True)] + gcs = [gc.to_string() for gc in sort_constraints(self.constraints)] gcs = ", ".join(gcs) return f" ({gcs})" @@ -564,16 +577,29 @@ def dedupe(self): """ Return a new GemRequirement with sorted and unique constraints. """ - return GemRequirement(*self.as_constraints(sort=True, unique=True)) + return GemRequirement(*sort_constraints(self.constraints)) + + def simplify(self): + """ + Return a new simplified GemRequirement with: + - sorted and unique constraints. + - where ~> constraints are replaced by simpler contrainsts. + """ + constraints = [] + for const in self.constraints: + if const.op == "~>": + low_high = get_tilde_constraints(const) + constraints.extend(low_high) + else: + constraints.append(const) + return GemRequirement(*sort_constraints(constraints)) def __eq__(self, other): if not isinstance(other, self.__class__): return False # An == check is always necessary - if self.as_constraints(sort=True, unique=True) == other.as_constraints( - sort=True, unique=True - ): + if sort_constraints(self.constraints) == sort_constraints(other.constraints): stilde = self.tilde_requirements() if not stilde: # An == check is sufficient unless any requirements use ~> @@ -604,23 +630,6 @@ def exact(self): """ return len(self.constraints) == 1 and self.constraints[0].op == "=" - def as_constraints(self, sort=False, unique=False): - """ - Return a sequence of GemConstraints optionally sorted and deduplicated. - """ - constraints = self.constraints[:] - if sort: - constraints = sorted(constraints, key=lambda gc: (gc.version, gc.op)) - if unique: - consts = [] - for gc in constraints: - if gc in consts: - continue - consts.append(gc) - constraints = consts - - return constraints - @classmethod def create(cls, reqs): """ @@ -696,5 +705,31 @@ def tilde_requirements(self): """ Return a sorted sequence of all pessimistic "~>" GemConstraint. """ - constraints = self.as_constraints(sort=True, unique=True) + constraints = sort_constraints(self.constraints) return [gc for gc in constraints if gc.op == "~>"] + + +def get_tilde_constraints(constraint): + """ + Return a tuple of two GemConstraint representing the lower and upper + bound of a version range ``string`` that uses a tilde "~>" pessimistic operator. + Raise a ValueError if this is not a tilde range. + + For example: + >>> lower_bound, upper_bound = get_tilde_constraints(GemConstraint("~>", GemVersion("1.0.2"))) + >>> vlow = GemVersion("1.0.2") + >>> vup = GemVersion("1.1.0") + >>> assert lower_bound == GemConstraint(op=">=", version=vlow) + >>> assert upper_bound == GemConstraint(op="<", version=vup) + """ + if not isinstance(constraint, GemConstraint) or not constraint.op == "~>": + raise ValueError(f"Invalid tilde GemConstraint: {constraint!r}") + version = constraint.version + assert isinstance(version, GemVersion) + lower_bound = version.release() + upper_bound = lower_bound.bump() + + return ( + GemConstraint(op=">=", version=lower_bound), + GemConstraint(op="<", version=upper_bound), + ) diff --git a/src/univers/semver.py b/src/univers/semver.py index 2baefca1..e7abb3b3 100644 --- a/src/univers/semver.py +++ b/src/univers/semver.py @@ -75,7 +75,6 @@ def get_pessimistic_constraints(string): bound of version range ``string`` that contains a pessimistic Ruby range. Raise a ValueError if this is not a pessimistic Rubygems range. - For example: >>> lower_bound, upper_bound = get_pessimistic_constraints("~>2.0.8") >>> vlow = semantic_version.Version("2.0.8") diff --git a/src/univers/version_range.py b/src/univers/version_range.py index 90372543..c1e3b0d6 100644 --- a/src/univers/version_range.py +++ b/src/univers/version_range.py @@ -13,6 +13,7 @@ from univers import versions from univers.utils import remove_spaces from univers.version_constraint import VersionConstraint +from univers import gem @attr.s(frozen=True, order=False, eq=True, hash=True) @@ -210,17 +211,22 @@ def get_allof_constraints(cls, clause): class GemVersionRange(VersionRange): - # gem need its own scheme see https//github.com/nexB/univers/issues/5 - # See https://github.com/ruby/ruby/blob/415671a28273e5bfbe9aa00a0e386f025720ac23/lib/rubygems/requirement.rb - # See https//semver.org/spec/v2.0.0.html#spec-item-11 - # See https//snyk.io/blog/differences-in-version-handling-gems-and-npm/ - # See https://github.com/npm/node-semver/issues/112 + """ + A version range implementation for Rubygems. + + gem need its own versioning scheme as this is not semver. + See https//github.com/nexB/univers/issues/5 + See https://github.com/ruby/ruby/blob/415671a28273e5bfbe9aa00a0e386f025720ac23/lib/rubygems/requirement.rb + See https//semver.org/spec/v2.0.0.html#spec-item-11 + See https//snyk.io/blog/differences-in-version-handling-gems-and-npm/ + See https://github.com/npm/node-semver/issues/112 + """ scheme = "gem" - version_class = versions.RubyVersion + version_class = versions.RubygemsVersion vers_by_native_comparators = { - "==": "=", + "=": "=", "!=": "!=", "<=": "<=", ">=": ">=", @@ -232,28 +238,22 @@ class GemVersionRange(VersionRange): def from_native(cls, string): """ Return a VersionRange built from a Rubygem version range ``string``. + + Gem version semantics are different from semver: + there can be commonly more than 3 segments and + the operators are also different. """ - # TODO: Gem version semantics are different from semver: - # there can be commonly more than 3 segments - # the operators are also different. - # replace Rubygem ~> pessimistic operator by node-semver equivalent - string = string.replace("~>", "~") - spec = semantic_version.NpmSpec(string) + gr = gem.GemRequirement.from_string(string).simplify() - clause = spec.clause.simplify() - assert isinstance(clause, (AnyOf, AllOf)) - anyof_constraints = [] - if isinstance(clause, AnyOf): - for allof_clause in clause.clauses: - anyof_constraints.append(get_allof_constraints(cls, allof_clause)) - elif isinstance(clause, AllOf): - alloc = get_allof_constraints(cls, clause) - anyof_constraints.append(alloc) - else: - raise ValueError(f"Unknown clause type: {spec!r}") + constraints = [] + for gc in gr.constraints: + version = cls.version_class(str(gc.version)) + op = cls.vers_by_native_comparators[gc.op] + vc = VersionConstraint(comparator=op, version=version) + constraints.append(vc) - return cls(constraints=anyof_constraints) + return cls(constraints=[constraints]) class DebianVersionRange(VersionRange): diff --git a/src/univers/versions.py b/src/univers/versions.py index c61846a6..cdfbe561 100644 --- a/src/univers/versions.py +++ b/src/univers/versions.py @@ -12,6 +12,7 @@ from univers import arch from univers import debian +from univers import gem from univers import gentoo from univers import maven from univers import rpm @@ -194,25 +195,20 @@ def is_valid(cls, string): @total_ordering @attr.s(frozen=True, order=False, eq=False, hash=True) -class RubyVersion(Version): +class RubygemsVersion(Version): """ - Ruby version encourages but does not enforce semver + Rubygems encourages semver version but does not enforce it. + Rubygems supports 4 or more segments in versions such + as with https://rubygems.org/gems/rails/versions/5.0.0.1 """ - # FIXME: Ruby is NOT semver support 4 or more segments in versions such as https://rubygems.org/gems/rails/versions/5.0.0.1 - # See https://github.com/ruby/ruby/blob/415671a28273e5bfbe9aa00a0e386f025720ac23/lib/rubygems/requirement.rb - @classmethod def build_value(cls, string): - return semantic_version.Version.coerce(string) + return gem.GemVersion(string) @classmethod def is_valid(cls, string): - try: - semantic_version.Version.parse(string) - return True - except ValueError: - return False + return gem.GemVersion.is_correct(string) @total_ordering diff --git a/tests/test_version_range.py b/tests/test_version_range.py index 3ed058c2..4c7b92dc 100644 --- a/tests/test_version_range.py +++ b/tests/test_version_range.py @@ -10,7 +10,7 @@ from univers.version_range import GemVersionRange from univers.version_range import VersionRange from univers.versions import PypiVersion -from univers.versions import RubyVersion +from univers.versions import RubygemsVersion class TestVersionRange(TestCase): @@ -52,10 +52,10 @@ def test_VersionRange_from_string_pypi(self): def test_GemVersionRange_from_native_range_with_pessimistic_operator(self): gem_range = "~>2.0.8" version_range = GemVersionRange.from_native(gem_range) - assert version_range.to_string() == "vers:gem/<2.1.0,>=2.0.8" + assert version_range.to_string() == "vers:gem/<2.1,>=2.0.8" assert version_range.constraints == [ [ - VersionConstraint(comparator="<", version=RubyVersion(string="2.1.0")), - VersionConstraint(comparator=">=", version=RubyVersion(string="2.0.8")), + VersionConstraint(comparator="<", version=RubygemsVersion(string="2.1")), + VersionConstraint(comparator=">=", version=RubygemsVersion(string="2.0.8")), ], ] From 5015b43ff4993d1ec3f2e813c60fe5481c142987 Mon Sep 17 00:00:00 2001 From: Philippe Ombredanne Date: Tue, 7 Dec 2021 19:03:20 +0100 Subject: [PATCH 694/707] Remove expected failure for RPMs The isue has been fixed the previous merge Reference: https://github.com/nexB/univers/issues/2 Reference: https://github.com/sassoftware/python-rpm-vercmp/issues/2 Reference: https://github.com/sassoftware/python-rpm-vercmp/issues/4 Reported-by: Shivam Sandbhor @sbs2001 Signed-off-by: Philippe Ombredanne --- tests/test_rpm_vercmp.py | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/tests/test_rpm_vercmp.py b/tests/test_rpm_vercmp.py index e9036cba..3bc1925a 100644 --- a/tests/test_rpm_vercmp.py +++ b/tests/test_rpm_vercmp.py @@ -93,12 +93,7 @@ def get_tests(): tests = list(parse_rpmvercmp_tests(rpmtests, with_buggy_comparisons=True)) for test_count, (ver1, ver2, expected) in enumerate(tests, 1): name = f"test_rpm_version_{test_count}" - func = create_test_function(ver1, ver2, expected, name) - if "^" in ver1 or "^" in ver2: - result = vercmp.vercmp(ver1, ver2) - if result != expected: - func = unittest.expectedFailure(func) - yield func + yield create_test_function(ver1, ver2, expected, name) # Make sure we still test something, in case the m4 file drops # content this will fail the test From bfb1bc57ffc693288dbf547f679ec95d9f6eea0c Mon Sep 17 00:00:00 2001 From: Philippe Ombredanne Date: Wed, 8 Dec 2021 00:12:33 +0100 Subject: [PATCH 695/707] Update src/univers/rpm.py Fix typo in docstring Signed-off-by: Philippe Ombredanne --- src/univers/rpm.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/univers/rpm.py b/src/univers/rpm.py index cc0b43f5..199b6492 100644 --- a/src/univers/rpm.py +++ b/src/univers/rpm.py @@ -52,7 +52,7 @@ def from_evr(s): def compare_rpm_versions(a: Union[RpmVersion, str], b: Union[RpmVersion, str]) -> int: """ - Compare to RPM versions ``a`` and ``b`` and return: + Compare two RPM versions ``a`` and ``b`` and return: - 1 if the version of a is newer than b - 0 if the versions match - -1 if the version of a is older than b From 4c2629a7876e759873b762b9f59e291e65b9629e Mon Sep 17 00:00:00 2001 From: Philippe Ombredanne Date: Thu, 16 Dec 2021 00:57:12 +0100 Subject: [PATCH 696/707] Remove range spec now at package-url Signed-off-by: Philippe Ombredanne --- VERSION-RANGE-SPEC.rst | 646 ----------------------------------------- 1 file changed, 646 deletions(-) delete mode 100644 VERSION-RANGE-SPEC.rst diff --git a/VERSION-RANGE-SPEC.rst b/VERSION-RANGE-SPEC.rst deleted file mode 100644 index 101a6644..00000000 --- a/VERSION-RANGE-SPEC.rst +++ /dev/null @@ -1,646 +0,0 @@ -====================================================== -vers: a mostly universal version range specifier -====================================================== - -This specification is a new syntax for dependency and vulnerable version ranges. - - -Context --------- - -Software package version ranges and version constraints are essential: - -- When resolving the dependencies of a package to express which subset of the - versions are supported. For instance a dependency or requirement statement - such as "I require package foo, version 2.0 or later versions" defines a - range of acceptable foo versions. - -- When stating that a known vulnerability or bug affects a range of package - versions. For instance a security advisory such as "vulnerability 123 affects - package bar, version 3.1 and version 4.2 but not version 5" defines a range of - vulnerable "bar" package versions. - -Version ranges can be replaced by a list enumerating all the versions of -interest. But in practice, all the versions may not yet exist when defining an -open version range such as "v2.0 or later". - -Therefore, a version range is a necessary, compact and practical way to -reference multiple versions rather than listing all the versions. - - -Problem --------- - -Several version range notations exist and have evolved separately to serve the -specific needs of each package ecosystem, vulnerability databases and tools. - -There is no (mostly) universal notation for version ranges and there is no -universal way to compare two versions, even though the concepts that exist in -most version range notations are similar. - -Each package type or ecosystem may define their own ranges notation and version -comparison semantics for dependencies. And for security advisories, the lack of -a portable and compact notation for vulnerable package version ranges means that -these ranges may be either ambiguous or hard to compute and may be best replaced -by complete enumerations of all impacted versions, such as in the `NVD CPE Match -feed `_. - -Because of this, expressing and resolving a version range is often a complex, or -error prone task. - -In particular the need for common notation for version has emerged based on the -usage of Package URLs referencing vulnerable package version ranges such as in -vulnerability databases like `VulnerableCode -`_. - -To better understand the problem, here are some of the notations and conventions -in use: - -- ``semver`` https://semver.org/ is a popular specification to structure version - strings, but does not provide a way to express version ranges. - -- Rubygems strongly suggest using ``semver`` for version but does not enforce it. - As a result some use semver and several popular package do not use strict - semver. Rubygems use their own notation for version ranges which ressembles - the ``node-semver`` notation with some subtle differences. - See https://guides.rubygems.org/patterns/#semantic-versioning - -- ``node-semver`` ranges are used in npm at https://github.com/npm/node-semver#ranges - with range semantics that are specific to ``semver`` and npm. - -- Dart pub versioning scheme is similar to ``node-semver`` and the documentation - at https://dart.dev/tools/pub/versioning provides a comprehensive coverage of - the topic of versioning. Version resolution uses its own algorithm. - -- Python uses its own version and version ranges notation with notable - specificities on how how pre- and post-release suffixes are used - https://www.python.org/dev/peps/pep-0440/ - -- Debian and Ubuntu use their own notation and are remarkabel for their use of - ``epochs`` to disambiguate versions. - https://www.debian.org/doc/debian-policy/ch-relationships.html - -- RPM distros use their own range notation and use epochs like Debian. - https://rpm-software-management.github.io/rpm/manual/dependencies.html - -- Perl CPAN defines its own version range notation similar to this specification - and uses two-segment versions. https://metacpan.org/pod/CPAN::Meta::Spec#Version-Ranges - -- Apache Maven and NuGet use similar math intervals notation using brackets - https://en.wikipedia.org/wiki/Interval_(mathematics) - - - Apache Maven http://maven.apache.org/enforcer/enforcer-rules/versionRanges.html - - NuGet https://docs.microsoft.com/en-us/nuget/concepts/package-versioning#version-ranges - -- gradle uses Apache Maven notation with some extensions - https://docs.gradle.org/current/userguide/single_versions.html - -- Gentoo and Alpine Linux use comparison operators similar to this specification: - - Gentoo https://wiki.gentoo.org/wiki/Version_specifier - - Alpine linux https://gitlab.alpinelinux.org/alpine/apk-tools/-/blob/master/src/version.c - -- Arch Linux https://wiki.archlinux.org/title/PKGBUILD#Dependencies use its - own simplified notation for its PKGBUILD depends array. - -- Go modules https://golang.org/ref/mod#versions use semver versions with - specific version resolution algorithms. - -- Haskell Package Versioning Policy https://pvp.haskell.org/ provides a notation - similar to this specification based on a modified semver with extra notations - such as star and caret. - -- The NVD https://nvd.nist.gov/vuln/data-feeds#cpeMatch defines CPE ranges as - lists of version start and end either including or excluding the start or end - version. And also provides a concrete enumeration of the available ranges as - a daily feed. - -- The version 5 of the NVD CVE JSON data format at - https://github.com/CVEProject/cve-schema/blob/master/schema/v5.0/CVE_JSON_5.0.schema#L303 - defines version ranges with a starting version, a versionType, and an upper - limit for the version range as lessThan or lessThanOrEqual. Or an enumeration - of versions. The versionType is defined as ``"The version numbering system - used for specifying the range. This defines the exact semantics of the - comparison (less-than) operation on versions, which is required to understand - the range itself"``. - -- The OSSF OSV schema https://ossf.github.io/osv-schema/ defines vulnerable - ranges with version events using "introduced" and "limit" fields and an - enumeration of all the versions in these ranges, except for semver-based - versions. A range may be ecosystem-specific based on a provided package - "ecosystem" value that ressembles closely the Package URL package "type". - - -The way two versions are compared as equal, lesser or greater is a closely -related topic: - -- Each package ecosystem may have evolved its own peculiar version string - conventions, semantics and comparison procedure. - -- For instance, ``semver`` is a prominent specification in this domain but this is - just one of the many ways to structure a version string. - -- Debian, RPM, PyPI, Rubygems, and Composer have their own subtly different - approach on how to determine which version is greater or lesser. - - -Solution ---------- - -A solution to the many version range syntaxes is to design a new notation to -unify them all with: - -- a mostly universal and minimalist, compact notation to express version ranges - from many different package types and ecosystems. - -- the package type-specific definitions to normalize existing range expressions - to this common notation. - -- the designation of which algorithm or procedure to use when comparing two - versions such that it is possible to resolve if a version is within or - outside of a version range. - -We call this solution "version range specifier" or "vers" and it is described -in this document. - - -Version range specifier -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -A version range specifier (aka. "vers") is a URI string using the ``vers`` -URI-scheme with this syntax:: - - vers:/|,... - -For example to define a set of versions that contains either version ``1.2.3``, -or any versions greater than or equal to ``2.0.0`` but less than ``5.0.0`` using -the ``node-semver`` versioning scheme, the version range specifier will be:: - - vers:npm/1.2.3|>=2.0.0,<5.0.0 - -Each ```` in the pipe-separated list is either a simple -constraint such as:: - - - -Or a composite constraint grouping multiple ```` joined by -a comma such as:: - - ,... - -The pipe is a logical `OR` and the comma is a logical `AND`. - -A version range specifier is therefore an "OR of ANDs" where there are two -levels of constraints that a version should satisfy to be part of the range: - -- At the first level, anyone of the constraints should be satisfied -- At the second level, all of the constraints must be satisfied - -This is also called a "disjunctive normal form" in boolean logic. -See https://en.wikipedia.org/wiki/Disjunctive_normal_form for details. - -``vers`` is the URI-scheme and is an acronym for "VErsion Range Specifier". It -has been selected because it is short, obviously about version and available -for a future formal registration for this URI-scheme at the IANA registry. - - -```` ------------------------- - -The ```` (such as ``npm``, ``deb``, etc.) determines: - -- the specific notation and conventions used for a version string encoded in - this scheme. Versioning schemes often specify a version segments separator and - the meaning of each version segments, such as [major.minor.patch] in semver. - -- how two versions are compared as greater or lesser to determine if a version - is within or outside a range. - -- how a versioning scheme-specific range notation can be transformed in the - ``vers`` simplified notation defined here. - -- by convention the versioning scheme should be the same string as the Package - URL package type for a given package ecosystem. It is OK to have other schemes - beyond the purl type and even schemes that are specific to a single package. - -The ```` is followed by a slash "/". - - -```` ----------------------------- - -After the ```` and "/" there are one or more -```` separated by a pipe "|". The pipe "|" means that -**any** of these constraints must be satisfied for a version to be resolved as -within this version range. - -Each ```` of this pipe-separated list can be either a -single constraint or a list of constraints separated in turn by an comma "," as -in ``1.2.3|>=2.0.0,<5.0.0``. - -Multiple ```` combined with a comma means that **all** these -constraints must be satisfied for a version to be resolved as contained in this -range. - -Each simple version constraint has this syntax:: - - - -The ```` is one of these comparison operators: - -- "=": Version equality comparator. It is the default and implied if not - present and means that a version must be equal to the provided version. - For example: "=1.2.3". It must be omitted in the canonical representation. - Equality is based on the equality of two lower-cased and normalized version - strings and is typically not versioning scheme-specific, though some - scheme such as pypi PEP440 may apply some version string normalization - before testing for equality. - -- "!=": Version exclusion or inequality comparator. This means a version must - not be equal to the provided version and this version must be excluded from - the range. For example: "!=1.2.3" means that version "1.2.3" is excluded. - -- "<", "<=": Less than or less-or-equal version comparators points to all - versions less than or equal to the provided version. For example "<=1.2.3" - means less than or equal to "1.2.3". - -- ">", ">=": Greater than or greater-or-equal version comparators points to - all versions greater than or equal to the provided version. For example - ">=1.2.3" means greater than or equal to "1.2.3". - -- The way two version strings are compared using these comparators is defined - by the ````. - -- The structure and meaning of a version string such as "1.2.3" is defined by - the ````. For instance, ``semver`` defines three - dot-separated segments name major, minor and patch. - -- The special star "*" ```` matches any version. This star - constraint must be used **alone** in a version range, exclusive of any other - constraint. For example "vers:deb/\*" resolves to any version of a Debian - package. - -- The way each of these comparators work when doing a version comparison is - specific to a versioning scheme. - - -Examples -~~~~~~~~~ - -TODO. - - -Normalized or canonical representation -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -- A version range specifier contains only printable ASCII letters, digits and - punctuation. - -- Spaces are not significant and are removed in the canonical form. For example - "!=1.2.3" and " ! = 1.2. 3" are equivalent. And so are "1.2.3 & < = 2.0.0" and - "1.2.3&<=2.0.0" - -- A version range specifier is case-insensitive and lowercase in canonical form. - -- The ordering of multiple ```` in a range specifier is not - significant. The canonical ordering is by sorting these by lexicographical - order applied with this two steps approach: - - - first to each sub-list of comma-separated ````. - - then to the top level list of pipe-separated ````. - -- A version in a ```` can only contain printable ASCII - characters excluding the special characters used as separators and comparators - ``><=!,&*|``. If it contains special characters (which should be rare in - practice) the version string in a constraint must be quoted using the URL - quoting rules. - - -Using version range specifiers -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -``vers`` primary usage is to test if a version is within or outside a range. - -An version is within a version range if satisfies or is "contained" in -**any one** of the first level of constraints. To satisfy or be "contained" in -a first level constraint, a version must satisfy or be "contained" in -**all** the second level of constraints. Otherwise, the input version is outside -of the version range. - -Some important usages derived from this primary usage include: - -- **Resolving a version range specifier to a list of concrete versions.** - In this case, the input is the set of known versions of a package (typically - obtained from some package repository or registry). Each version is then - tested individually to check if it is within or outside the range. For - example, this can be used to determine which existing package versions are - affected by a known vulnerability if they match the vulnerability version - range specifier. - -- **Selecting one of several versions that are within a range.** - In this case, given several versions that are within a range and several - packages that each expression inter dependencies together with version ranges, - package management tools need to determine and select a set of package versions - that satify all the version ranges of all dependencies. This usually requires - deploying heuristics and algorithms (possibly complex such as sat solvers) - that are ecosystem- and tool-specific and outside of the scope for this - specification; yet ``vers`` could be used in tandem with ``purl`` to provide - an input to a dependencies resolution process. - - -Parsing version range specifiers -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -To parse a version range specifier string: - -- Remove all spaces and tabs. -- Start from left, and split once on colon ":". -- The left hand side is the URI-scheme that must be lowercase. - - Verify that the URI-scheme value is ``vers``. -- The right hand side is the specifier. - -- Split the specifier from left once on a slash "/". -- The left hand side is the that must be lowercase. -- The right hand side is a list of one or more constraints. - -- If the constraints string is equal to "*", the is "*". - Parsing is done and no further processing is needed for this ``vers``. A tool - may be strict and report an error if there are extra characters beyond "*" or - be lenient. - -- Split the constraints on pipe "|". The result is a list of top-level - lists. Consecutive pipes should be treated as one. - -- For each list: - - - Split on comma ",". Consecutive commas should be treated as one. The result - is a sub-list of . - - - For each in this sub-list: - - - Identify the comparator and version based on the - start of the in this sequence: - - - If it starts with "=", then the comparator is "=" - - If it starts with "!=", then the comparator is "!=". - - If it starts with "<=", then the comparator is "<=". - - If it starts with ">=", then the comparator is ">=". - - If it starts with "<", then the comparator is "<". - - If it starts with ">", then the comparator is ">". - - Else the comparator is "=" (default) and the - version is the full string. - - - After the operation and removing the comparator from - string, the remaining string is the version. - - - Validate that the version is not empty. - - - If the version contains a percent "%" character, apply URL quoting rules - to unquote this string. - - - Append the comparator and version of this constraint to the inner list - of constraints. - - - Append the accumulated list of (comparator and version) that must apply to - the top level list of constraints. - -- Finally return the and the nested list of - - -Notes and caveats -~~~~~~~~~~~~~~~~~~~ - -- Comparing versions from two different versioning schemes is unspecified. Even - though there may be some similarities between the ``semver`` version of an npm - and the `debian` version of its Debian packaging, these similarities are - specific to each versioning scheme. Tools should report an error in these - cases as it does not make sense to perform these comparisons. - - -Some of the known versioning schemes -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -TODO: add details on how to convert to and from ``vers`` for a given versioning -scheme and package type. - -- ``deb``: Debian and Ubuntu https://www.debian.org/doc/debian-policy/ch-relationships.html - The comparators are <<, <=, =, >= and >>. - -- ``rpm``: RPM distros https://rpm-software-management.github.io/rpm/manual/dependencies.html - The version comparison routine of rmpvercmp is also used by archlinux Pacman. - -- ``gem``: Rubygems https://guides.rubygems.org/patterns/#semantic-versioning - which is almost but not exactly ``node-semver``. - -- ``npm``: npm uses node-semver which is based on semver with its own range - notation https://github.com/npm/node-semver#ranges - A similar but different scheme is used by Rust - https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html - and several other package types may use ``node-semver``-like ranges. But most - of these related schemes are not strictly the same as what is implemented in - ``node-semver``. For instance PHP ``composer`` may need its own scheme as this - is not strictly ``node-semver``. - -- ``pypi``: Python https://www.python.org/dev/peps/pep-0440/ - -- ``perl``: Perl https://perlmaven.com/how-to-compare-version-numbers-in-perl-and-for-cpan-modules - -- ``go``: Go modules https://golang.org/ref/mod#versions use semver versions - with a specific minimum version resolution algorithm. - -- ``maven``: Apache Maven http://maven.apache.org/enforcer/enforcer-rules/versionRanges.html - -- ``nuget``: NuGet https://docs.microsoft.com/en-us/nuget/concepts/package-versioning#version-ranges - Note that Apache Maven and NuGet are following a similar approach with a - math-derived intervals syntax as in https://en.wikipedia.org/wiki/Interval_(mathematics) - -- ``gentoo``: Gentoo https://wiki.gentoo.org/wiki/Version_specifier - -- ``alpine``: Alpine linux https://gitlab.alpinelinux.org/alpine/apk-tools/-/blob/master/src/version.c - which is using Gentoo-like conventions. - -- ``generic``: a generic version comparison algorithm (which is TBD, likely a - split on punctuation and dealing with digit vs. strings comparisons, like is - done in libversion) - -TODO: add Rust, composer and archlinux - - -Implementations -~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -- Python: https://github.com/nexB/univers -- Yours! - - -Why not reuse existing version range notations? -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Most existing version range notations are tied to a specific version string -syntax and are therefore not readily applicable to other contexts. For example, -the use of elements such as tilde and caret ranges in Rubygems, npm or Dart -notations implies that a certain structure exists in the version string (semver -or semver- like). The inclusion of these additional comparators is a result of -the history and evolution in a given package ecosystem to address specific needs. - -In practice, the unified and reduced set of comparators and syntax defined for -``vers`` has been designed such that all these notations can be converted to a -``vers`` and back from a ``vers`` to the original notation. - -In contrast, this would not be possible with existing notations. For instance, -the Python notation may not work with npm semver versions and reciprocally. - -There are likely to be a few rare cases where round tripping from and to -``vers`` may not be possible, and in any case round tripping to and from ``vers`` -should produce equivalent results and even if not strictly the same original -strings. - -Another issue with existing version range notations is that they are primarily -meant to be used for dependency constraints and may not readily be reusable for -the definitions of vulnerable ranges. In particular, a vulnerability may exist -for multiple "version branches" of a given package such as with Django 2.x and -3.x. Several version range notations have difficulties to communicate these -as typically all the version constraints must be satisfied. In constrast, -a vulnerability can affect multiple disjoint version ranges of a package and any -version satisfying these constraints would be vulnerable: it may not be possible -to express this with a notation designed exclusively for dependent versions -resolution. - - -Why not use the NVD CPE Ranges? -############################### - -See: - -- https://nvd.nist.gov/vuln/vulnerability-detail-pages#divRange -- https://nvd.nist.gov/developers/vulnerabilities#divResponse -- https://csrc.nist.gov/schema/nvd/feed/1.1/nvd_cve_feed_json_1.1.schema - -The version ranges notation defined in the JSON schema of the CVE API payload -uses these four fields: ``versionStartIncluding``, ``versionStartExcluding``, -``versionEndIncluding`` and ``versionEndExcluding``. For example:: - - "versionStartIncluding": "7.3.0", - "versionEndExcluding": "7.3.31", - "versionStartExcluding" : "9.0.0", - "versionEndIncluding" : "9.0.46", - -In addition to these ranges, the NVD publishes a list of concrete CPE with -versions resolved for a range with daily updates at -https://nvd.nist.gov/vuln/data-feeds#cpeMatch - -Note that the NVD CVE configuration is a complex specification that goes well -beyond version ranges and is used to match comprehensive configurations across -multiple products and version ranges. ``vers`` focus is exclusively versions. - -The NVD JSON notation is verbose in contrast with ``vers`` that attempts to -provide a compact notation. It provides the same =, <=, < and > comparators -specified in ``vers`` and found in other notations. - - -Why not use node-semver ranges? -############################### - -- https://github.com/npm/node-semver#ranges - -The node-semver spec is similar to this spec but is an AND of ORs constraints -with a few practical issues: - -- The space means "AND", therefore whitespaces are significant. Having - significant whitespaces in a string makes normalization more complicated and - may be a source of confusion if you remove the spaces from the string. Using - a comma as an "AND" operator in ``vers`` makes this explicit and avoids the - ambiguity of a space. - -- There is no negation "!=" operator meaning that some version constraints are - difficult to express and require combining < and > comparators. For instance - stating that a vulnerability affects babel 6.2 or later but not babel 7.0 is - possible but complicated. - -- The advanced range syntax has grown to be rather complex using hyphen, stars, - carets and tilde constructs that are all tied to the JavaScript and npm ways - of handling versions in their ecosystem and are bound furthermore to the - semver semantics and its npm implementation. These are not readily reusable - elsewhere and these extended multiple comparators and modifiers make the - notation grammar more complex to parse for a machine and harder to read for - human. - -Notations that are directly derived from node-semver as used in Rust and PHP -Composer have the same issues. - - -Why not use Python pep-0440 ranges? -##################################### - -See: - -- https://www.python.org/dev/peps/pep-0440/#version-specifiers - -The Python pep-0440 "Version Identification and Dependency Specification" -provides a comprehensive specification for Python package versioning and a -notation for "version specifiers" to express the version constraints of -dependencies. - -This specification is similar to this ``vers`` spec, but has a richer notation -with some aspects specific to the versions used only in the Python ecosystem. - -- In particular pep-0440 uses tilde, triple equal and wildcard star operators - that are specific to how two Python versions are compared. - -- The comma separator between constraints is a logical "AND" rather than an - "OR". The "OR" does not exist in the syntax making some version ranges - harder to express, in particular for vulnerabilities that may affect several - exact versions or version ranges such as when there are multiple release - branches that exist in parallel. For instance a statement such as: Django 1.2 - or later, or Django 2.2 or later or Django 3.2 or later is difficult to - express without an "OR" logic. - - -Why not use Rubygems requirements notation? -############################################### - -- https://guides.rubygems.org/patterns/#declaring-dependencies - -The rubygems specification suggests but does not enforce using semver. It is -similar to this spec's operators with the addition of the "~>" aka. pessimistic -operator or tilde-wakka which is similar to the "tilde" used in node-semver and -implies semver versioning. This makes the notation impractical to reuse -in places that do not use the same semver-like semantics. - - -Why not use fancier comparators such as a tilde, caret and star? -################################################################## - -Several existing notations such as used with npm, gem or python or composer -provide syntactic shorthands such as: - -- a tilde prefix or ~> prefix or =~ as in "~1.3" or "~>1.2.3" -- a caret ^ prefix as in "^ 1.2" -- using a star in a segment of a version as in "1.2.*" -- dash-separated ranges as in "1.2 - 1.4" - -These range syntaxes can typcially be reduced to a set of simpler operators. -Furthermore they are designed for the structure of a version string (most often -semver) as used in one ecosystem and therefore are not reusable in another -ecosystem that would not use the version string conventions. - - -Why not use mathematical interval notation for ranges? -####################################################### - -Apache Maven and NuGet make use of a mathematical interval with "[" and ")" as a -syntax for version ranges. - -All other notations are using >, <, and = as base symbols for ranges. ``vers`` -reuses this approach because it is more common across package ecosystems. - - -References -~~~~~~~~~~~~~~~~~~~~ - -Here are some of the discussions that led to the creation of this specification: - -- https://github.com/package-url/purl-spec/issues/66 -- https://github.com/package-url/purl-spec/issues/84 -- https://github.com/package-url/purl-spec/pull/93 -- https://github.com/nexB/vulnerablecode/issues/119 -- https://github.com/nexB/vulnerablecode/issues/140 From 80b515a4dafc5072f645c0c71dcef34d0ff1cf8e Mon Sep 17 00:00:00 2001 From: Philippe Ombredanne Date: Thu, 16 Dec 2021 00:58:47 +0100 Subject: [PATCH 697/707] Implement latest "vers" spec Using full comparator set and single constraints list Reference: https://github.com/package-url/purl-spec/pull/139 Reference: https://github.com/package-url/purl-spec/pull/139/commits/5430731ece32b790c047b71185fc6adca0f88656 Signed-off-by: Philippe Ombredanne --- README.rst | 33 +-- src/univers/version_constraint.py | 374 ++++++++++++++++++++++++------ src/univers/version_range.py | 154 ++++++------ src/univers/versions.py | 25 +- tests/test_version_range.py | 67 ++++-- 5 files changed, 453 insertions(+), 200 deletions(-) diff --git a/README.rst b/README.rst index 972f3e47..483db93d 100644 --- a/README.rst +++ b/README.rst @@ -66,18 +66,20 @@ For each scheme, **univers** provides an implementation for: version range syntax. It can parse and convert an existing native version range strings to this unified syntax. For example, this means: -- converting ">1.2.3" as used in a Python package into ``vers:pypi/>1.2.3``, +- converting ">=1.2.3" as used in a Python package into ``vers:pypi/>=1.2.3``, -- or converting "^1.0.2" as used in an npm package dependency declartion into - ``vers:npm/>=1.0.2,<2.0.0`` +- or converting "^1.0.2" as used in an npm package dependency declaration into + ``vers:npm/>=1.0.2|<2.0.0`` The supported package ecosystems versioning schemes and underlying libraries include: - npm that use the "node-semver" ranges notation and the semver versions syntax - This is supported in part by the `semantic_version `_ library. + This is supported in part by the `semantic_version + `_ library. -- pypi: handled by Python's packaging library and the standard ``packaging.version`` module. +- pypi: handled by Python's packaging library and the standard + ``packaging.version`` module. - Rubygems which use a semver-like but not-quite-semver scheme and there can be commonly more than three version segments. @@ -86,22 +88,27 @@ include: as a pessimistic operator and supports exclusion with != and does not support "OR" between constraints (that it call requirements). Gem are handled by Python port of the Rubygems requirements and version - handling code from the `puppeteer tool `_ + handling code from the `puppeteer tool + `_ -- debian: handled by the `debian-inspector `_ - library. +- debian: handled by the `debian-inspector library + `_. -- maven: handled by the embedded `pymaven `_ library. +- maven: handled by the embedded `pymaven library + `_. -- rpm: handled by the embedded `rpm_vercmp `_ library. +- rpm: handled by the embedded `rpm_vercmp library + `_. - golang (using semver) - PHP composer -- ebuild/gentoo: handled by the embedded `gentoo_vercmp `_ module. +- ebuild/gentoo: handled by the embedded `gentoo_vercmp module + `_. -- arch linux : handled by the embedded `arch utility borrowed from msys2 `_ module. +- arch linux: handled by the embedded `arch utility module borrowed from msys2 + `_. The level of support for each ecosystem may not be even for now and new schemes and support for more package types are implemented on a continuous basis. @@ -142,7 +149,7 @@ Normalize a version range from an npm: from univers.version_range import NpmVersionRange range = NpmVersionRange.from_native("^1.0.2") - assert str(range) == "vers:npm/>=1.0.2,<2.0.0" + assert str(range) == "vers:npm/>=1.0.2|<2.0.0" Test if a version is within or outside a version range: diff --git a/src/univers/version_constraint.py b/src/univers/version_constraint.py index 8da70cfd..b945e15e 100644 --- a/src/univers/version_constraint.py +++ b/src/univers/version_constraint.py @@ -6,12 +6,24 @@ import operator from functools import total_ordering - import attr from univers.utils import remove_spaces from univers.versions import Version +try: + # only stanadard in Python 3.10 and up + from itertools import pairwise # NOQA +except ImportError: + # back from docs at https://docs.python.org/3/library/itertools.html#itertools.pairwise + import itertools + + def pairwise(iterable): + a, b = itertools.tee(iterable) + next(b, None) + return zip(a, b) + + """ Universal version constraint object that stores a comparator such as "=" and an ecosystem- or package-specific Version object. @@ -26,14 +38,15 @@ def operator_star(a, b): return True +# a minimalist, reduced set of comparators +MINIMALIST_COMPARATORS = {">=", "<", "*"} + COMPARATORS = { - # note: the operators may look like inverted... but that's because we - # b in a rather than a in b as a containment test - ">=": operator.le, - "<=": operator.ge, + ">=": operator.ge, + "<=": operator.le, "!=": operator.ne, - "<": operator.gt, - ">": operator.lt, + "<": operator.lt, + ">": operator.gt, "=": operator.eq, "*": operator_star, } @@ -44,48 +57,73 @@ def operator_star(a, b): class VersionConstraint: """ Represent a single constraint composed of a comparator and a version. - Version constraints are sortable by version then comparator + VersionConstraint is: + - comparable and orderable e.g., implements functools.total_ordering + by version then comparator. + - immutable and hashable. """ # one of the COMPARATORS - comparator = attr.ib(type=str) + comparator = attr.ib(type=str, default="=") # a Version subclass instance or None - version = attr.ib(type=Version, default=None) + version = attr.ib(type=Version, default="") + + # a function for the comparator + comp_operator = attr.ib(default=None, repr=False) + + def __attrs_post_init__(self): + # Notes: setattr is used because this is an immutable frozen instance. + # See https://www.attrs.org/en/stable/init.html?#post-init + try: + object.__setattr__(self, "comp_operator", COMPARATORS[self.comparator]) + except KeyError as e: + raise ValueError(f"Unknown comparator: {self.comparator}") from e def __str__(self): """ Return a string representing this constraint. For example:: >>> assert str(VersionConstraint(comparator=">=", version="2.3")) == ">=2.3" - >>> assert str(VersionConstraint(comparator="*", version=None)) == "*" + >>> assert str(VersionConstraint(comparator="*")) == "*" >>> assert str(VersionConstraint(comparator="<", version="2.3")) == "<2.3" >>> assert str(VersionConstraint(comparator="=", version="2.3.0")) == "2.3.0" + >>> assert str(VersionConstraint(version="2.3.0")) == "2.3.0" """ if self.comparator == "*": return "*" - elif self.comparator == "=": + + if self.comparator == "=": return str(self.version) - else: - version = str(self.version) - return f"{self.comparator}{version}" + + version = str(self.version) + return f"{self.comparator}{version}" to_string = __str__ def to_dict(self): return dict(comparator=self.comparator, version=str(self.version)) + def __hash__(self): + return hash(str(self)) + + def __eq__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return self.comparator == other.comparator and self.version == other.version + def __lt__(self, other): if not isinstance(other, self.__class__): return NotImplemented - return self.version.__lt__ == other.version + # we compare tuples, version first + return (self.version, self.comparator).__lt__((other.version, other.comparator)) @classmethod def from_string(cls, string, version_class): """ - Return a single VersionConstraint built from a constraint ``string`` and a - ``version_class`` Version class. + Return a single VersionConstraint built from a constraint ``string`` and + a ``version_class`` Version class. """ constraint_string = remove_spaces(string) comparator, version = cls.split(constraint_string) @@ -123,8 +161,8 @@ def split(string): for comparator in COMPARATORS: if constraint_string.startswith(comparator): - # we do not report an error if this is not valid - version = constraint_string.lstrip("><=!") + # NOTE: we do not report an error if this is not valid + version = constraint_string.lstrip(comparator) if comparator == "*": version = "" return comparator, version @@ -132,7 +170,6 @@ def split(string): # default to equality return "=", constraint_string - # FIXME: this may be not enough to only handle "contains"? def __contains__(self, version): """ Return a True if the ``version`` Version is contained in this @@ -165,66 +202,269 @@ def __contains__(self, version): >>> assert v24 in VersionConstraint(comparator="<=", version=v24) >>> assert v24 not in VersionConstraint(comparator="<", version=v24) """ - if version.__class__ != self.version.__class__: + + if not isinstance(version, self.version.__class__): raise ValueError( f"Cannot compare {version.__class__!r} instance " f"with {self.version.__class__!r} instance." ) - try: - comp_operator = COMPARATORS[self.comparator] - except KeyError as e: - raise ValueError(f"Unknown comparator: {self.comparator}") from e - - return comp_operator(self.version, version) + return self.comp_operator(version, self.version) contains = __contains__ @classmethod def validate(cls, constraints): """ - Raise an assertion error if the ``constraints`` is not a two-level - nested list of VersionConstraint objects. + Raise an assertion error if the ``constraints`` is not a list of + VersionConstraint objects or if two VersionConstraint contain the same + Version (ignoring the comparator). + Also validate that the sequence of comparators is valid. + Return True otherwise. """ - assert isinstance(constraints, (list, tuple)), constraints - for inner_constraints in constraints: - assert isinstance(inner_constraints, (list, tuple)), inner_constraints - for constraint in inner_constraints: - assert isinstance(constraint, VersionConstraint), constraint + + if not isinstance(constraints, (list, tuple)): + raise ValueError(f"{constraints!r} is a not list or tuple") + + if not all(isinstance(c, VersionConstraint) for c in constraints): + raise ValueError(f"{constraints!r} can contain only VersionConstraint") + + if len(set(c.version for c in constraints)) != len(constraints): + raise ValueError(f"{constraints!r} cannot contain duplicated Version") + + constraints.sort() + return validate_comparators(constraints) @classmethod - def sort(cls, constraints): + def dedupe(cls, constraints): """ - Return sorted nested list of ``constraints`` using the "vers" canonical - order. Sorting is done in place. + Return a new ``constraints`` list with duplicated constraints removed. + This includes removing exact duplicates adn redundant constraints. """ - for inner_constraints in constraints: - inner_constraints.sort(key=lambda vc: str(vc)) - constraints.sort(key=lambda vc: str(vc)) + constraints = deduplicate_exact(constraints) + constraints = deduplicate_comparators(constraints) return constraints - @classmethod - def to_constraints_string(cls, constraints): - """ - Return a string representing the provided ``constraints`` nested - list of VersionConstraint objects such that the outer sequence - VersionConstraints are joined with an "OR" e.g., a "vers" pipe "|" and - the inner sequences of VersionConstraint are each joined with an "AND" - e.g., a "vers" comma ",". - For instance: - >>> from univers.versions import PypiVersion - >>> constraints = [ - ... [VersionConstraint(comparator="=", version=PypiVersion("2"))], - ... [ - ... VersionConstraint(comparator="=>", version=PypiVersion("3")), - ... VersionConstraint(comparator="<", version=PypiVersion("4")), - ... ], - ... [VersionConstraint(comparator="=", version=PypiVersion("5"))], - ... ] - >>> assert VersionConstraint.to_constraints_string(constraints) == "2|=>3,<4|5" - """ - cls.validate(constraints) - anyof_constraints = [] - for inner_constraints in constraints: - allof_constraints = ",".join(map(str, inner_constraints)) - anyof_constraints.append(allof_constraints) - return "|".join(anyof_constraints) + +def deduplicate_exact(constraints): + """ + Return a new ``constraints`` list with exact duplicated constraints removed. + """ + seen = set() + unique = [] + for c in constraints: + if c not in seen: + unique.append(c) + seen.add(c) + return unique + + +def validate_comparators(constraints): + """ + Raise an assertion error if the ``constraints`` list contains an invalid + sequence of constraint comparators according to ``vers`` rules. + Return True otherwise. + + The following are the validity rules for contiguous constraints where the + constraints are canonical e.g., sorted by version and versions are unique + ignoring comparators: + + - "*" can only occur alone + - "!=" can be followed by anything, i.e., one of "=", "!=", ">", ">=", "<", "<=" + + And ignoring all "!=": + - "=" can be followed only by one of "=", ">", ">=" + + And ignoring all "=" and "!=", there must be an alternation of greater and lesser: + - "<" and "<=" can only be followed by one of ">", ">=" + - ">" and ">=" can only be followed by one of "<", "<=" + """ + + if any(c.comparator == "*" for c in constraints): + if len(constraints) != 1: + raise ValueError(f"Invalid {constraints!r}: can contain only one star '*'") + return True + + # discard != that can occur anywhere + constraints = [c for c in constraints if c.comparator != "!="] + if not constraints: + return True + + # check that equals is followed only by "=", ">", ">=" + invalid_equal = [ + (cur, nxt) + for cur, nxt in pairwise(constraints) + if cur.comparator == "=" and nxt.comparator not in ("=", ">", ">=") + ] + if invalid_equal: + raise ValueError( + f"Invalid {constraints!r}\n: where \n{invalid_equal!r} " + "cannot contain an equal = followed by either < or <=" + ) + + # discard = that have been validated above + constraints = [c for c in constraints if c.comparator != "="] + if not constraints: + return True + + # from now on this must be an alternation of greater/lesser + for cur_constraint, nxt_constraint in pairwise(constraints): + cur_comp = cur_constraint.comparator + nxt_comp = nxt_constraint.comparator + + if (cur_comp in ("<", "<=") and nxt_comp not in (">", ">=")) or ( + cur_comp in (">", ">=") and nxt_comp not in ("<", "<=") + ): + + raise ValueError( + f"Invalid {constraints!r}: {cur_constraint!r} " + f"cannot be followed by {nxt_constraint!r}" + ) + + return True + + +def deduplicate_comparators(constraints): + """ + Return a list of VersionConstraint given a ``constraints`` list by + discarding redundant constraints according to ``vers`` rules. + """ + if len(constraints) == 1 or any(c.comparator == "*" for c in constraints): + return list(constraints) + + constraints = sorted(constraints) + + inequal_constraints = [c for c in constraints if c.comparator == "!="] + constraints = [c for c in constraints if c.comparator != "!="] + + if not constraints: + return sorted(inequal_constraints) + + # iterate as long as constraints length diminishes with each ieration + cycle = 1 + while True: + starting_length = len(constraints) + constraints = list(dedup(constraints)) + ending_length = len(constraints) + if ending_length == 1 or ending_length == starting_length: + # no filtering happened in this iteration, we are done + break + cycle += 1 + + return sorted(inequal_constraints + constraints) + + +def dedup(constraints): + """ + Yield filtered constraints, discarding redundant ones according to ``vers``. + """ + skip = False + for cur, nxt in pairwise(constraints): + cur_comp = cur.comparator + nxt_comp = nxt.comparator + if skip: + skip = False + continue + + if cur_comp in ("=", "<", "<=") and nxt_comp in ("<", "<="): + # keep only next (drop current) + skip = True + yield nxt + continue + + if cur_comp in (">", ">=") and nxt_comp in ("=", ">", ">="): + # keep only current (drop next) + skip = True + yield cur + continue + + # keep cur + skip = False + yield cur + + # yield last next + yield nxt + + +def contains_version(version, constraints): + """ + Return True an assertion error if the ``constraints`` list contains the + ``version`` Version object according to ``vers`` rules. + """ + # If the constraint list contains only one item and the comparator is "*", + # then the "tested version" is IN the range. Check is finished. + + # If the constraint list contains only one item and and the "tested version" + # satisfies the comparator then the "tested version" is IN the range. + # Check is finished. + if len(constraints) == 1: + return version in constraints[0] + + # If the "tested version" is equal to the any of the constraint version + # where the constraint comparator is for equality (any of "=", "<=", or ">=") + # then the "tested version" is in the range. Check is finished. + for constraint in constraints: + if "=" in constraint.comparator and version == constraint.version: + return True + + # If the "tested version" is equal to the any of the constraint version where + # the constraint comparator is "=!" then the "tested version" is NOT in the + # range. Check is finished. + for constraint in constraints: + if "!=" in constraint.comparator and version == constraint.version: + return False + + # Split the constraint list in two sub lists: + # a first list where the comparator is "=" or "!=" + # a second list where the comparator is neither "=" nor "!=" + constraints = [c for c in constraints if c.comparator not in ("=", "!=")] + if not constraints: + return False + + # Iterate over the current and next contiguous constraints pairs (aka. pairwise) + # in the second list. + # For each current and next constraint: + + cur_comp = nxt_comp = cur_constraint = nxt_constraint = None + first_iteration = True + for cur_constraint, nxt_constraint in pairwise(constraints): + cur_comp = cur_constraint.comparator + nxt_comp = nxt_constraint.comparator + + # If this is the first iteration and current comparator is "<" or <=" + # and the "tested version" is less than the current version + # then the "tested version" is IN the range. Check is finished. + if first_iteration: + if cur_comp in ("<", "<=") and version < cur_constraint.version: + return True + first_iteration = False + + # If current comparator is ">" or >=" and next comparator is "<" or <=" + # and the "tested version" is greater than the current version + # and the "tested version" is less than the next version + # then the "tested version" is IN the range. Check is finished. + if ( + cur_comp in (">", ">=") + and nxt_comp in ("<", "<=") + and version > cur_constraint.version + and version < nxt_constraint.version + ): + return True + + # If current comparator is "<" or <=" and next comparator is ">" or >=" + # then these versions are out the range. Continue to the next iteration. + elif cur_comp in ("<", "<=") and nxt_comp in (">", ">="): + pass + + else: + # this should never happen as the constraints must be valid going in + raise Exception(f"Invalid constraints sequence: {constraints }") + + # If this is the last iteration and next comparator is ">" or >=" + # and the "tested version" is greater than the next version + # then the "tested version" is IN the range. Check is finished. + if nxt_comp in (">", ">=") and version > nxt_constraint.version: + return True + + # Reaching here without having finished the check before means that the + # "tested version" is NOT in the range. + return False diff --git a/src/univers/version_range.py b/src/univers/version_range.py index c1e3b0d6..d6fc27c4 100644 --- a/src/univers/version_range.py +++ b/src/univers/version_range.py @@ -10,16 +10,19 @@ from semantic_version.base import AllOf from semantic_version.base import AnyOf +from univers import gem from univers import versions from univers.utils import remove_spaces from univers.version_constraint import VersionConstraint -from univers import gem +from univers.version_constraint import contains_version @attr.s(frozen=True, order=False, eq=True, hash=True) class VersionRange: """ Base version range class. Subclasses must provide implememt. + A VersionRange represents a list of constraints on the versions "timeline" + of a package. """ # Versioning scheme. By convention this is the same as the Package URL @@ -40,7 +43,7 @@ class VersionRange: constraints = attr.ib(type=list, default=attr.Factory(list)) def __attrs_post_init__(self, *args, **kwargs): - VersionConstraint.sort(self.constraints) + self.constraints.sort() @classmethod def from_native(cls, string): @@ -58,7 +61,7 @@ def to_native(self): return NotImplementedError @classmethod - def from_string(cls, vers): + def from_string(cls, vers, dedupe=False, validate=False): """ Return a VersionRange built from a ``vers`` version range spec string, such as "vers:npm/1.2.3,>=2.0.0" @@ -66,90 +69,70 @@ def from_string(cls, vers): vers = remove_spaces(vers) uri_scheme, _, scheme_range_spec = vers.partition(":") - if not uri_scheme == "vers": + uri_scheme = uri_scheme.lower() + + if uri_scheme != "vers": raise ValueError(f"{vers!r} must start with the 'vers:' URI scheme.") versioning_scheme, _, constraints = scheme_range_spec.partition("/") + versioning_scheme = versioning_scheme.lower() range_class = RANGE_CLASS_BY_SCHEMES.get(versioning_scheme) if not range_class: raise ValueError( f"{vers!r} has an unknown versioning scheme: " f"{versioning_scheme!r}.", ) + constraints = constraints.strip() if not constraints: raise ValueError(f"{vers!r} specifies no version range constraints.") - # parse_constraints - version_constraints = [] - for or_constraints in constraints.split("|"): - and_constraints = [] - for constraint in or_constraints.split(","): - constraint = VersionConstraint.from_string( - string=constraint, - version_class=range_class.version_class, - ) - and_constraints.append(constraint) - version_constraints.append(and_constraints) + if constraints.startswith("*"): + if constraints != "*": + raise ValueError(f"{vers!r} contains an invalid '*' constraint.") + return range_class([VersionConstraint.from_string("*")]) + + parsed_constraints = [] + + constraints = constraints.strip("|") + for const in constraints.split("|"): + constraint = VersionConstraint.from_string( + string=const, + version_class=range_class.version_class, + ) + parsed_constraints.append(constraint) + + parsed_constraints.sort() + if dedupe: + parsed_constraints = VersionConstraint.dedupe(parsed_constraints) + if validate: + VersionConstraint.validate(parsed_constraints) - return range_class(version_constraints) + return range_class(parsed_constraints) def __str__(self): - constraints = VersionConstraint.to_constraints_string(self.constraints) + constraints = "|".join(str(c) for c in sorted(self.constraints)) return f"vers:{self.scheme}/{constraints}" to_string = __str__ def to_dict(self): - VersionConstraint.validate(self.constraints) - - constraints = [] - for inner_constraints in self.constraints: - constraints.append([c.to_dict() for c in inner_constraints]) + constraints = [c.to_dict() for c in self.constraints] return dict(scheme=self.scheme, constraints=constraints) def __contains__(self, version): """ Return True if this VersionRange contains the ``version`` Version object. A version is contained in a VersionRange if it satisfies its - constraints this way: - - - at least one of its ``constraints`` nested inner list of - VersionConstraint should be satisfied - - - a nested inner list of VersionConstraint is satisfied if all of its - VersionConstraints are satisfied, e.g., the ``version`` is contained in - all of the version ranges described by the constraint. - - - a VersionConstraint is "satisfied" if the ``version`` Version is "in" - this VersionConstraint. Conversely, the ``version`` satisfies a constraint. + constraints according to ``vers`` rules. """ if not isinstance(version, self.version_class): raise TypeError( f"{version!r} is not of expected type: {self.version_class!r}", ) - for inner_constraints in self.constraints: - if version.satisfies_all(inner_constraints): - return True - return False + return contains_version(version, self.constraints) contains = __contains__ - @classmethod - def join(cls, constraints): - """ - Return a string representing the provided ``constraints`` nested - sequence of VersionConstraint objects such that the outer sequence - VersionConstraints are joined with an "OR" e.g., a "vers" pipe "|" and - the inner sequences of VersionConstraint are each joined with an "AND" - e.g., a "vers" coma ",". - """ - cls.validate(constraints) - or_constraints = [] - for inner_constraints in constraints: - and_constraints = ",".join(str(c) for c in sorted(inner_constraints)) - or_constraints.append(and_constraints) - return "|".join(or_constraints) - def __eq__(self, other): return ( self.scheme == other.scheme @@ -239,9 +222,8 @@ def from_native(cls, string): """ Return a VersionRange built from a Rubygem version range ``string``. - Gem version semantics are different from semver: - there can be commonly more than 3 segments and - the operators are also different. + Gem version semantics are different from semver: there can be commonly + more than three segments and the operators are also different. """ gr = gem.GemRequirement.from_string(string).simplify() @@ -253,7 +235,7 @@ def from_native(cls, string): vc = VersionConstraint(comparator=op, version=version) constraints.append(vc) - return cls(constraints=[constraints]) + return cls(constraints=constraints) class DebianVersionRange(VersionRange): @@ -262,6 +244,21 @@ class DebianVersionRange(VersionRange): class PypiVersionRange(VersionRange): + """ + PyPI PEP 440 version range. + + For example: + >>> from univers.versions import PypiVersion + >>> constraints = [ + ... VersionConstraint(version=PypiVersion("2")), + ... VersionConstraint(comparator=">=", version=PypiVersion("3")), + ... VersionConstraint(comparator="<", version=PypiVersion("4")), + ... VersionConstraint(version=PypiVersion("5")), + ... ] + >>> range = PypiVersionRange(constraints=constraints) + >>> assert str(range) == "vers:pypi/2|>=3|<4|5" + """ + scheme = "pypi" version_class = versions.PypiVersion @@ -289,8 +286,7 @@ def from_native(cls, string): specifiers = SpecifierSet(string) # In PyPI all constraints apply - allof_constraints = [] - constraints = [allof_constraints] + constraints = [] for spec in specifiers: operator = spec.operator @@ -298,7 +294,7 @@ def from_native(cls, string): assert isinstance(version, cls.version_class) comparator = cls.vers_by_native_comparators[operator] constraint = VersionConstraint(comparator=comparator, version=version) - allof_constraints.append(constraint) + constraints.append(constraint) return cls(constraints=constraints) @@ -449,16 +445,16 @@ def from_native(cls, string): >>> assert str(result) == "vers:nginx/1.5.10", str(result) >>> result = NginxVersionRange.from_native("0.7.52-0.8.39") - >>> assert str(result) == "vers:nginx/<=0.8.39,>=0.7.52", str(result) + >>> assert str(result) == "vers:nginx/>=0.7.52|<=0.8.39", str(result) >>> result = NginxVersionRange.from_native("1.1.4-1.2.8, 1.3.9-1.4.0") - >>> assert str(result) == "vers:nginx/<=1.2.8,>=1.1.4|<=1.4.0,>=1.3.9", str(result) + >>> assert str(result) == "vers:nginx/>=1.1.4|<=1.2.8|>=1.3.9|<=1.4.0", str(result) >>> result = NginxVersionRange.from_native("0.8.40+, 0.7.66+") - >>> assert str(result) == "vers:nginx/<0.9.0,>=0.8.40|>=0.7.66", str(result) + >>> assert str(result) == "vers:nginx/>=0.7.66|>=0.8.40|<0.9.0", str(result) >>> result = NginxVersionRange.from_native("1.5.0+, 1.4.1+") - >>> assert str(result) == "vers:nginx/<1.5.0,>=1.4.1|>=1.5.0", str(result) + >>> assert str(result) == "vers:nginx/>=1.4.1|<1.5.0|>=1.5.0", str(result) >>> result = NginxVersionRange.from_native("all") >>> assert str(result) == "vers:nginx/*", str(result) @@ -470,25 +466,24 @@ def from_native(cls, string): """ cleaned = remove_spaces(string).lower() if cleaned == "all": - return cls(constraints=[[VersionConstraint(comparator="*")]]) + return cls(constraints=[VersionConstraint(comparator="*")]) - anyof_constraints = [] + constraints = [] - for allof_clauses in cleaned.split(","): + for clauses in cleaned.split(","): - if "-" in allof_clauses: + if "-" in clauses: # dash range - start, _, end = allof_clauses.partition("-") + start, _, end = clauses.partition("-") start_version = semantic_version.Version.coerce(start) end_version = semantic_version.Version.coerce(end) vstart = VersionConstraint(comparator=">=", version=start_version) vend = VersionConstraint(comparator="<=", version=end_version) - allof_constaints = [vstart, vend] - anyof_constraints.append(allof_constaints) + constraints.extend([vstart, vend]) - elif "+" in allof_clauses: + elif "+" in clauses: # suffixed version - vs = allof_clauses.rstrip("+") + vs = clauses.rstrip("+") version = semantic_version.Version.coerce(vs) is_stable = is_even(version.minor) @@ -498,23 +493,20 @@ def from_native(cls, string): end_version = start_version.next_minor() vstart = VersionConstraint(comparator=">=", version=start_version) vend = VersionConstraint(comparator="<", version=end_version) - allof_constaints = [vstart, vend] - anyof_constraints.append(allof_constaints) + constraints.extend([vstart, vend]) else: # mainline branch ranges are resolved to a singel constraint version = semantic_version.Version.coerce(vs) constraint = VersionConstraint(comparator=">=", version=version) - allof_constaints = [constraint] - anyof_constraints.append(allof_constaints) + constraints.append(constraint) else: # plain single version - version = semantic_version.Version.coerce(allof_clauses) + version = semantic_version.Version.coerce(clauses) constraint = VersionConstraint(comparator="=", version=version) - allof_constaints = [constraint] - anyof_constraints.append(allof_constaints) + constraints.append(constraint) - return cls(constraints=anyof_constraints) + return cls(constraints=constraints) def is_even(s): diff --git a/src/univers/versions.py b/src/univers/versions.py index cdfbe561..1ed3eaed 100644 --- a/src/univers/versions.py +++ b/src/univers/versions.py @@ -40,7 +40,7 @@ class Version: Base version mixin to subclass for each version syntax implementation. Each version subclass is: - - comparable and orderable e.g., implement functools.total_ordering + - comparable and orderable e.g., such as implementing functools.total_ordering - immutable and hashable """ @@ -51,7 +51,7 @@ class Version: # lowercased. Any leading v is removed too. normalized_string = attr.ib(type=str, default=None, repr=False) - # a comparable version object constructed from the version string + # a comparable scheme-specific version object constructed from the version string value = attr.ib(default=None, repr=False) def __attrs_post_init__(self): @@ -59,10 +59,10 @@ def __attrs_post_init__(self): if not self.is_valid(normalized_string): raise InvalidVersion(f"{self.string!r} is not a valid {self.__class__!r}") - # See https://www.attrs.org/en/stable/init.html?#post-init - # we use a post init on frozen objects + # Set the normalized string as default value - # use the normalized string as default value + # Notes: setattr is used because this is an immutable frozen instance. + # See https://www.attrs.org/en/stable/init.html?#post-init object.__setattr__(self, "normalized_string", normalized_string) value = self.build_value(normalized_string) object.__setattr__(self, "value", value) @@ -102,21 +102,6 @@ def satisfies(self, constraint): """ return self in constraint - def satisfies_all(self, constraints, explain=False): - """ - Return True is this version satifies all the ``constraints`` list of - VersionConstraint. - If ``explain`` is True, prints de debug explanation. - """ - if explain: - print() - for constraint in constraints: - if self not in constraint: - print(f"{self!r} not in constraint : {constraint!r}") - else: - print(f"{self!r} in constraint : {constraint!r}") - return all(self in constraint for constraint in constraints) - def __str__(self): return str(self.value) diff --git a/tests/test_version_range.py b/tests/test_version_range.py index 4c7b92dc..10c2364f 100644 --- a/tests/test_version_range.py +++ b/tests/test_version_range.py @@ -8,20 +8,27 @@ from univers.version_constraint import VersionConstraint from univers.version_range import GemVersionRange +from univers.version_range import PypiVersionRange from univers.version_range import VersionRange from univers.versions import PypiVersion from univers.versions import RubygemsVersion class TestVersionRange(TestCase): + def test_VersionRange_afrom_string(self): + version_range = VersionRange.from_string("vers:pypi/>0.0.2") + assert version_range == PypiVersionRange( + constraints=[VersionConstraint(comparator=">", version=PypiVersion(string="0.0.2"))] + ) + def test_VersionRange_to_string(self): - vers = "vers:pypi/0.0.2,0.0.6,>=0.0.0,0.0.1,0.0.4,0.0.5,0.0.3" + vers = "vers:pypi/0.0.2|0.0.6|>=0.0.0|0.0.1|0.0.4|0.0.5|0.0.3" version_range = VersionRange.from_string(vers) # note the sorting taking place - assert str(version_range) == "vers:pypi/0.0.1,0.0.2,0.0.3,0.0.4,0.0.5,0.0.6,>=0.0.0" + assert str(version_range) == "vers:pypi/>=0.0.0|0.0.1|0.0.2|0.0.3|0.0.4|0.0.5|0.0.6" def test_VersionRange_not_contains(self): - vers = "vers:pypi/0.0.2,0.0.6,>=0.0.0,0.0.1,0.0.4,0.0.5,0.0.3" + vers = "vers:pypi/0.0.2|0.0.6|>=0.0.0|0.0.1|0.0.4|0.0.5|0.0.3" version_range = VersionRange.from_string(vers) assert not version_range.contains(PypiVersion("2.0.3")) @@ -30,32 +37,54 @@ def test_VersionRange_contains(self): assert PypiVersion("0.0.3") in version_range def test_VersionRange_from_string_pypi(self): - vers = "vers:pypi/0.0.2,0.0.6,0.0.0,0.0.1,0.0.4,0.0.5,0.0.3" + vers = "vers:pypi/0.0.2|0.0.6|0.0.0|0.0.1|0.0.4|0.0.5|0.0.3" version_range = VersionRange.from_string(vers) assert version_range.scheme == "pypi" # note the sorting taking place expected = [ - [ - VersionConstraint(comparator="=", version=PypiVersion(string="0.0.0")), - VersionConstraint(comparator="=", version=PypiVersion(string="0.0.1")), - VersionConstraint(comparator="=", version=PypiVersion(string="0.0.2")), - VersionConstraint(comparator="=", version=PypiVersion(string="0.0.3")), - VersionConstraint(comparator="=", version=PypiVersion(string="0.0.4")), - VersionConstraint(comparator="=", version=PypiVersion(string="0.0.5")), - VersionConstraint(comparator="=", version=PypiVersion(string="0.0.6")), - ] + VersionConstraint(comparator="=", version=PypiVersion(string="0.0.0")), + VersionConstraint(comparator="=", version=PypiVersion(string="0.0.1")), + VersionConstraint(comparator="=", version=PypiVersion(string="0.0.2")), + VersionConstraint(comparator="=", version=PypiVersion(string="0.0.3")), + VersionConstraint(comparator="=", version=PypiVersion(string="0.0.4")), + VersionConstraint(comparator="=", version=PypiVersion(string="0.0.5")), + VersionConstraint(comparator="=", version=PypiVersion(string="0.0.6")), ] assert version_range.constraints == expected # note the sorting taking place - assert str(version_range) == "vers:pypi/0.0.0,0.0.1,0.0.2,0.0.3,0.0.4,0.0.5,0.0.6" + assert str(version_range) == "vers:pypi/0.0.0|0.0.1|0.0.2|0.0.3|0.0.4|0.0.5|0.0.6" + + version_range1 = VersionRange.from_string(vers, dedupe=False, validate=True) + assert version_range1.constraints == expected + + version_range2 = VersionRange.from_string(vers, dedupe=True, validate=False) + assert version_range2.constraints == expected + + version_range3 = VersionRange.from_string(vers, dedupe=True, validate=True) + assert version_range3.constraints == expected + + def test_VersionRange_from_string_pypi_complex_dedupe(self): + vers = "vers:pypi/0.0.2|>=0.0.6|>0.0.0|>=0.0.1|0.0.4|<0.0.5|<0.0.3" + version_range = VersionRange.from_string(vers, dedupe=True) + assert str(version_range) == "vers:pypi/>0.0.0|<0.0.5|>=0.0.6" + try: + version_range = VersionRange.from_string(vers, validate=True) + raise Exception(f"Exception not raised: {vers}") + except ValueError: + pass + version_range = VersionRange.from_string(vers, validate=True, dedupe=True) + assert str(version_range) == "vers:pypi/>0.0.0|<0.0.5|>=0.0.6" + + def test_VersionRange_from_string_pypi_complex_dedupe_and_validate(self): + vers = "vers:pypi/0.0.2|>=0.0.6|>0.0.0|>=0.0.1|0.0.4|<0.0.5|0.0.3" + version_range = VersionRange.from_string(vers, dedupe=True) + assert str(version_range) == "vers:pypi/>0.0.0|<0.0.5|>=0.0.6" def test_GemVersionRange_from_native_range_with_pessimistic_operator(self): gem_range = "~>2.0.8" version_range = GemVersionRange.from_native(gem_range) - assert version_range.to_string() == "vers:gem/<2.1,>=2.0.8" + assert version_range.to_string() == "vers:gem/>=2.0.8|<2.1" assert version_range.constraints == [ - [ - VersionConstraint(comparator="<", version=RubygemsVersion(string="2.1")), - VersionConstraint(comparator=">=", version=RubygemsVersion(string="2.0.8")), - ], + VersionConstraint(comparator=">=", version=RubygemsVersion(string="2.0.8")), + VersionConstraint(comparator="<", version=RubygemsVersion(string="2.1")), ] From 323cb8987b3365626e0062c00b0db58357662b73 Mon Sep 17 00:00:00 2001 From: Philippe Ombredanne Date: Thu, 16 Dec 2021 12:06:59 +0100 Subject: [PATCH 698/707] Use isinstance check. order operators This is a minor refactoring, mostly cosmetic. Signed-off-by: Philippe Ombredanne --- src/univers/debian.py | 37 +++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/src/univers/debian.py b/src/univers/debian.py index 4e243cae..f81675e2 100644 --- a/src/univers/debian.py +++ b/src/univers/debian.py @@ -96,30 +96,32 @@ def __hash__(self): return hash(self.tuple()) def __eq__(self, other): - return type(self) is type(other) and self.tuple() == other.tuple() + if not isinstance(other, self.__class__): + return NotImplemented + return self.tuple() == other.tuple() def __ne__(self, other): return not self.__eq__(other) def __lt__(self, other): - if type(self) is type(other): - return eval_constraint(self, "<<", other) - return NotImplemented + if not isinstance(other, self.__class__): + return NotImplemented + return eval_constraint(self, "<<", other) def __le__(self, other): - if type(self) is type(other): - return eval_constraint(self, "<=", other) - return NotImplemented + if not isinstance(other, self.__class__): + return NotImplemented + return eval_constraint(self, "<=", other) def __gt__(self, other): - if type(self) is type(other): - return eval_constraint(self, ">>", other) - return NotImplemented + if not isinstance(other, self.__class__): + return NotImplemented + return eval_constraint(self, ">>", other) def __ge__(self, other): - if type(self) is type(other): - return eval_constraint(self, ">=", other) - return NotImplemented + if not isinstance(other, self.__class__): + return NotImplemented + return eval_constraint(self, ">=", other) @classmethod def from_string(cls, version): @@ -187,15 +189,14 @@ def eval_constraint(version1, operator, version2): result = compare_versions(version1, version2) # See https://www.debian.org/doc/debian-policy/ch-relationships.html#syntax-of-relationship-fields operators = { + "<<": operator_module.lt, "<=": operator_module.le, - # legacy for compat - "<": operator_module.le, + "=": operator_module.eq, ">=": operator_module.ge, + ">>": operator_module.gt, # legacy for compat + "<": operator_module.le, ">": operator_module.ge, - "<<": operator_module.lt, - ">>": operator_module.gt, - "=": operator_module.eq, } try: From f4815a315e998ab282ef975e9887065399bd88f3 Mon Sep 17 00:00:00 2001 From: Philippe Ombredanne Date: Fri, 17 Dec 2021 14:50:10 +0100 Subject: [PATCH 699/707] Expand and correct test expectations Signed-off-by: Philippe Ombredanne --- tests/test_version_range.py | 68 +++++++++++++++++++++++++++++++++++-- 1 file changed, 65 insertions(+), 3 deletions(-) diff --git a/tests/test_version_range.py b/tests/test_version_range.py index 10c2364f..92e00be8 100644 --- a/tests/test_version_range.py +++ b/tests/test_version_range.py @@ -64,7 +64,7 @@ def test_VersionRange_from_string_pypi(self): assert version_range3.constraints == expected def test_VersionRange_from_string_pypi_complex_dedupe(self): - vers = "vers:pypi/0.0.2|>=0.0.6|>0.0.0|>=0.0.1|0.0.4|<0.0.5|<0.0.3" + vers = "vers:pypi/>0.0.0|>=0.0.1|0.0.2|<0.0.3|0.0.4|<0.0.5|>=0.0.6" version_range = VersionRange.from_string(vers, dedupe=True) assert str(version_range) == "vers:pypi/>0.0.0|<0.0.5|>=0.0.6" try: @@ -76,9 +76,71 @@ def test_VersionRange_from_string_pypi_complex_dedupe(self): assert str(version_range) == "vers:pypi/>0.0.0|<0.0.5|>=0.0.6" def test_VersionRange_from_string_pypi_complex_dedupe_and_validate(self): - vers = "vers:pypi/0.0.2|>=0.0.6|>0.0.0|>=0.0.1|0.0.4|<0.0.5|0.0.3" + vers = "vers:pypi/>0.0.0|>=0.0.1|0.0.2|0.0.3|0.0.4|<0.0.5|>=0.0.6|!=0.8" version_range = VersionRange.from_string(vers, dedupe=True) - assert str(version_range) == "vers:pypi/>0.0.0|<0.0.5|>=0.0.6" + assert str(version_range) == "vers:pypi/>0.0.0|<0.0.5|>=0.0.6|!=0.8" + version_range = VersionRange.from_string(vers, dedupe=True, validate=True) + + def test_VersionRange_from_string_pypi_complex_dedupe2(self): + vers = ( + "vers:pypi/>0.0.0|>=0.0.1|>=0.0.1|0.0.2|0.0.3|0.0.4|<0.0.5|<=0.0.6|!=0.7|8.0|>12|<15.3" + ) + version_range = VersionRange.from_string(vers, dedupe=True) + assert str(version_range) == "vers:pypi/>0.0.0|<=0.0.6|!=0.7|8.0|>12|<15.3" + + def test_VersionRange_from_string_pypi_simple_cases(self): + vers = "vers:pypi/>0.0.1" + version_range = VersionRange.from_string(vers, dedupe=True, validate=True) + assert str(version_range) == vers + + vers = "vers:pypi/>=0.0.1" + version_range = VersionRange.from_string(vers, dedupe=True, validate=True) + assert str(version_range) == vers + + vers = "vers:pypi/<0.0.1" + version_range = VersionRange.from_string(vers, dedupe=True, validate=True) + assert str(version_range) == vers + + vers = "vers:pypi/<=0.0.1" + version_range = VersionRange.from_string(vers, dedupe=True, validate=True) + assert str(version_range) == vers + + vers = "vers:pypi/0.0.1" + version_range = VersionRange.from_string(vers, dedupe=True, validate=True) + assert str(version_range) == vers + + vers = "vers:pypi/!=0.0.1" + version_range = VersionRange.from_string(vers, dedupe=True, validate=True) + assert str(version_range) == vers + + vers = "vers:pypi/*" + version_range = VersionRange.from_string(vers, dedupe=True, validate=True) + assert str(version_range) == vers + + def test_VersionRange_from_string_pypi_two_cases(self): + vers = "vers:pypi/>0.0.1|<0.1" + version_range = VersionRange.from_string(vers, dedupe=True, validate=True) + assert str(version_range) == vers + + vers = "vers:pypi/>=0.0.1|<0.1" + version_range = VersionRange.from_string(vers, dedupe=True, validate=True) + assert str(version_range) == vers + + vers = "vers:pypi/<0.0.1|>0.1" + version_range = VersionRange.from_string(vers, dedupe=True, validate=True) + assert str(version_range) == vers + + vers = "vers:pypi/<=0.0.1|>0.1" + version_range = VersionRange.from_string(vers, dedupe=True, validate=True) + assert str(version_range) == vers + + vers = "vers:pypi/0.0.1|>0.1" + version_range = VersionRange.from_string(vers, dedupe=True, validate=True) + assert str(version_range) == vers + + vers = "vers:pypi/!=0.0.1|>0.1" + version_range = VersionRange.from_string(vers, dedupe=True, validate=True) + assert str(version_range) == vers def test_GemVersionRange_from_native_range_with_pessimistic_operator(self): gem_range = "~>2.0.8" From 7d59d048162f45c1fd8c0f1db83d57268eeadb89 Mon Sep 17 00:00:00 2001 From: Philippe Ombredanne Date: Sat, 18 Dec 2021 16:58:09 +0100 Subject: [PATCH 700/707] Make VersionConstraint.version None by default In partucular a star range has a None version and not an empty string Signed-off-by: Philippe Ombredanne --- src/univers/version_constraint.py | 7 +++++-- src/univers/version_range.py | 6 ++++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/univers/version_constraint.py b/src/univers/version_constraint.py index b945e15e..e17314ae 100644 --- a/src/univers/version_constraint.py +++ b/src/univers/version_constraint.py @@ -68,7 +68,7 @@ class VersionConstraint: comparator = attr.ib(type=str, default="=") # a Version subclass instance or None - version = attr.ib(type=Version, default="") + version = attr.ib(type=Version, default=None) # a function for the comparator comp_operator = attr.ib(default=None, repr=False) @@ -134,7 +134,10 @@ def from_string(cls, string, version_class): if not version and comparator != "*": raise ValueError("Empty version") - version = version_class(version) + if comparator == "*": + version = None + else: + version = version_class(version) return cls(comparator, version) @staticmethod diff --git a/src/univers/version_range.py b/src/univers/version_range.py index d6fc27c4..eb803484 100644 --- a/src/univers/version_range.py +++ b/src/univers/version_range.py @@ -82,6 +82,8 @@ def from_string(cls, vers, dedupe=False, validate=False): f"{vers!r} has an unknown versioning scheme: " f"{versioning_scheme!r}.", ) + version_class = range_class.version_class + constraints = constraints.strip() if not constraints: raise ValueError(f"{vers!r} specifies no version range constraints.") @@ -89,7 +91,7 @@ def from_string(cls, vers, dedupe=False, validate=False): if constraints.startswith("*"): if constraints != "*": raise ValueError(f"{vers!r} contains an invalid '*' constraint.") - return range_class([VersionConstraint.from_string("*")]) + return range_class([VersionConstraint.from_string(string="*", version_class=None)]) parsed_constraints = [] @@ -97,7 +99,7 @@ def from_string(cls, vers, dedupe=False, validate=False): for const in constraints.split("|"): constraint = VersionConstraint.from_string( string=const, - version_class=range_class.version_class, + version_class=version_class, ) parsed_constraints.append(constraint) From 3846509e47618e338a76f8b72949f60d1ae7aad7 Mon Sep 17 00:00:00 2001 From: Philippe Ombredanne Date: Sat, 18 Dec 2021 17:04:24 +0100 Subject: [PATCH 701/707] Do not reuse built-ins as variable name Signed-off-by: Philippe Ombredanne --- tests/test_maven_version.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/test_maven_version.py b/tests/test_maven_version.py index 388fe416..5cfc6912 100644 --- a/tests/test_maven_version.py +++ b/tests/test_maven_version.py @@ -620,9 +620,9 @@ def test_compare(self): assert 1 < vr1 def test_str(self): - for input in ("[1.0,2.0]", "1.0"): - actual = str(VersionRange(input)) - assert input == actual, "VersionRange(%s) == %s, wanted %s" % (input, actual, input) + for inp in ("[1.0,2.0]", "1.0"): + actual = str(VersionRange(inp)) + assert inp == actual, "VersionRange(%s) == %s, wanted %s" % (inp, actual, inp) def test_fromversion(self): v = Version("1.0") From ac07db5e200834b95e2600e6b6c6ac58a7c8726a Mon Sep 17 00:00:00 2001 From: Philippe Ombredanne Date: Sat, 18 Dec 2021 17:04:50 +0100 Subject: [PATCH 702/707] Implement vers simplify spec Use simplify, not dedupe as a function name and implement latest spec. Signed-off-by: Philippe Ombredanne --- src/univers/version_constraint.py | 110 +++++++++++++++++------------- src/univers/version_range.py | 6 +- tests/test_version_range.py | 48 ++++++------- 3 files changed, 88 insertions(+), 76 deletions(-) diff --git a/src/univers/version_constraint.py b/src/univers/version_constraint.py index e17314ae..aebbca29 100644 --- a/src/univers/version_constraint.py +++ b/src/univers/version_constraint.py @@ -238,17 +238,18 @@ def validate(cls, constraints): return validate_comparators(constraints) @classmethod - def dedupe(cls, constraints): + def simplify(cls, constraints): """ - Return a new ``constraints`` list with duplicated constraints removed. - This includes removing exact duplicates adn redundant constraints. + Return a new simplified ``constraints`` list with duplicated constraints + removed. This includes removing exact duplicates adn redundant + constraints. """ - constraints = deduplicate_exact(constraints) - constraints = deduplicate_comparators(constraints) + constraints = deduplicate(constraints) + constraints = simplify_constraints(constraints) return constraints -def deduplicate_exact(constraints): +def deduplicate(constraints): """ Return a new ``constraints`` list with exact duplicated constraints removed. """ @@ -299,9 +300,10 @@ def validate_comparators(constraints): if cur.comparator == "=" and nxt.comparator not in ("=", ">", ">=") ] if invalid_equal: + c = "|".join(map(str, constraints)) + i = ", ".join(f"{x}|{y}" for x, y in invalid_equal) raise ValueError( - f"Invalid {constraints!r}\n: where \n{invalid_equal!r} " - "cannot contain an equal = followed by either < or <=" + f"Invalid {c!r}: where {i!r} " "cannot contain an equal = followed by either < or <=" ) # discard = that have been validated above @@ -326,66 +328,76 @@ def validate_comparators(constraints): return True -def deduplicate_comparators(constraints): +def simplify_constraints(constraints): """ Return a list of VersionConstraint given a ``constraints`` list by discarding redundant constraints according to ``vers`` rules. """ - if len(constraints) == 1 or any(c.comparator == "*" for c in constraints): - return list(constraints) + # Start from a list of constraints of comparator and version, sorted by version + # and where each version occurs only once in any constraint. - constraints = sorted(constraints) + # If the constraints list contains a single constraint (star, equal or anything) + # return this list and simplification is finished. + if len(constraints) < 2: + return constraints - inequal_constraints = [c for c in constraints if c.comparator == "!="] + # Split the constraints list in two sub lists: + # a list of "unequal constraints" where the comparator is "!=" + # a remainder list of "constraints" where the comparator is not "!=" + unequal_constraints = [c for c in constraints if c.comparator == "!="] constraints = [c for c in constraints if c.comparator != "!="] + # If the remainder list of "constraints" is empty, return the "unequal constraints" + # list and de-duplication is finished. if not constraints: - return sorted(inequal_constraints) - - # iterate as long as constraints length diminishes with each ieration - cycle = 1 - while True: - starting_length = len(constraints) - constraints = list(dedup(constraints)) - ending_length = len(constraints) - if ending_length == 1 or ending_length == starting_length: - # no filtering happened in this iteration, we are done - break - cycle += 1 + return unequal_constraints - return sorted(inequal_constraints + constraints) + # Iterate over the current and next contiguous constraints of this list: + i = 0 + j = 0 + while i < len(constraints) - 1: + j = i + 1 -def dedup(constraints): - """ - Yield filtered constraints, discarding redundant ones according to ``vers``. - """ - skip = False - for cur, nxt in pairwise(constraints): + cur = constraints[i] + nxt = constraints[j] cur_comp = cur.comparator nxt_comp = nxt.comparator - if skip: - skip = False - continue + # If current comparator is ">" or ">=" and next comparator is "=", ">" or ">=", + if cur_comp in (">", ">=") and nxt_comp in ("=", ">", ">="): + # discard next constraint + constraints.pop(j) + + # If current comparator is "=", "<" or "<=" and next comparator is <" or <=", if cur_comp in ("=", "<", "<=") and nxt_comp in ("<", "<="): - # keep only next (drop current) - skip = True - yield nxt - continue + # discard current constraint + constraints.pop(i) + # Previous constraint becomes current if if exists. + if i: + i -= 1 - if cur_comp in (">", ">=") and nxt_comp in ("=", ">", ">="): - # keep only current (drop next) - skip = True - yield cur - continue + # If there is a previous constraint: + if i: + + prv = constraints[i - 1] + prv_comp = prv.comparator + + # If previous comparator is ">" or ">=" and current comparator is "=", ">" or ">=", + if prv_comp in (">", ">=") and cur_comp in ("=", ">", ">="): + # discard current constraint + constraints.pop(i) + + # If previous comparator is "=", "<" or "<=" and current comparator is <" or <=", + if prv_comp in ("=", "<", "<=") and cur_comp in ("<", "<="): + # discard previous constraint. + constraints.pop(i - 1) - # keep cur - skip = False - yield cur + i += 1 - # yield last next - yield nxt + # Concatenate the "unequal constraints" list and the filtered "constraints" list + # Sort by version and return. + return sorted(set(unequal_constraints + constraints)) def contains_version(version, constraints): diff --git a/src/univers/version_range.py b/src/univers/version_range.py index eb803484..5e75ac09 100644 --- a/src/univers/version_range.py +++ b/src/univers/version_range.py @@ -61,7 +61,7 @@ def to_native(self): return NotImplementedError @classmethod - def from_string(cls, vers, dedupe=False, validate=False): + def from_string(cls, vers, simplify=False, validate=False): """ Return a VersionRange built from a ``vers`` version range spec string, such as "vers:npm/1.2.3,>=2.0.0" @@ -104,8 +104,8 @@ def from_string(cls, vers, dedupe=False, validate=False): parsed_constraints.append(constraint) parsed_constraints.sort() - if dedupe: - parsed_constraints = VersionConstraint.dedupe(parsed_constraints) + if simplify: + parsed_constraints = VersionConstraint.simplify(parsed_constraints) if validate: VersionConstraint.validate(parsed_constraints) diff --git a/tests/test_version_range.py b/tests/test_version_range.py index 92e00be8..e5ad4328 100644 --- a/tests/test_version_range.py +++ b/tests/test_version_range.py @@ -54,92 +54,92 @@ def test_VersionRange_from_string_pypi(self): # note the sorting taking place assert str(version_range) == "vers:pypi/0.0.0|0.0.1|0.0.2|0.0.3|0.0.4|0.0.5|0.0.6" - version_range1 = VersionRange.from_string(vers, dedupe=False, validate=True) + version_range1 = VersionRange.from_string(vers, simplify=False, validate=True) assert version_range1.constraints == expected - version_range2 = VersionRange.from_string(vers, dedupe=True, validate=False) + version_range2 = VersionRange.from_string(vers, simplify=True, validate=False) assert version_range2.constraints == expected - version_range3 = VersionRange.from_string(vers, dedupe=True, validate=True) + version_range3 = VersionRange.from_string(vers, simplify=True, validate=True) assert version_range3.constraints == expected - def test_VersionRange_from_string_pypi_complex_dedupe(self): + def test_VersionRange_from_string_pypi_complex_simplify(self): vers = "vers:pypi/>0.0.0|>=0.0.1|0.0.2|<0.0.3|0.0.4|<0.0.5|>=0.0.6" - version_range = VersionRange.from_string(vers, dedupe=True) + version_range = VersionRange.from_string(vers, simplify=True) assert str(version_range) == "vers:pypi/>0.0.0|<0.0.5|>=0.0.6" try: version_range = VersionRange.from_string(vers, validate=True) raise Exception(f"Exception not raised: {vers}") except ValueError: pass - version_range = VersionRange.from_string(vers, validate=True, dedupe=True) + version_range = VersionRange.from_string(vers, validate=True, simplify=True) assert str(version_range) == "vers:pypi/>0.0.0|<0.0.5|>=0.0.6" - def test_VersionRange_from_string_pypi_complex_dedupe_and_validate(self): + def test_VersionRange_from_string_pypi_complex_simplify_and_validate(self): vers = "vers:pypi/>0.0.0|>=0.0.1|0.0.2|0.0.3|0.0.4|<0.0.5|>=0.0.6|!=0.8" - version_range = VersionRange.from_string(vers, dedupe=True) + version_range = VersionRange.from_string(vers, simplify=True) assert str(version_range) == "vers:pypi/>0.0.0|<0.0.5|>=0.0.6|!=0.8" - version_range = VersionRange.from_string(vers, dedupe=True, validate=True) + version_range = VersionRange.from_string(vers, simplify=True, validate=True) - def test_VersionRange_from_string_pypi_complex_dedupe2(self): + def test_VersionRange_from_string_pypi_complex_simplify2(self): vers = ( "vers:pypi/>0.0.0|>=0.0.1|>=0.0.1|0.0.2|0.0.3|0.0.4|<0.0.5|<=0.0.6|!=0.7|8.0|>12|<15.3" ) - version_range = VersionRange.from_string(vers, dedupe=True) + version_range = VersionRange.from_string(vers, simplify=True) assert str(version_range) == "vers:pypi/>0.0.0|<=0.0.6|!=0.7|8.0|>12|<15.3" def test_VersionRange_from_string_pypi_simple_cases(self): vers = "vers:pypi/>0.0.1" - version_range = VersionRange.from_string(vers, dedupe=True, validate=True) + version_range = VersionRange.from_string(vers, simplify=True, validate=True) assert str(version_range) == vers vers = "vers:pypi/>=0.0.1" - version_range = VersionRange.from_string(vers, dedupe=True, validate=True) + version_range = VersionRange.from_string(vers, simplify=True, validate=True) assert str(version_range) == vers vers = "vers:pypi/<0.0.1" - version_range = VersionRange.from_string(vers, dedupe=True, validate=True) + version_range = VersionRange.from_string(vers, simplify=True, validate=True) assert str(version_range) == vers vers = "vers:pypi/<=0.0.1" - version_range = VersionRange.from_string(vers, dedupe=True, validate=True) + version_range = VersionRange.from_string(vers, simplify=True, validate=True) assert str(version_range) == vers vers = "vers:pypi/0.0.1" - version_range = VersionRange.from_string(vers, dedupe=True, validate=True) + version_range = VersionRange.from_string(vers, simplify=True, validate=True) assert str(version_range) == vers vers = "vers:pypi/!=0.0.1" - version_range = VersionRange.from_string(vers, dedupe=True, validate=True) + version_range = VersionRange.from_string(vers, simplify=True, validate=True) assert str(version_range) == vers vers = "vers:pypi/*" - version_range = VersionRange.from_string(vers, dedupe=True, validate=True) + version_range = VersionRange.from_string(vers, simplify=True, validate=True) assert str(version_range) == vers def test_VersionRange_from_string_pypi_two_cases(self): vers = "vers:pypi/>0.0.1|<0.1" - version_range = VersionRange.from_string(vers, dedupe=True, validate=True) + version_range = VersionRange.from_string(vers, simplify=True, validate=True) assert str(version_range) == vers vers = "vers:pypi/>=0.0.1|<0.1" - version_range = VersionRange.from_string(vers, dedupe=True, validate=True) + version_range = VersionRange.from_string(vers, simplify=True, validate=True) assert str(version_range) == vers vers = "vers:pypi/<0.0.1|>0.1" - version_range = VersionRange.from_string(vers, dedupe=True, validate=True) + version_range = VersionRange.from_string(vers, simplify=True, validate=True) assert str(version_range) == vers vers = "vers:pypi/<=0.0.1|>0.1" - version_range = VersionRange.from_string(vers, dedupe=True, validate=True) + version_range = VersionRange.from_string(vers, simplify=True, validate=True) assert str(version_range) == vers vers = "vers:pypi/0.0.1|>0.1" - version_range = VersionRange.from_string(vers, dedupe=True, validate=True) + version_range = VersionRange.from_string(vers, simplify=True, validate=True) assert str(version_range) == vers vers = "vers:pypi/!=0.0.1|>0.1" - version_range = VersionRange.from_string(vers, dedupe=True, validate=True) + version_range = VersionRange.from_string(vers, simplify=True, validate=True) assert str(version_range) == vers def test_GemVersionRange_from_native_range_with_pessimistic_operator(self): From 98a94d6eb1c5140d9979c7c8d733f16fa84c8069 Mon Sep 17 00:00:00 2001 From: Philippe Ombredanne Date: Sun, 19 Dec 2021 07:46:22 +0100 Subject: [PATCH 703/707] Align Debian versions with actual Debian version and release can have trailing punctuations. We were arbitrarily disabling this. Signed-off-by: Philippe Ombredanne --- src/univers/debian.py | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/univers/debian.py b/src/univers/debian.py index f81675e2..25e791e9 100644 --- a/src/univers/debian.py +++ b/src/univers/debian.py @@ -69,6 +69,13 @@ class Version(object): >>> print([str(v) for v in sorted(Version.from_string(s) for s in unsorted)]) ['0.1', '0.5', '1.0', '2.0', '3.0', '1:0.4', '2:0.3'] + We also accept trailing punctuations in the version and release: + + >>> v = "2:4.13.1-0ubuntu0.16.04.1.1~" + >>> assert str(Version.from_string(v)) == v + >>> v = "2:4.13.1~" + >>> assert str(Version.from_string(v)) == v + This example uses 'epoch' numbers (the numbers before the colons) to demonstrate that this version sorting order is different from regular sorting and 'natural order sorting'. @@ -165,12 +172,10 @@ def tuple(self): r"(" # upstream can contain only alphanumerics and the characters . + - # ~ (full stop, plus, hyphen, tilde) - # we are adding the extra check that it must end with alphanum - r"[A-Za-z0-9\.\+\-\~]*[A-Za-z0-9]" + r"[A-Za-z0-9\.\+\~\-]+" r"|" - # If there is no debian_revision then hyphens are not allowed. - # we are adding the extra check that it must end with alphanum - r"[A-Za-z0-9\.\+\~]*[A-Za-z0-9]-[A-Za-z0-9\+\.\~]*[A-Za-z0-9]" + # If there is no debian_revision then hyphens are not allowed in version. + r"[A-Za-z0-9\.\+\~]+-[A-Za-z0-9\+\.\~]+" r")?" r"$" ).match @@ -195,8 +200,8 @@ def eval_constraint(version1, operator, version2): ">=": operator_module.ge, ">>": operator_module.gt, # legacy for compat - "<": operator_module.le, - ">": operator_module.ge, + "<": operator_module.lt, + ">": operator_module.gt, } try: From 0811ffb2c0f32c43a300b4b1cc2eb0d545e213fc Mon Sep 17 00:00:00 2001 From: Philippe Ombredanne Date: Sun, 19 Dec 2021 07:46:46 +0100 Subject: [PATCH 704/707] Add support for Debian version ranges Signed-off-by: Philippe Ombredanne --- src/univers/version_range.py | 101 +++++++++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) diff --git a/src/univers/version_range.py b/src/univers/version_range.py index 5e75ac09..9f0363f5 100644 --- a/src/univers/version_range.py +++ b/src/univers/version_range.py @@ -241,8 +241,109 @@ def from_native(cls, string): class DebianVersionRange(VersionRange): + """ + Debian version ranges as seen in Debian manual for relationships: + https://www.debian.org/doc/debian-policy/ch-relationships.html + + These are for defined one expression at a time. Multiple expressions each + com with a package name. Therefore there is no "range string" per se, instead + there is always a list of version constraints as an input. For instance:: + + libc6 (>> 2.23), libc6 (<< 2.24)' + + Therefore native conversions are different. + """ + scheme = "deb" version_class = versions.DebianVersion + vers_by_native_comparators = { + "=": "=", + "<=": "<=", + ">=": ">=", + "<<": "<", + ">>": ">", + # legacy + "<": "<", + ">": ">", + } + + @classmethod + def split(cls, string): + """ + Return a tuple of (vers comparator, version) strings given a Debian + version relationship ``string`` such as ">>2.3" or "(<< 2.3)". Raise a + ValueError for unknown comparators. + + For example:: + >>> assert DebianVersionRange.split("=2.3") == ("=", "2.3",) + >>> assert DebianVersionRange.split(" < = 2 . 3 ") == ("<=", "2.3",) + >>> assert DebianVersionRange.split("(>=2.3)") == (">=", "2.3",) + >>> assert DebianVersionRange.split(">=2.3") == (">=", "2.3",) + >>> assert DebianVersionRange.split("<=2.3") == ("<=", "2.3",) + >>> assert DebianVersionRange.split("<<2.3") == ("<<", "2.3",) + >>> assert DebianVersionRange.split(">>2.3") == (">>", "2.3",) + >>> assert DebianVersionRange.split(">2.3") == (">", "2.3",) + >>> assert DebianVersionRange.split("<2.3") == ("<", "2.3",) + >>> try: + ... DebianVersionRange.split("~2.3") + ... raise Exception("ValueError should be raised") + ... except ValueError: + ... pass + """ + constraint_string = remove_spaces(string).strip(")(") + + for comparator in cls.vers_by_native_comparators: + if constraint_string.startswith(comparator): + version = constraint_string.lstrip(comparator) + return comparator, version + + raise ValueError(f"Unknown Debian version relationship: {string}") + + @classmethod + def from_native(cls, relationships): + """ + Return a VersionRange built from a ``relationships`` list of Debian + version relationship strings or a single relationship string. + For example:: + + >>> dvr = DebianVersionRange.from_native("= 3.5.6") + >>> assert str(dvr) == "vers:deb/3.5.6" + + >>> rels = ["(>= 2.8.16)"] + >>> dvr = DebianVersionRange.from_native(rels) + >>> assert str(dvr) == "vers:deb/>=2.8.16" + + >>> rels = [">= 1:1.1.4", "(>= 2.8.16)", "<= 2.8.16-z"] + >>> dvr = DebianVersionRange.from_native(rels) + >>> assert str(dvr) == "vers:deb/>=2.8.16|<=2.8.16-z|>=1:1.1.4" + + >>> rels = ["(>= 2:4.13.1)", "(<= 2:4.13.1-0ubuntu0.16.04.1.1~)"] + >>> dvr = DebianVersionRange.from_native(rels) + >>> assert str(dvr) == "vers:deb/>=2:4.13.1|<=2:4.13.1-0ubuntu0.16.04.1.1~" + + >>> rels = ["= 5.0", "(>> 2.23)", "< 2.24"] + >>> dvr = DebianVersionRange.from_native(rels) + >>> assert str(dvr) == "vers:deb/>2.23|<2.24|5.0" + + >>> rels = ["(<< 3:1.1.25~)", "(>> 2:1.1.24~)"] + >>> dvr = DebianVersionRange.from_native(rels) + >>> assert str(dvr) == "vers:deb/>2:1.1.24~|<3:1.1.25~" + """ + constraints = [] + + if isinstance(relationships, str): + relationships = [relationships] + + for rel in relationships: + comparator, version = cls.split(rel) + comparator = cls.vers_by_native_comparators[comparator] + version = cls.version_class(version) + constraint = VersionConstraint(comparator=comparator, version=version) + constraints.append(constraint) + + constraints.sort() + + return cls(constraints=constraints) class PypiVersionRange(VersionRange): From 668a5d7d845f0396b928e128161a1413528f9e65 Mon Sep 17 00:00:00 2001 From: Philippe Ombredanne Date: Sun, 19 Dec 2021 22:29:43 +0100 Subject: [PATCH 705/707] Improve Debian validation Signed-off-by: Philippe Ombredanne --- src/univers/debian.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/univers/debian.py b/src/univers/debian.py index 25e791e9..b9520df4 100644 --- a/src/univers/debian.py +++ b/src/univers/debian.py @@ -137,7 +137,7 @@ def from_string(cls, version): version = version.strip() if not version: raise ValueError('Invalid version string: "{}"'.format(version)) - if not _is_valid_version(version): + if not cls.is_valid(version): raise ValueError('Invalid version string: "{}"'.format(version)) if ":" in version: @@ -153,6 +153,10 @@ def from_string(cls, version): revision = "0" return cls(epoch=epoch, upstream=upstream, revision=revision) + @classmethod + def is_valid(cls, version): + return is_valid_debian_version(version) + def compare(self, other_version): return compare_versions(self, other_version) @@ -163,7 +167,7 @@ def tuple(self): return self.epoch, self.upstream, self.revision -_is_valid_version = re.compile( +is_valid_debian_version = re.compile( r"^" # epoch must start with a digit r"(\d+:)?" From 021247c02613c05114eff3bfc3d56e5bf53320cb Mon Sep 17 00:00:00 2001 From: Philippe Ombredanne Date: Sun, 19 Dec 2021 22:34:06 +0100 Subject: [PATCH 706/707] Implement RPM and Archlinux. Refine Debian Use share function split_req() to split Debian relationships and RPM requirements that are highly similar. Also introduce VersionRange.from_natives() using a list input in addition to VersionRange.from_native() using a single string. Add empty provisoional from_cve_v4() from_cve_v5() and from_osv_v1() placeholder functions. Add or improve various minor docstring Signed-off-by: Philippe Ombredanne --- src/univers/rpm.py | 36 ++++ src/univers/version_constraint.py | 9 +- src/univers/version_range.py | 278 +++++++++++++++++++++++++----- src/univers/versions.py | 72 +++++--- 4 files changed, 324 insertions(+), 71 deletions(-) diff --git a/src/univers/rpm.py b/src/univers/rpm.py index 199b6492..88b1b558 100644 --- a/src/univers/rpm.py +++ b/src/univers/rpm.py @@ -15,15 +15,48 @@ class RpmVersion(NamedTuple): + """ + Represent an RPM version. It is ordered. + """ + epoch: int version: str release: str + def __str__(self, *args, **kwargs): + return self.to_string() + + def to_string(self): + if self.release: + vr = f"{self.version}-{self.release}" + else: + vr = self.version + + if self.epoch: + vr = f"{self.epoch}:{vr}" + return vr + @classmethod def from_string(cls, s): + s.strip() e, v, r = from_evr(s) return cls(e, v, r) + def __lt__(self, other): + return compare_rpm_versions(self, other) < 0 + + def __gt__(self, other): + return compare_rpm_versions(self, other) > 0 + + def __eq__(self, other): + return compare_rpm_versions(self, other) == 0 + + def __le__(self, other): + return compare_rpm_versions(self, other) <= 0 + + def __ge__(self, other): + return compare_rpm_versions(self, other) >= 0 + def from_evr(s): """ @@ -74,6 +107,9 @@ def compare_rpm_versions(a: Union[RpmVersion, str], b: Union[RpmVersion, str]) - a = RpmVersion.from_string(a) if isinstance(b, str): b = RpmVersion.from_string(b) + if not isinstance(a, RpmVersion) and not isinstance(b, RpmVersion): + raise TypeError(f"{a!r} and {b!r} must be RpmVersion or strings") + # First compare the epoch, if set. If the epoch's are not the same, then # the higher one wins no matter what the rest of the EVR is. if a.epoch != b.epoch: diff --git a/src/univers/version_constraint.py b/src/univers/version_constraint.py index aebbca29..13e91bcb 100644 --- a/src/univers/version_constraint.py +++ b/src/univers/version_constraint.py @@ -25,8 +25,9 @@ def pairwise(iterable): """ -Universal version constraint object that stores a comparator such as "=" and -an ecosystem- or package-specific Version object. +Universal version constraint object that stores a comparator such as "=" or "<=" +and a Version object using a class that is specific to a package type (aka. +ecosystem) """ @@ -38,9 +39,7 @@ def operator_star(a, b): return True -# a minimalist, reduced set of comparators -MINIMALIST_COMPARATORS = {">=", "<", "*"} - +# note: ORDER MATTER here: we tests startswith(key) for each key in sequence COMPARATORS = { ">=": operator.ge, "<=": operator.le, diff --git a/src/univers/version_range.py b/src/univers/version_range.py index 9f0363f5..88bfd314 100644 --- a/src/univers/version_range.py +++ b/src/univers/version_range.py @@ -38,8 +38,8 @@ class VersionRange: # PypiVersion. Subclasses MUST provide this. version_class = None - # A list of lists of VersionConstraint where the outer list is an "OR" of - # the innner lists that are each "ANDs" of atomic constraints + # A list of lists of VersionConstraint that are signposts on the versions + # timeline constraints = attr.ib(type=list, default=attr.Factory(list)) def __attrs_post_init__(self, *args, **kwargs): @@ -49,14 +49,24 @@ def __attrs_post_init__(self, *args, **kwargs): def from_native(cls, string): """ Return a VersionRange built from a scheme-specific, native version range - ``string``. Subclasses must implement. + ``string``. Subclasses can implement. """ return NotImplementedError - def to_native(self): + @classmethod + def from_natives(cls, strings): """ - Return a native range string for this VersionRange. Subclasses must - implement. + Return a VersionRange built from a ``strings`` list of scheme- + specific native version range strings. Subclasses can implement. + """ + return NotImplementedError + + def to_native(self, *args, **kwargs): + """ + Return a native range string for this VersionRange. Subclasses can + implement. Opetional ``args`` and ``kwargs`` allow subclass to require + extra arguments (such as a package name that some scheme may require + like for deb and rpm.) """ return NotImplementedError @@ -143,6 +153,33 @@ def __eq__(self, other): ) +def from_cve_v4(data, scheme): + """ + Return a VersionRange build from the provided CVE V4 API ``data`` using the + provided versioning vers ``scheme``. + """ + + +def from_cve_v5(data, scheme): + """ + Return a VersionRange build from the provided CVE V5 API ``data`` using the + provided versioning vers ``scheme``. + + See https://github.com/CVEProject/cve-schema/tree/master/schema/v5.0 + ``data`` can be: + - a mapping of collectionURL and versions: + {"collectionURL": "some URL", "versions": [{"versionValue": "1.0"}]} + + """ + + +def from_osv_v1(data, scheme): + """ + Return a VersionRange build from the provided CVE V4 API data using the + provided versioning vers ``scheme``. + """ + + class NpmVersionRange(VersionRange): scheme = "npm" version_class = versions.SemverVersion @@ -240,6 +277,53 @@ def from_native(cls, string): return cls(constraints=constraints) +def split_req(string, comparators, default=None, strip=""): + """ + Return a tuple of (vers comparator, version) strings given an common version + requirement``string`` such as "> 2.3" or "<= 2.3" using the ``comparators`` + mapping of {native comparator: vers comparator}. Strip the ``string`` from + the provided leading of training characters in ``strip``. + + If there is none of the ``comparators`` found in ``string``: + + - Return the ``default`` vers comparator string if provided. + - Otherwise, raise a ValueError for an unknown comparator. + + For example:: + + >>> comps = {"=": "=", "<=": "<=", ">=": ">="} + >>> assert split_req("= 2.3", comparators=comps) == ("=", "2.3",) + >>> assert split_req(" < = 2 . 3 ", comparators=comps) == ("<=", "2.3",) + >>> assert split_req(">= 2.3", comparators=comps) == (">=", "2.3",) + >>> assert split_req(">= 2.3", comparators=comps) == (">=", "2.3",) + >>> assert split_req("<= 2.3", comparators=comps) == ("<=", "2.3",) + >>> assert split_req("(< = 2.3 )", comparators=comps, strip=")(") == ("<=", "2.3",) + + With a default, we return the default comparator:: + + >>> assert split_req("2.3,", comparators=comps, default="=", strip=",") == ("=", "2.3",) + + Otherwise, a ValuaeError:: + + >>> try: + ... split_req("~2.3", comparators=comps, ) + ... raise Exception("ValueError should be raised") + ... except ValueError: + ... pass + """ + constraint_string = remove_spaces(string).strip(strip) + + for native_comparator, vers_comparator in comparators.items(): + if constraint_string.startswith(native_comparator): + version = constraint_string.lstrip(native_comparator) + return vers_comparator, version + + if default: + return default, constraint_string + + raise ValueError(f"Unknown comparator in version requirement: {string!r} ") + + class DebianVersionRange(VersionRange): """ Debian version ranges as seen in Debian manual for relationships: @@ -280,8 +364,8 @@ def split(cls, string): >>> assert DebianVersionRange.split("(>=2.3)") == (">=", "2.3",) >>> assert DebianVersionRange.split(">=2.3") == (">=", "2.3",) >>> assert DebianVersionRange.split("<=2.3") == ("<=", "2.3",) - >>> assert DebianVersionRange.split("<<2.3") == ("<<", "2.3",) - >>> assert DebianVersionRange.split(">>2.3") == (">>", "2.3",) + >>> assert DebianVersionRange.split("<<2.3") == ("<", "2.3",) + >>> assert DebianVersionRange.split(">>2.3") == (">", "2.3",) >>> assert DebianVersionRange.split(">2.3") == (">", "2.3",) >>> assert DebianVersionRange.split("<2.3") == ("<", "2.3",) >>> try: @@ -290,59 +374,77 @@ def split(cls, string): ... except ValueError: ... pass """ - constraint_string = remove_spaces(string).strip(")(") + return split_req( + string=string, + comparators=cls.vers_by_native_comparators, + strip=")(", + ) + + @classmethod + def build_constraint_from_string(cls, string): + """ + Return a VersionConstraint built from a single Debian version + relationship ``string``. + + >>> vr = DebianVersionRange.build_constraint_from_string("= 5.0") + >>> assert str(vr) == "5.0" + >>> vr = DebianVersionRange.build_constraint_from_string("(>> 2.23)") + >>> assert str(vr) == ">2.23" + >>> vr = DebianVersionRange.build_constraint_from_string("<= 2.24") + >>> assert str(vr) == "<=2.24" + """ + comparator, version = cls.split(string) + version = cls.version_class(version) + return VersionConstraint(comparator=comparator, version=version) + + @classmethod + def from_native(cls, string): + """ + Return a VersionRange built from a ``string`` single Debian + version relationship string. - for comparator in cls.vers_by_native_comparators: - if constraint_string.startswith(comparator): - version = constraint_string.lstrip(comparator) - return comparator, version + For example:: - raise ValueError(f"Unknown Debian version relationship: {string}") + >>> vr = DebianVersionRange.from_native("(= 3.5.6)") + >>> assert str(vr) == "vers:deb/3.5.6" + """ + return cls(constraints=[cls.build_constraint_from_string(string)]) @classmethod - def from_native(cls, relationships): + def from_natives(cls, strings): """ - Return a VersionRange built from a ``relationships`` list of Debian - version relationship strings or a single relationship string. + Return a VersionRange built from a ``strings`` list of Debian + version relationships or a single relationship string. + For example:: - >>> dvr = DebianVersionRange.from_native("= 3.5.6") - >>> assert str(dvr) == "vers:deb/3.5.6" + >>> vr = DebianVersionRange.from_natives("= 3.5.6") + >>> assert str(vr) == "vers:deb/3.5.6" >>> rels = ["(>= 2.8.16)"] - >>> dvr = DebianVersionRange.from_native(rels) - >>> assert str(dvr) == "vers:deb/>=2.8.16" + >>> vr = DebianVersionRange.from_natives(rels) + >>> assert str(vr) == "vers:deb/>=2.8.16" >>> rels = [">= 1:1.1.4", "(>= 2.8.16)", "<= 2.8.16-z"] - >>> dvr = DebianVersionRange.from_native(rels) - >>> assert str(dvr) == "vers:deb/>=2.8.16|<=2.8.16-z|>=1:1.1.4" + >>> vr = DebianVersionRange.from_natives(rels) + >>> assert str(vr) == "vers:deb/>=2.8.16|<=2.8.16-z|>=1:1.1.4" >>> rels = ["(>= 2:4.13.1)", "(<= 2:4.13.1-0ubuntu0.16.04.1.1~)"] - >>> dvr = DebianVersionRange.from_native(rels) - >>> assert str(dvr) == "vers:deb/>=2:4.13.1|<=2:4.13.1-0ubuntu0.16.04.1.1~" + >>> vr = DebianVersionRange.from_natives(rels) + >>> assert str(vr) == "vers:deb/>=2:4.13.1|<=2:4.13.1-0ubuntu0.16.04.1.1~" >>> rels = ["= 5.0", "(>> 2.23)", "< 2.24"] - >>> dvr = DebianVersionRange.from_native(rels) - >>> assert str(dvr) == "vers:deb/>2.23|<2.24|5.0" + >>> vr = DebianVersionRange.from_natives(rels) + >>> assert str(vr) == "vers:deb/>2.23|<2.24|5.0" >>> rels = ["(<< 3:1.1.25~)", "(>> 2:1.1.24~)"] - >>> dvr = DebianVersionRange.from_native(rels) - >>> assert str(dvr) == "vers:deb/>2:1.1.24~|<3:1.1.25~" + >>> vr = DebianVersionRange.from_natives(rels) + >>> assert str(vr) == "vers:deb/>2:1.1.24~|<3:1.1.25~" """ - constraints = [] - - if isinstance(relationships, str): - relationships = [relationships] - - for rel in relationships: - comparator, version = cls.split(rel) - comparator = cls.vers_by_native_comparators[comparator] - version = cls.version_class(version) - constraint = VersionConstraint(comparator=comparator, version=version) - constraints.append(constraint) - - constraints.sort() + if isinstance(strings, str): + return cls.from_native(strings) + constraints = [cls.build_constraint_from_string(rel) for rel in strings] return cls(constraints=constraints) @@ -413,6 +515,10 @@ class MavenVersionRange(VersionRange): class NugetVersionRange(VersionRange): + """ + NuGet range as in:[3.10.1,4) + """ + scheme = "nuget" version_class = versions.NugetVersion @@ -425,12 +531,94 @@ class ComposerVersionRange(VersionRange): class RpmVersionRange(VersionRange): - # https://twiki.cern.ch/twiki/bin/view/Main/RPMAndDebVersioning + # http://ftp.rpm.org/api/4.4.2.2/dependencies.html + # http://ftp.rpm.org/max-rpm/s1-rpm-depend-manual-dependencies.html scheme = "rpm" version_class = versions.RpmVersion + vers_by_native_comparators = { + "=": "=", + "<=": "<=", + ">=": ">=", + "<": "<", + ">": ">", + # seen in RPM code but never seen in the doc or in the wild so far + "<>": "!=", + # seen in a specfile parser code + "!=": "!=", + "==": "=", + } + + @classmethod + def build_constraint_from_string(cls, string): + """ + Return a VersionConstraint built from a single RPM version + relationship ``string``. + + >>> vr = RpmVersionRange.build_constraint_from_string("= 5.0") + >>> assert str(vr) == "5.0", str(vr) + >>> vr = RpmVersionRange.build_constraint_from_string("> 2.23,") + >>> assert str(vr) == ">2.23", str(vr) + >>> vr = RpmVersionRange.build_constraint_from_string("<= 2.24") + >>> assert str(vr) == "<=2.24", str(vr) + """ + comparator, version = split_req( + string=string, + comparators=cls.vers_by_native_comparators, + strip=",", + ) + version = cls.version_class(version) + return VersionConstraint(comparator=comparator, version=version) + + @classmethod + def from_native(cls, string): + """ + Return a VersionRange built from a ``string`` single RPM + version requirement string. + + For example:: + + >>> vr = RpmVersionRange.from_native("= 3.5.6") + >>> assert str(vr) == "vers:rpm/3.5.6", str(vr) + """ + return cls(constraints=[cls.build_constraint_from_string(string)]) + + @classmethod + def from_natives(cls, strings): + """ + Return a VersionRange built from a ``strings`` list of RPM + version requirements or a single requirement string. + + For example:: + + >>> vr = RpmVersionRange.from_natives("= 3.5.6") + >>> assert str(vr) == "vers:rpm/3.5.6", str(vr) + + >>> reqs = [">= 2.8.16"] + >>> vr = RpmVersionRange.from_natives(reqs) + >>> assert str(vr) == "vers:rpm/>=2.8.16", str(vr) + + >>> reqs = [">= 1:1.1.4", ">= 2.8.16", "<= 2.8.16-z"] + >>> vr = RpmVersionRange.from_natives(reqs) + >>> assert str(vr) == "vers:rpm/>=2.8.16|<=2.8.16-z|>=1:1.1.4", str(vr) + + >>> reqs = ["= 5.0", "> 2.23,", "< 2.24"] + >>> vr = RpmVersionRange.from_natives(reqs) + >>> assert str(vr) == "vers:rpm/>2.23|<2.24|5.0", str(vr) + """ + + if isinstance(strings, str): + return cls.from_native(strings) + constraints = [cls.build_constraint_from_string(rel) for rel in strings] + return cls(constraints=constraints) + class GolangVersionRange(VersionRange): + """ + Go modules use strict semver with pseudo numbering for Git repos + https://go.dev/doc/modules/version-numbers + """ + scheme = "golang" version_class = versions.SemverVersion @@ -438,11 +626,11 @@ class GolangVersionRange(VersionRange): class GenericVersionRange(VersionRange): scheme = "generic" version_class = versions.SemverVersion - # apache is not semver at large. And in particular we may have schemes that - # are package name-specific class ApacheVersionRange(VersionRange): + # apache is not semver at large. And in particular we may have schemes that + # are package name-specific scheme = "apache" version_class = versions.SemverVersion diff --git a/src/univers/versions.py b/src/univers/versions.py index 1ed3eaed..82c81d30 100644 --- a/src/univers/versions.py +++ b/src/univers/versions.py @@ -40,8 +40,11 @@ class Version: Base version mixin to subclass for each version syntax implementation. Each version subclass is: - - comparable and orderable e.g., such as implementing functools.total_ordering + - immutable and hashable + - comparable and orderable e.g., such as implementing all rich comparison + operators or implementing functools.total_ordering. The default is to + compare the value as-is. """ # the original string used to build this Version @@ -81,8 +84,8 @@ def normalize(cls, string): """ Return a normalized version string from ``string ``. Subclass can override. """ - # FIXME: Is lowercase and strip v the right thing to do? - return remove_spaces(string).lower().rstrip("v") + # FIXME: Is removing spaces and strip v the right thing to do? + return remove_spaces(string).rstrip("v") @classmethod def build_value(self, string): @@ -115,8 +118,22 @@ def __lt__(self, other): return NotImplemented return self.value.__lt__(other.value) + def __gt__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return self.value.__gt__(other.value) + + def __le__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return self.value.__le__(other.value) + + def __ge__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return self.value.__ge__(other.value) + -@total_ordering @attr.s(frozen=True, order=False, hash=True) class GenericVersion(Version): @classmethod @@ -132,7 +149,6 @@ def is_valid(cls, string): return super(GenericVersion, cls).is_valid(string) -@total_ordering @attr.s(frozen=True, order=False, eq=False, hash=True) class PypiVersion(Version): """ @@ -158,7 +174,6 @@ def is_valid(cls, string): return False -@total_ordering @attr.s(frozen=True, order=False, eq=False, hash=True) class SemverVersion(Version): """ @@ -178,7 +193,6 @@ def is_valid(cls, string): return False -@total_ordering @attr.s(frozen=True, order=False, eq=False, hash=True) class RubygemsVersion(Version): """ @@ -196,7 +210,6 @@ def is_valid(cls, string): return gem.GemVersion.is_correct(string) -@total_ordering @attr.s(frozen=True, order=False, eq=False, hash=True) class ArchLinuxVersion(Version): def __eq__(self, other): @@ -207,18 +220,35 @@ def __eq__(self, other): def __lt__(self, other): if not isinstance(other, self.__class__): return NotImplemented - return arch.vercmp(self.value, other.value) == -1 + return arch.vercmp(self.value, other.value) < 0 + + def __gt__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return arch.vercmp(self.value, other.value) > 0 + + def __le__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return arch.vercmp(self.value, other.value) <= 0 + + def __ge__(self, other): + if not isinstance(other, self.__class__): + return NotImplemented + return arch.vercmp(self.value, other.value) >= 0 -@total_ordering @attr.s(frozen=True, order=False, eq=False, hash=True) class DebianVersion(Version): @classmethod def build_value(cls, string): return debian.Version.from_string(string) + @classmethod + def is_valid(cls, string): + return debian.Version.is_valid(string) + -@total_ordering @attr.s(frozen=True, order=False, eq=False, hash=True) class MavenVersion(Version): # See https://maven.apache.org/enforcer/enforcer-rules/versionRanges.html @@ -229,25 +259,25 @@ def build_value(cls, string): return maven.Version(string) -@total_ordering @attr.s(frozen=True, order=False, eq=False, hash=True) class NugetVersion(SemverVersion): # See https://docs.microsoft.com/en-us/nuget/concepts/package-versioning pass -@total_ordering @attr.s(frozen=True, order=False, eq=False, hash=True) class RpmVersion(Version): - def __eq__(self, other): - if not isinstance(other, self.__class__): - return NotImplemented - return rpm.vercmp(self.value, other.value) == 0 + """ + Represent an RPM version. - def __lt__(self, other): - if not isinstance(other, self.__class__): - return NotImplemented - return rpm.vercmp(self.value, other.value) == -1 + For example:: + + # 1:1.1.4|>=2.8.16|<=2.8.16-z + """ + + @classmethod + def build_value(cls, string): + return rpm.RpmVersion.from_string(string) @total_ordering From 8b84788c7f43271bd10274785f315c05c476b61d Mon Sep 17 00:00:00 2001 From: Philippe Ombredanne Date: Wed, 29 Dec 2021 00:50:33 +0100 Subject: [PATCH 707/707] Implement vers spec validations Signed-off-by: Philippe Ombredanne --- src/univers/version_constraint.py | 47 +++++++++++++++++++++++++------ src/univers/version_range.py | 16 ++++++++++- 2 files changed, 54 insertions(+), 9 deletions(-) diff --git a/src/univers/version_constraint.py b/src/univers/version_constraint.py index 13e91bcb..a9acd1ae 100644 --- a/src/univers/version_constraint.py +++ b/src/univers/version_constraint.py @@ -6,8 +6,8 @@ import operator from functools import total_ordering -import attr +import attr from univers.utils import remove_spaces from univers.versions import Version @@ -125,8 +125,14 @@ def from_string(cls, string, version_class): a ``version_class`` Version class. """ constraint_string = remove_spaces(string) - comparator, version = cls.split(constraint_string) + # A version range specifier contains only printable ASCII letters, digits and + # punctuation. + is_ascii = len(constraint_string) + 2 == len(ascii(constraint_string)) + if not is_ascii: + raise ValueError(f"Invalid non ASCII characters: {string!r}") + + comparator, version = cls.split(constraint_string) if comparator not in COMPARATORS: raise ValueError(f"Unknown comparator: {comparator!r}") @@ -230,10 +236,18 @@ def validate(cls, constraints): if not all(isinstance(c, VersionConstraint) for c in constraints): raise ValueError(f"{constraints!r} can contain only VersionConstraint") + # Versions are unique. Each ``version`` must be unique in a range and can + # occur only once in any ```` of a range specifier, + # irrespective of its comparators. Tools must report an error for duplicated + # versions. if len(set(c.version for c in constraints)) != len(constraints): raise ValueError(f"{constraints!r} cannot contain duplicated Version") + # Constraints are sorted by version**. The canonical ordering is the versions + # order. The ordering of ```` is not significant otherwise + # but this sort order is needed when check if a version is contained in a range. constraints.sort() + return validate_comparators(constraints) @classmethod @@ -282,17 +296,28 @@ def validate_comparators(constraints): - ">" and ">=" can only be followed by one of "<", "<=" """ + # Starting from a de-duplicated and sorted list of constraints, these extra rules + # apply to the comparators of any two contiguous constraints to be valid: + + # There is only one star: "*" must only occur once and alone in a range, + # without any other constraint or version. if any(c.comparator == "*" for c in constraints): if len(constraints) != 1: raise ValueError(f"Invalid {constraints!r}: can contain only one star '*'") return True - # discard != that can occur anywhere + # "!=" constraint can be followed by a constraint using any comparator, i.e., + # any of "=", "!=", ">", ">=", "<", "<=" as comparator (or no constraint). + + # Ignoring all constraints with "!=" comparators: + # --> discard != that can occur anywhere constraints = [c for c in constraints if c.comparator != "!="] if not constraints: return True - # check that equals is followed only by "=", ">", ">=" + # A "=" constraint must be followed only by a constraint with one of "=", ">", + # ">=" as comparator (or no constraint). + # --> check that equals is followed only by "=", ">", ">=" invalid_equal = [ (cur, nxt) for cur, nxt in pairwise(constraints) @@ -305,16 +330,22 @@ def validate_comparators(constraints): f"Invalid {c!r}: where {i!r} " "cannot contain an equal = followed by either < or <=" ) - # discard = that have been validated above + # And ignoring all constraints with "=" or "!=" comparators: + # --> discard = that have been validated above constraints = [c for c in constraints if c.comparator != "="] if not constraints: return True - # from now on this must be an alternation of greater/lesser + # the sequence of constraint comparators must be an alternation of greater + # and lesser comparators: + # --> from now on this must be an alternation of greater/lesser for cur_constraint, nxt_constraint in pairwise(constraints): cur_comp = cur_constraint.comparator nxt_comp = nxt_constraint.comparator + # "<" and "<=" must be followed by one of ">", ">=" (or no constraint). + # ">" and ">=" must be followed by one of "<", "<=" (or no constraint). + # Tools must report an error for such invalid ranges. if (cur_comp in ("<", "<=") and nxt_comp not in (">", ">=")) or ( cur_comp in (">", ">=") and nxt_comp not in ("<", "<=") ): @@ -373,11 +404,11 @@ def simplify_constraints(constraints): # discard current constraint constraints.pop(i) # Previous constraint becomes current if if exists. - if i: + if i > 0: i -= 1 # If there is a previous constraint: - if i: + if i > 0: prv = constraints[i - 1] prv_comp = prv.comparator diff --git a/src/univers/version_range.py b/src/univers/version_range.py index 88bfd314..d7bc141f 100644 --- a/src/univers/version_range.py +++ b/src/univers/version_range.py @@ -76,8 +76,16 @@ def from_string(cls, vers, simplify=False, validate=False): Return a VersionRange built from a ``vers`` version range spec string, such as "vers:npm/1.2.3,>=2.0.0" """ + # Spaces are not significant and removed in a canonical form. vers = remove_spaces(vers) + # A version range specifier contains only printable ASCII letters, digits and + # punctuation. + is_ascii = len(vers) + 2 == len(ascii(vers)) + if not is_ascii: + raise ValueError(f"Invalid non ASCII characters: {vers!r}") + + # The URI scheme and versioning scheme are always lowercase as in ``vers:npm``. uri_scheme, _, scheme_range_spec = vers.partition(":") uri_scheme = uri_scheme.lower() @@ -94,10 +102,12 @@ def from_string(cls, vers, simplify=False, validate=False): version_class = range_class.version_class - constraints = constraints.strip() + constraints = remove_spaces(constraints) if not constraints: raise ValueError(f"{vers!r} specifies no version range constraints.") + # There is only one star: "*" must only occur once and alone in a range, + # without any other constraint or version. if constraints.startswith("*"): if constraints != "*": raise ValueError(f"{vers!r} contains an invalid '*' constraint.") @@ -113,7 +123,11 @@ def from_string(cls, vers, simplify=False, validate=False): ) parsed_constraints.append(constraint) + # Constraints are sorted by version**. The canonical ordering is the versions + # order. The ordering of ```` is not significant otherwise + # but this sort order is needed when check if a version is contained in a range. parsed_constraints.sort() + if simplify: parsed_constraints = VersionConstraint.simplify(parsed_constraints) if validate: