Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Branches: REPL backslash commands for branches #1284

Merged
merged 9 commits into from
Apr 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/branch/current.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crossterm::style::Stylize;
use crate::branch::context::Context;
use crate::branch::option::Current;
use crate::connect::Connection;


pub async fn main(
options: &Current,
Expand Down
41 changes: 27 additions & 14 deletions src/branch/main.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@

use crate::branch::context::Context;
use crate::branch::option::{BranchCommand, Command};
use crate::branch::{create, current, drop, list, merge, rebase, rename, switch, wipe};
Expand All @@ -10,31 +11,43 @@ use edgedb_tokio::get_project_dir;
pub async fn branch_main(options: &Options, cmd: &BranchCommand) -> anyhow::Result<()> {
let context = create_context().await?;

run_branch_command(&cmd.subcommand, options, &context, None).await
}

pub async fn run_branch_command(cmd: &Command, options: &Options, context: &Context, connection: Option<&mut Connection>) -> anyhow::Result<()> {
let mut connector: Connector = options.conn_params.clone();

// match commands that don't require a connection to run, then match the ones that do with a connection.
match &cmd.subcommand {
match &cmd {
Command::Switch(switch) => switch::main(switch, &context, &mut connector).await,
Command::Wipe(wipe) => wipe::main(wipe, &context, &mut connector).await,
Command::Current(current) => current::main(current, &context).await,
command => {
let mut connection = connector.connect().await?;
verify_server_can_use_branches(&mut connection).await?;

match command {
Command::Create(create) => create::main(create, &context, &mut connection).await,
Command::Drop(drop) => drop::main(drop, &context, &mut connection).await,
Command::List(list) => list::main(list, &context, &mut connection).await,
Command::Rename(rename) => rename::main(rename, &context, &mut connection, &options).await,
Command::Rebase(rebase) => rebase::main(rebase, &context, &mut connection, &options).await,
Command::Merge(merge) => merge::main(merge, &context, &mut connection, &options).await,
unhandled => anyhow::bail!("unimplemented branch command '{:?}'", unhandled)
match connection {
Some(conn) => run_branch_command1(command, conn, context, options).await,
None => {
let mut conn = connector.connect().await?;
run_branch_command1(command, &mut conn, context, options).await
}
}
}
}
}

async fn create_context() -> anyhow::Result<Context> {
async fn run_branch_command1(command: &Command, connection: &mut Connection, context: &Context, options: &Options) -> anyhow::Result<()> {
verify_server_can_use_branches(connection).await?;

match command {
Command::Create(create) => create::main(create, &context, connection).await,
Command::Drop(drop) => drop::main(drop, &context, connection).await,
Command::List(list) => list::main(list, &context, connection).await,
Command::Rename(rename) => rename::main(rename, &context, connection, &options).await,
Command::Rebase(rebase) => rebase::main(rebase, &context, connection, &options).await,
Command::Merge(merge) => merge::main(merge, &context, connection, &options).await,
unhandled => anyhow::bail!("unimplemented branch command '{:?}'", unhandled)
}
}

pub async fn create_context() -> anyhow::Result<Context> {
let project_dir = get_project_dir(None, true).await?;
Context::new(project_dir.as_ref()).await
}
Expand Down
2 changes: 1 addition & 1 deletion src/branch/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
mod context;
pub mod context;
mod create;
mod drop;
mod list;
Expand Down
17 changes: 17 additions & 0 deletions src/branch/option.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@

use crate::commands::parser::BranchingCmd;
use crate::options::ConnectionOptions;

#[derive(clap::Args, Debug, Clone)]
pub struct BranchCommand {
#[command(flatten)]
pub conn: ConnectionOptions,

#[command(subcommand)]
pub subcommand: Command,
}
Expand All @@ -17,6 +24,16 @@ pub enum Command {
Current(Current)
}

impl From<&BranchingCmd> for Command {
fn from(cmd: &BranchingCmd) -> Self {
match cmd {
BranchingCmd::Create(args) => Command::Create(args.clone()),
BranchingCmd::Drop(args) => Command::Drop(args.clone()),
BranchingCmd::Wipe(args) => Command::Wipe(args.clone()),
}
}
}

/// Creates a new branch and switches to it.
#[derive(clap::Args, Debug, Clone)]
pub struct Create {
Expand Down
7 changes: 4 additions & 3 deletions src/commands/backslash.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ Introspection
\d [-v] NAME Describe schema object
\ds Describe whole schema (alias: \describe schema)
\l List databases (alias: \list databases)
\l List databases/branches (alias: \list branches)
\ls [-sc] [PATTERN] List scalar types (alias: \list scalars)
\lt [-sc] [PATTERN] List object types (alias: \list types)
\lr [-c] [PATTERN] List roles (alias: \list roles)
Expand All @@ -63,7 +63,7 @@ Editing
Defaults to vi (Notepad in Windows).
Connection
\c, \connect [DBNAME] Connect to database DBNAME
\c, \connect [DBNAME] Connect to database/branch DBNAME
Settings
\set [OPTION [VALUE]] Show/change settings. Type \set to list
Expand Down Expand Up @@ -306,7 +306,7 @@ impl CommandCache {
let mut aliases = BTreeMap::new();
aliases.insert("d", &["describe", "object"][..]);
aliases.insert("ds", &["describe", "schema"]);
aliases.insert("l", &["list", "databases"]);
aliases.insert("l", &["list", "branches"]);
aliases.insert("ls", &["list", "scalars"]);
aliases.insert("lt", &["list", "types"]);
aliases.insert("lr", &["list", "roles"]);
Expand All @@ -322,6 +322,7 @@ impl CommandCache {
aliases.insert("quit", &["exit"]);
aliases.insert("?", &["help"]);
aliases.insert("h", &["help"]);
aliases.insert("branch", &["branching"]);
let mut setting_cmd = None;
let commands: BTreeMap<_,_> = clap.get_subcommands_mut()
.map(|cmd| {
Expand Down
10 changes: 10 additions & 0 deletions src/commands/branching.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
use crate::branch;
use crate::commands::parser::BranchingCmd;
use crate::connect::Connection;
use crate::commands::Options;

pub async fn main(connection: &mut Connection, cmd: &BranchingCmd, options: &Options) -> anyhow::Result<()> {
let context = branch::main::create_context().await?;

branch::main::run_branch_command(&cmd.into(), options, &context, Some(connection)).await
}
10 changes: 8 additions & 2 deletions src/commands/execute.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
use crate::connect::Connection;
use edgedb_tokio::server_params::PostgresAddress;

use crate::analyze;
use crate::{analyze, options};
use crate::commands::parser::{Common, DatabaseCmd, ListCmd, DescribeCmd};
use crate::commands::{self, Options};
use crate::commands::{self, branching, Options};
use crate::migrations::options::{MigrationCmd};
use crate::migrations;
use crate::print;
Expand All @@ -29,6 +29,9 @@ pub async fn common(cli: &mut Connection, cmd: &Common, options: &Options)
}
ListCmd::Databases => {
commands::list_databases(cli, &options).await?;
},
ListCmd::Branches => {
commands::list_branches(cli, &options).await?;
}
ListCmd::Scalars(c) => {
commands::list_scalar_types(cli, &options,
Expand Down Expand Up @@ -91,6 +94,9 @@ pub async fn common(cli: &mut Connection, cmd: &Common, options: &Options)
DatabaseCmd::Wipe(w) => {
commands::database::wipe(cli, w, &options).await?;
}
},
Branching(branching) => {
branching::main(cli, &branching.subcommand, &options).await?
}
Migrate(params) => {
migrations::migrate(cli, &options, params).await?;
Expand Down
27 changes: 27 additions & 0 deletions src/commands/list_branches.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
use crate::commands::list_databases::get_databases;
use crate::commands::{list, list_databases, Options};
use crate::connect::Connection;
use crate::print;

pub async fn get_branches(cli: &mut Connection) -> anyhow::Result<Vec<String>> {
get_databases(cli).await
}

pub async fn list_branches(cli: &mut Connection, options: &Options)
-> Result<(), anyhow::Error>
{
let version = cli.get_version().await?;

if version.specific().major <= 4 {
print::warn(format!("Branches are not supported in EdgeDB {}, printing list of databases instead", version));
return list_databases(cli, options).await;
}

list_branches0(cli, options).await
}

pub async fn list_branches0(cli: &mut Connection, options: &Options) -> Result<(), anyhow::Error> {
let databases = get_branches(cli).await?;
list::print(databases, "List of branches", options).await?;
Ok(())
}
10 changes: 10 additions & 0 deletions src/commands/list_databases.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use crate::commands::Options;
use crate::commands::list;
use crate::commands::list_branches::{list_branches0};
use crate::connect::Connection;
use crate::print;


pub async fn get_databases(cli: &mut Connection) -> anyhow::Result<Vec<String>>
Expand All @@ -15,6 +17,14 @@ pub async fn get_databases(cli: &mut Connection) -> anyhow::Result<Vec<String>>
pub async fn list_databases(cli: &mut Connection, options: &Options)
-> Result<(), anyhow::Error>
{
let version = cli.get_version().await?;


if version.specific().major >= 5 {
print::warn(format!("Databases are not supported in EdgeDB {}, printing list of branches instead", version));
return list_branches0(cli, options).await;
}

let databases = get_databases(cli).await?;
list::print(databases, "List of databases", options).await?;
Ok(())
Expand Down
3 changes: 3 additions & 0 deletions src/commands/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ pub mod cli;
pub mod options;
pub mod parser;
mod ui;
mod list_branches;
mod branching;

pub use self::configure::configure;
pub use self::dump::{dump, dump_all};
Expand All @@ -32,6 +34,7 @@ pub use self::describe_schema::describe_schema;
pub use self::list_aliases::list_aliases;
pub use self::list_casts::list_casts;
pub use self::list_databases::list_databases;
pub use self::list_branches::list_branches;
pub use self::list_indexes::list_indexes;
pub use self::list_modules::list_modules;
pub use self::list_object_types::list_object_types;
Expand Down
27 changes: 26 additions & 1 deletion src/commands/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ pub enum Common {

/// Database commands
Database(Database),
Branching(Branching),
/// Describe database schema or object
Describe(Describe),

Expand Down Expand Up @@ -96,8 +97,10 @@ pub enum ListCmd {
Aliases(ListAliases),
/// Display list of casts defined in the schema
Casts(ListCasts),
/// Display list of databases for an EdgeDB instance
/// On EdgeDB < 5.x: Display list of databases for an EdgeDB instance
Databases,
/// On EdgeDB >= 5.x: Display list of branches for an EdgeDB instance
Branches,
/// Display list of indexes defined in the schema
Indexes(ListIndexes),
/// Display list of modules defined in the schema
Expand All @@ -110,6 +113,28 @@ pub enum ListCmd {
Types(ListTypes),
}

#[derive(clap::Args, Clone, Debug)]
#[command(version = "help_expand")]
#[command(disable_version_flag=true)]
pub struct Branching {
#[command(flatten)]
pub conn: ConnectionOptions,

#[command(subcommand)]
pub subcommand: BranchingCmd,
}

#[derive(clap::Subcommand, Clone, Debug)]
pub enum BranchingCmd {
/// Create a new branch
Create(crate::branch::option::Create),
/// Delete a branch along with its data
Drop(crate::branch::option::Drop),
/// Delete a branches data and reset its schema while
/// preserving the branch itself (its cfg::DatabaseConfig)
/// and existing migration scripts
Wipe(crate::branch::option::Wipe),
}

#[derive(clap::Args, Clone, Debug)]
#[command(version = "help_expand")]
Expand Down
18 changes: 9 additions & 9 deletions src/migrations/create.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::borrow::Cow;
use std::collections::BTreeMap;
use std::path::{Path, PathBuf};
use std::slice::Iter;

use anyhow::Context as _;
use colorful::Colorful;
Expand Down Expand Up @@ -106,12 +107,11 @@ pub enum MigrationKey {
Fixup { target_revision: String },
}

pub trait MigrationToText {
type StatementsIter<'a>: Iterator<Item = &'a String> where Self: 'a;
pub trait MigrationToText<'a, T: Iterator<Item = &'a String> = std::iter::Once<&'a String>> {
fn key(&self) -> &MigrationKey;
fn parent(&self) -> anyhow::Result<&str>;
fn id(&self) -> anyhow::Result<&str>;
fn statements<'a>(&'a self) -> Self::StatementsIter<'a>;
fn statements(&'a self) -> T;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, this is bizzare. How'd you find the linked issue?

It doesn't seem obvious that these two problems are connected.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a lot of debugging ended up the codepath in branch commands that used that trait, and some cheeki googling

}

#[derive(Debug)]
Expand Down Expand Up @@ -165,9 +165,7 @@ impl FutureMigration {
}
}

impl MigrationToText for FutureMigration {
type StatementsIter<'a> = std::slice::Iter<'a, String>;

impl<'a> MigrationToText<'a, Iter<'a, String> > for FutureMigration {
fn key(&self) -> &MigrationKey {
&self.key
}
Expand All @@ -188,7 +186,7 @@ impl MigrationToText for FutureMigration {
}).map(|s| &s[..])
}

fn statements<'a>(&'a self) -> Self::StatementsIter<'a> {
fn statements(&'a self) -> Iter<'a, String> {
self.statements.iter()
}
}
Expand Down Expand Up @@ -699,9 +697,10 @@ async fn run_interactive(_ctx: &Context, cli: &mut Connection,
Ok(FutureMigration::new(key, descr))
}

pub async fn write_migration(ctx: &Context, descr: &impl MigrationToText,
pub async fn write_migration<'a, T>(ctx: &Context, descr: &'a impl MigrationToText<'a, T>,
verbose: bool)
-> anyhow::Result<()>
where T : Iterator<Item = &'a String>
{
let filename = match &descr.key() {
MigrationKey::Index(idx) => {
Expand All @@ -717,9 +716,10 @@ pub async fn write_migration(ctx: &Context, descr: &impl MigrationToText,
}

#[context("could not write migration file {}", filepath.display())]
async fn _write_migration(descr: &impl MigrationToText, filepath: &Path,
async fn _write_migration<'a, T>(descr: &'a impl MigrationToText<'a, T>, filepath: &Path,
verbose: bool)
-> anyhow::Result<()>
where T : Iterator<Item = &'a String>
{
let id = descr.id()?;
let dir = filepath.parent().unwrap();
Expand Down
7 changes: 3 additions & 4 deletions src/migrations/extract.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use std::iter::Once;
use fs_err as fs;

use crate::commands::{ExitCode, Options};
Expand All @@ -14,9 +15,7 @@ pub struct DatabaseMigration {
pub migration: db_migration::DBMigration,
}

impl MigrationToText for DatabaseMigration {
type StatementsIter<'a> = std::iter::Once<&'a String>;

impl<'a> MigrationToText<'a, Once<&'a String>> for DatabaseMigration {
fn key(&self) -> &MigrationKey {
&self.key
}
Expand All @@ -35,7 +34,7 @@ impl MigrationToText for DatabaseMigration {
Ok(&self.migration.name)
}

fn statements<'a>(&'a self) -> Self::StatementsIter<'a> {
fn statements(&'a self) -> Once<&'a String> {
std::iter::once(&self.migration.script)
}
}
Expand Down
Loading
Loading