diff --git a/gcli/src/cmd/meta.rs b/gcli/src/cmd/meta.rs deleted file mode 100644 index b3dddfed8b5..00000000000 --- a/gcli/src/cmd/meta.rs +++ /dev/null @@ -1,52 +0,0 @@ -// This file is part of Gear. -// -// Copyright (C) 2021-2023 Gear Technologies Inc. -// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0 -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -//! command `meta` -use crate::{metadata::Metadata, result::Result}; -use clap::Parser; -use std::{fs, path::PathBuf}; - -/// Show metadata structure, read types from registry, etc. -#[derive(Debug, Parser)] -pub enum Action { - /// Display the structure of the metadata. - Display, -} - -/// Show metadata structure, read types from registry, etc. -#[derive(Debug, Parser)] -pub struct Meta { - /// Path of "*.meta.wasm". - pub metadata: PathBuf, - #[command(subcommand)] - pub action: Action, -} - -impl Meta { - /// Run command meta. - pub fn exec(&self) -> Result<()> { - let wasm = fs::read(&self.metadata)?; - let meta = Metadata::of(&wasm)?; - - match self.action { - Action::Display => println!("{}", format!("{meta:#}").replace('"', "")), - } - - Ok(()) - } -} diff --git a/gcli/src/cmd/mod.rs b/gcli/src/cmd/mod.rs index 29ea7ef4c41..8676ee9636e 100644 --- a/gcli/src/cmd/mod.rs +++ b/gcli/src/cmd/mod.rs @@ -71,6 +71,21 @@ impl Command { Ok(()) } + + #[cfg(feature = "embed")] + pub async fn exec_embedded( + self, + app: &impl App, + artifact: crate::embed::Artifact, + ) -> anyhow::Result<()> { + let this = match self { + Command::Upload(upload) => Command::Upload(upload.override_code(artifact.opt)), + Command::Program(program) => Command::Program(program.try_override_meta(artifact.meta)), + _ => self, + }; + + Self::exec(&this, app).await + } } /// Gear command-line interface. diff --git a/gcli/src/cmd/program.rs b/gcli/src/cmd/program.rs index e6c7bdaba78..07657b62898 100644 --- a/gcli/src/cmd/program.rs +++ b/gcli/src/cmd/program.rs @@ -17,7 +17,7 @@ // along with this program. If not, see . //! Command `program`. -use crate::{meta::Meta, result::Result, App}; +use crate::{meta::Meta, result::Result, utils, App}; use clap::Parser; use gsdk::{ext::sp_core::H256, Api}; use std::{fs, path::PathBuf}; @@ -33,7 +33,8 @@ pub enum Program { /// /// - "*.meta.txt" describes the metadata of the program /// - "*.meta.wasm" describes the wasm exports of the program - meta: PathBuf, + #[arg(short, long)] + meta: Option, /// Derive the description of the specified type from registry. #[arg(short, long)] derive: Option, @@ -60,6 +61,17 @@ pub enum Program { } impl Program { + /// Try override meta path. + pub fn try_override_meta(mut self, meta: Option) -> Self { + if let Program::Meta { meta: m, .. } = &mut self { + if m.is_none() { + *m = meta; + } + } + + self + } + /// Run command program. pub async fn exec(&self, app: &impl App) -> Result<()> { match self { @@ -79,7 +91,9 @@ impl Program { Self::full_state(api, *pid, *at).await?; } } - Program::Meta { meta, derive } => Self::meta(meta, derive)?, + Program::Meta { meta, derive } => { + Self::meta(&utils::meta_path(meta.clone(), "meta")?, derive)? + } } Ok(()) diff --git a/gcli/src/cmd/upload.rs b/gcli/src/cmd/upload.rs index 27f8073e362..e934f107afa 100644 --- a/gcli/src/cmd/upload.rs +++ b/gcli/src/cmd/upload.rs @@ -30,7 +30,8 @@ use std::{fs, path::PathBuf}; /// Deploy program to gear node or save program `code` in storage. #[derive(Parser, Debug)] pub struct Upload { - /// gear program code <*.wasm> + /// Gear program code <*.wasm>. + #[cfg_attr(feature = "embed", clap(skip))] code: PathBuf, /// Save program `code` in storage only. #[arg(short, long)] @@ -50,6 +51,12 @@ pub struct Upload { } impl Upload { + /// Override code path. + pub fn override_code(mut self, code: PathBuf) -> Self { + self.code = code; + self + } + /// Exec command submit pub async fn exec(&self, signer: Signer) -> Result<()> { let code = diff --git a/gcli/src/embed.rs b/gcli/src/embed.rs index 17a27744a38..8d6f0fcde2b 100644 --- a/gcli/src/embed.rs +++ b/gcli/src/embed.rs @@ -21,7 +21,11 @@ use std::path::PathBuf; -/// This macro is used to lookup the artifact from the `OUT_DIR`. +/// This macro is used to lookup the artifact from the `OUT_DIR`, +/// it's just a wrapper around [`Artifact::from_out_dir`] for +/// avoiding importing [`Artifact`] in users' code. +/// +/// NOTE: This macro should only be used in external crates. #[macro_export] macro_rules! lookup { () => {{ @@ -38,7 +42,13 @@ const OUT_SUFFIX_LENGTH: usize = 17; #[derive(Debug)] pub struct Artifact { /// Path of the optitmized WASM binary. + /// + /// TODO: load the binary into memory instead of file path in + /// case of users renaming the binary after the build. (#3592) pub opt: PathBuf, + + /// Path of the metadata WASM binary. + pub meta: Option, } impl Artifact { @@ -53,19 +63,28 @@ impl Artifact { .nth(1)? .file_name()? .to_str() - .map(|name| name.get(..name.len().checked_sub(OUT_SUFFIX_LENGTH)?)) - .flatten()?, - (ancestors.nth(1)?.file_name()?.to_str()? == "debug") - .then(|| "debug") - .unwrap_or("release"), + .and_then(|name| name.get(..name.len().checked_sub(OUT_SUFFIX_LENGTH)?))?, + if ancestors.nth(1)?.file_name()?.to_str()? == "debug" { + "debug" + } else { + "release" + }, ancestors.next()?.to_str()?, ]; - let opt = PathBuf::from(format!( - "{target}/wasm32-unknown-unknown/{profile}/{}.opt.wasm", - name.replace('-', "_") - )); + let [bin, stem] = [ + PathBuf::from(format!("{target}/wasm32-unknown-unknown/{profile}")), + PathBuf::from(name.replace('-', "_")), + ]; + + let [opt, meta] = [ + bin.join(stem.with_extension("wasm")), + bin.join(stem.with_extension("meta.wasm")), + ]; - opt.exists().then(|| Self { opt }) + opt.exists().then(|| Self { + opt, + meta: meta.exists().then_some(meta), + }) } } diff --git a/gcli/src/utils.rs b/gcli/src/utils.rs index 8630ecffc39..79eb1557244 100644 --- a/gcli/src/utils.rs +++ b/gcli/src/utils.rs @@ -20,7 +20,7 @@ use crate::result::Result; use anyhow::anyhow; -use std::{fs, path::PathBuf}; +use std::{env, fs, path::PathBuf}; /// home directory of cli `gear` pub fn home() -> PathBuf { @@ -33,6 +33,26 @@ pub fn home() -> PathBuf { home } +/// Parse the metadata path with result. +pub fn meta_path(meta: Option, opt: &str) -> Result { + if let Some(meta) = meta { + return Ok(meta); + } + + let cwd = env::current_dir()?; + for entry in fs::read_dir(&cwd)? { + let file = entry?.path(); + if file.ends_with(".meta.wasm") { + return Ok(file); + } + } + + Err(anyhow!( + "Could not find any *.meta.wasm in {cwd:?}, please specify the metadata path with --{opt}", + ) + .into()) +} + pub trait Hex { fn to_vec(&self) -> Result>; fn to_hash(&self) -> Result<[u8; 32]>;