feat: publish members when publishing workspace

This commit is contained in:
daimond113 2024-10-12 16:00:21 +02:00
parent 9a64a12f8e
commit fa00a97f8b
No known key found for this signature in database
GPG key ID: 3A8ECE51328B513C
6 changed files with 57 additions and 25 deletions

View file

@ -5,7 +5,11 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased] - 2024-10-07
## [Unreleased]
### Added
- Add `yes` argument to skip all prompts in publish command by @daimond113
- Publish all workspace members when publishing a workspace by @daimond113
### Fixed
- Add feature gates to `wally-compat` specific code in init command by @daimond113

View file

@ -131,7 +131,7 @@ impl InstallCommand {
println!(
"\n{}\n",
format!("[now installing {}]", manifest.name)
format!("[now installing {} {}]", manifest.name, manifest.target)
.bold()
.on_bright_black()
);

View file

@ -9,7 +9,7 @@ use std::{
};
use tempfile::tempfile;
use crate::cli::up_to_date_lockfile;
use crate::cli::{run_on_workspace_members, up_to_date_lockfile};
use pesde::{
manifest::{target::Target, DependencyType},
scripts::ScriptName,
@ -23,19 +23,30 @@ use pesde::{
Project, DEFAULT_INDEX_NAME, MANIFEST_FILE_NAME,
};
#[derive(Debug, Args)]
#[derive(Debug, Args, Copy, Clone)]
pub struct PublishCommand {
/// Whether to output a tarball instead of publishing
#[arg(short, long)]
dry_run: bool,
/// Agree to all prompts
#[arg(short, long)]
yes: bool,
}
impl PublishCommand {
pub fn run(self, project: Project, reqwest: reqwest::blocking::Client) -> anyhow::Result<()> {
fn run_impl(self, project: &Project, reqwest: reqwest::blocking::Client) -> anyhow::Result<()> {
let mut manifest = project
.deser_manifest()
.context("failed to read manifest")?;
println!(
"\n{}\n",
format!("[now publishing {} {}]", manifest.name, manifest.target)
.bold()
.on_bright_black()
);
if manifest.private {
println!("{}", "package is private, cannot publish".red().bold());
@ -54,7 +65,7 @@ impl PublishCommand {
anyhow::bail!("no build files found in target");
}
match up_to_date_lockfile(&project)? {
match up_to_date_lockfile(project)? {
Some(lockfile) => {
if lockfile
.graph
@ -313,7 +324,7 @@ impl PublishCommand {
}
DependencySpecifiers::Workspace(spec) => {
let pkg_ref = WorkspacePackageSource
.resolve(spec, &project, target_kind)
.resolve(spec, project, target_kind)
.context("failed to resolve workspace package")?
.1
.pop_last()
@ -410,7 +421,10 @@ impl PublishCommand {
display_includes.into_iter().collect::<Vec<_>>().join(", ")
);
if !self.dry_run && !inquire::Confirm::new("is this information correct?").prompt()? {
if !self.dry_run
&& !self.yes
&& !inquire::Confirm::new("is this information correct?").prompt()?
{
println!("\n{}", "publish aborted".red().bold());
return Ok(());
@ -447,10 +461,10 @@ impl PublishCommand {
.clone(),
);
source
.refresh(&project)
.refresh(project)
.context("failed to refresh source")?;
let config = source
.config(&project)
.config(project)
.context("failed to get source config")?;
if archive.len() > config.max_archive_size {
@ -497,30 +511,36 @@ impl PublishCommand {
match status {
StatusCode::CONFLICT => {
println!("{}", "package version already exists".red().bold());
Ok(())
}
StatusCode::FORBIDDEN => {
println!(
"{}",
"unauthorized to publish under this scope".red().bold()
);
Ok(())
}
StatusCode::BAD_REQUEST => {
println!("{}: {text}", "invalid package".red().bold());
Ok(())
}
code if !code.is_success() => {
anyhow::bail!("failed to publish package: {code} ({text})");
}
_ => {
println!("{text}");
Ok(())
}
}
Ok(())
}
pub fn run(self, project: Project, reqwest: reqwest::blocking::Client) -> anyhow::Result<()> {
let result = self.run_impl(&project, reqwest.clone());
if project.workspace_dir().is_some() {
return result;
} else if let Err(result) = result {
println!("an error occurred publishing workspace root: {result}");
}
run_on_workspace_members(&project, |project| self.run_impl(&project, reqwest.clone()))
.map(|_| ())
}
}

View file

@ -1,6 +1,7 @@
use crate::cli::{download_graph, run_on_workspace_members};
use anyhow::Context;
use clap::Args;
use colored::Colorize;
use indicatif::MultiProgress;
use pesde::{lockfile::Lockfile, Project};
use std::collections::HashSet;
@ -25,6 +26,13 @@ impl UpdateCommand {
.deser_manifest()
.context("failed to read manifest")?;
println!(
"\n{}\n",
format!("[now updating {} {}]", manifest.name, manifest.target)
.bold()
.on_bright_black()
);
let graph = project
.dependency_graph(None, &mut refreshed_sources)
.context("failed to build dependency graph")?;

View file

@ -272,8 +272,8 @@ pub fn run_on_workspace_members(
) -> anyhow::Result<BTreeMap<PackageName, BTreeMap<TargetKind, RelativePathBuf>>> {
Ok(match project.workspace_dir() {
Some(_) => {
// this might seem counterintuitive, but remember that the workspace
// is the package_dir when the user isn't in a member package
// this might seem counterintuitive, but remember that
// the presence of a workspace dir means that this project is a member of one
Default::default()
}
None => project

View file

@ -130,27 +130,27 @@ impl Project {
}
}
/// Access the package directory
/// The directory of the package
pub fn package_dir(&self) -> &Path {
&self.package_dir
}
/// Access the workspace directory
/// The directory of the workspace this package belongs to, if any
pub fn workspace_dir(&self) -> Option<&Path> {
self.workspace_dir.as_deref()
}
/// Access the data directory
/// The directory to store general-purpose data
pub fn data_dir(&self) -> &Path {
&self.data_dir
}
/// Access the authentication configuration
/// The authentication configuration
pub fn auth_config(&self) -> &AuthConfig {
&self.auth_config
}
/// Access the CAS (content-addressable storage) directory
/// The CAS (content-addressable storage) directory
pub fn cas_dir(&self) -> &Path {
&self.cas_dir
}