Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fork maint #154

Closed
wants to merge 20 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
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: 2 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
name: CI
on:
pull_request:
merge_group:
push:
branches: [ release, dev ]
schedule: [ cron: "0 6 * * 4" ]
Expand Down Expand Up @@ -103,6 +104,7 @@ jobs:
check_commit_conventions:
name: Commit messages follow project guidelines
runs-on: ubuntu-latest
if: github.event_name != 'pull_request' || github.event.action == 'enqueued'
steps:
- uses: actions/checkout@v2
with:
Expand Down
40 changes: 40 additions & 0 deletions .github/workflows/permaref.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Automatically creates a tag for each commit to `main` so when we rebase
# changes on top of the upstream, we retain permanent references to each
# previous commit so they are not orphaned and eventually deleted.
name: Create permanent reference

on:
push:
branches:
- "main"

jobs:
release:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3

- name: Get the permanent ref number
id: get_version
run: |
# Enable pipefail so git command failures do not result in null versions downstream
set -x

echo ::set-output name=LAST_PERMA_NUMBER::$(\
git ls-remote --tags --refs --sort="v:refname" \
https://github.com/zanieb/pubgrub.git | grep "tags/perma-" | tail -n1 | sed 's/.*\/perma-//' \
)

- name: Configure Git
run: |
git config user.name "$GITHUB_ACTOR"
git config user.email "$GITHUB_ACTOR@users.noreply.github.com"

- name: Create and push the new tag
run: |
TAG="perma-$((LAST_PERMA_NUMBER + 1))"
git tag -a "$TAG" -m "Automatically created on push to `main`"
git push origin "$TAG"
env:
LAST_PERMA_NUMBER: ${{ steps.get_version.outputs.LAST_PERMA_NUMBER }}
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ The gist of it is:

#### Added

- Links to code items in the code documenation.
- Links to code items in the code documentation.
- New `"serde"` feature that allows serializing some library types, useful for making simple reproducible bug reports.
- New variants for `error::PubGrubError` which are `DependencyOnTheEmptySet`,
`SelfDependency`, `ErrorChoosingPackageVersion` and `ErrorInShouldCancel`.
Expand Down
6 changes: 5 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ authors = [
"Alex Tokarev <aleksator@gmail.com>",
"Jacob Finkelman <Eh2406@wayne.edu>",
]
edition = "2018"
edition = "2021"
description = "PubGrub version solving algorithm"
readme = "README.md"
repository = "https://github.com/pubgrub-rs/pubgrub"
Expand All @@ -20,15 +20,19 @@ include = ["Cargo.toml", "LICENSE", "README.md", "src/**", "tests/**", "examples
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
indexmap = "2.0.2"
priority-queue = "1.1.1"
thiserror = "1.0"
rustc-hash = "1.1.0"
serde = { version = "1.0", features = ["derive"], optional = true }
log = "0.4.14" # for debug logs in tests

[dev-dependencies]
proptest = "0.10.1"
ron = "0.6"
varisat = "0.2.2"
criterion = "0.3"
env_logger = "0.9.0"

[[bench]]
name = "large_case"
Expand Down
17 changes: 10 additions & 7 deletions benches/large_case.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,19 @@ extern crate criterion;
use self::criterion::*;

use pubgrub::package::Package;
use pubgrub::range::Range;
use pubgrub::solver::{resolve, OfflineDependencyProvider};
use pubgrub::version::{NumberVersion, SemanticVersion, Version};
use pubgrub::version::{NumberVersion, SemanticVersion};
use pubgrub::version_set::VersionSet;
use serde::de::Deserialize;
use std::hash::Hash;

fn bench<'a, P: Package + Deserialize<'a>, V: Version + Hash + Deserialize<'a>>(
fn bench<'a, P: Package + Deserialize<'a>, VS: VersionSet + Deserialize<'a>>(
b: &mut Bencher,
case: &'a str,
) {
let dependency_provider: OfflineDependencyProvider<P, V> = ron::de::from_str(&case).unwrap();
) where
<VS as VersionSet>::V: Deserialize<'a>,
{
let dependency_provider: OfflineDependencyProvider<P, VS> = ron::de::from_str(&case).unwrap();

b.iter(|| {
for p in dependency_provider.packages() {
Expand All @@ -35,11 +38,11 @@ fn bench_nested(c: &mut Criterion) {
let data = std::fs::read_to_string(&case).unwrap();
if name.ends_with("u16_NumberVersion.ron") {
group.bench_function(name, |b| {
bench::<u16, NumberVersion>(b, &data);
bench::<u16, Range<NumberVersion>>(b, &data);
});
} else if name.ends_with("str_SemanticVersion.ron") {
group.bench_function(name, |b| {
bench::<&str, SemanticVersion>(b, &data);
bench::<&str, Range<SemanticVersion>>(b, &data);
});
}
}
Expand Down
30 changes: 16 additions & 14 deletions examples/branching_error_reporting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,51 +6,53 @@ use pubgrub::report::{DefaultStringReporter, Reporter};
use pubgrub::solver::{resolve, OfflineDependencyProvider};
use pubgrub::version::SemanticVersion;

type SemVS = Range<SemanticVersion>;

// https://github.com/dart-lang/pub/blob/master/doc/solver.md#branching-error-reporting
fn main() {
let mut dependency_provider = OfflineDependencyProvider::<&str, SemanticVersion>::new();
let mut dependency_provider = OfflineDependencyProvider::<&str, SemVS>::new();
#[rustfmt::skip]
// root 1.0.0 depends on foo ^1.0.0
dependency_provider.add_dependencies(
"root", (1, 0, 0),
vec![("foo", Range::between((1, 0, 0), (2, 0, 0)))],
[("foo", Range::from_range_bounds((1, 0, 0)..(2, 0, 0)))],
);
#[rustfmt::skip]
// foo 1.0.0 depends on a ^1.0.0 and b ^1.0.0
dependency_provider.add_dependencies(
"foo", (1, 0, 0),
vec![
("a", Range::between((1, 0, 0), (2, 0, 0))),
("b", Range::between((1, 0, 0), (2, 0, 0))),
[
("a", Range::from_range_bounds((1, 0, 0)..(2, 0, 0))),
("b", Range::from_range_bounds((1, 0, 0)..(2, 0, 0))),
],
);
#[rustfmt::skip]
// foo 1.1.0 depends on x ^1.0.0 and y ^1.0.0
dependency_provider.add_dependencies(
"foo", (1, 1, 0),
vec![
("x", Range::between((1, 0, 0), (2, 0, 0))),
("y", Range::between((1, 0, 0), (2, 0, 0))),
[
("x", Range::from_range_bounds((1, 0, 0)..(2, 0, 0))),
("y", Range::from_range_bounds((1, 0, 0)..(2, 0, 0))),
],
);
#[rustfmt::skip]
// a 1.0.0 depends on b ^2.0.0
dependency_provider.add_dependencies(
"a", (1, 0, 0),
vec![("b", Range::between((2, 0, 0), (3, 0, 0)))],
[("b", Range::from_range_bounds((2, 0, 0)..(3, 0, 0)))],
);
// b 1.0.0 and 2.0.0 have no dependencies.
dependency_provider.add_dependencies("b", (1, 0, 0), vec![]);
dependency_provider.add_dependencies("b", (2, 0, 0), vec![]);
dependency_provider.add_dependencies("b", (1, 0, 0), []);
dependency_provider.add_dependencies("b", (2, 0, 0), []);
#[rustfmt::skip]
// x 1.0.0 depends on y ^2.0.0.
dependency_provider.add_dependencies(
"x", (1, 0, 0),
vec![("y", Range::between((2, 0, 0), (3, 0, 0)))],
[("y", Range::from_range_bounds((2, 0, 0)..(3, 0, 0)))],
);
// y 1.0.0 and 2.0.0 have no dependencies.
dependency_provider.add_dependencies("y", (1, 0, 0), vec![]);
dependency_provider.add_dependencies("y", (2, 0, 0), vec![]);
dependency_provider.add_dependencies("y", (1, 0, 0), []);
dependency_provider.add_dependencies("y", (2, 0, 0), []);

// Run the algorithm.
match resolve(&dependency_provider, "root", (1, 0, 0)) {
Expand Down
46 changes: 29 additions & 17 deletions examples/caching_dependency_provider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,21 @@ use std::error::Error;
use pubgrub::package::Package;
use pubgrub::range::Range;
use pubgrub::solver::{resolve, Dependencies, DependencyProvider, OfflineDependencyProvider};
use pubgrub::version::{NumberVersion, Version};
use pubgrub::version::NumberVersion;
use pubgrub::version_set::VersionSet;

type NumVS = Range<NumberVersion>;

// An example implementing caching dependency provider that will
// store queried dependencies in memory and check them before querying more from remote.
struct CachingDependencyProvider<P: Package, V: Version, DP: DependencyProvider<P, V>> {
struct CachingDependencyProvider<P: Package, VS: VersionSet, DP: DependencyProvider<P, VS>> {
remote_dependencies: DP,
cached_dependencies: RefCell<OfflineDependencyProvider<P, V>>,
cached_dependencies: RefCell<OfflineDependencyProvider<P, VS>>,
}

impl<P: Package, V: Version, DP: DependencyProvider<P, V>> CachingDependencyProvider<P, V, DP> {
impl<P: Package, VS: VersionSet, DP: DependencyProvider<P, VS>>
CachingDependencyProvider<P, VS, DP>
{
pub fn new(remote_dependencies_provider: DP) -> Self {
CachingDependencyProvider {
remote_dependencies: remote_dependencies_provider,
Expand All @@ -24,22 +29,15 @@ impl<P: Package, V: Version, DP: DependencyProvider<P, V>> CachingDependencyProv
}
}

impl<P: Package, V: Version, DP: DependencyProvider<P, V>> DependencyProvider<P, V>
for CachingDependencyProvider<P, V, DP>
impl<P: Package, VS: VersionSet, DP: DependencyProvider<P, VS>> DependencyProvider<P, VS>
for CachingDependencyProvider<P, VS, DP>
{
fn choose_package_version<T: std::borrow::Borrow<P>, U: std::borrow::Borrow<Range<V>>>(
&self,
packages: impl Iterator<Item = (T, U)>,
) -> Result<(T, Option<V>), Box<dyn Error>> {
self.remote_dependencies.choose_package_version(packages)
}

// Caches dependencies if they were already queried
fn get_dependencies(
&self,
package: &P,
version: &V,
) -> Result<Dependencies<P, V>, Box<dyn Error>> {
version: &VS::V,
) -> Result<Dependencies<P, VS>, Box<dyn Error + Send + Sync>> {
let mut cache = self.cached_dependencies.borrow_mut();
match cache.get_dependencies(package, version) {
Ok(Dependencies::Unknown) => {
Expand All @@ -49,7 +47,7 @@ impl<P: Package, V: Version, DP: DependencyProvider<P, V>> DependencyProvider<P,
cache.add_dependencies(
package.clone(),
version.clone(),
dependencies.clone().into_iter(),
dependencies.clone(),
);
Ok(Dependencies::Known(dependencies))
}
Expand All @@ -61,11 +59,25 @@ impl<P: Package, V: Version, DP: DependencyProvider<P, V>> DependencyProvider<P,
error @ Err(_) => error,
}
}

fn choose_version(
&self,
package: &P,
range: &VS,
) -> Result<Option<VS::V>, Box<dyn Error + Send + Sync>> {
self.remote_dependencies.choose_version(package, range)
}

type Priority = DP::Priority;

fn prioritize(&self, package: &P, range: &VS) -> Self::Priority {
self.remote_dependencies.prioritize(package, range)
}
}

fn main() {
// Simulating remote provider locally.
let mut remote_dependencies_provider = OfflineDependencyProvider::<&str, NumberVersion>::new();
let mut remote_dependencies_provider = OfflineDependencyProvider::<&str, NumVS>::new();

// Add dependencies as needed. Here only root package is added.
remote_dependencies_provider.add_dependencies("root", 1, Vec::new());
Expand Down
12 changes: 7 additions & 5 deletions examples/doc_interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,21 @@ use pubgrub::range::Range;
use pubgrub::solver::{resolve, OfflineDependencyProvider};
use pubgrub::version::NumberVersion;

type NumVS = Range<NumberVersion>;

// `root` depends on `menu` and `icons`
// `menu` depends on `dropdown`
// `dropdown` depends on `icons`
// `icons` has no dependency
#[rustfmt::skip]
fn main() {
let mut dependency_provider = OfflineDependencyProvider::<&str, NumberVersion>::new();
let mut dependency_provider = OfflineDependencyProvider::<&str, NumVS>::new();
dependency_provider.add_dependencies(
"root", 1, vec![("menu", Range::any()), ("icons", Range::any())],
"root", 1, [("menu", Range::full()), ("icons", Range::full())],
);
dependency_provider.add_dependencies("menu", 1, vec![("dropdown", Range::any())]);
dependency_provider.add_dependencies("dropdown", 1, vec![("icons", Range::any())]);
dependency_provider.add_dependencies("icons", 1, vec![]);
dependency_provider.add_dependencies("menu", 1, [("dropdown", Range::full())]);
dependency_provider.add_dependencies("dropdown", 1, [("icons", Range::full())]);
dependency_provider.add_dependencies("icons", 1, []);

// Run the algorithm.
let solution = resolve(&dependency_provider, "root", 1);
Expand Down
Loading