├── .gitignore ├── Cargo.lock ├── Cargo.toml ├── docs ├── README.md └── pics │ └── rustix-visual-1.png └── src ├── add_file.rs ├── database └── mod.rs ├── delete.rs ├── initialize.rs ├── log.rs ├── main.rs ├── print.rs ├── select.rs └── time.rs /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "rustix-vcs" 7 | version = "0.1.0" 8 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rustix-vcs" 3 | version = "0.1.0" 4 | edition = "2021" 5 | description = "Version Control System" 6 | documentation = "https://github.com/nkr413/rustix-vcs#readme" 7 | repository = "https://github.com/nkr413/rustix-vcs" 8 | 9 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 10 | 11 | [profile.release] 12 | opt-level = "z" 13 | panic = "abort" 14 | strip = true 15 | debug = false 16 | debug-assertions = false 17 | lto = false 18 | incremental = false -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | # rustix-vcs 2 | 3 | ![rustix visual](https://github.com/knoxydev/rustix-vcs/blob/main/docs/pics/rustix-visual-1.png) 4 | 5 | ## Compiling 6 | 7 | First, you'll want to check out this repository 8 | 9 | ``` 10 | git clone https://github.com/rust-lang/cargo 11 | cd cargo 12 | ``` 13 | 14 | With `cargo` already installed, you can simply run: 15 | 16 | ``` 17 | cargo build --release 18 | ``` 19 | 20 | ## Installation 21 | 22 | You can download the .exe file or the source code on the [releases page](github.com/knoxydev/rustix-vcs/releases) 23 | 24 | ## Usage 25 | 26 | Don't forget to add to the PATH (environment) to use rustix-vcs from any folder 27 | 28 | ## Commands 29 | - ```rustix-vcs init``` - command to initialize the project 30 | - ```rustix-vcs add src/main.js save_name``` - command to save the file. 31 | - ```rustix-vcs delete save_name``` - command to delete the save. 32 | - ```rustix-vcs select save_name``` - command to insert saved content into a file. 33 | - ```rustix-vcs print``` - command to display all saves and info about project. 34 | - ```rustix-vcs info``` - command to view information about the initialized project. 35 | - ```rustix-vcs cmd``` - command to display all commands. 36 | - ```rustix-vcs log``` - command to view logs. 37 | 38 | -------------------------------------------------------------------------------- /docs/pics/rustix-visual-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/knoxydev/rustix-vcs/ed66815e3354dc7a30dc5d48f0231e20af7fd701/docs/pics/rustix-visual-1.png -------------------------------------------------------------------------------- /src/add_file.rs: -------------------------------------------------------------------------------- 1 | pub mod add_fn 2 | { 3 | // PACKAGES 4 | use std::fs; 5 | use std::io::Write; 6 | 7 | 8 | // COPY FILE'S CONTENT and CREATE SAVE 9 | fn create_save(unq_name: &String, file_path: &String) 10 | { 11 | fn copy_file(file_path: &String) -> String { return fs::read_to_string(file_path).expect("Should have been able to read the file"); } 12 | 13 | let file_name = format!("rustix/saves/{:02}.txt", unq_name); 14 | let data = copy_file(&file_path); 15 | let new_data = data.as_bytes(); 16 | 17 | let mut f = fs::File::create(file_name).expect("Unable to create file"); 18 | f.write_all(new_data).expect("Unable to write data"); 19 | } 20 | 21 | 22 | // START POINT 23 | pub fn start(file_path: &String, unq_name: &String) 24 | { 25 | let time_date : [String; 2] = crate::time::time_fn::start(); 26 | 27 | let save_info : [String; 4] = [ 28 | file_path.to_string(), 29 | unq_name.to_string(), 30 | time_date[0].to_string(), 31 | time_date[1].to_string()]; 32 | 33 | let create_copy = crate::database::add::start(save_info); 34 | if create_copy == true { 35 | create_save(&unq_name, &file_path); 36 | crate::log::logger::start("ADD ".to_string()); 37 | } else { 38 | println!(":("); 39 | crate::log::logger::start("ADD -> ERROR".to_string()); 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /src/database/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod get 2 | { 3 | // PACKAGES 4 | use std::fs::File; 5 | use std::io::{prelude::*, BufReader}; 6 | 7 | 8 | const STORAGE_PATH : &str = "rustix/storage.txt"; 9 | 10 | 11 | pub fn start() -> std::io::Result> 12 | { 13 | fn get_saves(x: String) -> [String; 4] 14 | { 15 | let mut elem_start_point : i64 = 0; 16 | let mut save_info : [String; 4] = ["".to_string(), "".to_string(), "".to_string(), "".to_string()]; 17 | 18 | for i in x.chars() 19 | { 20 | if i == '|' { elem_start_point += 1; } 21 | if elem_start_point == 1 { save_info[0].push(i); } 22 | if elem_start_point == 2 { save_info[1].push(i); } 23 | if elem_start_point == 3 { save_info[2].push(i); } 24 | if elem_start_point == 4 { save_info[3].push(i); } 25 | } 26 | for i in save_info.iter_mut() { i.remove(0); } 27 | 28 | return save_info; 29 | } 30 | 31 | let file = File::open(STORAGE_PATH)?; 32 | let reader = BufReader::new(file); 33 | let mut saves_base = Vec::new(); 34 | 35 | for line in reader.lines() { saves_base.push(get_saves(line?)); } 36 | 37 | Ok(saves_base) 38 | } 39 | } 40 | 41 | 42 | pub mod add 43 | { 44 | // PACKAGES 45 | use std::path::Path; 46 | use std::io::prelude::*; 47 | use std::fs::OpenOptions; 48 | 49 | 50 | const STORAGE_PATH : &str = "rustix/storage.txt"; 51 | 52 | 53 | fn write_file(save_info: [String; 4]) -> bool 54 | { 55 | let saves_base = crate::database::get::start().unwrap(); 56 | let mut unique_save : bool = true; 57 | 58 | for i in saves_base { if i[1] == save_info[1] { unique_save = false; } } 59 | 60 | if unique_save == true { 61 | let res = format!("|{}|{}|{}|{}|", save_info[0], save_info[1], save_info[2], save_info[3]); 62 | let mut file = OpenOptions::new().write(true).append(true).open(STORAGE_PATH).unwrap(); 63 | writeln!(file, "{}", res); 64 | 65 | println!("Added !"); 66 | } else { println!("Such a name already exists !"); } 67 | 68 | return unique_save; 69 | } 70 | 71 | 72 | // START POINT 73 | pub fn start(save_info: [String; 4]) -> bool 74 | { if Path::new(STORAGE_PATH).exists() == true { return write_file(save_info); } else { return false; } } 75 | } 76 | 77 | 78 | pub mod del 79 | { 80 | // PACKAGES 81 | use std::fs; 82 | use std::io::prelude::*; 83 | use std::fs::OpenOptions; 84 | 85 | 86 | const STORAGE_PATH : &str = "rustix/storage.txt"; 87 | 88 | 89 | fn checking(mut base: Vec<[String; 4]>, save_name: String) 90 | { 91 | let mut exist_save : bool = false; 92 | let mut save_id : usize = 0; 93 | 94 | for (i, el) in base.iter().enumerate() { 95 | if el[1] == save_name { exist_save = true; save_id = i; break; } 96 | } 97 | 98 | if exist_save == true 99 | { 100 | base.remove(save_id); 101 | 102 | { // BLOCK FOR DELETE SAVE FILE 103 | let save_path = format!("rustix/saves/{:02}.txt", save_name); 104 | 105 | match fs::remove_file(save_path) { 106 | Err(error) => println!("{:?}", error.kind()), 107 | Ok(_) => { 108 | println!("The save was successfully deleted !"); 109 | crate::log::logger::start("DELETE".to_string()); 110 | } 111 | } 112 | } 113 | 114 | // CODE FOR MAKE STORAGE.TXT EMPTY 115 | OpenOptions::new().write(true).truncate(true).open(STORAGE_PATH); 116 | 117 | { // BLOCK FOR ADD NEW INFO ABOUT SAVES IN STORAGE.TXT 118 | let mut file = OpenOptions::new().write(true).append(false).open(STORAGE_PATH).unwrap(); 119 | 120 | for i in base { 121 | let res = format!("|{}|{}|{}|{}|", i[0], i[1], i[2], i[3]); 122 | writeln!(file, "{}", res); 123 | } 124 | } 125 | } else { 126 | println!("Error when deleting. Something went wrong :("); 127 | crate::log::logger::start("DELETE -> ERROR".to_string()); 128 | } 129 | } 130 | 131 | 132 | // START POINT 133 | pub fn start(save_name: String) 134 | { checking(crate::database::get::start().unwrap(), save_name); } 135 | } 136 | 137 | 138 | pub mod slc 139 | { 140 | // PACKAGES 141 | use std::fs; 142 | use std::io::Write; 143 | 144 | pub fn write_content(file_path: &String, file_name: &String) 145 | { 146 | let new_file_name = format!("rustix/saves/{:02}.txt", file_name); 147 | match fs::read_to_string(new_file_name) { 148 | Err(error) => println!("{:?}", error.kind()), 149 | Ok(x) => { 150 | let mut f = fs::File::create(file_path).expect("Unable to create file"); 151 | f.write_all(x.as_bytes()).expect("Unable to write data"); 152 | 153 | println!("To a file {:?} moved saving {:?}", file_path, file_name); 154 | }, 155 | } 156 | } 157 | 158 | 159 | pub fn start(save_name: &String) -> (bool, String) 160 | { 161 | let saves_base = crate::database::get::start().unwrap(); 162 | let mut save_info : (bool, String) = (false, "".to_string()); 163 | 164 | for i in saves_base { 165 | if i[1] == *save_name { 166 | save_info.0 = true; 167 | save_info.1 = i[0].to_string(); 168 | } 169 | } 170 | 171 | return save_info; 172 | } 173 | } -------------------------------------------------------------------------------- /src/delete.rs: -------------------------------------------------------------------------------- 1 | pub mod delete_fn 2 | { 3 | // START POINT 4 | pub fn start(save_name: String) { crate::database::del::start(save_name); } 5 | } -------------------------------------------------------------------------------- /src/initialize.rs: -------------------------------------------------------------------------------- 1 | pub mod init_fn 2 | { 3 | // PACKAGES 4 | use std::env; 5 | use std::fs; 6 | 7 | 8 | fn create_yaml() 9 | { 10 | let time_date: [String; 2] = crate::time::time_fn::start(); 11 | 12 | let cwd = env::current_dir().unwrap(); 13 | let folder: String = String::from(cwd.to_string_lossy()); 14 | let os_name = String::from(env::consts::OS); 15 | let created_date = &time_date[0]; 16 | let created_time = &time_date[1]; 17 | 18 | let info = format!("name: {folder}\nos_name: {os_name}\ncreated_date: {created_date}\ncreated_time: {created_time}"); 19 | 20 | fs::write("rustix/init.txt", info).expect("Unable to write file"); 21 | 22 | println!("Initialized !"); 23 | } 24 | 25 | 26 | // START POINT 27 | pub fn start() { 28 | match fs::create_dir("rustix") { 29 | Err(why) => { 30 | println!("{:?} !", why.kind()); 31 | crate::log::logger::start("INIT -> ERROR".to_string()); 32 | } 33 | Ok(_) => { 34 | fs::File::create("rustix/log.txt"); 35 | fs::File::create("rustix/init.txt"); 36 | fs::File::create("rustix/storage.txt"); 37 | fs::create_dir("rustix/saves"); 38 | create_yaml(); 39 | 40 | crate::log::logger::start("INIT ".to_string()); 41 | }, 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /src/log.rs: -------------------------------------------------------------------------------- 1 | pub mod logger 2 | { 3 | use std::fs::OpenOptions; 4 | use std::io::prelude::*; 5 | 6 | 7 | pub fn start(action: String) 8 | { 9 | let time_date: [String; 2] = crate::time::time_fn::start(); 10 | 11 | let created_date = &time_date[0]; 12 | let created_time = &time_date[1]; 13 | 14 | let info = format!("{} | {} - {}", action, created_date, created_time); 15 | 16 | let mut file = OpenOptions::new().write(true).append(true) 17 | .open("rustix/log.txt").unwrap(); 18 | 19 | if let Err(e) = writeln!(file, "{}", info) { println!("Couldn't write to file: {}", e); } 20 | } 21 | } -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | #![allow(warnings)] 2 | 3 | // PACKAGES 4 | use std::io; 5 | 6 | // MODULES 7 | mod initialize; 8 | pub use crate::initialize::init_fn; 9 | 10 | mod add_file; 11 | pub use crate::add_file::add_fn; 12 | 13 | mod delete; 14 | pub use crate::delete::delete_fn; 15 | 16 | mod select; 17 | pub use crate::select::select_fn; 18 | 19 | mod print; 20 | pub use crate::print::print_fn; 21 | 22 | mod log; 23 | 24 | mod time; 25 | 26 | mod database; 27 | // MODULES 28 | 29 | 30 | fn main() { 31 | { 32 | let args: Vec<_> = std::env::args().collect(); 33 | 34 | if args.len() == 1 { 35 | println!("You should enter arguments to use the program.\n"); 36 | 37 | print_fn::print_commands(); 38 | 39 | io::stdin().read_line(&mut String::new()).unwrap(); 40 | return; 41 | } 42 | } 43 | 44 | let first_arg = std::env::args().nth(1).expect("no pattern given"); 45 | 46 | match first_arg.as_ref() { 47 | "init" => init_fn::start(), 48 | "add" => { 49 | let args: Vec<_> = std::env::args().collect(); 50 | 51 | if args.len() > 3 { 52 | let scd_arg = std::env::args().nth(2).expect("no pattern given"); 53 | let thd_arg = std::env::args().nth(3).expect("no pattern given"); 54 | 55 | let fl_exist = std::path::Path::new(&scd_arg).exists(); 56 | 57 | if fl_exist == true { add_fn::start(&scd_arg, &thd_arg); } 58 | else { println!("not exist"); } 59 | } 60 | else 61 | { println!("where is third argument ?"); } 62 | }, 63 | "delete" => { 64 | let scd_arg = std::env::args().nth(2).expect("no pattern given"); 65 | delete_fn::start(scd_arg); 66 | }, 67 | "select" => { 68 | let scd_arg = std::env::args().nth(2).expect("no pattern given"); 69 | select_fn::start(scd_arg); 70 | }, 71 | "print" => print_fn::start(0), 72 | "log" => print_fn::start(1), 73 | "info" => print_fn::read_yaml(), 74 | "cmd" => print_fn::print_commands(), 75 | "exit" => return, 76 | _ => { 77 | println!("Incorrect command !"); 78 | return; 79 | }, 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /src/print.rs: -------------------------------------------------------------------------------- 1 | pub mod print_fn 2 | { 3 | // PACKAGES 4 | use std::fs; 5 | use std::fs::File; 6 | use std::io::{prelude::*, BufReader}; 7 | 8 | 9 | pub fn print_commands() { 10 | println!("Commands:\n"); 11 | println!("rustix-vcs init\n command to initialize the project\n"); 12 | println!("rustix-vcs add src/main.js save_name\n command to save the file.\n"); 13 | println!("rustix-vcs delete save_name\n command to delete the save.\n"); 14 | println!("rustix-vcs select save_name\n command to insert saved content into a file.\n"); 15 | println!("rustix-vcs print\n command to display all saves and info about project.\n"); 16 | println!("rustix-vcs info\n command to view information about the initialized project.\n"); 17 | println!("rustix-vcs cmd\n command to display all commands.\n"); 18 | println!("rustix-vcs log\n command to view logs.\n"); 19 | } 20 | 21 | 22 | fn show_log() -> std::io::Result<()> { 23 | let file = fs::File::open("rustix/log.txt")?; 24 | let reader = BufReader::new(file); 25 | for line in reader.lines() { println!("{}", line?); } 26 | 27 | Ok(()) 28 | } 29 | 30 | 31 | pub fn read_yaml() { 32 | fn cut_data(x: String) -> String 33 | { 34 | let mut elem_start_point : i64 = 0; 35 | let mut s = String::new(); 36 | 37 | for i in x.chars() { 38 | if i == ':' { elem_start_point += 1; } 39 | if elem_start_point >= 1 { s.push(i); } 40 | } 41 | 42 | s.remove(0); 43 | s.remove(0); 44 | 45 | return s; 46 | } 47 | 48 | fn get_data() -> std::io::Result> 49 | { 50 | let file = File::open("rustix/init.txt")?; 51 | let reader = BufReader::new(file); 52 | let mut info_base = Vec::new(); 53 | 54 | for line in reader.lines() { info_base.push(cut_data(line.unwrap())); } 55 | 56 | Ok(info_base) 57 | } 58 | 59 | let info : Vec = get_data().unwrap(); 60 | 61 | println!("\nINFO\n os: {}\n created date: {} - {}\n current path: {}\n\n", 62 | info[1], info[3], info[2], info[0]); 63 | } 64 | 65 | 66 | fn print_db() { 67 | let saves_base = crate::database::get::start().unwrap(); 68 | let mut id : i64 = 1; 69 | 70 | for x in saves_base.into_iter() { 71 | println!("{}. {}\n - path\n {}\n - saved\n {}\n {}\n", 72 | id, x[1], x[0], x[2], x[3]); 73 | 74 | id += 1; 75 | } 76 | } 77 | 78 | 79 | // START POINT 80 | pub fn start(x: i64) { 81 | if x == 1 { show_log(); } 82 | else { 83 | crate::log::logger::start("PRINT ".to_string()); 84 | read_yaml(); 85 | print_db(); 86 | } 87 | } 88 | } -------------------------------------------------------------------------------- /src/select.rs: -------------------------------------------------------------------------------- 1 | pub mod select_fn 2 | { 3 | // START POINT 4 | pub fn start(save_name: String) 5 | { 6 | let save_info : (bool, String) = crate::database::slc::start(&save_name); 7 | 8 | if save_info.0 == true { 9 | crate::database::slc::write_content(&save_info.1, &save_name); 10 | crate::log::logger::start("SELECT".to_string()); 11 | } else { 12 | println!("there is no save with this name !"); 13 | crate::log::logger::start("SELECT -> ERROR".to_string()); 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /src/time.rs: -------------------------------------------------------------------------------- 1 | pub mod time_fn 2 | { 3 | // PACKAGES 4 | use std::process::Command; 5 | 6 | 7 | fn del_newline(s: &mut String) 8 | { 9 | if s.ends_with('\n') || s.ends_with('\r') { s.pop(); 10 | if s.ends_with('\r') || s.ends_with('\n') { s.pop(); 11 | if s.ends_with(' ') { s.pop(); } } } 12 | } 13 | 14 | 15 | fn get_date() -> String 16 | { 17 | let foo = if cfg!(target_os = "windows") { 18 | Command::new("cmd") 19 | .args(["/C", "DATE /t"]) 20 | .output().expect("failed to execute process") 21 | } else { 22 | Command::new("sh") 23 | .args(["-c", "date +'%e.%m.%Y'"]) 24 | .output().expect("failed to execute process") 25 | }; 26 | 27 | let mut new_str = String::from_utf8(foo.stdout.clone()).unwrap(); 28 | 29 | del_newline(&mut new_str); 30 | 31 | new_str 32 | } 33 | 34 | 35 | fn get_time() -> String 36 | { 37 | let foo = if cfg!(target_os = "windows") { 38 | Command::new("cmd") 39 | .args(["/C", "TIME /t"]) 40 | .output().expect("failed to execute process") 41 | } else { 42 | Command::new("sh") 43 | .args(["-c", "date +'%H.%M.%S'"]) 44 | .output().expect("failed to execute process") 45 | }; 46 | 47 | let mut new_str = String::from_utf8(foo.stdout.clone()).unwrap(); 48 | 49 | del_newline(&mut new_str); 50 | 51 | new_str 52 | } 53 | 54 | pub fn start() -> [String; 2] { 55 | let res: [String; 2] = [get_date(), get_time()]; 56 | return res; 57 | } 58 | } --------------------------------------------------------------------------------