Skip to content

Commit

Permalink
refine create subcommand
Browse files Browse the repository at this point in the history
  • Loading branch information
Songmu committed Dec 24, 2019
1 parent 379281c commit 9d53b27
Show file tree
Hide file tree
Showing 6 changed files with 96 additions and 29 deletions.
54 changes: 44 additions & 10 deletions cmd_create.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,39 +2,73 @@ package main

import (
"fmt"
"io"
"os"
"os/exec"
"path/filepath"

"github.com/motemen/ghq/cmdutil"
"github.com/urfave/cli"
)

func doCreate(c *cli.Context) error {
var (
name = c.Args().First()
vcs = c.String("vcs")
w = c.App.Writer
)
u, err := newURL(name, false, true)
if err != nil {
return err
}
root, err := getRoot(u.String())

localRepo, err := LocalRepositoryFromURL(u)
if err != nil {
return err
}

p := localRepo.FullPath
ok, err := isNotExistOrEmpty(p)
if err != nil {
return err
}
p := filepath.Join(root, u.Hostname(), u.Path)
if !ok {
return fmt.Errorf("directory %q already exists and not empty", p)
}
if err := os.MkdirAll(p, 0755); err != nil {
return err
}

cmd := exec.Command("git", "init")
cmd.Stdout = os.Stderr
cmd.Stderr = os.Stderr
cmd.Dir = p
if err := cmdutil.RunCommand(cmd, true); err != nil {
remoteRepo, err := NewRemoteRepository(u)
if err != nil {
return nil
}

vcsBackend, ok := vcsRegistry[vcs]
if !ok {
vcsBackend, u = remoteRepo.VCS()
}
initFunc := vcsBackend.Init
if initFunc == nil {
return fmt.Errorf("failed to init: unsupported VCS")
}
if err := initFunc(p); err != nil {
return err
}
_, err = fmt.Fprintln(w, p)
return err
}

func isNotExistOrEmpty(name string) (bool, error) {
f, err := os.Open(name)
if err != nil {
if os.IsNotExist(err) {
return true, nil
}
return false, err
}
defer f.Close()

_, err = f.Readdirnames(1)
if err == io.EOF {
return true, nil
}
return false, err
}
10 changes: 10 additions & 0 deletions cmdutil/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,16 @@ func RunInDirSilently(dir, command string, args ...string) error {
return RunCommand(cmd, true)
}

// RunInDirStderr run the command in the specified directory and prevent stdout output
func RunInDirStderr(dir, command string, args ...string) error {
cmd := exec.Command(command, args...)
cmd.Stdout = os.Stderr
cmd.Stderr = os.Stderr
cmd.Dir = dir

return RunCommand(cmd, true)
}

// RunFunc for the type command execution
type RunFunc func(*exec.Cmd) error

Expand Down
3 changes: 3 additions & 0 deletions commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,9 @@ var commandCreate = cli.Command{
Name: "create",
Usage: "Create repository",
Action: doCreate,
Flags: []cli.Flag{
&cli.StringFlag{Name: "vcs", Usage: "Specify VCS backend explicitly"},
},
}

type commandDoc struct {
Expand Down
9 changes: 3 additions & 6 deletions getter.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,6 @@ func (g *getter) get(argURL string) error {
return err
}

if !remote.IsValid() {
return fmt.Errorf("Not a valid repository: %s", u)
}

return g.getRemoteRepository(remote)
}

Expand Down Expand Up @@ -118,8 +114,9 @@ func (g *getter) getRemoteRepository(remote RemoteRepository) error {
}
if getRepoLock(localRepoRoot) {
return vcs.Update(&vcsGetOption{
dir: localRepoRoot,
silent: g.silent,
dir: localRepoRoot,
silent: g.silent,
recursive: g.recursive,
})
}
return nil
Expand Down
30 changes: 17 additions & 13 deletions remote_repository.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package main

import (
"fmt"
"net/url"
"strings"

Expand Down Expand Up @@ -149,18 +150,21 @@ func (repo *OtherRepository) VCS() (*VCSBackend, *url.URL) {
}

// NewRemoteRepository returns new RemoteRepository object from URL
func NewRemoteRepository(url *url.URL) (RemoteRepository, error) {
if url.Host == "github.com" {
return &GitHubRepository{url}, nil
func NewRemoteRepository(u *url.URL) (RemoteRepository, error) {
repo := func() RemoteRepository {
switch u.Host {
case "github.com":
return &GitHubRepository{u}
case "gist.github.com":
return &GitHubGistRepository{u}
case "hub.darcs.net":
return &DarksHubRepository{u}
default:
return &OtherRepository{u}
}
}()
if !repo.IsValid() {
return nil, fmt.Errorf("Not a valid repository: %s", u)
}

if url.Host == "gist.github.com" {
return &GitHubGistRepository{url}, nil
}

if url.Host == "hub.darcs.net" {
return &DarksHubRepository{url}, nil
}

return &OtherRepository{url}, nil
return repo, nil
}
19 changes: 19 additions & 0 deletions vcs.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ type VCSBackend struct {
Clone func(*vcsGetOption) error
// Updates a cloned local repository.
Update func(*vcsGetOption) error
Init func(dir string) error
// Returns VCS specific files
Contents []string
}
Expand Down Expand Up @@ -77,6 +78,9 @@ var GitBackend = &VCSBackend{
}
return nil
},
Init: func(dir string) error {
return cmdutil.RunInDirStderr(dir, "git", "init")
},
Contents: []string{".git"},
}

Expand Down Expand Up @@ -153,6 +157,9 @@ var MercurialBackend = &VCSBackend{
Update: func(vg *vcsGetOption) error {
return runInDir(vg.silent)(vg.dir, "hg", "pull", "--update")
},
Init: func(dir string) error {
return cmdutil.RunInDirStderr(dir, "hg", "init")
},
Contents: []string{".hg"},
}

Expand Down Expand Up @@ -180,6 +187,9 @@ var DarcsBackend = &VCSBackend{
Update: func(vg *vcsGetOption) error {
return runInDir(vg.silent)(vg.dir, "darcs", "pull")
},
Init: func(dir string) error {
return cmdutil.RunInDirStderr(dir, "darcs", "init")
},
Contents: []string{"_darcs"},
}

Expand Down Expand Up @@ -213,6 +223,12 @@ var FossilBackend = &VCSBackend{
Update: func(vg *vcsGetOption) error {
return runInDir(vg.silent)(vg.dir, "fossil", "update")
},
Init: func(dir string) error {
if err := cmdutil.RunInDirStderr(dir, "fossil", "init", fossilRepoName); err != nil {
return err
}
return cmdutil.RunInDirStderr(dir, "fossil", "open", fossilRepoName)
},
Contents: []string{".fslckout", "_FOSSIL_"},
}

Expand All @@ -234,6 +250,9 @@ var BazaarBackend = &VCSBackend{
// Without --overwrite bzr will not pull tags that changed.
return runInDir(vg.silent)(vg.dir, "bzr", "pull", "--overwrite")
},
Init: func(dir string) error {
return cmdutil.RunInDirStderr(dir, "bzr", "init")
},
Contents: []string{".bzr"},
}

Expand Down

0 comments on commit 9d53b27

Please sign in to comment.