9 Commits

Author SHA1 Message Date
d94ed4d167 fix: rename args variables 2025-11-14 13:45:40 +01:00
36bc38a5a2 feat: update documentation 2025-11-13 16:20:03 +01:00
8a26e5736e fix: update version number in cargo manifest 2025-11-13 12:25:17 +01:00
741ce597f9 feat: updates deps 2025-11-13 12:23:10 +01:00
b3c202c880 Merge pull request 'feat/restore' (#2) from feat/restore into master
Reviewed-on: #2
2025-11-13 11:18:08 +00:00
5a63d792fb fix: remove tests from git 2025-11-13 12:17:04 +01:00
6ca5decd91 fix: remove old actions 2025-11-13 12:15:39 +01:00
c3e4b276e9 feat: restore and compare before deletion
All checks were successful
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 11s
2025-11-13 12:13:45 +01:00
ac912fea08 feat: add demo actions
All checks were successful
Gitea Actions Demo / Explore-Gitea-Actions (push) Successful in 4s
2025-10-02 17:11:18 +02:00
9 changed files with 189 additions and 160 deletions

View File

@@ -1,23 +0,0 @@
name: Rust
on:
push:
branches: [ "master" ]
tags: [ "*" ]
pull_request:
branches: [ "master" ]
env:
CARGO_TERM_COLOR: always
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build
run: cargo build --verbose
- name: Run tests
run: cargo test --verbose

1
.gitignore vendored
View File

@@ -1 +1,2 @@
target/
tests/

139
Cargo.lock generated
View File

@@ -4,9 +4,9 @@ version = 4
[[package]]
name = "anstream"
version = "0.6.18"
version = "0.6.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b"
checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a"
dependencies = [
"anstyle",
"anstyle-parse",
@@ -19,42 +19,42 @@ dependencies = [
[[package]]
name = "anstyle"
version = "1.0.10"
version = "1.0.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9"
checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78"
[[package]]
name = "anstyle-parse"
version = "0.2.6"
version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9"
checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2"
dependencies = [
"utf8parse",
]
[[package]]
name = "anstyle-query"
version = "1.1.2"
version = "1.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c"
checksum = "9e231f6134f61b71076a3eab506c379d4f36122f2af15a9ff04415ea4c3339e2"
dependencies = [
"windows-sys",
]
[[package]]
name = "anstyle-wincon"
version = "3.0.7"
version = "3.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca3534e77181a9cc07539ad51f2141fe32f6c3ffd4df76db8ad92346b003ae4e"
checksum = "3e0633414522a32ffaac8ac6cc8f748e090c5717661fddeea04219e2344f5f2a"
dependencies = [
"anstyle",
"once_cell",
"once_cell_polyfill",
"windows-sys",
]
[[package]]
name = "bak"
version = "0.2.0"
version = "0.3.2"
dependencies = [
"clap",
"sha2",
@@ -71,15 +71,15 @@ dependencies = [
[[package]]
name = "cfg-if"
version = "1.0.0"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
[[package]]
name = "clap"
version = "4.5.36"
version = "4.5.51"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2df961d8c8a0d08aa9945718ccf584145eee3f3aa06cddbeac12933781102e04"
checksum = "4c26d721170e0295f191a69bd9a1f93efcdb0aff38684b61ab5750468972e5f5"
dependencies = [
"clap_builder",
"clap_derive",
@@ -87,9 +87,9 @@ dependencies = [
[[package]]
name = "clap_builder"
version = "4.5.36"
version = "4.5.51"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "132dbda40fb6753878316a489d5a1242a8ef2f0d9e47ba01c951ea8aa7d013a5"
checksum = "75835f0c7bf681bfd05abe44e965760fea999a5286c6eb2d59883634fd02011a"
dependencies = [
"anstream",
"anstyle",
@@ -99,9 +99,9 @@ dependencies = [
[[package]]
name = "clap_derive"
version = "4.5.32"
version = "4.5.49"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09176aae279615badda0765c0c0b3f6ed53f4709118af73cf4655d85d1530cd7"
checksum = "2a0b5487afeab2deb2ff4e03a807ad1a03ac532ff5a2cee5d86884440c7f7671"
dependencies = [
"heck",
"proc-macro2",
@@ -111,15 +111,15 @@ dependencies = [
[[package]]
name = "clap_lex"
version = "0.7.4"
version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6"
checksum = "a1d728cc89cf3aee9ff92b05e62b19ee65a02b5702cff7d5a377e32c6ae29d8d"
[[package]]
name = "colorchoice"
version = "1.0.3"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990"
checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75"
[[package]]
name = "cpufeatures"
@@ -132,9 +132,9 @@ dependencies = [
[[package]]
name = "crypto-common"
version = "0.1.6"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a"
dependencies = [
"generic-array",
"typenum",
@@ -168,45 +168,45 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
[[package]]
name = "is_terminal_polyfill"
version = "1.70.1"
version = "1.70.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695"
[[package]]
name = "libc"
version = "0.2.172"
version = "0.2.177"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa"
checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976"
[[package]]
name = "once_cell"
version = "1.21.3"
name = "once_cell_polyfill"
version = "1.70.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe"
[[package]]
name = "proc-macro2"
version = "1.0.95"
version = "1.0.103"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778"
checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.40"
version = "1.0.42"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f"
dependencies = [
"proc-macro2",
]
[[package]]
name = "sha2"
version = "0.10.8"
version = "0.10.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8"
checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283"
dependencies = [
"cfg-if",
"cpufeatures",
@@ -221,9 +221,9 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
[[package]]
name = "syn"
version = "2.0.100"
version = "2.0.110"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0"
checksum = "a99801b5bd34ede4cf3fc688c5919368fea4e4814a4664359503e6015b280aea"
dependencies = [
"proc-macro2",
"quote",
@@ -232,15 +232,15 @@ dependencies = [
[[package]]
name = "typenum"
version = "1.18.0"
version = "1.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f"
checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb"
[[package]]
name = "unicode-ident"
version = "1.0.18"
version = "1.0.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5"
[[package]]
name = "utf8parse"
@@ -255,20 +255,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
[[package]]
name = "windows-sys"
version = "0.59.0"
name = "windows-link"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
[[package]]
name = "windows-sys"
version = "0.60.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb"
dependencies = [
"windows-targets",
]
[[package]]
name = "windows-targets"
version = "0.52.6"
version = "0.53.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3"
dependencies = [
"windows-link",
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
@@ -281,48 +288,48 @@ dependencies = [
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.52.6"
version = "0.53.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53"
[[package]]
name = "windows_aarch64_msvc"
version = "0.52.6"
version = "0.53.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006"
[[package]]
name = "windows_i686_gnu"
version = "0.52.6"
version = "0.53.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3"
[[package]]
name = "windows_i686_gnullvm"
version = "0.52.6"
version = "0.53.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c"
[[package]]
name = "windows_i686_msvc"
version = "0.52.6"
version = "0.53.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2"
[[package]]
name = "windows_x86_64_gnu"
version = "0.52.6"
version = "0.53.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.6"
version = "0.53.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1"
[[package]]
name = "windows_x86_64_msvc"
version = "0.52.6"
version = "0.53.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650"

View File

@@ -1,6 +1,6 @@
[package]
name = "bak"
version = "0.2.0"
version = "0.3.2"
edition = "2021"
[dependencies]

View File

@@ -1,4 +1,4 @@
Copyright © 2024 RamiusLr
Copyright © 2024-2025 RamiusLr
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

View File

@@ -8,18 +8,22 @@ This may be for you: `bak myfile`
# Options
```console
Usage: bak [OPTIONS] <FILENAME>
Usage: bak [FILE] [COMMAND]
Commands:
res
del
help Print this message or the help of the given subcommand(s)
Arguments:
<FILENAME> Specify the filename to backup
[FILE] File to backup (used if no subcommand is provided)
Options:
-d, --delete Add this flag to delete the backup file
-h, --help Print help
-V, --version Print version
```
# License
```console
MIT License Copyright (c) 2024 ramiuslr
MIT License Copyright (c) 2024-2025 ramiuslr
```

View File

@@ -1,47 +1,83 @@
// use sha2::{Digest, Sha256};
use std::path::Path;
use sha2::{Digest, Sha256};
use std::fs;
use std::io::{self, Read, Write};
use std::path::{Path, PathBuf};
// fn hash_file(path: &Path) -> Result<Vec<u8>, std::io::Error> {
// let mut file = fs::File::open(path)?;
// let mut hasher = Sha256::new();
// let mut buffer = [0; 4096];
/// Calculate hash sum of given file
fn hash_file(path: &Path) -> Result<Vec<u8>, std::io::Error> {
let mut file = fs::File::open(path)?;
let mut hasher = Sha256::new();
let mut buffer = [0; 4096];
// loop {
// let bytes_read = file.read(&mut buffer)?;
// if bytes_read == 0 {
// break;
// }
// hasher.update(&buffer[..bytes_read]);
// }
loop {
let bytes_read = file.read(&mut buffer)?;
if bytes_read == 0 {
break;
}
hasher.update(&buffer[..bytes_read]);
}
// Ok(hasher.finalize().to_vec())
// }
Ok(hasher.finalize().to_vec())
}
// fn compare_hashes(file1: &Path, file2: &Path) -> Result<bool, std::io::Error> {
// let hash1 = hash_file(file1)?;
// let hash2 = hash_file(file2)?;
// Ok(hash1 == hash2)
// }
/// Check if files differ by comparing hashes
fn files_differ(file1: &Path, file2: &Path) -> Result<bool, std::io::Error> {
if !file1.exists() || !file2.exists() {
return Ok(false); // treat non-existent files as "no difference"
}
Ok(hash_file(file1)? != hash_file(file2)?)
}
/// The function which backups the file
/// It erases any existing backup with the same name
fn set_bak_file_name(file: &Path) -> PathBuf {
file.with_file_name(format!("{}.bak", file.display()))
}
/// Backup the file
/// It overwrites any existing backup with the same name
pub fn backup_file(file: &Path) -> Result<(), std::io::Error> {
let mut bak_name = file.to_path_buf();
bak_name.set_extension("bak");
if let Err(e) = std::fs::copy(file, bak_name) {
let bak_name = set_bak_file_name(file);
fs::copy(file, bak_name)?;
Ok(())
}
/// Delete the backup file, optionally confirming if it differs from the original
pub fn delete_backup_file(file: &Path) -> Result<(), std::io::Error> {
let bak_name = set_bak_file_name(file);
if bak_name.exists() {
if files_differ(file, &bak_name)? {
print!(
"Backup '{}' differs from '{}'. Delete anyway? (y/N): ",
bak_name.display(),
file.display()
);
io::stdout().flush()?; // Make sure the prompt shows
let mut input = String::new();
io::stdin().read_line(&mut input)?;
let input = input.trim().to_lowercase();
if input != "y" && input != "yes" {
println!("Deletion canceled.");
return Ok(());
}
}
fs::remove_file(&bak_name)?;
println!("Backup '{}' deleted.", bak_name.display());
} else {
println!("Backup '{}' does not exist.", bak_name.display());
}
Ok(())
}
/// Restore the backup file, erasing the actual file
pub fn restore_backup_file(file: &Path) -> Result<(), std::io::Error> {
let bak_name = set_bak_file_name(file);
if let Err(e) = std::fs::rename(bak_name, file) {
return Err(e);
} else {
return Ok(());
}
}
/// A function to delete the backup file
pub fn delete_backup_file(file: &Path) -> Result<(), std::io::Error> {
let mut bak_name = file.to_path_buf();
bak_name.set_extension("bak");
if let Err(e) = std::fs::remove_file(&bak_name) {
Err(e)
} else {
Ok(())
}
}

View File

@@ -1,38 +1,46 @@
use bak::{backup_file, delete_backup_file};
use clap::Parser;
use bak::{backup_file, delete_backup_file, restore_backup_file};
use clap::{Parser, Subcommand};
use std::path::PathBuf;
use std::process;
#[derive(Parser)]
#[command(version, about, long_about = None)]
struct Opts {
/// Add this flag to delete the backup file
#[arg(short, long)]
delete: bool,
#[command(name = "bak-rs", version, about, long_about = None)]
struct Args {
/// Optional subcommand (restore or delete). Default is backup
#[command(subcommand)]
command: Option<Commands>,
/// Specify the filename to backup
file: PathBuf,
/// File to backup (used if no subcommand is provided)
file: Option<PathBuf>,
}
fn error_handling(e: std::io::Error) {
match e.kind() {
std::io::ErrorKind::NotFound => eprintln!("File not found"),
std::io::ErrorKind::PermissionDenied => eprintln!("Cannot open file, check permissions"),
_ => eprintln!("Critical error: {}", e),
}
std::process::exit(1);
#[derive(Subcommand)]
enum Commands {
Res { file: PathBuf },
Del { file: PathBuf },
}
fn main() -> Result<(), std::io::Error> {
let opts = Opts::parse();
fn main() {
let opts = Args::parse();
if opts.delete {
if let Err(e) = delete_backup_file(&opts.file) {
error_handling(e);
let result = match opts.command {
Some(Commands::Res { file }) => restore_backup_file(&file),
Some(Commands::Del { file }) => delete_backup_file(&file),
None => {
let file = opts
.file
.as_ref()
.expect("File must be specified for backup");
backup_file(file)
}
} else {
if let Err(e) = backup_file(&opts.file) {
error_handling(e);
};
if let Err(e) = result {
match e.kind() {
std::io::ErrorKind::NotFound => eprintln!("File not found"),
std::io::ErrorKind::PermissionDenied => eprintln!("Permission denied"),
_ => eprintln!("Critical error: {}", e),
}
process::exit(1);
}
Ok(())
}

View File

@@ -1,4 +0,0 @@
#[test]
fn test_true() {
assert!(true);
}