migrations_internals/
lib.rs1#![allow(
4 clippy::map_unwrap_or,
5 clippy::match_same_arms,
6 clippy::type_complexity
7)]
8#![warn(
9 clippy::unwrap_used,
10 clippy::print_stdout,
11 clippy::mut_mut,
12 clippy::non_ascii_literal,
13 clippy::similar_names,
14 clippy::unicode_not_nfc,
15 clippy::enum_glob_use,
16 clippy::if_not_else,
17 clippy::items_after_statements,
18 clippy::used_underscore_binding,
19 missing_debug_implementations,
20 missing_copy_implementations
21)]
22
23use std::ffi::OsString;
24use std::fs::{DirEntry, File};
25use std::io::Read;
26use std::path::{Path, PathBuf};
27
28#[doc(hidden)]
29#[derive(#[automatically_derived]
#[allow(missing_copy_implementations)]
impl ::core::fmt::Debug for TomlMetadata {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field1_finish(f, "TomlMetadata",
"run_in_transaction", &&self.run_in_transaction)
}
}Debug, #[doc(hidden)]
#[allow(non_upper_case_globals, unused_attributes, unused_qualifications,
clippy :: absolute_paths,)]
const _: () =
{
#[allow(unused_extern_crates, clippy :: useless_attribute)]
extern crate serde as _serde;
;
#[automatically_derived]
impl<'de> _serde::Deserialize<'de> for TomlMetadata {
fn deserialize<__D>(__deserializer: __D)
-> _serde::__private229::Result<Self, __D::Error> where
__D: _serde::Deserializer<'de> {
#[allow(non_camel_case_types)]
#[doc(hidden)]
enum __Field { __field0, __ignore, }
#[doc(hidden)]
struct __FieldVisitor;
#[automatically_derived]
impl<'de> _serde::de::Visitor<'de> for __FieldVisitor {
type Value = __Field;
fn expecting(&self,
__formatter: &mut _serde::__private229::Formatter)
-> _serde::__private229::fmt::Result {
_serde::__private229::Formatter::write_str(__formatter,
"field identifier")
}
fn visit_u64<__E>(self, __value: u64)
-> _serde::__private229::Result<Self::Value, __E> where
__E: _serde::de::Error {
match __value {
0u64 => _serde::__private229::Ok(__Field::__field0),
_ => _serde::__private229::Ok(__Field::__ignore),
}
}
fn visit_str<__E>(self, __value: &str)
-> _serde::__private229::Result<Self::Value, __E> where
__E: _serde::de::Error {
match __value {
"run_in_transaction" =>
_serde::__private229::Ok(__Field::__field0),
_ => { _serde::__private229::Ok(__Field::__ignore) }
}
}
fn visit_bytes<__E>(self, __value: &[u8])
-> _serde::__private229::Result<Self::Value, __E> where
__E: _serde::de::Error {
match __value {
b"run_in_transaction" =>
_serde::__private229::Ok(__Field::__field0),
_ => { _serde::__private229::Ok(__Field::__ignore) }
}
}
}
#[automatically_derived]
impl<'de> _serde::Deserialize<'de> for __Field {
#[inline]
fn deserialize<__D>(__deserializer: __D)
-> _serde::__private229::Result<Self, __D::Error> where
__D: _serde::Deserializer<'de> {
_serde::Deserializer::deserialize_identifier(__deserializer,
__FieldVisitor)
}
}
#[doc(hidden)]
struct __Visitor<'de> {
marker: _serde::__private229::PhantomData<TomlMetadata>,
lifetime: _serde::__private229::PhantomData<&'de ()>,
}
#[automatically_derived]
impl<'de> _serde::de::Visitor<'de> for __Visitor<'de> {
type Value = TomlMetadata;
fn expecting(&self,
__formatter: &mut _serde::__private229::Formatter)
-> _serde::__private229::fmt::Result {
_serde::__private229::Formatter::write_str(__formatter,
"struct TomlMetadata")
}
#[inline]
fn visit_seq<__A>(self, mut __seq: __A)
-> _serde::__private229::Result<Self::Value, __A::Error>
where __A: _serde::de::SeqAccess<'de> {
let __field0 =
match _serde::de::SeqAccess::next_element::<bool>(&mut __seq)?
{
_serde::__private229::Some(__value) => __value,
_serde::__private229::None =>
_serde::__private229::Default::default(),
};
_serde::__private229::Ok(TomlMetadata {
run_in_transaction: __field0,
})
}
#[inline]
fn visit_map<__A>(self, mut __map: __A)
-> _serde::__private229::Result<Self::Value, __A::Error>
where __A: _serde::de::MapAccess<'de> {
let mut __field0: _serde::__private229::Option<bool> =
_serde::__private229::None;
while let _serde::__private229::Some(__key) =
_serde::de::MapAccess::next_key::<__Field>(&mut __map)? {
match __key {
__Field::__field0 => {
if _serde::__private229::Option::is_some(&__field0) {
return _serde::__private229::Err(<__A::Error as
_serde::de::Error>::duplicate_field("run_in_transaction"));
}
__field0 =
_serde::__private229::Some(_serde::de::MapAccess::next_value::<bool>(&mut __map)?);
}
_ => {
let _ =
_serde::de::MapAccess::next_value::<_serde::de::IgnoredAny>(&mut __map)?;
}
}
}
let __field0 =
match __field0 {
_serde::__private229::Some(__field0) => __field0,
_serde::__private229::None =>
_serde::__private229::Default::default(),
};
_serde::__private229::Ok(TomlMetadata {
run_in_transaction: __field0,
})
}
}
#[doc(hidden)]
const FIELDS: &'static [&'static str] =
&["run_in_transaction"];
_serde::Deserializer::deserialize_struct(__deserializer,
"TomlMetadata", FIELDS,
__Visitor {
marker: _serde::__private229::PhantomData::<TomlMetadata>,
lifetime: _serde::__private229::PhantomData,
})
}
}
};serde::Deserialize)]
30#[allow(missing_copy_implementations)]
31pub struct TomlMetadata {
32 #[serde(default)]
33 pub run_in_transaction: bool,
34}
35
36impl Default for TomlMetadata {
37 fn default() -> Self {
38 Self {
39 run_in_transaction: true,
40 }
41 }
42}
43
44impl TomlMetadata {
45 pub const fn new(run_in_transaction: bool) -> Self {
46 Self { run_in_transaction }
47 }
48
49 pub fn read_from_file(path: &Path) -> Result<Self, Box<dyn std::error::Error>> {
50 let mut toml = String::new();
51 let mut file = File::open(path)?;
52 file.read_to_string(&mut toml)?;
53
54 Ok(toml::from_str(&toml)?)
55 }
56}
57
58pub fn search_for_migrations_directory(path: &Path) -> Option<PathBuf> {
59 let migration_path = path.join("migrations");
60 if migration_path.is_dir() {
61 Some(migration_path)
62 } else {
63 path.parent().and_then(search_for_migrations_directory)
64 }
65}
66
67pub fn valid_sql_migration_directory(path: &Path) -> bool {
68 file_names(path).is_ok_and(|files| files.iter().any(|f| f == "up.sql"))
69}
70
71pub fn version_from_string(path: &str) -> Option<String> {
72 path.split('_').next().map(|s| s.replace('-', ""))
73}
74
75fn file_names(path: &Path) -> Result<Vec<OsString>, std::io::Error> {
76 path.read_dir()?
77 .filter_map(|entry| match entry {
78 Ok(entry) if entry.file_name().to_string_lossy().starts_with('.') => None,
79 Ok(entry) => Some(Ok(entry.file_name())),
80 Err(e) => Some(Err(e)),
81 })
82 .collect::<Result<Vec<_>, _>>()
83}
84
85pub fn migrations_directories(
86 path: &'_ Path,
87) -> Result<impl Iterator<Item = Result<DirEntry, std::io::Error>> + '_, std::io::Error> {
88 Ok(path.read_dir()?.filter_map(|entry_res| {
89 entry_res
90 .and_then(|entry| {
91 Ok(
92 if entry.metadata()?.is_file()
93 || entry.file_name().to_string_lossy().starts_with('.')
94 {
95 None
96 } else if entry.metadata()?.is_dir() {
97 let inner_dir_entry_count = entry.path().read_dir()?.count();
98
99 if inner_dir_entry_count == 0 {
100 None
101 } else {
102 Some(entry)
103 }
104 } else {
105 Some(entry)
106 },
107 )
108 })
109 .transpose()
110 }))
111}