Skip to content
Closed
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
5 changes: 3 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/target
.pre-commit-config.yaml
.direnv
.pre-commit-config.yaml
readme
/result
/target
/test
4 changes: 3 additions & 1 deletion src/channel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
//!
//! This should be preferred over pinning the equivaleng `nixpkgs` git branch.

use crate::*;
use crate::{build_client, diff, nix, Updatable};
use anyhow::Result;
use serde::{Deserialize, Serialize};

#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, Hash)]
pub struct Pin {
Expand Down
2 changes: 1 addition & 1 deletion src/flake.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! Convert+Import Nix flake lock files

use crate::*;
use crate::{git, Pin};
use anyhow::{Context, Result};
use serde::{Deserialize, Serialize};
use std::convert::TryFrom;
Expand Down
2 changes: 1 addition & 1 deletion src/git.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
//! instance. This should be preferred over the generic Git API if possible. See [`Repository`]
//! for more on this.

use crate::*;
use crate::{diff, git, nix, GenericVersion, Updatable};
use anyhow::{Context, Result};
use lenient_version::Version;
use serde::{Deserialize, Serialize};
Expand Down
59 changes: 21 additions & 38 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,39 +52,20 @@ where
/// - **The serialized dictionaries of all are disjoint** (unchecked invariant at the moment)
#[async_trait::async_trait]
pub trait Updatable:
Serialize
+ Deserialize<'static>
+ std::fmt::Debug
+ Clone
+ PartialEq
+ Eq
+ std::hash::Hash
+ diff::Diff
Serialize + Deserialize<'static> + Clone + PartialEq + Eq + diff::Diff
{
/// Version information, produced by the [`update`](Self::update) method.
///
/// It should contain information that charactarizes a version, e.g. the release version.
/// It should contain information that characterizes a version, e.g. the release version.
/// A user should be able to manually specify it, if they want to pin a specific version.
/// Each version should map to the same set of hashes over time, and violations of this
/// should only be caused by upstream errors.
type Version: diff::Diff
+ Serialize
+ Deserialize<'static>
+ std::fmt::Debug
+ Clone
+ PartialEq
+ Eq;
type Version: diff::Diff + Serialize + Deserialize<'static> + Clone + PartialEq + Eq;

/// The pinned hashes for a given version, produced by the [`fetch`](Self::fetch) method.
///
/// It may contain multiple different hashes, or download URLs that go with them.
type Hashes: diff::Diff
+ Serialize
+ Deserialize<'static>
+ std::fmt::Debug
+ Clone
+ PartialEq
+ Eq;
type Hashes: diff::Diff + Serialize + Deserialize<'static> + Clone + PartialEq + Eq;

/// Fetch the latest applicable commit data
///
Expand All @@ -97,25 +78,26 @@ pub trait Updatable:

/// Create the `Pin` type
///
/// We need a type to unify over all possible way to pin a dependency. Normally, this would be done with a trait
/// and trait objects. However, designing such a trait to be object-safe turns out to be highly non-trivial.
/// (We'd need the `serde_erase` crate for `Deserialize` alone). Since writing this as an enum is extremely repetitive,
/// this macro does the work for you.
/// We need a type to unify over all possible way to pin a dependency. Normally, this would be done
/// with a trait and trait objects. However, designing such a trait to be object-safe turns out to
/// be highly non-trivial. (We'd need the `serde_erase` crate for `Deserialize` alone).
/// Since writing this as an enum is extremely repetitive, this macro does the work for you.
///
/// For each pin type, call it with `(Name, lower_name, human readable name, Type)`. `Name` will be the name of the enum variant,
/// `lower_name` will be used for the constructor.
/// For each pin type, call it with `(Name, lower_name, human readable name, Type)`.
/// `Name` will be the name of the enum variant and `lower_name` will be used for the constructor.
macro_rules! mkPin {
( $(( $name:ident, $lower_name:ident, $human_name:expr, $input_name:path )),* $(,)? ) => {
/* The type declaration */
/// Enum over all possible pin types
///
/// Every pin type has two parts, an `input` and an `output`. The input implements [`Updatable`], which
/// will generate output in its most up-to-date form.
/// Every pin type has two parts, an `input` and an `output`. The input implements
/// [`Updatable`], which will generate output in its most up-to-date form.
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
#[serde(tag = "type")]
pub enum Pin {
$(
/* One variant per type. input and output are serialized to a common JSON dict using `flatten`. Output is optional. */
/* One variant per type. input and output are serialized to a common JSON dict
* using `flatten`. Output is optional. */
$name {
#[serde(flatten)]
input: $input_name,
Expand All @@ -137,7 +119,8 @@ macro_rules! mkPin {
async fn update(&mut self) -> Result<Vec<diff::DiffEntry>> {
Ok(match self {
$(Self::$name { input, version, .. } => {
/* Use very explicit syntax to force the correct types and get good compile errors */
/* Use very explicit syntax to force the correct types and get good compile
* errors */
let new_version = <$input_name as Updatable>::update(input, version.as_ref()).await?;
version.insert_diffed(new_version)
}),*
Expand All @@ -152,7 +135,8 @@ macro_rules! mkPin {
$(Self::$name { input, version, hashes } => {
let version = version.as_ref()
.ok_or_else(|| anyhow::format_err!("No version information available, call `update` first or manually set one"))?;
/* Use very explicit syntax to force the correct types and get good compile errors */
/* Use very explicit syntax to force the correct types and get good compile
* errors */
let new_hashes = <$input_name as Updatable>::fetch(input, &version).await?;
hashes.insert_diffed(new_hashes)
}),*
Expand Down Expand Up @@ -196,7 +180,8 @@ macro_rules! mkPin {
}
}

// Each variant holds exactly one distinct type, so we can easily create convenient type wrappers that simply call the constructor
// Each variant holds exactly one distinct type, so we can easily create convenient type
// wrappers that simply call the constructor.
$(
impl From<$input_name> for Pin {
fn from(input: $input_name) -> Self {
Expand Down Expand Up @@ -226,9 +211,7 @@ mkPin! {
(Channel, channel, "Nix channel", channel::Pin),
}

/// The main struct the CLI operates on
///
/// For serialization purposes, use the `NixPinsVersioned` wrapper instead.
/// The main struct the CLI operates on. See `versions::from_value_versioned` for versioning.
#[derive(Debug, Serialize, Deserialize, Clone, Default, PartialEq, Eq)]
pub struct NixPins {
pins: BTreeMap<String, Pin>,
Expand Down
2 changes: 1 addition & 1 deletion src/niv.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! Convert+Import Niv files

use crate::*;
use crate::{git, Pin};
use anyhow::Result;
use serde::{Deserialize, Serialize};
use std::convert::TryFrom;
Expand Down
2 changes: 1 addition & 1 deletion src/pypi.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! Pin a PyPi package

use crate::*;
use crate::{diff, get_and_deserialize, GenericUrlHashes, GenericVersion, Updatable};
use anyhow::{Context, Result};
use lenient_version::Version;
use serde::{Deserialize, Serialize};
Expand Down