Skip to main content

libwally/commands/
publish.rs

1use std::path::{Path, PathBuf};
2
3use anyhow::{bail, Context};
4use structopt::StructOpt;
5use ubyte::ToByteUnit;
6use url::Url;
7
8use crate::{
9    auth::AuthStore, manifest::Manifest, package_contents::PackageContents,
10    package_index::PackageIndex, GlobalOptions,
11};
12
13const VERSION: &str = env!("CARGO_PKG_VERSION");
14
15/// Publish this project to a registry.
16#[derive(Debug, StructOpt)]
17pub struct PublishSubcommand {
18    /// Path to the project to publish.
19    #[structopt(long = "project-path", default_value = ".")]
20    pub project_path: PathBuf,
21}
22
23impl PublishSubcommand {
24    pub fn run(self, global: GlobalOptions) -> anyhow::Result<()> {
25        let manifest = Manifest::load(&self.project_path)?;
26
27        if manifest.package.private {
28            bail!("Cannot publish private package.");
29        }
30
31        let auth_store = AuthStore::load()?;
32
33        let index_url = if global.test_registry {
34            let index_path = Path::new(&manifest.package.registry)
35                .join("index")
36                .canonicalize()?;
37
38            Url::from_directory_path(index_path).unwrap()
39        } else {
40            Url::parse(&manifest.package.registry)?
41        };
42
43        let package_index = if global.use_temp_index {
44            PackageIndex::new_temp(&index_url, None)?
45        } else {
46            PackageIndex::new(&index_url, None)?
47        };
48
49        let api = package_index.config()?.api;
50        let contents = PackageContents::pack_from_path(&self.project_path)?;
51
52        if contents.data().len() > 2.mebibytes() {
53            bail!("Package size exceeds 2MB. Reduce package size and try again.");
54        }
55
56        let auth = auth_store
57            .tokens
58            .get(api.as_str())
59            .with_context(|| "Authentication is required to publish, use `wally login`")?;
60
61        println!(
62            "Publishing {} to {}",
63            manifest.package_id(),
64            package_index.url()
65        );
66
67        let client = reqwest::blocking::Client::new();
68        let response = client
69            .post(api.join("/v1/publish")?)
70            .header("accept", "application/json")
71            .header("Wally-Version", VERSION)
72            .bearer_auth(auth)
73            .body(contents.data().to_owned())
74            .send()?;
75
76        if response.status().is_success() {
77            println!("Package published successfully!");
78        } else {
79            println!("Error: {}", response.status());
80            println!("{}", response.text()?);
81        }
82
83        Ok(())
84    }
85}