Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/.shards.info
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ version: 1.0
shards:
molinillo:
git: https://github.com/crystal-lang/crystal-molinillo.git
version: 0.2.0
version: 0.2.2
31 changes: 20 additions & 11 deletions lib/molinillo/.github/workflows/crystal.yml
Original file line number Diff line number Diff line change
@@ -1,18 +1,27 @@
name: Crystal CI

on: [push]
on: [push, pull_request]

jobs:
build:
test:
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest]
crystal: [latest, nightly]
runs-on: ${{ matrix.os }}

runs-on: ubuntu-latest
steps:
- name: Install Crystal
uses: crystal-lang/install-crystal@v1
with:
crystal: ${{ matrix.crystal }}

container:
image: crystallang/crystal
- name: Download source
uses: actions/checkout@v3

steps:
- uses: actions/checkout@v6
- name: Install dependencies
run: shards install
- name: Run tests
run: crystal spec
- name: Install dependencies
run: shards install

- name: Run specs
run: crystal spec
6 changes: 0 additions & 6 deletions lib/molinillo/.travis.yml

This file was deleted.

29 changes: 13 additions & 16 deletions lib/molinillo/LICENSE
Original file line number Diff line number Diff line change
@@ -1,22 +1,19 @@
This project is licensed under the MIT license.
MIT License

Copyright (c) 2020 Manas Technology Solutions
Copyright (c) 2014 Samuel E. Giddins segiddins@segiddins.me

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.
18 changes: 18 additions & 0 deletions lib/molinillo/LICENSES/MIT.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
MIT License

Copyright (c) <year> <copyright holders>

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.
7 changes: 7 additions & 0 deletions lib/molinillo/REUSE.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
version = 1

# All original code in this repository is licensed under MIT.
[[annotations]]
path = ["**"]
SPDX-FileCopyrightText = "Copyright 2020 Manas Technology Solutions."
SPDX-License-Identifier = "MIT"
2 changes: 1 addition & 1 deletion lib/molinillo/shard.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: molinillo
version: 0.2.0
version: 0.2.2

authors:
- Juan Wajnerman <waj@manas.tech>
Expand Down
2 changes: 1 addition & 1 deletion lib/molinillo/spec/dependency_graph/log_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ end

describe Molinillo::DependencyGraph::Log do
describe "with empty log" do
shared_examples_for_replay ->(g : DG) {}
shared_examples_for_replay ->(_g : DG) { }
end

describe "with some graph" do
Expand Down
2 changes: 1 addition & 1 deletion lib/molinillo/spec/spec_helper/index.cr
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ module Molinillo
lines = File.read_lines(FIXTURE_INDEX_DIR / (fixture_name + ".json"))
lines = lines.map { |line| line.partition("//")[0] }
Hash(String, Array(TestSpecification)).from_json(lines.join '\n').tap do |all_specs|
all_specs.each do |name, specs|
all_specs.each do |_name, specs|
specs.sort! { |a, b| Shards::Versions.compare(b.version, a.version) }
end
end
Expand Down
28 changes: 14 additions & 14 deletions lib/molinillo/spec/spec_helper/specification.cr
Original file line number Diff line number Diff line change
Expand Up @@ -20,23 +20,23 @@ module Molinillo

module DepConverter
def self.from_json(parser)
deps =
if parser.kind.begin_object?
Hash(String, String).new(parser)
else
Hash(String, String).new.tap do |deps|
parser.read_array do
parser.read_begin_array
key = parser.read_string
value = parser.read_string
parser.read_end_array
deps[key] = value
end
end
if parser.kind.begin_object?
deps = Hash(String, String).new(parser)
else
deps = Hash(String, String).new

parser.read_array do
parser.read_begin_array
key = parser.read_string
value = parser.read_string
parser.read_end_array

deps[key] = value
end
end

deps.map do |name, requirement|
requirements = requirement.split(',').map(&.chomp)
requirements = requirement.split(',').map!(&.chomp)
Gem::Dependency.new(name, requirements).as(Gem::Dependency | TestSpecification)
end
end
Expand Down
2 changes: 1 addition & 1 deletion lib/molinillo/spec/spec_helper/versions.cr
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ module Shards
end
end

def only_zeroes?
def only_zeroes?(&)
return if empty?
yield unless to_i? == 0

Expand Down
2 changes: 1 addition & 1 deletion lib/molinillo/src/molinillo.cr
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
module Molinillo
VERSION = "0.2.0"
VERSION = {{ `shards version "#{__DIR__}"`.chomp.stringify }}
end

require "./molinillo/**"
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ module Molinillo
# Ensures any raised {NoSuchDependencyError} has its
# {NoSuchDependencyError#required_by} set.
# @yield
private def with_no_such_dependency_error_handling
private def with_no_such_dependency_error_handling(&)
yield
rescue error : NoSuchDependencyError
if state
Expand Down
2 changes: 1 addition & 1 deletion lib/molinillo/src/molinillo/dependency_graph.cr
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ require "./dependency_graph/vertex"
class Molinillo::DependencyGraph(P, R)
# Enumerates through the vertices of the graph.
# @return [Array<Vertex>] The graph's vertices.
def each
def each(&)
# return vertices.values.each unless block_given?
vertices.values.each { |v| yield v }
end
Expand Down
2 changes: 1 addition & 1 deletion lib/molinillo/src/molinillo/dependency_graph/log.cr
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ class Molinillo::DependencyGraph::Log(P, R)

# Enumerates each action in the log
# @yield [Action]
def each
def each(&)
action = @first_action
loop do
break unless action
Expand Down
63 changes: 3 additions & 60 deletions lib/molinillo/src/molinillo/errors.cr
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ module Molinillo
# The error message for the missing dependency, including the specifications
# that had this dependency.
def message
sources = required_by.map { |r| "`#{r}`" }.join(" and ")
sources = required_by.join(" and ") { |r| "`#{r}`" }
message = "Unable to find a specification for `#{dependency}`"
message += " depended upon by #{sources}" unless sources.empty?
message
Expand All @@ -45,7 +45,7 @@ module Molinillo
# @param [Array<DependencyGraph::Vertex>] vertices the vertices in the dependency
# that caused the error
def initialize(@vertices)
super "There is a circular dependency between #{vertices.map(&.name).join(" and ")}"
super "There is a circular dependency between #{vertices.join(" and ", &.name)}"
# @dependencies = vertices.map { |vertex| vertex.payload.possibilities.last }.to_set
end
end
Expand Down Expand Up @@ -74,69 +74,12 @@ module Molinillo
end

super "Unable to satisfy the following requirements:\n\n" \
"#{pairs.map { |r, d| "- `#{r}` required by `#{d}`" }.join("\n")}"
"#{pairs.join('\n') { |r, d| "- `#{r}` required by `#{d}`" }}"

@conflicts = conflicts
@specification_provider = specification_provider
end

include Delegates::SpecificationProvider

# @return [String] An error message that includes requirement trees,
# which is much more detailed & customizable than the default message
# @param [Hash] opts the options to create a message with.
# @option opts [String] :solver_name The user-facing name of the solver
# @option opts [String] :possibility_type The generic name of a possibility
# @option opts [Proc] :reduce_trees A proc that reduced the list of requirement trees
# @option opts [Proc] :printable_requirement A proc that pretty-prints requirements
# @option opts [Proc] :additional_message_for_conflict A proc that appends additional
# messages for each conflict
# @option opts [Proc] :version_for_spec A proc that returns the version number for a
# possibility
def message_with_trees(opts = {} of Symbol => String)
solver_name = opts.delete(:solver_name) { self.class.name.split("::").first }
possibility_type = opts.delete(:possibility_type) { "possibility named" }
reduce_trees = opts.delete(:reduce_trees) { proc { |trees| trees.uniq.sort_by(&:to_s) } }
printable_requirement = opts.delete(:printable_requirement) { proc { |req| req.to_s } }
additional_message_for_conflict = opts.delete(:additional_message_for_conflict) { proc { } }
version_for_spec = opts.delete(:version_for_spec) { proc(&:to_s) }
incompatible_version_message_for_conflict = opts.delete(:incompatible_version_message_for_conflict) do
proc do |name, _conflict|
%(#{solver_name} could not find compatible versions for #{possibility_type} "#{name}":)
end
end

conflicts.sort.reduce("".dup) do |o, (name, conflict)|
o << "\n" << incompatible_version_message_for_conflict.call(name, conflict) << "\n"
if conflict.locked_requirement
o << %( In snapshot (#{name_for_locking_dependency_source}):\n)
o << %( #{printable_requirement.call(conflict.locked_requirement)}\n)
o << %(\n)
end
o << %( In #{name_for_explicit_dependency_source}:\n)
trees = reduce_trees.call(conflict.requirement_trees)

o << trees.map do |tree|
t = "".dup
depth = 2
tree.each do |req|
t << " " * depth << req.to_s
unless tree.last == req
if spec = conflict.activated_by_name[name_for(req)]
t << %( was resolved to #{version_for_spec.call(spec)}, which)
end
t << %( depends on)
end
t << %(\n)
depth += 1
end
t
end.join("\n")

additional_message_for_conflict.call(o, name, conflict)

o
end.strip
end
end
end
2 changes: 1 addition & 1 deletion lib/molinillo/src/molinillo/modules/ui.cr
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ module Molinillo
#
# @param [Integer] depth the current depth of the resolution process.
# @return [void]
def debug(depth = 0)
def debug(depth = 0, &)
if debug?
debug_info = yield
debug_info = debug_info.inspect unless debug_info.is_a?(String)
Expand Down
27 changes: 16 additions & 11 deletions lib/molinillo/src/molinillo/resolution.cr
Original file line number Diff line number Diff line change
Expand Up @@ -131,10 +131,10 @@ module Molinillo
# non-primary unwinds
def sub_dependencies_to_avoid
@requirements_to_avoid ||=
requirement_trees.map do |tree|
requirement_trees.compact_map do |tree|
index = tree.index(state_requirement)
tree[index + 1] if index
end.compact
end
end

@all_requirements : Array(R)?
Expand Down Expand Up @@ -228,11 +228,16 @@ module Molinillo

private def resolve_activated_specs
activated.vertices.each do |_, vertex|
next unless payload = vertex.payload

latest_version = check_possibility_set(vertex).possibilities.reverse_each.find do |possibility|
vertex.requirements.all? { |req| requirement_satisfied_by?(req, activated, possibility) }
end
next unless vertex.payload

latest_version = check_possibility_set(vertex)
.possibilities
.reverse_each
.find do |possibility|
vertex.requirements.all? do |req|
requirement_satisfied_by?(req, activated, possibility)
end
end

activated.set_payload(vertex.name, latest_version)
end
Expand Down Expand Up @@ -324,7 +329,7 @@ module Molinillo
private def raise_error_unless_state(conflicts)
return if state

error = conflicts.values.map(&.underlying_error).compact.first?
error = conflicts.values.compact_map(&.underlying_error).first?
raise error || VersionConflict(R, S).new(conflicts, specification_provider)
end

Expand Down Expand Up @@ -498,7 +503,7 @@ module Molinillo
unwinds_to_state = unused_unwind_options.select { |uw| uw.state_index == unwind_details.state_index }
unwinds_to_state << unwind_details

primary_unwinds = unwinds_to_state.select(&.unwinding_to_primary_requirement?).uniq
primary_unwinds = unwinds_to_state.select(&.unwinding_to_primary_requirement?).uniq!
parent_unwinds = unwinds_to_state.uniq - primary_unwinds

allowed_possibility_sets = primary_unwinds.flat_map do |unwind|
Expand All @@ -523,7 +528,7 @@ module Molinillo
private def binding_requirements_for_conflict(conflict)
return [conflict.requirement] if conflict.possibility.nil?

possible_binding_requirements = conflict.requirements.values.flatten.uniq
possible_binding_requirements = conflict.requirements.values.flatten.uniq!

# When there’s a `CircularDependency` error the conflicting requirement
# (the one causing the circular) won’t be `conflict.requirement`
Expand Down Expand Up @@ -669,7 +674,7 @@ module Molinillo
# @param [Integer] depth the depth of the {#states} stack
# @param [Proc] block a block that yields a {#to_s}
# @return [void]
private def debug(depth = 0)
private def debug(depth = 0, &)
resolver_ui.debug(depth) { yield }
end

Expand Down
2 changes: 1 addition & 1 deletion shard.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@ version: 2.0
shards:
molinillo:
git: https://github.com/crystal-lang/crystal-molinillo.git
version: 0.2.0
version: 0.2.2