1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
//! Interacts with the registry [yank] and [unyank] API.
//!
//! [yank]: https://doc.rust-lang.org/nightly/cargo/reference/registry-web-api.html#yank
//! [unyank]: https://doc.rust-lang.org/nightly/cargo/reference/registry-web-api.html#unyank

use anyhow::bail;
use anyhow::Context as _;
use cargo_credential::Operation;
use cargo_credential::Secret;

use crate::core::Workspace;
use crate::util::config::Config;
use crate::util::errors::CargoResult;
use crate::util::important_paths::find_root_manifest_for_wd;

use super::RegistryOrIndex;

pub fn yank(
    config: &Config,
    krate: Option<String>,
    version: Option<String>,
    token: Option<Secret<String>>,
    reg_or_index: Option<RegistryOrIndex>,
    undo: bool,
) -> CargoResult<()> {
    let name = match krate {
        Some(name) => name,
        None => {
            let manifest_path = find_root_manifest_for_wd(config.cwd())?;
            let ws = Workspace::new(&manifest_path, config)?;
            ws.current()?.package_id().name().to_string()
        }
    };
    let Some(version) = version else {
        bail!("a version must be specified to yank")
    };

    let message = if undo {
        Operation::Unyank {
            name: &name,
            vers: &version,
        }
    } else {
        Operation::Yank {
            name: &name,
            vers: &version,
        }
    };

    let (mut registry, _) = super::registry(
        config,
        token.as_ref().map(Secret::as_deref),
        reg_or_index.as_ref(),
        true,
        Some(message),
    )?;

    let package_spec = format!("{}@{}", name, version);
    if undo {
        config.shell().status("Unyank", package_spec)?;
        registry.unyank(&name, &version).with_context(|| {
            format!(
                "failed to undo a yank from the registry at {}",
                registry.host()
            )
        })?;
    } else {
        config.shell().status("Yank", package_spec)?;
        registry
            .yank(&name, &version)
            .with_context(|| format!("failed to yank from the registry at {}", registry.host()))?;
    }

    Ok(())
}