Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Gnorm docs #34

Merged
merged 2 commits into from
Sep 20, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion Gopkg.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ go get gnorm.org/gnorm
```

However, using go get to install will mean that `gnorm version` doesn't report
the correct data.
the correct data, and `gnorm docs` won't show you the docs in your browser.

For best results, use the go "makefile" in the root of the repo, which will do
all the build-time magic:
Expand Down
14 changes: 14 additions & 0 deletions cli/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (

"github.com/pkg/errors"
"github.com/spf13/cobra"

"gnorm.org/gnorm/environ"
"gnorm.org/gnorm/run"
)
Expand Down Expand Up @@ -111,6 +112,19 @@ Creates a default gnorm.toml and the various template files needed to run GNORM.
}
}

func docCmd(env environ.Values) *cobra.Command {
return &cobra.Command{
Use: "docs",
Short: "Runs a local webserver serving gnorm documentation.",
Long: `
Starts a web server running at localhost:8080 that serves docs for this version
of Gnorm.`[1:],
RunE: func(cmd *cobra.Command, args []string) error {
return showDocs(env, cmd, args)
},
}
}

func createFile(name, contents string) error {
f, err := os.OpenFile(name, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0600)
if err != nil {
Expand Down
40 changes: 40 additions & 0 deletions cli/docs_make.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
//+build make

package cli

import (
"fmt"
"log"
"net/http"

"github.com/pkg/browser"
"github.com/pkg/errors"
"github.com/rakyll/statik/fs"
"github.com/spf13/cobra"

_ "gnorm.org/gnorm/cli/statik"
"gnorm.org/gnorm/environ"
)

func showDocs(env environ.Values, cmd *cobra.Command, args []string) error {
// this folder gets briefly copied here during go run make.go
statikFS, err := fs.New()
if err != nil {
log.Fatal(err)
}

http.Handle("/", http.FileServer(statikFS))
fmt.Fprintln(env.Stdout, "serving docs at http://localhost:8080")
fmt.Fprintln(env.Stdout, "hit ctrl-C to cancel")
go func() {
if err := browser.OpenURL("http://localhost:8080"); err != nil {
fmt.Println("failed to open browser")
}
}()
err = http.ListenAndServe(":8080", nil)
if err != nil {
return codeErr{errors.WithMessage(err, "can't serve docs"), 1}
}

return nil
}
17 changes: 17 additions & 0 deletions cli/docs_nomake.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
//+build !make

package cli

import (
"fmt"

"github.com/spf13/cobra"

"gnorm.org/gnorm/environ"
)

func showDocs(env environ.Values, cmd *cobra.Command, args []string) error {
fmt.Fprintln(env.Stdout, "docs not available, you need to build with go run make.go")

return nil
}
1 change: 1 addition & 0 deletions cli/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ runnable code. See full docs at https://gnorm.org`[1:],
rootCmd.AddCommand(genCmd(env))
rootCmd.AddCommand(versionCmd(env))
rootCmd.AddCommand(initCmd(env))
rootCmd.AddCommand(docCmd(env))
return code(rootCmd.Execute())
}

Expand Down
1 change: 1 addition & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
//go:generate gocog ./site/content/cli/commands/version.md --startmark={{{ --endmark=}}}
//go:generate gocog ./site/content/cli/commands/init.md --startmark={{{ --endmark=}}}
//go:generate gocog ./site/content/cli/commands/gen.md --startmark={{{ --endmark=}}}
//go:generate gocog ./site/content/cli/commands/docs.md --startmark={{{ --endmark=}}}
//go:generate gocog ./site/content/templates/functions.md --startmark={{{ --endmark=}}}
//go:generate gocog ./site/content/cli/configuration.md --startmark={{{ --endmark=}}}

Expand Down
134 changes: 105 additions & 29 deletions make.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,85 +5,161 @@
package main

import (
"flag"
"fmt"
"io/ioutil"
"log"
"os"
"os/exec"
"strings"
"time"
)

const usage = `usage: go run make.go [command]
const usage = `
usage: go run make.go [flags] [command]

make.go is the build script for gnorm.

flags:

-v show verbose output

commands:
install compile with go install [default]
all build for all supported platforms
help display this help
`

var verbose = false

func main() {
switch len(os.Args) {
log.SetFlags(0)
flag.BoolVar(&verbose, "v", false, "")
flag.Parse()
if !verbose {
log.SetOutput(ioutil.Discard)
}
if len(flag.Args()) > 1 {
Fatal("invalid args" + usage)
}

genSite()
log.Print("downloading statik")
run("go", "get", "github.com/rakyll/statik")
log.Print("generating statik embedded files")
run("statik", "-f", "-src", "./cli/public", "-dest", "./cli")
defer func() {
log.Print("removing generated hugo site")
mustRemove("./cli/public")
log.Print("removing generated statik package")
mustRemove("./cli/statik")
}()
switch len(flag.Args()) {
case 0:
// (default)
log.Print("running go install")
run("go", "install", "-tags", "make", "--ldflags="+flags(), "gnorm.org/gnorm")
case 1:
fmt.Print(run("go", "install", "--ldflags="+flags(), "gnorm.org/gnorm"))
case 2:
switch os.Args[1] {
switch flag.Args()[1] {
case "install":
fmt.Print(run("go", "install", "--ldflags="+flags(), "gnorm.org/gnorm"))
log.Print("running go install")
run("go", "install", "-tags", "make", "--ldflags="+flags(), "gnorm.org/gnorm")
case "all":
ldf := flags()
for _, OS := range []string{"windows", "darwin", "linux"} {
if err := os.Setenv("GOOS", OS); err != nil {
fmt.Println(err)
os.Exit(1)
}
for _, ARCH := range []string{"amd64", "386"} {
if err := os.Setenv("GOOS", OS); err != nil {
fmt.Println(err)
os.Exit(1)
}
fmt.Print(run("go", "build", "-o", "gnorm_"+OS+"_"+ARCH, "--ldflags="+ldf, "gnorm.org/gnorm"))
}
}
makeAll()
case "help":
fmt.Println(usage)
log.Print(usage)
default:
fmt.Println(usage)
os.Exit(1)
Fatal(usage)
}
default:
// we already checked for this, but just in case
Fatal("invalid args" + usage)
}
}

func makeAll() {
ldf := flags()
for _, OS := range []string{"windows", "darwin", "linux"} {
if err := os.Setenv("GOOS", OS); err != nil {
Fatal(err)
}
for _, ARCH := range []string{"amd64", "386"} {
if err := os.Setenv("GOOS", OS); err != nil {
Fatal(err)
}
log.Printf("running go build for GOOS=%s GOARCH=%s", OS, ARCH)
run("go", "build", "-tags", "make", "-o", "gnorm_"+OS+"_"+ARCH, "--ldflags="+ldf)
}
}
}

func flags() string {
timestamp := time.Now().Format(time.RFC3339)
hash := run("git", "rev-parse", "HEAD")
hash := output("git", "rev-parse", "HEAD")
version := gitTag()
return fmt.Sprintf(`-X "gnorm.org/gnorm/cli.timestamp=%s" -X "gnorm.org/gnorm/cli.commitHash=%s" -X "gnorm.org/gnorm/cli.version=%s"`, timestamp, hash, version)
}

func run(cmd string, args ...string) string {
func run(cmd string, args ...string) {
c := exec.Command(cmd, args...)
c.Stderr = os.Stderr
if verbose {
c.Stdout = os.Stdout
}
err := c.Run()
if err != nil {
Fatal(err)
}
}

func output(cmd string, args ...string) string {
c := exec.Command(cmd, args...)
c.Stderr = os.Stderr
b, err := c.Output()
if err != nil {
fmt.Print(string(b))
os.Exit(1)
log.Print(string(b))
Fatal(err)
}
return string(b)
}

func gitTag() string {
c := exec.Command("git", "describe", "--tags")
c.Stderr = os.Stderr
b, err := c.Output()
if err != nil {
exit, ok := err.(*exec.ExitError)
if ok && exit.Exited() {
// probably no git tag
return "dev"
}
fmt.Print(string(b))
os.Exit(1)
Fatal(string(b))
}

return strings.TrimSuffix(string(b), "\n")
}

func genSite() {
log.Print("cleaning up any existing hugo generated files")
mustRemove("./cli/public")
log.Print("downloading hugo")
run("go", "get", "github.com/gohugoio/hugo")
log.Print("generating docs site")
run("hugo", "-s", "./site", "-d", "../cli/public")
log.Print("removing fonts from generated site")
// fonts are BIG
mustRemove("./cli/public/fonts")
mustRemove("./cli/public/revealjs/lib/font")
}

func mustRemove(s string) {
err := os.RemoveAll(s)
if !os.IsNotExist(err) && err != nil {
log.Fatal(err)
}
}

func Fatal(args ...interface{}) {
log.SetOutput(os.Stdout)
log.Fatal(args...)
}
1 change: 1 addition & 0 deletions site/content/cli/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ Usage:
gnorm [command]

Available Commands:
docs Runs a local webserver serving gnorm documentation.
gen Generate code from DB schema
help Help about any command
init Generates the files needed to run GNORM.
Expand Down
39 changes: 39 additions & 0 deletions site/content/cli/commands/docs.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
+++
title= "docs"
date= 2017-08-17T13:16:04-04:00
description = ""
+++

<!-- {{{gocog
package main
import (
"fmt"
"os"
"gnorm.org/gnorm/cli"
"gnorm.org/gnorm/environ"
)
func main() {
fmt.Println("```\ngnorm docs\n")
os.Stderr = os.Stdout
x := cli.ParseAndRun(environ.Values{
Stderr: os.Stdout,
Stdout: os.Stdout,
Args: []string{"help", "docs"},
})
fmt.Println("```")
os.Exit(x)
}
gocog}}} -->
```
gnorm docs

Starts a web server running at localhost:8080 that serves docs for this version
of Gnorm.

Usage:
gnorm docs [flags]

Flags:
-h, --help help for docs
```
<!-- {{{end}}} -->
Loading