pub struct BackupManager { /* private fields */ }Expand description
BackupManager is a struct responsible for managing backup operations.
This struct serves as a core component for creating, storing, and retrieving backups
in the system. It encapsulates the Repository where backup data is managed,
providing an interface to interact with the underlying repository for backup-related tasks.
§Fields
repository: The repository where backup data is stored and managed.
§Example
use obsidian_backups::BackupManager;
let backup_manager = BackupManager::new("./backup_store", "./my_data")
.expect("Failed to create BackupManager");Implementations§
Source§impl BackupManager
impl BackupManager
Sourcepub fn new(
store_directory: impl AsRef<Path>,
working_directory: impl AsRef<Path>,
) -> Result<Self>
pub fn new( store_directory: impl AsRef<Path>, working_directory: impl AsRef<Path>, ) -> Result<Self>
Creates a new instance of BackupManager.
This function initializes a BackupManager by setting up a new Git repository
in the specified store_directory with the specified working_directory as
the working directory for the repository.
§Arguments
store_directory- A reference to a path where the repository data will be stored.working_directory- A reference to a path that will serve as the working directory for the repository.
Both arguments accept types that can be converted into a PathBuf.
§Returns
Returns Ok(Self) with the initialized BackupManager if successful, or an error
if the Git repository initialization fails.
§Logging
- Logs an informational message when starting and successfully completing the initialization process.
- Logs debug messages showing the resolved paths and steps during initialization.
§Errors
Returns an error if repository initialization fails. This typically occurs due to invalid paths, insufficient permissions, or issues with the Git backend.
§Example
use obsidian_backup_system::BackupManager;
let manager = BackupManager::new("./backup_store", "./my_data")
.expect("Failed to initialize BackupManager");Note: Ensure that the provided paths are valid and writable for the process.
Sourcepub fn setup_ignore_file(&mut self, ignore_file: impl AsRef<Path>) -> Result<()>
pub fn setup_ignore_file(&mut self, ignore_file: impl AsRef<Path>) -> Result<()>
Sets up a .gitignore-style ignore file for the repository using the provided file path.
This function configures an ignore matcher to exclude specified paths or patterns.
§Arguments
ignore_file- A path-like object referencing the ignore file to process. The file should follow.gitignoresyntax.
§Returns
Result<()>- ReturnsOk(())if the ignore matcher is successfully built and configured. Returns an error if the ignore matcher cannot be built or if the ignore file causes an issue.
§Behavior
- Locates the working directory of the repository. Defaults to
./if the repository has no working directory. - Initializes a
GitignoreBuilderusing the repository’s working directory. - Checks whether the provided ignore file exists:
- If the file exists, attempts to add it to the builder. Logs a warning if there’s an issue while adding the file.
- Attempts to construct the ignore matcher from the builder:
- If successful, stores the ignore matcher in
self.ignore_matcher. - If unsuccessful, logs an error message and returns an error.
- If successful, stores the ignore matcher in
§Errors
- Returns an error if:
- The ignore file could not be properly parsed or added.
- The ignore matcher fails to build successfully.
§Logging
- Logs a warning message if the function fails to add the ignore file to the builder.
- Logs an error message if the function fails to build the ignore matcher.
§Example Usage
use std::path::Path;
use obsidian_backup_system::BackupManager;
let mut backup_manager = BackupManager::new("./backup_store", "./my_data")?;
backup_manager.setup_ignore_file(".my_ignore_file")?;Sourcepub fn list(&self) -> Result<Vec<BackupItem>>
pub fn list(&self) -> Result<Vec<BackupItem>>
Lists all backup items available in the repository.
The method traverses the commit history of the repository, collects metadata for each commit, and returns a list of items representing the backup points. Each item includes the commit ID, timestamp, and commit message.
§Process
- Logs an informational message indicating the start of the operation.
- Initializes a revision walk over the repository to retrieve commit objects.
- Iterates through each commit, retrieves its metadata, and constructs a
BackupIteminstance. - Each created
BackupItemis logged at the trace level, and the total count is logged at the end.
§Returns
A Result containing a vector of BackupItem instances if the operation succeeds, or an error
if any repository operation fails.
§Errors
Returns an error if:
- The revision walk initialization fails.
- Retrieving an individual commit in the history fails.
- Any other repository-related operation encounters an error.
§Logging
- Logs informational messages about the start and result of the operation.
- Logs debug messages about processing individual commits.
- Logs trace messages with details of each created
BackupItem.
§Example
use obsidian_backup_system::BackupManager;
let manager = BackupManager::new("./backup_store", "./my_data")
.expect("Failed to initialize BackupManager");
match manager.list() {
Ok(backup_items) => {
for item in backup_items {
println!("Backup ID: {}, Timestamp: {}, Description: {}",
item.id, item.timestamp, item.description);
}
},
Err(e) => eprintln!("Error listing backup items: {}", e),
}§Note
The method assumes that commit messages are UTF-8 encoded. If a commit has no message, an empty string is used as the description.
§Dependencies
- Requires the repository to be properly initialized and accessible.
- Relies on the
BackupItemstruct to hold commit metadata.
Sourcepub fn backup(&self, description: Option<String>) -> Result<String>
pub fn backup(&self, description: Option<String>) -> Result<String>
Creates a backup by committing the current state of the repository.
This method stages all changes, creates a commit with the given description, and returns the ID of the newly created commit. If no description is provided, a default description of “No description provided” is used. It also ensures proper handling for creating an initial commit if the repository does not have an existing HEAD.
§Arguments
description- An optional string containing a description for the backup commit.
§Returns
Returns a Result<String> which contains:
- On success: The ID of the newly created commit as a string.
- On failure: An error indicating the cause of the failure.
§Errors
This function will return an error if:
- There is an issue accessing or writing the repository index.
- There is an issue creating a new tree or finding the tree object in the repository.
- The repository signature (user name and email) is invalid or not set.
- The commit operation fails due to any Git-related error.
§Logging
This method emits the following log messages:
infologs for the overall operation (Creating backup,Backup created successfully).debuglogs for intermediate steps, such as getting the index, adding files, writing the tree, finding parents, creating signatures, and creating the commit.
§Example
use obsidian_backup_system::BackupManager;
let manager = BackupManager::new("./backup_store", "./my_data")
.expect("Failed to initialize BackupManager");
let description = Some("Backup before deployment".to_string());
match manager.backup(description) {
Ok(commit_id) => println!("Backup created with ID: {}", commit_id),
Err(e) => eprintln!("Failed to create backup: {}", e),
}§Notes
- This method assumes that the caller has already initialized the repository (
self.repository) and has proper permissions to write to it. - If no HEAD exists (e.g., for an empty repository), it creates an initial commit without parent commits.
Sourcepub fn restore(&self, backup_id: impl AsRef<str>) -> Result<()>
pub fn restore(&self, backup_id: impl AsRef<str>) -> Result<()>
Restores a backup by its ID and checks out the associated commit.
§Arguments
backup_id- A reference to a string that uniquely identifies the backup. This ID is parsed as a git object ID.
§Returns
Result<()>- ReturnsOk(())if the backup was successfully restored, or an error if the operation fails at any stage.
§Process
- The backup ID is parsed as a git object ID (OID).
- The associated git commit is retrieved using the OID.
- The commit’s tree is accessed, and its contents are checked out in the repository.
- If the repository is configured with a working directory:
- The contents of the current working directory are removed.
- A new working directory is created.
- HEAD is checked out into the working directory.
- Logs are generated at various points to provide insights into the restoration process.
§Logs
- Info logs are used to indicate the start and successful completion of the restore operation.
- Debug logs provide detailed information about each step of the process, such as parsing the backup ID, working with git objects, and modifying the working directory.
- Warning logs occur if no working directory is configured for the repository.
§Errors
Returns an error if any of the following occurs:
- The backup ID cannot be parsed as a valid git OID.
- The associated commit cannot be found in the repository.
- The commit’s tree cannot be accessed.
- Checking out the tree in the repository fails.
- File system operations, such as removing or creating the working directory, encounter errors.
§Example Usage
use obsidian_backup_system::BackupManager;
let manager = BackupManager::new("./backup_store", "./my_data")
.expect("Failed to initialize BackupManager");
let backup_id = "abcdef1234567890";
if let Err(err) = manager.restore(backup_id) {
eprintln!("Failed to restore backup: {}", err);
} else {
println!("Backup restored successfully!");
}Sourcepub fn diff(&self, backup_id: impl AsRef<str>) -> Result<Vec<ModifiedFile>>
pub fn diff(&self, backup_id: impl AsRef<str>) -> Result<Vec<ModifiedFile>>
Computes the list of files that were modified (added, updated, or deleted) in the specified backup/commit within the repository.
§Arguments
backup_id- A string-like identifier for the backup or commit to compute the modified files against its parent commit. The function expects this to be in the format of a valid Git object ID.
§Returns
A Result containing:
Ok(Vec<ModifiedFile>)- A vector ofModifiedFileobjects, each representing a file that was added, updated, or deleted. EachModifiedFileincludes:path: The path of the file.content_before: The file’s content before modification (if applicable,Someif the file existed, otherwiseNone).content_after: The file’s content after modification (if applicable,Someif the file exists, otherwiseNonefor deletions).
Err(git2::Error)- In case of any error during Git repository or commit/tree operations.
§Details
- The function computes the difference between the specified commit/tree and its immediate parent (if available). If there is no parent commit (e.g., for the first commit), only the newly added files will appear in the output list.
- For each file in the current tree:
- If a corresponding file exists in the parent tree, the function checks for modifications.
- If the file does not exist in the parent tree, it is marked as newly added.
- For files that existed in the parent tree but are absent in the current tree, the function marks them as deleted.
§Errors
This function can return an Err in the following situations:
- If the provided
backup_idis not a valid Git commit or tree object ID. - If the repository cannot find the commit or tree corresponding to
backup_id. - If there are errors while retrieving or processing blobs within the trees.
§Example
use obsidian_backup_system::BackupManager;
let manager = BackupManager::new("./backup_store", "./my_data")
.expect("Failed to initialize BackupManager");
let backup_id = "abcd1234";
let modified_files = manager.diff(backup_id)
.expect("Failed to get diff");
for file in modified_files {
println!("Path: {}", file.path);
match (&file.content_before, &file.content_after) {
(Some(before), Some(after)) => {
println!("File was modified. Before size: {}, After size: {}", before.len(), after.len());
}
(None, Some(after)) => {
println!("File was added. Size: {}", after.len());
}
(Some(before), None) => {
println!("File was deleted. Previous size: {}", before.len());
}
_ => {}
}
}§Structs Used
ModifiedFile: A struct representing a modified file, with the following fields:path: The file’s path as aString.content_before: An optionalVec<u8>containing the file’s content in the parent revision (if it existed).content_after: An optionalVec<u8>containing the file’s content in the current revision (if it exists).
§Note
- This function assumes text or binary files are stored as blobs in the Git repository.
- Files that are not blobs (e.g., submodules or symlinks) are ignored.