Basic structure reworked

This commit is contained in:
Daniel_I_Am 2021-02-16 15:34:28 +01:00
parent 3e553e568b
commit 038b2160bc
No known key found for this signature in database
GPG Key ID: 80C428FCC9743E84
9 changed files with 168 additions and 183 deletions

1
.gitignore vendored
View File

@ -1,2 +1,3 @@
/target
/.idea
contents/packages

72
Cargo.lock generated
View File

@ -4,56 +4,68 @@
name = "aur-helper"
version = "0.1.0"
dependencies = [
"rustc-serialize",
"toml-config",
"serde",
"serde_derive",
"toml",
]
[[package]]
name = "cfg-if"
version = "0.1.10"
name = "proc-macro2"
version = "1.0.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
[[package]]
name = "log"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b"
checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71"
dependencies = [
"log 0.4.11",
"unicode-xid",
]
[[package]]
name = "log"
version = "0.4.11"
name = "quote"
version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4fabed175da42fed1fa0746b0ea71f412aa9d35e76e95e59b192c64b9dc2bf8b"
checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7"
dependencies = [
"cfg-if",
"proc-macro2",
]
[[package]]
name = "rustc-serialize"
version = "0.3.24"
name = "serde"
version = "1.0.123"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda"
checksum = "92d5161132722baa40d802cc70b15262b98258453e85e5d1d365c757c73869ae"
[[package]]
name = "serde_derive"
version = "1.0.123"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9391c295d64fc0abb2c556bad848f33cb8296276b1ad2677d1ae1ace4f258f31"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "syn"
version = "1.0.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c700597eca8a5a762beb35753ef6b94df201c81cca676604f547495a0d7f0081"
dependencies = [
"proc-macro2",
"quote",
"unicode-xid",
]
[[package]]
name = "toml"
version = "0.1.30"
version = "0.5.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0590d72182e50e879c4da3b11c6488dae18fccb1ae0c7a3eda18e16795844796"
checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa"
dependencies = [
"rustc-serialize",
"serde",
]
[[package]]
name = "toml-config"
version = "0.4.0"
name = "unicode-xid"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3de5e51a3b687866a2af93d043ff056f797b8c49e2d9d93376eeeaaf66682871"
dependencies = [
"log 0.3.9",
"rustc-serialize",
"toml",
]
checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"

View File

@ -7,5 +7,6 @@ edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
toml-config = "0.4.0"
rustc-serialize = "0.3.24"
toml = "0.5.8"
serde = "1.0.123"
serde_derive = "1.0.123"

6
aur_config.toml Normal file
View File

@ -0,0 +1,6 @@
packages_directory = "contents/packages"
[packages]
authy = "https://aur.archlinux.org/authy.git"
[pre_install_script]

0
contents/.gitkeep Normal file
View File

View File

@ -1,14 +0,0 @@
use std::env;
pub struct Args {
pub(crate) operation: Option<String>,
pub(crate) argument: Option<String>
}
pub fn get_argument_settings() -> Args {
let args: Vec<String> = env::args().collect();
Args {
operation: args.get(1).cloned(),
argument: args.get(2).cloned()
}
}

View File

@ -1,80 +0,0 @@
extern crate rustc_serialize;
extern crate toml_config;
use std::path::Path;
use toml_config::ConfigFactory;
use std::fs::{create_dir_all, OpenOptions};
use std::{env, io};
use std::io::{ErrorKind, Write};
#[derive(RustcEncodable, RustcDecodable)]
pub struct Config {
pub nested: NestedConfig
}
// Defaults will be used for missing/invalid configurations in the TOML config file
impl Default for Config {
fn default() -> Config {
Config {
nested: NestedConfig::default()
}
}
}
impl Config {
const PATH: &'static str = "config.toml";
fn serialize(&self) -> String {
format!("[nested]\ninstall_directory = \"{}\"\ninstalled_packages = [\"{}\"]", self.nested.install_directory, self.nested.installed_packages.to_owned().join("\",\""))
}
pub fn write(&self) -> Result<(), io::Error> {
let path_string = Config::PATH;
let path = Path::new(path_string);
if path.exists() && !path.is_file() {
Err(io::Error::new(ErrorKind::InvalidInput, format!("The given path is not a file: {}", path_string).as_str()))
} else {
let dir = path.parent().expect(format!("Config path does not have a parent directory: {}", path_string).as_str());
create_dir_all(dir).expect(format!("Could not create directory {}", dir.display()).as_str());
let mut config_buffer = OpenOptions::new()
.write(true)
.truncate(true)
.open(path)
.unwrap();
config_buffer.write_all(self.serialize().as_bytes()).expect(format!("Could not write to config file {}", path_string).as_str());
Ok(())
}
}
}
#[derive(RustcEncodable, RustcDecodable)]
pub struct NestedConfig {
pub install_directory: String,
pub installed_packages: Vec<String>
}
impl Default for NestedConfig {
fn default() -> NestedConfig {
NestedConfig {
install_directory: "~/.cache/aur-helper/packages".to_owned(),
installed_packages: Vec::new()
}
}
}
pub fn load_config() -> Config {
let cfg: Config = ConfigFactory::load(Path::new(Config::PATH));
let home_env = env::var("HOME").expect("Could not find HOME environment variable.");
let relative_home_dir = home_env.as_str();
let absolute_home_dir = cfg.nested.install_directory.replace("~", relative_home_dir);
let package_path = Path::new(absolute_home_dir.as_str());
create_dir_all(package_path).expect(format!("Could not create package directory {}", package_path.display()).as_str());
cfg.write().expect("Cannot write configuration to file");
cfg
}

View File

@ -1,47 +1,125 @@
use crate::argument_parser::get_argument_settings;
use crate::config_file_actions::Config;
use std::env::args;
use std::fs::{File, create_dir_all, remove_dir_all};
use std::io::Read;
use serde_derive::Deserialize;
use std::collections::HashMap;
use std::path::Path;
use std::process::Command;
mod config_file_actions;
mod argument_parser;
mod ops;
#[derive(Deserialize, Debug)]
struct Config {
packages_directory: Option<String>,
packages: Option<HashMap<String, String>>,
pre_install_script: Option<HashMap<String, String>>
}
// git --version >= 2.25.0
fn main() {
let args = get_argument_settings();
let config: Config = get_configuration();
let mut cfg: Config = config_file_actions::load_config();
println!("{}", cfg.nested.install_directory);
println!("{:?}", cfg.nested.installed_packages);
let packages_directory_path = &config.packages_directory.clone().unwrap();
let packages_directory = Path::new(packages_directory_path);
create_dir_all(packages_directory).unwrap();
if let Some(operation) = args.operation {
let argument = args.argument;
match operation.to_lowercase().as_str() {
"install" => {
require_argument(&argument);
ops::install(argument.unwrap());
},
"list" => {
ops::list_installed();
},
"update" => {
require_argument(&argument);
ops::update(argument.unwrap());
},
"remove" => {
require_argument(&argument);
ops::remove(argument.unwrap());
}
_ => {
ops::help();
}
for (package_name, url) in &config.packages.unwrap() {
let result = process_package(&config.packages_directory.clone().unwrap(), package_name, url);
if result.is_err() {
println!("Processing package '{}' threw an error: {}", package_name, result.err().unwrap())
}
} else {
ops::help();
}
}
fn require_argument(argument: &Option<String>) {
if argument.is_none() {
panic!("This option requires an additional argument.");
fn process_package(packages_path: &String, package_name: &String, url: &String) -> Result<(), String> {
println!("Processing package '{}' ({}) in directory {}", package_name, url, packages_path);
let folder_path = Path::new(packages_path).join(package_name);
let folder_exists = folder_path. exists();
let repo_exists = folder_path. join(".git") . exists();
if folder_exists && !repo_exists {
println!("Removing directory '{}' as it is not a valid git repository.", folder_path.clone().to_str().unwrap());
remove_dir_all(folder_path.clone()).unwrap();
}
if !folder_exists {
println!("Cloning package '{}' from '{}'.", package_name, url);
Command::new("git")
.arg("clone")
.arg(url)
.arg(folder_path.clone().to_str().unwrap())
.output()
.expect(&*format!("Could not clone '{}' to '{}'", url, package_name));
}
// let status_information = Command::new("git")
// .arg("-C")
// .arg(folder_path.clone().to_str().unwrap())
// .arg("status")
// .arg("--porcelain=v1")
// .output()
// .expect(&*format!("Could not get repository status for repository root at {}", folder_path.clone().to_str().unwrap()))
// .stdout;
Command::new("git")
.arg("-C")
.arg(folder_path.clone().to_str().unwrap())
.arg("clean")
.arg("-f")
.arg("-x")
.output()
.expect(&*format!("Could not clean repository for repository root at {}", folder_path.clone().to_str().unwrap()));
Command::new("git")
.arg("-C")
.arg(folder_path.clone().to_str().unwrap())
.arg("restore")
.arg(".")
.output()
.expect(&*format!("Could not clean repository for repository root at {}", folder_path.clone().to_str().unwrap()));
// for file_status in std::str::from_utf8(&*status_information).unwrap().split('\n').into_iter() {
// if file_status.len() < 3 {
// continue;
// }
//
// let status_code = file_status.chars().into_iter().take(2).collect::<String>();
// let status_path = file_status.chars().rev().into_iter().take(file_status.len() - 3).collect::<String>().chars().rev().collect::<String>();
//
// println!("{} {}", status_code, status_path);
//
//
// }
if !folder_path.join("PKGBUILD").is_file() {
return Err(format!("Package '{}' does not seem to have a PKGBUILD file, if this is a mistake, please delete/update the package manually.", package_name));
}
println!("This package does {}have a folder and does {}have a repository.", if folder_exists { "" } else { "not " }, if repo_exists { "" } else { "not " });
Ok(())
}
fn get_configuration_file_path() -> String {
args().nth(1).expect("Required parameter configuration file missing.")
}
fn get_configuration_file_contents() -> std::io::Result<String> {
let file_name = get_configuration_file_path();
let file = File::open(file_name)?;
let mut file_copy = file.try_clone()?;
let mut contents: Vec<u8> = vec![];
file_copy.read_to_end(&mut contents)?;
Ok(std::str::from_utf8(&*contents)
.expect("Found data in the configuration file that is not according to UTF8").to_string())
}
fn get_configuration() -> Config {
let configuration_contents = get_configuration_file_contents().unwrap();
let config: Config = toml::from_str(&*configuration_contents).unwrap();
config.packages_directory.clone().expect("Configuration does not contain string `packages_directory`.");
config.packages.clone().expect("Configuration does not contain array `packages`");
config
}

View File

@ -1,19 +0,0 @@
pub fn install(argument: String) {
println!("Argument: {}", argument);
}
pub fn list_installed() {
println!("Here's packages!");
}
pub fn update(argument: String) {
println!("Argument: {}", argument);
}
pub fn remove(argument: String) {
println!("Argument: {}", argument);
}
pub fn help() {
println!("Help!");
}