diff --git a/README.md b/README.md index cbb5843..8b19d5e 100644 --- a/README.md +++ b/README.md @@ -133,6 +133,12 @@ Refer to `:h backupcopy` for details on how this works. ## Contribution +To get started, we recommend reviewing the documentation: + +```bash +cargo doc --open +``` + Install git hooks as follows: ```bash diff --git a/src/config.rs b/src/config.rs index c59b36e..114fd2c 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,3 +1,29 @@ +//! The in-memory representation of the homesync config. Refer to +//! [homesync/template.yml](https://github.com/jrpotter/homesync/blob/main/rsrc/template.yml) +//! (copied below) for an example of what this config might look like. +//! +//! ```yaml +//! --- +//! user: +//! name: name +//! email: email@email.com +//! ssh: +//! public: $HOME/.ssh/id_ed25519.pub +//! private: $HOME/.ssh/id_ed25519 +//! repos: +//! local: $HOME/.homesync +//! remote: +//! name: origin +//! branch: master +//! url: "https://github.com/owner/repo.git" +//! packages: +//! homesync: +//! - $HOME/.homesync.yml +//! - $HOME/.config/homesync/homesync.yml +//! - $XDG_CONFIG_HOME/homesync.yml +//! - $XDG_CONFIG_HOME/homesync/homesync.yml +//! ``` + use super::{path, path::ResPathBuf}; use paris::formatter::colorize_string; use serde_derive::{Deserialize, Serialize}; @@ -134,6 +160,7 @@ impl PathConfig { // Loading // ======================================== +/// The paths our homesync configuration may live in, ordered by priority. pub const DEFAULT_PATHS: &[&str] = &[ "$HOME/.homesync.yml", "$HOME/.config/homesync/homesync.yml", @@ -141,10 +168,13 @@ pub const DEFAULT_PATHS: &[&str] = &[ "$XDG_CONFIG_HOME/homesync/homesync.yml", ]; +/// The paths our homesync configuration may live in, ordered by priority. pub fn default_paths() -> Vec { DEFAULT_PATHS.iter().map(|s| PathBuf::from(s)).collect() } +/// Reads in the homesync configuration file into a [PathConfig](struct.PathConfig.html) +/// instance. pub fn load(candidates: &Vec) -> Result { // When trying our paths, the only acceptable error is a `NotFound` file. // Anything else should be surfaced to the end user. @@ -161,6 +191,11 @@ pub fn load(candidates: &Vec) -> Result { Err(Error::MissingConfig) } +/// Reads in the homesync configuration file into a [PathConfig](struct.PathConfig.html) +/// instance. +/// +/// Useful in cases where we notice the homesync config itself has changed while +/// homesync is running. pub fn reload(pc: &PathConfig) -> Result { info!( "Reloaded: Configuration {}.", @@ -173,6 +208,7 @@ pub fn reload(pc: &PathConfig) -> Result { // Listing // ======================================== +/// Prints the list of packages found in a [PathConfig](struct.PathConfig.html). pub fn list_packages(pc: PathConfig) { println!( "Listing packages in {}...\n", diff --git a/src/copy.rs b/src/copy.rs index ee1d8b9..5eee22a 100644 --- a/src/copy.rs +++ b/src/copy.rs @@ -1,3 +1,5 @@ +//! Utilities for traversing directories and copying files around. + use super::{config::PathConfig, path, path::ResPathBuf}; use git2::Repository; use simplelog::{info, paris, warn}; @@ -122,6 +124,13 @@ fn apply_one(pc: &PathConfig, package: &str) -> Result<()> { Ok(()) } +/// Copy files from the local repository to the corresponding file location on +/// the current machine. +/// +/// By default we are required to specify which package we want to apply. If +/// we'd like, we can choose to apply all files found in the local repository. +/// Warning! You should probably `pull` first to ensure your local repository is +/// synced with the remote one, especially if running with `--all`. pub fn apply(pc: &PathConfig, package: Option<&str>) -> Result<()> { if let Some(package) = package { apply_one(pc, package) @@ -134,6 +143,8 @@ pub fn apply(pc: &PathConfig, package: Option<&str>) -> Result<()> { // Staging // ======================================== +/// Finds all files specified in the homesync config and copies them (if they +/// exist) into the local repo. pub fn stage(pc: &PathConfig) -> Result<()> { let workdir = get_workdir(pc)?; let repo_files = walk_repo(workdir.as_ref())?; diff --git a/src/daemon.rs b/src/daemon.rs index 8af3c3d..f0010ae 100644 --- a/src/daemon.rs +++ b/src/daemon.rs @@ -1,3 +1,10 @@ +//! Utilites around launching a filewatcher daemon service. +//! +//! This is intended to be the primary use case of Homesync once stable. The +//! daemon is responsible for loading in the homesync config (reloading as it +//! changes) and monitoring any files/file paths specified within. On changes, +//! it will automatically stage the files to the local repository. + use super::{config, config::PathConfig, copy, path, path::ResPathBuf}; use notify::{DebouncedEvent, RecommendedWatcher, RecursiveMode, Watcher}; use simplelog::{error, paris, trace, warn}; @@ -137,6 +144,10 @@ impl<'a> WatchState<'a> { // Daemon // ======================================== +/// Launches a daemon service that monitors changes to files specified in the +/// config and stages them for changes in the local repository. +/// +/// Warning! This service is still under development. pub fn launch(mut pc: PathConfig, freq_secs: u64) -> Result<(), Box> { let (poll_tx, poll_rx) = channel(); let (watch_tx, watch_rx) = channel(); diff --git a/src/git.rs b/src/git.rs index c4e2914..9dd6f68 100644 --- a/src/git.rs +++ b/src/git.rs @@ -1,3 +1,7 @@ +//! Utilities around git +//! [plumbing](https://git-scm.com/book/en/v2/Git-Internals-Plumbing-and-Porcelain) +//! commands. + use super::{config::PathConfig, path}; use git2::{ BranchType, Commit, Cred, DiffOptions, Direction, FetchOptions, Index, IndexAddOption, @@ -83,7 +87,8 @@ fn clone(pc: &PathConfig, expanded: &Path) -> Result { // for both ensuring any remote repositories are already managed by homesync and // for storing any persisted configurations. -/// Sets up a local github repository all configuration files will be synced to. +/// Sets up a local git repository all configuration files will be synced to. +/// /// If there does not exist a local repository at the requested location, we /// attempt to make it via cloning or initializing. pub fn init(pc: &PathConfig) -> Result { @@ -153,6 +158,11 @@ fn create_readme(repo: &Repository) -> Result<()> { Ok(()) } +/// Take the current state of the local repository and push changes to the +/// remote. +/// +/// This method will always pull before pushing to make sure there are no +/// conflicts that should be resolved. pub fn push(pc: &PathConfig, repo: &mut Repository) -> Result<()> { // First pull to make sure there are no conflicts when we push our changes. // This will also perform validation and construct our local and remote @@ -260,6 +270,11 @@ fn local_rebase_remote(pc: &PathConfig, repo: &Repository) -> Result<()> { Ok(()) } +/// Take the current state of the remote repository and pull changes to the +/// local. +/// +/// Using git parlance, this method will stash any changes that currently exist +/// and reapply the changes after in case of merge conflicts. pub fn pull(pc: &PathConfig, repo: &mut Repository) -> Result<()> { repo.workdir().ok_or(Error::InvalidBareRepo)?; diff --git a/src/lib.rs b/src/lib.rs index a00c3f0..c5cf5ca 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,17 @@ +//! [homesync](https://github.com/jrpotter/homesync) is a project for collecting +//! various files strewn across your computer and consolidating them +//! automatically into a local git repository. It has the means of pushing those +//! changes to a remote git repository for syncing to other machines. Homesync +//! can pull in these changes on a different machine and *apply* the files, +//! putting them all in the correct spot. +//! +//! Throughout this documentation the "local repository" always refers to the +//! git repository homesync is managing (and potentially created on start). The +//! remote repository refers to the git repo hosted at the URL specified in the +//! homesync config. +//! +//! Thank you for your interest in contributing! + pub mod config; pub mod copy; pub mod daemon; @@ -9,33 +23,39 @@ use std::error::Error; type Result = std::result::Result<(), Box>; +/// Refer to [copy::apply](copy/fn.apply.html). pub fn run_apply(config: PathConfig, package: Option<&str>) -> Result { copy::apply(&config, package)?; Ok(()) } +/// Refer to [daemon::launch](daemon/fn.launch.html). pub fn run_daemon(config: PathConfig, freq_secs: u64) -> Result { daemon::launch(config, freq_secs)?; Ok(()) } +/// Refer to [config::list_packages](config/fn.list_packages.html). pub fn run_list(config: PathConfig) -> Result { config::list_packages(config); Ok(()) } +/// Refer to [git::push](git/fn.run_push.html). pub fn run_push(config: PathConfig) -> Result { let mut repo = git::init(&config)?; git::push(&config, &mut repo)?; Ok(()) } +/// Refer to [git::pull](git/fn.run_pull.html). pub fn run_pull(config: PathConfig) -> Result { let mut repo = git::init(&config)?; git::pull(&config, &mut repo)?; Ok(()) } +/// Refer to [copy::stage](copy/fn.stage.html). pub fn run_stage(config: PathConfig) -> Result { copy::stage(&config)?; Ok(()) diff --git a/src/main.rs b/src/main.rs index 6054ab2..2014cb6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -42,7 +42,7 @@ fn main() { ) .subcommand( App::new("apply") - .about("Copy files from local repository to rest of desktop") + .about("Copy files from local repository to corresponding location") .arg( Arg::new("package") .value_name("PACKAGE") diff --git a/src/path.rs b/src/path.rs index dccdb83..89e3917 100644 --- a/src/path.rs +++ b/src/path.rs @@ -1,3 +1,5 @@ +//! Utilities for resolving paths. + use serde::{ de, de::{Unexpected, Visitor}, @@ -54,6 +56,10 @@ impl error::Error for Error {} // Path // ======================================== +/// A "resolved" `PathBuf` that takes in the originally supplied (potentially +/// relative) path and annotates it with the absolute path. A `ResPathBuf` +/// instance cannot be made if the relative path supplied to it does not refer +/// to an actual file. #[derive(Clone, Debug)] pub struct ResPathBuf { inner: PathBuf,