Merge branch 'master' of github.com:/MajorBarnulf/epitls-pi
This commit is contained in:
commit
37cad03cf3
6 changed files with 84 additions and 21 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -138,7 +138,7 @@ checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "epitls-pi"
|
name = "epitls-pi"
|
||||||
version = "1.2.1"
|
version = "1.3.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"chrono",
|
"chrono",
|
||||||
"clap",
|
"clap",
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "epitls-pi"
|
name = "epitls-pi"
|
||||||
version = "1.2.1"
|
version = "1.3.1"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license = "GPL-3.0+"
|
license = "GPL-3.0+"
|
||||||
description = "A little helper tool meant to ease the developpment of the C piscine at EPITA/Toulouse."
|
description = "A little helper tool meant to ease the developpment of the C piscine at EPITA/Toulouse."
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
use std::{
|
use std::{
|
||||||
env, fs,
|
env, fs,
|
||||||
|
io::stdin,
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
};
|
};
|
||||||
|
|
||||||
use ron::ser::PrettyConfig;
|
use ron::ser::PrettyConfig;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::utils::{log_success, Apply};
|
use crate::utils::{log_process, log_success, Apply};
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
|
@ -23,7 +24,7 @@ impl Config {
|
||||||
Self {
|
Self {
|
||||||
identifier,
|
identifier,
|
||||||
main_file: "main.c".into(),
|
main_file: "main.c".into(),
|
||||||
test_file: "test.c".into(),
|
test_file: "test.ctest".into(),
|
||||||
includes: vec![],
|
includes: vec![],
|
||||||
strict_mode: false,
|
strict_mode: false,
|
||||||
}
|
}
|
||||||
|
@ -33,6 +34,11 @@ impl Config {
|
||||||
path.extend([Self::CONFIG_FILE_NAME]);
|
path.extend([Self::CONFIG_FILE_NAME]);
|
||||||
let content =
|
let content =
|
||||||
ron::ser::to_string_pretty(self, PrettyConfig::default().struct_names(true)).unwrap();
|
ron::ser::to_string_pretty(self, PrettyConfig::default().struct_names(true)).unwrap();
|
||||||
|
if path.exists() {
|
||||||
|
log_process("config already exists, overwrite it?");
|
||||||
|
let mut buff = String::new();
|
||||||
|
stdin().read_line(&mut buff).unwrap();
|
||||||
|
}
|
||||||
fs::write(path, content).unwrap();
|
fs::write(path, content).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,11 +53,21 @@ impl Config {
|
||||||
.unwrap_or_else(|| Self::new(path.file_name().unwrap().to_str().unwrap().to_string()))
|
.unwrap_or_else(|| Self::new(path.file_name().unwrap().to_str().unwrap().to_string()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_local_path() -> Option<PathBuf> {
|
||||||
|
let path = env::current_dir().unwrap();
|
||||||
|
Self::get_path(&path)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get(path: &Path) -> Option<Self> {
|
pub fn get(path: &Path) -> Option<Self> {
|
||||||
let path = path.to_path_buf().canonicalize().unwrap();
|
let path = path.to_path_buf().canonicalize().unwrap();
|
||||||
Self::try_get(&path).or_else(|| path.parent().and_then(Self::get))
|
Self::try_get(&path).or_else(|| path.parent().and_then(Self::get))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_path(path: &Path) -> Option<PathBuf> {
|
||||||
|
let path = path.to_path_buf().canonicalize().unwrap();
|
||||||
|
Self::try_get_path(&path).or_else(|| path.parent().and_then(Self::get_path))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn identifier(&self) -> &str {
|
pub fn identifier(&self) -> &str {
|
||||||
&self.identifier
|
&self.identifier
|
||||||
}
|
}
|
||||||
|
@ -78,6 +94,15 @@ impl Config {
|
||||||
.ok()
|
.ok()
|
||||||
.and_then(|content| ron::from_str(&content).ok())
|
.and_then(|content| ron::from_str(&content).ok())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn try_get_path(path: &Path) -> Option<PathBuf> {
|
||||||
|
let path = path.to_path_buf().apply(|p| p.push(Self::CONFIG_FILE_NAME));
|
||||||
|
fs::read_to_string(&path)
|
||||||
|
.ok()
|
||||||
|
.and_then(|content| ron::from_str::<Self>(&content).ok())
|
||||||
|
.is_some()
|
||||||
|
.then_some(path)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create(path: String, identifier: String) {
|
pub fn create(path: String, identifier: String) {
|
||||||
|
@ -94,3 +119,17 @@ pub fn create(path: String, identifier: String) {
|
||||||
.to_string();
|
.to_string();
|
||||||
log_success(&format!("created '{path}'"));
|
log_success(&format!("created '{path}'"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn create_test(mut path: String) {
|
||||||
|
const DEFAULT_CONTENT: &str = r#"
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
void test_it_works() {
|
||||||
|
assert( (2 + 2) == (4) );
|
||||||
|
}
|
||||||
|
"#;
|
||||||
|
path += "/test.ctest";
|
||||||
|
fs::write(path, DEFAULT_CONTENT).unwrap();
|
||||||
|
}
|
||||||
|
|
39
src/main.rs
39
src/main.rs
|
@ -1,3 +1,5 @@
|
||||||
|
use std::env;
|
||||||
|
|
||||||
use clap::{Parser, Subcommand};
|
use clap::{Parser, Subcommand};
|
||||||
use config::Config;
|
use config::Config;
|
||||||
|
|
||||||
|
@ -45,10 +47,9 @@ pub enum Commands {
|
||||||
|
|
||||||
/// Files to run tests from.
|
/// Files to run tests from.
|
||||||
files: Vec<String>,
|
files: Vec<String>,
|
||||||
|
// /// Specific tests to run.
|
||||||
/// Specific tests to run.
|
// #[clap(short, long)]
|
||||||
#[clap(short, long)]
|
// tests: Vec<String>,
|
||||||
tests: Vec<String>,
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/// Watches changes to the project included files and runs a command on changes.
|
/// Watches changes to the project included files and runs a command on changes.
|
||||||
|
@ -61,11 +62,13 @@ pub enum Commands {
|
||||||
|
|
||||||
/// Initializes a project directory configuration, useful for custom flags, includes and custop push messages.
|
/// Initializes a project directory configuration, useful for custom flags, includes and custop push messages.
|
||||||
init {
|
init {
|
||||||
/// Path to the folder containing the project.
|
|
||||||
path: String,
|
|
||||||
|
|
||||||
/// Identifier for the automated tests.
|
/// Identifier for the automated tests.
|
||||||
identifier: String,
|
prefix: String,
|
||||||
|
/// Path to the folder containing the project.
|
||||||
|
path: Option<String>,
|
||||||
|
/// e
|
||||||
|
#[clap(short, long)]
|
||||||
|
tests: bool,
|
||||||
},
|
},
|
||||||
|
|
||||||
/// Pushes changes to the git server with a custom tag.
|
/// Pushes changes to the git server with a custom tag.
|
||||||
|
@ -87,6 +90,7 @@ fn compilation_args() -> Vec<String> {
|
||||||
"-fsanitize=address".to_string(),
|
"-fsanitize=address".to_string(),
|
||||||
"-Wextra".to_string(),
|
"-Wextra".to_string(),
|
||||||
"-std=c99".to_string(),
|
"-std=c99".to_string(),
|
||||||
|
// "-pedantic".to_string(),
|
||||||
];
|
];
|
||||||
if Config::get_local_or_default().strict_mode() {
|
if Config::get_local_or_default().strict_mode() {
|
||||||
args.push("-Werror".to_string());
|
args.push("-Werror".to_string());
|
||||||
|
@ -114,15 +118,14 @@ fn main() {
|
||||||
Commands::test {
|
Commands::test {
|
||||||
capture,
|
capture,
|
||||||
mut files,
|
mut files,
|
||||||
tests,
|
// tests,
|
||||||
} => {
|
} => {
|
||||||
if files.is_empty() {
|
if files.is_empty() {
|
||||||
files.push(Config::get_local_or_default().test_file().to_string());
|
files.push(Config::get_local_or_default().test_file().to_string());
|
||||||
}
|
}
|
||||||
append_includes(&mut files);
|
append_includes(&mut files);
|
||||||
let args = compilation_args();
|
let args = compilation_args();
|
||||||
let tests = (!tests.is_empty()).then_some(tests);
|
test::main(capture, files, args)
|
||||||
test::main(capture, files, args, tests)
|
|
||||||
}
|
}
|
||||||
Commands::watch { command, files } => {
|
Commands::watch { command, files } => {
|
||||||
let mut files = files.unwrap_or_default();
|
let mut files = files.unwrap_or_default();
|
||||||
|
@ -130,8 +133,18 @@ fn main() {
|
||||||
watch::main(files, command);
|
watch::main(files, command);
|
||||||
}
|
}
|
||||||
|
|
||||||
Commands::init { path, identifier } => {
|
Commands::init {
|
||||||
config::create(path, identifier);
|
path,
|
||||||
|
prefix,
|
||||||
|
tests,
|
||||||
|
} => {
|
||||||
|
let path =
|
||||||
|
path.unwrap_or_else(|| env::current_dir().unwrap().to_str().unwrap().to_string());
|
||||||
|
let prefix = prefix.trim().trim_end_matches('*');
|
||||||
|
config::create(path.clone(), prefix.to_string());
|
||||||
|
if tests {
|
||||||
|
config::create_test(path);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Commands::push { message } => {
|
Commands::push { message } => {
|
||||||
|
|
17
src/push.rs
17
src/push.rs
|
@ -7,15 +7,26 @@ use crate::{
|
||||||
utils::{log_error, log_process, log_success},
|
utils::{log_error, log_process, log_success},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub fn add() {
|
||||||
|
let path = Config::get_local_path().unwrap();
|
||||||
|
let path = path.parent().unwrap();
|
||||||
|
let path = path.to_str().unwrap();
|
||||||
|
Command::new("git")
|
||||||
|
.args(["add", path])
|
||||||
|
.status()
|
||||||
|
.unwrap()
|
||||||
|
.success()
|
||||||
|
.then_some(())
|
||||||
|
.unwrap_or_else(|| exit(1));
|
||||||
|
}
|
||||||
|
|
||||||
pub fn main(message: Option<String>) {
|
pub fn main(message: Option<String>) {
|
||||||
let message = message.unwrap_or_else(|| Utc::now().format("pi - %d/%m/%Y %H:%M").to_string());
|
let message = message.unwrap_or_else(|| Utc::now().format("pi - %d/%m/%Y %H:%M").to_string());
|
||||||
let timestamp = Utc::now().timestamp();
|
let timestamp = Utc::now().timestamp();
|
||||||
let suffix = format!("pi{timestamp}");
|
let suffix = format!("pi{timestamp}");
|
||||||
let tag = Config::get_local()
|
let tag = Config::get_local()
|
||||||
.unwrap_or_else(|| {
|
.unwrap_or_else(|| {
|
||||||
log_error(
|
log_error("no config file found.\nPlease initialize with 'pi init <tag-prefix>'");
|
||||||
"no config file found.\nPlease initialize with 'pi init <path> <identifier>'",
|
|
||||||
);
|
|
||||||
exit(1)
|
exit(1)
|
||||||
})
|
})
|
||||||
.identifier()
|
.identifier()
|
||||||
|
|
|
@ -5,7 +5,7 @@ use crate::{
|
||||||
utils::{log_failure, log_process, log_success},
|
utils::{log_failure, log_process, log_success},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn main(_capture: bool, files: Vec<String>, args: Vec<String>, _test: Option<Vec<String>>) {
|
pub fn main(_capture: bool, files: Vec<String>, args: Vec<String>) {
|
||||||
log_process("testing");
|
log_process("testing");
|
||||||
for path in files {
|
for path in files {
|
||||||
let content = fs::read_to_string(&path).unwrap();
|
let content = fs::read_to_string(&path).unwrap();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue