Skip to content

Commit

Permalink
Merge pull request #11 from integer32llc/yank
Browse files Browse the repository at this point in the history
Support yanking a crate
  • Loading branch information
shepmaster authored May 16, 2024
2 parents 023743c + 5f976fc commit 9660c81
Show file tree
Hide file tree
Showing 4 changed files with 135 additions and 22 deletions.
4 changes: 2 additions & 2 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 Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ unused_crate_dependencies = "deny"

[workspace.dependencies]
argh = { version = "0.1.12", default-features = false }
registry-conformance = { version = "0.2.0", registry = "registry-conformance" }
registry-conformance = { version = "0.3.0", registry = "registry-conformance" }
snafu = { version = "0.8.2", default-features = false, features = ["rust_1_65", "std"] }
tokio = { version = "1.37.0", default-features = false, features = ["macros", "process", "rt-multi-thread"] }

Expand Down
32 changes: 32 additions & 0 deletions conformance/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,22 @@ impl Margo {
Ok(())
}

async fn yank_crate_(&mut self, crate_: &CreatedCrate) -> Result<(), YankError> {
use yank_error::*;

self.command()
.arg("yank")
.arg("--registry")
.arg(&self.directory)
.arg(crate_.name())
.args(["--version", crate_.version()])
.expect_success()
.await
.context(ExecutionSnafu)?;

Ok(())
}

async fn shutdown_(self) -> Result<(), ShutdownError> {
use shutdown_error::*;

Expand Down Expand Up @@ -220,6 +236,15 @@ pub enum BuildError {
},
}

#[derive(Debug, Snafu)]
#[snafu(module)]
pub enum YankError {
#[snafu(display("Could not yank the crate from the registry"))]
Execution {
source: registry_conformance::CommandError,
},
}

#[derive(Debug, Snafu)]
#[snafu(module)]
pub enum PublishError {
Expand Down Expand Up @@ -269,6 +294,10 @@ impl Registry for Margo {
Ok(self.publish_crate_(crate_).await?)
}

async fn yank_crate(&mut self, crate_: &CreatedCrate) -> Result<(), Error> {
Ok(self.yank_crate_(crate_).await?)
}

async fn shutdown(self) -> Result<(), Error> {
Ok(self.shutdown_().await?)
}
Expand All @@ -283,6 +312,9 @@ pub enum Error {
#[snafu(transparent)]
Publish { source: PublishError },

#[snafu(transparent)]
Yank { source: YankError },

#[snafu(transparent)]
Shutdown { source: ShutdownError },
}
119 changes: 100 additions & 19 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ enum Subcommand {
Init(InitArgs),
Add(AddArgs),
GenerateHtml(GenerateHtmlArgs),
Yank(YankArgs),
}

/// Initialize a new registry
Expand Down Expand Up @@ -81,6 +82,24 @@ struct GenerateHtmlArgs {
registry: PathBuf,
}

/// Yank a version of a crate from the registry
#[derive(Debug, argh::FromArgs)]
#[argh(subcommand)]
#[argh(name = "yank")]
struct YankArgs {
/// path to the registry to modify
#[argh(option)]
registry: PathBuf,

/// the version of the crate
#[argh(option)]
version: Version,

/// the name of the crate
#[argh(positional)]
name: CrateName,
}

#[snafu::report]
fn main() -> Result<(), Error> {
let args: Args = argh::from_env();
Expand All @@ -92,6 +111,7 @@ fn main() -> Result<(), Error> {
Subcommand::Init(init) => do_init(global, init)?,
Subcommand::Add(add) => do_add(global, add)?,
Subcommand::GenerateHtml(html) => do_generate_html(global, html)?,
Subcommand::Yank(yank) => do_yank(global, yank)?,
}

Ok(())
Expand All @@ -114,6 +134,9 @@ enum Error {

#[snafu(transparent)]
Html { source: HtmlError },

#[snafu(transparent)]
Yank { source: YankError },
}

trait UnwrapOrDialog<T> {
Expand Down Expand Up @@ -259,6 +282,12 @@ fn do_generate_html(_global: &Global, html: GenerateHtmlArgs) -> Result<(), Erro
Ok(())
}

fn do_yank(_global: &Global, yank: YankArgs) -> Result<(), Error> {
let r = Registry::open(yank.registry)?;
r.yank(yank.name, yank.version)?;
Ok(())
}

#[derive(Debug)]
struct Registry {
path: PathBuf,
Expand Down Expand Up @@ -354,17 +383,14 @@ impl Registry {
fs::create_dir_all(path).context(CrateDirSnafu { path })?;
}

// FUTURE: Add `yank` subcommand
// FUTURE: Add `unyank` subcommand
// FUTURE: Add `remove` subcommand
// FUTURE: Stronger file system consistency (atomic file overwrites, rollbacks on error)

let mut index_file =
Self::parse_index_file(&index_path).context(IndexParseSnafu { path: &index_path })?;

index_file.insert(index_entry.vers.clone(), index_entry);

Self::write_index_file(index_file, &index_path)
.context(IndexWriteSnafu { path: &index_path })?;
self.read_modify_write(&index_entry.name.clone(), |index_file| {
index_file.insert(index_entry.vers.clone(), index_entry);
Ok::<_, AddError>(())
})?;

println!("Wrote crate index to `{}`", index_path.display());

Expand All @@ -386,6 +412,36 @@ impl Registry {
Err(HtmlError)
}

fn yank(&self, name: CrateName, version: Version) -> Result<(), YankError> {
use yank_error::*;

self.read_modify_write(&name, |index| {
let entry = index.get_mut(&version).context(VersionSnafu)?;
entry.yanked = true;
Ok(())
})
}

fn read_modify_write<T, E>(
&self,
name: &CrateName,
modify: impl FnOnce(&mut Index) -> Result<T, E>,
) -> Result<T, E>
where
E: From<ReadModifyWriteError>,
{
use read_modify_write_error::*;

let path = self.index_file_path_for(name);
let mut index = Self::parse_index_file(&path).context(IndexParseSnafu { path: &path })?;

let val = modify(&mut index)?;

Self::write_index_file(index, &path).context(IndexWriteSnafu { path })?;

Ok(val)
}

fn list_crate_files(
crate_dir: &Path,
) -> impl Iterator<Item = walkdir::Result<walkdir::DirEntry>> {
Expand Down Expand Up @@ -573,17 +629,8 @@ enum AddError {
#[snafu(display("Could not create the crate's index directory {}", path.display()))]
IndexDir { source: io::Error, path: PathBuf },

#[snafu(display("Could not parse the crate's index file {}", path.display()))]
IndexParse {
source: ParseIndexError,
path: PathBuf,
},

#[snafu(display("Could not write the crate's index file {}", path.display()))]
IndexWrite {
source: WriteIndexError,
path: PathBuf,
},
#[snafu(transparent)]
IndexModify { source: ReadModifyWriteError },

#[snafu(display("Could not create the crate directory {}", path.display()))]
CrateDir { source: io::Error, path: PathBuf },
Expand All @@ -600,6 +647,32 @@ use html::Error as HtmlError;
#[snafu(display("Margo was not compiled with the HTML feature enabled. This binary will not be able to generate HTML files"))]
struct HtmlError;

#[derive(Debug, Snafu)]
#[snafu(module)]
enum YankError {
#[snafu(display("The version does not exist in the index"))]
Version,

#[snafu(transparent)]
Modify { source: ReadModifyWriteError },
}

#[derive(Debug, Snafu)]
#[snafu(module)]
enum ReadModifyWriteError {
#[snafu(display("Could not parse the crate's index file {}", path.display()))]
IndexParse {
source: ParseIndexError,
path: PathBuf,
},

#[snafu(display("Could not write the crate's index file {}", path.display()))]
IndexWrite {
source: WriteIndexError,
path: PathBuf,
},
}

#[derive(Debug, Snafu)]
#[snafu(module)]
enum ListIndexFilesError {
Expand Down Expand Up @@ -1198,6 +1271,14 @@ mod common {
}
}

impl FromStr for CrateName {
type Err = CrateNameError;

fn from_str(s: &str) -> Result<Self, Self::Err> {
s.try_into()
}
}

impl TryFrom<&str> for CrateName {
type Error = CrateNameError;

Expand Down

0 comments on commit 9660c81

Please sign in to comment.