Copy even if locally our file doesn't exist.
parent
4bff745573
commit
a43561832f
105
src/copy.rs
105
src/copy.rs
|
@ -1,5 +1,5 @@
|
||||||
use super::{config::PathConfig, path, path::ResPathBuf};
|
use super::{config::PathConfig, path, path::ResPathBuf};
|
||||||
use simplelog::{info, paris};
|
use simplelog::{info, paris, warn};
|
||||||
use std::{
|
use std::{
|
||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
env::VarError,
|
env::VarError,
|
||||||
|
@ -58,15 +58,32 @@ impl error::Error for Error {}
|
||||||
|
|
||||||
fn apply_all(pc: &PathConfig) -> Result<()> {
|
fn apply_all(pc: &PathConfig) -> Result<()> {
|
||||||
let workdir = path::resolve(&pc.config.repos.local)?;
|
let workdir = path::resolve(&pc.config.repos.local)?;
|
||||||
let repo_lookup = get_repo_lookup(workdir.as_ref(), workdir.as_ref())?;
|
let repo_files = walk_repo(workdir.as_ref())?;
|
||||||
let package_lookup = get_package_lookup(pc);
|
let package_lookup = get_package_lookup(pc);
|
||||||
|
|
||||||
for (repo_unresolved, repo_resolved) in &repo_lookup {
|
for repo_file in &repo_files {
|
||||||
if let Some(package_resolved) = package_lookup.get(repo_unresolved) {
|
let path = match package_lookup.get(repo_file.unresolved()) {
|
||||||
fs::copy(repo_resolved, package_resolved)?;
|
Some(value) => value,
|
||||||
|
None => continue,
|
||||||
|
};
|
||||||
|
if let Some(value) = path {
|
||||||
|
fs::copy(repo_file.resolved(), value.resolved())?;
|
||||||
info!(
|
info!(
|
||||||
"Copied `{}` from local repository.",
|
"Copied `{}` from local repository.",
|
||||||
repo_unresolved.display(),
|
repo_file.unresolved().display(),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
let expanded = match path::expand(repo_file.unresolved()) {
|
||||||
|
Ok(expanded) => expanded,
|
||||||
|
Err(_) => continue,
|
||||||
|
};
|
||||||
|
if let Some(p) = expanded.parent() {
|
||||||
|
fs::create_dir_all(p)?;
|
||||||
|
}
|
||||||
|
fs::copy(repo_file.resolved(), expanded)?;
|
||||||
|
info!(
|
||||||
|
"Copied `{}` from local repository.",
|
||||||
|
repo_file.unresolved().display(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -74,25 +91,36 @@ fn apply_all(pc: &PathConfig) -> Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn apply_one(pc: &PathConfig, target: &Path) -> Result<()> {
|
fn apply_one(pc: &PathConfig, package: &str) -> Result<()> {
|
||||||
let workdir = path::resolve(&pc.config.repos.local)?;
|
let workdir = path::resolve(&pc.config.repos.local)?;
|
||||||
let repo_lookup = get_repo_lookup(workdir.as_ref(), workdir.as_ref())?;
|
|
||||||
let package_lookup = get_package_lookup(pc);
|
|
||||||
|
|
||||||
// The user must specify a path that matches the unresolved one.
|
if let Some(paths) = pc.config.packages.get(package) {
|
||||||
if let Some(repo_resolved) = repo_lookup.get(target) {
|
for path in paths {
|
||||||
if let Some(package_resolved) = package_lookup.get(target) {
|
let mut repo_file = workdir.resolved().to_path_buf();
|
||||||
fs::copy(repo_resolved, package_resolved)?;
|
repo_file.push(path);
|
||||||
info!("Copied `{}` from local repository.", target.display(),);
|
if !repo_file.exists() {
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
let expanded = match path::expand(path) {
|
||||||
|
Ok(expanded) => expanded,
|
||||||
|
Err(_) => continue,
|
||||||
|
};
|
||||||
|
if let Some(p) = expanded.parent() {
|
||||||
|
fs::create_dir_all(p)?;
|
||||||
|
}
|
||||||
|
fs::copy(repo_file, expanded)?;
|
||||||
|
info!("Copied `{}` from local repository.", path.display());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
warn!("Could not find package `{}` in config.", package);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn apply(pc: &PathConfig, file: Option<&str>) -> Result<()> {
|
pub fn apply(pc: &PathConfig, package: Option<&str>) -> Result<()> {
|
||||||
if let Some(file) = file {
|
if let Some(package) = package {
|
||||||
apply_one(pc, Path::new(file))
|
apply_one(pc, package)
|
||||||
} else {
|
} else {
|
||||||
apply_all(pc)
|
apply_all(pc)
|
||||||
}
|
}
|
||||||
|
@ -104,16 +132,16 @@ pub fn apply(pc: &PathConfig, file: Option<&str>) -> Result<()> {
|
||||||
|
|
||||||
pub fn stage(pc: &PathConfig) -> Result<()> {
|
pub fn stage(pc: &PathConfig) -> Result<()> {
|
||||||
let workdir = path::resolve(&pc.config.repos.local)?;
|
let workdir = path::resolve(&pc.config.repos.local)?;
|
||||||
let repo_lookup = get_repo_lookup(workdir.as_ref(), workdir.as_ref())?;
|
let repo_files = walk_repo(workdir.as_ref())?;
|
||||||
let package_lookup = get_package_lookup(pc);
|
let package_lookup = get_package_lookup(pc);
|
||||||
|
|
||||||
// Find all files in our repository that are no longer being referenced in
|
// Find all files in our repository that are no longer being referenced in
|
||||||
// our primary config file. They should be removed from the repository.
|
// our primary config file. They should be removed from the repository.
|
||||||
for (repo_unresolved, repo_resolved) in &repo_lookup {
|
for repo_file in &repo_files {
|
||||||
if !package_lookup.contains_key(repo_unresolved) {
|
if !package_lookup.contains_key(repo_file.unresolved()) {
|
||||||
fs::remove_file(repo_resolved)?;
|
fs::remove_file(repo_file.resolved())?;
|
||||||
}
|
}
|
||||||
if let Some(p) = repo_resolved.resolved().parent() {
|
if let Some(p) = repo_file.resolved().parent() {
|
||||||
if p.read_dir()?.next().is_none() {
|
if p.read_dir()?.next().is_none() {
|
||||||
fs::remove_dir(p)?;
|
fs::remove_dir(p)?;
|
||||||
}
|
}
|
||||||
|
@ -122,13 +150,15 @@ pub fn stage(pc: &PathConfig) -> Result<()> {
|
||||||
|
|
||||||
// Find all resolvable files in our primary config and copy them into the
|
// Find all resolvable files in our primary config and copy them into the
|
||||||
// repository.
|
// repository.
|
||||||
for (package_unresolved, package_resolved) in &package_lookup {
|
for (key, value) in &package_lookup {
|
||||||
let mut copy = package_resolved.resolved().to_path_buf();
|
if let Some(value) = value {
|
||||||
copy.push(package_unresolved);
|
let mut copy = value.resolved().to_path_buf();
|
||||||
|
copy.push(key);
|
||||||
if let Some(p) = copy.parent() {
|
if let Some(p) = copy.parent() {
|
||||||
fs::create_dir_all(p)?;
|
fs::create_dir_all(p)?;
|
||||||
}
|
}
|
||||||
fs::copy(package_resolved.resolved(), copy)?;
|
fs::copy(value.resolved(), copy)?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
info!(
|
info!(
|
||||||
|
@ -143,8 +173,8 @@ pub fn stage(pc: &PathConfig) -> Result<()> {
|
||||||
// Utility
|
// Utility
|
||||||
// ========================================
|
// ========================================
|
||||||
|
|
||||||
fn get_repo_lookup(root: &Path, path: &Path) -> Result<HashMap<PathBuf, ResPathBuf>> {
|
fn recursive_walk_repo(root: &Path, path: &Path) -> Result<Vec<ResPathBuf>> {
|
||||||
let mut seen = HashMap::new();
|
let mut seen = Vec::new();
|
||||||
if path.is_dir() {
|
if path.is_dir() {
|
||||||
for entry in fs::read_dir(path)? {
|
for entry in fs::read_dir(path)? {
|
||||||
let nested = entry?.path();
|
let nested = entry?.path();
|
||||||
|
@ -152,26 +182,31 @@ fn get_repo_lookup(root: &Path, path: &Path) -> Result<HashMap<PathBuf, ResPathB
|
||||||
if nested.ends_with(".git") {
|
if nested.ends_with(".git") {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let nested = get_repo_lookup(root, &nested)?;
|
let nested = recursive_walk_repo(root, &nested)?;
|
||||||
seen.extend(nested);
|
seen.extend_from_slice(&nested);
|
||||||
} else {
|
} else {
|
||||||
let relative = nested
|
let relative = nested
|
||||||
.strip_prefix(root)
|
.strip_prefix(root)
|
||||||
.expect("Relative git file could not be stripped properly.")
|
.expect("Relative git file could not be stripped properly.");
|
||||||
.to_path_buf();
|
seen.push(ResPathBuf::new(&nested, relative)?);
|
||||||
seen.insert(relative, ResPathBuf::new(&nested)?);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(seen)
|
Ok(seen)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_package_lookup(pc: &PathConfig) -> HashMap<PathBuf, ResPathBuf> {
|
fn walk_repo(root: &Path) -> Result<Vec<ResPathBuf>> {
|
||||||
|
recursive_walk_repo(root, root)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_package_lookup(pc: &PathConfig) -> HashMap<PathBuf, Option<ResPathBuf>> {
|
||||||
let mut seen = HashMap::new();
|
let mut seen = HashMap::new();
|
||||||
for (_, packages) in &pc.config.packages {
|
for (_, packages) in &pc.config.packages {
|
||||||
for path in packages {
|
for path in packages {
|
||||||
if let Ok(resolved) = path::resolve(path) {
|
if let Ok(resolved) = path::resolve(path) {
|
||||||
seen.insert(path.to_path_buf(), resolved);
|
seen.insert(path.to_path_buf(), Some(resolved));
|
||||||
|
} else {
|
||||||
|
seen.insert(path.to_path_buf(), None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,8 +9,8 @@ use std::error::Error;
|
||||||
|
|
||||||
type Result = std::result::Result<(), Box<dyn Error>>;
|
type Result = std::result::Result<(), Box<dyn Error>>;
|
||||||
|
|
||||||
pub fn run_apply(config: PathConfig, file: Option<&str>) -> Result {
|
pub fn run_apply(config: PathConfig, package: Option<&str>) -> Result {
|
||||||
copy::apply(&config, file)?;
|
copy::apply(&config, package)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
18
src/main.rs
18
src/main.rs
|
@ -1,8 +1,10 @@
|
||||||
use clap::{App, AppSettings, Arg};
|
use clap::{App, AppSettings, Arg};
|
||||||
use homesync::path::ResPathBuf;
|
use homesync::path::ResPathBuf;
|
||||||
use simplelog;
|
|
||||||
use simplelog::{error, paris};
|
|
||||||
use std::{error::Error, io, path::PathBuf};
|
use std::{error::Error, io, path::PathBuf};
|
||||||
|
use {
|
||||||
|
simplelog,
|
||||||
|
simplelog::{error, paris},
|
||||||
|
};
|
||||||
|
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
fn log_level() -> simplelog::LevelFilter {
|
fn log_level() -> simplelog::LevelFilter {
|
||||||
|
@ -42,18 +44,18 @@ fn main() {
|
||||||
App::new("apply")
|
App::new("apply")
|
||||||
.about("Copy files from local repository to rest of desktop")
|
.about("Copy files from local repository to rest of desktop")
|
||||||
.arg(
|
.arg(
|
||||||
Arg::new("file")
|
Arg::new("package")
|
||||||
.value_name("FILE")
|
.value_name("PACKAGE")
|
||||||
.conflicts_with("all")
|
.conflicts_with("all")
|
||||||
.required_unless_present("all")
|
.required_unless_present("all")
|
||||||
.help("The file we want to overwrite from the local repository")
|
.help("The package we want to configure from the local repository")
|
||||||
.takes_value(true),
|
.takes_value(true),
|
||||||
)
|
)
|
||||||
.arg(
|
.arg(
|
||||||
Arg::new("all")
|
Arg::new("all")
|
||||||
.long("all")
|
.long("all")
|
||||||
.conflicts_with("file")
|
.conflicts_with("package")
|
||||||
.help("Indicates we want to copy all files from the local repository")
|
.help("Indicates we want to copy all configurations from the local repository")
|
||||||
.takes_value(false),
|
.takes_value(false),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
@ -93,7 +95,7 @@ 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)?;
|
let config = homesync::config::load(&candidates)?;
|
||||||
match matches.subcommand() {
|
match matches.subcommand() {
|
||||||
Some(("apply", matches)) => Ok(homesync::run_apply(config, matches.value_of("file"))?),
|
Some(("apply", matches)) => Ok(homesync::run_apply(config, matches.value_of("package"))?),
|
||||||
Some(("daemon", matches)) => {
|
Some(("daemon", matches)) => {
|
||||||
let freq_secs: u64 = match matches.value_of("frequency") {
|
let freq_secs: u64 = match matches.value_of("frequency") {
|
||||||
Some(f) => f.parse().unwrap_or(0),
|
Some(f) => f.parse().unwrap_or(0),
|
||||||
|
|
10
src/path.rs
10
src/path.rs
|
@ -68,13 +68,13 @@ fn unresolved_error(path: &Path) -> io::Error {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ResPathBuf {
|
impl ResPathBuf {
|
||||||
pub fn new(path: &Path) -> Result<Self> {
|
pub fn new(inner: &Path, unresolved: &Path) -> Result<Self> {
|
||||||
if !path.is_absolute() {
|
if !inner.is_absolute() {
|
||||||
Err(unresolved_error(path))?;
|
Err(unresolved_error(inner))?;
|
||||||
}
|
}
|
||||||
Ok(ResPathBuf {
|
Ok(ResPathBuf {
|
||||||
inner: path.to_path_buf(),
|
inner: inner.to_path_buf(),
|
||||||
unresolved: path.to_path_buf(),
|
unresolved: unresolved.to_path_buf(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue