168 lines
3.9 KiB
Go
168 lines
3.9 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"flag"
|
|
"fmt"
|
|
"net/http"
|
|
"net/url"
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"go.jolheiser.com/git-import"
|
|
|
|
"github.com/peterbourgon/ff/v3"
|
|
"github.com/peterbourgon/ff/v3/ffcli"
|
|
"go.jolheiser.com/beaver"
|
|
)
|
|
|
|
var (
|
|
Version = "develop"
|
|
|
|
fs = flag.NewFlagSet("git-get <import-url>", flag.ExitOnError)
|
|
output = fs.String("out", "", "Path to clone into (default: git-import name)")
|
|
author = fs.String("author", "", "Signature Author ($GIT_IMPORT_AUTHOR)")
|
|
email = fs.String("email", "", "Signature Email ($GIT_IMPORT_EMAIL)")
|
|
gpg = fs.String("gpg", "", "GPG key to sign with ($GIT_IMPORT_GPG)")
|
|
noMeta = fs.Bool("no-meta", false, "Don't check for meta, just clone")
|
|
display = fs.Bool("display", false, "Display URL instead of cloning")
|
|
ssh = fs.Bool("ssh", false, "Use SSH if $GIT_SSH_COMMAND is set")
|
|
insecure = fs.Bool("insecure", false, "Use HTTP instead of HTTPS by default")
|
|
debug = fs.Bool("debug", false, "Debug logging")
|
|
)
|
|
|
|
func main() {
|
|
cmd := &ffcli.Command{
|
|
Name: "git-get",
|
|
ShortUsage: "git-get <import-url>",
|
|
LongHelp: fmt.Sprintf("VERSION\n %s", Version),
|
|
FlagSet: fs,
|
|
Options: []ff.Option{
|
|
ff.WithEnvVarPrefix("GIT_IMPORT"),
|
|
},
|
|
Exec: doImport,
|
|
}
|
|
|
|
if err := cmd.ParseAndRun(context.Background(), os.Args[1:]); err != nil {
|
|
beaver.Error(err)
|
|
}
|
|
}
|
|
|
|
func doImport(_ context.Context, _ []string) error {
|
|
if *debug {
|
|
beaver.Console.Level = beaver.DEBUG
|
|
}
|
|
|
|
if fs.NArg() == 0 {
|
|
fs.Usage()
|
|
return nil
|
|
}
|
|
|
|
raw := fs.Arg(0)
|
|
if !strings.HasPrefix(raw, "http") {
|
|
raw = fmt.Sprintf("https://%s", raw)
|
|
}
|
|
|
|
u, err := url.Parse(raw)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if *insecure {
|
|
u.Scheme = "http"
|
|
}
|
|
|
|
var gitImport gimport.GitImport
|
|
if *noMeta {
|
|
p := strings.Split(u.Path, "/")
|
|
gitImport = gimport.GitImport{
|
|
Name: p[len(p)-1],
|
|
HTTP: u.String(),
|
|
SSH: fmt.Sprintf("git@%s:%s.git", u.Host, u.Path[1:]),
|
|
}
|
|
} else {
|
|
u.RawQuery = "git-import=1"
|
|
beaver.Debugf("Getting git-import from %s", u.String())
|
|
res, err := http.Get(u.String())
|
|
if err != nil {
|
|
return fmt.Errorf("could not request URL `%s`: %v", u.String(), err)
|
|
}
|
|
defer res.Body.Close()
|
|
gitImport, err = gimport.ParseMetaGitImport(res.Body)
|
|
if err != nil {
|
|
return fmt.Errorf("could not parse: %v", err)
|
|
}
|
|
}
|
|
beaver.Debug(gitImport)
|
|
|
|
if *display {
|
|
if *ssh {
|
|
fmt.Println(gitImport.SSH)
|
|
return nil
|
|
}
|
|
fmt.Println(gitImport.HTTP)
|
|
return nil
|
|
}
|
|
return doClone(gitImport)
|
|
}
|
|
|
|
func doClone(gitImport gimport.GitImport) error {
|
|
if *output == "" {
|
|
*output = gitImport.Name
|
|
}
|
|
|
|
cmd := exec.Command("git", "clone", gitImport.HTTP, *output)
|
|
if *ssh {
|
|
if gitImport.SSH == "" {
|
|
return errors.New("SSH was not provided by git-import")
|
|
}
|
|
if os.Getenv("GIT_SSH_COMMAND") == "" {
|
|
return errors.New("no environment variable found for GIT_SSH_COMMAND")
|
|
}
|
|
cmd = exec.Command("git", "clone", gitImport.SSH, *output)
|
|
}
|
|
cmd.Stdout = os.Stdout
|
|
cmd.Stderr = os.Stderr
|
|
|
|
if err := cmd.Run(); err != nil {
|
|
return fmt.Errorf("could not clone: %v", err)
|
|
}
|
|
|
|
if *ssh {
|
|
if err := gitConfig("core.sshCommand", os.Getenv("GIT_SSH_COMMAND")); err != nil {
|
|
beaver.Errorf("could not configure SSH: %v", err)
|
|
}
|
|
}
|
|
|
|
if *author != "" {
|
|
if err := gitConfig("user.name", *author); err != nil {
|
|
beaver.Errorf("could not configure author: %v", err)
|
|
}
|
|
}
|
|
if *email != "" {
|
|
if err := gitConfig("user.email", *email); err != nil {
|
|
beaver.Errorf("could not configure email: %v", err)
|
|
}
|
|
}
|
|
if *gpg != "" {
|
|
if err := gitConfig("user.signingkey", *gpg); err != nil {
|
|
beaver.Errorf("could not configure GPG key: %v", err)
|
|
}
|
|
if err := gitConfig("commit.gpgsign", "true"); err != nil {
|
|
beaver.Errorf("could not configure GPG signing: %v", err)
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func gitConfig(key, value string) error {
|
|
cmd := exec.Command("git", "config", "--local", key, value)
|
|
cmd.Dir = filepath.Join(".", *output)
|
|
cmd.Stdout = os.Stdout
|
|
cmd.Stderr = os.Stderr
|
|
return cmd.Run()
|
|
}
|