passionfruitdev_cli/
cli.rs1use chrono::{Datelike, Timelike, Utc};
2use clap::{Subcommand, ValueEnum};
3use std::process::Command as RunCommand;
4use std::{fmt, fs};
5use toml_edit::{value, Document};
6
7pub use clap::Parser;
8
9#[derive(Parser)]
10#[command(author, version, about, long_about = None)]
11pub struct Cli {
12 #[command(subcommand)]
13 command: Command,
14}
15
16#[derive(Subcommand)]
17enum Command {
18 Install {
19 #[arg(short, long, value_enum, default_value_t = Architecture::Aarch64AppleDarwin)]
20 architecture: Architecture,
21 #[arg(long, value_enum, value_enum, default_value_t = OperatingSystem::MacOS)]
22 os: OperatingSystem,
23 },
24 New {
25 name: String,
26 },
27 Publish {
28 #[arg(short, long, value_enum, default_value_t = Lifecycle::Nightly)]
29 lifecycle: Lifecycle,
30 },
31}
32
33#[derive(ValueEnum, Debug, Clone)]
34#[clap(rename_all = "kebab_case")]
35enum Architecture {
36 Aarch64AppleDarwin,
37}
38
39#[derive(ValueEnum, Debug, Clone)]
40enum OperatingSystem {
41 MacOS,
42}
43
44#[derive(ValueEnum, Debug, Clone, PartialEq)]
45enum Lifecycle {
46 Manual,
47 Pull,
48 Merge,
49 Nightly,
50 Candidate,
51 Official,
52}
53
54impl fmt::Display for Lifecycle {
55 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
56 match self {
57 Lifecycle::Manual => write!(f, "manual"),
58 Lifecycle::Pull => write!(f, "pull"),
59 Lifecycle::Merge => write!(f, "merge"),
60 Lifecycle::Nightly => write!(f, "nightly"),
61 Lifecycle::Candidate => write!(f, "rc"),
62 Lifecycle::Official => write!(f, "official"),
63 }
64 }
65}
66
67pub fn execute(cli: Cli) {
68 match &cli.command {
69 Command::Install { architecture, os } => match (architecture, os) {
70 (Architecture::Aarch64AppleDarwin, OperatingSystem::MacOS) => {
71 println!("Installing Aarch64AppleDarwin on MacOS dependencies");
72 }
73 },
74 Command::New { name } => {
75 println!("Creating project: {}", name)
76 }
77 Command::Publish { lifecycle } => publish(lifecycle),
78 }
79}
80
81fn publish(lifecycle: &Lifecycle) {
82 let datetime = Utc::now();
83 let datetime = format!(
84 "{:02}{:02}{:02}{:02}{:02}{:02}",
85 datetime.year(),
86 datetime.month(),
87 datetime.day(),
88 datetime.hour(),
89 datetime.minute(),
90 datetime.second()
91 );
92 let git_hash = RunCommand::new("git")
93 .args(&["rev-parse", "HEAD"])
94 .output()
95 .unwrap();
96 let git_hash = String::from_utf8(git_hash.stdout).unwrap();
97 let git_hash = git_hash.lines().next().unwrap();
98
99 let dryrun = RunCommand::new("cargo")
100 .args(&["publish", "--dry-run"])
101 .output()
102 .unwrap();
103 if dryrun.status.success() {
104 let current_directory = std::env::current_dir().unwrap();
105 let cargo_toml_path = format!("{}/Cargo.toml", current_directory.display());
106 let cargo_toml_backup_path = format!("{}/Cargo.toml.bak", current_directory.display());
107 let _ = RunCommand::new("cp")
108 .args(&[&cargo_toml_path, &cargo_toml_backup_path])
109 .output()
110 .unwrap();
111 let cargo_toml = fs::read_to_string(&cargo_toml_path).unwrap();
112 let mut cargo_toml = cargo_toml.parse::<Document>().unwrap();
113 let version = cargo_toml["package"]["version"].as_str().unwrap();
114
115 let version = format!(
116 "{}-{}.{}+{}",
117 &version,
118 lifecycle.to_string(),
119 &datetime,
120 &git_hash
121 );
122 cargo_toml["package"]["version"] = value(&version);
123 let _ = fs::write(&cargo_toml_path, cargo_toml.to_string()).unwrap();
124 let _ = RunCommand::new("cargo")
125 .args(&["publish", "--allow-dirty"])
126 .output()
127 .unwrap();
128 let _ = RunCommand::new("mv")
129 .args(&[&cargo_toml_backup_path, &cargo_toml_path])
130 .output()
131 .unwrap();
132 if lifecycle.to_string() == Lifecycle::Official.to_string() {
133 let _ = RunCommand::new("cargo")
134 .args(&["publish"])
135 .output()
136 .unwrap();
137 }
139 } else {
140 println!(
141 "Publish failed dry run with error:\n{}",
142 String::from_utf8_lossy(&dryrun.stderr)
143 );
144 }
145 ()
146}