Skip to content

Commit 71eeb7d

Browse files
authored
Merge pull request #1 from JheisonMB/feature/implement-core-v1
Feature/implement core v1
2 parents 20e7360 + 3cba3b9 commit 71eeb7d

12 files changed

Lines changed: 861 additions & 3 deletions

File tree

.gitignore

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,10 @@ Cargo.lock
1111
.kiro/
1212
.agents/
1313
.idea/
14-
skills-lock.json
14+
skills-lock.json
15+
16+
# Added by cargo
17+
#
18+
# already existing elements were commented out
19+
20+
#/target

Cargo.toml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
[package]
2+
name = "gitkit"
3+
version = "0.1.0"
4+
edition = "2021"
5+
description = "Standalone CLI for configuring git repos — hooks, .gitignore, and .gitattributes"
6+
license = "MIT"
7+
repository = "https://github.com/JheisonMB/gitkit"
8+
keywords = ["git", "hooks", "cli", "gitignore", "gitattributes"]
9+
categories = ["command-line-utilities", "development-tools"]
10+
11+
[[bin]]
12+
name = "gitkit"
13+
path = "src/main.rs"
14+
15+
[dependencies]
16+
anyhow = "1"
17+
clap = { version = "4", features = ["derive"] }
18+
ureq = "2"

README.md

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,12 @@ Standalone CLI for configuring git repos — hooks, .gitignore, and .gitattribut
1919
curl -fsSL https://raw.githubusercontent.com/JheisonMB/gitkit/main/install.sh | sh
2020
```
2121

22+
**Windows (PowerShell):**
23+
24+
```powershell
25+
irm https://raw.githubusercontent.com/JheisonMB/gitkit/main/install.ps1 | iex
26+
```
27+
2228
### Via cargo
2329

2430
```bash
@@ -50,7 +56,7 @@ gitkit hooks init pre-push "cargo test"
5056
gitkit hooks list
5157

5258
# Generate a .gitignore
53-
gitkit ignore add rust macos
59+
gitkit ignore add rust,vscode
5460

5561
# Apply line endings preset
5662
gitkit attributes init
@@ -67,8 +73,9 @@ gitkit attributes init
6773
| `gitkit hooks remove <hook>` | Remove a hook |
6874
| `gitkit hooks show <hook>` | Show hook content |
6975
| `gitkit ignore add <templates>` | Generate .gitignore via gitignore.io |
70-
| `gitkit ignore list` | List available templates |
76+
| `gitkit ignore list [filter]` | List available templates |
7177
| `gitkit attributes init` | Apply line endings preset |
78+
| `gitkit config apply <preset>` | Apply git config preset (defaults, advanced, delta) |
7279

7380
---
7481

install.ps1

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
# install.ps1 — download and install gitkit on Windows
2+
# Usage: irm https://raw.githubusercontent.com/JheisonMB/gitkit/main/install.ps1 | iex
3+
#
4+
# Options (set as env vars before running):
5+
# $env:VERSION = "0.1.0" # pin a specific version
6+
# $env:INSTALL_DIR = "C:\my\bin" # custom install directory
7+
8+
$ErrorActionPreference = "Stop"
9+
10+
$Repo = "JheisonMB/gitkit"
11+
$Binary = "gitkit.exe"
12+
$Target = "x86_64-pc-windows-msvc"
13+
$InstallDir = if ($env:INSTALL_DIR) { $env:INSTALL_DIR } else { "$env:USERPROFILE\.local\bin" }
14+
15+
function Info($label, $msg) {
16+
Write-Host " " -NoNewline
17+
Write-Host $label -ForegroundColor Blue -NoNewline
18+
Write-Host " $msg"
19+
}
20+
21+
function Fail($msg) {
22+
Write-Host " error: $msg" -ForegroundColor Red
23+
exit 1
24+
}
25+
26+
# --- resolve version ---
27+
if ($env:VERSION) {
28+
$Tag = "v$($env:VERSION)"
29+
Info "version" "$Tag (pinned)"
30+
} else {
31+
$latest = Invoke-RestMethod "https://api.github.com/repos/$Repo/releases/latest"
32+
$Tag = $latest.tag_name
33+
if (-not $Tag) { Fail "Could not resolve latest release tag" }
34+
Info "version" "$Tag (latest)"
35+
}
36+
37+
# --- download ---
38+
$Archive = "gitkit-$Tag-$Target.zip"
39+
$Url = "https://github.com/$Repo/releases/download/$Tag/$Archive"
40+
$Tmp = Join-Path $env:TEMP "gitkit-install"
41+
New-Item -ItemType Directory -Force -Path $Tmp | Out-Null
42+
43+
Info "download" $Url
44+
try {
45+
Invoke-WebRequest -Uri $Url -OutFile "$Tmp\$Archive" -UseBasicParsing
46+
} catch {
47+
Fail "Download failed: $_`nURL: $Url"
48+
}
49+
50+
# --- extract ---
51+
Expand-Archive -Path "$Tmp\$Archive" -DestinationPath $Tmp -Force
52+
$extracted = Join-Path $Tmp $Binary
53+
if (-not (Test-Path $extracted)) { Fail "Binary not found in archive" }
54+
55+
# --- install ---
56+
New-Item -ItemType Directory -Force -Path $InstallDir | Out-Null
57+
Copy-Item $extracted "$InstallDir\$Binary" -Force
58+
Info "installed" "$InstallDir\$Binary"
59+
60+
# --- ensure PATH ---
61+
$userPath = [Environment]::GetEnvironmentVariable("PATH", "User")
62+
if ($userPath -notlike "*$InstallDir*") {
63+
[Environment]::SetEnvironmentVariable("PATH", "$InstallDir;$userPath", "User")
64+
$env:PATH = "$InstallDir;$env:PATH"
65+
Info "updated" "User PATH"
66+
}
67+
68+
# --- cleanup ---
69+
Remove-Item $Tmp -Recurse -Force
70+
71+
# --- verify ---
72+
$ver = & "$InstallDir\$Binary" --version 2>$null
73+
Info "done" $ver
74+
Write-Host ""
75+
Info "ready" "Run 'gitkit hooks init commit-msg conventional-commits' to get started!"

install.sh

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
#!/bin/sh
2+
# install.sh — download and install gitkit from GitHub Releases
3+
# Usage: curl -fsSL https://raw.githubusercontent.com/JheisonMB/gitkit/main/install.sh | sh
4+
set -eu
5+
6+
REPO="JheisonMB/gitkit"
7+
BINARY="gitkit"
8+
INSTALL_DIR="${INSTALL_DIR:-$HOME/.local/bin}"
9+
10+
info() { printf ' \033[1;34m%s\033[0m %s\n' "$1" "$2"; }
11+
error() { printf ' \033[1;31merror:\033[0m %s\n' "$1" >&2; exit 1; }
12+
13+
# --- detect OS ---
14+
OS="$(uname -s)"
15+
case "$OS" in
16+
Linux*) OS_TARGET="unknown-linux-musl" ;;
17+
Darwin*) OS_TARGET="apple-darwin" ;;
18+
*) error "Unsupported OS: $OS (only Linux and macOS are supported)" ;;
19+
esac
20+
21+
# --- detect arch ---
22+
ARCH="$(uname -m)"
23+
case "$ARCH" in
24+
x86_64|amd64) ARCH_TARGET="x86_64" ;;
25+
arm64|aarch64) ARCH_TARGET="aarch64" ;;
26+
*) error "Unsupported architecture: $ARCH" ;;
27+
esac
28+
29+
TARGET="${ARCH_TARGET}-${OS_TARGET}"
30+
info "platform" "$TARGET"
31+
32+
TMPDIR="$(mktemp -d)"
33+
trap 'rm -rf "$TMPDIR"' EXIT
34+
35+
# --- resolve version ---
36+
if [ -n "${VERSION:-}" ]; then
37+
TAG="v$VERSION"
38+
info "version" "$TAG (pinned)"
39+
else
40+
TAG=$(curl -fsSL -o /dev/null -w '%{url_effective}' "https://github.com/$REPO/releases/latest" | rev | cut -d'/' -f1 | rev)
41+
[ -z "$TAG" ] && error "Could not resolve latest release tag"
42+
info "version" "$TAG (latest)"
43+
fi
44+
45+
# --- download ---
46+
ARCHIVE="${BINARY}-${TAG}-${TARGET}.tar.gz"
47+
URL="https://github.com/$REPO/releases/download/${TAG}/${ARCHIVE}"
48+
49+
info "download" "$URL"
50+
HTTP_CODE=$(curl -fSL -w '%{http_code}' -o "$TMPDIR/$ARCHIVE" "$URL" 2>/dev/null) || true
51+
[ "$HTTP_CODE" = "200" ] || error "Download failed (HTTP $HTTP_CODE). Check that $TAG exists for $TARGET at:\n $URL"
52+
53+
# --- extract ---
54+
tar xzf "$TMPDIR/$ARCHIVE" -C "$TMPDIR"
55+
[ -f "$TMPDIR/$BINARY" ] || error "Binary not found in archive"
56+
57+
# --- install ---
58+
mkdir -p "$INSTALL_DIR"
59+
mv "$TMPDIR/$BINARY" "$INSTALL_DIR/$BINARY"
60+
chmod +x "$INSTALL_DIR/$BINARY"
61+
info "installed" "$INSTALL_DIR/$BINARY"
62+
63+
# --- ensure PATH ---
64+
case ":$PATH:" in
65+
*":$INSTALL_DIR:"*) ;;
66+
*)
67+
export PATH="$INSTALL_DIR:$PATH"
68+
for profile in "$HOME/.bashrc" "$HOME/.zshrc" "$HOME/.profile"; do
69+
if [ -f "$profile" ]; then
70+
if ! grep -q "export PATH=\"$INSTALL_DIR:\$PATH\"" "$profile" 2>/dev/null; then
71+
printf '\n# Added by gitkit installer\nexport PATH="%s:$PATH"\n' "$INSTALL_DIR" >> "$profile"
72+
info "updated" "$profile"
73+
fi
74+
fi
75+
done
76+
;;
77+
esac
78+
79+
# --- verify ---
80+
info "done" "$($INSTALL_DIR/$BINARY --version 2>/dev/null || echo "$BINARY installed")"
81+
echo ""
82+
info "ready" "Run 'gitkit hooks init commit-msg conventional-commits' to get started!"

src/attributes/mod.rs

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
use anyhow::{Context, Result};
2+
use clap::Subcommand;
3+
use std::fs;
4+
5+
use crate::utils::{confirm, find_repo_root};
6+
7+
const PRESET: &str = "* text=auto eol=lf\n";
8+
9+
#[derive(Subcommand)]
10+
pub enum AttributesCommand {
11+
/// Apply line endings preset to .gitattributes
12+
Init {
13+
#[arg(short, long)]
14+
yes: bool,
15+
#[arg(short, long)]
16+
force: bool,
17+
#[arg(long)]
18+
dry_run: bool,
19+
},
20+
}
21+
22+
pub fn run(cmd: AttributesCommand) -> Result<()> {
23+
let AttributesCommand::Init {
24+
yes,
25+
force,
26+
dry_run,
27+
} = cmd;
28+
29+
let root = find_repo_root()?;
30+
let path = root.join(".gitattributes");
31+
32+
if path.exists() && !force {
33+
if !confirm(".gitattributes already exists. Overwrite?", yes) {
34+
println!("Aborted.");
35+
return Ok(());
36+
}
37+
if !dry_run {
38+
let backup = root.join(".gitattributes.bak");
39+
std::fs::copy(&path, &backup).context("Failed to backup .gitattributes")?;
40+
println!("Backed up to {}", backup.display());
41+
}
42+
}
43+
44+
if dry_run {
45+
println!("[dry-run] Would write .gitattributes:\n{PRESET}");
46+
return Ok(());
47+
}
48+
49+
fs::write(&path, PRESET).context("Failed to write .gitattributes")?;
50+
println!("Applied line endings preset to .gitattributes.");
51+
Ok(())
52+
}

0 commit comments

Comments
 (0)