mirror of
https://github.com/grdl/git-get.git
synced 2026-02-09 09:44:18 +00:00
Merge pull request #27 from grdl/issue-5-single-binary
Build a single binary instead of two
This commit is contained in:
11
.github/workflows/ci.yml
vendored
11
.github/workflows/ci.yml
vendored
@@ -124,19 +124,20 @@ jobs:
|
|||||||
go-version: '1.24'
|
go-version: '1.24'
|
||||||
cache: true
|
cache: true
|
||||||
|
|
||||||
- name: Build binaries
|
- name: Build binary
|
||||||
run: |
|
run: |
|
||||||
go build -v -o bin/git-get ./cmd/get
|
go build -v -o bin/git-get ./cmd/
|
||||||
go build -v -o bin/git-list ./cmd/list
|
|
||||||
|
|
||||||
- name: Test binaries
|
- name: Test binary and symlink behavior
|
||||||
run: |
|
run: |
|
||||||
./bin/git-get --version
|
./bin/git-get --version
|
||||||
|
# Test symlink functionality
|
||||||
|
ln -sf git-get bin/git-list
|
||||||
./bin/git-list --version
|
./bin/git-list --version
|
||||||
|
|
||||||
- name: Upload build artifacts
|
- name: Upload build artifacts
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: binaries
|
name: binary
|
||||||
path: bin/
|
path: bin/
|
||||||
retention-days: 30
|
retention-days: 30
|
||||||
|
|||||||
24
.github/workflows/release-simple.yml
vendored
24
.github/workflows/release-simple.yml
vendored
@@ -1,24 +0,0 @@
|
|||||||
name: release
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
tags:
|
|
||||||
- '*'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
goreleaser:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
- name: Set up Go
|
|
||||||
uses: actions/setup-go@v5
|
|
||||||
with:
|
|
||||||
go-version: '1.24'
|
|
||||||
- name: Run GoReleaser
|
|
||||||
uses: goreleaser/goreleaser-action@v6
|
|
||||||
with:
|
|
||||||
version: latest
|
|
||||||
args: release --clean
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GORELEASER_TOKEN }}
|
|
||||||
14
.github/workflows/release.yml
vendored
14
.github/workflows/release.yml
vendored
@@ -8,7 +8,6 @@ on:
|
|||||||
permissions:
|
permissions:
|
||||||
contents: write
|
contents: write
|
||||||
security-events: write
|
security-events: write
|
||||||
id-token: write # For SLSA provenance
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
validate:
|
validate:
|
||||||
@@ -64,15 +63,4 @@ jobs:
|
|||||||
version: latest
|
version: latest
|
||||||
args: release --clean
|
args: release --clean
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GORELEASER_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GORELEASER_TOKEN }}
|
||||||
|
|
||||||
provenance:
|
|
||||||
name: Generate SLSA Provenance
|
|
||||||
needs: release
|
|
||||||
if: startsWith(github.ref, 'refs/tags/')
|
|
||||||
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v2.0.0
|
|
||||||
with:
|
|
||||||
base64-subjects: "${{ needs.release.outputs.hashes }}"
|
|
||||||
upload-assets: true
|
|
||||||
secrets:
|
|
||||||
registry-password: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
@@ -6,36 +6,39 @@ before:
|
|||||||
|
|
||||||
builds:
|
builds:
|
||||||
- id: git-get
|
- id: git-get
|
||||||
main: ./cmd/get/main.go
|
main: ./cmd/
|
||||||
binary: git-get
|
binary: git-get
|
||||||
ldflags:
|
ldflags:
|
||||||
- -s -w
|
- -s -w
|
||||||
- -X git-get/pkg/cfg.version={{.Version}}
|
- -X git-get/pkg/cfg.version={{.Version}}
|
||||||
- -X git-get/pkg/cfg.commit={{.Commit}}
|
- -X git-get/pkg/cfg.commit={{.Commit}}
|
||||||
- -X git-get/pkg/cfg.date={{.Date}}
|
|
||||||
goos:
|
goos:
|
||||||
- linux
|
- linux
|
||||||
- darwin
|
|
||||||
- windows
|
- windows
|
||||||
- id: git-list
|
goarch:
|
||||||
main: ./cmd/list/main.go
|
- amd64
|
||||||
binary: git-list
|
- arm64
|
||||||
|
- arm
|
||||||
|
goarm:
|
||||||
|
- 7
|
||||||
|
- id: git-get-macos
|
||||||
|
main: ./cmd/
|
||||||
|
binary: git-get
|
||||||
ldflags:
|
ldflags:
|
||||||
- -s -w
|
- -s -w
|
||||||
- -X git-get/pkg/cfg.version={{.Version}}
|
- -X git-get/pkg/cfg.version={{.Version}}
|
||||||
- -X git-get/pkg/cfg.commit={{.Commit}}
|
- -X git-get/pkg/cfg.commit={{.Commit}}
|
||||||
- -X git-get/pkg/cfg.date={{.Date}}
|
|
||||||
goos:
|
goos:
|
||||||
- linux
|
|
||||||
- darwin
|
- darwin
|
||||||
- windows
|
goarch:
|
||||||
|
- amd64
|
||||||
|
- arm64
|
||||||
|
|
||||||
archives:
|
archives:
|
||||||
- id: archive
|
- id: archive
|
||||||
ids:
|
ids:
|
||||||
- git-get
|
- git-get
|
||||||
- git-list
|
name_template: "git-get_{{ .Version }}_{{ .Os }}_{{ .Arch }}{{- if .Arm }}v{{ .Arm }}{{ end }}{{- if .Amd64 }}v{{ .Amd64 }}{{ end }}"
|
||||||
name_template: "git-get_{{ .Version }}_{{ .Os }}_{{ .Arch }}"
|
|
||||||
formats:
|
formats:
|
||||||
- tar.gz
|
- tar.gz
|
||||||
- zip
|
- zip
|
||||||
@@ -43,6 +46,14 @@ archives:
|
|||||||
- goos: windows
|
- goos: windows
|
||||||
formats: [zip]
|
formats: [zip]
|
||||||
# Don't include any additional files into the archives (such as README, CHANGELOG etc).
|
# Don't include any additional files into the archives (such as README, CHANGELOG etc).
|
||||||
|
files:
|
||||||
|
- none*
|
||||||
|
- id: macos-archive
|
||||||
|
ids:
|
||||||
|
- git-get-macos
|
||||||
|
name_template: "git-get_{{ .Version }}_{{ .Os }}_{{ .Arch }}{{- if .Arm }}v{{ .Arm }}{{ end }}{{- if .Amd64 }}v{{ .Amd64 }}{{ end }}"
|
||||||
|
formats:
|
||||||
|
- tar.gz
|
||||||
files:
|
files:
|
||||||
- none*
|
- none*
|
||||||
|
|
||||||
@@ -64,8 +75,10 @@ release:
|
|||||||
owner: grdl
|
owner: grdl
|
||||||
name: git-get
|
name: git-get
|
||||||
|
|
||||||
brews:
|
homebrew_casks:
|
||||||
- name: git-get
|
- name: git-get
|
||||||
|
ids:
|
||||||
|
- macos-archive
|
||||||
repository:
|
repository:
|
||||||
owner: grdl
|
owner: grdl
|
||||||
name: homebrew-tap
|
name: homebrew-tap
|
||||||
@@ -73,13 +86,14 @@ brews:
|
|||||||
commit_author:
|
commit_author:
|
||||||
name: Grzegorz Dlugoszewski
|
name: Grzegorz Dlugoszewski
|
||||||
email: git-get@grdl.dev
|
email: git-get@grdl.dev
|
||||||
directory: Formula
|
|
||||||
homepage: https://github.com/grdl/git-get/
|
homepage: https://github.com/grdl/git-get/
|
||||||
description: Better way to clone, organize and manage multiple git repositories
|
description: Better way to clone, organize and manage multiple git repositories
|
||||||
test: |
|
url:
|
||||||
system "git-get --version"
|
verified: github.com/grdl/git-get
|
||||||
install: |
|
hooks:
|
||||||
bin.install "git-get", "git-list"
|
post:
|
||||||
|
install: |
|
||||||
|
system_command "/bin/ln", args: ["-sf", "#{staged_path}/git-get", "#{HOMEBREW_PREFIX}/bin/git-list"]
|
||||||
|
|
||||||
nfpms:
|
nfpms:
|
||||||
- id: packages
|
- id: packages
|
||||||
@@ -94,6 +108,9 @@ nfpms:
|
|||||||
formats:
|
formats:
|
||||||
- deb
|
- deb
|
||||||
- rpm
|
- rpm
|
||||||
|
scripts:
|
||||||
|
postinstall: "scripts/postinstall.sh"
|
||||||
|
preremove: "scripts/preremove.sh"
|
||||||
|
|
||||||
scoops:
|
scoops:
|
||||||
- name: git-get
|
- name: git-get
|
||||||
@@ -110,3 +127,6 @@ scoops:
|
|||||||
homepage: "https://github.com/grdl/git-get"
|
homepage: "https://github.com/grdl/git-get"
|
||||||
description: "Better way to clone, organize and manage multiple git repositories"
|
description: "Better way to clone, organize and manage multiple git repositories"
|
||||||
license: MIT
|
license: MIT
|
||||||
|
post_install: [
|
||||||
|
"New-Item -ItemType HardLink -Path \"$dir\\git-list.exe\" -Target \"$dir\\git-get.exe\" -Force | Out-Null"
|
||||||
|
]
|
||||||
|
|||||||
74
README.md
74
README.md
@@ -37,10 +37,12 @@ A tool to clone, organize, and manage multiple Git repositories with an automati
|
|||||||
|
|
||||||
**git-get** solves the problem of manually organizing multiple Git repositories. Instead of scattered clones in random directories, it creates a clean, predictable directory structure based on repository URLs, similar to Go's `go get` command.
|
**git-get** solves the problem of manually organizing multiple Git repositories. Instead of scattered clones in random directories, it creates a clean, predictable directory structure based on repository URLs, similar to Go's `go get` command.
|
||||||
|
|
||||||
It provides two commands:
|
It provides two commands through a single binary:
|
||||||
- **`git get`** - Clones repositories into an organized directory tree
|
- **`git get`** - Clones repositories into an organized directory tree
|
||||||
- **`git list`** - Shows the status of all your repositories at a glance
|
- **`git list`** - Shows the status of all your repositories at a glance
|
||||||
|
|
||||||
|
*Note: Both commands are provided by a single `git-get` binary that automatically detects how it was invoked (either directly or via symlink).*
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
@@ -56,51 +58,91 @@ It provides two commands:
|
|||||||
## Prerequisites
|
## Prerequisites
|
||||||
|
|
||||||
- Git 2.0+ installed and configured
|
- Git 2.0+ installed and configured
|
||||||
- Go 1.19+ (only if building from source)
|
- Go 1.24+ (only if building from source)
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
### macOS
|
### macOS
|
||||||
|
|
||||||
|
**Option 1: Homebrew (Recommended)**
|
||||||
```bash
|
```bash
|
||||||
brew install grdl/tap/git-get
|
brew install grdl/tap/git-get
|
||||||
```
|
```
|
||||||
|
*This automatically installs both `git-get` and `git-list` commands.*
|
||||||
|
|
||||||
|
**Option 2: Manual Installation**
|
||||||
|
1. Download the latest macOS `.tar.gz` file from [releases](https://github.com/grdl/git-get/releases/latest)
|
||||||
|
2. Extract and install:
|
||||||
|
```bash
|
||||||
|
tar -xzf git-get_*_darwin_*.tar.gz
|
||||||
|
sudo mv git-get /usr/local/bin/
|
||||||
|
sudo ln -sf /usr/local/bin/git-get /usr/local/bin/git-list
|
||||||
|
```
|
||||||
|
|
||||||
### Linux
|
### Linux
|
||||||
|
|
||||||
**Option 1: Package managers**
|
**Option 1: Package Managers (Recommended)**
|
||||||
```bash
|
```bash
|
||||||
# Download .deb or .rpm from releases
|
# Ubuntu/Debian - Download and install .deb package
|
||||||
wget https://github.com/grdl/git-get/releases/latest/download/git-get_linux_amd64.deb
|
wget https://github.com/grdl/git-get/releases/latest/download/git-get_*_linux_amd64.deb
|
||||||
sudo dpkg -i git-get_linux_amd64.deb
|
sudo dpkg -i git-get_*_linux_amd64.deb
|
||||||
|
|
||||||
|
# CentOS/RHEL/Fedora - Download and install .rpm package
|
||||||
|
wget https://github.com/grdl/git-get/releases/latest/download/git-get_*_linux_amd64.rpm
|
||||||
|
sudo rpm -i git-get_*_linux_amd64.rpm
|
||||||
|
```
|
||||||
|
*Package installation automatically creates the `git-list` symlink.*
|
||||||
|
|
||||||
|
**Option 2: Manual Installation**
|
||||||
|
```bash
|
||||||
|
# Download and extract
|
||||||
|
wget https://github.com/grdl/git-get/releases/latest/download/git-get_*_linux_amd64.tar.gz
|
||||||
|
tar -xzf git-get_*_linux_amd64.tar.gz
|
||||||
|
|
||||||
|
# Install binary and create symlink
|
||||||
|
sudo mv git-get /usr/local/bin/
|
||||||
|
sudo ln -sf /usr/local/bin/git-get /usr/local/bin/git-list
|
||||||
```
|
```
|
||||||
|
|
||||||
**Option 2: Homebrew on Linux**
|
**Option 3: Homebrew on Linux**
|
||||||
```bash
|
```bash
|
||||||
brew install grdl/tap/git-get
|
brew install grdl/tap/git-get
|
||||||
```
|
```
|
||||||
|
|
||||||
### Windows
|
### Windows
|
||||||
|
|
||||||
**Option 1: Download binary**
|
**Option 1: Scoop (Recommended)**
|
||||||
1. Download the latest `.zip` file from [releases](https://github.com/grdl/git-get/releases/latest)
|
|
||||||
2. Extract the binaries to a directory in your PATH
|
|
||||||
|
|
||||||
**Option 2: Using Scoop**
|
|
||||||
```powershell
|
```powershell
|
||||||
scoop bucket add git-get https://github.com/grdl/git-get
|
scoop bucket add grdl https://github.com/grdl/git-get
|
||||||
scoop install git-get
|
scoop install git-get
|
||||||
```
|
```
|
||||||
|
*This automatically creates both `git-get.exe` and `git-list.exe` commands.*
|
||||||
|
|
||||||
|
**Option 2: Manual Installation**
|
||||||
|
1. Download the latest Windows `.zip` file from [releases](https://github.com/grdl/git-get/releases/latest)
|
||||||
|
2. Extract `git-get.exe` to a directory in your PATH
|
||||||
|
3. Create a copy or hard link for `git-list`:
|
||||||
|
```powershell
|
||||||
|
# In the same directory as git-get.exe
|
||||||
|
Copy-Item git-get.exe git-list.exe
|
||||||
|
# OR create a hard link (requires admin privileges)
|
||||||
|
New-Item -ItemType HardLink -Path "git-list.exe" -Target "git-get.exe"
|
||||||
|
```
|
||||||
|
|
||||||
### Building from Source
|
### Building from Source
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git clone https://github.com/grdl/git-get.git
|
git clone https://github.com/grdl/git-get.git
|
||||||
cd git-get
|
cd git-get
|
||||||
go build -o bin/ ./cmd/...
|
go build -o git-get ./cmd/
|
||||||
|
|
||||||
|
# Create symlink for git-list
|
||||||
|
ln -sf git-get git-list # Unix/Linux/macOS
|
||||||
|
# OR
|
||||||
|
copy git-get.exe git-list.exe # Windows
|
||||||
```
|
```
|
||||||
|
|
||||||
Then add the `bin/` directory to your PATH.
|
**Note:** The single binary (`git-get`) automatically detects how it's invoked and behaves as either `git-get` or `git-list` accordingly.
|
||||||
|
|
||||||
## Quick Start
|
## Quick Start
|
||||||
|
|
||||||
|
|||||||
@@ -4,27 +4,28 @@ import (
|
|||||||
"git-get/pkg"
|
"git-get/pkg"
|
||||||
"git-get/pkg/cfg"
|
"git-get/pkg/cfg"
|
||||||
"git-get/pkg/git"
|
"git-get/pkg/git"
|
||||||
|
"os"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
)
|
)
|
||||||
|
|
||||||
const example = ` git get grdl/git-get
|
const getExample = ` git get grdl/git-get
|
||||||
git get https://github.com/grdl/git-get.git
|
git get https://github.com/grdl/git-get.git
|
||||||
git get git@github.com:grdl/git-get.git
|
git get git@github.com:grdl/git-get.git
|
||||||
git get -d path/to/dump/file`
|
git get -d path/to/dump/file`
|
||||||
|
|
||||||
var cmd = &cobra.Command{
|
func newGetCommand() *cobra.Command {
|
||||||
Use: "git get <REPO>",
|
cmd := &cobra.Command{
|
||||||
Short: "Clone git repository into an automatically created directory tree based on the repo's URL.",
|
Use: "git get <REPO>",
|
||||||
Example: example,
|
Short: "Clone git repository into an automatically created directory tree based on the repo's URL.",
|
||||||
RunE: run,
|
Example: getExample,
|
||||||
Args: cobra.MaximumNArgs(1), // TODO: add custom validator
|
RunE: runGetCommand,
|
||||||
Version: cfg.Version(),
|
Args: cobra.MaximumNArgs(1), // TODO: add custom validator
|
||||||
SilenceUsage: true, // We don't want to show usage on legit errors (eg, wrong path, repo already existing etc.)
|
Version: cfg.Version(),
|
||||||
}
|
SilenceUsage: true, // We don't want to show usage on legit errors (eg, wrong path, repo already existing etc.)
|
||||||
|
}
|
||||||
|
|
||||||
func init() {
|
|
||||||
cmd.PersistentFlags().StringP(cfg.KeyBranch, "b", "", "Branch (or tag) to checkout after cloning.")
|
cmd.PersistentFlags().StringP(cfg.KeyBranch, "b", "", "Branch (or tag) to checkout after cloning.")
|
||||||
cmd.PersistentFlags().StringP(cfg.KeyDefaultHost, "t", cfg.Defaults[cfg.KeyDefaultHost], "Host to use when <REPO> doesn't have a specified host.")
|
cmd.PersistentFlags().StringP(cfg.KeyDefaultHost, "t", cfg.Defaults[cfg.KeyDefaultHost], "Host to use when <REPO> doesn't have a specified host.")
|
||||||
cmd.PersistentFlags().StringP(cfg.KeyDefaultScheme, "c", cfg.Defaults[cfg.KeyDefaultScheme], "Scheme to use when <REPO> doesn't have a specified scheme.")
|
cmd.PersistentFlags().StringP(cfg.KeyDefaultScheme, "c", cfg.Defaults[cfg.KeyDefaultScheme], "Scheme to use when <REPO> doesn't have a specified scheme.")
|
||||||
@@ -41,10 +42,10 @@ func init() {
|
|||||||
viper.BindPFlag(cfg.KeyReposRoot, cmd.PersistentFlags().Lookup(cfg.KeyReposRoot))
|
viper.BindPFlag(cfg.KeyReposRoot, cmd.PersistentFlags().Lookup(cfg.KeyReposRoot))
|
||||||
viper.BindPFlag(cfg.KeySkipHost, cmd.PersistentFlags().Lookup(cfg.KeySkipHost))
|
viper.BindPFlag(cfg.KeySkipHost, cmd.PersistentFlags().Lookup(cfg.KeySkipHost))
|
||||||
|
|
||||||
cfg.Init(&git.ConfigGlobal{})
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
func run(cmd *cobra.Command, args []string) error {
|
func runGetCommand(cmd *cobra.Command, args []string) error {
|
||||||
var url string
|
var url string
|
||||||
if len(args) > 0 {
|
if len(args) > 0 {
|
||||||
url = args[0]
|
url = args[0]
|
||||||
@@ -64,6 +65,17 @@ func run(cmd *cobra.Command, args []string) error {
|
|||||||
return pkg.Get(config)
|
return pkg.Get(config)
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func runGet(args []string) {
|
||||||
cmd.Execute()
|
// Initialize configuration
|
||||||
|
cfg.Init(&git.ConfigGlobal{})
|
||||||
|
|
||||||
|
// Create and execute the get command
|
||||||
|
cmd := newGetCommand()
|
||||||
|
|
||||||
|
// Set args for cobra to parse
|
||||||
|
cmd.SetArgs(args)
|
||||||
|
|
||||||
|
if err := cmd.Execute(); err != nil {
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -5,22 +5,23 @@ import (
|
|||||||
"git-get/pkg"
|
"git-get/pkg"
|
||||||
"git-get/pkg/cfg"
|
"git-get/pkg/cfg"
|
||||||
"git-get/pkg/git"
|
"git-get/pkg/git"
|
||||||
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
)
|
)
|
||||||
|
|
||||||
var cmd = &cobra.Command{
|
func newListCommand() *cobra.Command {
|
||||||
Use: "git list",
|
cmd := &cobra.Command{
|
||||||
Short: "List all repositories cloned by 'git get' and their status.",
|
Use: "git list",
|
||||||
RunE: run,
|
Short: "List all repositories cloned by 'git get' and their status.",
|
||||||
Args: cobra.NoArgs,
|
RunE: runListCommand,
|
||||||
Version: cfg.Version(),
|
Args: cobra.NoArgs,
|
||||||
SilenceUsage: true, // We don't want to show usage on legit errors (eg, wrong path, repo already existing etc.)
|
Version: cfg.Version(),
|
||||||
}
|
SilenceUsage: true, // We don't want to show usage on legit errors (eg, wrong path, repo already existing etc.)
|
||||||
|
}
|
||||||
|
|
||||||
func init() {
|
|
||||||
cmd.PersistentFlags().BoolP(cfg.KeyFetch, "f", false, "First fetch from remotes before listing repositories.")
|
cmd.PersistentFlags().BoolP(cfg.KeyFetch, "f", false, "First fetch from remotes before listing repositories.")
|
||||||
cmd.PersistentFlags().StringP(cfg.KeyOutput, "o", cfg.Defaults[cfg.KeyOutput], fmt.Sprintf("Output format. Allowed values: [%s].", strings.Join(cfg.AllowedOut, ", ")))
|
cmd.PersistentFlags().StringP(cfg.KeyOutput, "o", cfg.Defaults[cfg.KeyOutput], fmt.Sprintf("Output format. Allowed values: [%s].", strings.Join(cfg.AllowedOut, ", ")))
|
||||||
cmd.PersistentFlags().StringP(cfg.KeyReposRoot, "r", cfg.Defaults[cfg.KeyReposRoot], "Path to repos root where repositories are cloned.")
|
cmd.PersistentFlags().StringP(cfg.KeyReposRoot, "r", cfg.Defaults[cfg.KeyReposRoot], "Path to repos root where repositories are cloned.")
|
||||||
@@ -31,10 +32,10 @@ func init() {
|
|||||||
viper.BindPFlag(cfg.KeyOutput, cmd.PersistentFlags().Lookup(cfg.KeyOutput))
|
viper.BindPFlag(cfg.KeyOutput, cmd.PersistentFlags().Lookup(cfg.KeyOutput))
|
||||||
viper.BindPFlag(cfg.KeyReposRoot, cmd.PersistentFlags().Lookup(cfg.KeyReposRoot))
|
viper.BindPFlag(cfg.KeyReposRoot, cmd.PersistentFlags().Lookup(cfg.KeyReposRoot))
|
||||||
|
|
||||||
cfg.Init(&git.ConfigGlobal{})
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
func run(cmd *cobra.Command, args []string) error {
|
func runListCommand(cmd *cobra.Command, args []string) error {
|
||||||
cfg.Expand(cfg.KeyReposRoot)
|
cfg.Expand(cfg.KeyReposRoot)
|
||||||
|
|
||||||
config := &pkg.ListCfg{
|
config := &pkg.ListCfg{
|
||||||
@@ -46,6 +47,17 @@ func run(cmd *cobra.Command, args []string) error {
|
|||||||
return pkg.List(config)
|
return pkg.List(config)
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func runList(args []string) {
|
||||||
cmd.Execute()
|
// Initialize configuration
|
||||||
|
cfg.Init(&git.ConfigGlobal{})
|
||||||
|
|
||||||
|
// Create and execute the list command
|
||||||
|
cmd := newListCommand()
|
||||||
|
|
||||||
|
// Set args for cobra to parse
|
||||||
|
cmd.SetArgs(args)
|
||||||
|
|
||||||
|
if err := cmd.Execute(); err != nil {
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
61
cmd/main.go
Normal file
61
cmd/main.go
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
// This program behaves as a git subcommand (see https://git.github.io/htmldocs/howto/new-command.html)
|
||||||
|
// When added to PATH, git recognizes it as its subcommand and it can be invoked as "git get..." or "git list..."
|
||||||
|
// It can also be invoked as a regular binary with subcommands: "git-get get..." or "git-get list"
|
||||||
|
// The following flow detects the invokation method and runs the appropriate command.
|
||||||
|
|
||||||
|
programName := filepath.Base(os.Args[0])
|
||||||
|
|
||||||
|
// Remove common executable extensions
|
||||||
|
programName = strings.TrimSuffix(programName, ".exe")
|
||||||
|
|
||||||
|
// Determine which command to run based on program name or first argument
|
||||||
|
var command string
|
||||||
|
var args []string
|
||||||
|
|
||||||
|
switch programName {
|
||||||
|
case "git-get":
|
||||||
|
// Check if first argument is a subcommand
|
||||||
|
if len(os.Args) > 1 && (os.Args[1] == "get" || os.Args[1] == "list") {
|
||||||
|
// Called as: git-get get <repo> or git-get list
|
||||||
|
command = os.Args[1]
|
||||||
|
args = os.Args[2:]
|
||||||
|
} else {
|
||||||
|
// Called as: git-get <repo> (default to get command)
|
||||||
|
command = "get"
|
||||||
|
args = os.Args[1:]
|
||||||
|
}
|
||||||
|
case "git-list":
|
||||||
|
// Called as: git-list (symlinked binary)
|
||||||
|
command = "list"
|
||||||
|
args = os.Args[1:]
|
||||||
|
default:
|
||||||
|
// Fallback: use first argument as command
|
||||||
|
if len(os.Args) > 1 {
|
||||||
|
command = os.Args[1]
|
||||||
|
args = os.Args[2:]
|
||||||
|
} else {
|
||||||
|
command = "get"
|
||||||
|
args = []string{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Execute the appropriate command
|
||||||
|
switch command {
|
||||||
|
case "get":
|
||||||
|
runGet(args)
|
||||||
|
case "list":
|
||||||
|
runList(args)
|
||||||
|
default:
|
||||||
|
// Default to get command for unknown commands
|
||||||
|
runGet(os.Args[1:])
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -49,17 +49,20 @@ var AllowedOut = []string{OutDump, OutFlat, OutTree}
|
|||||||
var (
|
var (
|
||||||
version string
|
version string
|
||||||
commit string
|
commit string
|
||||||
date string
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Version returns a string with version metadata: version number, git sha and build date.
|
// Version returns a string with version metadata: version number and git commit.
|
||||||
// It returns "development" if version variables are not set during the build.
|
// It returns "git-get development" if version variables are not set during the build.
|
||||||
func Version() string {
|
func Version() string {
|
||||||
if version == "" {
|
if version == "" {
|
||||||
return "development"
|
return "git-get development"
|
||||||
}
|
}
|
||||||
|
|
||||||
return fmt.Sprintf("%s - revision %s built at %s", version, commit[:6], date)
|
if commit != "" {
|
||||||
|
return fmt.Sprintf("git-get %s (%s)", version, commit[:7])
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Sprintf("git-get %s", version)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gitconfig represents gitconfig file
|
// Gitconfig represents gitconfig file
|
||||||
|
|||||||
3
scripts/postinstall.sh
Executable file
3
scripts/postinstall.sh
Executable file
@@ -0,0 +1,3 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# Create symlink for git-list command
|
||||||
|
ln -sf /usr/local/bin/git-get /usr/local/bin/git-list
|
||||||
3
scripts/preremove.sh
Executable file
3
scripts/preremove.sh
Executable file
@@ -0,0 +1,3 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# Remove symlink for git-list command
|
||||||
|
rm -f /usr/local/bin/git-list
|
||||||
Reference in New Issue
Block a user