Skip to content

Commit

Permalink
Replicate local absolute path on remote machine (#236)
Browse files Browse the repository at this point in the history
Closes #214.

As discussed in #214, we now replicate absolute path from local machine in `~/mainframer/…` on remote machine.

This allows user to have multiple projects with same leaf node in the path without clashing, ie:

- `/home/artem_zin/myproject` → `/home/remote_user/mainframer/home/artem_zin/myproject`
- `/home/artem_zin/projects/myproject` → `/home/remote_user/mainframer/home/artem_zin/projects/myproject`

We can also add local machine hostname, but I don't think it's a good idea.

---

Integration tests were updated to expect files in new path. Also tested myself.
  • Loading branch information
artem-zinnatullin authored Nov 15, 2018
1 parent fe6f022 commit 1097180
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 23 deletions.
30 changes: 15 additions & 15 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ use args::Args;
use config::Config;
use ignore::*;
use std::env;
use std::fs;
use std::path::Path;
use std::process;
use std::time::Instant;
use time::*;
Expand All @@ -22,32 +24,30 @@ fn main() {
Ok(value) => value,
};

let working_dir = match env::current_dir() {
let local_dir_absolute_path = match env::current_dir() {
Err(_) => exit_with_error(&"Could not resolve working directory, make sure it exists and user has enough permissions to work with it.", 1),
Ok(value) => value
Ok(value) => fs::canonicalize(value).unwrap()
};

let working_dir_name = working_dir.file_name().unwrap().to_string_lossy().clone();

let mut config_file = working_dir.clone();
let mut config_file = local_dir_absolute_path.to_owned();
config_file.push(".mainframer/config");

let config = match Config::from_file(config_file.as_path()) {
Err(message) => exit_with_error(&message, 1),
Ok(value) => value
};

let ignore = Ignore::from_working_dir(&working_dir);
let ignore = Ignore::from_working_dir(&local_dir_absolute_path);

let start = Instant::now();

if let Err(error) = sync_before_remote_command(&working_dir_name, &config, &ignore) {
if let Err(error) = sync_before_remote_command(&local_dir_absolute_path, &config, &ignore) {
exit_with_error(&format!("Sync local → remote machine failed: {}.", error), 1)
}

let remote_command_result = execute_remote_command(&working_dir_name, &args, &config);
let remote_command_result = execute_remote_command(&local_dir_absolute_path, &args, &config);

if let Err(error) = sync_after_remote_command(&working_dir_name, &config, &ignore) {
if let Err(error) = sync_after_remote_command(&local_dir_absolute_path, &config, &ignore) {
exit_with_error(&format!("Sync remote → local machine failed: {}.", error), 1)
}

Expand All @@ -66,13 +66,13 @@ fn exit_with_error(message: &str, code: i32) -> ! {
process::exit(code);
}

fn sync_before_remote_command(working_dir_name: &str, config: &Config, ignore: &Ignore) -> Result<(), String> {
fn sync_before_remote_command(local_dir_absolute_path: &Path, config: &Config, ignore: &Ignore) -> Result<(), String> {
println!("Sync local → remote machine...");

let start = Instant::now();

let result = sync::sync_local_to_remote(
&working_dir_name,
&local_dir_absolute_path,
config,
ignore,
);
Expand All @@ -88,15 +88,15 @@ fn sync_before_remote_command(working_dir_name: &str, config: &Config, ignore: &
}
}

fn execute_remote_command(working_dir_name: &str, args: &Args, config: &Config) -> Result<(), ()> {
fn execute_remote_command(local_dir_absolute_path: &Path, args: &Args, config: &Config) -> Result<(), ()> {
println!("Executing command on remote machine...\n");

let start = Instant::now();

let result = remote_command::execute_remote_command(
&args.command.clone(),
config,
&format!("~/mainframer/{}", working_dir_name),
sync::project_dir_on_remote_machine(local_dir_absolute_path).as_ref(),
);

let duration = start.elapsed();
Expand All @@ -109,13 +109,13 @@ fn execute_remote_command(working_dir_name: &str, args: &Args, config: &Config)
result
}

fn sync_after_remote_command(working_dir_name: &str, config: &Config, ignore: &Ignore) -> Result<(), String> {
fn sync_after_remote_command(working_dir_name: &Path, config: &Config, ignore: &Ignore) -> Result<(), String> {
println!("Sync remote → local machine...");

let start = Instant::now();

let result = sync::sync_remote_to_local(
&working_dir_name,
working_dir_name,
config,
ignore,
);
Expand Down
15 changes: 8 additions & 7 deletions src/sync.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
use config::Config;
use ignore::Ignore;
use std::path::Path;
use std::path::PathBuf;
use std::process::Command;

// TODO add internal version of sync functions with closures as parameters to unit test properly.
pub fn sync_local_to_remote(local_project_dir_name: &str, config: &Config, ignore: &Ignore) -> Result<(), String> {
pub fn sync_local_to_remote(local_dir_absolute_path: &Path, config: &Config, ignore: &Ignore) -> Result<(), String> {
let mut command = Command::new("rsync");

command
.arg("--archive")
.arg("--delete")
// Create (if not exists) project dir on remote machine.
.arg(format!("--rsync-path=mkdir -p {} && rsync", project_dir_on_remote_machine(local_project_dir_name)))
.arg(format!("--rsync-path=mkdir -p {} && rsync", project_dir_on_remote_machine(local_dir_absolute_path)))
.arg(format!("--compress-level={}", config.local_compression_level));

apply_exclude_from(&mut command, &ignore.common_ignore_file);
Expand All @@ -24,13 +25,13 @@ pub fn sync_local_to_remote(local_project_dir_name: &str, config: &Config, ignor
command.arg(format!(
"{remote_machine_name}:{project_dir_on_remote_machine}",
remote_machine_name = config.remote_machine_name,
project_dir_on_remote_machine = project_dir_on_remote_machine(local_project_dir_name))
project_dir_on_remote_machine = project_dir_on_remote_machine(local_dir_absolute_path))
);

execute_rsync(&mut command)
}

pub fn sync_remote_to_local(local_project_dir_name: &str, config: &Config, ignore: &Ignore) -> Result<(), String> {
pub fn sync_remote_to_local(local_dir_absolute_path: &Path, config: &Config, ignore: &Ignore) -> Result<(), String> {
let mut command = Command::new("rsync");

command
Expand All @@ -46,15 +47,15 @@ pub fn sync_remote_to_local(local_project_dir_name: &str, config: &Config, ignor
.arg(format!(
"{remote_machine_name}:{project_dir_on_remote_machine}/",
remote_machine_name = config.remote_machine_name,
project_dir_on_remote_machine = project_dir_on_remote_machine(local_project_dir_name))
project_dir_on_remote_machine = project_dir_on_remote_machine(local_dir_absolute_path))
)
.arg("./");

execute_rsync(&mut command)
}

fn project_dir_on_remote_machine(local_project_dir_name: &str) -> String {
format!("~/mainframer/{}", local_project_dir_name)
pub fn project_dir_on_remote_machine(local_dir_absolute_path: &Path) -> String {
format!("~/mainframer{}", local_dir_absolute_path.to_string_lossy())
}

fn apply_exclude_from(rsync_command: &mut Command, exclude_file: &Option<PathBuf>) {
Expand Down
2 changes: 1 addition & 1 deletion test/common.sh
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ fi
# Tilde expands on remote machine during ssh.
# shellcheck disable=SC2088
PRIVATE_REMOTE_BUILD_ROOT_DIR="~/mainframer"
PRIVATE_REMOTE_BUILD_DIR="$PRIVATE_REMOTE_BUILD_ROOT_DIR/$PRIVATE_BUILD_DIR_NAME"
PRIVATE_REMOTE_BUILD_DIR="${PRIVATE_REMOTE_BUILD_ROOT_DIR}${DIR}/$PRIVATE_BUILD_DIR_NAME"

### Used by tests (shellcheck raises SC2034)
BUILD_DIR="$DIR/$PRIVATE_BUILD_DIR_NAME"
Expand Down

0 comments on commit 1097180

Please sign in to comment.