1use flate2::{write::GzEncoder, Compression};
2use sha2::{Digest, Sha256};
3
4use crate::{error, in_repo};
5
6use std::{
7 fs,
8 fs::File,
9 io,
10 io::{Read, Write},
11 path::Path,
12};
13
14pub fn add(file: &str) -> io::Result<()> {
15 if !in_repo() {
16 return Err(error!("Current folder is not a rvcs repository."));
17 }
18
19 if !Path::new(file).exists() {
20 return Err(error!(
21 (&format!("No file named `{}` in the current folder.", file))
22 ));
23 }
24
25 if Path::new(file).is_dir() {
26 if file.contains(".rvcs") {
27 return Ok(());
28 }
29
30 let entries = fs::read_dir(file)?;
31 for entry in entries {
32 add(entry?.path().to_str().unwrap())?;
33 }
34 } else {
35 let mut content = vec![];
36 File::open(file)?.read_to_end(&mut content)?;
37
38 let mut hasher = Sha256::new();
39 hasher.update(&content);
40 let fname = format!("{:x}", hasher.finalize());
41
42 if Path::new(&format!(".rvcs/objects/{}", fname)).exists() {
43 return Ok(());
44 }
45
46 let mut compressor = GzEncoder::new(vec![], Compression::best());
47 compressor.write_all(&content)?;
48
49 let mut nfile = File::create(&format!(".rvcs/objects/{}", fname))?;
50 nfile.write_all(&compressor.finish()?)?;
51
52 if !Path::new(".rvcs/objects/links").exists() {
53 File::create(".rvcs/objects/links")?;
54 }
55 let mut flink = fs::OpenOptions::new()
56 .append(true)
57 .open(".rvcs/objects/links")?;
58 flink.write_all(format!("{}|{}\n", file, fname).as_bytes())?;
59 }
60
61 Ok(())
62}