commit
ed89dccfa6
@ -1,28 +0,0 @@
|
|||||||
# Crystal Linux Contributing Guidelines
|
|
||||||
|
|
||||||
#### !! Always make sure to `git pull` before doing any work to avoid commit hell !!
|
|
||||||
|
|
||||||
### Pre-Commit Checks
|
|
||||||
|
|
||||||
- Make sure to `cargo fmt` your code before every commit push
|
|
||||||
- Unless in specific edge cases, don't push code that doesn't pass `cargo check`
|
|
||||||
- Try to correct any code with `cargo clippy` before you push
|
|
||||||
|
|
||||||
### Formatting
|
|
||||||
|
|
||||||
- UNIX line endings (LF instead of CRLF)
|
|
||||||
- 4 spaces per TAB
|
|
||||||
|
|
||||||
### Good Practices
|
|
||||||
|
|
||||||
- Try to use .unwrap() as little as possible
|
|
||||||
- Try to never use panic!() in production code, always try to have a possible way to resolve errors, even if it's just
|
|
||||||
unwrap_or/_else()
|
|
||||||
- Never use println!() or eprintln!() in finalised code. Using string functions (e.g. info() in Amethyst v3.0.0) is
|
|
||||||
preferred
|
|
||||||
- Compartmentalise as much as you can, avoid writing the exact same line of code 50 times if you can turn it into a
|
|
||||||
function
|
|
||||||
|
|
||||||
### Examples of these guidelines in practice
|
|
||||||
|
|
||||||
- https://git.getcryst.al/crystal/ame/src/branch/rewrite
|
|
@ -1,46 +1,89 @@
|
|||||||
{
|
{
|
||||||
inputs = {
|
inputs = {
|
||||||
nixpkgs.url = "github:nixos/nixpkgs";
|
nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable";
|
||||||
utils.url = "github:numtide/flake-utils";
|
utils.url = "github:numtide/flake-utils";
|
||||||
naersk.url = "github:nix-community/naersk";
|
naersk = {
|
||||||
|
url = "github:nix-community/naersk";
|
||||||
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
|
};
|
||||||
|
fenix = {
|
||||||
|
url = "github:nix-community/fenix";
|
||||||
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
outputs = { self, nixpkgs, utils, naersk }:
|
outputs = {
|
||||||
utils.lib.eachDefaultSystem (system:
|
self,
|
||||||
let
|
nixpkgs,
|
||||||
pkgs = nixpkgs.legacyPackages."${system}";
|
utils,
|
||||||
naersk-lib = naersk.lib."${system}";
|
naersk,
|
||||||
in rec
|
fenix,
|
||||||
{
|
}:
|
||||||
packages.amethyst = naersk-lib.buildPackage {
|
utils.lib.eachDefaultSystem (system: let
|
||||||
pname = "ame";
|
pkgs = nixpkgs.legacyPackages."${system}";
|
||||||
root = ./.;
|
toolchain = with fenix.packages."${system}";
|
||||||
nativeBuildInputs = with pkgs; [
|
combine [
|
||||||
openssl
|
minimal.rustc
|
||||||
sqlite
|
minimal.cargo
|
||||||
pkg-config
|
targets.x86_64-pc-windows-gnu.latest.rust-std
|
||||||
];
|
targets.x86_64-unknown-linux-gnu.latest.rust-std
|
||||||
};
|
];
|
||||||
|
naersk-lib = naersk.lib."${system}".override {
|
||||||
packages.default = packages.amethyst;
|
cargo = toolchain;
|
||||||
|
rustc = toolchain;
|
||||||
apps.amethyst = utils.lib.mkApp {
|
};
|
||||||
drv = packages.amethyst;
|
in rec
|
||||||
};
|
{
|
||||||
|
packages.amethyst = naersk-lib.buildPackage {
|
||||||
apps.default = apps.amethyst;
|
pname = "Amethyst";
|
||||||
|
root = ./.;
|
||||||
devShells.default = pkgs.mkShell {
|
};
|
||||||
nativeBuildInputs = with pkgs; [
|
|
||||||
rustc
|
packages.amethyst-win = naersk-lib.buildPackage {
|
||||||
cargo
|
pname = "Amethyst";
|
||||||
rustfmt
|
root = ./.;
|
||||||
cargo-audit
|
strictDeps = true;
|
||||||
clippy
|
depsBuildBuild = with pkgs; [
|
||||||
openssl
|
pkgsCross.mingwW64.stdenv.cc
|
||||||
sqlite
|
pkgsCross.mingwW64.windows.pthreads
|
||||||
pkg-config
|
];
|
||||||
];
|
nativeBuildInputs = with pkgs; [
|
||||||
};
|
(
|
||||||
});
|
if system == "x86_64-linux"
|
||||||
|
then wineWowPackages.stable
|
||||||
|
else hello
|
||||||
|
)
|
||||||
|
];
|
||||||
|
CARGO_BUILD_TARGET = "x86_64-pc-windows-gnu";
|
||||||
|
CARGO_TARGET_X86_64_PC_WINDOWS_GNU_RUNNER = pkgs.writeScript "wine-wrapper" ''
|
||||||
|
export WINEPREFIX="$(mktemp -d)"
|
||||||
|
exec wine64 $@
|
||||||
|
'';
|
||||||
|
doCheck = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
packages.default = packages.amethyst;
|
||||||
|
|
||||||
|
apps.apod = utils.lib.mkApp {
|
||||||
|
drv = packages.amethyst;
|
||||||
|
};
|
||||||
|
|
||||||
|
apps.default = apps.amethyst;
|
||||||
|
|
||||||
|
devShells.default = pkgs.mkShell {
|
||||||
|
nativeBuildInputs = with pkgs; [
|
||||||
|
rustc
|
||||||
|
cargo
|
||||||
|
cargo-audit
|
||||||
|
rustfmt
|
||||||
|
clippy
|
||||||
|
|
||||||
|
openssl
|
||||||
|
sqlite
|
||||||
|
pkg-config
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
formatter = pkgs.alejandra;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
@ -1,21 +0,0 @@
|
|||||||
use crate::internal::exit_code::AppExitCode;
|
|
||||||
use crate::internal::rpc::Package;
|
|
||||||
use crate::{crash, log, Options};
|
|
||||||
|
|
||||||
use super::get_database_connection;
|
|
||||||
|
|
||||||
pub fn add(pkg: Package, options: Options) {
|
|
||||||
let conn = get_database_connection();
|
|
||||||
|
|
||||||
if options.verbosity >= 1 {
|
|
||||||
log!("Adding package {} to database", pkg.name);
|
|
||||||
}
|
|
||||||
let pkg_description = pkg
|
|
||||||
.description
|
|
||||||
.unwrap_or_else(|| "No description found.".parse().unwrap());
|
|
||||||
conn.execute("INSERT OR REPLACE INTO packages (name, version, description, depends, make_depends) VALUES (?1, ?2, ?3, ?4, ?5)",
|
|
||||||
[&pkg.name, &pkg.version, &pkg_description, &pkg.depends.join(" "), &pkg.make_depends.join(" ")],
|
|
||||||
).unwrap_or_else(|e|
|
|
||||||
crash!(AppExitCode::FailedAddingPkg, "Failed adding package {} to the database: {}", pkg.name, e)
|
|
||||||
);
|
|
||||||
}
|
|
@ -1,41 +0,0 @@
|
|||||||
use rusqlite::Connection;
|
|
||||||
use std::env;
|
|
||||||
use std::path::Path;
|
|
||||||
|
|
||||||
use crate::internal::exit_code::AppExitCode;
|
|
||||||
use crate::{crash, log, Options};
|
|
||||||
|
|
||||||
pub fn init(options: Options) {
|
|
||||||
let path = format!("{}/.local/share/ame/db.sqlite", env::var("HOME").unwrap());
|
|
||||||
let dbpath = Path::new(&path);
|
|
||||||
let verbosity = options.verbosity;
|
|
||||||
|
|
||||||
if verbosity >= 1 {
|
|
||||||
log!("Creating database at {}", &path);
|
|
||||||
}
|
|
||||||
|
|
||||||
let conn =
|
|
||||||
Connection::open(dbpath).expect("Couldn't create database at ~/.local/share/ame/db.sqlite");
|
|
||||||
|
|
||||||
if verbosity >= 1 {
|
|
||||||
log!("Populating database with table");
|
|
||||||
}
|
|
||||||
|
|
||||||
conn.execute(
|
|
||||||
"CREATE TABLE packages (
|
|
||||||
name TEXT PRIMARY KEY NOT NULL,
|
|
||||||
version TEXT NOT NULL,
|
|
||||||
description TEXT,
|
|
||||||
depends BLOB,
|
|
||||||
make_depends BLOB
|
|
||||||
)",
|
|
||||||
[],
|
|
||||||
)
|
|
||||||
.unwrap_or_else(|e| {
|
|
||||||
crash!(
|
|
||||||
AppExitCode::FailedInitDb,
|
|
||||||
"Couldn't initialise database: {}",
|
|
||||||
e,
|
|
||||||
)
|
|
||||||
});
|
|
||||||
}
|
|
@ -1,17 +0,0 @@
|
|||||||
use std::{env, path::PathBuf};
|
|
||||||
|
|
||||||
pub mod add;
|
|
||||||
pub mod initialise;
|
|
||||||
pub mod query;
|
|
||||||
pub mod remove;
|
|
||||||
|
|
||||||
pub use add::*;
|
|
||||||
pub use initialise::*;
|
|
||||||
pub use query::*;
|
|
||||||
pub use remove::*;
|
|
||||||
use rusqlite::Connection;
|
|
||||||
|
|
||||||
fn get_database_connection() -> Connection {
|
|
||||||
let db_path = format!("{}/.local/share/ame/db.sqlite", env::var("HOME").unwrap());
|
|
||||||
Connection::open(PathBuf::from(db_path)).expect("Couldn't connect to database")
|
|
||||||
}
|
|
@ -1,63 +0,0 @@
|
|||||||
use rusqlite::Connection;
|
|
||||||
use std::env;
|
|
||||||
use std::path::Path;
|
|
||||||
|
|
||||||
use crate::internal::rpc::Package;
|
|
||||||
use crate::{log, Options};
|
|
||||||
|
|
||||||
pub fn query(options: Options) -> Vec<Package> {
|
|
||||||
let verbosity = options.verbosity;
|
|
||||||
|
|
||||||
if verbosity >= 1 {
|
|
||||||
log!("Connecting to database");
|
|
||||||
}
|
|
||||||
|
|
||||||
let conn = Connection::open(Path::new(&format!(
|
|
||||||
"{}/.local/share/ame/db.sqlite",
|
|
||||||
env::var("HOME").unwrap()
|
|
||||||
)))
|
|
||||||
.expect("Couldn't connect to database");
|
|
||||||
|
|
||||||
if verbosity >= 1 {
|
|
||||||
log!("Querying database for input");
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut rs = conn.prepare("SELECT * FROM packages;").unwrap();
|
|
||||||
let packages_iter = rs
|
|
||||||
.query_map([], |row| {
|
|
||||||
Ok(Package {
|
|
||||||
name: row.get(0).unwrap(),
|
|
||||||
version: row.get(1).unwrap(),
|
|
||||||
description: row.get(2).unwrap(),
|
|
||||||
depends: row
|
|
||||||
.get::<usize, String>(3)
|
|
||||||
.unwrap()
|
|
||||||
.split(' ')
|
|
||||||
.map(|s| s.to_string())
|
|
||||||
.collect::<Vec<String>>(),
|
|
||||||
make_depends: row
|
|
||||||
.get::<usize, String>(4)
|
|
||||||
.unwrap()
|
|
||||||
.split(' ')
|
|
||||||
.map(|s| s.to_string())
|
|
||||||
.collect::<Vec<String>>(),
|
|
||||||
})
|
|
||||||
})
|
|
||||||
.expect("Couldn't query database for packages");
|
|
||||||
|
|
||||||
if verbosity >= 1 {
|
|
||||||
log!("Retrieved results");
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut results: Vec<Package> = vec![];
|
|
||||||
|
|
||||||
for package in packages_iter {
|
|
||||||
results.push(package.unwrap());
|
|
||||||
}
|
|
||||||
|
|
||||||
if verbosity >= 1 {
|
|
||||||
log!("Collected results");
|
|
||||||
}
|
|
||||||
|
|
||||||
results
|
|
||||||
}
|
|
@ -1,23 +0,0 @@
|
|||||||
use crate::{log, Options};
|
|
||||||
|
|
||||||
use super::get_database_connection;
|
|
||||||
|
|
||||||
pub fn remove(pkg: &str, options: Options) {
|
|
||||||
let conn = get_database_connection();
|
|
||||||
|
|
||||||
let verbosity = options.verbosity;
|
|
||||||
|
|
||||||
if verbosity >= 1 {
|
|
||||||
log!("Removing package {} from database", pkg);
|
|
||||||
}
|
|
||||||
|
|
||||||
conn.execute(
|
|
||||||
"DELETE FROM packages
|
|
||||||
WHERE EXISTS
|
|
||||||
(SELECT *
|
|
||||||
FROM packages
|
|
||||||
WHERE name = ?);",
|
|
||||||
[pkg],
|
|
||||||
)
|
|
||||||
.expect("Couldn't delete package from database");
|
|
||||||
}
|
|
@ -1,12 +1,10 @@
|
|||||||
pub enum AppExitCode {
|
pub enum AppExitCode {
|
||||||
RunAsRoot = 1,
|
RunAsRoot = 1,
|
||||||
FailedAddingPkg = 2,
|
FailedCreatingPaths = 2,
|
||||||
FailedInitDb = 3,
|
MissingDeps = 3,
|
||||||
FailedCreatingPaths = 4,
|
UserCancellation = 4,
|
||||||
MissingDeps = 5,
|
PacmanError = 5,
|
||||||
UserCancellation = 6,
|
GitError = 6,
|
||||||
PacmanError = 7,
|
MakePkgError = 7,
|
||||||
GitError = 8,
|
Other = 63,
|
||||||
MakePkgError = 9,
|
|
||||||
Other = 102,
|
|
||||||
}
|
}
|
||||||
|
@ -1,129 +1,62 @@
|
|||||||
use std::env;
|
use std::env;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::process::Command;
|
|
||||||
|
|
||||||
use crate::{crash, internal::exit_code::AppExitCode, log, Options};
|
use crate::{crash, internal::exit_code::AppExitCode, log, Options};
|
||||||
|
|
||||||
pub fn init(options: Options) {
|
pub fn init(options: Options) {
|
||||||
|
// Initialise variables
|
||||||
let verbosity = options.verbosity;
|
let verbosity = options.verbosity;
|
||||||
let homedir = env::var("HOME").unwrap();
|
let homedir = env::var("HOME").unwrap();
|
||||||
|
|
||||||
|
// Initialise stateful directory
|
||||||
if !Path::new(&format!("{}/.local/share/ame", homedir)).exists() {
|
if !Path::new(&format!("{}/.local/share/ame", homedir)).exists() {
|
||||||
let r = std::fs::create_dir_all(format!("{}/.local/share/ame", homedir));
|
if verbosity >= 1 {
|
||||||
match r {
|
log!("Initialising stateful directory");
|
||||||
Ok(_) => {
|
|
||||||
if verbosity >= 1 {
|
|
||||||
log!("Created path: {}/.local/share/ame", homedir);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
crash!(
|
|
||||||
AppExitCode::FailedCreatingPaths,
|
|
||||||
"Couldn't create path: {}/.local/share/ame: {}",
|
|
||||||
homedir,
|
|
||||||
e,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
std::fs::create_dir_all(format!("{}/.local/share/ame", homedir)).unwrap_or_else(|e| {
|
||||||
|
crash!(
|
||||||
|
AppExitCode::FailedCreatingPaths,
|
||||||
|
"Failed to create stateful directory: {}",
|
||||||
|
e
|
||||||
|
);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if !Path::new(&format!("{}/.local/share/ame/db.sqlite", homedir)).exists() {
|
// If cache path doesn't exist, create it, if it does, delete it and recreate it
|
||||||
crate::database::init(options);
|
|
||||||
}
|
|
||||||
|
|
||||||
if !Path::new(&format!("{}/.cache/ame/", homedir)).exists() {
|
if !Path::new(&format!("{}/.cache/ame/", homedir)).exists() {
|
||||||
let r = std::fs::create_dir_all(format!("{}/.cache/ame", homedir));
|
if verbosity >= 1 {
|
||||||
match r {
|
log!("Initialising cache directory");
|
||||||
Ok(_) => {
|
|
||||||
if verbosity >= 1 {
|
|
||||||
log!("Created path: {}/.cache/ame", homedir);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
crash!(
|
|
||||||
AppExitCode::FailedCreatingPaths,
|
|
||||||
"Couldn't create path: {}/.cache/ame: {}",
|
|
||||||
homedir,
|
|
||||||
e,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
std::fs::create_dir_all(format!("{}/.cache/ame", homedir)).unwrap_or_else(|e| {
|
||||||
let r = std::fs::remove_dir_all(format!("{}/.cache/ame", homedir));
|
|
||||||
match r {
|
|
||||||
Ok(_) => {
|
|
||||||
if verbosity >= 1 {
|
|
||||||
log!("Removing cache: {}/.cache/ame", homedir);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
crash!(
|
|
||||||
AppExitCode::FailedCreatingPaths,
|
|
||||||
"Couldn't remove path: {}/.cache/ame: {}",
|
|
||||||
homedir,
|
|
||||||
e,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let r2 = std::fs::create_dir_all(format!("{}/.cache/ame", homedir));
|
|
||||||
match r2 {
|
|
||||||
Ok(_) => {
|
|
||||||
if verbosity >= 1 {
|
|
||||||
log!("Created path: {}/.cache/ame", homedir);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(e2) => {
|
|
||||||
crash!(
|
|
||||||
AppExitCode::FailedCreatingPaths,
|
|
||||||
"Couldn't create path: {}/.cache/ame: {}",
|
|
||||||
homedir,
|
|
||||||
e2,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let r = Command::new("chmod")
|
|
||||||
.arg("-R")
|
|
||||||
.arg("770")
|
|
||||||
.arg(format!("{}/.cache/ame", homedir))
|
|
||||||
.status();
|
|
||||||
match r {
|
|
||||||
Ok(_) => {
|
|
||||||
if verbosity >= 1 {
|
|
||||||
log!("Set correct permissions for path: {}/.cache/ame", homedir);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
crash!(
|
crash!(
|
||||||
AppExitCode::FailedCreatingPaths,
|
AppExitCode::FailedCreatingPaths,
|
||||||
"Couldn't set permissions for path: {}/.cache/ame: {}",
|
"Couldn't create path: {}/.cache/ame: {}",
|
||||||
homedir,
|
homedir,
|
||||||
e,
|
e,
|
||||||
);
|
);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
if verbosity >= 1 {
|
||||||
|
log!("Deleting cache directory");
|
||||||
}
|
}
|
||||||
};
|
rm_rf::remove(format!("{}/.cache/ame", homedir)).unwrap_or_else(|e| {
|
||||||
let r = Command::new("chmod")
|
|
||||||
.arg("-R")
|
|
||||||
.arg("770")
|
|
||||||
.arg(format!("{}/.local/share/ame", homedir))
|
|
||||||
.status();
|
|
||||||
match r {
|
|
||||||
Ok(_) => {
|
|
||||||
if verbosity >= 1 {
|
|
||||||
log!(
|
|
||||||
"Set correct permissions for path: {}/.local/share/ame",
|
|
||||||
homedir
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(e) => {
|
|
||||||
crash!(
|
crash!(
|
||||||
AppExitCode::FailedCreatingPaths,
|
AppExitCode::FailedCreatingPaths,
|
||||||
"Couldn't set permissions for path: {}/.local/share/ame: {}",
|
"Couldn't remove path: {}/.cache/ame: {}",
|
||||||
homedir,
|
homedir,
|
||||||
e,
|
e
|
||||||
);
|
)
|
||||||
|
});
|
||||||
|
if verbosity >= 1 {
|
||||||
|
log!("Creating cache directory");
|
||||||
}
|
}
|
||||||
};
|
std::fs::create_dir_all(format!("{}/.cache/ame", homedir)).unwrap_or_else(|e| {
|
||||||
|
crash!(
|
||||||
|
AppExitCode::FailedCreatingPaths,
|
||||||
|
"Couldn't create path: {}/.cache/ame: {}",
|
||||||
|
homedir,
|
||||||
|
e
|
||||||
|
)
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue