Skip to content

Commit

Permalink
fix: correct conditional compilation
Browse files Browse the repository at this point in the history
gix is a somewhat heavy dependency, in addition, as the atom and eka api
evolve, it will be quite possible that not all users will want or need
all possible features. It was always intended to keep the major feature
groups guarded behind features (such as store implementations), but we
sort of fell behind keeping track of that for a bit.

This commit corrects that and ensures that compilation works both with
or without features enabled.
  • Loading branch information
nrdxp committed Oct 13, 2024
1 parent c2c55b2 commit 90ab179
Show file tree
Hide file tree
Showing 20 changed files with 241 additions and 335 deletions.
19 changes: 2 additions & 17 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 6 additions & 9 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,9 +1,4 @@
workspace.members = [
"crates/atom",
"crates/config",
"crates/nixec",
"crates/resolve",
]
workspace.members = ["crates/atom", "crates/config", "crates/nixec"]

[package]
edition = "2021"
Expand Down Expand Up @@ -67,8 +62,10 @@ gix = { version = "^0.66", default-features = false, features = [
] }

[features]
default = ["git"]
git = ["gix"]
default = ["stores"]
git = ["gix", "atom/git"]
stores = ["git"]

[patch.crates-io]
gix = { git = "https://github.com/nrdxp/gitoxide", tag = "gix-v0.66.0-eka" }
gix = { git = "https://github.com/nrdxp/gitoxide", tag = "gix-v0.66.0-eka" }
gix-url = { git = "https://github.com/nrdxp/gitoxide", tag = "gix-v0.66.0-eka" }
12 changes: 10 additions & 2 deletions crates/atom/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,17 @@ thiserror.workspace = true
tokio.workspace = true
toml_edit.workspace = true
tracing.workspace = true
url.workspace = true

config = { path = "../config", features = ["git"] }
gix = { workspace = true, default-features = false, features = ["serde"] }
config = { path = "../config" }
gix = { workspace = true, default-features = false, features = [
"serde",
], optional = true }
gix-url = { version = "^0.27", features = ["serde"] }

[features]
default = []
git = ["dep:gix", "config/git"]

[dev-dependencies]
anyhow.workspace = true
Expand Down
1 change: 1 addition & 0 deletions crates/atom/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
//! point to the original commit from which the Atom's content references, ensuring
//! it remains live. Ensuring we can trivially verify an Atom's content at any time.
#![deny(missing_docs)]
#![cfg_attr(not(feature = "git"), allow(dead_code))]

mod core;
mod id;
Expand Down
45 changes: 45 additions & 0 deletions crates/atom/src/manifest/depends.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
use std::path::PathBuf;

use semver::Version;
use serde::{Deserialize, Serialize};
use url::Url;

#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
enum AtomSrc {
Url(Url),
Path(PathBuf),
}

/// atom dependencies
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
pub struct Dependencies {
version: Version,
src: AtomSrc,
}

/// legacy pins
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
pub struct Pins {
url: Url,
}

/// sources fetched at build time
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
pub struct Srcs {
url: Url,
}

impl AtomSrc {
pub(crate) fn url(self) -> Option<Url> {
match self {
AtomSrc::Url(url) => Some(url),
_ => None,
}
}
pub(crate) fn path(self) -> Option<PathBuf> {
match self {
AtomSrc::Path(path) => Some(path),
_ => None,
}
}
}
194 changes: 100 additions & 94 deletions crates/atom/src/publish/error.rs
Original file line number Diff line number Diff line change
@@ -1,112 +1,118 @@
//! # Publishing Errors
//!
//! This module contains the error types for errors that might occur during publishing.
use crate::store::git::Root;
use gix::object;
use std::path::PathBuf;
use thiserror::Error;

#[derive(Error, Debug)]
/// The error representing a failure during publishing for any store implementation.
pub enum PublishError {
#[cfg(feature = "git")]
/// A transparent wrapper for a [`GitError`].
#[error(transparent)]
Git(#[from] GitError),
Git(#[from] git::Error),
}

/// An error representing a failure during publishing to a Git Ekala store.
#[derive(Error, Debug)]
pub enum GitError {
/// A transparent wrapper for a [`Box<gix::remote::find::existing::Error>`]
#[error(transparent)]
RemotNotFound(#[from] Box<gix::remote::find::existing::Error>),
/// A transparent wrapper for a [`Box<gix::revision::spec::parse::single::Error>`]
#[error(transparent)]
RevParseFailed(#[from] Box<gix::revision::spec::parse::single::Error>),
/// A transparent wrapper for a [`object::find::existing::with_conversion::Error`]
#[error(transparent)]
NoCommit(#[from] object::find::existing::with_conversion::Error),
/// A transparent wrapper for a [`object::commit::Error`]
#[error(transparent)]
NoTree(#[from] object::commit::Error),
/// A transparent wrapper for a [`object::find::existing::Error`]
#[error(transparent)]
NoObject(#[from] object::find::existing::Error),
/// A transparent wrapper for a [`object::write::Error`]
#[error(transparent)]
WriteFailed(#[from] object::write::Error),
/// A transparent wrapper for a [`gix::reference::edit::Error`]
#[error(transparent)]
RefUpdateFailed(#[from] gix::reference::edit::Error),
/// A transparent wrapper for a [`gix::revision::walk::Error`]
#[error(transparent)]
CalculatingRootFailed(#[from] gix::revision::walk::Error),
/// A transparent wrapper for a [`gix::traverse::commit::simple::Error`]
#[error(transparent)]
RootConversionFailed(#[from] gix::traverse::commit::simple::Error),
/// A transparent wrapper for a [`std::io::Error`]
#[error(transparent)]
Io(#[from] std::io::Error),
/// A transparent wrapper for a [`tokio::task::JoinError`]
#[error(transparent)]
JoinFailed(#[from] tokio::task::JoinError),
/// The reported root & the atom root are inconsistent.
#[error("Atom does not derive from the initialized history")]
InconsistentRoot {
/// The root according to the remote we are publishing to.
remote: Root,
/// The root of history for the source from which the atom is derived.
atom: Root,
},
/// The remote is not initialized as an Ekala store.
#[error("Remote is not initialized")]
NotInitialized,
/// The Atom manifest is invalid, and this Atom will be ignored.
#[error("Ignoring invalid Atom manifest")]
Invalid(#[source] crate::manifest::AtomError, Box<PathBuf>),
/// The path given does not point to an Atom.
#[error("The given path does not point to an Atom")]
NotAnAtom(PathBuf),
/// Failed to sync a least one Atom to the remote.
#[error("Failed to sync some Atoms to the remote")]
SomePushFailed,
/// Some Atoms failed to publish
#[error("Failed to published some of the specified Atoms")]
Failed,
/// A transparent wrapper for a [`crate::store::git::Error`]
#[error(transparent)]
StoreError(#[from] crate::store::git::Error),
/// No Atoms found under the given directory.
#[error("Failed to find any Atoms under the current directory")]
NotFound,
/// Atoms with the same Unicode ID were found in the given revision.
#[error("Duplicate Atoms detected in the given revision, refusing to publish")]
Duplicates,
}
#[cfg(feature = "git")]
pub mod git {
//! # Git Publishing Errors
use crate::store::git::Root;
use gix::object;
use std::path::PathBuf;
/// An error representing a failure during publishing to a Git Ekala store.
#[derive(thiserror::Error, Debug)]
pub enum Error {
/// A transparent wrapper for a [`Box<gix::remote::find::existing::Error>`]
#[error(transparent)]
RemotNotFound(#[from] Box<gix::remote::find::existing::Error>),
/// A transparent wrapper for a [`Box<gix::revision::spec::parse::single::Error>`]
#[error(transparent)]
RevParseFailed(#[from] Box<gix::revision::spec::parse::single::Error>),
/// A transparent wrapper for a [`object::find::existing::with_conversion::Error`]
#[error(transparent)]
NoCommit(#[from] object::find::existing::with_conversion::Error),
/// A transparent wrapper for a [`object::commit::Error`]
#[error(transparent)]
NoTree(#[from] object::commit::Error),
/// A transparent wrapper for a [`object::find::existing::Error`]
#[error(transparent)]
NoObject(#[from] object::find::existing::Error),
/// A transparent wrapper for a [`object::write::Error`]
#[error(transparent)]
WriteFailed(#[from] object::write::Error),
/// A transparent wrapper for a [`gix::reference::edit::Error`]
#[error(transparent)]
RefUpdateFailed(#[from] gix::reference::edit::Error),
/// A transparent wrapper for a [`gix::revision::walk::Error`]
#[error(transparent)]
CalculatingRootFailed(#[from] gix::revision::walk::Error),
/// A transparent wrapper for a [`gix::traverse::commit::simple::Error`]
#[error(transparent)]
RootConversionFailed(#[from] gix::traverse::commit::simple::Error),
/// A transparent wrapper for a [`std::io::Error`]
#[error(transparent)]
Io(#[from] std::io::Error),
/// A transparent wrapper for a [`tokio::task::JoinError`]
#[error(transparent)]
JoinFailed(#[from] tokio::task::JoinError),
/// The reported root & the atom root are inconsistent.
#[error("Atom does not derive from the initialized history")]
InconsistentRoot {
/// The root according to the remote we are publishing to.
remote: Root,
/// The root of history for the source from which the atom is derived.
atom: Root,
},
/// The remote is not initialized as an Ekala store.
#[error("Remote is not initialized")]
NotInitialized,
/// The Atom manifest is invalid, and this Atom will be ignored.
#[error("Ignoring invalid Atom manifest")]
Invalid(#[source] crate::manifest::AtomError, Box<PathBuf>),
/// The path given does not point to an Atom.
#[error("The given path does not point to an Atom")]
NotAnAtom(PathBuf),
/// Failed to sync a least one Atom to the remote.
#[error("Failed to sync some Atoms to the remote")]
SomePushFailed,
/// Some Atoms failed to publish
#[error("Failed to published some of the specified Atoms")]
Failed,
/// A transparent wrapper for a [`crate::store::git::Error`]
#[error(transparent)]
StoreError(#[from] crate::store::git::Error),
/// No Atoms found under the given directory.
#[error("Failed to find any Atoms under the current directory")]
NotFound,
/// Atoms with the same Unicode ID were found in the given revision.
#[error("Duplicate Atoms detected in the given revision, refusing to publish")]
Duplicates,
}

impl GitError {
const INCONSISTENT_ROOT_SUGGESTION: &str =
"You may need to reinitalize the remote if the issue persists";
#[cfg(feature = "git")]
impl Error {
const INCONSISTENT_ROOT_SUGGESTION: &str =
"You may need to reinitalize the remote if the issue persists";

/// Warn the user about specific error conditions encountered during publishing.
pub fn warn(&self) {
match self {
GitError::InconsistentRoot { remote, atom } => {
tracing::warn!(
message = %self,
atom_root = %**atom,
remote_root = %**remote,
suggest = GitError::INCONSISTENT_ROOT_SUGGESTION
);
}
GitError::Invalid(e, path) => {
tracing::warn!(message = %self, path = %path.display(), message = format!("\n{}", e));
}
GitError::NotAnAtom(path) => {
tracing::warn!(message = %self, path = %path.display());
/// Warn the user about specific error conditions encountered during publishing.
pub fn warn(&self) {
match self {
Error::InconsistentRoot { remote, atom } => {
tracing::warn!(
message = %self,
atom_root = %**atom,
remote_root = %**remote,
suggest = Error::INCONSISTENT_ROOT_SUGGESTION
);
}
Error::Invalid(e, path) => {
tracing::warn!(message = %self, path = %path.display(), message = format!("\n{}", e));
}
Error::NotAnAtom(path) => {
tracing::warn!(message = %self, path = %path.display());
}
Error::Failed => (),
_ => tracing::warn!(message = %self),
}
GitError::Failed => (),
_ => tracing::warn!(message = %self),
}
}
}
10 changes: 5 additions & 5 deletions crates/atom/src/publish/git/inner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use super::{
};
use crate::{
core::AtomPaths,
publish::{error::GitError, ATOM_ORIGIN},
publish::{error::git::Error, ATOM_ORIGIN},
store::git,
Atom, AtomId, Manifest,
};
Expand Down Expand Up @@ -33,7 +33,7 @@ impl<'a> GitContext<'a> {
Ok(content)
})?;

Manifest::get_atom(&content).map_err(|e| GitError::Invalid(e, Box::new(path.into())))
Manifest::get_atom(&content).map_err(|e| Error::Invalid(e, Box::new(path.into())))
}

/// Compute the [`ObjectId`] of the given proto-object in memory
Expand Down Expand Up @@ -74,10 +74,10 @@ impl<'a> GitContext<'a> {
let paths = AtomPaths::new(path);
let entry = self
.tree_search(paths.spec())?
.ok_or(GitError::NotAnAtom(path.into()))?;
.ok_or(Error::NotAnAtom(path.into()))?;

if !entry.mode().is_blob() {
return Err(GitError::NotAnAtom(path.into()));
return Err(Error::NotAnAtom(path.into()));
}

let lock = self
Expand All @@ -92,7 +92,7 @@ impl<'a> GitContext<'a> {
.and_then(|spec| {
let id = AtomId::compute(&self.commit, spec.id.clone())?;
if self.root != *id.root() {
return Err(GitError::InconsistentRoot {
return Err(Error::InconsistentRoot {
remote: self.root,
atom: *id.root(),
});
Expand Down
Loading

0 comments on commit 90ab179

Please sign in to comment.