mirror of
https://github.com/pesde-pkg/pesde.git
synced 2024-12-12 11:00:36 +00:00
feat: publish members when publishing workspace
This commit is contained in:
parent
9a64a12f8e
commit
fa00a97f8b
6 changed files with 57 additions and 25 deletions
|
@ -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
|
||||
|
||||
|
|
|
@ -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()
|
||||
);
|
||||
|
|
|
@ -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(|_| ())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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")?;
|
||||
|
|
|
@ -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
|
||||
|
|
10
src/lib.rs
10
src/lib.rs
|
@ -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
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue