sql_from_models_cli/
opt.rs

1use anyhow::Result;
2use sqlx::migrate::{MigrateError, Migrator};
3use std::path::Path;
4use structopt::StructOpt;
5#[derive(StructOpt, Debug)]
6pub struct Opt {
7    #[structopt(subcommand)]
8    pub command: Command,
9}
10
11#[derive(StructOpt, Debug)]
12pub enum Command {
13    #[structopt(alias = "db")]
14    Database(DatabaseOpt),
15
16    #[structopt(alias = "mig")]
17    Migrate(MigrateOpt),
18
19    #[structopt(alias = "gen")]
20    Generate(GenerateOpt),
21}
22
23/// Group of commands for creating and dropping your database.
24#[derive(StructOpt, Debug)]
25pub struct DatabaseOpt {
26    #[structopt(subcommand)]
27    pub command: DatabaseCommand,
28}
29
30#[derive(StructOpt, Debug)]
31pub enum DatabaseCommand {
32    /// Creates the database specified in your DATABASE_URL.
33    Create {
34        /// Location of the DB, by default will be read from the DATABASE_URL env var
35        #[structopt(long, short = "D", env)]
36        database_url: String,
37    },
38
39    /// Drops the database specified in your DATABASE_URL.
40    Drop {
41        /// Automatic confirmation. Without this option, you will be prompted before dropping
42        /// your database.
43        #[structopt(short)]
44        yes: bool,
45
46        /// Location of the DB, by default will be read from the DATABASE_URL env var
47        #[structopt(long, short = "D", env)]
48        database_url: String,
49    },
50
51    /// Drops the database specified in your DATABASE_URL, re-creates it, and runs any pending migrations.
52    Reset {
53        /// Automatic confirmation. Without this option, you will be prompted before dropping
54        /// your database.
55        #[structopt(short)]
56        yes: bool,
57
58        /// Path to folder containing migrations.
59        #[structopt(long, default_value = "migrations")]
60        source: String,
61
62        /// Location of the DB, by default will be read from the DATABASE_URL env var
63        #[structopt(long, short = "D", env)]
64        database_url: String,
65    },
66
67    /// Creates the database specified in your DATABASE_URL and runs any pending migrations.
68    Setup {
69        /// Path to folder containing migrations.
70        #[structopt(long, default_value = "migrations")]
71        source: String,
72
73        /// Location of the DB, by default will be read from the DATABASE_URL env var
74        #[structopt(long, short = "D", env)]
75        database_url: String,
76    },
77}
78
79/// Group of commands for creating and running migrations.
80#[derive(StructOpt, Debug)]
81pub struct MigrateOpt {
82    /// Path to folder containing migrations.
83    #[structopt(long, default_value = "migrations")]
84    pub source: String,
85
86    #[structopt(subcommand)]
87    pub command: MigrateCommand,
88}
89/// Commands related to automatic migration generation.
90#[derive(StructOpt, Debug)]
91pub struct GenerateOpt {
92    /// Location of the DB, by default will be read from the DATABASE_URL env var
93    #[structopt(long, short = "D", env)]
94    pub database_url: String,
95    /// Path to folder containing migrations.
96    #[structopt(long, default_value = "migrations")]
97    pub source: String,
98    /// Used to filter through the sql_from_models to execute.
99    #[structopt(long)]
100    pub table: Option<String>,
101    /// Used to generate a down migrations along with up migrations.
102    #[structopt(short)]
103    pub reversible: bool,
104}
105
106impl GenerateOpt {
107    pub async fn validate(&self) -> Result<()> {
108        url::Url::parse(&self.database_url)?;
109        let migrator = Migrator::new(Path::new(&self.source)).await?;
110        for migration in migrator.iter() {
111            if migration.migration_type.is_reversible() != self.reversible {
112                Err(MigrateError::InvalidMixReversibleAndSimple)?
113            }
114        }
115
116        Ok(())
117    }
118}
119
120#[derive(StructOpt, Debug)]
121pub enum MigrateCommand {
122    /// Create a new migration with the given description,
123    /// and the current time as the version.
124    Add {
125        description: String,
126
127        /// If true, creates a pair of up and down migration files with same version
128        /// else creates a single sql file
129        #[structopt(short)]
130        reversible: bool,
131    },
132
133    /// Run all pending migrations.
134    Run {
135        /// List all the migrations to be run without applying
136        #[structopt(long)]
137        dry_run: bool,
138
139        /// Ignore applied migrations that missing in the resolved migrations
140        #[structopt(long)]
141        ignore_missing: bool,
142
143        /// Location of the DB, by default will be read from the DATABASE_URL env var
144        #[structopt(long, short = "D", env)]
145        database_url: String,
146    },
147
148    /// Revert the latest migration with a down file.
149    Revert {
150        /// List the migration to be reverted without applying
151        #[structopt(long)]
152        dry_run: bool,
153
154        /// Ignore applied migrations that missing in the resolved migrations
155        #[structopt(long)]
156        ignore_missing: bool,
157
158        /// Location of the DB, by default will be read from the DATABASE_URL env var
159        #[structopt(long, short = "D", env)]
160        database_url: String,
161    },
162
163    /// List all available migrations.
164    Info {
165        /// Location of the DB, by default will be read from the DATABASE_URL env var
166        #[structopt(long, env)]
167        database_url: String,
168    },
169
170    /// Generate a `build.rs` to trigger recompilation when a new migration is added.
171    ///
172    /// Must be run in a Cargo project root.
173    BuildScript {
174        /// Overwrite the build script if it already exists.
175        #[structopt(long)]
176        force: bool,
177    },
178}