Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
8 changes: 8 additions & 0 deletions zk_toolbox/Cargo.lock

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

3 changes: 3 additions & 0 deletions zk_toolbox/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ members = [
"crates/types",
"crates/zk_inception",
"crates/zk_supervisor",
"crates/git_version_macro",
]
resolver = "2"

Expand All @@ -25,6 +26,7 @@ keywords = ["zk", "cryptography", "blockchain", "ZKStack", "ZKsync"]
common = { path = "crates/common" }
config = { path = "crates/config" }
types = { path = "crates/types" }
git_version_macro = { path = "crates/git_version_macro" }

# ZkSync deps
zksync_config = { path = "../core/lib/config" }
Expand All @@ -37,6 +39,7 @@ zksync_protobuf = "=0.1.1"
# External dependencies
anyhow = "1.0.82"
clap = { version = "4.4", features = ["derive", "wrap_help", "string"] }
chrono = "0.4"
slugify-rs = "0.0.3"
cliclack = "0.2.5"
console = "0.15.8"
Expand Down
1 change: 1 addition & 0 deletions zk_toolbox/crates/common/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,4 @@ url.workspace = true
xshell.workspace = true
thiserror.workspace = true
strum.workspace = true
git_version_macro.workspace = true
1 change: 1 addition & 0 deletions zk_toolbox/crates/common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ pub mod files;
pub mod forge;
pub mod git;
pub mod server;
pub mod version;
pub mod wallets;

pub use prerequisites::{
Expand Down
24 changes: 24 additions & 0 deletions zk_toolbox/crates/common/src/version.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
const GIT_VERSION: &str = git_version_macro::build_git_revision!();
const GIT_BRANCH: &str = git_version_macro::build_git_branch!();
const GIT_SUBMODULES: &[(&str, &str)] = git_version_macro::build_git_submodules!();
const BUILD_TIMESTAMP: &str = git_version_macro::build_timestamp!();

/// Returns a multi-line version message that includes:
/// - provided crate version
/// - git revision
/// - git branch
/// - git submodules
/// - build timestamp
pub fn version_message(crate_version: &str) -> String {
let mut version = format!("v{}-{}\n", crate_version, GIT_VERSION);
version.push_str(&format!("Branch: {}\n", GIT_BRANCH));
#[allow(clippy::const_is_empty)] // Proc-macro generated.
if !GIT_SUBMODULES.is_empty() {
version.push_str("Submodules:\n");
for (name, rev) in GIT_SUBMODULES {
version.push_str(&format!(" - {}: {}\n", name, rev));
}
}
version.push_str(&format!("Build timestamp: {}\n", BUILD_TIMESTAMP));
version
}
17 changes: 17 additions & 0 deletions zk_toolbox/crates/git_version_macro/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
[package]
name = "git_version_macro"
edition = "2021"
description = "Procedural macro to generate metainformation about build in compile time"
version.workspace = true
homepage.workspace = true
license.workspace = true
authors.workspace = true
exclude.workspace = true
repository.workspace = true
keywords.workspace = true

[lib]
proc-macro = true

[dependencies]
chrono.workspace = true
81 changes: 81 additions & 0 deletions zk_toolbox/crates/git_version_macro/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
extern crate proc_macro;
use std::{process::Command, str::FromStr};

use proc_macro::TokenStream;

/// Outputs the current date and time as a string literal.
/// Can be used to include the build timestamp in the binary.
#[proc_macro]
pub fn build_timestamp(_item: TokenStream) -> TokenStream {
let now = chrono::Local::now().format("%Y-%m-%d %H:%M:%S").to_string();
encode_as_str(&now)
}

/// Outputs the current git branch as a string literal.
#[proc_macro]
pub fn build_git_branch(_item: TokenStream) -> TokenStream {
let out = run_cmd("git", &["rev-parse", "--abbrev-ref", "HEAD"]);
encode_as_str(&out)
}

/// Outputs the current git commit hash as a string literal.
#[proc_macro]
pub fn build_git_revision(_item: TokenStream) -> TokenStream {
let out = run_cmd("git", &["rev-parse", "--short", "HEAD"]);
encode_as_str(&out)
}

/// Creates a slice of `&[(&str, &str)]` tuples that correspond to
/// the submodule name -> revision.
/// Results in an empty list if there are no submodules or if
/// the command fails.
#[proc_macro]
pub fn build_git_submodules(_item: TokenStream) -> TokenStream {
let Some(out) = run_cmd_opt("git", &["submodule", "status"]) else {
return TokenStream::from_str("&[]").unwrap();
};
let submodules = out
.lines()
.filter_map(|line| {
let parts: Vec<&str> = line.split_whitespace().collect();
// Index 0 is commit hash, index 1 is the path to the folder, and there
// may be some metainformation after that.
if parts.len() >= 2 {
let folder_name = parts[1].split('/').last().unwrap_or(parts[1]);
Some((folder_name, parts[0]))
} else {
None
}
})
.collect::<Vec<_>>();
let submodules = submodules
.iter()
.map(|(name, rev)| format!("(\"{}\", \"{}\")", name, rev))
.collect::<Vec<_>>()
.join(", ");
TokenStream::from_str(format!("&[{}]", submodules).as_str())
.unwrap_or_else(|_| panic!("Unable to encode submodules: {}", submodules))
}

/// Tries to run the command, only returns `Some` if the command
/// succeeded and the output was valid utf8.
fn run_cmd(cmd: &str, args: &[&str]) -> String {
run_cmd_opt(cmd, args).unwrap_or("unknown".to_string())
}

fn run_cmd_opt(cmd: &str, args: &[&str]) -> Option<String> {
let output = Command::new(cmd).args(args).output().ok()?;
if output.status.success() {
String::from_utf8(output.stdout)
.ok()
.map(|s| s.trim().to_string())
} else {
None
}
}

/// Encodes string as a literal.
fn encode_as_str(s: &str) -> TokenStream {
TokenStream::from_str(format!("\"{}\"", s).as_str())
.unwrap_or_else(|_| panic!("Unable to encode string: {}", s))
}
11 changes: 9 additions & 2 deletions zk_toolbox/crates/zk_inception/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use common::{
config::{global_config, init_global_config, GlobalConfig},
error::log_error,
init_prompt_theme, logger,
version::version_message,
};
use config::EcosystemConfig;
use xshell::Shell;
Expand All @@ -26,7 +27,10 @@ mod messages;
mod utils;

#[derive(Parser, Debug)]
#[command(version, about)]
#[command(
version = version_message(env!("CARGO_PKG_VERSION")),
about
)]
struct Inception {
#[command(subcommand)]
command: InceptionSubcommands,
Expand Down Expand Up @@ -86,13 +90,16 @@ struct InceptionGlobalArgs {
async fn main() -> anyhow::Result<()> {
human_panic::setup_panic!();

// We must parse arguments before printing the intro, because some autogenerated
// Clap commands (like `--version` would look odd otherwise).
let inception_args = Inception::parse();

init_prompt_theme();

logger::new_empty_line();
logger::intro();

let shell = Shell::new().unwrap();
let inception_args = Inception::parse();

init_global_config_inner(&shell, &inception_args.global)?;

Expand Down
12 changes: 9 additions & 3 deletions zk_toolbox/crates/zk_supervisor/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use common::{
config::{global_config, init_global_config, GlobalConfig},
error::log_error,
init_prompt_theme, logger,
version::version_message,
};
use config::EcosystemConfig;
use messages::{
Expand All @@ -25,7 +26,10 @@ mod defaults;
mod messages;

#[derive(Parser, Debug)]
#[command(version, about)]
#[command(
version = version_message(env!("CARGO_PKG_VERSION")),
about
)]
struct Supervisor {
#[command(subcommand)]
command: SupervisorSubcommands,
Expand Down Expand Up @@ -73,14 +77,16 @@ struct SupervisorGlobalArgs {
async fn main() -> anyhow::Result<()> {
human_panic::setup_panic!();

// We must parse arguments before printing the intro, because some autogenerated
// Clap commands (like `--version` would look odd otherwise).
let args = Supervisor::parse();

init_prompt_theme();

logger::new_empty_line();
logger::intro();

let shell = Shell::new().unwrap();
let args = Supervisor::parse();

init_global_config_inner(&shell, &args.global)?;

if !global_config().ignore_prerequisites {
Expand Down
Loading