1use clap::{ArgAction, Parser, Subcommand};
2
3use crate::init::init;
4use crate::make_migrations::{run_make_migrations, MakeMigrationsOptions};
5use crate::migrate::{run_migrate, MigrateOptions};
6use crate::squash_migrations::squash_migrations;
7
8#[derive(Subcommand)]
9pub enum InitDriver {
10 #[cfg(feature = "sqlite")]
11 #[clap(about = "Initialize a sqlite configuration")]
12 Sqlite {
13 #[clap(long = "filename")]
14 #[clap(default_value_t = String::from("db.sqlite3"))]
15 #[clap(help = "Name of the sqlite file.")]
16 filename: String,
17 },
18 #[cfg(feature = "mysql")]
19 #[clap(about = "Initialize a mysql configuration")]
20 Mysql {
21 #[clap(long = "host")]
22 #[clap(default_value_t = String::from("127.0.0.1"))]
23 #[clap(help = "The address to use to connect to the database.")]
24 host: String,
25 #[clap(long = "port")]
26 #[clap(default_value_t = 5432)]
27 #[clap(help = "The port to use to connect to the database.")]
28 port: u16,
29 #[clap(long = "user")]
30 #[clap(default_value_t = String::from("dbuser"))]
31 #[clap(help = "The user to use to connect to the database.")]
32 user: String,
33 #[clap(long = "password")]
34 #[clap(
35 help = "Set the password. To minimize the risk of exposing your password, use --ask-password instead."
36 )]
37 password: Option<String>,
38 #[clap(long = "ask-password")]
39 #[clap(
40 help = "Ask for the password for the database. If specified with the --password option, this value will be prevalent."
41 )]
42 ask_password: bool,
43 #[clap(long = "name")]
44 #[clap(default_value_t = String::from("dbname"))]
45 #[clap(help = "The name of the database to connect to.")]
46 name: String,
47 },
48 #[cfg(feature = "postgres")]
49 #[clap(about = "Initialize a postgres configuration")]
50 Postgres {
51 #[clap(long = "host")]
52 #[clap(default_value_t = String::from("127.0.0.1"))]
53 #[clap(help = "The address to use to connect to the database.")]
54 host: String,
55 #[clap(long = "port")]
56 #[clap(default_value_t = 5432)]
57 #[clap(help = "The port to use to connect to the database.")]
58 port: u16,
59 #[clap(long = "user")]
60 #[clap(default_value_t = String::from("dbuser"))]
61 #[clap(help = "The user to use to connect to the database.")]
62 user: String,
63 #[clap(long = "password")]
64 #[clap(
65 help = "Set the password. To minimize the risk of exposing your password, use --ask-password instead."
66 )]
67 password: Option<String>,
68 #[clap(long = "ask-password")]
69 #[clap(
70 help = "Ask for the password for the database. If specified with the --password option, this value will be prevalent."
71 )]
72 ask_password: bool,
73 #[clap(long = "name")]
74 #[clap(default_value_t = String::from("dbname"))]
75 #[clap(help = "The name of the database to connect to.")]
76 name: String,
77 },
78}
79
80#[derive(Subcommand)]
81enum Commands {
82 #[clap(about = "Create the database configuration file")]
83 Init {
84 #[clap(long = "database-config")]
85 #[clap(default_value_t = String::from("./database.toml"))]
86 #[clap(help = "Path to the database configuration file that should be created.")]
87 database_config: String,
88
89 #[clap(short = 'f', long = "force")]
90 #[clap(help = "Overwrite the database configuration if it is existent already")]
91 force: bool,
92
93 #[clap(subcommand)]
94 driver: InitDriver,
95 },
96
97 #[clap(about = "Tool to create migrations")]
98 MakeMigrations {
99 #[clap(long = "models-file")]
100 #[clap(default_value_t=String::from("./.models.json"))]
101 #[clap(help = "Location of the intermediate representation of models.")]
102 models_file: String,
103
104 #[clap(short = 'm', long = "migration-dir")]
105 #[clap(default_value_t=String::from("./migrations/"))]
106 #[clap(help = "Destination to / from which migrations are written / read.")]
107 migration_dir: String,
108
109 #[clap(help = "Use this name as migration name instead of generating one.")]
110 name: Option<String>,
111
112 #[clap(long = "non-interactive")]
113 #[clap(action = ArgAction::SetTrue)]
114 #[clap(help = "If set, no questions will be asked.")]
115 non_interactive: bool,
116
117 #[clap(long = "disable-warnings")]
118 #[clap(action = ArgAction::SetTrue)]
119 #[clap(help = "If set, no warnings will be printed.")]
120 warnings_disabled: bool,
121 },
122
123 #[clap(about = "Apply migrations")]
124 Migrate {
125 #[clap(short = 'm', long = "migration-dir")]
126 #[clap(default_value_t=String::from("./migrations/"))]
127 #[clap(help = "Destination to / from which migrations are written / read.")]
128 migration_dir: String,
129
130 #[clap(long = "database-config")]
131 #[clap(default_value_t=String::from("./database.toml"))]
132 #[clap(help = "Path to the database configuration file.")]
133 database_config: String,
134
135 #[clap(long = "log-sql")]
136 #[clap(action = ArgAction::SetTrue)]
137 #[clap(help = "If turned on, all queries to the database will be logged")]
138 log_queries: bool,
139
140 #[clap(long = "apply-until")]
141 #[clap(id = "MIGRATION_ID")]
142 #[clap(help = "Only apply the migrations to (inclusive) the given migration.")]
143 apply_until: Option<u16>,
144 },
145
146 #[clap(about = "Squash migrations")]
147 SquashMigrations {
148 #[clap(short = 'm', long = "migration-dir")]
149 #[clap(default_value_t = String::from("./migrations/"))]
150 #[clap(help = "Destination to / from which migrations are written / read.")]
151 migration_dir: String,
152
153 #[clap(help = "First migration to start squashing from.")]
154 first_migration: u16,
155
156 #[clap(help = "Last migration to squash.")]
157 last_migration: u16,
158 },
159
160 #[clap(about = "Merge migrations")]
161 MergeMigrations {},
162}
163
164#[derive(Parser)]
165#[clap(version, about = "CLI tool for rorm", long_about = None)]
166#[clap(arg_required_else_help = true)]
167#[clap(name = "rorm-cli")]
168pub struct Cli {
169 #[clap(subcommand)]
170 command: Option<Commands>,
171}
172
173pub async fn entry(cli: Cli) -> anyhow::Result<()> {
174 match cli.command {
175 Some(Commands::Init {
176 force,
177 driver,
178 database_config,
179 }) => init(database_config, driver, force)?,
180 Some(Commands::MakeMigrations {
181 models_file,
182 migration_dir,
183 name,
184 non_interactive,
185 warnings_disabled,
186 }) => {
187 run_make_migrations(MakeMigrationsOptions {
188 models_file,
189 migration_dir,
190 name,
191 non_interactive,
192 warnings_disabled,
193 })?;
194 }
195 Some(Commands::Migrate {
196 migration_dir,
197 database_config,
198 log_queries,
199 apply_until,
200 }) => {
201 run_migrate(MigrateOptions {
202 migration_dir,
203 database_config,
204 log_queries,
205 apply_until,
206 })
207 .await?;
208 }
209 Some(Commands::SquashMigrations {
210 migration_dir,
211 first_migration,
212 last_migration,
213 }) => {
214 squash_migrations(migration_dir, first_migration, last_migration).await?;
215 }
216 _ => {}
217 }
218
219 Ok(())
220}