Replaced git2 crate add to index, commit and push with calls to git cli and changed delay to 30 min

This commit is contained in:
Robin Gottschalk 2025-03-14 09:05:20 +01:00
parent f1e025e059
commit 8d149e201c
5 changed files with 34 additions and 68 deletions

18
Cargo.lock generated
View File

@ -168,12 +168,6 @@ version = "1.21.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef657dfab802224e671f5818e9a4935f9b1957ed18e58292690cc39e7a4092a3"
[[package]]
name = "byteorder"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]]
name = "bytes"
version = "1.9.0"
@ -1135,17 +1129,6 @@ dependencies = [
"unicode-segmentation",
]
[[package]]
name = "keyring"
version = "3.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2f8fe839464d4e4b37d756d7e910063696af79a7e877282cb1825e4ec5f10833"
dependencies = [
"byteorder",
"log",
"windows-sys 0.59.0",
]
[[package]]
name = "kqueue"
version = "1.0.8"
@ -1664,7 +1647,6 @@ version = "0.1.0"
dependencies = [
"chrono",
"git2",
"keyring",
"notify",
"tray-icon",
"winit",

View File

@ -9,4 +9,3 @@ notify = "8.0.0"
tray-icon = "0.19.2"
git2 = "0.20.0"
chrono = "0.4.39"
keyring = { version = "3.6.1", features = ["windows-native"] }

View File

@ -7,6 +7,7 @@ This script automates the process of backing up your Obsidian vault to a Git rep
- [x] Trigger backup after file changes with delay
- [x] Maintain git repo in a seperate folder to not have the repo synced by syncthing (copy changed files over)
- [x] Push changes to remote repository
- [x] Make adding and pushing LFS objects work with git
- [x] Tray Menu
- [x] Exit
- [x] Backup now
@ -30,3 +31,4 @@ This script automates the process of backing up your Obsidian vault to a Git rep
*.svg filter=lfs diff=lfs merge=lfs -text
```
- Link repository to origin as remote
- Make sure the underlying system has the git user set up with the corresponding access token

View File

@ -1,7 +1,7 @@
use chrono::Local;
use git2::{Cred, Error, IndexAddOption, PushOptions, RemoteCallbacks, Repository, StatusOptions};
use keyring::Entry;
use git2::{Error, Repository, StatusOptions};
use std::path::Path;
use std::process::Command;
pub fn current_change_count(repo_path: &Path) -> Result<usize, Error> {
// Open the repository at the provided path
@ -38,58 +38,41 @@ pub fn backup_changes(repo_path: &Path) -> Result<(), Box<dyn std::error::Error>
println!(" - {}: {:?}", path, status);
}
// Add all changes to the index
let mut index = repo.index()?;
index.add_all(["*"].iter(), IndexAddOption::DEFAULT, None)?;
index.write()?;
// Write the index to a tree
let tree_id = index.write_tree()?;
let tree = repo.find_tree(tree_id)?;
// Use the repository signature for both author and committer
let signature = repo.signature()?;
// Determine the parent commit
let parent_commit = repo.head()?.peel_to_commit()?;
// Stage all changes using the Git CLI
let status = Command::new("git")
.arg("add")
.arg("-A")
.current_dir(repo_path)
.status()?;
if !status.success() {
return Err("git add failed".into());
}
// Generate commit message with current timestamp
let commit_message = format!("{} Autobackup", Local::now().format("%Y-%m-%d %H:%M:%S"));
// Create commit
repo.commit(
Some("HEAD"),
&signature,
&signature,
&commit_message,
&tree,
&[&parent_commit],
)?;
// Create a commit with a timestamped message
let status = Command::new("git")
.arg("commit")
.arg("-m")
.arg(&commit_message)
.current_dir(repo_path)
.status()?;
if !status.success() {
return Err("git commit failed".into());
}
// Set up remote push with credentials callback
let mut callbacks = RemoteCallbacks::new();
callbacks.credentials(move |_url, username, _allowed_types| {
let user = username.unwrap_or("git");
let token = get_git_token();
Cred::userpass_plaintext(user, &token)
});
// Push changes
let mut push_options = PushOptions::new();
push_options.remote_callbacks(callbacks);
let mut remote = repo.find_remote("origin")?;
remote.push(&["refs/heads/main"], Some(&mut push_options))?;
// Push changes with Git CLI
let status = Command::new("git")
.arg("push")
.arg("origin")
.arg("main")
.current_dir(repo_path)
.status()?;
if !status.success() {
return Err("git push failed".into());
}
println!("Changes committed and pushed successfully.");
Ok(())
}
fn get_git_token() -> String {
// Get token from Windows Credential Manager
let service = "obsidian-git-backup"; // git.obsidian-git-backup in Credetial Manager
let username = "git";
let entry = Entry::new(service, username).unwrap();
entry
.get_password()
.expect("Git access token could not be retrieved from Windows Credential Manager")
}

View File

@ -19,7 +19,7 @@ const PROTECT_PREFIX: &str = ".git"; // only at first directory level
const SOURCE_VAULT: &str = "D:\\Cloud\\Syncthing\\obsidian-vault"; // syncthing vault folder
const REPO_VAULT: &str =
"C:\\Users\\robin\\AppData\\Roaming\\obsidian-git-backup\\obsidian-vault-clone"; // git repo folder
const GIT_COMMIT_DELAY_AFTER_FILE_CHANGE: Duration = Duration::from_secs(5 * 60); // 5 min
const GIT_COMMIT_DELAY_AFTER_FILE_CHANGE: Duration = Duration::from_secs(30 * 60); // 30 min
#[derive(Debug)]
enum UserEvent {