Compare commits
8 Commits
4c4cd837fe
...
v0.1.0
Author | SHA1 | Date | |
---|---|---|---|
5d372f87cb
|
|||
cf2722feee
|
|||
42c87cf6e5
|
|||
39904c22c1
|
|||
9594c3b5aa
|
|||
8e44310c41
|
|||
b8d5a81436 | |||
5b77ec39e8 |
85
.gitea/workflows/linting.yaml
Normal file
85
.gitea/workflows/linting.yaml
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
name: Code style
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
pull_request:
|
||||||
|
|
||||||
|
env:
|
||||||
|
CARGO_TERM_COLOR: always
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
cargo-check:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout source code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Setup rust
|
||||||
|
uses: actions-rs/toolchain@v1
|
||||||
|
with:
|
||||||
|
toolchain: stable
|
||||||
|
components: rustfmt,clippy
|
||||||
|
|
||||||
|
# Cache cargo registry
|
||||||
|
- name: Hash the lock file
|
||||||
|
uses: https://gitea.com/seepine/hash-files@v1
|
||||||
|
id: get-hash
|
||||||
|
with:
|
||||||
|
patterns: |
|
||||||
|
**/Cargo.lock
|
||||||
|
- name: Cache cargo registry
|
||||||
|
uses: actions/cache@v3
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
~/.cargo/bin/
|
||||||
|
~/.cargo/registry/index/
|
||||||
|
~/.cargo/registry/cache/
|
||||||
|
~/.cargo/git/db/
|
||||||
|
target/
|
||||||
|
key: cargo-${{ steps.get-hash.outputs.hash }}
|
||||||
|
restore-keys: |
|
||||||
|
cargo-
|
||||||
|
# Cache cargo registry - end
|
||||||
|
|
||||||
|
- name: Cargo check
|
||||||
|
uses: actions-rs/cargo@v1
|
||||||
|
with:
|
||||||
|
command: check
|
||||||
|
|
||||||
|
clippy:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout source code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Setup rust
|
||||||
|
uses: actions-rs/toolchain@v1
|
||||||
|
with:
|
||||||
|
toolchain: stable
|
||||||
|
components: rustfmt,clippy
|
||||||
|
|
||||||
|
# Cache cargo registry
|
||||||
|
- name: Hash the lock file
|
||||||
|
uses: https://gitea.com/seepine/hash-files@v1
|
||||||
|
id: get-hash
|
||||||
|
with:
|
||||||
|
patterns: |
|
||||||
|
**/Cargo.lock
|
||||||
|
- name: Cache cargo registry
|
||||||
|
uses: actions/cache@v3
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
~/.cargo/bin/
|
||||||
|
~/.cargo/registry/index/
|
||||||
|
~/.cargo/registry/cache/
|
||||||
|
~/.cargo/git/db/
|
||||||
|
target/
|
||||||
|
key: cargo-${{ steps.get-hash.outputs.hash }}
|
||||||
|
restore-keys: |
|
||||||
|
cargo-
|
||||||
|
# Cache cargo registry - end
|
||||||
|
|
||||||
|
- name: Run clippy
|
||||||
|
uses: actions-rs/clippy-check@v1
|
||||||
|
with:
|
||||||
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
args: --all-targets --all-features -- -Dwarnings
|
68
.gitea/workflows/release-package.yaml
Normal file
68
.gitea/workflows/release-package.yaml
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
---
|
||||||
|
name: Release packages
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- 'v*'
|
||||||
|
|
||||||
|
env:
|
||||||
|
CARGO_TERM_COLOR: always
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-and-release-artifact:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Setup rust
|
||||||
|
uses: actions-rs/toolchain@v1
|
||||||
|
with:
|
||||||
|
profile: minimal
|
||||||
|
toolchain: stable
|
||||||
|
|
||||||
|
# Cache cargo registry
|
||||||
|
- name: Hash the lock file
|
||||||
|
uses: https://gitea.com/seepine/hash-files@v1
|
||||||
|
id: get-hash
|
||||||
|
with:
|
||||||
|
patterns: |
|
||||||
|
**/Cargo.lock
|
||||||
|
- name: Cache cargo registry
|
||||||
|
uses: actions/cache@v4
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
~/.cargo/bin/
|
||||||
|
~/.cargo/registry/index/
|
||||||
|
~/.cargo/registry/cache/
|
||||||
|
~/.cargo/git/db/
|
||||||
|
target/
|
||||||
|
key: cargo-${{ steps.get-hash.outputs.hash }}
|
||||||
|
restore-keys: |
|
||||||
|
cargo-
|
||||||
|
# Cache cargo registry - end
|
||||||
|
|
||||||
|
- name: Build application
|
||||||
|
uses: actions-rs/cargo@v1
|
||||||
|
with:
|
||||||
|
command: build
|
||||||
|
args: --release --all-features --workspace --all-targets
|
||||||
|
|
||||||
|
- name: Package application
|
||||||
|
uses: actions-rs/cargo@v1
|
||||||
|
with:
|
||||||
|
command: package
|
||||||
|
args: --all-features --workspace --allow-dirty
|
||||||
|
|
||||||
|
- name: Add registry to cargo config
|
||||||
|
run: echo -e '[registries.gitea]\nindex = "sparse+https://git.noahknegt.com/api/packages/${{ github.repository_owner }}/cargo/"\n' > ~/.cargo/config.toml
|
||||||
|
|
||||||
|
- name: Publish to cargo registry
|
||||||
|
uses: actions-rs/cargo@v1
|
||||||
|
with:
|
||||||
|
command: publish
|
||||||
|
args: --no-verify --registry gitea --token ${{ secrets.CARGO_REGISTRY_TOKEN }}
|
||||||
|
env:
|
||||||
|
CARGO_NET_GIT_FETCH_WITH_CLI: true
|
||||||
|
CARGO_NET_RETRY: 2
|
||||||
|
CARGO_NET_TIMEOUT: 120
|
2
.gitignore
vendored
2
.gitignore
vendored
@@ -6,7 +6,7 @@ target/
|
|||||||
|
|
||||||
# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
|
# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
|
||||||
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
|
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
|
||||||
Cargo.lock
|
# Cargo.lock
|
||||||
|
|
||||||
# These are backup files generated by rustfmt
|
# These are backup files generated by rustfmt
|
||||||
**/*.rs.bk
|
**/*.rs.bk
|
||||||
|
517
Cargo.lock
generated
Normal file
517
Cargo.lock
generated
Normal file
@@ -0,0 +1,517 @@
|
|||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 4
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstream"
|
||||||
|
version = "0.6.18"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b"
|
||||||
|
dependencies = [
|
||||||
|
"anstyle",
|
||||||
|
"anstyle-parse",
|
||||||
|
"anstyle-query",
|
||||||
|
"anstyle-wincon",
|
||||||
|
"colorchoice",
|
||||||
|
"is_terminal_polyfill",
|
||||||
|
"utf8parse",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstyle"
|
||||||
|
version = "1.0.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstyle-parse"
|
||||||
|
version = "0.2.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9"
|
||||||
|
dependencies = [
|
||||||
|
"utf8parse",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstyle-query"
|
||||||
|
version = "1.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c"
|
||||||
|
dependencies = [
|
||||||
|
"windows-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anstyle-wincon"
|
||||||
|
version = "3.0.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ca3534e77181a9cc07539ad51f2141fe32f6c3ffd4df76db8ad92346b003ae4e"
|
||||||
|
dependencies = [
|
||||||
|
"anstyle",
|
||||||
|
"once_cell",
|
||||||
|
"windows-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anyhow"
|
||||||
|
version = "1.0.98"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bitflags"
|
||||||
|
version = "2.9.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bumpalo"
|
||||||
|
version = "3.17.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cfg-if"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clap"
|
||||||
|
version = "4.5.37"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "eccb054f56cbd38340b380d4a8e69ef1f02f1af43db2f0cc817a4774d80ae071"
|
||||||
|
dependencies = [
|
||||||
|
"clap_builder",
|
||||||
|
"clap_derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clap_builder"
|
||||||
|
version = "4.5.37"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "efd9466fac8543255d3b1fcad4762c5e116ffe808c8a3043d4263cd4fd4862a2"
|
||||||
|
dependencies = [
|
||||||
|
"anstream",
|
||||||
|
"anstyle",
|
||||||
|
"clap_lex",
|
||||||
|
"strsim",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clap_derive"
|
||||||
|
version = "4.5.32"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "09176aae279615badda0765c0c0b3f6ed53f4709118af73cf4655d85d1530cd7"
|
||||||
|
dependencies = [
|
||||||
|
"heck",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clap_lex"
|
||||||
|
version = "0.7.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "colorchoice"
|
||||||
|
version = "1.0.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "colored"
|
||||||
|
version = "3.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fde0e0ec90c9dfb3b4b1a0891a7dcd0e2bffde2f7efed5fe7c9bb00e5bfb915e"
|
||||||
|
dependencies = [
|
||||||
|
"windows-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "console"
|
||||||
|
version = "0.15.11"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "054ccb5b10f9f2cbf51eb355ca1d05c2d279ce1804688d0db74b4733a5aeafd8"
|
||||||
|
dependencies = [
|
||||||
|
"encode_unicode",
|
||||||
|
"libc",
|
||||||
|
"once_cell",
|
||||||
|
"unicode-width",
|
||||||
|
"windows-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "create-worktree"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"clap",
|
||||||
|
"colored",
|
||||||
|
"dirs",
|
||||||
|
"indicatif",
|
||||||
|
"thiserror",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[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]]
|
||||||
|
name = "encode_unicode"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "getrandom"
|
||||||
|
version = "0.2.16"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"wasi",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "heck"
|
||||||
|
version = "0.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "indicatif"
|
||||||
|
version = "0.17.11"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "183b3088984b400f4cfac3620d5e076c84da5364016b4f49473de574b2586235"
|
||||||
|
dependencies = [
|
||||||
|
"console",
|
||||||
|
"number_prefix",
|
||||||
|
"portable-atomic",
|
||||||
|
"unicode-width",
|
||||||
|
"web-time",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "is_terminal_polyfill"
|
||||||
|
version = "1.70.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "js-sys"
|
||||||
|
version = "0.3.77"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f"
|
||||||
|
dependencies = [
|
||||||
|
"once_cell",
|
||||||
|
"wasm-bindgen",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libc"
|
||||||
|
version = "0.2.172"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libredox"
|
||||||
|
version = "0.1.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "log"
|
||||||
|
version = "0.4.27"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "number_prefix"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "once_cell"
|
||||||
|
version = "1.21.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "option-ext"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "portable-atomic"
|
||||||
|
version = "1.11.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "350e9b48cbc6b0e028b0473b114454c6316e57336ee184ceab6e53f72c178b3e"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro2"
|
||||||
|
version = "1.0.95"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quote"
|
||||||
|
version = "1.0.40"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
|
||||||
|
dependencies = [
|
||||||
|
"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]]
|
||||||
|
name = "setup-repo"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"clap",
|
||||||
|
"colored",
|
||||||
|
"indicatif",
|
||||||
|
"thiserror",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "strsim"
|
||||||
|
version = "0.11.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "2.0.101"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8ce2b7fc941b3a24138a0a7cf8e858bfc6a992e7978a068a5c760deb0ed43caf"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thiserror"
|
||||||
|
version = "2.0.12"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708"
|
||||||
|
dependencies = [
|
||||||
|
"thiserror-impl",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "thiserror-impl"
|
||||||
|
version = "2.0.12"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-ident"
|
||||||
|
version = "1.0.18"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-width"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1fc81956842c57dac11422a97c3b8195a1ff727f06e85c84ed2e8aa277c9a0fd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "utf8parse"
|
||||||
|
version = "0.2.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasi"
|
||||||
|
version = "0.11.0+wasi-snapshot-preview1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen"
|
||||||
|
version = "0.2.100"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"once_cell",
|
||||||
|
"wasm-bindgen-macro",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen-backend"
|
||||||
|
version = "0.2.100"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6"
|
||||||
|
dependencies = [
|
||||||
|
"bumpalo",
|
||||||
|
"log",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
"wasm-bindgen-shared",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen-macro"
|
||||||
|
version = "0.2.100"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407"
|
||||||
|
dependencies = [
|
||||||
|
"quote",
|
||||||
|
"wasm-bindgen-macro-support",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen-macro-support"
|
||||||
|
version = "0.2.100"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
"wasm-bindgen-backend",
|
||||||
|
"wasm-bindgen-shared",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasm-bindgen-shared"
|
||||||
|
version = "0.2.100"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-ident",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "web-time"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb"
|
||||||
|
dependencies = [
|
||||||
|
"js-sys",
|
||||||
|
"wasm-bindgen",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-sys"
|
||||||
|
version = "0.59.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
|
||||||
|
dependencies = [
|
||||||
|
"windows-targets",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-targets"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
|
||||||
|
dependencies = [
|
||||||
|
"windows_aarch64_gnullvm",
|
||||||
|
"windows_aarch64_msvc",
|
||||||
|
"windows_i686_gnu",
|
||||||
|
"windows_i686_gnullvm",
|
||||||
|
"windows_i686_msvc",
|
||||||
|
"windows_x86_64_gnu",
|
||||||
|
"windows_x86_64_gnullvm",
|
||||||
|
"windows_x86_64_msvc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_gnullvm"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_msvc"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_gnu"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_gnullvm"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_msvc"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnu"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnullvm"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_msvc"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
13
Cargo.toml
Normal file
13
Cargo.toml
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
[workspace]
|
||||||
|
resolver = "3"
|
||||||
|
members = [
|
||||||
|
"create-worktree",
|
||||||
|
"setup-repo",
|
||||||
|
]
|
||||||
|
|
||||||
|
package.edition = "2024"
|
||||||
|
package.authors = [
|
||||||
|
"Noah Knegt <personal@noahknegt.com>"
|
||||||
|
]
|
||||||
|
package.license-file = "LICENSE"
|
||||||
|
package.repository = "https://git.noahknegt.com/noah.knegt/repo-utils"
|
@@ -1,3 +1,3 @@
|
|||||||
# repo-utils
|
# repo-utils
|
||||||
|
|
||||||
Rust tools that help manage repositories and worktrees
|
Rust tools that help manage repositories and worktrees
|
||||||
|
17
create-worktree/Cargo.toml
Normal file
17
create-worktree/Cargo.toml
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
[package]
|
||||||
|
name = "create-worktree"
|
||||||
|
version = "0.1.0"
|
||||||
|
description = "A tool to create git worktrees with convenient branch management"
|
||||||
|
|
||||||
|
edition.workspace = true
|
||||||
|
authors.workspace = true
|
||||||
|
license-file.workspace = true
|
||||||
|
repository.workspace = true
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
clap = { version = "4.5", features = ["derive"] }
|
||||||
|
anyhow = "1.0"
|
||||||
|
colored = "3.0"
|
||||||
|
indicatif = "0.17"
|
||||||
|
dirs = "6.0"
|
||||||
|
thiserror = { version = "2.0" }
|
231
create-worktree/src/main.rs
Normal file
231
create-worktree/src/main.rs
Normal file
@@ -0,0 +1,231 @@
|
|||||||
|
use std::env;
|
||||||
|
use std::path::Path;
|
||||||
|
use std::process::{Command, Stdio};
|
||||||
|
|
||||||
|
use anyhow::{Context, Result};
|
||||||
|
use clap::{ArgAction, Parser};
|
||||||
|
use colored::*;
|
||||||
|
use indicatif::{ProgressBar, ProgressStyle};
|
||||||
|
|
||||||
|
/// Tool to create git worktrees with convenient branch management
|
||||||
|
#[derive(Parser, Debug)]
|
||||||
|
#[command(author, version, about)]
|
||||||
|
struct Args {
|
||||||
|
/// Path for the new worktree
|
||||||
|
worktree: String,
|
||||||
|
|
||||||
|
/// Branch to create
|
||||||
|
#[arg(short, long)]
|
||||||
|
branch: Option<String>,
|
||||||
|
|
||||||
|
/// Base branch to use for the new worktree
|
||||||
|
#[arg(short = 'B', long, default_value = "origin/main")]
|
||||||
|
base: String,
|
||||||
|
|
||||||
|
/// Prefix to apply to the branch name
|
||||||
|
#[arg(short, long, default_value = "")]
|
||||||
|
prefix: String,
|
||||||
|
|
||||||
|
/// Do not create an upstream branch
|
||||||
|
#[arg(short = 'N', long, action = ArgAction::SetFalse)]
|
||||||
|
no_create_upstream: bool,
|
||||||
|
|
||||||
|
/// Enable verbose output
|
||||||
|
#[arg(short, long)]
|
||||||
|
verbose: bool,
|
||||||
|
|
||||||
|
/// Disable colored output
|
||||||
|
#[arg(long)]
|
||||||
|
no_color: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Git operations error type
|
||||||
|
#[derive(Debug, thiserror::Error)]
|
||||||
|
enum GitError {
|
||||||
|
#[error("Command failed with exit code: {0}")]
|
||||||
|
Failed(i32),
|
||||||
|
|
||||||
|
#[error("Command failed without exit code")]
|
||||||
|
FailedNoCode,
|
||||||
|
|
||||||
|
#[error("Failed to execute command: {0}")]
|
||||||
|
ExecutionError(#[from] std::io::Error),
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Runs a git command with a progress spinner
|
||||||
|
fn run_command(command: &mut Command, message: &str) -> Result<()> {
|
||||||
|
let spinner = ProgressBar::new_spinner();
|
||||||
|
spinner.set_style(
|
||||||
|
ProgressStyle::default_spinner()
|
||||||
|
.tick_chars("⣾⣽⣻⢿⡿⣟⣯⣷")
|
||||||
|
.template("{spinner:.green} {msg}")
|
||||||
|
.expect("Invalid template format"),
|
||||||
|
);
|
||||||
|
spinner.set_message(message.to_string());
|
||||||
|
|
||||||
|
// Configure the command to not show output
|
||||||
|
command.stdout(Stdio::null()).stderr(Stdio::null());
|
||||||
|
|
||||||
|
// Execute the command and wait for it to complete
|
||||||
|
spinner.enable_steady_tick(std::time::Duration::from_millis(100));
|
||||||
|
|
||||||
|
let status = command.status().context("Failed to execute command")?;
|
||||||
|
spinner.finish_and_clear();
|
||||||
|
|
||||||
|
if status.success() {
|
||||||
|
println!("{message} {}", "Done.".green());
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
println!("{message} {}", "FAILED.".red());
|
||||||
|
|
||||||
|
let code = status.code();
|
||||||
|
match code {
|
||||||
|
Some(code) => Err(GitError::Failed(code).into()),
|
||||||
|
None => Err(GitError::FailedNoCode.into()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Git command wrapper
|
||||||
|
struct Git;
|
||||||
|
|
||||||
|
impl Git {
|
||||||
|
/// Check if a branch exists locally
|
||||||
|
fn branch_exists_locally(branch: &str) -> Result<bool> {
|
||||||
|
let output = Command::new("git")
|
||||||
|
.args([
|
||||||
|
"branch",
|
||||||
|
"--list",
|
||||||
|
branch
|
||||||
|
])
|
||||||
|
.output()
|
||||||
|
.context("Failed to check branch existence")?;
|
||||||
|
|
||||||
|
Ok(!output.stdout.is_empty())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Check if a branch exists on the remote
|
||||||
|
fn branch_exists_on_remote(branch: &str) -> Result<bool> {
|
||||||
|
let output = Command::new("git")
|
||||||
|
.args([
|
||||||
|
"ls-remote",
|
||||||
|
"--heads",
|
||||||
|
"origin",
|
||||||
|
branch
|
||||||
|
])
|
||||||
|
.output()
|
||||||
|
.context("Failed to check remote branch existence")?;
|
||||||
|
|
||||||
|
Ok(!output.stdout.is_empty())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a new worktree with an existing branch
|
||||||
|
fn create_worktree_existing_branch(worktree_path: &str, branch: &str) -> Result<()> {
|
||||||
|
let mut cmd = Command::new("git");
|
||||||
|
cmd.args([
|
||||||
|
"worktree",
|
||||||
|
"add",
|
||||||
|
worktree_path,
|
||||||
|
branch
|
||||||
|
]);
|
||||||
|
run_command(&mut cmd, &format!("Generating new worktree from existing branch: {branch}"))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a new worktree with a new branch
|
||||||
|
fn create_worktree_new_branch(worktree_path: &str, branch: &str, base: &str) -> Result<()> {
|
||||||
|
let mut cmd = Command::new("git");
|
||||||
|
cmd.args([
|
||||||
|
"worktree",
|
||||||
|
"add",
|
||||||
|
"-b", branch,
|
||||||
|
worktree_path,
|
||||||
|
base
|
||||||
|
]);
|
||||||
|
run_command(&mut cmd, &format!("Generating new worktree: {worktree_path}"))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create and push a new remote branch
|
||||||
|
fn create_remote_branch(branch: &str) -> Result<()> {
|
||||||
|
let mut cmd = Command::new("git");
|
||||||
|
cmd.args([
|
||||||
|
"push",
|
||||||
|
"-u", "origin",
|
||||||
|
branch
|
||||||
|
]);
|
||||||
|
run_command(&mut cmd, &format!("Creating remote branch {branch}..."))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set the upstream branch
|
||||||
|
fn set_upstream_branch(branch: &str) -> Result<()> {
|
||||||
|
let mut cmd = Command::new("git");
|
||||||
|
cmd.args([
|
||||||
|
"branch",
|
||||||
|
"--set-upstream-to", &format!("origin/{branch}")
|
||||||
|
]);
|
||||||
|
run_command(&mut cmd, &format!("Setting upstream branch to 'origin/{branch}'"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Update or create the remote tracking branch
|
||||||
|
fn update_remote(branch: &str, create_upstream: bool) -> Result<()> {
|
||||||
|
// Do nothing if create_upstream is disabled
|
||||||
|
if !create_upstream {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if branch exists on remote
|
||||||
|
let has_remote = Git::branch_exists_on_remote(branch)?;
|
||||||
|
|
||||||
|
if !has_remote {
|
||||||
|
// Create remote branch
|
||||||
|
println!("{}", format!("Branch '{branch}' does not exist on remote. Creating.").dimmed());
|
||||||
|
Git::set_upstream_branch(branch)?;
|
||||||
|
// Git::create_remote_branch(branch)?;
|
||||||
|
} else {
|
||||||
|
println!("{}", format!("Branch '{branch}' exists. Setting upstream.").dimmed());
|
||||||
|
Git::set_upstream_branch(branch)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() -> Result<()> {
|
||||||
|
// Parse arguments
|
||||||
|
let args = Args::parse();
|
||||||
|
|
||||||
|
// Enable or disable colored output
|
||||||
|
colored::control::set_override(!args.no_color);
|
||||||
|
|
||||||
|
// Print verbose information if enabled
|
||||||
|
if args.verbose {
|
||||||
|
println!("{}", "Verbose mode enabled".dimmed());
|
||||||
|
println!("{}", format!("Base branch: {}", args.base).dimmed());
|
||||||
|
println!("{}", format!("Create upstream: {}", args.no_create_upstream).dimmed());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determine branch name if not specified
|
||||||
|
let branch = args.branch.unwrap_or_else(|| format!("{}{}", args.prefix, args.worktree));
|
||||||
|
|
||||||
|
// Normalize paths
|
||||||
|
let worktree_path = Path::new(&args.worktree).to_string_lossy();
|
||||||
|
|
||||||
|
// Check if branch already exists
|
||||||
|
let branch_exists = Git::branch_exists_locally(&branch)?;
|
||||||
|
|
||||||
|
// Create the worktree
|
||||||
|
if branch_exists {
|
||||||
|
Git::create_worktree_existing_branch(&args.worktree, &branch)?;
|
||||||
|
} else {
|
||||||
|
Git::create_worktree_new_branch(&args.worktree, &branch, &args.base)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Change to worktree directory
|
||||||
|
println!("{}", format!("Moving into worktree: {worktree_path}").dimmed());
|
||||||
|
env::set_current_dir(&args.worktree).context("Failed to change directory")?;
|
||||||
|
|
||||||
|
// Update remote
|
||||||
|
update_remote(&branch, args.no_create_upstream)?;
|
||||||
|
|
||||||
|
println!("{}", "Success.".green());
|
||||||
|
Ok(())
|
||||||
|
}
|
16
setup-repo/Cargo.toml
Normal file
16
setup-repo/Cargo.toml
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
[package]
|
||||||
|
name = "setup-repo"
|
||||||
|
version = "0.1.0"
|
||||||
|
description = "Tool to set up Git repositories for worktree development"
|
||||||
|
|
||||||
|
edition.workspace = true
|
||||||
|
authors.workspace = true
|
||||||
|
license-file.workspace = true
|
||||||
|
repository.workspace = true
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
anyhow = "1.0"
|
||||||
|
clap = { version = "4.5", features = ["derive"] }
|
||||||
|
colored = "3.0"
|
||||||
|
indicatif = "0.17"
|
||||||
|
thiserror = "2.0"
|
168
setup-repo/src/main.rs
Normal file
168
setup-repo/src/main.rs
Normal file
@@ -0,0 +1,168 @@
|
|||||||
|
use std::path::Path;
|
||||||
|
use std::process::{Command, Stdio};
|
||||||
|
|
||||||
|
use anyhow::{Context, Result};
|
||||||
|
use clap::Parser;
|
||||||
|
use colored::*;
|
||||||
|
use indicatif::{ProgressBar, ProgressStyle};
|
||||||
|
|
||||||
|
/// Tool to set up Git repositories for worktree development
|
||||||
|
#[derive(Parser, Debug)]
|
||||||
|
#[command(author, version, about)]
|
||||||
|
struct Args {
|
||||||
|
/// Repository URL to clone
|
||||||
|
#[arg(short, long)]
|
||||||
|
repo_url: String,
|
||||||
|
|
||||||
|
/// Target directory for the repository setup
|
||||||
|
#[arg(short, long)]
|
||||||
|
target_dir: String,
|
||||||
|
|
||||||
|
/// Enable verbose output
|
||||||
|
#[arg(short, long)]
|
||||||
|
verbose: bool,
|
||||||
|
|
||||||
|
/// Disable colored output
|
||||||
|
#[arg(long)]
|
||||||
|
no_color: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Git operations error type
|
||||||
|
#[derive(Debug, thiserror::Error)]
|
||||||
|
enum GitError {
|
||||||
|
#[error("Command failed with exit code: {0}")]
|
||||||
|
Failed(i32),
|
||||||
|
|
||||||
|
#[error("Command failed without exit code")]
|
||||||
|
FailedNoCode,
|
||||||
|
|
||||||
|
#[error("Failed to execute command: {0}")]
|
||||||
|
ExecutionError(#[from] std::io::Error),
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Runs a command with a progress spinner
|
||||||
|
fn run_command(command: &mut Command, message: &str) -> Result<()> {
|
||||||
|
let spinner = ProgressBar::new_spinner();
|
||||||
|
spinner.set_style(
|
||||||
|
ProgressStyle::default_spinner()
|
||||||
|
.tick_chars("⣾⣽⣻⢿⡿⣟⣯⣷")
|
||||||
|
.template("{spinner:.green} {msg}")
|
||||||
|
.expect("Invalid template format"),
|
||||||
|
);
|
||||||
|
spinner.set_message(message.to_string());
|
||||||
|
|
||||||
|
// Configure the command to not show output
|
||||||
|
command.stdout(Stdio::null()).stderr(Stdio::null());
|
||||||
|
|
||||||
|
// Execute the command and wait for it to complete
|
||||||
|
spinner.enable_steady_tick(std::time::Duration::from_millis(100));
|
||||||
|
|
||||||
|
let status = command.status().context("Failed to execute command")?;
|
||||||
|
spinner.finish_and_clear();
|
||||||
|
|
||||||
|
if status.success() {
|
||||||
|
println!("{message} {}", "Done.".green());
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
println!("{message} {}", "FAILED.".red());
|
||||||
|
|
||||||
|
let code = status.code();
|
||||||
|
match code {
|
||||||
|
Some(code) => Err(GitError::Failed(code).into()),
|
||||||
|
None => Err(GitError::FailedNoCode.into()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Git command wrapper
|
||||||
|
struct Git;
|
||||||
|
|
||||||
|
impl Git {
|
||||||
|
/// Clone a repository as a bare clone in a .bare directory
|
||||||
|
fn clone_bare_repo(repo_url: &str, target_dir: &str) -> Result<()> {
|
||||||
|
// Create the base directory first
|
||||||
|
std::fs::create_dir_all(target_dir).context("Failed to create target directory")?;
|
||||||
|
|
||||||
|
// Create the .bare subdirectory path
|
||||||
|
let bare_dir = Path::new(target_dir).join(".bare");
|
||||||
|
let bare_dir_str = bare_dir.to_string_lossy();
|
||||||
|
|
||||||
|
// Clone the repository as a bare clone into .bare directory
|
||||||
|
let mut cmd = Command::new("git");
|
||||||
|
cmd.args([
|
||||||
|
"clone",
|
||||||
|
"--bare",
|
||||||
|
repo_url,
|
||||||
|
&bare_dir_str
|
||||||
|
]);
|
||||||
|
run_command(&mut cmd, &format!("Cloning repository as bare clone into {bare_dir_str}"))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set up the .git file to point to the .bare directory
|
||||||
|
fn setup_git_pointer(target_dir: &str) -> Result<()> {
|
||||||
|
let git_file_path = Path::new(target_dir).join(".git");
|
||||||
|
std::fs::write(git_file_path, "gitdir: ./.bare")
|
||||||
|
.context("Failed to create .git file pointing to .bare directory")
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Configure remote.origin.fetch to fetch all references
|
||||||
|
fn configure_remote_fetch(target_dir: &str) -> Result<()> {
|
||||||
|
let bare_dir = Path::new(target_dir).join(".bare");
|
||||||
|
let bare_dir_str = bare_dir.to_string_lossy();
|
||||||
|
|
||||||
|
let mut cmd = Command::new("git");
|
||||||
|
cmd.args([
|
||||||
|
"--git-dir", &bare_dir_str,
|
||||||
|
"config",
|
||||||
|
"remote.origin.fetch", "+refs/heads/*:refs/remotes/origin/*"
|
||||||
|
]);
|
||||||
|
run_command(&mut cmd, "Configuring remote.origin.fetch")
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Fetch all remotes
|
||||||
|
fn fetch_remotes(target_dir: &str) -> Result<()> {
|
||||||
|
let bare_dir = Path::new(target_dir).join(".bare");
|
||||||
|
let bare_dir_str = bare_dir.to_string_lossy();
|
||||||
|
|
||||||
|
let mut cmd = Command::new("git");
|
||||||
|
cmd.args([
|
||||||
|
"--git-dir", &bare_dir_str,
|
||||||
|
"fetch",
|
||||||
|
"--all"
|
||||||
|
]);
|
||||||
|
run_command(&mut cmd, "Fetching all remotes")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() -> Result<()> {
|
||||||
|
// Parse arguments
|
||||||
|
let args = Args::parse();
|
||||||
|
|
||||||
|
// Enable or disable colored output
|
||||||
|
colored::control::set_override(!args.no_color);
|
||||||
|
|
||||||
|
// Print verbose information if enabled
|
||||||
|
if args.verbose {
|
||||||
|
println!("{}", "Verbose mode enabled".dimmed());
|
||||||
|
println!("{}", format!("Repository URL: {}", args.repo_url).dimmed());
|
||||||
|
println!("{}", format!("Target directory: {}", args.target_dir).dimmed());
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("{}", "Setting up repository for worktree development".blue());
|
||||||
|
|
||||||
|
// Clone the repository as a bare clone
|
||||||
|
Git::clone_bare_repo(&args.repo_url, &args.target_dir)?;
|
||||||
|
|
||||||
|
// Set up the .git file to point to the .bare directory
|
||||||
|
Git::setup_git_pointer(&args.target_dir)?;
|
||||||
|
|
||||||
|
// Configure the remote.origin.fetch setting
|
||||||
|
Git::configure_remote_fetch(&args.target_dir)?;
|
||||||
|
|
||||||
|
// Fetch all remotes
|
||||||
|
Git::fetch_remotes(&args.target_dir)?;
|
||||||
|
|
||||||
|
println!("{}", "Repository setup complete.".green());
|
||||||
|
println!("{}", format!("You can now create worktrees in '{}'.", args.target_dir).green());
|
||||||
|
Ok(())
|
||||||
|
}
|
Reference in New Issue
Block a user