Skip to content

Commit 3c3e427

Browse files
committed
read the file chunk by chunk to check the modification of files
1 parent 8a18325 commit 3c3e427

9 files changed

Lines changed: 219 additions & 18 deletions

File tree

Cargo.lock

Lines changed: 78 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,14 @@ members = ["cli", "crates/*"]
44

55
[workspace.dependencies]
66
clap = { version = "4.5.47", features = ["derive"] }
7+
zip = { version = "7.0.0", default-features = false }
78
walkdir = "2.5.0"
89

910
[workspace.package]
1011
description = "A simple Rust tool for syncing directories with change detection"
1112
edition = "2024"
1213
repository = "https://github.com/ibilalkayy/cover"
13-
version = "0.1.22"
14+
version = "0.1.23"
1415
license = "Apache-2.0"
1516
readme = "README.md"
1617
keywords = ["backup", "sync", "filesystem"]

cli/src/flags/archive.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use std::path::PathBuf;
2+
13
use clap::Parser;
24

35
/// It takes the required information for archiving the data
@@ -11,6 +13,7 @@ use clap::Parser;
1113
/// use my_crate::ArchiveData;
1214
///
1315
/// let archive = ArchiveData {
16+
/// source: PathBuf::from("source_directory"),
1417
/// zip: true,
1518
/// tar: false,
1619
/// encrypt: false,
@@ -19,6 +22,10 @@ use clap::Parser;
1922
/// ```
2023
#[derive(Debug, Parser)]
2124
pub struct ArchiveData {
25+
/// Source folder to take the file from
26+
#[clap(short, long)]
27+
pub source: PathBuf,
28+
2229
/// Save the file as .zip
2330
#[clap(long)]
2431
pub zip: bool,

cli/src/main.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ fn handle_commands() {
3838
}
3939
Command::Archive(a) => {
4040
let archive_data = ArchiveData {
41+
source: a.source,
4142
zip: a.zip,
4243
tar: a.tar,
4344
encrypt: a.encrypt,

crates/cover_files/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,4 @@ categories.workspace = true
99

1010
[dependencies]
1111
walkdir.workspace = true
12+
zip.workspace = true

crates/cover_files/src/archive/archive.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1+
use std::path::PathBuf;
2+
13
pub struct ArchiveData {
4+
pub source: PathBuf,
25
pub zip: bool,
36
pub tar: bool,
47
pub encrypt: bool,

crates/cover_files/src/sync/changes.rs

Lines changed: 42 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,47 @@
11
use super::sync::SyncData;
2-
use std::{fs::read_to_string, path::PathBuf};
2+
use std::{
3+
fs::File,
4+
io::{BufReader, Read},
5+
path::PathBuf,
6+
};
7+
8+
const CHUNK_SIZE: usize = 8 * 1024;
39

410
/// Implementation of the source and destination files that are created or modified.
511
impl SyncData {
12+
pub fn files_are_equal(&self, src_file: &PathBuf, dest_file: &PathBuf) -> bool {
13+
let src_open = File::open(src_file).expect("[ERROR]: failed to open the source file");
14+
let dest_open =
15+
File::open(dest_file).expect("[ERROR]: failed to open the destination file");
16+
17+
let mut src_reader = BufReader::new(src_open);
18+
let mut dest_reader = BufReader::new(dest_open);
19+
20+
let mut buf_src = [0u8; CHUNK_SIZE];
21+
let mut buf_dest = [0u8; CHUNK_SIZE];
22+
23+
loop {
24+
let src_content = src_reader
25+
.read(&mut buf_src)
26+
.expect("[ERROR]: failed to read the file");
27+
let dest_content = dest_reader
28+
.read(&mut buf_dest)
29+
.expect("[ERROR]: failed to read the file");
30+
31+
if src_content != dest_content {
32+
return false;
33+
}
34+
35+
if src_content == 0 {
36+
return true;
37+
}
38+
39+
if buf_src[..src_content] != buf_dest[..dest_content] {
40+
return false;
41+
}
42+
}
43+
}
44+
645
/// Checks whether the source file is created or not.
746
///
847
/// Resturns:
@@ -115,12 +154,7 @@ impl SyncData {
115154
let src_path = self.source.join(path);
116155
let dest_path = self.destination.join(path);
117156

118-
let src_content =
119-
read_to_string(src_path).expect("[ERROR]: failed to read the file");
120-
let dest_content =
121-
read_to_string(dest_path).expect("[ERROR]: failed to read the file");
122-
123-
if src_content != dest_content {
157+
if !self.files_are_equal(&src_path, &dest_path) {
124158
modified_files.push(path.clone());
125159
}
126160
}
@@ -245,12 +279,7 @@ impl SyncData {
245279
let src_path = self.source.join(path);
246280
let dest_path = self.destination.join(path);
247281

248-
let src_content =
249-
read_to_string(src_path).expect("[ERROR]: failed to read the file");
250-
let dest_content =
251-
read_to_string(dest_path).expect("[ERROR]: failed to read the file");
252-
253-
if src_content != dest_content {
282+
if !self.files_are_equal(&src_path, &dest_path) {
254283
modified_files.push(path.clone());
255284
}
256285
}
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
// use cover_files::archive::archive::ArchiveData;
2+
// use std::{
3+
// env,
4+
// fs::{create_dir_all, remove_dir_all},
5+
// path::PathBuf,
6+
// };
7+
8+
// #[test]
9+
// fn test_src_dir_present() {
10+
// let home_dir = env::var("HOME").expect("[ERROR]: failed to get the home directory");
11+
// let src_parent_dir = PathBuf::from(&home_dir).join("tmpsrc_present");
12+
13+
// if src_parent_dir.exists() {
14+
// remove_dir_all(&src_parent_dir).ok();
15+
// }
16+
// create_dir_all(&src_parent_dir).expect("[ERROR]: failed to create a source directory");
17+
18+
// let archive = ArchiveData {
19+
// source: src_parent_dir.clone(),
20+
// zip: true,
21+
// tar: false,
22+
// encrypt: false,
23+
// timestamp: false,
24+
// };
25+
26+
// assert!(
27+
// archive.src_dir_present(),
28+
// "[ERROR]: source directory not detected"
29+
// );
30+
31+
// remove_dir_all(&src_parent_dir).ok();
32+
// }
33+
34+
// #[test]
35+
// fn test_single_flag_provided() {
36+
// let home_dir = env::var("HOME").expect("[ERROR]: failed to get the home directory");
37+
// let src_parent_dir = PathBuf::from(&home_dir).join("tmpsrc_zip_flag");
38+
39+
// if src_parent_dir.exists() {
40+
// remove_dir_all(&src_parent_dir).ok();
41+
// }
42+
43+
// create_dir_all(&src_parent_dir).expect("[ERROR]: failed to create a source directory");
44+
45+
// let archive = ArchiveData {
46+
// source: src_parent_dir.clone(),
47+
// zip: true,
48+
// tar: false,
49+
// encrypt: false,
50+
// timestamp: false,
51+
// };
52+
53+
// assert!(
54+
// archive.single_flag_provided(),
55+
// "[ERROR]: expected one flag, but multiple are reported"
56+
// );
57+
58+
// remove_dir_all(&src_parent_dir).ok();
59+
// }
60+
61+
// #[test]
62+
// fn test_src_file_zipped() {
63+
// let home_dir = env::var("HOME").expect("[ERROR]: failed to get the home directory");
64+
// let src_parent_dir = PathBuf::from(&home_dir).join("tmpsrc_zip");
65+
66+
// if src_parent_dir.exists() {
67+
// remove_dir_all(&src_parent_dir).ok();
68+
// }
69+
70+
// create_dir_all(&src_parent_dir).expect("[ERROR]: failed to create a source directory");
71+
72+
// let archive = ArchiveData {
73+
// source: src_parent_dir.clone(),
74+
// zip: true,
75+
// tar: false,
76+
// encrypt: false,
77+
// timestamp: false,
78+
// };
79+
80+
// assert!(archive.src_file_zipped(), "[ERROR]: failed to zip the file");
81+
82+
// remove_dir_all(src_parent_dir).ok();
83+
// }

crates/cover_files/tests/sync_test.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use walkdir::WalkDir;
1616

1717
#[test]
1818
fn test_src_dest_dir_present() {
19-
let home_dir = env::var("HOME").expect("HOME env variable not set");
19+
let home_dir = env::var("HOME").expect("[ERROR]: failed to get the home directory");
2020

2121
let src_parent_dir = PathBuf::from(&home_dir).join("tmpsrc_present");
2222
let dest_parent_dir = PathBuf::from(&home_dir).join("tmpdest_present");
@@ -1066,7 +1066,7 @@ fn test_src_dir_present() {
10661066

10671067
#[test]
10681068
fn test_dest_dir_present() {
1069-
let home_dir = env::var("HOME").expect("HOME env variable not set");
1069+
let home_dir = env::var("HOME").expect("[ERROR]: failed to get the home directory");
10701070
let dest_parent_dir = PathBuf::from(&home_dir).join("tmpdest_presence");
10711071

10721072
if dest_parent_dir.exists() {

0 commit comments

Comments
 (0)