use crate::Settings;
use crate::traits::CommandBuilder;
use std::convert::AsRef;
use std::ffi::{OsStr, OsString};
use std::path::PathBuf;
#[derive(Clone, Debug, Default)]
pub struct PgUpgradeBuilder {
program_dir: Option<PathBuf>,
envs: Vec<(OsString, OsString)>,
old_bindir: Option<OsString>,
new_bindir: Option<OsString>,
check: bool,
old_datadir: Option<OsString>,
new_datadir: Option<OsString>,
jobs: Option<OsString>,
link: bool,
no_sync: bool,
old_options: Option<OsString>,
new_options: Option<OsString>,
old_port: Option<u16>,
new_port: Option<u16>,
retain: bool,
socketdir: Option<OsString>,
username: Option<OsString>,
verbose: bool,
version: bool,
clone: bool,
copy: bool,
help: bool,
}
impl PgUpgradeBuilder {
#[must_use]
pub fn new() -> Self {
Self::default()
}
pub fn from(settings: &dyn Settings) -> Self {
Self::new().program_dir(settings.get_binary_dir())
}
#[must_use]
pub fn program_dir<P: Into<PathBuf>>(mut self, path: P) -> Self {
self.program_dir = Some(path.into());
self
}
#[must_use]
pub fn old_bindir<S: AsRef<OsStr>>(mut self, old_bindir: S) -> Self {
self.old_bindir = Some(old_bindir.as_ref().to_os_string());
self
}
#[must_use]
pub fn new_bindir<S: AsRef<OsStr>>(mut self, new_bindir: S) -> Self {
self.new_bindir = Some(new_bindir.as_ref().to_os_string());
self
}
#[must_use]
pub fn check(mut self) -> Self {
self.check = true;
self
}
#[must_use]
pub fn old_datadir<S: AsRef<OsStr>>(mut self, old_datadir: S) -> Self {
self.old_datadir = Some(old_datadir.as_ref().to_os_string());
self
}
#[must_use]
pub fn new_datadir<S: AsRef<OsStr>>(mut self, new_datadir: S) -> Self {
self.new_datadir = Some(new_datadir.as_ref().to_os_string());
self
}
#[must_use]
pub fn jobs<S: AsRef<OsStr>>(mut self, jobs: S) -> Self {
self.jobs = Some(jobs.as_ref().to_os_string());
self
}
#[must_use]
pub fn link(mut self) -> Self {
self.link = true;
self
}
#[must_use]
pub fn no_sync(mut self) -> Self {
self.no_sync = true;
self
}
#[must_use]
pub fn old_options<S: AsRef<OsStr>>(mut self, old_options: S) -> Self {
self.old_options = Some(old_options.as_ref().to_os_string());
self
}
#[must_use]
pub fn new_options<S: AsRef<OsStr>>(mut self, new_options: S) -> Self {
self.new_options = Some(new_options.as_ref().to_os_string());
self
}
#[must_use]
pub fn old_port(mut self, old_port: u16) -> Self {
self.old_port = Some(old_port);
self
}
#[must_use]
pub fn new_port(mut self, new_port: u16) -> Self {
self.new_port = Some(new_port);
self
}
#[must_use]
pub fn retain(mut self) -> Self {
self.retain = true;
self
}
#[must_use]
pub fn socketdir<S: AsRef<OsStr>>(mut self, socketdir: S) -> Self {
self.socketdir = Some(socketdir.as_ref().to_os_string());
self
}
#[must_use]
pub fn username<S: AsRef<OsStr>>(mut self, username: S) -> Self {
self.username = Some(username.as_ref().to_os_string());
self
}
#[must_use]
pub fn verbose(mut self) -> Self {
self.verbose = true;
self
}
#[must_use]
pub fn version(mut self) -> Self {
self.version = true;
self
}
#[must_use]
pub fn clone(mut self) -> Self {
self.clone = true;
self
}
#[must_use]
pub fn copy(mut self) -> Self {
self.copy = true;
self
}
#[must_use]
pub fn help(mut self) -> Self {
self.help = true;
self
}
}
impl CommandBuilder for PgUpgradeBuilder {
fn get_program(&self) -> &'static OsStr {
"pg_upgrade".as_ref()
}
fn get_program_dir(&self) -> &Option<PathBuf> {
&self.program_dir
}
fn get_args(&self) -> Vec<OsString> {
let mut args: Vec<OsString> = Vec::new();
if let Some(old_bindir) = &self.old_bindir {
args.push("--old-bindir".into());
args.push(old_bindir.into());
}
if let Some(new_bindir) = &self.new_bindir {
args.push("--new-bindir".into());
args.push(new_bindir.into());
}
if self.check {
args.push("--check".into());
}
if let Some(old_datadir) = &self.old_datadir {
args.push("--old-datadir".into());
args.push(old_datadir.into());
}
if let Some(new_datadir) = &self.new_datadir {
args.push("--new-datadir".into());
args.push(new_datadir.into());
}
if let Some(jobs) = &self.jobs {
args.push("--jobs".into());
args.push(jobs.into());
}
if self.link {
args.push("--link".into());
}
if self.no_sync {
args.push("--no-sync".into());
}
if let Some(old_options) = &self.old_options {
args.push("--old-options".into());
args.push(old_options.into());
}
if let Some(new_options) = &self.new_options {
args.push("--new-options".into());
args.push(new_options.into());
}
if let Some(old_port) = &self.old_port {
args.push("--old-port".into());
args.push(old_port.to_string().into());
}
if let Some(new_port) = &self.new_port {
args.push("--new-port".into());
args.push(new_port.to_string().into());
}
if self.retain {
args.push("--retain".into());
}
if let Some(socketdir) = &self.socketdir {
args.push("--socketdir".into());
args.push(socketdir.into());
}
if let Some(username) = &self.username {
args.push("--username".into());
args.push(username.into());
}
if self.verbose {
args.push("--verbose".into());
}
if self.version {
args.push("--version".into());
}
if self.clone {
args.push("--clone".into());
}
if self.copy {
args.push("--copy".into());
}
if self.help {
args.push("--help".into());
}
args
}
fn get_envs(&self) -> Vec<(OsString, OsString)> {
self.envs.clone()
}
fn env<S: AsRef<OsStr>>(mut self, key: S, value: S) -> Self {
self.envs
.push((key.as_ref().to_os_string(), value.as_ref().to_os_string()));
self
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::TestSettings;
use crate::traits::CommandToString;
use test_log::test;
#[test]
fn test_builder_new() {
let command = PgUpgradeBuilder::new().program_dir(".").build();
assert_eq!(
PathBuf::from(".").join("pg_upgrade"),
PathBuf::from(command.to_command_string().replace('"', ""))
);
}
#[test]
fn test_builder_from() {
let command = PgUpgradeBuilder::from(&TestSettings).build();
#[cfg(not(target_os = "windows"))]
let command_prefix = r#""./pg_upgrade""#;
#[cfg(target_os = "windows")]
let command_prefix = r#"".\\pg_upgrade""#;
assert_eq!(format!("{command_prefix}"), command.to_command_string());
}
#[test]
fn test_builder() {
let command = PgUpgradeBuilder::new()
.env("PGDATABASE", "database")
.old_bindir("old")
.new_bindir("new")
.check()
.old_datadir("old_data")
.new_datadir("new_data")
.jobs("10")
.link()
.no_sync()
.old_options("old")
.new_options("new")
.old_port(5432)
.new_port(5433)
.retain()
.socketdir("socket")
.username("user")
.verbose()
.version()
.clone()
.copy()
.help()
.build();
#[cfg(not(target_os = "windows"))]
let command_prefix = r#"PGDATABASE="database" "#;
#[cfg(target_os = "windows")]
let command_prefix = String::new();
assert_eq!(
format!(
r#"{command_prefix}"pg_upgrade" "--old-bindir" "old" "--new-bindir" "new" "--check" "--old-datadir" "old_data" "--new-datadir" "new_data" "--jobs" "10" "--link" "--no-sync" "--old-options" "old" "--new-options" "new" "--old-port" "5432" "--new-port" "5433" "--retain" "--socketdir" "socket" "--username" "user" "--verbose" "--version" "--clone" "--copy" "--help""#
),
command.to_command_string()
);
}
}