Skip to content

Commit 143ae21

Browse files
committed
update
1 parent 8d3bd73 commit 143ae21

6 files changed

Lines changed: 1292 additions & 1185 deletions

File tree

example/qop.toml

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
version = ">=0.0.0,<1.0.0"
2-
[backend.postgres]
2+
[subsystem.postgres]
33
table = "__qop"
44
schema = "public"
5-
[backend.postgres.connection]
6-
from_env = "QOP_BACKEND_POSTGRES_CONNECTION"
7-
[backend.postgres.migrations]
8-
timeout = 60
5+
timeout = 60
6+
[subsystem.postgres.connection]
7+
from_env = "QOP_BACKEND_POSTGRES_CONNECTION"

src/args.rs

Lines changed: 118 additions & 143 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,9 @@ impl CallArgs {
3030
}
3131

3232
match &self.command {
33-
| Command::Migration(Migration { command: MigrationCommand::Diff, .. }) => anyhow::bail!("diff is experimental"),
34-
| Command::Migration(Migration { command: MigrationCommand::Up { diff: true, .. }, .. }) => anyhow::bail!("diff is experimental"),
35-
| Command::Migration(Migration { command: MigrationCommand::Down { diff: true, .. }, .. }) => anyhow::bail!("diff is experimental"),
33+
| Command::Migration(Migration { subsystem: Subsystem::Postgres(crate::subsystem::postgres::commands::Command::Diff), .. }) => anyhow::bail!("diff is experimental"),
34+
| Command::Migration(Migration { subsystem: Subsystem::Postgres(crate::subsystem::postgres::commands::Command::Up { diff: true, .. }), .. }) => anyhow::bail!("diff is experimental"),
35+
| Command::Migration(Migration { subsystem: Subsystem::Postgres(crate::subsystem::postgres::commands::Command::Down { diff: true, .. }), .. }) => anyhow::bail!("diff is experimental"),
3636
| _ => (),
3737
}
3838

@@ -41,50 +41,14 @@ impl CallArgs {
4141
}
4242

4343
#[derive(Debug)]
44-
pub(crate) enum MigrationApply {
45-
Up {
46-
id: String,
47-
timeout: Option<u64>,
48-
},
49-
Down {
50-
id: String,
51-
timeout: Option<u64>,
52-
remote: bool,
53-
},
54-
}
55-
56-
#[derive(Debug)]
57-
pub(crate) enum HistoryCommand {
58-
Sync,
59-
Fix,
60-
}
61-
62-
63-
#[derive(Debug)]
64-
pub(crate) enum MigrationCommand {
65-
Init,
66-
New,
67-
Up {
68-
timeout: Option<u64>,
69-
count: Option<usize>,
70-
diff: bool,
71-
},
72-
Down {
73-
timeout: Option<u64>,
74-
count: Option<usize>,
75-
remote: bool,
76-
diff: bool,
77-
},
78-
Apply(MigrationApply),
79-
List,
80-
History(HistoryCommand),
81-
Diff,
44+
pub(crate) enum Subsystem {
45+
Postgres(crate::subsystem::postgres::commands::Command),
8246
}
8347

8448
#[derive(Debug)]
8549
pub(crate) struct Migration {
8650
pub path: PathBuf,
87-
pub command: MigrationCommand,
51+
pub subsystem: Subsystem,
8852
}
8953

9054
#[derive(Debug)]
@@ -157,72 +121,79 @@ impl ClapArgumentLoader {
157121
),
158122
)
159123
.subcommand(
160-
clap::Command::new("migration")
161-
.about("Manages migrations.")
162-
.arg(clap::Arg::new("path").short('p').long("path").default_value("qop.toml"))
124+
clap::Command::new("subsystem")
125+
.about("Manages subsystems.")
163126
.subcommand_required(true)
127+
.aliases(["sub", "s"])
164128
.subcommand(
165-
clap::Command::new("init")
166-
.about("Initializes the database."),
167-
)
168-
.subcommand(
169-
clap::Command::new("new")
170-
.about("Creates a new migration."),
171-
)
172-
.subcommand(
173-
clap::Command::new("up")
174-
.about("Runs the migrations.")
175-
.arg(clap::Arg::new("timeout").short('t').long("timeout").required(false))
176-
.arg(clap::Arg::new("count").short('c').long("count").required(false))
177-
.arg(clap::Arg::new("diff").short('d').long("diff").required(false).num_args(0).help("Show migration diff before applying")),
178-
)
179-
.subcommand(
180-
clap::Command::new("down")
181-
.about("Rolls back the migrations.")
182-
.arg(clap::Arg::new("timeout").short('t').long("timeout").required(false))
183-
.arg(clap::Arg::new("remote").short('r').long("remote").required(false).num_args(0))
184-
.arg(clap::Arg::new("count").short('c').long("count").required(false))
185-
.arg(clap::Arg::new("diff").short('d').long("diff").required(false).num_args(0).help("Show migration diff before applying")),
186-
)
187-
.subcommand(
188-
clap::Command::new("list")
189-
.about("Lists all applied migrations."),
190-
)
191-
.subcommand(
192-
clap::Command::new("history")
193-
.about("Manages migration history.")
129+
clap::Command::new("postgres")
130+
.aliases(["pg"])
131+
.about("Manages PostgreSQL migrations.")
132+
.arg(clap::Arg::new("path").short('p').long("path").default_value("qop.toml"))
194133
.subcommand_required(true)
195134
.subcommand(
196-
clap::Command::new("sync")
197-
.about("Upserts all remote migrations locally."),
135+
clap::Command::new("init")
136+
.about("Initializes the database."),
198137
)
199138
.subcommand(
200-
clap::Command::new("fix")
201-
.about("Shuffles all non-run local migrations to the end of the chain."),
202-
),
203-
)
204-
.subcommand(
205-
clap::Command::new("diff")
206-
.about("Shows pending migration operations without applying them."),
207-
)
208-
.subcommand(
209-
clap::Command::new("apply")
210-
.about("Applies or reverts a specific migration by ID.")
211-
.subcommand_required(true)
139+
clap::Command::new("new")
140+
.about("Creates a new migration."),
141+
)
212142
.subcommand(
213143
clap::Command::new("up")
214-
.about("Applies a specific migration.")
215-
.arg(clap::Arg::new("id").help("Migration ID to apply").required(true))
216-
.arg(clap::Arg::new("timeout").short('t').long("timeout").required(false)),
144+
.about("Runs the migrations.")
145+
.arg(clap::Arg::new("timeout").short('t').long("timeout").required(false))
146+
.arg(clap::Arg::new("count").short('c').long("count").required(false))
147+
.arg(clap::Arg::new("diff").short('d').long("diff").required(false).num_args(0).help("Show migration diff before applying")),
217148
)
218149
.subcommand(
219150
clap::Command::new("down")
220-
.about("Reverts a specific migration.")
221-
.arg(clap::Arg::new("id").help("Migration ID to revert").required(true))
151+
.about("Rolls back the migrations.")
222152
.arg(clap::Arg::new("timeout").short('t').long("timeout").required(false))
223-
.arg(clap::Arg::new("remote").short('r').long("remote").required(false).num_args(0)),
153+
.arg(clap::Arg::new("remote").short('r').long("remote").required(false).num_args(0))
154+
.arg(clap::Arg::new("count").short('c').long("count").required(false))
155+
.arg(clap::Arg::new("diff").short('d').long("diff").required(false).num_args(0).help("Show migration diff before applying")),
156+
)
157+
.subcommand(
158+
clap::Command::new("list")
159+
.about("Lists all applied migrations."),
160+
)
161+
.subcommand(
162+
clap::Command::new("history")
163+
.about("Manages migration history.")
164+
.subcommand_required(true)
165+
.subcommand(
166+
clap::Command::new("sync")
167+
.about("Upserts all remote migrations locally."),
168+
)
169+
.subcommand(
170+
clap::Command::new("fix")
171+
.about("Shuffles all non-run local migrations to the end of the chain."),
172+
),
173+
)
174+
.subcommand(
175+
clap::Command::new("diff")
176+
.about("Shows pending migration operations without applying them."),
177+
)
178+
.subcommand(
179+
clap::Command::new("apply")
180+
.about("Applies or reverts a specific migration by ID.")
181+
.subcommand_required(true)
182+
.subcommand(
183+
clap::Command::new("up")
184+
.about("Applies a specific migration.")
185+
.arg(clap::Arg::new("id").help("Migration ID to apply").required(true))
186+
.arg(clap::Arg::new("timeout").short('t').long("timeout").required(false)),
187+
)
188+
.subcommand(
189+
clap::Command::new("down")
190+
.about("Reverts a specific migration.")
191+
.arg(clap::Arg::new("id").help("Migration ID to revert").required(true))
192+
.arg(clap::Arg::new("timeout").short('t').long("timeout").required(false))
193+
.arg(clap::Arg::new("remote").short('r').long("remote").required(false).num_args(0)),
194+
),
224195
),
225-
),
196+
)
226197
)
227198
}
228199

@@ -253,60 +224,64 @@ impl ClapArgumentLoader {
253224
Command::Init {
254225
path: Self::get_absolute_path(subc, "path")?,
255226
}
256-
} else if let Some(subc) = command.subcommand_matches("migration") {
257-
let path = Self::get_absolute_path(subc, "path")?;
258-
let migration_cmd = if let Some(_) = subc.subcommand_matches("init") {
259-
MigrationCommand::Init
260-
} else if let Some(_) = subc.subcommand_matches("new") {
261-
MigrationCommand::New
262-
} else if let Some(up_subc) = subc.subcommand_matches("up") {
263-
MigrationCommand::Up {
264-
timeout: up_subc.get_one::<String>("timeout").map(|s| s.parse::<u64>().unwrap()),
265-
count: up_subc.get_one::<String>("count").map(|s| s.parse::<usize>().unwrap()),
266-
diff: up_subc.get_flag("diff"),
267-
}
268-
} else if let Some(down_subc) = subc.subcommand_matches("down") {
269-
MigrationCommand::Down {
270-
timeout: down_subc.get_one::<String>("timeout").map(|s| s.parse::<u64>().unwrap()),
271-
count: down_subc.get_one::<String>("count").map(|s| s.parse::<usize>().unwrap()),
272-
remote: down_subc.get_flag("remote"),
273-
diff: down_subc.get_flag("diff"),
274-
}
275-
} else if let Some(_) = subc.subcommand_matches("list") {
276-
MigrationCommand::List
277-
} else if let Some(history_subc) = subc.subcommand_matches("history") {
278-
let history_cmd = if let Some(_) = history_subc.subcommand_matches("sync") {
279-
HistoryCommand::Sync
280-
} else if let Some(_) = history_subc.subcommand_matches("fix") {
281-
HistoryCommand::Fix
282-
} else {
283-
unreachable!();
284-
};
285-
MigrationCommand::History(history_cmd)
286-
} else if let Some(_) = subc.subcommand_matches("diff") {
287-
MigrationCommand::Diff
288-
} else if let Some(apply_subc) = subc.subcommand_matches("apply") {
289-
if let Some(up_subc) = apply_subc.subcommand_matches("up") {
290-
MigrationCommand::Apply(MigrationApply::Up {
291-
id: up_subc.get_one::<String>("id").unwrap().clone(),
227+
} else if let Some(subsystem_subc) = command.subcommand_matches("subsystem") {
228+
if let Some(postgres_subc) = subsystem_subc.subcommand_matches("postgres") {
229+
let path = Self::get_absolute_path(postgres_subc, "path")?;
230+
let postgres_cmd = if let Some(_) = postgres_subc.subcommand_matches("init") {
231+
crate::subsystem::postgres::commands::Command::Init
232+
} else if let Some(_) = postgres_subc.subcommand_matches("new") {
233+
crate::subsystem::postgres::commands::Command::New
234+
} else if let Some(up_subc) = postgres_subc.subcommand_matches("up") {
235+
crate::subsystem::postgres::commands::Command::Up {
292236
timeout: up_subc.get_one::<String>("timeout").map(|s| s.parse::<u64>().unwrap()),
293-
})
294-
} else if let Some(down_subc) = apply_subc.subcommand_matches("down") {
295-
MigrationCommand::Apply(MigrationApply::Down {
296-
id: down_subc.get_one::<String>("id").unwrap().clone(),
237+
count: up_subc.get_one::<String>("count").map(|s| s.parse::<usize>().unwrap()),
238+
diff: up_subc.get_flag("diff"),
239+
}
240+
} else if let Some(down_subc) = postgres_subc.subcommand_matches("down") {
241+
crate::subsystem::postgres::commands::Command::Down {
297242
timeout: down_subc.get_one::<String>("timeout").map(|s| s.parse::<u64>().unwrap()),
243+
count: down_subc.get_one::<String>("count").map(|s| s.parse::<usize>().unwrap()),
298244
remote: down_subc.get_flag("remote"),
299-
})
245+
diff: down_subc.get_flag("diff"),
246+
}
247+
} else if let Some(_) = postgres_subc.subcommand_matches("list") {
248+
crate::subsystem::postgres::commands::Command::List
249+
} else if let Some(history_subc) = postgres_subc.subcommand_matches("history") {
250+
let history_cmd = if let Some(_) = history_subc.subcommand_matches("sync") {
251+
crate::subsystem::postgres::commands::HistoryCommand::Sync
252+
} else if let Some(_) = history_subc.subcommand_matches("fix") {
253+
crate::subsystem::postgres::commands::HistoryCommand::Fix
254+
} else {
255+
unreachable!();
256+
};
257+
crate::subsystem::postgres::commands::Command::History(history_cmd)
258+
} else if let Some(_) = postgres_subc.subcommand_matches("diff") {
259+
crate::subsystem::postgres::commands::Command::Diff
260+
} else if let Some(apply_subc) = postgres_subc.subcommand_matches("apply") {
261+
if let Some(up_subc) = apply_subc.subcommand_matches("up") {
262+
crate::subsystem::postgres::commands::Command::Apply(crate::subsystem::postgres::commands::MigrationApply::Up {
263+
id: up_subc.get_one::<String>("id").unwrap().clone(),
264+
timeout: up_subc.get_one::<String>("timeout").map(|s| s.parse::<u64>().unwrap()),
265+
})
266+
} else if let Some(down_subc) = apply_subc.subcommand_matches("down") {
267+
crate::subsystem::postgres::commands::Command::Apply(crate::subsystem::postgres::commands::MigrationApply::Down {
268+
id: down_subc.get_one::<String>("id").unwrap().clone(),
269+
timeout: down_subc.get_one::<String>("timeout").map(|s| s.parse::<u64>().unwrap()),
270+
remote: down_subc.get_flag("remote"),
271+
})
272+
} else {
273+
unreachable!();
274+
}
300275
} else {
301276
unreachable!();
302-
}
277+
};
278+
Command::Migration(Migration {
279+
path,
280+
subsystem: Subsystem::Postgres(postgres_cmd),
281+
})
303282
} else {
304-
unreachable!();
305-
};
306-
Command::Migration(Migration {
307-
path,
308-
command: migration_cmd,
309-
})
283+
return Err(anyhow::anyhow!("subsystem required"));
284+
}
310285
} else {
311286
return Err(anyhow::anyhow!("unknown command"));
312287
};

src/config.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,13 +40,12 @@ impl WithVersion {
4040
#[serde(rename_all = "snake_case")]
4141
pub struct Config {
4242
pub version: String,
43-
pub backend: Backend,
43+
pub subsystem: Subsystem,
4444
}
4545

4646
#[derive(Debug, Serialize, Deserialize)]
4747
#[serde(rename_all = "snake_case")]
4848
pub struct PostgresMigrations {
49-
pub timeout: Option<u64>,
5049
}
5150

5251

@@ -60,10 +59,10 @@ pub enum DataSource<T: Serialize + DeserializeOwned> {
6059

6160
#[derive(Debug, Serialize, Deserialize)]
6261
#[serde(rename_all = "snake_case")]
63-
pub enum Backend {
62+
pub enum Subsystem {
6463
Postgres {
6564
connection: DataSource<String>,
66-
migrations: PostgresMigrations,
65+
timeout: Option<u64>,
6766
schema: String,
6867
table: String,
6968
},

0 commit comments

Comments
 (0)