iota_move/
manage_package.rs

1// Copyright (c) Mysten Labs, Inc.
2// Modifications Copyright (c) 2024 IOTA Stiftung
3// SPDX-License-Identifier: Apache-2.0
4
5use std::path::{Path, PathBuf};
6
7use anyhow::bail;
8use clap::Parser;
9use iota_types::base_types::ObjectID;
10use move_cli::base;
11use move_package::{
12    BuildConfig,
13    lock_file::{self, LockFile},
14    source_package::layout::SourcePackageLayout,
15};
16
17const NO_LOCK_FILE: &str = "Expected a `Move.lock` file to exist in the package path, \
18                            but none found. Consider running `iota move build` to \
19                            generate the `Move.lock` file in the package directory.";
20
21/// Record addresses (Object IDs) for where this package is published on chain
22/// (this command sets variables in Move.lock).
23#[derive(Parser)]
24#[group(id = "iota-move-manage-package")]
25pub struct ManagePackage {
26    #[arg(long)]
27    /// The environment to associate this package information with (consider
28    /// using `iota client active-env`).
29    pub environment: String,
30    #[arg(long = "network-id")]
31    /// The network chain identifier. Use '6364aad5' for mainnet.
32    pub chain_id: String,
33    #[arg(long, value_parser = ObjectID::from_hex_literal)]
34    /// The original address (Object ID) where this package is published.
35    pub original_id: ObjectID,
36    #[arg(long, value_parser = ObjectID::from_hex_literal)]
37    /// The most recent address (Object ID) where this package is published. It
38    /// is the same as 'original-id' if the package is immutable and
39    /// published once. It is different from 'original-id' if the package has
40    /// been upgraded to a different address.
41    pub latest_id: ObjectID,
42    #[arg(long)]
43    /// The version number of the published package. It is '1' if the package is
44    /// immutable and published once. It is some number greater than '1' if
45    /// the package has been upgraded once or more.
46    pub version_number: u64,
47}
48
49impl ManagePackage {
50    pub fn execute(
51        self,
52        package_path: Option<&Path>,
53        build_config: BuildConfig,
54    ) -> anyhow::Result<()> {
55        let build_config = resolve_lock_file_path(build_config, package_path)?;
56        let Some(lock_file) = build_config.lock_file else {
57            bail!(NO_LOCK_FILE)
58        };
59        if !lock_file.exists() {
60            bail!(NO_LOCK_FILE)
61        };
62        let install_dir = build_config.install_dir.unwrap_or(PathBuf::from("."));
63        let mut lock = LockFile::from(install_dir.clone(), &lock_file)?;
64
65        // Updating managed packages in the Move.lock file is controlled by distinct
66        // `Published` and `Upgraded` commands. To set all relevant values, we
67        // run both commands. First use the `Published` update to set the
68        // environment, chain ID, and original ID.
69        lock_file::schema::update_managed_address(
70            &mut lock,
71            &self.environment,
72            lock_file::schema::ManagedAddressUpdate::Published {
73                chain_id: self.chain_id,
74                original_id: self.original_id.to_string(),
75            },
76        )?;
77        // Next use the `Upgraded` update to subsequently set the latest ID and version.
78        lock_file::schema::update_managed_address(
79            &mut lock,
80            &self.environment,
81            lock_file::schema::ManagedAddressUpdate::Upgraded {
82                latest_id: self.latest_id.to_string(),
83                version: self.version_number,
84            },
85        )?;
86        lock.commit(lock_file)?;
87        Ok(())
88    }
89}
90
91/// Resolve Move.lock file path in package directory (where Move.toml is).
92pub fn resolve_lock_file_path(
93    mut build_config: BuildConfig,
94    package_path: Option<&Path>,
95) -> Result<BuildConfig, anyhow::Error> {
96    if build_config.lock_file.is_none() {
97        let package_root = base::reroot_path(package_path)?;
98        let lock_file_path = package_root.join(SourcePackageLayout::Lock.path());
99        build_config.lock_file = Some(lock_file_path);
100    }
101    Ok(build_config)
102}