Compare commits

..

28 Commits
v0.1.2 ... main

Author SHA1 Message Date
ec34a47faf fix(deps): update rust crate clap to v4.5.27
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2025-01-21 01:38:22 +00:00
85d80db364 fix(deps): update rust crate dirs to v6
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2025-01-13 01:37:07 +00:00
4f44862160 fix(deps): update rust crate clap to v4.5.26
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2025-01-10 01:33:59 +00:00
25d43765d9 fix(deps): update rust crate clap to v4.5.24
All checks were successful
continuous-integration/drone/pr Build is passing
continuous-integration/drone/push Build is passing
2025-01-08 01:32:29 +00:00
88680da7d5 feat: empty empty
All checks were successful
continuous-integration/drone/push Build is passing
Signed-off-by: kjuulh <contact@kjuulh.io>
2024-12-27 16:28:43 +01:00
2a46b7b170 feat: can handle empty struct
Some checks failed
continuous-integration/drone/push Build is failing
Signed-off-by: kjuulh <contact@kjuulh.io>
2024-12-27 16:28:21 +01:00
f9513fe051 feat: trigger commit
Some checks failed
continuous-integration/drone/push Build is failing
2024-12-27 16:26:02 +01:00
09cfa5b88f feat: add publish
Some checks failed
continuous-integration/drone/push Build is failing
Signed-off-by: kjuulh <contact@kjuulh.io>
2024-12-27 16:25:03 +01:00
88b602a124 chore: override release for smaller binaries
All checks were successful
continuous-integration/drone/push Build is passing
Signed-off-by: kjuulh <contact@kjuulh.io>
2024-12-22 15:13:02 +01:00
674266664d chore(release): v0.4.0 (#90)
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/tag Build is passing
chore(release): 0.4.0

Co-authored-by: cuddle-please <bot@cuddle.sh>
Reviewed-on: #90
2024-12-22 14:53:58 +01:00
39dc4ae15c chore: make variant for the other shell commands
All checks were successful
continuous-integration/drone/push Build is passing
Signed-off-by: kjuulh <contact@kjuulh.io>
2024-12-22 14:52:05 +01:00
55a5a9a1e1 feat: make init zsh
All checks were successful
continuous-integration/drone/push Build is passing
Signed-off-by: kjuulh <contact@kjuulh.io>
2024-12-22 13:33:46 +01:00
92a0e3b1b3 chore(release): v0.3.0 (#89)
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/tag Build is passing
chore(release): 0.3.0

Co-authored-by: cuddle-please <bot@cuddle.sh>
Reviewed-on: #89
2024-12-22 13:01:48 +01:00
b167b3ebfa feat: make cli look nice
All checks were successful
continuous-integration/drone/push Build is passing
Signed-off-by: kjuulh <contact@kjuulh.io>
2024-12-22 13:00:58 +01:00
b78631d6ac chore(release): v0.2.4 (#88)
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/tag Build is passing
chore(release): 0.2.4

Co-authored-by: cuddle-please <bot@cuddle.sh>
Reviewed-on: #88
2024-12-22 12:44:31 +01:00
00a249978e chore: trigger commit
All checks were successful
continuous-integration/drone/push Build is passing
2024-12-22 12:43:57 +01:00
a86a4197f7 chore(release): v0.2.3 (#87)
Some checks failed
continuous-integration/drone/push Build is passing
continuous-integration/drone/tag Build is failing
chore(release): 0.2.3

Co-authored-by: cuddle-please <bot@cuddle.sh>
Reviewed-on: #87
2024-12-22 12:37:08 +01:00
0397b64e28 chore: trigger commit
All checks were successful
continuous-integration/drone/push Build is passing
2024-12-22 12:36:39 +01:00
77901c6ac9 chore(release): v0.2.2 (#86)
Some checks failed
continuous-integration/drone/push Build is passing
continuous-integration/drone/tag Build is failing
chore(release): 0.2.2

Co-authored-by: cuddle-please <bot@cuddle.sh>
Reviewed-on: #86
2024-12-22 12:34:09 +01:00
a1eadd67e1 feat: trigger commit
All checks were successful
continuous-integration/drone/push Build is passing
2024-12-22 12:33:24 +01:00
d5271807f7 chore(release): v0.2.1 (#85)
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/tag Build is passing
chore(release): 0.2.1

Co-authored-by: cuddle-please <bot@cuddle.sh>
Reviewed-on: #85
2024-12-22 12:03:58 +01:00
947e05e573 chore: fix cargo toml
All checks were successful
continuous-integration/drone/push Build is passing
Signed-off-by: kjuulh <contact@kjuulh.io>
2024-12-22 11:55:17 +01:00
a720dedcf5 chore(release): v0.2.0 (#84)
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/tag Build is passing
chore(release): 0.2.0

Co-authored-by: cuddle-please <bot@cuddle.sh>
Reviewed-on: #84
2024-12-22 11:54:23 +01:00
446c957a97 feat: transform to binary
All checks were successful
continuous-integration/drone/push Build is passing
Signed-off-by: kjuulh <contact@kjuulh.io>
2024-12-22 11:53:43 +01:00
fa7041187f feat: redo project structure
Some checks failed
continuous-integration/drone/push Build is failing
Signed-off-by: kjuulh <contact@kjuulh.io>
2024-12-22 11:51:36 +01:00
f5ff75bfbe chore: update lock
All checks were successful
continuous-integration/drone/push Build is passing
Signed-off-by: kjuulh <contact@kjuulh.io>
2024-12-22 11:47:12 +01:00
a34118b5e8 chore(release): v0.1.3 (#83)
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/tag Build is passing
chore(release): 0.1.3

Co-authored-by: cuddle-please <bot@cuddle.sh>
Reviewed-on: #83
2024-12-22 11:44:28 +01:00
6e4fa67778 chore: update cargo
All checks were successful
continuous-integration/drone/push Build is passing
Signed-off-by: kjuulh <contact@kjuulh.io>
2024-12-22 11:43:37 +01:00
17 changed files with 326 additions and 549 deletions

View File

@ -1,178 +0,0 @@
# The way this works is the following:
#
# The create-release job runs purely to initialize the GitHub release itself
# and to output upload_url for the following job.
#
# The build-release job runs only once create-release is finished. It gets the
# release upload URL from create-release job outputs, then builds the release
# executables for each supported platform and attaches them as release assets
# to the previously created release.
#
# The key here is that we create the release only once.
#
# Reference:
# https://eugene-babichenko.github.io/blog/2020/05/09/github-actions-cross-platform-auto-releases/
name: release
on:
push:
# Enable when testing release infrastructure on a branch.
branches:
- kjuulh/test
tags:
- "[0-9]+.[0-9]+.[0-9]+"
jobs:
create-release:
name: create-release
runs-on: ubuntu-22.04
# env:
# Set to force version number, e.g., when no tag exists.
# KIGNORE_VERSION: TEST-0.0.0
outputs:
upload_url: ${{ steps.release.outputs.upload_url }}
kignore_version: ${{ env.KIGNORE_VERSION }}
steps:
- name: Get the release version from the tag
shell: bash
if: env.KIGNORE_VERSION == ''
run: |
# Apparently, this is the right way to get a tag name. Really?
#
# See: https://github.community/t5/GitHub-Actions/How-to-get-just-the-tag-name/m-p/32167/highlight/true#M1027
echo "KIGNORE_VERSION=${GITHUB_REF#refs/tags/}" >> $GITHUB_ENV
echo "version is: ${{ env.KIGNORE_VERSION }}"
- name: Create GitHub release
id: release
uses: actions/create-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ env.KIGNORE_VERSION }}
release_name: ${{ env.KIGNORE_VERSION }}
build-release:
name: build-release
needs: ["create-release"]
runs-on: ${{ matrix.os }}
env:
# For some builds, we use cross to test on 32-bit and big-endian
# systems.
CARGO: cargo
# When CARGO is set to CROSS, this is set to `--target matrix.target`.
TARGET_FLAGS: ""
# When CARGO is set to CROSS, TARGET_DIR includes matrix.target.
TARGET_DIR: ./target
# Emit backtraces on panics.
RUST_BACKTRACE: 1
# Build static releases with PCRE2.
PCRE2_SYS_STATIC: 1
strategy:
matrix:
build: [linux, linux-arm, macos] #, win-msvc, win-gnu, win32-msvc]
include:
- build: linux
os: ubuntu-22.04
rust: nightly
target: x86_64-unknown-linux-musl
- build: linux-arm
os: ubuntu-22.04
rust: nightly
target: arm-unknown-linux-gnueabihf
- build: macos
os: macos-12
rust: nightly
target:
x86_64-apple-darwin
# - build: win-msvc
# os: windows-2022
# rust: nightly
# target: x86_64-pc-windows-msvc
# - build: win-gnu
# os: windows-2022
# rust: nightly-x86_64-gnu
# target: x86_64-pc-windows-gnu
# - build: win32-msvc
# os: windows-2022
# rust: nightly
# target: i686-pc-windows-msvc
steps:
- name: Checkout repository
uses:
actions/checkout@v3
#- name: Install packages (Ubuntu)
# if: matrix.os == 'ubuntu-22.04'
# run: |
# ci/ubuntu-install-packages
- name: Install Rust
uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{ matrix.rust }}
target: ${{ matrix.target }}
- name: Use Cross
shell: bash
run: |
cargo install cross
echo "CARGO=cross" >> $GITHUB_ENV
echo "TARGET_FLAGS=--target ${{ matrix.target }}" >> $GITHUB_ENV
echo "TARGET_DIR=./target/${{ matrix.target }}" >> $GITHUB_ENV
- name: Show command used for Cargo
run: |
echo "cargo command is: ${{ env.CARGO }}"
echo "target flag is: ${{ env.TARGET_FLAGS }}"
echo "target dir is: ${{ env.TARGET_DIR }}"
- name: Build release binary
run: ${{ env.CARGO }} build --verbose --release ${{ env.TARGET_FLAGS }}
- name: Strip release binary (linux and macos)
if: matrix.build == 'linux' || matrix.build == 'macos'
run: strip "target/${{ matrix.target }}/release/kignore"
- name: Strip release binary (arm)
if: matrix.build == 'linux-arm'
run: |
docker run --rm -v \
"$PWD/target:/target:Z" \
rustembedded/cross:arm-unknown-linux-gnueabihf \
arm-linux-gnueabihf-strip \
/target/arm-unknown-linux-gnueabihf/release/kignore
- name: Build archive
shell: bash
run: |
outdir="$(ci/cargo-out-dir "${{ env.TARGET_DIR }}")"
staging="kignore-${{ needs.create-release.outputs.kignore_version }}-${{ matrix.target }}"
mkdir -p "$staging"/{complete,doc}
cp {README.md,LICENSE-MIT} "$staging/"
#cp {CHANGELOG.md,FAQ.md,GUIDE.md} "$staging/doc/"
#cp "$outdir"/{rg.bash,rg.fish,_rg.ps1} "$staging/complete/"
#cp complete/_rg "$staging/complete/"
if [ "${{ matrix.os }}" = "windows-2022" ]; then
cp "target/${{ matrix.target }}/release/kignore.exe" "$staging/"
7z a "$staging.zip" "$staging"
echo "ASSET=$staging.zip" >> $GITHUB_ENV
else
cp "git-alias/git-ignore" "$staging/"
# The man page is only generated on Unix systems.
#cp "$outdir"/kignore.1 "$staging/doc/"
cp "target/${{ matrix.target }}/release/kignore" "$staging/"
tar czf "$staging.tar.gz" "$staging"
echo "ASSET=$staging.tar.gz" >> $GITHUB_ENV
fi
- name: Upload release archive
uses: actions/upload-release-asset@v1.0.2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ needs.create-release.outputs.upload_url }}
asset_path: ${{ env.ASSET }}
asset_name: ${{ env.ASSET }}
asset_content_type: application/octet-stream

View File

@ -6,6 +6,53 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased] ## [Unreleased]
## [0.4.0] - 2024-12-22
### Added
- make init zsh
### Other
- make variant for the other shell commands
## [0.3.0] - 2024-12-22
### Added
- make cli look nice
## [0.2.4] - 2024-12-22
### Other
- trigger commit
## [0.2.3] - 2024-12-22
### Other
- trigger commit
## [0.2.2] - 2024-12-22
### Added
- trigger commit
## [0.2.1] - 2024-12-22
### Other
- fix cargo toml
## [0.2.0] - 2024-12-22
### Added
- transform to binary
- redo project structure
### Other
- update lock
## [0.1.3] - 2024-12-22
### Other
- update cargo
## [0.1.2] - 2024-12-22 ## [0.1.2] - 2024-12-22
### Added ### Added

110
Cargo.lock generated
View File

@ -60,6 +60,12 @@ dependencies = [
"windows-sys", "windows-sys",
] ]
[[package]]
name = "bitflags"
version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
[[package]] [[package]]
name = "cfg-if" name = "cfg-if"
version = "1.0.0" version = "1.0.0"
@ -68,18 +74,18 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]] [[package]]
name = "clap" name = "clap"
version = "4.5.23" version = "4.5.27"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3135e7ec2ef7b10c6ed8950f0f792ed96ee093fa088608f1c76e569722700c84" checksum = "769b0145982b4b48713e01ec42d61614425f27b7058bda7180a3a41f30104796"
dependencies = [ dependencies = [
"clap_builder", "clap_builder",
] ]
[[package]] [[package]]
name = "clap_builder" name = "clap_builder"
version = "4.5.23" version = "4.5.27"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "30582fc632330df2bd26877bde0c1f4470d57c582bbc070376afcd04d8cb4838" checksum = "1b26884eb4b57140e4d2d93652abfa49498b938b3c9179f9fc487b0acc3edad7"
dependencies = [ dependencies = [
"anstream", "anstream",
"anstyle", "anstyle",
@ -123,6 +129,27 @@ dependencies = [
"powerfmt", "powerfmt",
] ]
[[package]]
name = "dirs"
version = "6.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3e8aa94d75141228480295a7d0e7feb620b1a5ad9f12bc40be62411e38cce4e"
dependencies = [
"dirs-sys",
]
[[package]]
name = "dirs-sys"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab"
dependencies = [
"libc",
"option-ext",
"redox_users",
"windows-sys",
]
[[package]] [[package]]
name = "encode_unicode" name = "encode_unicode"
version = "1.0.0" version = "1.0.0"
@ -140,14 +167,14 @@ dependencies = [
] ]
[[package]] [[package]]
name = "gitignore_inner" name = "getrandom"
version = "0.1.0" version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
dependencies = [ dependencies = [
"clap", "cfg-if",
"console", "libc",
"eyre", "wasi",
"tracing",
"tracing-subscriber",
] ]
[[package]] [[package]]
@ -170,10 +197,14 @@ checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674"
[[package]] [[package]]
name = "kignore" name = "kignore"
version = "0.1.2" version = "0.4.0"
dependencies = [ dependencies = [
"clap",
"console",
"dirs",
"eyre", "eyre",
"gitignore_inner", "tracing",
"tracing-subscriber",
] ]
[[package]] [[package]]
@ -188,6 +219,16 @@ version = "0.2.169"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a"
[[package]]
name = "libredox"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d"
dependencies = [
"bitflags",
"libc",
]
[[package]] [[package]]
name = "log" name = "log"
version = "0.4.22" version = "0.4.22"
@ -240,6 +281,12 @@ version = "1.20.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775"
[[package]]
name = "option-ext"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d"
[[package]] [[package]]
name = "overload" name = "overload"
version = "0.1.1" version = "0.1.1"
@ -276,6 +323,17 @@ dependencies = [
"proc-macro2", "proc-macro2",
] ]
[[package]]
name = "redox_users"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd6f9d3d47bdd2ad6945c5015a226ec6155d0bcdfd8f7cd29f86b71f8de99d2b"
dependencies = [
"getrandom",
"libredox",
"thiserror",
]
[[package]] [[package]]
name = "regex" name = "regex"
version = "1.11.1" version = "1.11.1"
@ -372,6 +430,26 @@ dependencies = [
"unicode-ident", "unicode-ident",
] ]
[[package]]
name = "thiserror"
version = "2.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d452f284b73e6d76dd36758a0c8684b1d5be31f92b89d07fd5822175732206fc"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "2.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "26afc1baea8a989337eeb52b6e72a039780ce45c3edfcc9c5b9d112feeb173c2"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]] [[package]]
name = "thread_local" name = "thread_local"
version = "1.1.8" version = "1.1.8"
@ -508,6 +586,12 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]] [[package]]
name = "winapi" name = "winapi"
version = "0.3.9" version = "0.3.9"

View File

@ -1,24 +1,15 @@
[workspace] [workspace]
members = ["crates/gitignore_inner", "."] members = ["crates/*"]
resolver = "2"
[workspace.package] [workspace.package]
version = "0.1.2" version = "0.4.0"
[package] [profile.release]
name = "kignore" opt-level = "z"
version.workspace = true lto = true
authors = ["Kasper J. Hermansen <contact@kjuulh.io>"] codegen-units = 1
license = "MIT" debug = false
readme = "README.md" panic = "abort"
keywords = ["git", "ignore", "clap", "interactive"] overflow-checks = false
repository = "https://github.com/kjuulh/gitignore" strip = true
documentation = "https://docs.rs/gitignore"
description = """
kignore is a tool for easily adding patterns to .gitignore and cleaning up afterwards
"""
categories = ["command-line-interface"]
edition = "2021"
[dependencies]
eyre = "0.6.12"
gitignore_inner = { path = "crates/gitignore_inner", version = "0.1.0" }

View File

@ -1 +0,0 @@
pkg/brew/

View File

@ -27,24 +27,22 @@ Cargo will only pull the `kignore` command and won't add a subcommand to `git.
```bash ```bash
$ cargo install kignore $ cargo install kignore
$ cargo binstall kignore # binstall will warn that git.front.kjuulh.io isn't a valid repo, it is still installable though
``` ```
#### Post install #### Post install
To get the `git ignore` subcommand working you will need to have the file To get the `git ignore` subcommand working you will need to have the file
git-ignore available on your path, either add it yourself using git-ignore available on your path
`git-alias/git-ignore` as a template or:
``` ```
git clone https://github.com/kjuulh/gitignore # zsh
./scripts/install-git-alias.sh # only tested on mac and linux eval "kignore init zsh"
```
# shell
### Homebrew eval "kignore init sh"
Added in HomebrewFormula # bash
eval "kignore init bash"
```bash
$ brew tap kjuulh/gitignore https://github.com/kjuulh/gitignore
$ brew install kjuulh/gitignore/kignore-bin
``` ```

View File

@ -1,33 +0,0 @@
#!/bin/bash
set -e
D="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"
# This script builds a binary dpkg for Debian based distros. It does not
# currently run in CI, and is instead run manually and the resulting dpkg is
# uploaded to GitHub via the web UI.
#
# Note that this requires 'cargo deb', which can be installed with
# 'cargo install cargo-deb'.
#
# This should be run from the root of the ripgrep repo.
if ! command -V cargo-deb > /dev/null 2>&1; then
echo "cargo-deb command missing" >&2
exit 1
fi
# 'cargo deb' does not seem to provide a way to specify an asset that is
# created at build time, such as ripgrep's man page. To work around this,
# we force a debug build, copy out the man page (and shell completions)
# produced from that build, put it into a predictable location and then build
# the deb, which knows where to look.
cargo build
DEPLOY_DIR=deployment/deb
OUT_DIR="$("$D"/cargo-out-dir target/debug/)"
mkdir -p "$DEPLOY_DIR"
# Since we're distributing the dpkg, we don't know whether the user will have
# PCRE2 installed, so just do a static build.
PCRE2_SYS_STATIC=1 cargo deb --target x86_64-unknown-linux-musl

View File

@ -1,14 +0,0 @@
#!/bin/bash
if [ $# != 1 ]; then
echo "Usage: $(basename "$0") <target-dir>" >&2
exit 2
fi
# This works by finding the most recent stamp file, which is produced by
# every ripgrep build.
target_dir="$1"
find "$target_dir" -name kignore-stamp -print0 \
| xargs -0 ls -t \
| head -n1 \
| xargs dirname

View File

@ -1,10 +0,0 @@
#!/bin/sh
if ! command -V sudo; then
apt-get update
apt-get install -y --no-install-recommends sudo
fi
sudo apt-get update
sudo apt-get install -y --no-install-recommends \
zsh xz-utils liblz4-tool musl-tools \
brotli zstd

View File

@ -1,191 +0,0 @@
use clap::{Arg, Command};
use eyre::{Context, ContextCompat};
use std::io::prelude::*;
use std::{env::current_dir, io::Read, path::PathBuf};
fn main() -> eyre::Result<()> {
let matches = Command::new("gitignore")
.version("0.1")
.author("Kasper J. Hermansen <contact@kjuulh.io>")
.about("Easily ignore items and remove from git state")
.long_about("git ignore is a utility tool for easily adding patterns to your .gitignore file.
Easily add patterns using `git ignore <pattern>` this will by default also help you remove committed code violating these patterns
")
.propagate_version(true)
.arg(
Arg::new("pattern")
.help("the pattern you want to ignore")
.long_help("the pattern you want to ignore in the nearest .gitignore file")
.required(true),
).arg(
Arg::new("log-level").long("log-level").help("choose a log level and get more messages").long_help("Choose a log level and get more message, defaults to [INFO]"))
.get_matches();
let pattern = matches
.get_one::<String>("pattern")
.context("missing [pattern]")?;
add_gitignore_pattern(pattern)
}
enum GitActions {
AddPattern {
git_path: PathBuf,
gitignore_path: PathBuf,
},
CreateIgnoreAndAddPattern {
git_path: PathBuf,
},
}
fn add_gitignore_pattern(pattern: &String) -> eyre::Result<()> {
let curdir = current_dir().context(
"could not find current_dir, you may not have permission to access that directory",
)?;
let actions = match search_for_dotgitignore(&curdir)? {
// If we have an ignore path, make sure it is in a git repo as well
GitSearchResult::GitIgnore(ignorepath) => match search_for_git_root(&curdir)? {
GitSearchResult::Git(gitpath) => GitActions::AddPattern {
git_path: gitpath,
gitignore_path: ignorepath,
},
_ => return Err(eyre::anyhow!("could not find parent git directory")),
},
// Find the nearest git repo
GitSearchResult::Git(gitpath) => {
GitActions::CreateIgnoreAndAddPattern { git_path: gitpath }
} // We will always have either above, or an error so we have no default arm
};
match actions {
GitActions::AddPattern {
git_path,
gitignore_path,
} => {
let mut gitignore_file = open_gitignore_file(&gitignore_path)?;
// TODO: search for pattern in file
let mut gitignore_content = String::new();
gitignore_file
.read_to_string(&mut gitignore_content)
.context(format!(
"could not read file: {}",
gitignore_path.to_string_lossy()
))?;
if gitignore_content.contains(pattern) {
return Ok(());
}
writeln!(gitignore_file, "{}", pattern).context("could not write contents to file")?;
gitignore_file
.sync_all()
.context("failed to write data to disk")?;
}
GitActions::CreateIgnoreAndAddPattern { git_path } => {
// TODO: Create gitignore file in root
let mut gitignore_file = create_gitignore_file(&git_path)?;
// TODO: do same as above
writeln!(gitignore_file, "{}", pattern).context("could not write contents to file")?;
gitignore_file
.sync_all()
.context("failed to write data to disk")?;
}
}
// TODO: Run git rm -r --cached on the .git root
Ok(())
}
fn create_gitignore_file(gitroot: &PathBuf) -> eyre::Result<std::fs::File> {
let mut ignore_path = gitroot.clone();
if !ignore_path.pop() {
return Err(eyre::anyhow!("could not open parent dir"));
}
ignore_path.push(".gitignore");
let file = std::fs::File::create(ignore_path.clone()).context(format!(
"could not create file at path: {}",
ignore_path.to_string_lossy()
))?;
Ok(file)
}
fn open_gitignore_file(gitignore: &PathBuf) -> eyre::Result<std::fs::File> {
let file = std::fs::OpenOptions::new()
.read(true)
.write(true)
.open(gitignore)
.context(format!(
"could not create file at path: {}",
gitignore.to_string_lossy()
))?;
return Ok(file);
}
enum GitSearchResult {
GitIgnore(PathBuf),
Git(PathBuf),
}
fn search_for_git_root(path: &PathBuf) -> eyre::Result<GitSearchResult> {
if !path.is_dir() {
return Err(eyre::anyhow!(
"path is not a dir: {}",
path.to_string_lossy()
));
}
let direntries = std::fs::read_dir(path)
.context(format!("could not open dir: {}", path.to_string_lossy()))?;
for direntry in direntries {
let entry = direntry.context("could not access file")?;
let file_name = entry.file_name().to_os_string();
match file_name.to_str().context("could not convert to str")? {
".git" => return Ok(GitSearchResult::Git(entry.path())),
_ => {}
}
}
let mut upwards_par = path.clone();
if !upwards_par.pop() {
return Err(eyre::anyhow!(
"no parent exists, cannot check further, you may not be in a git repository"
));
}
search_for_git_root(&upwards_par)
}
fn search_for_dotgitignore(path: &PathBuf) -> eyre::Result<GitSearchResult> {
if !path.is_dir() {
return Err(eyre::anyhow!(
"path is not a dir: {}",
path.to_string_lossy()
));
}
let direntries = std::fs::read_dir(path)
.context(format!("could not open dir: {}", path.to_string_lossy()))?;
for direntry in direntries {
let entry = direntry.context("could not access file")?;
let file_name = entry.file_name().to_os_string();
match file_name.to_str().context("could not convert to str")? {
".gitignore" => return Ok(GitSearchResult::GitIgnore(entry.path())),
".git" => return Ok(GitSearchResult::Git(entry.path())),
_ => {}
}
}
let mut upwards_par = path.clone();
if !upwards_par.pop() {
return Err(eyre::anyhow!(
"no parent exists, cannot check further, you may not be in a git repository"
));
}
search_for_dotgitignore(&upwards_par)
}

View File

@ -1,23 +1,25 @@
[package] [package]
name = "gitignore_inner" name = "kignore"
version.workspace = true version.workspace = true
edition = "2021"
authors = ["Kasper J. Hermansen <contact@kjuulh.io>"] authors = ["Kasper J. Hermansen <contact@kjuulh.io>"]
license = "MIT" license = "MIT"
readme = "../../README.md" readme = "../../README.md"
keywords = ["git", "ignore", "clap", "interactive"] keywords = ["git", "ignore", "clap", "interactive"]
repository = "https://github.com/kjuulh/gitignore" repository = "https://git.front.kjuulh.io/kjuulh/gitignore"
documentation = "https://docs.rs/gitignore" documentation = "https://docs.rs/kignore"
description = """ description = """
gitignore_inner is the internal module for cargo kignore is a tool for easily adding patterns to .gitignore and cleaning up afterwards
""" """
categories = ["command-line-interface"] categories = ["command-line-interface"]
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
clap = { version = "4.5.4", features = ["env", "unicode", "string"] } clap = { version = "4.5.4", features = ["env", "unicode", "string"] }
console = "0.15.8" console = "0.15.8"
dirs = "6.0.0"
eyre = "0.6.12" eyre = "0.6.12"
tracing = { version = "0.1.40", features = ["log"] } tracing = { version = "0.1.40", features = ["log"] }
tracing-subscriber = { version = "0.3.18", features = [ tracing-subscriber = { version = "0.3.18", features = [

View File

@ -1,52 +1,102 @@
use clap::{Arg, Command}; use clap::{Arg, Command};
use eyre::{Context, ContextCompat}; use console::style;
use eyre::{Context, ContextCompat, OptionExt};
use std::io::prelude::*; use std::io::prelude::*;
use std::os::unix::fs::PermissionsExt;
use std::{env::current_dir, io::Read, path::PathBuf}; use std::{env::current_dir, io::Read, path::PathBuf};
use tracing_subscriber::layer::SubscriberExt; use tracing_subscriber::layer::SubscriberExt;
use tracing_subscriber::util::SubscriberInitExt; use tracing_subscriber::util::SubscriberInitExt;
const ZSH_FILE_CONTENTS: &[u8] = b"#!/usr/bin/env zsh
set -e
kignore $@
";
const SH_FILE_CONTENTS: &[u8] = b"#!/usr/bin/env sh
set -e
kignore $@
";
const BASH_FILE_CONTENTS: &[u8] = b"#!/usr/bin/env bash
set -e
kignore $@
";
pub fn main() -> eyre::Result<()> { pub fn main() -> eyre::Result<()> {
let matches = Command::new("gitignore") let matches = Command::new("gitignore")
.version("0.1") .version("0.1")
.author("Kasper J. Hermansen <contact@kjuulh.io>") .author("Kasper J. Hermansen <contact@kjuulh.io>")
.about("Easily ignore items and remove from git state") .about("Easily ignore items and remove from git state")
.long_about("git ignore is a utility tool for easily adding patterns to your .gitignore file. .long_about(
Easily add patterns using `git ignore <pattern>` this will by default also help you remove committed code violating these patterns "git ignore is a utility tool for easily adding patterns to your .gitignore file.
") Easily add patterns using `git ignore <pattern>` this will by default
also help you remove committed code violating these patterns
",
)
.propagate_version(true) .propagate_version(true)
.arg( .arg(
Arg::new("pattern") Arg::new("pattern")
.help("the pattern you want to ignore") .help("the pattern you want to ignore")
.long_help("the pattern you want to ignore in the nearest .gitignore file") .long_help("the pattern you want to ignore in the nearest .gitignore file"),
.required(true), )
).arg( .arg(
Arg::new("log-level").long("log-level").help("choose a log level and get more messages").long_help("Choose a log level and get more message, defaults to [fatal]")) Arg::new("log-level")
.long("log-level")
.default_value("warn")
.help("choose a log level and get more messages")
.long_help("Choose a log level and get more message, defaults to [warn]"),
)
.subcommand(
clap::Command::new("init")
.subcommand_required(true)
.subcommand(Command::new("zsh"))
.subcommand(Command::new("sh"))
.subcommand(Command::new("bash")),
)
.get_matches(); .get_matches();
let log_level = match matches.get_one::<String>("log-level").map(|f| f.as_str()) { match matches.subcommand() {
Some("off") => "off", Some(("init", args)) => match args
Some("info") => "info", .subcommand()
Some("debug") => "debug", .expect("should never be able to call on init")
Some("warn") => "warn", {
Some("error") => "error", ("zsh", _) => init_script(ShellType::Zsh),
_ => "error", ("bash", _) => init_script(ShellType::Bash),
}; ("sh", _) => init_script(ShellType::Shell),
(subcommand, _) => {
panic!("cannot call on subcommand: {}", subcommand);
}
},
_ => {
let log_level = match matches.get_one::<String>("log-level").map(|f| f.as_str()) {
Some("off") => "off",
Some("info") => "info",
Some("debug") => "debug",
Some("warn") => "warn",
Some("error") => "error",
_ => "error",
};
tracing_subscriber::registry() tracing_subscriber::registry()
.with(tracing_subscriber::EnvFilter::new(format!( .with(tracing_subscriber::EnvFilter::new(format!(
"gitignore={}", "gitignore={}",
log_level log_level
))) )))
.with(tracing_subscriber::fmt::layer()) .with(tracing_subscriber::fmt::layer())
.init(); .init();
let term = console::Term::stdout(); let term = console::Term::stdout();
let pattern = matches let pattern = matches
.get_one::<String>("pattern") .get_one::<String>("pattern")
.context("missing [pattern]")?; .context("missing [pattern]")?;
add_gitignore_pattern(term, pattern) add_gitignore_pattern(term, pattern)
}
}
} }
enum GitActions { enum GitActions {
@ -55,7 +105,7 @@ enum GitActions {
} }
fn add_gitignore_pattern(term: console::Term, pattern: &String) -> eyre::Result<()> { fn add_gitignore_pattern(term: console::Term, pattern: &String) -> eyre::Result<()> {
term.write_line("git ignore: Add pattern")?; println!("git ignore: Add pattern");
let curdir = current_dir().context( let curdir = current_dir().context(
"could not find current_dir, you may not have permission to access that directory", "could not find current_dir, you may not have permission to access that directory",
)?; )?;
@ -75,7 +125,7 @@ fn add_gitignore_pattern(term: console::Term, pattern: &String) -> eyre::Result<
match actions { match actions {
GitActions::AddPattern { gitignore_path } => { GitActions::AddPattern { gitignore_path } => {
term.write_line("Found existing .gitignore")?; println!("Found existing {}", style(".gitignore").green());
let mut gitignore_file = open_gitignore_file(&gitignore_path)?; let mut gitignore_file = open_gitignore_file(&gitignore_path)?;
let mut gitignore_content = String::new(); let mut gitignore_content = String::new();
gitignore_file gitignore_file
@ -85,22 +135,26 @@ fn add_gitignore_pattern(term: console::Term, pattern: &String) -> eyre::Result<
gitignore_path.to_string_lossy() gitignore_path.to_string_lossy()
))?; ))?;
if gitignore_content.contains(pattern) { if gitignore_content.contains(pattern) {
term.write_line(".gitignore already contains pattern, skipping")?; println!(
".gitignore already contains pattern, {}",
style("skipping...").blue()
);
return Ok(()); return Ok(());
} }
term.write_line("adding pattern to file")?; println!("adding pattern to file");
writeln!(gitignore_file, "{}", pattern).context("could not write contents to file")?; writeln!(gitignore_file, "{}", pattern).context("could not write contents to file")?;
gitignore_file gitignore_file
.sync_all() .sync_all()
.context("failed to write data to disk")?; .context("failed to write data to disk")?;
} }
GitActions::CreateIgnoreAndAddPattern { git_path } => { GitActions::CreateIgnoreAndAddPattern { git_path } => {
term.write_line( println!(
"could not find .gitignore file, creating one in the root of the git repository", "could not find {} file, creating one in the root of the git repository",
)?; style(".gitignore").yellow()
);
let mut gitignore_file = create_gitignore_file(git_path)?; let mut gitignore_file = create_gitignore_file(git_path)?;
term.write_line("adding pattern to file")?; println!("adding pattern to file");
writeln!(gitignore_file, "{}", pattern).context("could not write contents to file")?; writeln!(gitignore_file, "{}", pattern).context("could not write contents to file")?;
gitignore_file gitignore_file
.sync_all() .sync_all()
@ -121,8 +175,19 @@ fn add_gitignore_pattern(term: console::Term, pattern: &String) -> eyre::Result<
String::from_utf8(output.stdout)? String::from_utf8(output.stdout)?
.lines() .lines()
.chain(String::from_utf8(output.stderr)?.lines()) .chain(String::from_utf8(output.stderr)?.lines())
.try_for_each(|l| term.write_line(l)) .map(|l| {
.context("could not print all output to terminal")?; // make rm 'path' look nice
if l.contains("rm") {
if let Some((_, pruned_first)) = l.split_once("'") {
if let Some((content, _)) = pruned_first.rsplit_once("'") {
return content;
}
}
}
l
})
.for_each(|l| println!("removed from git history: {}", style(l).yellow()));
if !output.status.success() { if !output.status.success() {
return Err(eyre::anyhow!("failed to run git index command")); return Err(eyre::anyhow!("failed to run git index command"));
@ -235,3 +300,50 @@ fn search_for_dotgitignore(path: &PathBuf) -> eyre::Result<GitSearchResult> {
search_for_dotgitignore(&upwards_par) search_for_dotgitignore(&upwards_par)
} }
enum ShellType {
Bash,
Shell,
Zsh,
}
fn init_script(shell: ShellType) -> eyre::Result<()> {
let bin_dir = dirs::executable_dir().ok_or_eyre("failed to find executable dir")?;
let script = match shell {
ShellType::Bash => BASH_FILE_CONTENTS,
ShellType::Shell => SH_FILE_CONTENTS,
ShellType::Zsh => ZSH_FILE_CONTENTS,
};
let alias_script = bin_dir.join("git-ignore");
if let Ok(existing_file) = std::fs::read(&alias_script) {
if existing_file == script {
return Ok(());
}
} else {
std::fs::create_dir_all(&bin_dir).context("failed to create bin dir")?;
}
let mut file = std::fs::OpenOptions::new()
.write(true)
.create(true)
.truncate(true)
.open(&alias_script)?;
file.write_all(script)?;
file.flush()?;
// Set the file to be executable
let metadata = file.metadata()?;
let mut permissions = metadata.permissions();
permissions.set_mode(0o755); // rwxr-xr-x
file.set_permissions(permissions)?;
println!(
"successfully wrote alias to {}",
style(alias_script.display()).green()
);
Ok(())
}

View File

@ -6,6 +6,9 @@ vars:
service: "kignore" service: "kignore"
registry: kasperhermansen registry: kasperhermansen
rust:
publish: {}
please: please:
project: project:
owner: kjuulh owner: kjuulh

View File

@ -1,5 +0,0 @@
#!/usr/bin/env sh
set -e
kignore $@

View File

@ -1,17 +0,0 @@
class KignoreBin < Formula
desc "Easily add items to .gitignore and cleanup afterwards"
homepage "https://github.com/kjuulh/gitignore"
version "0.1.3"
license "MIT"
if OS.mac?
url "https://github.com/kjuulh/gitignore/releases/download/#{version}/kignore-#{version}-x86_64-apple-darwin.tar.gz"
sha256 "fa4e520854f0cc8222625b0398c778d4f474dd7a9ad1da1dd9a326ff7893bd44"
end
def install
bin.install "kignore"
bin.install "git-ignore"
end
end

View File

@ -1,8 +0,0 @@
#!/usr/bin/env bash
set -e
mkdir ~/.git-bins
cp git-alias/git-ignore ~/.git-bins/git-ignore
echo "Make sure to add ~/.git-bins to your PATH"

View File

@ -1,3 +0,0 @@
fn main() -> eyre::Result<()> {
gitignore_inner::main()
}