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]>;