package main import ( "errors" "fmt" "github.com/urfave/cli/v2" "go.jolheiser.com/beaver" "net/http" "os" "os/exec" "strings" ) var Version = "develop" func main() { app := cli.NewApp() app.Name = "git-import" app.Usage = "Import from vanity git URLs" app.Version = Version app.Flags = []cli.Flag{ &cli.BoolFlag{ Name: "display", Aliases: []string{"d"}, Usage: "Display URL instead of cloning", }, &cli.BoolFlag{ Name: "ssh", Aliases: []string{"s"}, Usage: "Use SSH if available", }, } app.UseShortOptionHandling = true app.EnableBashCompletion = true app.Action = doImport err := app.Run(os.Args) if err != nil { beaver.Error(err) } } func doImport(ctx *cli.Context) error { if ctx.NArg() < 1 { return errors.New("must specify an import URL") } importURL := ctx.Args().First() if !strings.HasPrefix(importURL, "https") { importURL = fmt.Sprintf("http://%s", importURL) } res, err := http.Get(importURL) if err != nil { return fmt.Errorf("could not request URL `%s`: %v", importURL, err) } defer res.Body.Close() gitImport, err := parseMetaGitImport(res.Body) if err != nil { return fmt.Errorf("could not parse: %v", err) } if ctx.Bool("display") { if ctx.Bool("ssh") { fmt.Println(gitImport.SSH) return nil } fmt.Println(gitImport.HTTPS) return nil } return doClone(ctx, gitImport) } func doClone(ctx *cli.Context, gitImport GitImport) error { projectName := gitImport.ProjectName if ctx.NArg() > 1 { projectName = ctx.Args().Get(1) } cmd := exec.Command("git", "clone", gitImport.HTTPS, projectName) if ctx.Bool("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, projectName) } cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr if err := cmd.Run(); err != nil { return fmt.Errorf("could not clone: %v", err) } if ctx.Bool("ssh") { if err := os.Chdir(projectName); err != nil { return fmt.Errorf("could not change to `%s` directory. Git config will not store SSH command", projectName) } cmd := exec.Command("git", "config", "--local", "core.sshCommand", os.Getenv("GIT_SSH_COMMAND")) cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr if err := cmd.Run(); err != nil { return fmt.Errorf("could not configure SSH: %v", err) } } return nil }