bundler-patch 0.9.0 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 96da032d4f30feda0e83bb1869df9e962846bd7c
4
- data.tar.gz: 8b73a7082fa6190b406d6204666118717d2328ac
3
+ metadata.gz: db13e486dca6bfc05d93f62cf35c04e8635ba49d
4
+ data.tar.gz: 9bc70139fc23c0411919e2c14405ee508ca10527
5
5
  SHA512:
6
- metadata.gz: 3d0fd0304763dbec00ce7cb8ea9bb60103733527627d470f00526bc2868c4f154cc6ac185dcbc59f198a1f579c3c9a1ea33616c374fceaeec5aa070460b85a53
7
- data.tar.gz: ee72e66cea4c8c44b5e3392ca091fc858fbe7929f795a31210d3af92c3bdfd132351739bde6cdc39286c215c4d3e07020fbc9a261ca79136a644cd12e81e3b7f
6
+ metadata.gz: b48d69a664d17906a3f38b2c1b235124e0c52e015e71afec2030a7a5cc88d9171737f33a34244655456aea0798abe95812dc75422b984739a1e1827dae454024
7
+ data.tar.gz: 848c2620c837d61da57080be7d5a982c068af6c82c35685eb8edd43243dfee1e917ec6941315497285d2e6aa6b95eeeae9835c7e8d33ce745b0cd744b675cf74
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 2.2.4
1
+ 2.3.1
data/.travis.yml CHANGED
@@ -5,12 +5,16 @@ before_install:
5
5
  - gem install bundler -v $BUNDLER_TEST_VERSION
6
6
  - bundle --version
7
7
 
8
+ script: bundle exec rake test:all
9
+
8
10
  matrix:
9
11
  include:
10
12
  - rvm: 2.1.10
11
13
  env: BUNDLER_TEST_VERSION=1.12.5
12
14
  - rvm: 2.2.5
13
15
  env: BUNDLER_TEST_VERSION=1.12.5
16
+ - rvm: 2.3.1
17
+ env: BUNDLER_TEST_VERSION=1.9.10
14
18
  - rvm: 2.3.1
15
19
  env: BUNDLER_TEST_VERSION=1.10.5
16
20
  - rvm: 2.3.1
@@ -18,4 +22,4 @@ matrix:
18
22
  - rvm: 2.3.1
19
23
  env: BUNDLER_TEST_VERSION=1.12.5
20
24
  - rvm: 2.3.1
21
- env: BUNDLER_TEST_VERSION=1.13.0.rc.1
25
+ env: BUNDLER_TEST_VERSION=1.13.0.rc.2
data/BUNDLER.md ADDED
@@ -0,0 +1,154 @@
1
+ # Conservative Bundle Updates
2
+
3
+ Starting with 1.13.0.rc.2, a subset of bundler-patch behavior was ported to Bundler itself.
4
+ The plan is to leave it undocumented and unsupported in 1.13 to give it a chance to
5
+ be used and flush out bugs and iron out some design decisions.
6
+
7
+ Part of that work before 1.14 (or maybe a later version) will be to properly document
8
+ `bundle update` as well as the [Conservative Updating](http://bundler.io/v1.12/man/bundle-install.1.html#CONSERVATIVE-UPDATING)
9
+ section of `bundle install`, but right now we need a placeholder document showing the new
10
+ stuff so folks know how to use it.
11
+
12
+ This is largely copy/pasta of the bundler-patch [README](README.md).
13
+
14
+ ## Usage
15
+
16
+ The default `bundle update` behavior remains untouched. Use of the new `--patch`
17
+ or `--minor` options will invoke the new conservative update behavior.
18
+
19
+ "Conservative" means it will sort all available versions to prefer the
20
+ latest releases from the current version, then the latest minor releases and
21
+ then the latest major releases.
22
+
23
+ "Prefer" means that no available versions are removed from consideration, to
24
+ help ensure a suitable dependency graph can be reconciled. This does mean some
25
+ gems cannot be upgraded or may be upgraded to unexpected versions. NOTE: There is
26
+ a `--strict` option which _will_ remove versions from consideration, see below.
27
+
28
+ Gem requirements as defined in the Gemfile will still define what versions are available.
29
+ The new conservative behavior controls the preference order of those versions.
30
+
31
+ For example, if gem 'foo' is locked at 1.0.2, with no gem requirement defined
32
+ in the Gemfile, and versions 1.0.3, 1.0.4, 1.1.0, 1.1.1, 2.0.0 all exist, the
33
+ default order of preference will be "1.0.4, 1.0.3, 1.0.2, 1.1.1, 1.1.0,
34
+ 2.0.0".
35
+
36
+ In the same example, if gem 'foo' has a requirement of '~> 1.0', version 2.0.0
37
+ will be removed from consideration as always.
38
+
39
+ With no gem names provided on the command line, all gems will be unlocked and
40
+ open for updating.
41
+
42
+ $ bundle update --patch
43
+
44
+ A list of gem names can be passed to restrict to just those gems.
45
+
46
+ $ bundle update --patch foo bar
47
+
48
+ * `--patch` option will give preference for release/patch versions, then minor,
49
+ then major.
50
+
51
+ * `--minor` option will give preference for minor versions over
52
+ release versions, then major versions.
53
+
54
+ * `--major` option will give preference for major versions over
55
+ minor or release versions. This is the default behavior currently, so this
56
+ flag is cosmetic for now. Bundler 2.0 will likely make `--patch` the default
57
+ behavior.
58
+
59
+ * `--strict` option will actually remove from consideration
60
+ versions outside either the current release (or minor version if `--minor`
61
+ specified). This increases the chances of Bundler being unable to
62
+ reconcile the dependency graph and in some cases could even raise a
63
+ `VersionConflict`.
64
+
65
+ ## Examples
66
+
67
+ ### Single Gem
68
+
69
+ | Requirements| Locked | Available | Option | Result |
70
+ |-------------|---------|----------------------------------|----------|--------|
71
+ | foo | 1.4.3 | 1.4.4, 1.4.5, 1.5.0, 1.5.1 1.6.0 | --patch | 1.4.5 |
72
+ | foo | 1.4.3 | 1.4.4, 1.4.5, 1.5.0, 1.5.1 1.6.0 | --minor | 1.5.1 |
73
+ | foo | 1.4.3 | 1.4.4, 1.4.5, 1.5.0, 1.5.1 1.6.0 | --major | 1.6.0 |
74
+
75
+ ### Two Gems
76
+
77
+ Given the following gem specifications:
78
+
79
+ - foo 1.4.3, requires: ~> bar 2.0
80
+ - foo 1.4.4, requires: ~> bar 2.0
81
+ - foo 1.4.5, requires: ~> bar 2.1
82
+ - foo 1.5.0, requires: ~> bar 2.1
83
+ - foo 1.5.1, requires: ~> bar 3.0
84
+ - bar with versions 2.0.3, 2.0.4, 2.1.0, 2.1.1, 3.0.0
85
+
86
+ Gemfile:
87
+
88
+ gem 'foo'
89
+
90
+ Gemfile.lock:
91
+
92
+ foo (1.4.3)
93
+ bar (~> 2.0)
94
+ bar (2.0.3)
95
+
96
+ | # | Command Line | Result |
97
+ |---|--------------------------------|---------------------------|
98
+ | 1 | bundle update --patch | 'foo 1.4.5', 'bar 2.1.1' |
99
+ | 2 | bundle update --patch foo | 'foo 1.4.4', 'bar 2.0.3' |
100
+ | 3 | bundle update --minor | 'foo 1.5.1', 'bar 3.0.0' |
101
+ | 4 | bundle update --minor --strict | 'foo 1.5.0', 'bar 2.1.1' |
102
+ | 5 | bundle update --patch --strict | 'foo 1.4.4', 'bar 2.0.4' |
103
+
104
+ In case 1, `bar` is upgraded to 2.1.1, a minor version increase, because the
105
+ dependency from `foo` 1.4.5 required it.
106
+
107
+ In case 2, only `foo` is unlocked, so `foo` can only go to 1.4.4 to maintain
108
+ the dependency to `bar`.
109
+
110
+ In case 3, `bar` goes up a whole major release, because a minor increase is
111
+ preferred now for `foo`, and when it goes to 1.5.1, it requires 3.0.0 of
112
+ `bar`.
113
+
114
+ In case 4, `foo` is preferred up to a 1.5.x, but 1.5.1 won't work because the
115
+ `--strict` flag removes `bar` 3.0.0 from consideration since it's a major
116
+ increment.
117
+
118
+ In case 5, both `foo` and `bar` have any minor or major increments removed
119
+ from consideration because of the `--strict` flag, so the most they can
120
+ move is up to 1.4.4 and 2.0.4.
121
+
122
+
123
+ ### Troubleshooting
124
+
125
+ First, make sure the current `bundle` command itself runs to completion on its
126
+ own without any problems.
127
+
128
+ The most frequent problems with this tool involve expectations around what
129
+ gems should or shouldn't be upgraded. This can quickly get complicated as even
130
+ a small dependency tree can involve many moving parts, and Bundler works hard
131
+ to find a combination that satisfies all of the dependencies and requirements.
132
+
133
+ NOTE: the requirements in the Gemfile trump anything else. The most control
134
+ you have is by modifying those in the Gemfile, in some circumstances it may be
135
+ better to pin your versions to what you need instead of trying to diagnose why
136
+ Bundler isn't calculating the versions you expect with a broader requirement.
137
+ If there is an incompatibility, pinning to desired versions can also aide in
138
+ debugging dependency conflicts.
139
+
140
+ You can get a (very verbose) look into how Bundler's resolution algorithm is
141
+ working by setting the `DEBUG_RESOLVER` environment variable. While it can be
142
+ tricky to dig through, it should explain how it came to the conclusions it
143
+ came to.
144
+
145
+ In particular, grep for 'Unwinding for conflict' in the debug output to
146
+ isolate some key issues that may be preventing the outcome you expect.
147
+
148
+ To get additional Bundler debugging output, enable the `DEBUG` env variable.
149
+ This will include all of the details of the downloading the full dependency
150
+ data from remote sources.
151
+
152
+ At the end of all of this though, again, the requirements in the Gemfile
153
+ trump anything else, and the most control you have is by modifying those
154
+ in the Gemfile.
data/README.md CHANGED
@@ -8,7 +8,9 @@ current version, over the latest minor releases or the latest major releases.
8
8
  This is somewhat opposite from `bundle update` which prefers newest/major
9
9
  versions first.
10
10
 
11
- Works with Bundler 1.10.x and higher.
11
+ Works with Bundler 1.9 and higher. Starting with Bundler 1.13, much of the
12
+ core behavior in `bundler-patch` has been ported to Bundler itself. Read
13
+ [BUNDLER.md](BUNDLER.md) for more information.
12
14
 
13
15
  [![Build Status](https://travis-ci.org/livingsocial/bundler-patch.svg?branch=master)](https://travis-ci.org/livingsocial/bundler-patch)
14
16
 
@@ -32,17 +34,10 @@ made.
32
34
  latest releases from the current version, then the latest minor releases and
33
35
  then the latest major releases.
34
36
 
35
- Gem requirements as defined in the Gemfile will restrict the available version
36
- options.
37
-
38
- For example, if gem 'foo' is locked at 1.0.2, with no gem requirement defined
39
- in the Gemfile, and versions 1.0.3, 1.0.4, 1.1.0, 1.1.1, 2.0.0 all exist, the
40
- default order of preference will be "1.0.4, 1.0.3, 1.0.2, 1.1.1, 1.1.0,
41
- 2.0.0".
42
-
43
37
  "Prefer" means that no available versions are removed from consideration*, to
44
38
  help ensure a suitable dependency graph can be reconciled. This does mean some
45
- gems cannot be upgraded or will be upgraded to unexpected versions.
39
+ gems cannot be upgraded or may be upgraded to unexpected versions. NOTE: There is
40
+ a `--strict_updates` option which _will_ remove versions from consideration, see below.
46
41
 
47
42
  _*That's a white-lie. bundler-patch will actually remove from consideration
48
43
  any versions older than the currently locked version, which `bundle update`
@@ -50,6 +45,17 @@ will not do. It's not common, but it is possible for `bundle update` to
50
45
  regress a gem to an older version, if necessary to reconcile the dependency
51
46
  graph._
52
47
 
48
+ Gem requirements as defined in the Gemfile will still define what versions are available.
49
+ The new conservative behavior controls the preference order of those versions.
50
+
51
+ For example, if gem 'foo' is locked at 1.0.2, with no gem requirement defined
52
+ in the Gemfile, and versions 1.0.3, 1.0.4, 1.1.0, 1.1.1, 2.0.0 all exist, the
53
+ default order of preference will be "1.0.4, 1.0.3, 1.0.2, 1.1.1, 1.1.0,
54
+ 2.0.0".
55
+
56
+ In the same example, if gem 'foo' has a requirement of '~> 1.0', version 2.0.0
57
+ will be removed from consideration as always.
58
+
53
59
  With no gem names provided on the command line, all gems will be unlocked and
54
60
  open for updating. A list of gem names can be passed to restrict to just those
55
61
  gems.
@@ -84,7 +90,7 @@ in the Gemfile on vulnerable gems to ensure they can be upgraded.
84
90
  The rules for updating vulnerable gems are almost identical to the general
85
91
  `bundler-patch` behavior described above, and abide by the same options (`-m`,
86
92
  `-p`, and `-s`) though there are some tweaks to encourage getting to at least
87
- a patched version of the gem. Keep in mind Bundler may choose unexpected
93
+ a patched version of the gem. Keep in mind Bundler may still choose unexpected
88
94
  versions in order to satisfy the dependency graph.
89
95
 
90
96
  * `-v/--vulnerable_gems_only` option will automatically restrict the gems
@@ -170,29 +176,40 @@ gems should or shouldn't be upgraded. This can quickly get complicated as even
170
176
  a small dependency tree can involve many moving parts, and Bundler works hard
171
177
  to find a combination that satisfies all of the dependencies and requirements.
172
178
 
179
+ NOTE: the requirements in the Gemfile trump anything else. The most control
180
+ you have is by modifying those in the Gemfile, in some circumstances it may be
181
+ better to pin your versions to what you need instead of trying to diagnose why
182
+ Bundler isn't calculating the versions you expect with a broader requirement.
183
+ If there is an incompatibility, pinning to desired versions can also aide in
184
+ debugging dependency conflicts.
185
+
173
186
  You can get a (very verbose) look into how Bundler's resolution algorithm is
174
187
  working by setting the `DEBUG_RESOLVER` environment variable. While it can be
175
188
  tricky to dig through, it should explain how it came to the conclusions it
176
189
  came to.
177
190
 
191
+ In particular, grep for 'Unwinding for conflict' in the debug output to
192
+ isolate some key issues that may be preventing the outcome you expect.
193
+
178
194
  Adding to the usual Bundler complexity, `bundler-patch` is injecting its own
179
195
  logic to the resolution process to achieve its goals. If there's a bug
180
196
  involved, it's almost certainly in the `bundler-patch` code as Bundler has
181
197
  been around a long time and has thorough testing and real world experience.
182
198
 
183
- In particular, grep for 'Unwinding for conflict' in the debug output to
184
- isolate some key issues that may be preventing the outcome you expect.
199
+ When used with versions of Bundler prior to 1.13, `bundler-patch` can dump
200
+ its own debug output, potentially helpful, with `DEBUG_PATCH_RESOLVER`.
185
201
 
186
- `bundler-patch` can dump its own debug output, potentially helpful, with
187
- `DEBUG_PATCH_RESOLVER`.
202
+ (When used with version 1.13+ of Bundler, `bundler-patch` only adds some
203
+ additional sorting behavior, the result of which will be included in the
204
+ `DEBUG_RESOLVER` output and `DEBUG_PATCH_RESOLVER` is not used).
188
205
 
189
206
  To get additional Bundler debugging output, enable the `DEBUG` env variable.
190
207
  This will include all of the details of the downloading the full dependency
191
208
  data from remote sources.
192
209
 
193
- At the end of all of this though, the requirements in the Gemfile trump
194
- anything else, and the most control you have is by modifying those in the
195
- Gemfile.
210
+ At the end of all of this though, again, the requirements in the Gemfile
211
+ trump anything else, and the most control you have is by modifying those
212
+ in the Gemfile.
196
213
 
197
214
 
198
215
  ## Development
@@ -19,12 +19,12 @@ Gem::Specification.new do |spec|
19
19
  spec.executables = ['bundler-patch']
20
20
  spec.require_paths = ['lib']
21
21
 
22
- spec.add_dependency 'bundler-advise', '~> 1.0', '>= 1.0.3'
22
+ spec.add_dependency 'bundler-advise', '~> 1.1', '>= 1.1.2'
23
23
  spec.add_dependency 'slop', '~> 3.0'
24
- spec.add_dependency 'bundler', '~> 1.10'
24
+ spec.add_dependency 'bundler', '~> 1.7'
25
25
 
26
26
  spec.add_development_dependency 'bundler-fixture', '~> 1.3'
27
27
  spec.add_development_dependency 'pry'
28
28
  spec.add_development_dependency 'rake', '~> 10.0'
29
- spec.add_development_dependency 'rspec'
29
+ spec.add_development_dependency 'rspec', '~> 3.5'
30
30
  end
@@ -1,3 +1,5 @@
1
+ require 'bundler'
2
+ require 'bundler/vendor/thor/lib/thor'
1
3
  require 'bundler/advise'
2
4
  require 'slop'
3
5
 
@@ -16,26 +16,37 @@ module Bundler::Patch
16
16
  else
17
17
  # Run a resolve against the locally available gems
18
18
  base = last_resolve.is_a?(Bundler::SpecSet) ? Bundler::SpecSet.new(last_resolve) : []
19
- resolver = ConservativeResolver.new(index, source_requirements, base)
20
- locked_specs = if @unlocking && @locked_specs.length == 0
21
- # Have to grab these again. Default behavior is to not store any
22
- # locked_specs if updating all gems, because behavior is the same
23
- # with no lockfile OR lockfile but update them all. In our case,
24
- # we need to know the locked versions for conservative comparison.
25
- locked = Bundler::LockfileParser.new(@lockfile_contents)
26
- Bundler::SpecSet.new(locked.specs)
27
- else
28
- @locked_specs
29
- end
30
-
31
- resolver.gems_to_update = @gems_to_update
32
- resolver.locked_specs = locked_specs
33
- resolver.strict = @strict
34
- resolver.minor_preferred = @minor_preferred
35
- resolver.prefer_minimal = @prefer_minimal
19
+ if Gem::Version.new(Bundler::VERSION) >= Gem::Version.new('1.13.0.rc.2')
20
+ require 'bundler/patch/gem_version_patch_promoter'
21
+
22
+ gvpp = Bundler::Patch::GemVersionPatchPromoter.new(@gem_version_promoter.locked_specs, @gem_version_promoter.unlock_gems)
23
+ gvpp.level = @minor_preferred ? :minor : :patch
24
+ gvpp.strict = @strict
25
+ gvpp.minimal = @prefer_minimal
26
+ gvpp.gems_to_update = @gems_to_update
27
+ resolver = Bundler::Resolver.new(index, source_requirements, base, nil, gvpp, additional_base_requirements_for_resolve)
28
+ else
29
+ resolver = ConservativeResolver.new(index, source_requirements, base)
30
+ locked_specs = if @unlocking && @locked_specs.length == 0
31
+ # Have to grab these again. Default behavior is to not store any
32
+ # locked_specs if updating all gems, because behavior is the same
33
+ # with no lockfile OR lockfile but update them all. In our case,
34
+ # we need to know the locked versions for conservative comparison.
35
+ locked = Bundler::LockfileParser.new(@lockfile_contents)
36
+ Bundler::SpecSet.new(locked.specs)
37
+ else
38
+ @locked_specs
39
+ end
40
+
41
+ resolver.gems_to_update = @gems_to_update
42
+ resolver.locked_specs = locked_specs
43
+ resolver.strict = @strict
44
+ resolver.minor_preferred = @minor_preferred
45
+ resolver.prefer_minimal = @prefer_minimal
46
+ end
47
+
36
48
  result = resolver.start(expanded_dependencies)
37
49
  spec_set = Bundler::SpecSet.new(result)
38
-
39
50
  last_resolve.merge spec_set
40
51
  end
41
52
  end
@@ -3,11 +3,10 @@ module Bundler::Patch
3
3
  attr_accessor :locked_specs, :gems_to_update, :strict, :minor_preferred, :prefer_minimal
4
4
 
5
5
  def initialize(index, source_requirements, base)
6
- # hack for 1.10 and 1.11+ support
7
6
  case Bundler::Resolver.instance_method(:initialize).arity
8
- when 3
7
+ when 3 # 1.9 1.10
9
8
  super(index, source_requirements, base)
10
- when 4
9
+ when 4 # 1.11 1.12
11
10
  super(index, source_requirements, base, nil)
12
11
  end
13
12
  end
@@ -74,48 +73,81 @@ module Bundler::Patch
74
73
  # reminder: sort still filters anything older than locked version
75
74
  def sort_specs(specs, locked_spec)
76
75
  return specs unless locked_spec
77
- gem_name = locked_spec.name
78
- locked_version = locked_spec.version
76
+ @gem_name = locked_spec.name
77
+ @locked_version = locked_spec.version
79
78
 
80
- filtered = specs.select { |s| s.first.version >= locked_version }
79
+ filtered = specs.select { |s| s.first.version >= @locked_version }
81
80
 
82
- filtered.sort do |a, b|
83
- a_ver = a.first.version
84
- b_ver = b.first.version
85
- gem_patch = @gems_to_update.gem_patch_for(gem_name)
86
- new_version = gem_patch ? gem_patch.new_version : nil
81
+ @gem_patch = @gems_to_update.gem_patch_for(@gem_name)
82
+ @new_version = @gem_patch ? @gem_patch.new_version : nil
83
+
84
+ result = filtered.sort do |a, b|
85
+ @a_ver = a.first.version
86
+ @b_ver = b.first.version
87
87
  case
88
- when a_ver.segments[0] != b_ver.segments[0]
89
- b_ver <=> a_ver
90
- when !@minor_preferred && (a_ver.segments[1] != b_ver.segments[1])
91
- b_ver <=> a_ver
92
- when @prefer_minimal && !@gems_to_update.unlocking_gem?(gem_name)
93
- b_ver <=> a_ver
94
- when @prefer_minimal && @gems_to_update.unlocking_gem?(gem_name) &&
95
- (![a_ver, b_ver].include?(locked_version) &&
96
- (!new_version || (new_version && a_ver >= new_version && b_ver >= new_version)))
97
- b_ver <=> a_ver
98
- else
99
- a_ver <=> b_ver
100
- end
101
- end.tap do |result|
102
- if @gems_to_update.unlocking_gem?(gem_name)
103
- gem_patch = @gems_to_update.gem_patch_for(gem_name)
104
- if gem_patch && gem_patch.new_version && @prefer_minimal
105
- move_version_to_end(specs, gem_patch.new_version, result)
106
- end
88
+ when segments_do_not_match(:major)
89
+ @b_ver <=> @a_ver
90
+ when !@minor_preferred && segments_do_not_match(:minor)
91
+ @b_ver <=> @a_ver
92
+ when @prefer_minimal && !unlocking_gem?
93
+ @b_ver <=> @a_ver
94
+ when @prefer_minimal && unlocking_gem? &&
95
+ (neither_version_matches(@locked_version) &&
96
+ (!@new_version || both_versions_gt_or_equal_to_version(@new_version)))
97
+ @b_ver <=> @a_ver
107
98
  else
108
- move_version_to_end(specs, locked_version, result)
99
+ @a_ver <=> @b_ver
109
100
  end
110
101
  end
102
+ post_sort(result)
111
103
  end
112
104
 
113
- def move_version_to_end(specs, version, result)
114
- spec_group = specs.detect { |s| s.first.version.to_s == version.to_s }
115
- if spec_group
116
- result.reject! { |s| s.first.version.to_s === version.to_s }
117
- result << spec_group
105
+ def post_sort(result)
106
+ unless unlocking_gem?
107
+ result = move_version_to_end(result, @locked_version)
108
+ end
109
+
110
+ if @new_version && unlocking_gem? && segments_match(:major, @new_version, @locked_version)
111
+ if @prefer_minimal || (!@prefer_minimal && (result.last.first.version < @new_version))
112
+ result = move_version_to_end(result, @new_version)
113
+ end
118
114
  end
115
+
116
+ result
117
+ end
118
+
119
+ def unlocking_gem?
120
+ @gems_to_update.unlocking_gem?(@gem_name)
121
+ end
122
+
123
+ def either_version_older_than_locked(locked_version)
124
+ @a_ver < locked_version || @b_ver < locked_version
125
+ end
126
+
127
+ def segments_match(level, a_ver=@a_ver, b_ver=@b_ver)
128
+ !segments_do_not_match(level, a_ver, b_ver)
129
+ end
130
+
131
+ def segments_do_not_match(level, a_ver=@a_ver, b_ver=@b_ver)
132
+ index = [:major, :minor].index(level)
133
+ a_ver.segments[index] != b_ver.segments[index]
134
+ end
135
+
136
+ def neither_version_matches(match_version)
137
+ !one_version_matches(match_version)
138
+ end
139
+
140
+ def one_version_matches(match_version)
141
+ [@a_ver, @b_ver].include?(match_version)
142
+ end
143
+
144
+ def both_versions_gt_or_equal_to_version(version)
145
+ version && @a_ver >= version && @b_ver >= version
146
+ end
147
+
148
+ def move_version_to_end(result, version)
149
+ move, keep = result.partition { |s| s.first.version.to_s == version.to_s }
150
+ keep.concat(move)
119
151
  end
120
152
  end
121
153
  end
@@ -0,0 +1,75 @@
1
+ module Bundler::Patch
2
+ class GemVersionPatchPromoter < Bundler::GemVersionPromoter
3
+ attr_accessor :minimal, :gems_to_update
4
+
5
+ private
6
+
7
+ def sort_dep_specs(spec_groups, locked_spec)
8
+ result = super(spec_groups, locked_spec)
9
+ return result unless locked_spec
10
+
11
+ @gem_name = locked_spec.name
12
+ @locked_version = locked_spec.version
13
+ gem_patch = @gems_to_update.gem_patch_for(@gem_name)
14
+ @new_version = gem_patch ? gem_patch.new_version : nil
15
+
16
+ return result unless @minimal || @new_version
17
+
18
+ # STDERR.puts "during sort_versions: #{debug_format_result(spec_groups.first.first.name, result).inspect}" if ENV["DEBUG_RESOLVER"]
19
+
20
+ # Custom sort_by-ish behavior to minimize index calls.
21
+ result = result.map { |a| [result.index(a), a] }.sort do |(a_index, a), (b_index, b)|
22
+ @a_ver = a.version
23
+ @b_ver = b.version
24
+ case
25
+ when @minimal && unlocking_gem? &&
26
+ (neither_version_matches(@locked_version) &&
27
+ (!@new_version || both_versions_gt_or_equal_to_version(@new_version)))
28
+ @b_ver <=> @a_ver
29
+ else
30
+ a_index <=> b_index # no change in current ordering
31
+ end
32
+ end.map { |a| a.last }
33
+
34
+ post_sort(result)
35
+ end
36
+
37
+ def unlocking_gem?
38
+ @gems_to_update.unlocking_gem?(@gem_name)
39
+ end
40
+
41
+ def one_version_matches(match_version)
42
+ [@a_ver, @b_ver].include?(match_version)
43
+ end
44
+
45
+ def neither_version_matches(match_version)
46
+ !one_version_matches(match_version)
47
+ end
48
+
49
+ def both_versions_gt_or_equal_to_version(version)
50
+ version && @a_ver >= version && @b_ver >= version
51
+ end
52
+
53
+ # Sorting won't work properly for some specific arrangements to the end of the list because not
54
+ # all versions are compared in quicksort and the result isn't deterministic.
55
+ def post_sort(result)
56
+ result = super(result)
57
+
58
+ if @new_version && unlocking_gem? && segments_match(:major, @new_version, @locked_version)
59
+ if @minimal || (!@minimal && result.last.version < @new_version)
60
+ # This handles two cases:
61
+ # - minimal doesn't want to go past requested new_version
62
+ # - new_version is up a minor rev but level is :patch
63
+ result = move_version_to_end(result, @new_version)
64
+ end
65
+ end
66
+
67
+ result
68
+ end
69
+
70
+ def segments_match(level, a_ver, b_ver)
71
+ index = [:major, :minor].index(level)
72
+ a_ver.segments[index] == b_ver.segments[index]
73
+ end
74
+ end
75
+ end
@@ -78,7 +78,7 @@ module Bundler::Patch
78
78
 
79
79
  def requirements_args_regexp
80
80
  ops = Gem::Requirement::OPS.keys.join "|"
81
- re = /(\s*['\"]\s*(#{ops})?\s*#{Gem::Version::VERSION_PATTERN}\s*['"],*)+/
81
+ /(\s*['\"]\s*(#{ops})?\s*#{Gem::Version::VERSION_PATTERN}\s*['"],*)+/
82
82
  end
83
83
 
84
84
  # See Bundler::Dsl for reference
@@ -1,9 +1,12 @@
1
1
  module Bundler::Patch
2
2
  class RubyVersion < UpdateSpec
3
+ RUBY_VERSION_LINE_REGEXPS = [/ruby\s+["'](.*)['"]/]
4
+
3
5
  def self.files
4
6
  {
5
7
  '.ruby-version' => [/.*/],
6
- 'Gemfile' => [/ruby\s+["'](.*)['"]/]
8
+ 'Gemfile' => RUBY_VERSION_LINE_REGEXPS,
9
+ 'gems.rb' => RUBY_VERSION_LINE_REGEXPS,
7
10
  }
8
11
  end
9
12
 
@@ -71,15 +71,3 @@ module Bundler::Patch
71
71
  end
72
72
  end
73
73
  end
74
-
75
- # def prep_git_checkout(spec)
76
- # Dir.chdir(spec.target_dir) do
77
- # status_first_line = `git status`.split("\n").first
78
- # raise "Not on master: #{status_first_line}" unless status_first_line == '# On branch master'
79
- #
80
- # raise 'Uncommitted files' unless `git status --porcelain`.chomp.empty?
81
- #
82
- # verbose_puts `git pull`
83
- # end
84
- # end
85
-
@@ -1,5 +1,5 @@
1
1
  module Bundler
2
2
  module Patch
3
- VERSION = '0.9.0'
3
+ VERSION = '0.10.0'
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bundler-patch
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.0
4
+ version: 0.10.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - chrismo
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-08-02 00:00:00.000000000 Z
11
+ date: 2016-08-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler-advise
@@ -16,20 +16,20 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '1.0'
19
+ version: '1.1'
20
20
  - - ">="
21
21
  - !ruby/object:Gem::Version
22
- version: 1.0.3
22
+ version: 1.1.2
23
23
  type: :runtime
24
24
  prerelease: false
25
25
  version_requirements: !ruby/object:Gem::Requirement
26
26
  requirements:
27
27
  - - "~>"
28
28
  - !ruby/object:Gem::Version
29
- version: '1.0'
29
+ version: '1.1'
30
30
  - - ">="
31
31
  - !ruby/object:Gem::Version
32
- version: 1.0.3
32
+ version: 1.1.2
33
33
  - !ruby/object:Gem::Dependency
34
34
  name: slop
35
35
  requirement: !ruby/object:Gem::Requirement
@@ -50,14 +50,14 @@ dependencies:
50
50
  requirements:
51
51
  - - "~>"
52
52
  - !ruby/object:Gem::Version
53
- version: '1.10'
53
+ version: '1.7'
54
54
  type: :runtime
55
55
  prerelease: false
56
56
  version_requirements: !ruby/object:Gem::Requirement
57
57
  requirements:
58
58
  - - "~>"
59
59
  - !ruby/object:Gem::Version
60
- version: '1.10'
60
+ version: '1.7'
61
61
  - !ruby/object:Gem::Dependency
62
62
  name: bundler-fixture
63
63
  requirement: !ruby/object:Gem::Requirement
@@ -104,16 +104,16 @@ dependencies:
104
104
  name: rspec
105
105
  requirement: !ruby/object:Gem::Requirement
106
106
  requirements:
107
- - - ">="
107
+ - - "~>"
108
108
  - !ruby/object:Gem::Version
109
- version: '0'
109
+ version: '3.5'
110
110
  type: :development
111
111
  prerelease: false
112
112
  version_requirements: !ruby/object:Gem::Requirement
113
113
  requirements:
114
- - - ">="
114
+ - - "~>"
115
115
  - !ruby/object:Gem::Version
116
- version: '0'
116
+ version: '3.5'
117
117
  description:
118
118
  email:
119
119
  - chrismo@clabs.org
@@ -126,6 +126,7 @@ files:
126
126
  - ".rspec"
127
127
  - ".ruby-version"
128
128
  - ".travis.yml"
129
+ - BUNDLER.md
129
130
  - Gemfile
130
131
  - LICENSE.txt
131
132
  - README.md
@@ -139,6 +140,7 @@ files:
139
140
  - lib/bundler/patch/cli.rb
140
141
  - lib/bundler/patch/conservative_definition.rb
141
142
  - lib/bundler/patch/conservative_resolver.rb
143
+ - lib/bundler/patch/gem_version_patch_promoter.rb
142
144
  - lib/bundler/patch/gemfile.rb
143
145
  - lib/bundler/patch/gems_to_patch_reconciler.rb
144
146
  - lib/bundler/patch/ruby_version.rb
@@ -164,7 +166,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
164
166
  version: '0'
165
167
  requirements: []
166
168
  rubyforge_project:
167
- rubygems_version: 2.4.5.1
169
+ rubygems_version: 2.6.4
168
170
  signing_key:
169
171
  specification_version: 4
170
172
  summary: Conservative bundler updates