8000 refactor(op): move init and update code into op crate by twitchyliquid64 · Pull Request #592 · gominimal/minimal · GitHub
[go: up one dir, main page]

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
1 change: 1 addition & 0 deletions Cargo.lock

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

2 changes: 1 addition & 1 deletion crates/decode/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ pub use profiles::Profile;
mod decl_tests;
pub use decl_tests::Test;
mod stacks;
pub use stacks::{Stack, StackMatcher};
pub use stacks::{PackageMatcherPredicate, Stack, StackMatcher};

// Increment for any big change to the format of build specs / stacks, so that hash
// keys get invalidated.
Expand Down
10 changes: 10 additions & 0 deletions crates/mctx/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,16 @@ impl From<graph::Error> for Error {
}
}

impl From<op::Error> for Error {
fn from(value: op::Error) -> Self {
match value {
op::Error::IO(e) => Self::IO("op", PathBuf::new(), e),
op::Error::Plan(graph, e) => Self::Plan(Box::new((graph, e))),
other => Self::Other(anyhow::anyhow!("{}", other)),
}
}
}

impl From<super::ConfigError> for Error {
fn from(value: super::ConfigError) -> Self {
Error::Config(value)
Expand Down
15 changes: 15 additions & 0 deletions crates/mctx/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ pub use mfile_search_strategy::MFileSearchStrategy;
mod scaffold;
pub use scaffold::scaffold_default_mfile;

mod project_setup;
pub use project_setup::ProjectSetup;

pub use env::Env;
use tokio::sync::Semaphore;
use toml_edit::{Array, DocumentMut, Item, TableLike, Value};
Expand Down Expand Up @@ -301,6 +304,18 @@ impl Context {
Self::new(self.config.clone())
}

/// Builds a [`ProjectSetup`] from this context, for running project-setup
/// operations (e.g. [`op::UpdateProject`]) that refresh the `minimal.toml`.
pub fn project_setup(&self) -> ProjectSetup {
ProjectSetup::from_parts(
self.config.clone(),
self.vcs.clone(),
self.stdlib_dir.clone(),
self.mfile.clone(),
self.repo_dir().to_path_buf(),
)
}

/// Returns a handle to the local cache.
pub fn local_cache(&self) -> Cache {
self.cache.clone()
Expand Down
115 changes: 115 additions & 0 deletions crates/mctx/src/project_setup.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
//! [`ProjectSetup`]: the `mctx` adapter implementing [`op::ProjectEnv`].

use std::path::{Path, PathBuf};

use checkouts::{GitRef, ManagerHandle as VcsManagerHandle};
use common::Target;
use graph::Graph;
use mfile::LinkConfig;

use crate::{Config, Context, Error, MFileSearchStrategy};

/// The environment project-setup operations ([`op::InitProject`],
/// [`op::UpdateProject`]) run against.
///
/// Unlike [`Context`], this can be constructed without a `minimal.toml` on disk,
/// which `init` requires when bootstrapping a fresh project.
pub struct ProjectSetup {
config: Config,
vcs: VcsManagerHandle,
stdlib_dir: PathBuf,
mfile: Option<mfile::File>,
repo_dir: PathBuf,
}

impl ProjectSetup {
/// Builds an environment for `init`, loading a `minimal.toml` if one is
/// already present (the user may be re-initializing).
pub fn for_init(config: Config) -> Result<Self, Error> {
let (vcs, _cache, stdlib_dir) = Context::sub_setup(&config)?;
let strategy = match config.repo_dir_override() {
Some(path) => MFileSearchStrategy::Override(path.to_path_buf()),
None => MFileSearchStrategy::CurrentDirOnly,
};
let mfile = match strategy.find_mfile() {
Ok(m) => Some(m),
Err(Error::MFile(mfile::Error::NotFound)) => None,
Err(e) => return Err(e),
};
let repo_dir = resolve_repo_dir(&config, mfile.as_ref())?;
Ok(Self {
config,
vcs,
stdlib_dir,
mfile,
repo_dir,
})
}

/// Builds an environment from the parts of an existing [`Context 8000 `].
pub(crate) fn from_parts(
config: Config,
vcs: VcsManagerHandle,
stdlib_dir: PathBuf,
mfile: mfile::File,
repo_dir: PathBuf,
) -> Self {
Self {
config,
vcs,
stdlib_dir,
mfile: Some(mfile),
repo_dir,
}
}
}

/// Resolves the project root: the minimal file's repo, else the configured
/// override, else the current directory.
fn resolve_repo_dir(config: &Config, mfile: Option<&mfile::File>) -> Result<PathBuf, Error> {
if let Some(p) = mfile.and_then(|m| m.repo_path()) {
return Ok(p.to_path_buf());
}
if let Some(p) = config.repo_dir_override() {
return Ok(p.to_path_buf());
}
std::env::current_dir().map_err(|e| Error::IO("Getting current directory", PathBuf::new(), e))
}

impl op::ProjectEnv for ProjectSetup {
fn repo_dir(&self) -> &Path {
&self.repo_dir
}

fn minimal_file(&self) -> Option<&mfile::File> {
self.mfile.as_ref()
}

fn checkout_branch(&mut self, repo: &str, branch: &str) -> Result<String, op::Error> {
self.vcs
.checkout_of(repo, GitRef::Branch(branch.to_string()))
.map(|(_dir, rev)| rev)
.map_err(|e| op::Error::Other(anyhow::Error::from(e)))
}

fn update_checkouts(&mut self) -> Result<(), op::Error> {
self.vcs
.update()
.map_err(|e| op::Error::Other(anyhow::Error::from(e)))
}

fn graph_from_chain(&mut self, link: LinkConfig, target: Target) -> Result<Graph, op::Error> {
Graph::new_from_chain(
self.vcs.clone(),
&mut graph::LayerCacheDir(self.config.layer_cache_dir()),
link,
self.stdlib_dir.clone(),
target,
)
.map_err(|e| op::Error::Other(anyhow::anyhow!("loading package graph: {e:?}")))
}

fn invalidate_remote_index(&mut self) {
std::fs::remove_file(self.config.index_dir().join(rcache::INDEX_FILENAME)).ok();
}
}
Loading
Loading
0