rvcs_lib/
add.rs

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}