-
-
Notifications
You must be signed in to change notification settings - Fork 542
/
Copy pathcli.rs
142 lines (122 loc) Β· 3.88 KB
/
cli.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
use std::future::Future;
use clap::Parser;
use dotenvy::dotenv;
use std::{error::Error, fmt::Display, process::exit};
use tracing_subscriber::{prelude::*, EnvFilter};
use sea_orm::{ConnectOptions, Database, DbConn, DbErr};
use sea_orm_cli::{run_migrate_generate, run_migrate_init, MigrateSubcommands};
use super::MigratorTrait;
const MIGRATION_DIR: &str = "./";
pub async fn run_cli<M>(migrator: M)
where
M: MigratorTrait,
{
run_cli_with_connection(migrator, Database::connect).await;
}
/// Same as [`run_cli`] where you provide the function to create the [`DbConn`].
///
/// This allows configuring the database connection as you see fit.
/// E.g. you can change settings in [`ConnectOptions`] or you can load sqlite
/// extensions.
pub async fn run_cli_with_connection<M, F, Fut>(migrator: M, make_connection: F)
where
M: MigratorTrait,
F: FnOnce(ConnectOptions) -> Fut,
Fut: Future<Output = Result<DbConn, DbErr>>,
{
dotenv().ok();
let cli = Cli::parse();
let url = cli
.database_url
.expect("Environment variable 'DATABASE_URL' not set");
let schema = cli.database_schema.unwrap_or_else(|| "public".to_owned());
let connect_options = ConnectOptions::new(url)
.set_schema_search_path(schema)
.to_owned();
let db = make_connection(connect_options)
.await
.expect("Fail to acquire database connection");
run_migrate(migrator, &db, cli.command, cli.verbose)
.await
.unwrap_or_else(handle_error);
}
pub async fn run_migrate<M>(
_: M,
db: &DbConn,
command: Option<MigrateSubcommands>,
verbose: bool,
) -> Result<(), Box<dyn Error>>
where
M: MigratorTrait,
{
let filter = match verbose {
true => "debug",
false => "sea_orm_migration=info",
};
let filter_layer = EnvFilter::try_new(filter).unwrap();
if verbose {
let fmt_layer = tracing_subscriber::fmt::layer();
tracing_subscriber::registry()
.with(filter_layer)
.with(fmt_layer)
.init()
} else {
let fmt_layer = tracing_subscriber::fmt::layer()
.with_target(false)
.with_level(false)
.without_time();
tracing_subscriber::registry()
.with(filter_layer)
.with(fmt_layer)
.init()
};
match command {
Some(MigrateSubcommands::Fresh) => M::fresh(db).await?,
Some(MigrateSubcommands::Refresh) => M::refresh(db).await?,
Some(MigrateSubcommands::Reset) => M::reset(db).await?,
Some(MigrateSubcommands::Status) => M::status(db).await?,
Some(MigrateSubcommands::Up { num }) => M::up(db, num).await?,
Some(MigrateSubcommands::Down { num }) => M::down(db, Some(num)).await?,
Some(MigrateSubcommands::Init) => run_migrate_init(MIGRATION_DIR)?,
Some(MigrateSubcommands::Generate {
migration_name,
universal_time: _,
local_time,
}) => run_migrate_generate(MIGRATION_DIR, &migration_name, !local_time)?,
_ => M::up(db, None).await?,
};
Ok(())
}
#[derive(Parser)]
#[command(version)]
pub struct Cli {
#[arg(short = 'v', long, global = true, help = "Show debug messages")]
verbose: bool,
#[arg(
global = true,
short = 's',
long,
env = "DATABASE_SCHEMA",
long_help = "Database schema\n \
- For MySQL and SQLite, this argument is ignored.\n \
- For PostgreSQL, this argument is optional with default value 'public'.\n"
)]
database_schema: Option<String>,
#[arg(
global = true,
short = 'u',
long,
env = "DATABASE_URL",
help = "Database URL"
)]
database_url: Option<String>,
#[command(subcommand)]
command: Option<MigrateSubcommands>,
}
fn handle_error<E>(error: E)
where
E: Display,
{
eprintln!("{error}");
exit(1);
}