PubGrub in Gleam

This repository is a Gleam port of the PubGrub version solving algorithm. PubGrub finds a set of package versions that satisfy all constraints and, when it cannot, produces a human-readable explanation for the conflict.

Features

Getting started

Add this project as a dependency (local path or git) and use the public API in src/pubgrub.gleam.

The solver requires a compare function for versions and a dependency provider. An offline provider is included for tests and simple uses.

Minimal example

import gleam/dict
import gleam/order
import pubgrub
import pubgrub/version
import version_ranges as ranges

pub fn example() {
  let compare = version.compare

  let provider =
    pubgrub.offline_new()
    |> pubgrub.offline_add_dependencies("root", version.new(1, 0, 0), [
      #("foo", ranges.between(compare, version.new(1, 0, 0), version.new(2, 0, 0))),
    ])
    |> pubgrub.offline_add_dependencies("foo", version.new(1, 0, 0), [])

  let dp = pubgrub.offline_provider(provider, compare)
  let result = pubgrub.resolve(dp, "root", version.new(1, 0, 0))

  result
  |> case {
    Ok(solution) -> solution
    Error(err) -> {
      panic as "no solution"
    }
  }
}

Integration specs

The integration tests demonstrate a tiny, readable spec format:

[package-a:1.0.0]
package-b = '2.0.0'

[package-b:2.0.0]
package-c = '>= 1.0.0 and < 2.0.0'

See test/integration_resolution_test.gleam for more examples and the parser.

Ranges and comparisons

Ranges are created with an explicit compare function:

let range = ranges.between(version.compare, version.new(1, 0, 0), version.new(2, 0, 0))

This lets you use semantic versions or simple integers:

fn int_compare(a: Int, b: Int) -> order.Order {
  case a < b { True -> order.Lt False -> case a > b { True -> order.Gt False -> order.Eq } }
}

Testing

Run:

gleam test

License

Mozilla Public License 2.0

Search Document