Skip to content

Commit

Permalink
copy, hash, file, meta, add scripts
Browse files Browse the repository at this point in the history
  • Loading branch information
jenna-a2ai committed Mar 26, 2024
1 parent e067d7b commit 46f2be8
Show file tree
Hide file tree
Showing 13 changed files with 162 additions and 37 deletions.
1 change: 1 addition & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"https://json.schemastore.org/github-workflow.json": "file:///home/andriygm/projects/devious/.github/workflows/goreleaser.yml"
},
"rust-analyzer.linkedProjects": [
"./Cargo.toml",
"./Cargo.toml",
"./Cargo.toml",
"./Cargo.toml"
Expand Down
12 changes: 12 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ edition = "2021"
[dependencies]
serde = { version = "1.0", features = ["derive"] }
serde_yaml = "0.9"
serde_json = "1.0.79"
clap = {version = "4.4.17", features = ["derive"]}
extendr-api = '*'
blake3 = { version = "1.5.1", features = ["rayon"] }
Expand Down
2 changes: 1 addition & 1 deletion src/internal/file/hash.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use blake3::Hasher;
use std::path::PathBuf;
use std::fs::File;
use extendr_api::prelude::*;
// use extendr_api::prelude::*;
use std::io::Result;
use std::io::{self, Read};

Expand Down
34 changes: 34 additions & 0 deletions src/internal/git/ignore.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
use std::{fs::{File, OpenOptions}, path::PathBuf};
use crate::internal::git::repo;
use std::io::prelude::*;

pub fn add_gitignore_entry(git_dir: &PathBuf, path: &PathBuf) -> Result<(), std::io::Error> {
// get relative path
let ignore_entry_temp = match repo::get_relative_path(git_dir, path) {
Ok(entry) => entry,
Err(e) => return Err(e)
};
// Add leading slash
let path = ignore_entry_temp.display().to_string();
let ignore_entry = format!("/{path}");

// open the gitignore file, creating one if it doesn't exist
let ignore_file = git_dir.join(".gitignore");
if !ignore_file.exists() {
File::create(&ignore_file).expect("gitignore cannot be created");
}
let contents = std::fs::read_to_string(&ignore_file).unwrap();
if !contents.contains(&ignore_entry) {
let mut file = OpenOptions::new()
.write(true)
.append(true)
.open(ignore_file)
.unwrap();

if let Err(e) = writeln!(file, "\n\n# Devious entry\n{ignore_entry}" ) {
eprintln!("Couldn't write to file: {}", e);
}

} // add ignore entry
Ok(())
}
3 changes: 2 additions & 1 deletion src/internal/git/mod.rs
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
pub mod repo;
pub mod repo;
pub mod ignore;
2 changes: 1 addition & 1 deletion src/internal/git/repo.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::path::{PathBuf, Path};
use std::fs;

fn get_relative_path(root_dir: &PathBuf, file_path: &PathBuf) -> Result<PathBuf, std::io::Error> {
pub fn get_relative_path(root_dir: &PathBuf, file_path: &PathBuf) -> Result<PathBuf, std::io::Error> {
let abs_file_path = match file_path.canonicalize() {
Ok(path) => path,
Err(e) => return Err(e),
Expand Down
38 changes: 38 additions & 0 deletions src/internal/meta/file.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
use std::time::SystemTime;
use std::path::PathBuf;
use std::fs::File;
use serde::{Deserialize, Serialize};
use serde_json::Result;
use std::fs;

#[derive(Serialize, Deserialize)]
pub struct Metadata {
pub file_hash: String,
pub file_size: u64,
pub time_stamp: SystemTime,
pub message: String,
pub group: String,
pub saved_by: String
}

// static FILE_EXTENSION: String = String::from(".dvsmeta");

pub fn save(metadata: &Metadata, path: &PathBuf) -> Result<()> {
// compose path file/to/file.ext.dvsmeta
let metadata_file_path = PathBuf::from(path.display().to_string() + ".dvsmeta");

// create file
File::create(&metadata_file_path);

// write to json
let contents = serde_json::to_string(&metadata).unwrap();
fs::write(&metadata_file_path, contents);
Ok(())
}

pub fn load(path: PathBuf) -> Result<Metadata> {
let contents = fs::read_to_string(path).unwrap();
let metadata_file: Metadata = serde_json::from_str(&contents)?;

return Ok(metadata_file);
}
1 change: 1 addition & 0 deletions src/internal/meta/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub mod file;
44 changes: 39 additions & 5 deletions src/internal/storage/add.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
use std::path::PathBuf;
use std::time::SystemTime;
use file_owner::PathExt;

use crate::internal::file::hash;
use crate::internal::storage::copy;
use crate::internal::meta::file;
use crate::internal::git::ignore;

pub fn add(local_path: &PathBuf, storage_dir: &PathBuf, git_dir: &PathBuf, message: String) -> Result<String, std::io::Error> {
// get file hash
Expand Down Expand Up @@ -43,17 +47,47 @@ pub fn add(local_path: &PathBuf, storage_dir: &PathBuf, git_dir: &PathBuf, messa
Ok(data) => data,
Err(e) => return Err(e),
};
let local_path_size = local_path_data.len();
let file_size = local_path_data.len();

// get user
let owner = match local_path.owner() {
Ok(owner) => owner,
Err(_) => return Err(std::io::Error::other("file owner not found")),
};
// get user name
let owner_name = match owner.name() {
Ok(name) => name.unwrap(),
Err(_) => {return Err(std::io::Error::other("file owner not found"))},
};

// get group
let group = match local_path.group() {
Ok(group) => group,
Err(_) => return Err(std::io::Error::other("file group not found")),
};
// get group name
let group_name = match group.name() {
Ok(name) => name.unwrap(),
Err(_) => {return Err(std::io::Error::other("file group not found"))},
};

// Create + write metadata file
// create + write metadata file
let metadata = file::Metadata{
file_hash: file_hash.clone(),
file_size: file_size,
time_stamp: SystemTime::now(),
message: message,
group: group_name,
saved_by: owner_name
};

match file::save(&metadata, &local_path) {
Ok(_) => {},
Err(_) => return Err(std::io::Error::other("metadata file not created"))
};

// Add file to gitignore


ignore::add_gitignore_entry(git_dir, local_path).expect("gitignore entry unable to be added");
return Ok(file_hash);

}
9 changes: 4 additions & 5 deletions src/internal/storage/copy.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use std::path::PathBuf;
use std::fs::{create_dir_all, File};
use std::os::unix::fs::PermissionsExt;
use std::io;
use std::fs;
use std::fs::Permissions;

Expand All @@ -28,7 +27,7 @@ pub fn copy(src_path: &PathBuf, dest_path: &PathBuf) -> Result<(), std::io::Erro
Ok(data) => data,
Err(e) => return Err(e),
};
let src_file_size = src_file_data.len();
let _src_file_size = src_file_data.len();

// ensure destination exists
match create_dir_all(dest_path.parent().unwrap()) {
Expand All @@ -37,18 +36,18 @@ pub fn copy(src_path: &PathBuf, dest_path: &PathBuf) -> Result<(), std::io::Erro
}

// create destination file
let dest_file = match File::create(dest_path) {
match File::create(dest_path) {
Ok(file) => file,
Err(e) => return Err(e),
};

// Set destination file permissions
let mode: u32 = 0o664;
let permissions: Permissions = fs::Permissions::from_mode(mode);
fs::set_permissions(dest_path, permissions);
fs::set_permissions(dest_path, permissions).expect("file unable to be copied, permissions denied");

// Copy the file
fs::copy(src_path, dest_path);
fs::copy(src_path, dest_path).expect("file unable to be copied");

Ok(())
}
45 changes: 24 additions & 21 deletions src/internal/storage/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,13 @@ use std::fs::Permissions;
use file_owner::{Group, PathExt};

pub fn init(root_dir: &PathBuf, storage_dir: &PathBuf, mode: &u32, group_name: &String) -> Result<(), std::io::Error> { //
// get storage directory as an absolute path (don't use canoniicalize which checks if the path exists)
let storage_dir_abs = normalize_path(storage_dir);

// check storage directory permissions
let md = fs::metadata(&storage_dir_abs)?;
let permissions = md.permissions();
let readonly = permissions.readonly();
if readonly { // create storage dir
// get storage directory as a normalized path
let storage_dir_norm = normalize_path(storage_dir);

// should I use .exists or .is_dir?
if !storage_dir.exists() { // if storage directory doesn't exist
// create storage dir
match create_dir(&storage_dir_abs) {
match create_dir(&storage_dir_norm) {
Ok(_) => {
// json: success
}
Expand All @@ -27,21 +24,21 @@ pub fn init(root_dir: &PathBuf, storage_dir: &PathBuf, mode: &u32, group_name: &
return Err(e)
}
};
}
else { // storage dir already exists
// json: Storage directory already exists
} // if

// Ensure storage dir is a directory
if !storage_dir_abs.clone().is_dir() {
// json: fail
return Err(std::io::Error::other("storage dir is not a directory"));
}
else { // else, storage directory exists
// json: Storage directory already exists

// Warn if storage dir is not readable
match repo::is_directory_empty(storage_dir_abs.as_path()) {
Ok(_) => {
// json
// Warn if storage dir is empty
match repo::is_directory_empty(storage_dir_norm.as_path()) {
Ok(empty) => {
if empty {
// json
println!("directory is empty")
}
else {
println!("directory is not empty")
}
}
Err(e) => {
//json
Expand All @@ -50,6 +47,12 @@ pub fn init(root_dir: &PathBuf, storage_dir: &PathBuf, mode: &u32, group_name: &
}
} // else

// get absolute path
let storage_dir_abs = match storage_dir_norm.canonicalize() {
Ok(path) => path,
Err(e) => return Err(e),
};

// set permissions
let permissions: Permissions = fs::Permissions::from_mode(*mode);
match fs::set_permissions(&storage_dir_abs, permissions) {
Expand Down
7 changes: 4 additions & 3 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,18 @@ use crate::internal::storage::copy;
fn main() -> io::Result<()> {
// test init
let storage_dir = PathBuf::from(r"src/test_directory");
let mode: u32 = 0o664;
let mode: u32 = 0o764;
let group = String::from("datascience");

fs::set_permissions(&storage_dir.canonicalize().unwrap(), fs::Permissions::from_mode(0o777)).unwrap();
init_cmd::get_init_runner(&storage_dir, &mode, &group)?;
//fs::set_permissions(&storage_dir.canonicalize().unwrap(), fs::Permissions::from_mode(0o777)).unwrap();
println!("initialized devious");

// test hash
let hash_path = PathBuf::from("/cluster-data/user-homes/jenna/Projects/devious/src/test_directory/test.txt");
let hash_output = hash::hash_file_with_blake3(&hash_path)?;
assert_eq!(hash_output, "71fe44583a6268b56139599c293aeb854e5c5a9908eca00105d81ad5e22b7bb6");
println!("{hash_output}");
println!("hash is {hash_output}");

// test copy
let src = PathBuf::from("src/test_directory/test.txt");
Expand Down

0 comments on commit 46f2be8

Please sign in to comment.