package main import ( "flag" "fmt" "io" "net/url" "os" "os/exec" "path/filepath" "strings" "github.com/rs/zerolog" "github.com/rs/zerolog/log" ) func main() { log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr}) fs := flag.NewFlagSet("clone", flag.ExitOnError) init := fs.Bool("init", false, "Initialize new project") last := fs.Bool("last", false, "Show last created project") if err := fs.Parse(os.Args[1:]); err != nil { log.Fatal().Err(err).Msg("") } if fs.NArg() < 1 && !*last { _, _ = fmt.Fprintln(fs.Output(), "Usage of clone:\nclone [-init|-last] ") return } uri := fs.Arg(0) path, err := clone(*init, *last, uri) if err != nil { log.Err(err).Msg("") return } if path != "" { log.Info().Msg(path) } } func clone(init, last bool, uri string) (string, error) { if last { lastProject() return "", nil } base := codeDir() if !strings.HasPrefix(uri, "http") { uri = "https://" + uri } u, err := url.Parse(uri) if err != nil || strings.EqualFold(u.String(), "") { return "", err } path := filepath.Join(base, u.Host+strings.TrimSuffix(u.Path, ".git")) setLastProject(path) // Init project if init { if err := os.MkdirAll(path, os.ModePerm); err != nil { return "", err } return path, nil } // Clone project if !strings.HasSuffix(u.String(), ".git") { u.Path += ".git" } dir := filepath.Dir(path) if err := os.MkdirAll(dir, os.ModePerm); err != nil { return "", err } cmd := exec.Command("git", "clone", u.String()) cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr cmd.Dir = dir if err := cmd.Run(); err != nil { return "", err } return path, nil } func codeDir() string { dir := os.Getenv("CLONE_DIR") if dir != "" { return dir } home, err := os.UserHomeDir() if err != nil { log.Fatal().Err(err).Msg("") } return filepath.Join(home, "code") } func config() (*os.File, error) { cfg, err := os.UserConfigDir() if err != nil { return nil, err } dir := filepath.Join(cfg, "clone") if err := os.MkdirAll(dir, os.ModePerm); err != nil { return nil, err } path := filepath.Join(dir, "last.txt") return os.OpenFile(path, os.O_CREATE|os.O_RDWR, os.ModePerm) } func lastProject() { fi, err := config() if err != nil { log.Err(err).Msg("") return } defer fi.Close() last, err := io.ReadAll(fi) if err != nil { log.Err(err).Msg("") return } fmt.Println(string(last)) } func setLastProject(last string) { fi, err := config() if err != nil { log.Err(err).Msg("") return } defer fi.Close() if err := fi.Truncate(0); err != nil { log.Err(err).Msg("") return } if _, err := fi.WriteString(last); err != nil { log.Err(err).Msg("") return } }