molinillo 0.5.7 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. checksums.yaml +5 -5
  2. data/ARCHITECTURE.md +102 -0
  3. data/CHANGELOG.md +352 -0
  4. data/lib/molinillo.rb +2 -0
  5. data/lib/molinillo/compatibility.rb +26 -0
  6. data/lib/molinillo/delegates/resolution_state.rb +7 -0
  7. data/lib/molinillo/delegates/specification_provider.rb +1 -0
  8. data/lib/molinillo/dependency_graph.rb +3 -2
  9. data/lib/molinillo/dependency_graph/action.rb +1 -0
  10. data/lib/molinillo/dependency_graph/add_edge_no_circular.rb +1 -0
  11. data/lib/molinillo/dependency_graph/add_vertex.rb +1 -0
  12. data/lib/molinillo/dependency_graph/delete_edge.rb +1 -0
  13. data/lib/molinillo/dependency_graph/detach_vertex_named.rb +1 -0
  14. data/lib/molinillo/dependency_graph/log.rb +1 -0
  15. data/lib/molinillo/dependency_graph/set_payload.rb +1 -0
  16. data/lib/molinillo/dependency_graph/tag.rb +1 -0
  17. data/lib/molinillo/dependency_graph/vertex.rb +3 -2
  18. data/lib/molinillo/errors.rb +69 -6
  19. data/lib/molinillo/gem_metadata.rb +2 -1
  20. data/lib/molinillo/modules/specification_provider.rb +1 -0
  21. data/lib/molinillo/modules/ui.rb +3 -1
  22. data/lib/molinillo/resolution.rb +495 -145
  23. data/lib/molinillo/resolver.rb +1 -0
  24. data/lib/molinillo/state.rb +8 -4
  25. metadata +8 -30
  26. data/spec/dependency_graph/log_spec.rb +0 -29
  27. data/spec/dependency_graph_spec.rb +0 -74
  28. data/spec/errors_spec.rb +0 -26
  29. data/spec/fuzz_spec.rb +0 -94
  30. data/spec/resolver_integration_specs/index_from_rubygems.rb +0 -76
  31. data/spec/resolver_spec.rb +0 -235
  32. data/spec/spec_helper.rb +0 -44
  33. data/spec/spec_helper/equal_dependency_graph.rb +0 -16
  34. data/spec/spec_helper/index.rb +0 -186
  35. data/spec/spec_helper/naive_resolver.rb +0 -48
  36. data/spec/spec_helper/specification.rb +0 -28
  37. data/spec/spec_helper/ui.rb +0 -14
  38. data/spec/state_spec.rb +0 -30
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA256:
3
- metadata.gz: bc6b96b69bd48c80f9653d4f9ec6dc89278555651dce6708d46b72d29d672f1f
4
- data.tar.gz: 79e47c90d5bd5122df464d52a578547df0b9813e91c9d222152033a214ab8642
2
+ SHA1:
3
+ metadata.gz: 9546ad44db45ffeeb600e30f638fb9210cf6c961
4
+ data.tar.gz: de98b81edb5384a6f0c25608f2809e7671a90559
5
5
  SHA512:
6
- metadata.gz: f2decb13085180919a650dcb5ded11ac64e4f3d86f5dfad349e05e434bdd425b56229f5c0aec8eefc2185a4eba88a03a5ba8ccb9faf0f1824fb59ce20c1c588d
7
- data.tar.gz: 46ab35180ece2e5b385599842fe26487114d1255298ff0a573c891a270f8d0697c9976bf15f0cc279d0288f7c17492e4dceb5f0ed7a47d1b9aa4ff2fc7de0c0c
6
+ metadata.gz: 6bf39875c6f19a858fbebe6ffd35b7e01bf5e7c45e081289bbda2020b4be8ba6229fd6b9b1629f04017165e5a9cbc1f8affb5fde1ba521670631b3fb1e091e38
7
+ data.tar.gz: 87eed61627ccbd8f4dbabdd362971e64e028354811fa7548c035749a5baf14999cc15937ba227046f5d96b90a46b8e9a7ecdd97dd8fa630bb6c420fe07ade143
@@ -0,0 +1,102 @@
1
+ # Molinillo Architecture
2
+
3
+ At the highest level, Molinillo is a dependency resolution algorithm.
4
+ You hand the `Resolver` a list of dependencies and a 'locking' `DependencyGraph`, and you get a resulting dependency graph out of that.
5
+ In order to guarantee that the list of dependencies is properly resolved, however, an algorithm is required that is smarter than just walking the list of dependencies and activating each, and its own dependencies, in turn.
6
+
7
+ ## Backtracking
8
+
9
+ At the heart of Molinillo is a [backtracking](http://en.wikipedia.org/wiki/Backtracking) algorithm with [forward checking](http://en.wikipedia.org/wiki/Look-ahead_(backtracking)).
10
+ Essentially, the resolution process keeps track of two types of states (dependency and possibility) in a stack.
11
+ If that stack is ever exhausted, resolution was impossible.
12
+ New states are pushed onto the stack for every dependency, and every time a dependency is successfully 'activated' a new state is pushed onto the stack that represents that activation.
13
+ This stack-based approach is used because backtracking (also known as *unwinding*) becomes as simple as popping a state off that stack.
14
+
15
+ ### Walkthrough
16
+
17
+ 1. The client initializes a `Resolver` with a `SpecificationProvider` and `UI`
18
+ 2. The client calls `resolve` with an array of user-requested dependencies and an optional 'locking' `DependencyGraph`
19
+ 3. The `Resolver` creates a new `Resolution` with those four user-specified parameters and calls `resolve` on it
20
+ 4. The `Resolution` creates an `initial_state`, which takes the user-requested dependencies and puts them into a `DependencyState`
21
+ - In the process of creating the state, the `SpecificationProvider` is asked to sort the dependencies and return all the `possibilities` for the `initial_requirement` (taking into account whether the dependency is `locked`). These possibilities are then grouped into `PossibilitySet`s, with each set representing a group of versions for the dependency which share the same sub-dependency requirements
22
+ - A `DependencyGraph` is created that has all of these requirements point to `root_vertices`
23
+ 5. The resolution process now enters its main loop, which continues as long as there is a current `state` to process, and the current state has requirements left to process
24
+ 6. `UI#indicate_progress` is called to allow the client to report progress
25
+ 7. If the current state is a `DependencyState`, we have it pop off a `PossibilityState` that encapsulates a `PossibilitySet` for that dependency
26
+ 8. Process the topmost state on the stack
27
+ 9. If there is a non-empty `PossibilitySet` for the state, `attempt_to_activate` it (jump to #11)
28
+ 10. If there is no non-empty `PossibilitySet` for the state, `create_conflict` if the state is a `PossibilityState`, and then `unwind_for_conflict`
29
+ - `create_conflict` builds a `Conflict` object, with details of all of the requirements for the given dependency, and adds it to a hash of conflicts stored on the `state`, indexed by the name of the dependency
30
+ - `unwind_for_conflict` loops through all the conflicts on the `state`, looking for a state it can rewind to that might avoid that conflict. If no such state exists, it raises a VersionConflict error. Otherwise, it takes the most recent state with a chance to avoid the current conflicts and rewinds to it (go to #6)
31
+ 11. Check if there is an existing vertex in the `activated` dependency graph for the dependency this state's `requirement` relates to
32
+ 12. If there is no existing vertex in the `activated` dependency graph for the dependency this state's `requirement` relates to, `activate_new_spec`. This creates a new vertex in the `activated` dependency graph, with it's payload set to the possibility's `PossibilitySet`. It also pushes a new `DependencyState`, with the now-activated `PossibilitySet`'s own dependencies. Go to #6
33
+ 13. If there is an existing, `activated` vertex for the dependency, `attempt_to_filter_existing_spec`
34
+ - This filters the contents of the existing vertex's `PossibilitySet` by the current state's `requirement`
35
+ - If any possibilities remain within the `PossibilitySet`, it updates the activated vertex's payload with the new, filtered state and pushes a new `DependencyState`
36
+ - If no possibilities remain within the `PossibilitySet` after filtering, or if the current state's `PossibilitySet` had a different set of sub-dependecy requirements to the existing vertex's `PossibilitySet`, `create_conflict` and `unwind_for_conflict`, back to the last `DependencyState` that has a chance to not generate a conflict. Go to #6
37
+ 15. Terminate with the topmost state's dependency graph when there are no more requirements left
38
+ 16. For each vertex with a payload of allowable versions for this resolution (i.e., a `PossibilitySet`), pick a single specific version.
39
+
40
+ ### Optimal unwinding
41
+
42
+ For our backtracking algorithm to be efficient as well as correct, we need to
43
+ unwind efficiently after a conflict is encountered. Unwind too far and we'll
44
+ miss valid resolutions - once we unwind passed a DependencyState we can never
45
+ get there again. Unwind too little and resolution will be extremely slow - we'll
46
+ repeatedly hit the same conflict, processing many unnecessary iterations before
47
+ getting to a branch that avoids it.
48
+
49
+ To unwind the optimal amount, we consider the current conflict, along with all
50
+ the previous unwinds that have determined our current state.
51
+
52
+ 1. First, consider the current conflict as follows:
53
+ - Find the earliest (lowest index) set of requirements which combine to cause
54
+ the conflict. Any non-binding requirements can be ignored, as removing them
55
+ would not resolve the current onflict
56
+ - For each binding requirement, find all the alternative possibilities that
57
+ would relax the requirement:
58
+ - the requirement's DependencyState might have alternative possibilities
59
+ that would satisfy all the other requirements
60
+ - the parent of the requirement might have alternative possibilities that
61
+ would prevent the requirement existing
62
+ - the parent of the parent of the requirement might have alternative
63
+ possibilities that would prevent the parent, and thus the requirement,
64
+ from existing
65
+ - etc., etc.
66
+ - Group all of the above possibilities into an array, and pick the one with
67
+ the highest index (i.e., the smallest rewind) as our candidate rewind
68
+ 2. Next, consider any previous unwinds that were not executed (because a
69
+ different, smaller unwind was chosen instead):
70
+ - Ignore any previously unused unwinds that would now unwind further than the
71
+ highest index found in (1), if any
72
+ - For the remaining unused unwinds, check whether the unwind has a chance of
73
+ preventing us encountering the current conflict. For this to be the case, the
74
+ unwind must have been rejected in favour of an unwind to one of the states in
75
+ the current conflict's requirement tree
76
+ - If any such unwinds exist, use the one with the highest index (smallest
77
+ unwind) instead of the one found in (1)
78
+ 3a. If no possible unwind was found in (1) and (2), raise a VersionConflict
79
+ error as resolution is not possible.
80
+ 3b. Filter the state that we're unwinding to, in order to remove any
81
+ possibilities we know will result in a conflict. Consider all possible unwinds
82
+ to the chosen state (there may be several, amasssed from previous unused
83
+ unwinds for different conflicts) when doing this filtering - only
84
+ possibilities that will certainly result in *all* of those conflicts can be
85
+ filtered out as having no chance of resolution
86
+ 4. Update the list of unused unwinds:
87
+ - Add all possible unwinds for the current conflict
88
+ - Update the `requirements_unwound_to_instead` attribute on any considered
89
+ unwind that was only rejected because it had a lower index than the chosen one
90
+ - Remove all unwinds to a state greater than or equal to the chosen unwind
91
+ 5. Go to #6 in the main loop
92
+
93
+ ## Specification Provider
94
+
95
+ The `SpecificationProvider` module forms the basis for the key integration point for a client library with Molinillo.
96
+ Its methods convert the client's domain-specific model objects into concepts the resolver understands:
97
+
98
+ - Nested dependencies
99
+ - Names
100
+ - Requirement satisfaction
101
+ - Finding specifications (known internally as `possibilities`)
102
+ - Sorting dependencies (for the sake of reasonable resolver performance)
@@ -0,0 +1,352 @@
1
+ # Molinillo Changelog
2
+
3
+ ## 0.6.0 (2017-07-27)
4
+
5
+ ##### Breaking
6
+
7
+ * Objects returned by `dependencies_for` and passed to `resolve` must properly implement
8
+ both `==` and `eql?`, such that they return `true` when they exhibit the same behavior in
9
+ `requirement_satisfied_by?`.
10
+
11
+ ##### Enhancements
12
+
13
+ * Speed up dependency resolution by considering multiple possible versions of a
14
+ dependency at once, grouped by sub-dependencies. Groups are then filtered as
15
+ additional requirements are introduced. If a group's sub-dependencies cause
16
+ conflicts the entire group can be discarded, which reduces the number of
17
+ possibilities that have to be tested to find a resolution.
18
+ [Grey Baker](https://github.com/greysteil)
19
+ [Samuel Giddins](https://github.com/segiddins)
20
+ [#69](https://github.com/CocoaPods/Molinillo/pull/69)
21
+
22
+ * Check for locked requirements when generating a new state's possibilities
23
+ array, and reduce possibilities set accordingly. Reduces scope for erroneous
24
+ VersionConflict errors.
25
+ [Grey Baker](https://github.com/greysteil)
26
+ [#67](https://github.com/CocoaPods/Molinillo/pull/67)
27
+
28
+ * Add `VersionConflict#message_with_trees` for consumers who prefer a more verbose
29
+ conflict message that includes full requirement trees for all conflicts.
30
+ [Samuel Giddins](https://github.com/segiddins)
31
+
32
+ ##### Bug Fixes
33
+
34
+ * Improve unwinding by considering previous conflicts for the same dependency
35
+ when deciding which state to unwind to. Previously, prior conflicts were
36
+ stored in a hash indexed by their name, with only the most recent conflict
37
+ stored for each dependency. With this fix, Molinillo can resolve anything
38
+ that's thrown at it. 🎉
39
+ [Grey Baker](https://github.com/greysteil)
40
+ [#73](https://github.com/CocoaPods/Molinillo/pull/73)
41
+
42
+ * Only raise CircularDependency errors if they prevent resolution.
43
+ [Ian Young](https://github.com/iangreenleaf)
44
+ [Grey Baker](https://github.com/greysteil)
45
+ [#78](https://github.com/CocoaPods/Molinillo/pull/78)
46
+
47
+ * Consider additional (binding) requirements that caused a conflict when
48
+ determining which state to unwind to. Previously, in some cases Molinillo
49
+ would erroneously throw a VersionConflict error if multiple requirements
50
+ combined to cause a conflict.
51
+ [Grey Baker](https://github.com/greysteil)
52
+ [#72](https://github.com/CocoaPods/Molinillo/pull/72)
53
+
54
+ * Consider previous conflicts when determining the state to unwind to. If a
55
+ previous conflict, for a different dependency, is the reason we ended up with
56
+ the current conflict, then unwinding to a state that would not have caused
57
+ that conflict could prevent the current one, too.
58
+ [Grey Baker](https://github.com/greysteil)
59
+ [#72](https://github.com/CocoaPods/Molinillo/pull/72)
60
+
61
+
62
+ ## 0.5.7 (2017-03-03)
63
+
64
+ ##### Enhancements
65
+
66
+ * None.
67
+
68
+ ##### Bug Fixes
69
+
70
+ * Keep a stack of parents per requirement, so unwinding past a swap point that
71
+ updated the parent of the requirement works.
72
+ [Samuel Giddins](https://github.com/segiddins)
73
+ [bundler#5425](https://github.com/bundler/bundler/issues/5425)
74
+
75
+
76
+ ## 0.5.6 (2017-02-08)
77
+
78
+ ##### Enhancements
79
+
80
+ * None.
81
+
82
+ ##### Bug Fixes
83
+
84
+ * Only reset the parent of a requirement after swapping when its original parent
85
+ was the same vertex being swapped.
86
+ [Samuel Giddins](https://github.com/segiddins)
87
+ [bundler#5359](https://github.com/bundler/bundler/issues/5359)
88
+ [bundler#5362](https://github.com/bundler/bundler/issues/5362)
89
+
90
+
91
+ ## 0.5.5 (2017-01-07)
92
+
93
+ ##### Enhancements
94
+
95
+ * None.
96
+
97
+ ##### Bug Fixes
98
+
99
+ * Only remove requirements from the to-be-resolved list if there are no
100
+ activated vertices depending upon them after swapping.
101
+ [Samuel Giddins](https://github.com/segiddins)
102
+ [bundler#5294](https://github.com/bundler/bundler/issues/5294)
103
+
104
+
105
+ ## 0.5.4 (2016-11-14)
106
+
107
+ ##### Enhancements
108
+
109
+ * None.
110
+
111
+ ##### Bug Fixes
112
+
113
+ * Fix unwinding when both sides of a conflict have a common parent
114
+ requirement.
115
+ [Samuel Giddins](https://github.com/segiddins)
116
+ [bundler#5154](https://github.com/bundler/bundler/issues/5154)
117
+
118
+
119
+ ## 0.5.3 (2016-10-28)
120
+
121
+ ##### Enhancements
122
+
123
+ * None.
124
+
125
+ ##### Bug Fixes
126
+
127
+ * Fixed a regression in v0.5.2 that could cause resolution to fail after
128
+ swapping, because stale dependencies would still be in the requirements
129
+ list.
130
+ [Samuel Giddins](https://github.com/segiddins)
131
+ [#48](https://github.com/CocoaPods/Molinillo/issues/48)
132
+
133
+ * Rename `Action.name` to `Action.action_name` to avoid overriding
134
+ `Module.name`.
135
+ [Samuel Giddins](https://github.com/segiddins)
136
+ [#50](https://github.com/CocoaPods/Molinillo/issues/50)
137
+
138
+
139
+ ## 0.5.2 (2016-10-24)
140
+
141
+ ##### Enhancements
142
+
143
+ * None.
144
+
145
+ ##### Bug Fixes
146
+
147
+ * Fixed a bug where `Resolution#parent_of` would return the incorrect parent for
148
+ a dependency after swapping had occurred, resulting in resolution failing.
149
+ [Samuel Giddins](https://github.com/segiddins)
150
+ [bundler#5059](https://github.com/bundler/bundler/issues/5059)
151
+
152
+
153
+ ## 0.5.1 (2016-09-12)
154
+
155
+ ##### Enhancements
156
+
157
+ * None.
158
+
159
+ ##### Bug Fixes
160
+
161
+ * Fixed a bug where `Resolution#parent_of` would return the incorrect parent for
162
+ a dependency, resulting in resolution failing.
163
+ [Samuel Giddins](https://github.com/segiddins)
164
+ [bundler#4961](https://github.com/bundler/bundler/issues/4961)
165
+
166
+
167
+ ## 0.5.0 (2016-06-14)
168
+
169
+ ##### Enhancements
170
+
171
+ * Add an operation log to `DependencyGraph` to eliminate the need for graph
172
+ copies during dependency resolution, resulting in a 3-100x speedup and
173
+ reduction in allocations.
174
+ [Samuel Giddins](https://github.com/segiddins)
175
+ [bundler#4376](https://github.com/bundler/bundler/issues/4376)
176
+
177
+ * Remove all metaprogramming to reduce array allocation overhead and improve
178
+ discoverability.
179
+ [Samuel Giddins](https://github.com/segiddins)
180
+
181
+ ##### Bug Fixes
182
+
183
+ * None.
184
+
185
+
186
+ ## 0.4.5 (2016-04-30)
187
+
188
+ ##### Enhancements
189
+
190
+ * For performance, don't needlessly dup objects in
191
+ `Resolution#push_state_for_requirements`.
192
+ [Joe Rafaniello](https://github.com/jrafanie)
193
+
194
+ ##### Bug Fixes
195
+
196
+ * Recursively prune requirements when removing an orphan after swapping.
197
+ [Daniel DeLeo](https://github.com/danielsdeleo)
198
+ [berkshelf/solve#57](https://github.com/berkshelf/solve/issues/57)
199
+
200
+
201
+ ## 0.4.4 (2016-02-28)
202
+
203
+ ##### Bug Fixes
204
+
205
+ * Fix mutating a frozen string in `NoSuchDependencyError#message`.
206
+ [Samuel Giddins](https://github.com/segiddins)
207
+
208
+
209
+ ## 0.4.3 (2016-02-18)
210
+
211
+ ##### Enhancements
212
+
213
+ * Add frozen string literal comments to all ruby files.
214
+ [Samuel Giddins](https://github.com/segiddins)
215
+
216
+ ##### Bug Fixes
217
+
218
+ * Prune the dependency list when removing an orphan after swapping.
219
+ [Samuel Giddins](https://github.com/segiddins)
220
+ [bundler/bundler#4276](https://github.com/bundler/bundler/issues/4276)
221
+
222
+
223
+ ## 0.4.2 (2016-01-30)
224
+
225
+ ##### Bug Fixes
226
+
227
+ * Detaching a vertex correctly removes it from the list of successors of its
228
+ predecessors.
229
+ [Samuel Giddins](https://github.com/segiddins)
230
+
231
+ * Vertices orphaned after swapping dependencies are properly cleaned up from the
232
+ graph of activated specs.
233
+ [Samuel Giddins](https://github.com/segiddins)
234
+ [bundler/bundler#4198](https://github.com/bundler/bundler/issues/4198)
235
+
236
+
237
+ ## 0.4.1 (2015-12-30)
238
+
239
+ ##### Enhancements
240
+
241
+ * Ensure every API is 100% documented.
242
+ [Samuel Giddins](https://github.com/segiddins)
243
+ [#22](https://github.com/CocoaPods/Molinillo/issues/22)
244
+
245
+
246
+ ## 0.4.0 (2015-07-27)
247
+
248
+ ##### API Breaking Changes
249
+
250
+ * The `DependencyGraph` no longer treats root vertices specially, nor does it
251
+ maintain a direct reference to `edges`. Additionally, `Vertex` no longer
252
+ has a reference to its parent graph.
253
+
254
+ ##### Enhancements
255
+
256
+ * Resolution has been sped up by 25x in some pathological cases, and in general
257
+ recursive operations on a `DependencyGraph` or `Vertex` are now `O(n)`.
258
+ [Samuel Giddins](https://github.com/segiddins)
259
+ [Bundler#3803](https://github.com/bundler/bundler/issues/3803)
260
+
261
+ * Re-sorting of dependencies is skipped when the unresolved dependency list has
262
+ not changed, speeding up resolution of fully locked graphs.
263
+ [Samuel Giddins](https://github.com/segiddins)
264
+
265
+
266
+ ## 0.3.1 (2015-07-24)
267
+
268
+ ##### Enhancements
269
+
270
+ * Add `Conflict#activated_by_name` to allow even richer version conflict
271
+ messages.
272
+ [Samuel Giddins](https://github.com/segiddins)
273
+
274
+ ##### Bug Fixes
275
+
276
+ * Ensure `Conflict#requirement_trees` is exhaustive.
277
+ [Samuel Giddins](https://github.com/segiddins)
278
+ [Bundler#3860](https://github.com/bundler/bundler/issues/3860)
279
+
280
+
281
+ ## 0.3.0 (2015-06-29)
282
+
283
+ ##### Enhancements
284
+
285
+ * Add the ability to optionally skip dependencies that have no possibilities.
286
+ [Samuel Giddins](https://github.com/segiddins)
287
+
288
+
289
+ ## 0.2.3 (2015-03-28)
290
+
291
+ ##### Bug Fixes
292
+
293
+ * Silence a silly MRI warning about declaring private attributes.
294
+ [Piotr Szotkowski](https://github.com/chastell)
295
+ [Bundler#3516](https://github.com/bundler/bundler/issues/3516)
296
+ [Bundler#3525](https://github.com/bundler/bundler/issues/3525)
297
+
298
+
299
+ ## 0.2.2 (2015-03-27)
300
+
301
+ ##### Bug Fixes
302
+
303
+ * Use an ivar in `DependencyGraph#initialize_copy` to silence an MRI warning.
304
+ [Samuel Giddins](https://github.com/segiddins)
305
+ [Bundler#3516](https://github.com/bundler/bundler/issues/3516)
306
+
307
+
308
+ ## 0.2.1 (2015-02-21)
309
+
310
+ * Allow resolving some pathological cases where the backjumping algorithm would
311
+ skip over a valid possibility.
312
+ [Samuel Giddins](https://github.com/segiddins)
313
+
314
+
315
+ ## 0.2.0 (2014-12-25)
316
+
317
+ * Institute stricter forward checking by backjumping to the source of a
318
+ conflict, even if that source comes from the existing spec. This further
319
+ improves performance in highly conflicting situations when sorting heuristics
320
+ prove misleading.
321
+ [Samuel Giddins](https://github.com/segiddins)
322
+ [Smit Shah](https://github.com/Who828)
323
+
324
+ * Add support for topologically sorting a dependency graph's vertices.
325
+ [Samuel Giddins](https://github.com/segiddins)
326
+
327
+
328
+ ## 0.1.2 (2014-11-19)
329
+
330
+ ##### Enhancements
331
+
332
+ * Improve performance in highly conflicting situations by backtracking more than
333
+ one state at a time.
334
+ [Samuel Giddins](https://github.com/segiddins)
335
+
336
+ ##### Bug Fixes
337
+
338
+ * Ensure that recursive invocations of `detach_vertex_named` don't lead to
339
+ messaging `nil`.
340
+ [Samuel Giddins](https://github.com/segiddins)
341
+ [CocoaPods#2805](https://github.com/CocoaPods/CocoaPods/issues/2805)
342
+
343
+ ## 0.1.1 (2014-11-06)
344
+
345
+ * Ensure that an unwanted exception is not raised when an error occurs before
346
+ the initial state has been pushed upon the stack.
347
+ [Samuel Giddins](https://github.com/segiddins)
348
+
349
+ ## 0.1.0 (2014-10-26)
350
+
351
+ * Initial release.
352
+ [Samuel Giddins](https://github.com/segiddins)