1mod auth;
2
3use crate::{cli, http::HttpClient};
4use gleam_core::{
5 Error, Result,
6 hex::{self, RetirementReason},
7 io::HttpClient as _,
8 paths::ProjectPaths,
9};
10
11pub use auth::HexAuthentication;
12
13pub fn retire(
14 package: String,
15 version: String,
16 reason: RetirementReason,
17 message: Option<String>,
18) -> Result<()> {
19 let runtime = tokio::runtime::Runtime::new().expect("Unable to start Tokio async runtime");
20 let config = hexpm::Config::new();
21 let api_key = HexAuthentication::new(&runtime, config.clone()).get_or_create_api_key()?;
22
23 runtime.block_on(hex::retire_release(
24 &package,
25 &version,
26 reason,
27 message.as_deref(),
28 &api_key,
29 &config,
30 &HttpClient::new(),
31 ))?;
32 cli::print_retired(&package, &version);
33 Ok(())
34}
35
36pub fn unretire(package: String, version: String) -> Result<()> {
37 let runtime = tokio::runtime::Runtime::new().expect("Unable to start Tokio async runtime");
38 let config = hexpm::Config::new();
39 let api_key = HexAuthentication::new(&runtime, config.clone()).get_or_create_api_key()?;
40
41 runtime.block_on(hex::unretire_release(
42 &package,
43 &version,
44 &api_key,
45 &config,
46 &HttpClient::new(),
47 ))?;
48 cli::print_unretired(&package, &version);
49 Ok(())
50}
51
52pub fn revert(
53 paths: &ProjectPaths,
54 package: Option<String>,
55 version: Option<String>,
56) -> Result<()> {
57 let (package, version) = match (package, version) {
58 (Some(pkg), Some(ver)) => (pkg, ver),
59 (None, Some(ver)) => (crate::config::root_config(paths)?.name.to_string(), ver),
60 (Some(pkg), None) => {
61 let query = format!("Which version of package {pkg} do you want to revert?");
62 let ver = cli::ask(&query)?;
63 (pkg, ver)
64 }
65 (None, None) => {
66 // Only want to access root_config once rather than twice
67 let config = crate::config::root_config(paths)?;
68 (config.name.to_string(), config.version.to_string())
69 }
70 };
71
72 let question = format!("Do you wish to revert {package} version {version}?");
73 if !cli::confirm(&question)? {
74 println!("Not reverting.");
75 return Ok(());
76 }
77
78 let runtime = tokio::runtime::Runtime::new().expect("Unable to start Tokio async runtime");
79 let hex_config = hexpm::Config::new();
80 let api_key = HexAuthentication::new(&runtime, hex_config.clone()).get_or_create_api_key()?;
81 let http = HttpClient::new();
82
83 // Revert release from API
84 let request = hexpm::revert_release_request(&package, &version, &api_key, &hex_config)
85 .map_err(Error::hex)?;
86 let response = runtime.block_on(http.send(request))?;
87 hexpm::revert_release_response(response).map_err(Error::hex)?;
88
89 // Done!
90 println!("{package} {version} has been removed from Hex");
91 Ok(())
92}
93
94pub(crate) fn authenticate() -> Result<()> {
95 let runtime = tokio::runtime::Runtime::new().expect("Unable to start Tokio async runtime");
96 let http = HttpClient::new();
97 let config = hexpm::Config::new();
98 let mut auth = HexAuthentication::new(&runtime, config.clone());
99 let previous = auth.read_stored_api_key()?;
100
101 if previous.is_some() {
102 let question = "You already have a local Hex API token. Would you like to replace it
103with a new one?";
104 if !cli::confirm(question)? {
105 return Ok(());
106 }
107 }
108
109 let new_key = auth.create_and_store_api_key()?;
110
111 if let Some(previous) = previous {
112 println!("Deleting previous key `{}` from Hex", previous.name);
113 runtime.block_on(hex::remove_api_key(
114 &previous.name,
115 &config,
116 &new_key.unencrypted,
117 &http,
118 ))?;
119 }
120 Ok(())
121}