Skip to content

Commit

Permalink
Adding barrel feature (#1573)
Browse files Browse the repository at this point in the history
I've taken the liberty to squash down this epic saga of a pull request. Here is its full list of commit messages for future reference:

* Optionally adding `barrel` crate to diesel_migrations
* Initial support for barrel migrations in diesel cli
* Using the barrel `diesel` feature
* Changing barrel call signature to build Migration on diesel side
* Connecting barrel to diesel migration layouts
* Formatting with rustfmt
* Changing generated migration function signatures
* Cleaning up migration process slightly
* Pointing barrel to github version
* Implementing requested changes in diesel_cli
* Fix git repository link
* Preliminarily commiting refactoring changes
* Moving Migration trait to core diesel library
* Adjusting the module comment formatting to let CI pass
* Moving MigrationName back to migrations_internals
* Adding new import to fix some Migration tests
* Changing the migration generation function signature
* Another clippy change
* Renaming external feature flag. Changing barrel version to non-git
* Changing barrel version to non-git in diesel_cli
* Adjust the diesel feature flag on barrel
* Re-exporting diesel::migration::* to avoid a breaking change
* Cleaning up diesel_migration exports
* Adjusting a few function calls into barrel to the v0.2.0 API
* Re-adding more re-exports to diesel_migrations
* Changing feature and type flag names in diesel_cli
* Making error enums non exhaustive. Only exporting speific error types
* Breaking formatting
* Fixing formatting again
* Touching code to make github see changes
* Changing formatting back to the way it's meant to be
* Handling __NonExaustive options for migration errors
* Not exposing the entire mirations/error module anymore
* Fixing some formatting issues
* Optionally adding `barrel` crate to diesel_migrations
* Initial support for barrel migrations in diesel cli
* Changing barrel call signature to build Migration on diesel side
* Connecting barrel to diesel migration layouts
* Formatting with rustfmt
* Changing generated migration function signatures
* Cleaning up migration process slightly
* Pointing barrel to github version
* Implementing requested changes in diesel_cli
* Preliminarily commiting refactoring changes
* Moving Migration trait to core diesel library
* Adjusting the module comment formatting to let CI pass
* Moving MigrationName back to migrations_internals
* Adding new import to fix some Migration tests
* Changing the migration generation function signature
* Another clippy change
* Renaming external feature flag. Changing barrel version to non-git
* Changing barrel version to non-git in diesel_cli
* Adjust the diesel feature flag on barrel
* Re-exporting diesel::migration::* to avoid a breaking change
* Cleaning up diesel_migration exports
* Adjusting a few function calls into barrel to the v0.2.0 API
* Re-adding more re-exports to diesel_migrations
* Changing feature and type flag names in diesel_cli
* Making error enums non exhaustive. Only exporting speific error types
* Breaking formatting
* Fixing formatting again
* Touching code to make github see changes
* Changing formatting back to the way it's meant to be
* Handling __NonExaustive options for migration errors
* Not exposing the entire mirations/error module anymore
* Fixing some formatting issues
* Cleaning a bad merge artefact
* Fixing a bad rebase
  • Loading branch information
spacekookie authored and killercup committed Apr 17, 2018
1 parent dc84d30 commit fb1e61b
Show file tree
Hide file tree
Showing 10 changed files with 140 additions and 70 deletions.
1 change: 1 addition & 0 deletions diesel/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ pub mod serialize;
pub mod sql_types;
pub mod types;
pub mod row;
pub mod migration;

#[cfg(feature = "mysql")]
pub mod mysql;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,30 @@
use diesel::result;
//! Error types that represent migration errors.
//! These are split into multiple segments, depending on
//! where in the migration process an error occurs.
use std::convert::From;
use std::{fmt, io};
use std::path::PathBuf;
use std::error::Error;

use result;

/// Errors that occur while preparing to run migrations
#[derive(Debug)]
pub enum MigrationError {
/// The migration directory wasn't found
MigrationDirectoryNotFound,
/// Provided migration was in an unknown format
UnknownMigrationFormat(PathBuf),
/// General system IO error
IoError(io::Error),
/// Provided migration had an incompatible version number
UnknownMigrationVersion(String),
/// No migrations had to be/ could be run
NoMigrationRun,
///
#[doc(hidden)]
__NonExhaustive,
}

impl Error for MigrationError {
Expand All @@ -31,6 +44,7 @@ impl Error for MigrationError {
MigrationError::NoMigrationRun => {
"No migrations have been run. Did you forget `diesel migration run`?"
}
MigrationError::__NonExhaustive => unreachable!(),
}
}
}
Expand Down Expand Up @@ -63,12 +77,19 @@ impl From<io::Error> for MigrationError {
}
}

/// Errors that occur while running migrations
#[derive(Debug, PartialEq)]
#[cfg_attr(feature = "clippy", allow(enum_variant_names))]
pub enum RunMigrationsError {
/// A general migration error occured
MigrationError(MigrationError),
/// The provided migration included an invalid query
QueryError(result::Error),
/// The provided migration was empty
EmptyMigration,
///
#[doc(hidden)]
__NonExhaustive,
}

impl Error for RunMigrationsError {
Expand All @@ -77,6 +98,7 @@ impl Error for RunMigrationsError {
RunMigrationsError::MigrationError(ref error) => error.description(),
RunMigrationsError::QueryError(ref error) => error.description(),
RunMigrationsError::EmptyMigration => "Attempted to run an empty migration.",
RunMigrationsError::__NonExhaustive => unreachable!(),
}
}
}
Expand Down
55 changes: 55 additions & 0 deletions diesel/src/migration/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
//! Representation of migrations
mod errors;
pub use self::errors::{MigrationError, RunMigrationsError};

use connection::SimpleConnection;
use std::path::Path;

/// Represents a migration that interacts with diesel
pub trait Migration {
/// Get the migration version
fn version(&self) -> &str;
/// Apply this migration
fn run(&self, conn: &SimpleConnection) -> Result<(), RunMigrationsError>;
/// Revert this migration
fn revert(&self, conn: &SimpleConnection) -> Result<(), RunMigrationsError>;
/// Get the migration file path
fn file_path(&self) -> Option<&Path> {
None
}
}

impl Migration for Box<Migration> {
fn version(&self) -> &str {
(&**self).version()
}

fn run(&self, conn: &SimpleConnection) -> Result<(), RunMigrationsError> {
(&**self).run(conn)
}

fn revert(&self, conn: &SimpleConnection) -> Result<(), RunMigrationsError> {
(&**self).revert(conn)
}
fn file_path(&self) -> Option<&Path> {
(&**self).file_path()
}
}

impl<'a> Migration for &'a Migration {
fn version(&self) -> &str {
(&**self).version()
}

fn run(&self, conn: &SimpleConnection) -> Result<(), RunMigrationsError> {
(&**self).run(conn)
}

fn revert(&self, conn: &SimpleConnection) -> Result<(), RunMigrationsError> {
(&**self).revert(conn)
}
fn file_path(&self) -> Option<&Path> {
(&**self).file_path()
}
}
2 changes: 2 additions & 0 deletions diesel_cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ migrations_internals = "~1.2.0"
serde = { version = "1.0.0", features = ["derive"] }
toml = "0.4.6"
url = { version = "1.4.0", optional = true }
barrel = { version = "<= 0.2.0", optional = true, features = ["diesel-filled"] }

[dev-dependencies]
difference = "1.0"
Expand All @@ -38,6 +39,7 @@ lint = ["clippy"]
postgres = ["diesel/postgres", "infer_schema_internals/postgres", "url"]
sqlite = ["diesel/sqlite", "infer_schema_internals/sqlite"]
mysql = ["diesel/mysql", "infer_schema_internals/mysql", "url"]
rust-migrations = ["migrations_internals/barrel", "barrel"]

[[test]]
name = "tests"
Expand Down
9 changes: 9 additions & 0 deletions diesel_cli/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,15 @@ pub fn build_cli() -> App<'static, 'static> {
for most use cases.",
)
.takes_value(true),
)
.arg(
Arg::with_name("TYPE")
.long("type")
.short("t")
.possible_values(&["sql", "rust"])
.default_value("sql")
.takes_value(true)
.help("Specify the migration type."),
),
)
.setting(AppSettings::SubcommandRequiredElseHelp);
Expand Down
58 changes: 36 additions & 22 deletions diesel_cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ extern crate toml;
extern crate url;

mod config;

#[cfg(feature = "rust-migrations")]
extern crate barrel;

mod database_error;
#[macro_use]
mod database;
Expand Down Expand Up @@ -113,39 +117,49 @@ fn run_migration_command(matches: &ArgMatches) -> Result<(), Box<Error>> {
println!("{:?}", result);
}
("generate", Some(args)) => {
use std::io::Write;

let migration_name = args.value_of("MIGRATION_NAME").unwrap();
let version = migration_version(args);
let versioned_name = format!("{}_{}", version, migration_name);
let migration_dir = migrations_dir(matches).join(versioned_name);
fs::create_dir(&migration_dir)?;

let migration_dir_relative =
convert_absolute_path_to_relative(&migration_dir, &env::current_dir()?);

let up_path = migration_dir.join("up.sql");
println!(
"Creating {}",
migration_dir_relative.join("up.sql").display()
);
let mut up = fs::File::create(up_path).unwrap();
up.write_all(b"-- Your SQL goes here").unwrap();

let down_path = migration_dir.join("down.sql");
println!(
"Creating {}",
migration_dir_relative.join("down.sql").display()
);
let mut down = fs::File::create(down_path)?;
down.write_all(b"-- This file should undo anything in `up.sql`")?;
let migration_type: Option<&str> = args.value_of("TYPE");
fs::create_dir(&migration_dir).unwrap();

match migration_type {
#[cfg(feature = "rust-migrations")]
Some("rust") => ::barrel::integrations::diesel::generate_initial(&migration_dir),
_ => generate_sql_migration(&migration_dir),
}
}
_ => unreachable!("The cli parser should prevent reaching here"),
};

Ok(())
}

fn generate_sql_migration(path: &PathBuf) {
use std::io::Write;

let migration_dir_relative =
convert_absolute_path_to_relative(path, &env::current_dir().unwrap());

let up_path = path.join("up.sql");
println!(
"Creating {}",
migration_dir_relative.join("up.sql").display()
);
let mut up = fs::File::create(up_path).unwrap();
up.write_all(b"-- Your SQL goes here").unwrap();

let down_path = path.join("down.sql");
println!(
"Creating {}",
migration_dir_relative.join("down.sql").display()
);
let mut down = fs::File::create(down_path).unwrap();
down.write_all(b"-- This file should undo anything in `up.sql`")
.unwrap();
}

use std::fmt::Display;
fn migration_version<'a>(matches: &'a ArgMatches) -> Box<Display + 'a> {
matches
Expand Down
1 change: 1 addition & 0 deletions diesel_migrations/migrations_internals/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ homepage = "http://diesel.rs"
[dependencies]
clippy = { optional = true, version = "=0.0.185" }
diesel = { version = "~1.2.0", default-features = false }
barrel = { version = "<= 0.2.0", optional = true, features = ["diesel-filled"] }

[dev-dependencies]
tempdir = "0.3.4"
Expand Down
8 changes: 5 additions & 3 deletions diesel_migrations/migrations_internals/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,18 +77,20 @@
#[macro_use]
extern crate diesel;

mod migration;
#[cfg(feature = "barrel")]
extern crate barrel;

pub mod migration;
#[doc(hidden)]
pub mod connection;
mod migration_error;
#[doc(hidden)]
pub mod schema;

#[doc(inline)]
pub use self::connection::MigrationConnection;
#[doc(inline)]
pub use self::migration::*;
pub use self::migration_error::*;
pub use diesel::migration::*;

use std::fs::DirEntry;
use std::io::{stdout, Write};
Expand Down
51 changes: 7 additions & 44 deletions diesel_migrations/migrations_internals/src/migration.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,9 @@
use diesel::connection::SimpleConnection;
use super::{MigrationError, RunMigrationsError};
use diesel::migration::*;

use std::path::{Path, PathBuf};
use std::fmt;

pub trait Migration {
fn version(&self) -> &str;
fn run(&self, conn: &SimpleConnection) -> Result<(), RunMigrationsError>;
fn revert(&self, conn: &SimpleConnection) -> Result<(), RunMigrationsError>;
fn file_path(&self) -> Option<&Path> {
None
}
}

#[allow(missing_debug_implementations)]
#[derive(Clone, Copy)]
pub struct MigrationName<'a> {
Expand Down Expand Up @@ -41,6 +32,12 @@ impl<'a> fmt::Display for MigrationName<'a> {
}

pub fn migration_from(path: PathBuf) -> Result<Box<Migration>, MigrationError> {
#[cfg(feature = "barrel")]
match ::barrel::integrations::diesel::migration_from(&path) {
Some(migration) => return Ok(migration),
None => {}
}

if valid_sql_migration_directory(&path) {
let version = try!(version_from_path(&path));
Ok(Box::new(SqlFileMigration(path, version)))
Expand All @@ -49,40 +46,6 @@ pub fn migration_from(path: PathBuf) -> Result<Box<Migration>, MigrationError> {
}
}

impl Migration for Box<Migration> {
fn version(&self) -> &str {
(&**self).version()
}

fn run(&self, conn: &SimpleConnection) -> Result<(), RunMigrationsError> {
(&**self).run(conn)
}

fn revert(&self, conn: &SimpleConnection) -> Result<(), RunMigrationsError> {
(&**self).revert(conn)
}
fn file_path(&self) -> Option<&Path> {
(&**self).file_path()
}
}

impl<'a> Migration for &'a Migration {
fn version(&self) -> &str {
(&**self).version()
}

fn run(&self, conn: &SimpleConnection) -> Result<(), RunMigrationsError> {
(&**self).run(conn)
}

fn revert(&self, conn: &SimpleConnection) -> Result<(), RunMigrationsError> {
(&**self).revert(conn)
}
fn file_path(&self) -> Option<&Path> {
(&**self).file_path()
}
}

fn valid_sql_migration_directory(path: &Path) -> bool {
file_names(path)
.map(|files| files.contains(&"down.sql".into()) && files.contains(&"up.sql".into()))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ pub fn derive_embed_migrations(input: &syn::DeriveInput) -> quote::Tokens {
extern crate diesel_migrations;

use self::diesel_migrations::*;
use self::diesel::migration::*;
use self::diesel::connection::SimpleConnection;
use std::io;

Expand Down

0 comments on commit fb1e61b

Please sign in to comment.