151 lines
2.6 KiB
Go
151 lines
2.6 KiB
Go
|
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] <path>")
|
||
|
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
|
||
|
}
|
||
|
}
|