Skip to content

Commit be4791c

Browse files
committed
maj: includes arguments, colored, error checking, modularisation
- args - owner // owner of repo - repo // repository - debug // get curl reposone headers - modularise - args, main, git, github, token and output - cargo.toml - added colored - error - returns good errors and descriptions
1 parent f004091 commit be4791c

File tree

8 files changed

+577
-134
lines changed

8 files changed

+577
-134
lines changed

git_workflows/Cargo.lock

Lines changed: 146 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

git_workflows/Cargo.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@ version = "0.1.0"
44
edition = "2021"
55

66
[dependencies]
7+
clap = { version = "4.4", features = ["derive"] }
78
reqwest = { version = "0.12.0", features = ["json"] }
89
serde = { version = "1.0", features = ["derive"] }
910
serde_json = "1.0"
1011
regex = "1.5"
1112
chrono = { version = "0.4", features = ["serde"] }
12-
tokio = { version = "1", features = ["full"] }
13+
tokio = { version = "1", features = ["full"] }
14+
colored = "2.0"

git_workflows/src/args.rs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
//! Command-line argument parser for the GitHub Workflow Checker.
2+
//!
3+
//! This module defines the [`Cli`] struct and its parsing behavior using the [`clap`] crate.
4+
//! It allows optional specification of the GitHub repository owner and name via `--owner` and `--repo` flags.
5+
//!
6+
//! If neither argument is supplied, the application falls back to detecting the repository from the local Git config.
7+
use clap::Parser;
8+
9+
/// CLI interface for the GitHub Workflow Checker.
10+
///
11+
/// Supports optional arguments to manually specify the GitHub repository:
12+
/// - `--owner`: GitHub username or organization (e.g., `uniofgreenwich`)
13+
/// - `--repo`: Repository name (e.g., `ELEE1149_Exercises`)
14+
///
15+
/// If not provided, the tool attempts to extract this info from `.git/config`.
16+
#[derive(Parser, Debug)]
17+
#[command(author, version, about)]
18+
pub struct Cli {
19+
/// Repository owner (e.g. uniofgreenwich)
20+
#[arg(short, long)]
21+
pub owner: Option<String>,
22+
23+
/// Repository name (e.g. ELEE1149_Exercises)
24+
#[arg(short, long)]
25+
pub repo: Option<String>,
26+
27+
/// Enable debug mode (prints internal info)
28+
#[arg(long)]
29+
pub debug: bool,
30+
}
31+
32+
impl Cli {
33+
/// Parse the CLI arguments and return a [`Cli`] instance.
34+
///
35+
/// # Panics
36+
/// This will panic if argument parsing fails (e.g., invalid input format).
37+
pub fn parse_args() -> Self {
38+
Cli::parse()
39+
}
40+
}

git_workflows/src/git.rs

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
//! Git repository inspector.
2+
//!
3+
//! This module provides functionality to extract the GitHub repository
4+
//! owner and name from the local `.git/config` file.
5+
//!
6+
//! If the program is not running inside a Git repository, it supports falling
7+
//! back to parsing command-line arguments for owner and repo name.
8+
use regex::Regex;
9+
use std::{env, fs, process::exit};
10+
use std::process::Command;
11+
12+
/// Attempts to determine the repository owner and name.
13+
///
14+
/// This function will first check if the current working directory is inside a Git
15+
/// repository using `git rev-parse --is-inside-work-tree`. If so, it reads the
16+
/// `.git/config` file and parses the `url` entry for the `origin` remote to extract
17+
/// the GitHub owner and repository name.
18+
///
19+
/// If the directory is not inside a Git repo, this function falls back to expecting
20+
/// two arguments: the repository owner at position 1 and the repository name at position 2.
21+
///
22+
/// # Arguments
23+
///
24+
/// * `args` - A vector of command-line arguments. Only used if not in a Git repo.
25+
///
26+
/// # Returns
27+
///
28+
/// A tuple `(owner, repo)` as `String` values.
29+
///
30+
/// # Panics / Exits
31+
///
32+
/// This function will terminate the program with an error message if:
33+
/// - The Git command fails or indicates it's not inside a repo
34+
/// - The `.git/config` file cannot be read or parsed
35+
/// - Not enough CLI arguments are provided when required
36+
pub async fn get_repo_path(args: Vec<String>) -> (String, String) {
37+
let current_dir = env::current_dir().expect("Unable to get current directory");
38+
let output = Command::new("git")
39+
.current_dir(&current_dir)
40+
.args(&["rev-parse", "--is-inside-work-tree"])
41+
.output()
42+
.expect("Failed to execute git command");
43+
44+
if output.status.success() && String::from_utf8_lossy(&output.stdout).trim() == "true" {
45+
let config_path = current_dir.join(".git").join("config");
46+
if !config_path.exists() {
47+
eprintln!(".git/config not found. Are you in a Git repository?");
48+
exit(1);
49+
}
50+
let config_content = fs::read_to_string(config_path).unwrap_or_else(|e| {
51+
eprintln!("Unable to read .git/config: {}", e);
52+
exit(1);
53+
});
54+
55+
let owner_re = Regex::new(r#"url\s*=\s*git@github\.com:(\w+)/([\w-]+)\.git"#).unwrap();
56+
let caps = owner_re.captures(&config_content).unwrap_or_else(|| {
57+
eprintln!("Failed to extract repository owner and name from .git/config");
58+
exit(1);
59+
});
60+
61+
let owner = caps.get(1).unwrap().as_str().to_string();
62+
let name = caps.get(2).unwrap().as_str().to_string();
63+
(owner, name)
64+
} else if args.len() == 3 {
65+
(args[1].clone(), args[2].clone())
66+
} else {
67+
eprintln!("Position 1: Owner, position 2: repo name, or be in a git repo");
68+
exit(1);
69+
}
70+
}

0 commit comments

Comments
 (0)