diff --git a/external-crates/move/crates/move-cli/src/base/new.rs b/external-crates/move/crates/move-cli/src/base/new.rs index 7c0baff52846f..05d992fbfa642 100644 --- a/external-crates/move/crates/move-cli/src/base/new.rs +++ b/external-crates/move/crates/move-cli/src/base/new.rs @@ -1,18 +1,13 @@ // Copyright (c) The Move Contributors // SPDX-License-Identifier: Apache-2.0 -use anyhow::anyhow; +use anyhow::{self, ensure, Context}; use clap::*; use move_core_types::identifier::Identifier; use move_package::source_package::layout::SourcePackageLayout; +use std::io::{BufRead, BufReader}; use std::{fmt::Display, fs::create_dir_all, io::Write, path::Path}; -// TODO get a stable path to this stdlib -// pub const MOVE_STDLIB_PACKAGE_NAME: &str = "MoveStdlib"; -// pub const MOVE_STDLIB_PACKAGE_PATH: &str = "{ \ -// git = \"https://github.com/move-language/move.git\", \ -// subdir = \"language/move-stdlib\", rev = \"main\" \ -// }"; pub const MOVE_STDLIB_ADDR_NAME: &str = "std"; pub const MOVE_STDLIB_ADDR_VALUE: &str = "0x1"; @@ -43,17 +38,53 @@ impl New { custom: &str, // anything else that needs to end up being in Move.toml (or empty string) ) -> anyhow::Result<()> { // TODO warn on build config flags - let Self { name } = self; - if !Identifier::is_valid(&name) { - return Err(anyhow!( - "Invalid package name. Package name must start with a lowercase letter \ - and consist only of lowercase letters, numbers, and underscores." - )); - } + ensure!( + Identifier::is_valid(&self.name), + "Invalid package name. Package name must start with a lowercase letter \ + and consist only of lowercase letters, numbers, and underscores." + ); - let path = path.unwrap_or_else(|| Path::new(&name)); + let path = path.unwrap_or_else(|| Path::new(&self.name)); create_dir_all(path.join(SourcePackageLayout::Sources.path()))?; + + self.write_move_toml(path, deps, addrs, custom)?; + self.write_gitignore(path)?; + Ok(()) + } + + /// add `build/*` to `{path}/.gitignore` if it doesn't already have it + fn write_gitignore(&self, path: &Path) -> anyhow::Result<()> { + let gitignore_entry = "build/*"; + + let mut file = std::fs::OpenOptions::new() + .create(true) + .truncate(false) + .read(true) + .write(true) + .open(path.join(".gitignore")) + .context("Unexpected error creating .gitignore")?; + + for line in BufReader::new(&file).lines().map_while(Result::ok) { + if line == gitignore_entry { + return Ok(()); + } + } + + writeln!(file, "{gitignore_entry}")?; + Ok(()) + } + + /// create default `Move.toml` + fn write_move_toml( + &self, + path: &Path, + deps: impl IntoIterator, + addrs: impl IntoIterator, + custom: &str, // anything else that needs to end up being in Move.toml (or empty string) + ) -> anyhow::Result<()> { + let Self { name } = self; + let mut w = std::fs::File::create(path.join(SourcePackageLayout::Manifest.path()))?; writeln!( w, diff --git a/external-crates/move/crates/move-cli/tests/build_tests/new_clobber/gitignore_exists/args.exp b/external-crates/move/crates/move-cli/tests/build_tests/new_clobber/gitignore_exists/args.exp new file mode 100644 index 0000000000000..d8d7505e4870f --- /dev/null +++ b/external-crates/move/crates/move-cli/tests/build_tests/new_clobber/gitignore_exists/args.exp @@ -0,0 +1,8 @@ +Command `new -p package example`: +External Command `cat package/.gitignore`: +existing_ignore +build/* +External Command `ls -A package`: +.gitignore +Move.toml +sources diff --git a/external-crates/move/crates/move-cli/tests/build_tests/new_clobber/gitignore_exists/args.txt b/external-crates/move/crates/move-cli/tests/build_tests/new_clobber/gitignore_exists/args.txt new file mode 100644 index 0000000000000..4f78cafe6830c --- /dev/null +++ b/external-crates/move/crates/move-cli/tests/build_tests/new_clobber/gitignore_exists/args.txt @@ -0,0 +1,4 @@ +# if `.gitignore` exists, everything should be created and .gitignore should be extended +new -p package example +>cat package/.gitignore +>ls -A package diff --git a/external-crates/move/crates/move-cli/tests/build_tests/new_clobber/gitignore_exists/package/.gitignore b/external-crates/move/crates/move-cli/tests/build_tests/new_clobber/gitignore_exists/package/.gitignore new file mode 100644 index 0000000000000..69817b3665c00 --- /dev/null +++ b/external-crates/move/crates/move-cli/tests/build_tests/new_clobber/gitignore_exists/package/.gitignore @@ -0,0 +1 @@ +existing_ignore diff --git a/external-crates/move/crates/move-cli/tests/build_tests/simple_new/args.exp b/external-crates/move/crates/move-cli/tests/build_tests/new_simple/args.exp similarity index 96% rename from external-crates/move/crates/move-cli/tests/build_tests/simple_new/args.exp rename to external-crates/move/crates/move-cli/tests/build_tests/new_simple/args.exp index d46c9a32f0833..5e3954b528e1d 100644 --- a/external-crates/move/crates/move-cli/tests/build_tests/simple_new/args.exp +++ b/external-crates/move/crates/move-cli/tests/build_tests/new_simple/args.exp @@ -35,6 +35,8 @@ edition = "2024.beta" # edition = "legacy" to use legacy (pre-2024) Move # and `--dev` modes. # alice = "0xB0B" +External Command `cat P1/.gitignore`: +build/* Command `new P2 -p other_dir`: External Command `cat other_dir/Move.toml`: [package] @@ -72,3 +74,5 @@ edition = "2024.beta" # edition = "legacy" to use legacy (pre-2024) Move # and `--dev` modes. # alice = "0xB0B" +External Command `cat other_dir/.gitignore`: +build/* diff --git a/external-crates/move/crates/move-cli/tests/build_tests/simple_new/args.txt b/external-crates/move/crates/move-cli/tests/build_tests/new_simple/args.txt similarity index 60% rename from external-crates/move/crates/move-cli/tests/build_tests/simple_new/args.txt rename to external-crates/move/crates/move-cli/tests/build_tests/new_simple/args.txt index f7b7ec18ae0aa..045be5bf2a401 100644 --- a/external-crates/move/crates/move-cli/tests/build_tests/simple_new/args.txt +++ b/external-crates/move/crates/move-cli/tests/build_tests/new_simple/args.txt @@ -1,5 +1,7 @@ new P1 > cat P1/Move.toml +> cat P1/.gitignore new P2 -p other_dir > cat other_dir/Move.toml +> cat other_dir/.gitignore