Created
September 1, 2015 15:11
-
-
Save mattn/4bf77ec122e6cb618972 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
From aad1bc815162d4c55dbc8609b1dc650e1dc782a6 Mon Sep 17 00:00:00 2001 | |
From: mathhun <achemer@gmail.com> | |
Date: Fri, 22 May 2015 07:41:18 +0900 | |
Subject: [PATCH 1/6] Implement download cheats feature | |
--- | |
cheat.go | 93 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ | |
1 file changed, 93 insertions(+) | |
diff --git a/cheat.go b/cheat.go | |
index 4284c86..b5592eb 100644 | |
--- a/cheat.go | |
+++ b/cheat.go | |
@@ -8,6 +8,7 @@ import ( | |
"github.com/atotto/clipboard" | |
"github.com/codegangsta/cli" | |
"github.com/mattn/go-colorable" | |
+ "io" | |
"io/ioutil" | |
"os" | |
"os/exec" | |
@@ -37,6 +38,8 @@ func main() { | |
config := &JSONData{} | |
config.ReadConfig() | |
+ cheatsDirectory := path.Join(os.Getenv("HOME"), "/.cheatsheets") | |
+ | |
app.Commands = []cli.Command{ | |
{ | |
Name: "show", | |
@@ -94,6 +97,25 @@ func main() { | |
editCheat(rcfile, config.Editor) | |
}, | |
}, | |
+ { | |
+ Name: "download", | |
+ Usage: "Download cheats", | |
+ Flags: []cli.Flag{ | |
+ cli.StringFlag{ | |
+ Name: "dir, d", | |
+ Value: cheatsDirectory, | |
+ Usage: fmt.Sprintf("cheats directory (default: %s)", cheatsDirectory), | |
+ }, | |
+ cli.BoolFlag{ | |
+ Name: "verbose, v", | |
+ }, | |
+ }, | |
+ Action: func(c *cli.Context) { | |
+ url := "https://github.com/jahendrie/cheat" | |
+ exitCode := download(url, c.String("dir"), c.Bool("verbose")) | |
+ os.Exit(exitCode) | |
+ }, | |
+ }, | |
} | |
app.Run(os.Args) | |
@@ -159,3 +181,74 @@ func editCheat(cheatfile string, configEditor string) { | |
cmd.Stderr = os.Stderr | |
cmd.Run() | |
} | |
+ | |
+func download(url string, cheatsDir string, verbose bool) int { | |
+ cloneDir, err := ioutil.TempDir(os.TempDir(), "cheat") | |
+ if err != nil { | |
+ fmt.Fprintln(os.Stderr, err) | |
+ return 1 | |
+ } | |
+ | |
+ defer func() { | |
+ if verbose { | |
+ fmt.Fprintf(os.Stderr, "Removing temporary directory: %s\n", cloneDir) | |
+ } | |
+ os.RemoveAll(cloneDir) | |
+ }() | |
+ | |
+ if runGitClone(url, cloneDir, verbose) != nil { | |
+ fmt.Fprintln(os.Stderr, err) | |
+ return 1 | |
+ } | |
+ | |
+ if copyCheatFiles(path.Join(cloneDir, "data"), cheatsDir) != nil { | |
+ fmt.Fprintln(os.Stderr, err) | |
+ return 1 | |
+ } | |
+ | |
+ return 0 | |
+} | |
+ | |
+func runGitClone(url, dir string, verbose bool) error { | |
+ cmd := exec.Command("git", "clone", url, dir) | |
+ if verbose { | |
+ cmd.Stdout = os.Stdout | |
+ cmd.Stderr = os.Stderr | |
+ } | |
+ return cmd.Run() | |
+} | |
+ | |
+func copyCheatFiles(cloneDir, cheatsDir string) error { | |
+ files, err := ioutil.ReadDir(cloneDir) | |
+ if err != nil { | |
+ return err | |
+ } | |
+ | |
+ for _, f := range files { | |
+ err := copyFile(path.Join(cloneDir, f.Name()), path.Join(cheatsDir, f.Name())) | |
+ if err != nil { | |
+ return err | |
+ } | |
+ } | |
+ | |
+ return nil | |
+} | |
+ | |
+func copyFile(src, dst string) error { | |
+ s, err := os.Open(src) | |
+ if err != nil { | |
+ return err | |
+ } | |
+ defer s.Close() | |
+ | |
+ d, err := os.Create(dst) | |
+ if err != nil { | |
+ return err | |
+ } | |
+ if _, err := io.Copy(d, s); err != nil { | |
+ d.Close() | |
+ return err | |
+ } | |
+ | |
+ return d.Close() | |
+} | |
From bacf2e267e252b4ded5f332af0b300b55f5e9a37 Mon Sep 17 00:00:00 2001 | |
From: mathhun <achemer@gmail.com> | |
Date: Fri, 22 May 2015 07:49:34 +0900 | |
Subject: [PATCH 2/6] fix | |
--- | |
cheat.go | 6 ++---- | |
1 file changed, 2 insertions(+), 4 deletions(-) | |
diff --git a/cheat.go b/cheat.go | |
index b5592eb..f45f825 100644 | |
--- a/cheat.go | |
+++ b/cheat.go | |
@@ -38,8 +38,6 @@ func main() { | |
config := &JSONData{} | |
config.ReadConfig() | |
- cheatsDirectory := path.Join(os.Getenv("HOME"), "/.cheatsheets") | |
- | |
app.Commands = []cli.Command{ | |
{ | |
Name: "show", | |
@@ -103,8 +101,8 @@ func main() { | |
Flags: []cli.Flag{ | |
cli.StringFlag{ | |
Name: "dir, d", | |
- Value: cheatsDirectory, | |
- Usage: fmt.Sprintf("cheats directory (default: %s)", cheatsDirectory), | |
+ Value: config.Cheatdirs[0], | |
+ Usage: fmt.Sprintf("cheats directory (default: %s)", config.Cheatdirs[0]), | |
}, | |
cli.BoolFlag{ | |
Name: "verbose, v", | |
From 17ed59818a787c6c0dd149ae37a48d166002ad8a Mon Sep 17 00:00:00 2001 | |
From: mathhun <achemer@gmail.com> | |
Date: Fri, 22 May 2015 08:05:49 +0900 | |
Subject: [PATCH 3/6] Use Chris' repo as a cheat source | |
--- | |
cheat.go | 6 +++--- | |
1 file changed, 3 insertions(+), 3 deletions(-) | |
diff --git a/cheat.go b/cheat.go | |
index f45f825..847ff62 100644 | |
--- a/cheat.go | |
+++ b/cheat.go | |
@@ -96,7 +96,7 @@ func main() { | |
}, | |
}, | |
{ | |
- Name: "download", | |
+ Name: "fetch", | |
Usage: "Download cheats", | |
Flags: []cli.Flag{ | |
cli.StringFlag{ | |
@@ -109,7 +109,7 @@ func main() { | |
}, | |
}, | |
Action: func(c *cli.Context) { | |
- url := "https://github.com/jahendrie/cheat" | |
+ url := "https://github.com/chrisallenlane/cheat" | |
exitCode := download(url, c.String("dir"), c.Bool("verbose")) | |
os.Exit(exitCode) | |
}, | |
@@ -199,7 +199,7 @@ func download(url string, cheatsDir string, verbose bool) int { | |
return 1 | |
} | |
- if copyCheatFiles(path.Join(cloneDir, "data"), cheatsDir) != nil { | |
+ if copyCheatFiles(path.Join(cloneDir, "cheat", "cheatsheets"), cheatsDir) != nil { | |
fmt.Fprintln(os.Stderr, err) | |
return 1 | |
} | |
From 07a93f85ed2929e1c9d56103af82cb89def3f7ab Mon Sep 17 00:00:00 2001 | |
From: mathhun <achemer@gmail.com> | |
Date: Fri, 22 May 2015 08:09:07 +0900 | |
Subject: [PATCH 4/6] Rename | |
--- | |
cheat.go | 4 ++-- | |
1 file changed, 2 insertions(+), 2 deletions(-) | |
diff --git a/cheat.go b/cheat.go | |
index 847ff62..e630f5c 100644 | |
--- a/cheat.go | |
+++ b/cheat.go | |
@@ -110,7 +110,7 @@ func main() { | |
}, | |
Action: func(c *cli.Context) { | |
url := "https://github.com/chrisallenlane/cheat" | |
- exitCode := download(url, c.String("dir"), c.Bool("verbose")) | |
+ exitCode := fetchCheats(url, c.String("dir"), c.Bool("verbose")) | |
os.Exit(exitCode) | |
}, | |
}, | |
@@ -180,7 +180,7 @@ func editCheat(cheatfile string, configEditor string) { | |
cmd.Run() | |
} | |
-func download(url string, cheatsDir string, verbose bool) int { | |
+func fetchCheats(url string, cheatsDir string, verbose bool) int { | |
cloneDir, err := ioutil.TempDir(os.TempDir(), "cheat") | |
if err != nil { | |
fmt.Fprintln(os.Stderr, err) | |
From e1f9e9096f414eccd0394cbe6850cb5df352424a Mon Sep 17 00:00:00 2001 | |
From: mathhun <achemer@gmail.com> | |
Date: Sat, 23 May 2015 10:41:36 +0900 | |
Subject: [PATCH 5/6] Keep cloned repos and do git pull when exists | |
--- | |
cheat.go | 119 +++++++++++++++++++++++++++++++++++++++++++++++---------------- | |
1 file changed, 89 insertions(+), 30 deletions(-) | |
diff --git a/cheat.go b/cheat.go | |
index e630f5c..28ba51d 100644 | |
--- a/cheat.go | |
+++ b/cheat.go | |
@@ -10,6 +10,7 @@ import ( | |
"github.com/mattn/go-colorable" | |
"io" | |
"io/ioutil" | |
+ "net/url" | |
"os" | |
"os/exec" | |
"os/user" | |
@@ -97,21 +98,30 @@ func main() { | |
}, | |
{ | |
Name: "fetch", | |
- Usage: "Download cheats", | |
+ Usage: "Fetch cheats", | |
Flags: []cli.Flag{ | |
cli.StringFlag{ | |
Name: "dir, d", | |
Value: config.Cheatdirs[0], | |
- Usage: fmt.Sprintf("cheats directory (default: %s)", config.Cheatdirs[0]), | |
+ Usage: "cheats directory", | |
}, | |
- cli.BoolFlag{ | |
- Name: "verbose, v", | |
+ cli.StringFlag{ | |
+ Name: "repo, r", | |
+ Value: "https://github.com/chrisallenlane/cheat/cheat/cheatsheets", | |
+ Usage: "repository to fetch cheats from", | |
+ }, | |
+ cli.StringFlag{ | |
+ Name: "local, l", | |
+ Usage: "local path to store repository", | |
}, | |
}, | |
Action: func(c *cli.Context) { | |
- url := "https://github.com/chrisallenlane/cheat" | |
- exitCode := fetchCheats(url, c.String("dir"), c.Bool("verbose")) | |
- os.Exit(exitCode) | |
+ if c.String("local") == "" && os.Getenv("GOPATH") == "" { | |
+ fmt.Fprintf(os.Stderr, "Local path to store repo is required.\n") | |
+ return | |
+ } | |
+ | |
+ fetchCheats(c) | |
}, | |
}, | |
} | |
@@ -180,56 +190,105 @@ func editCheat(cheatfile string, configEditor string) { | |
cmd.Run() | |
} | |
-func fetchCheats(url string, cheatsDir string, verbose bool) int { | |
- cloneDir, err := ioutil.TempDir(os.TempDir(), "cheat") | |
+func fetchCheats(c *cli.Context) { | |
+ // parse repo url | |
+ repo, err := url.Parse(c.String("repo")) | |
if err != nil { | |
fmt.Fprintln(os.Stderr, err) | |
- return 1 | |
+ return | |
} | |
- defer func() { | |
- if verbose { | |
- fmt.Fprintf(os.Stderr, "Removing temporary directory: %s\n", cloneDir) | |
- } | |
- os.RemoveAll(cloneDir) | |
- }() | |
+ repoPath := strings.Split(repo.Path, "/") | |
+ if len(repoPath) <= 3 { | |
+ fmt.Fprintln(os.Stderr, "Invalid Repo URL") | |
+ return | |
+ } | |
- if runGitClone(url, cloneDir, verbose) != nil { | |
- fmt.Fprintln(os.Stderr, err) | |
- return 1 | |
+ cheatsPath := repoPath[3:] | |
+ repo.Path = fmt.Sprintf("/%s/%s", repoPath[1], repoPath[2]) | |
+ | |
+ // directory where the cloned repository is stored | |
+ var cloneDir string | |
+ if c.String("local") != "" { | |
+ cloneDir = c.String("local") | |
+ } else if os.Getenv("GOPATH") != "" { | |
+ cloneDir = path.Join(os.Getenv("GOPATH"), "src", repo.Host, repoPath[1], repoPath[2]) | |
} | |
- if copyCheatFiles(path.Join(cloneDir, "cheat", "cheatsheets"), cheatsDir) != nil { | |
+ // update the repo | |
+ updated, err := updateLocalRepo(repo.String(), cloneDir) | |
+ if err != nil { | |
fmt.Fprintln(os.Stderr, err) | |
- return 1 | |
+ return | |
} | |
- return 0 | |
+ // copy cheats | |
+ if updated { | |
+ srcPath := cloneDir | |
+ for _, p := range cheatsPath { | |
+ srcPath = path.Join(srcPath, p) | |
+ } | |
+ | |
+ count, err := copyCheatFiles(srcPath, c.String("dir")) | |
+ if err != nil { | |
+ fmt.Fprintln(os.Stderr, err) | |
+ } | |
+ fmt.Fprintf(os.Stderr, "%d cheats updated.\n", count) | |
+ } else { | |
+ fmt.Fprintf(os.Stderr, "No cheats updated.\n") | |
+ } | |
} | |
-func runGitClone(url, dir string, verbose bool) error { | |
- cmd := exec.Command("git", "clone", url, dir) | |
- if verbose { | |
+func updateLocalRepo(url, dir string) (bool, error) { | |
+ var cmd *exec.Cmd | |
+ | |
+ _, err := os.Stat(dir) | |
+ if os.IsNotExist(err) { | |
+ cmd = exec.Command("git", "clone", url, dir) | |
cmd.Stdout = os.Stdout | |
cmd.Stderr = os.Stderr | |
+ return true, cmd.Run() | |
+ } else { | |
+ cmd = exec.Command("git", "pull", url) | |
+ cmd.Dir = dir | |
+ out, err := cmd.CombinedOutput() | |
+ | |
+ res := string(out) | |
+ fmt.Fprint(os.Stderr, res) | |
+ | |
+ updated := true | |
+ if strings.Contains(res, "Already up-to-date.") { | |
+ updated = false | |
+ } | |
+ | |
+ return updated, err | |
} | |
- return cmd.Run() | |
} | |
-func copyCheatFiles(cloneDir, cheatsDir string) error { | |
+func copyCheatFiles(cloneDir, cheatsDir string) (int, error) { | |
+ fmt.Fprintf(os.Stderr, "Copying from %s to %s\n", cloneDir, cheatsDir) | |
+ count := 0 | |
+ | |
files, err := ioutil.ReadDir(cloneDir) | |
if err != nil { | |
- return err | |
+ return count, err | |
+ } | |
+ | |
+ err = os.MkdirAll(cheatsDir, 0755) | |
+ if err != nil { | |
+ return count, err | |
} | |
for _, f := range files { | |
+ count += 1 | |
+ | |
err := copyFile(path.Join(cloneDir, f.Name()), path.Join(cheatsDir, f.Name())) | |
if err != nil { | |
- return err | |
+ return count, err | |
} | |
} | |
- return nil | |
+ return count, nil | |
} | |
func copyFile(src, dst string) error { | |
From c1c580cff53a6e29f18cf2a56338a629f606b41d Mon Sep 17 00:00:00 2001 | |
From: mathhun <achemer@gmail.com> | |
Date: Tue, 1 Sep 2015 06:12:19 +0900 | |
Subject: [PATCH 6/6] Fix according to the suggested changes | |
--- | |
cheat.go | 17 +++++++++++------ | |
1 file changed, 11 insertions(+), 6 deletions(-) | |
diff --git a/cheat.go b/cheat.go | |
index 28ba51d..3d635f2 100644 | |
--- a/cheat.go | |
+++ b/cheat.go | |
@@ -212,7 +212,7 @@ func fetchCheats(c *cli.Context) { | |
if c.String("local") != "" { | |
cloneDir = c.String("local") | |
} else if os.Getenv("GOPATH") != "" { | |
- cloneDir = path.Join(os.Getenv("GOPATH"), "src", repo.Host, repoPath[1], repoPath[2]) | |
+ cloneDir = filepath.Join(os.Getenv("GOPATH"), "src", repo.Host, repoPath[1], repoPath[2]) | |
} | |
// update the repo | |
@@ -226,7 +226,7 @@ func fetchCheats(c *cli.Context) { | |
if updated { | |
srcPath := cloneDir | |
for _, p := range cheatsPath { | |
- srcPath = path.Join(srcPath, p) | |
+ srcPath = filepath.Join(srcPath, p) | |
} | |
count, err := copyCheatFiles(srcPath, c.String("dir")) | |
@@ -251,7 +251,11 @@ func updateLocalRepo(url, dir string) (bool, error) { | |
} else { | |
cmd = exec.Command("git", "pull", url) | |
cmd.Dir = dir | |
+ | |
out, err := cmd.CombinedOutput() | |
+ if err != nil { | |
+ return false, err | |
+ } | |
res := string(out) | |
fmt.Fprint(os.Stderr, res) | |
@@ -261,7 +265,7 @@ func updateLocalRepo(url, dir string) (bool, error) { | |
updated = false | |
} | |
- return updated, err | |
+ return updated, nil | |
} | |
} | |
@@ -282,7 +286,7 @@ func copyCheatFiles(cloneDir, cheatsDir string) (int, error) { | |
for _, f := range files { | |
count += 1 | |
- err := copyFile(path.Join(cloneDir, f.Name()), path.Join(cheatsDir, f.Name())) | |
+ err := copyFile(filepath.Join(cloneDir, f.Name()), filepath.Join(cheatsDir, f.Name())) | |
if err != nil { | |
return count, err | |
} | |
@@ -302,10 +306,11 @@ func copyFile(src, dst string) error { | |
if err != nil { | |
return err | |
} | |
+ defer d.Close() | |
+ | |
if _, err := io.Copy(d, s); err != nil { | |
- d.Close() | |
return err | |
} | |
- return d.Close() | |
+ return nil | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment