Remove the init command.
parent
63085593c4
commit
7debe754d1
|
@ -1,4 +1,7 @@
|
||||||
---
|
---
|
||||||
|
user:
|
||||||
|
name: jrpotter
|
||||||
|
email: jrpotter@github.io
|
||||||
local: $HOME/.homesync
|
local: $HOME/.homesync
|
||||||
remote:
|
remote:
|
||||||
name: origin
|
name: origin
|
||||||
|
|
106
src/config.rs
106
src/config.rs
|
@ -2,13 +2,7 @@ use super::{path, path::ResPathBuf};
|
||||||
use paris::formatter::colorize_string;
|
use paris::formatter::colorize_string;
|
||||||
use serde_derive::{Deserialize, Serialize};
|
use serde_derive::{Deserialize, Serialize};
|
||||||
use simplelog::{info, paris};
|
use simplelog::{info, paris};
|
||||||
use std::{
|
use std::{collections::BTreeMap, env::VarError, error, fmt, fs, io, io::Write, path::PathBuf};
|
||||||
collections::BTreeMap,
|
|
||||||
env::VarError,
|
|
||||||
error, fmt, fs, io,
|
|
||||||
io::Write,
|
|
||||||
path::{Path, PathBuf},
|
|
||||||
};
|
|
||||||
use url::{ParseError, Url};
|
use url::{ParseError, Url};
|
||||||
|
|
||||||
// ========================================
|
// ========================================
|
||||||
|
@ -77,6 +71,12 @@ impl error::Error for Error {}
|
||||||
// Config
|
// Config
|
||||||
// ========================================
|
// ========================================
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
|
pub struct User {
|
||||||
|
pub name: String,
|
||||||
|
pub email: String,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize)]
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
pub struct Package {
|
pub struct Package {
|
||||||
pub configs: Vec<PathBuf>,
|
pub configs: Vec<PathBuf>,
|
||||||
|
@ -91,6 +91,7 @@ pub struct Remote {
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize)]
|
#[derive(Debug, Deserialize, Serialize)]
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
|
pub user: User,
|
||||||
pub local: PathBuf,
|
pub local: PathBuf,
|
||||||
pub remote: Remote,
|
pub remote: Remote,
|
||||||
pub packages: BTreeMap<String, Package>,
|
pub packages: BTreeMap<String, Package>,
|
||||||
|
@ -164,97 +165,6 @@ pub fn reload(pc: &PathConfig) -> Result<PathConfig> {
|
||||||
load(&vec![pc.homesync_yml.clone()])
|
load(&vec![pc.homesync_yml.clone()])
|
||||||
}
|
}
|
||||||
|
|
||||||
// ========================================
|
|
||||||
// Creation
|
|
||||||
// ========================================
|
|
||||||
|
|
||||||
fn prompt_default(prompt: &str, default: String) -> Result<String> {
|
|
||||||
print!("{}", prompt);
|
|
||||||
io::stdout().flush()?;
|
|
||||||
let mut value = String::new();
|
|
||||||
io::stdin().read_line(&mut value)?;
|
|
||||||
let trimmed = value.trim();
|
|
||||||
if trimmed.is_empty() {
|
|
||||||
Ok(default)
|
|
||||||
} else {
|
|
||||||
Ok(trimmed.to_owned())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn prompt_local(path: Option<&Path>) -> Result<PathBuf> {
|
|
||||||
let default = path.map_or("$HOME/.homesync".to_owned(), |p| p.display().to_string());
|
|
||||||
let value = prompt_default(
|
|
||||||
&format!(
|
|
||||||
"Local git repository <{}> (enter to continue): ",
|
|
||||||
colorize_string(format!("<yellow>{}</>", &default)),
|
|
||||||
),
|
|
||||||
default,
|
|
||||||
)?;
|
|
||||||
Ok(PathBuf::from(value))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn prompt_remote(remote: Option<&Remote>) -> Result<Remote> {
|
|
||||||
let default_name = remote.map_or("origin".to_owned(), |r| r.name.to_owned());
|
|
||||||
let remote_name = prompt_default(
|
|
||||||
&format!(
|
|
||||||
"Remote git name <{}> (enter to continue): ",
|
|
||||||
colorize_string(format!("<yellow>{}</>", &default_name))
|
|
||||||
),
|
|
||||||
default_name,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
let default_branch = remote.map_or("origin".to_owned(), |r| r.branch.to_owned());
|
|
||||||
let remote_branch = prompt_default(
|
|
||||||
&format!(
|
|
||||||
"Remote git branch <{}> (enter to continue): ",
|
|
||||||
colorize_string(format!("<yellow>{}</>", &default_branch))
|
|
||||||
),
|
|
||||||
default_branch,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
let default_url = remote.map_or("https://github.com/owner/repo.git".to_owned(), |r| {
|
|
||||||
r.url.to_string()
|
|
||||||
});
|
|
||||||
let remote_url = prompt_default(
|
|
||||||
&format!(
|
|
||||||
"Remote git url <{}> (enter to continue): ",
|
|
||||||
colorize_string(format!("<yellow>{}</>", &default_url))
|
|
||||||
),
|
|
||||||
default_url,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
Ok(Remote {
|
|
||||||
name: remote_name,
|
|
||||||
branch: remote_branch,
|
|
||||||
url: Url::parse(&remote_url)?,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn write(path: &ResPathBuf, loaded: Option<Config>) -> Result<PathConfig> {
|
|
||||||
println!(
|
|
||||||
"Generating config at {}...\n",
|
|
||||||
colorize_string(format!("<green>{}</>", path.unresolved().display())),
|
|
||||||
);
|
|
||||||
let local = prompt_local(match &loaded {
|
|
||||||
Some(c) => Some(c.local.as_ref()),
|
|
||||||
None => None,
|
|
||||||
})?;
|
|
||||||
let remote = prompt_remote(match &loaded {
|
|
||||||
Some(c) => Some(&c.remote),
|
|
||||||
None => None,
|
|
||||||
})?;
|
|
||||||
let generated = PathConfig {
|
|
||||||
homesync_yml: path.clone(),
|
|
||||||
config: Config {
|
|
||||||
local,
|
|
||||||
remote,
|
|
||||||
packages: loaded.map_or(BTreeMap::new(), |c| c.packages),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
generated.write()?;
|
|
||||||
Ok(generated)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ========================================
|
// ========================================
|
||||||
// Listing
|
// Listing
|
||||||
// ========================================
|
// ========================================
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use super::{config::PathConfig, path};
|
use super::{config::PathConfig, path};
|
||||||
use git2::{IndexAddOption, ObjectType, Remote, Repository, Signature, StashFlags};
|
use git2::{IndexAddOption, ObjectType, Remote, Repository, Signature};
|
||||||
use path::ResPathBuf;
|
use path::ResPathBuf;
|
||||||
use simplelog::{info, paris};
|
use simplelog::{info, paris};
|
||||||
use std::{
|
use std::{
|
||||||
|
|
32
src/lib.rs
32
src/lib.rs
|
@ -4,8 +4,7 @@ pub mod git;
|
||||||
pub mod path;
|
pub mod path;
|
||||||
|
|
||||||
use config::PathConfig;
|
use config::PathConfig;
|
||||||
use path::ResPathBuf;
|
use std::error::Error;
|
||||||
use std::{error::Error, io};
|
|
||||||
|
|
||||||
type Result = std::result::Result<(), Box<dyn Error>>;
|
type Result = std::result::Result<(), Box<dyn Error>>;
|
||||||
|
|
||||||
|
@ -21,35 +20,6 @@ pub fn run_daemon(config: PathConfig, freq_secs: u64) -> Result {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run_init(candidates: Vec<ResPathBuf>) -> Result {
|
|
||||||
debug_assert!(!candidates.is_empty(), "Empty candidates found in `init`.");
|
|
||||||
if candidates.is_empty() {
|
|
||||||
Err(config::Error::IOError(io::Error::new(
|
|
||||||
io::ErrorKind::NotFound,
|
|
||||||
"No suitable config file found.",
|
|
||||||
)))?;
|
|
||||||
}
|
|
||||||
let config = match config::load(&candidates) {
|
|
||||||
// Check if we already have a local config somewhere. If so, reprompt
|
|
||||||
// the same configuration options and override the values present in the
|
|
||||||
// current YAML file.
|
|
||||||
Ok(loaded) => config::write(&loaded.homesync_yml, Some(loaded.config))?,
|
|
||||||
// Otherwise create a new config file at the given location. We always
|
|
||||||
// assume we want to write to the first file in our priority list. If
|
|
||||||
// not, the user should specify which config they want to write using
|
|
||||||
// the `-c` flag.
|
|
||||||
// TODO(jrpotter): Verify I have permission to write at specified path.
|
|
||||||
// Make directories if necessary.
|
|
||||||
Err(config::Error::MissingConfig) if !candidates.is_empty() => {
|
|
||||||
config::write(&candidates[0], None)?
|
|
||||||
}
|
|
||||||
Err(e) => Err(e)?,
|
|
||||||
};
|
|
||||||
git::init(&config)?;
|
|
||||||
println!("\nFinished initialization.");
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn run_list(config: PathConfig) -> Result {
|
pub fn run_list(config: PathConfig) -> Result {
|
||||||
config::list_packages(config);
|
config::list_packages(config);
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
41
src/main.rs
41
src/main.rs
|
@ -60,7 +60,6 @@ fn main() {
|
||||||
.default_value("5"),
|
.default_value("5"),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.subcommand(App::new("init").about("Initialize the homesync local repository"))
|
|
||||||
.subcommand(App::new("list").about("See which packages homesync manages"))
|
.subcommand(App::new("list").about("See which packages homesync manages"))
|
||||||
.subcommand(App::new("push").about("Push changes from local to remote"))
|
.subcommand(App::new("push").about("Push changes from local to remote"))
|
||||||
.get_matches();
|
.get_matches();
|
||||||
|
@ -72,34 +71,24 @@ fn main() {
|
||||||
|
|
||||||
fn dispatch(matches: clap::ArgMatches) -> Result<(), Box<dyn Error>> {
|
fn dispatch(matches: clap::ArgMatches) -> Result<(), Box<dyn Error>> {
|
||||||
let candidates = find_candidates(&matches)?;
|
let candidates = find_candidates(&matches)?;
|
||||||
|
let config = homesync::config::load(&candidates)?;
|
||||||
match matches.subcommand() {
|
match matches.subcommand() {
|
||||||
Some(("init", _)) => Ok(homesync::run_init(candidates)?),
|
Some(("apply", _)) => Ok(homesync::run_apply(config)?),
|
||||||
// All subcommands beside `init` require a config. If we invoke any of
|
Some(("daemon", matches)) => {
|
||||||
// these, immediately attempt to load our config. Note once a config is
|
let freq_secs: u64 = match matches.value_of("frequency") {
|
||||||
// loaded, this same config is used throughout the lifetime of the
|
Some(f) => f.parse().unwrap_or(0),
|
||||||
// process. We avoid introducing the ability to "change" which config is
|
None => 5,
|
||||||
// used, even if one of higher priority is eventually defined.
|
};
|
||||||
subcommand => {
|
if freq_secs > 0 {
|
||||||
let config = homesync::config::load(&candidates)?;
|
homesync::run_daemon(config, freq_secs)?;
|
||||||
match subcommand {
|
} else {
|
||||||
Some(("apply", _)) => Ok(homesync::run_apply(config)?),
|
error!("Invalid frequency. Expected a positive integer.");
|
||||||
Some(("daemon", matches)) => {
|
|
||||||
let freq_secs: u64 = match matches.value_of("frequency") {
|
|
||||||
Some(f) => f.parse().unwrap_or(0),
|
|
||||||
None => 5,
|
|
||||||
};
|
|
||||||
if freq_secs > 0 {
|
|
||||||
homesync::run_daemon(config, freq_secs)?;
|
|
||||||
} else {
|
|
||||||
error!("Invalid frequency. Expected a positive integer.");
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
Some(("list", _)) => Ok(homesync::run_list(config)?),
|
|
||||||
Some(("push", _)) => Ok(homesync::run_push(config)?),
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
Some(("list", _)) => Ok(homesync::run_list(config)?),
|
||||||
|
Some(("push", _)) => Ok(homesync::run_push(config)?),
|
||||||
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue