Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion crates/mvr-cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ name = "unit_tests"
path = "tests/unit_tests.rs"

[dependencies]
bin-version = { git = "https://github.com/mystenlabs/sui", package = "bin-version", rev = "0f91f6b" }
bin-version = { git = "https://github.com/mystenlabs/sui", rev = "0f91f6b" }
jsonrpc = { git = "https://github.com/mystenlabs/sui", rev = "0f91f6b" }

clap = { workspace = true, features = ["derive"] }
reqwest = { version = "0.12", default-features = false, features = ["json", "rustls-tls"] }
Expand Down
5 changes: 1 addition & 4 deletions crates/mvr-cli/src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,7 @@ impl Display for CommandOutput {
let description = pkg
.metadata
.get("description")
.map(|s| s.as_str())
.flatten()
.and_then(|s| s.as_str())
.map(|s| s.to_string())
.unwrap_or("--".italic().to_string());

Expand Down Expand Up @@ -110,15 +109,13 @@ impl Display for CommandOutput {
"\n{}",
"There are multiple pages of results. Use the cursor to paginate through the results."
.italic()
.to_string()
)?;
writeln!(
f,
"{}",
format!("mvr search <query> --cursor {}", next_cursor)
.italic()
.blue()
.to_string()
)?;
}

Expand Down
27 changes: 11 additions & 16 deletions crates/mvr-cli/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ pub mod errors;
pub mod types;
pub mod utils;

use crate::types::api_data::{
query_multiple_dependencies, query_package, resolve_name, search_names,
};
use crate::types::MoveTomlPublishedID;

use commands::CommandOutput;
Expand All @@ -12,9 +15,6 @@ use mvr_types::name::VersionedName;
use types::api_types::PackageRequest;
use types::api_types::SafeGitInfo;
use types::Network;
use utils::api_data::resolve_name;
use utils::api_data::search_names;
use utils::api_data::{query_multiple_dependencies, query_package};
use utils::git::shallow_clone_repo;

use sui_sdk_types::ObjectId;
Expand Down Expand Up @@ -408,12 +408,7 @@ fn original_published_id(move_toml_content: &str, target_chain_id: &str) -> Opti
.as_table()?
.iter()
.filter_map(|(_, value)| value.as_table())
.find(|table| {
table
.get("chain-id")
.and_then(|v| v.as_str())
.map_or(false, |id| id == target_chain_id)
});
.find(|table| table.get("chain-id").and_then(|v| v.as_str()) == Some(target_chain_id));
let original_published_id = table.and_then(|table| {
table
.get("original-published-id")
Expand Down Expand Up @@ -540,9 +535,9 @@ fn insert_root_dependency(
new_package.insert(LOCK_PACKAGE_ID_KEY, value(root_name));

let mut source = Table::new();
source.insert("git", value(&git_info.repository_url.clone()));
source.insert("rev", value(&git_info.tag.clone()));
source.insert("subdir", value(&git_info.path.clone()));
source.insert("git", value(git_info.repository_url.clone()));
source.insert("rev", value(git_info.tag.clone()));
source.insert("subdir", value(git_info.path.clone()));
new_package.insert("source", value(source.into_inline_table()));

if let Some(deps) = original_deps {
Expand All @@ -560,7 +555,7 @@ fn insert_root_dependency(
.ok_or_else(|| anyhow!("Failed to get or create package array in lock file".red()))?;

for package in packages.iter_mut() {
if let Some(source) = convert_local_dep_to_git(package, &git_info)? {
if let Some(source) = convert_local_dep_to_git(package, git_info)? {
package.insert("source", value(source));
}
}
Expand Down Expand Up @@ -601,8 +596,8 @@ fn convert_local_dep_to_git(
.and_then(|items| items.get("local"))
.map(|local| {
let mut new_source = Table::new();
new_source.insert("git", value(&git_info.repository_url.clone()));
new_source.insert("rev", value(&git_info.tag.clone()));
new_source.insert("git", value(git_info.repository_url.clone()));
new_source.insert("rev", value(git_info.tag.clone()));

let local_str = local.as_str().ok_or_else(|| {
anyhow!("Failed to get local dependency path. Found empty path on transitive dependency: {}", local)
Expand Down Expand Up @@ -686,7 +681,7 @@ async fn update_mvr_packages(
.red()
);
};
move_toml.add_dependency(&name, &package_name)?;
move_toml.add_dependency(&name, package_name)?;

move_toml.save_to_file()?;

Expand Down
27 changes: 19 additions & 8 deletions crates/mvr-cli/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
use mvr::types::resolver_alt::new_package_resolver;

use std::env;

use anyhow::Result;
use clap::Parser;
use mvr::utils::sui_binary::check_sui_version;
Expand All @@ -11,6 +15,9 @@ struct Cli {
#[arg(long)]
resolve_move_dependencies: Option<String>,

#[arg(long, global = true)]
resolve_deps: bool,

#[command(subcommand)]
command: Option<Command>,

Expand All @@ -23,10 +30,17 @@ struct Cli {
async fn main() -> Result<()> {
let cli = Cli::parse();

// If we are in the new package resolver, we wanna special handle it and return early.
if cli.resolve_deps {
new_package_resolver().await?;
return Ok(());
}

if let Some(ref value) = cli.resolve_move_dependencies {
check_sui_version(MINIMUM_BUILD_SUI_VERSION)?;
// Resolver function that `sui move build` expects to call.
resolve_move_dependencies(&value).await?;
eprintln!("Resolving move dependencies for {}", value);
resolve_move_dependencies(value).await?;
} else if let Some(command) = cli.command {
let output = command.execute().await?;
if cli.json {
Expand All @@ -35,13 +49,10 @@ async fn main() -> Result<()> {
println!("{}", output);
}
} else {
let cli = Cli::parse_from(&["mvr", "--help"]);
match cli.command {
Some(x) => {
let c = x.execute().await?;
println!("{:?}", c.to_string());
}
None => {}
let cli = Cli::parse_from(["mvr", "--help"]);
if let Some(x) = cli.command {
let c = x.execute().await?;
println!("{:?}", c.to_string());
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ pub async fn query_package(name: &str, network: &Network) -> Result<(String, Pac
let response = reqwest::get(format!(
"{}/v1/names/{}",
get_api_url(network)?,
versioned_name.to_string()
versioned_name
))
.await
.map_err(|e| CliError::Querying(e.to_string()))?;
Expand All @@ -46,13 +46,9 @@ pub async fn query_package(name: &str, network: &Network) -> Result<(String, Pac
}

pub async fn resolve_name(name: &VersionedName, network: &Network) -> Result<ObjectId> {
let response = reqwest::get(format!(
"{}/v1/resolution/{}",
get_api_url(network)?,
name.to_string()
))
.await
.map_err(|e| CliError::Querying(e.to_string()))?;
let response = reqwest::get(format!("{}/v1/resolution/{}", get_api_url(network)?, name))
.await
.map_err(|e| CliError::Querying(e.to_string()))?;

if response.status() == reqwest::StatusCode::NOT_FOUND {
bail!(CliError::NameNotExists(
Expand Down
4 changes: 3 additions & 1 deletion crates/mvr-cli/src/types/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
pub mod api_data;
pub mod api_types;
pub mod resolver_alt;

use std::fmt;
use std::str::FromStr;
Expand Down Expand Up @@ -37,7 +39,7 @@ pub(crate) struct SuiConfig {
envs: Vec<Env>,
}

#[derive(Debug, Serialize, Deserialize, Clone, Copy)]
#[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq, PartialOrd, Eq, Ord)]
pub enum Network {
Mainnet,
Testnet,
Expand Down
137 changes: 137 additions & 0 deletions crates/mvr-cli/src/types/resolver_alt.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
use std::{collections::BTreeMap, env, io::stdin, str::FromStr};

use anyhow::Result;
use jsonrpc::types::{BatchRequest, JsonRpcResult, RemoteError, RequestID, Response, TwoPointZero};
use mvr_types::name::VersionedName;
use serde::Deserialize;
use yansi::Paint;

use crate::types::{api_data::query_multiple_dependencies, MoveRegistryDependencies, Network};

#[derive(Deserialize, Debug)]
struct ResolveRequest {
#[serde(default)]
// We expect a "chain-id" populated here, or we'll resolve on all known chain ids (mainnet / testnet)
env: Option<String>,

// we expect the "data" to be a plain string, being a MVR Name.
data: String,
}

/// [Experimental]
/// The package-alt resolver for packages.
/// Note: This does not provide validation for "IDs". A `validate` command needs to be implemented
/// for validation of expected IDs to occur.
pub async fn new_package_resolver() -> Result<()> {
let input = parse_input();
let mut names = BTreeMap::new();
let mut per_env = BTreeMap::new();

for (_, request) in &input {
let name = VersionedName::from_str(&request.data)?;
let normalized_network = get_normalized_network(&request.env.clone().unwrap_or_default())?;

eprintln!(
"{}: {:?} {} {}",
"[mvr] RESOLVING".blue(),
request.data.blue().bold(),
"ON".blue(),
normalized_network.blue().bold(),
);

names
.entry(normalized_network)
.or_insert_with(Vec::new)
.push(name);
}

for (network, names) in &names {
let response = query_multiple_dependencies(
MoveRegistryDependencies {
packages: names.iter().map(|n| n.to_string()).collect(),
},
&network,
)
.await?;

per_env.insert(network, response);
}

let responses: Vec<Response<serde_json::Value>> = input
.into_iter()
.map(|(id, request)| {
// TODO: properly propagate errors -- we can leave as is for now while we're testing pkg-alt.
let normalized_network = get_normalized_network(&request.env.unwrap_or_default()).expect("We should have a normalized network error by this point.");
let map = per_env.get(&normalized_network).expect("No response found for env");

let Some(response) = map.get(&request.data) else {
return format_result(id, JsonRpcResult::Err {
error: RemoteError { code: 404, message: format!("No name entries found for {}", request.data), data: None }
});
};

let Some(git_info) = &response.git_info else {
return format_result(id, JsonRpcResult::Err {
error: RemoteError { code: 404, message: format!("Package with name {} does not have git info for env {}", request.data, normalized_network), data: None }
});
};

format_result(id, JsonRpcResult::Ok {
result: serde_json::json!({ "git": git_info.repository_url, "rev": git_info.tag, "subdir": git_info.path })
})
})
.collect();

let json = serde_json::to_string(&responses).unwrap_or_default();

println!("{json}");
Ok(())
}

/// Read a [Request] from [stdin]
fn parse_input() -> BTreeMap<RequestID, ResolveRequest> {
let mut line = String::new();
stdin().read_line(&mut line).expect("stdin can be read");

let batch: BatchRequest<ResolveRequest> = serde_json::from_str(&line)
.expect("External resolver must be passed a JSON RPC batch request");

batch
.into_iter()
.map(|req| {
assert!(req.method == "resolve");
(req.id, req.params)
})
.collect()
}

/// Returns the "normalized" network:
/// 1. If the chain-id of the env is known, then we return that.
/// 2. If the chain-id is not known, we try to get the `flag`-based setup.
/// 3. We error with the "original" error.
fn get_normalized_network(env: &str) -> Result<Network> {
let normalized_network = Network::try_from_chain_identifier(&env);

if let Ok(normalized_network) = normalized_network {
return Ok(normalized_network);
}

let fallback_network = env::var("MVR_FALLBACK_NETWORK")
.ok()
.map(|s| Network::from_str(&s))
.transpose();

if let Ok(Some(fallback_network)) = fallback_network {
return Ok(fallback_network);
}

Ok(normalized_network?)
}

fn format_result<T>(id: u64, result: JsonRpcResult<T>) -> Response<T> {
Response {
jsonrpc: TwoPointZero,
id,
result,
}
}
5 changes: 2 additions & 3 deletions crates/mvr-cli/src/utils/manifest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ impl MoveToml {
);
new_dep_table.insert(RESOLVER_PREFIX_KEY, Value::InlineTable(r_table));

dependencies.insert(&name, Item::Value(Value::InlineTable(new_dep_table)));
dependencies.insert(name, Item::Value(Value::InlineTable(new_dep_table)));

Ok(())
}
Expand All @@ -61,8 +61,7 @@ impl MoveToml {
.get(RESOLVER_PREFIX_KEY)
.and_then(|v| v.get(MVR_RESOLVER_KEY))
.and_then(|v| v.get(NETWORK_KEY))
.map(|v| v.as_str())
.flatten()
.and_then(|v| v.as_str())
.map(|s| s.to_string())
}

Expand Down
1 change: 0 additions & 1 deletion crates/mvr-cli/src/utils/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
pub mod api_data;
pub mod git;
pub mod manifest;
pub mod sui_binary;
Loading
Loading