1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
|
mod git_tools;
use std::env;
use std::fs;
use std::io::{Result, Error, ErrorKind};
use std::path::Path;
use std::process::exit;
use git_tools::*;
fn main() -> Result<()> {
if let Ok(cwd) = env::current_dir() {
if let Err(e) = scan_directories_to_synchronize(&cwd) {
eprintln!("Could not check directory for git repositories: {}", e);
exit(1);
}
} else {
eprintln!("Could not find current directory.");
exit(1);
}
Ok(())
}
fn scan_directories_to_synchronize(path: &Path) -> Result<()> {
let sync_ignore_file = path.join(".syncignore");
if sync_ignore_file.exists() {
return Ok(())
}
let git_directory = path.join(".git");
if git_directory.exists() {
if let Err(e) = synchronize_directory(&path) {
let relative_path = get_relative_path(path).unwrap();
eprintln!("Sync failed for {:?}. {}", relative_path, e);
}
} else {
for entry in fs::read_dir(path)? {
let path = entry?.path();
if path.is_dir() {
scan_directories_to_synchronize(&path)?;
}
}
}
Ok(())
}
fn synchronize_directory(path: &Path) -> Result<()> {
let previous_branch = git_save_previous_branch(path)?;
git_checkout(path, "main")?;
let result = attempt_synchronization(path);
git_checkout(path, &previous_branch)?;
result
}
fn attempt_synchronization(path: &Path) -> Result<()> {
let relative_path = get_relative_path(path).unwrap();
eprint!("{:?}. ", relative_path);
let previous_commit = get_commit(path, "HEAD")?;
git_fetch(path)?;
let remote_commit = get_commit(path, "origin/main")?;
if previous_commit == remote_commit {
eprintln!("Already up to date.");
return Ok(());
}
match git_check_for_conflicts(path) {
Ok(conflicts) => {
if !conflicts {
git_merge(path)?;
let new_commit = get_commit(path, "HEAD")?;
eprint!("Merged origin {:?}->{:?}. ", previous_commit, new_commit);
git_push(path)?;
eprintln!("Pushed.");
} else {
return Err(Error::new(ErrorKind::Other, "Conflicts detected"));
}
},
Err(e) => {
return Err(e);
}
}
Ok(())
}
// Path Helpers
fn get_relative_path(path: &Path) -> Option<String> {
let cwd = env::current_dir().unwrap();
path.strip_prefix(cwd)
.ok()
.and_then(|p| p.to_str())
.map(|s| s.to_string())
}
|