forked from
gleam.run/gleam
⭐️ A friendly language for building type-safe, scalable systems!
4.6 kB
137 lines
1// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: 2021 The Gleam contributors
3
4mod auth;
5
6use crate::{cli, http::HttpClient};
7use gleam_core::{
8 Error, Result,
9 hex::{self, RetirementReason},
10 io::HttpClient as _,
11 paths::ProjectPaths,
12};
13
14pub use auth::{HexAuthentication, read_env_readonly_api_key};
15
16/// Prepare credentials for user for write actions.
17/// This will prompt for a one-time-password if needed.
18pub fn write_credentials(
19 credentials: &hexpm::Credentials,
20) -> Result<hexpm::WriteActionCredentials> {
21 match credentials {
22 hexpm::Credentials::ApiKey(key) => Ok(hexpm::WriteActionCredentials::ApiKey(key.clone())),
23 hexpm::Credentials::OAuthAccessToken(token) => {
24 let one_time_password = cli::ask("Enter your two-factor authentication code")?.into();
25 Ok(hexpm::WriteActionCredentials::OAuthAccessToken {
26 access_token: token.clone(),
27 one_time_password,
28 })
29 }
30 }
31}
32
33pub fn retire(
34 package: String,
35 version: String,
36 reason: RetirementReason,
37 message: Option<String>,
38) -> Result<()> {
39 let runtime = tokio::runtime::Runtime::new().expect("Unable to start Tokio async runtime");
40 let config = hexpm::Config::new();
41 let http = HttpClient::new();
42 let credentials =
43 HexAuthentication::new(&runtime, &http, config.clone()).get_or_create_api_credentials()?;
44
45 runtime.block_on(hex::retire_release(
46 &package,
47 &version,
48 reason,
49 message.as_deref(),
50 &write_credentials(&credentials)?,
51 &config,
52 &http,
53 ))?;
54 cli::print_retired(&package, &version);
55 Ok(())
56}
57
58pub fn unretire(package: String, version: String) -> Result<()> {
59 let runtime = tokio::runtime::Runtime::new().expect("Unable to start Tokio async runtime");
60 let http = HttpClient::new();
61 let config = hexpm::Config::new();
62 let credentials =
63 HexAuthentication::new(&runtime, &http, config.clone()).get_or_create_api_credentials()?;
64
65 runtime.block_on(hex::unretire_release(
66 &package,
67 &version,
68 &write_credentials(&credentials)?,
69 &config,
70 &http,
71 ))?;
72 cli::print_unretired(&package, &version);
73 Ok(())
74}
75
76pub fn revert(
77 paths: &ProjectPaths,
78 package: Option<String>,
79 version: Option<String>,
80) -> Result<()> {
81 let (package, version) = match (package, version) {
82 (Some(pkg), Some(ver)) => (pkg, ver),
83 (None, Some(ver)) => (crate::config::root_config(paths)?.name.to_string(), ver),
84 (Some(pkg), None) => {
85 let query = format!("Which version of package {pkg} do you want to revert?");
86 let ver = cli::ask(&query)?;
87 (pkg, ver)
88 }
89 (None, None) => {
90 // Only want to access root_config once rather than twice
91 let config = crate::config::root_config(paths)?;
92 (config.name.to_string(), config.version.to_string())
93 }
94 };
95
96 let question = format!("Do you wish to revert {package} version {version}?");
97 if !cli::confirm(&question)? {
98 println!("Not reverting.");
99 return Ok(());
100 }
101
102 let runtime = tokio::runtime::Runtime::new().expect("Unable to start Tokio async runtime");
103 let hex_config = hexpm::Config::new();
104 let http = HttpClient::new();
105 let credentials = HexAuthentication::new(&runtime, &http, hex_config.clone())
106 .get_or_create_api_credentials()?;
107
108 // Revert release from API
109 let request = hexpm::api_revert_release_request(
110 &package,
111 &version,
112 &write_credentials(&credentials)?,
113 &hex_config,
114 )
115 .map_err(Error::hex)?;
116 let response = runtime.block_on(http.send(request))?;
117 hexpm::api_revert_release_response(response).map_err(Error::hex)?;
118
119 // Done!
120 println!("{package} {version} has been removed from Hex");
121 Ok(())
122}
123
124pub(crate) fn authenticate() -> Result<()> {
125 let runtime = tokio::runtime::Runtime::new().expect("Unable to start Tokio async runtime");
126 let http = HttpClient::new();
127 let config = hexpm::Config::new();
128 let credentials = HexAuthentication::new(&runtime, &http, config.clone())
129 .create_and_store_new_credentials_via_oauth()?;
130
131 let request = hexpm::get_me_request(&credentials, &config);
132 let response = runtime.block_on(http.send(request))?;
133 let me = hexpm::get_me_response(response).map_err(Error::hex)?;
134 println!("\nSuccessfully logged in as {}", me.username);
135
136 Ok(())
137}