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

feat(cmd/gf): add command gf doc for local documentation #3634

Merged
merged 7 commits into from
Jun 12, 2024
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
1 change: 1 addition & 0 deletions cmd/gf/gfcmd/gfcmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ func GetCommand(ctx context.Context) (*Command, error) {
cmd.Docker,
cmd.Install,
cmd.Version,
cmd.Doc,
)
if err != nil {
return nil, err
Expand Down
177 changes: 177 additions & 0 deletions cmd/gf/internal/cmd/cmd_doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
// Copyright GoFrame gf Author(https://goframe.org). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://github.com/gogf/gf.

package cmd

import (
"context"
"io"
"net/http"
"os"
"path"
"path/filepath"
"time"

"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
"github.com/gogf/gf/v2/encoding/gcompress"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gfile"
)

const (
// DocURL is the download address of the document
DocURL = "https://github.com/gogf/gf/archive/refs/heads/gh-pages.zip"
)

var (
Doc = cDoc{}
)

type cDoc struct {
g.Meta `name:"doc" brief:"download https://pages.goframe.org/ to run locally"`
}

type cDocInput struct {
g.Meta `name:"doc" config:"gfcli.doc"`
Path string `short:"p" name:"path" brief:"download docs directory path, default is \"%temp%/goframe\""`
Port int `short:"o" name:"port" brief:"http server port, default is 8080" d:"8080"`
Update bool `short:"u" name:"update" brief:"clean docs directory and update docs"`
Clean bool `short:"c" name:"clean" brief:"clean docs directory"`
Proxy string `short:"x" name:"proxy" brief:"proxy for download, such as https://hub.gitmirror.com/;https://ghproxy.com/;https://ghproxy.net/;https://ghps.cc/"`
}

type cDocOutput struct{}

func (c cDoc) Index(ctx context.Context, in cDocInput) (out *cDocOutput, err error) {
docs := NewDocSetting(ctx, in)
mlog.Print("Directory where the document is downloaded:", docs.TempDir)
if in.Clean {
mlog.Print("Cleaning document directory")
err = docs.Clean()
if err != nil {
mlog.Print("Failed to clean document directory:", err)
return
}
return
}
if in.Update {
mlog.Print("Cleaning old document directory")
err = docs.Clean()
if err != nil {
mlog.Print("Failed to clean old document directory:", err)
return
}
}
err = docs.DownloadDoc()
if err != nil {
mlog.Print("Failed to download document:", err)
return
}
s := g.Server()
s.SetServerRoot(docs.DocDir)
s.SetPort(in.Port)
s.SetDumpRouterMap(false)
mlog.Printf("Access address http://127.0.0.1:%d", in.Port)
s.Run()
return
}

// DocSetting doc setting
type DocSetting struct {
TempDir string
DocURL string
DocDir string
DocZipFile string
}

// NewDocSetting new DocSetting
func NewDocSetting(ctx context.Context, in cDocInput) *DocSetting {
fileName := "gf-doc-md.zip"
tempDir := in.Path
if tempDir == "" {
tempDir = gfile.Temp("goframe/docs")
} else {
tempDir = gfile.Abs(path.Join(tempDir, "docs"))
}

return &DocSetting{
TempDir: filepath.FromSlash(tempDir),
DocDir: filepath.FromSlash(path.Join(tempDir, "gf-gh-pages")),
DocURL: in.Proxy + DocURL,
DocZipFile: filepath.FromSlash(path.Join(tempDir, fileName)),
}

}

// Clean clean the temporary directory
func (d *DocSetting) Clean() error {
if _, err := os.Stat(d.TempDir); err == nil {
err = gfile.Remove(d.TempDir)
if err != nil {
mlog.Print("Failed to delete temporary directory:", err)
return err
}
}
return nil
}

// DownloadDoc download the document
func (d *DocSetting) DownloadDoc() error {
if _, err := os.Stat(d.TempDir); err != nil {
err = gfile.Mkdir(d.TempDir)
if err != nil {
mlog.Print("Failed to create temporary directory:", err)
return nil
}
}
// Check if the file exists
if _, err := os.Stat(d.DocDir); err == nil {
mlog.Print("Document already exists, no need to download and unzip")
return nil
}

if _, err := os.Stat(d.DocZipFile); err == nil {
mlog.Print("File already exists, no need to download")
} else {
mlog.Printf("File does not exist, start downloading: %s", d.DocURL)
startTime := time.Now()
// Download the file
resp, err := http.Get(d.DocURL)
if err != nil {
mlog.Print("Failed to download file:", err)
return err
}
defer resp.Body.Close()

// Create the file
out, err := os.Create(d.DocZipFile)
if err != nil {
mlog.Print("Failed to create file:", err)
return err
}
defer out.Close()

// Write the response body to the file
_, err = io.Copy(out, resp.Body)
if err != nil {
mlog.Print("Failed to write file:", err)
return err
}
mlog.Printf("Download successful, time-consuming: %v", time.Since(startTime))
}

mlog.Print("Start unzipping the file...")
// Unzip the file
err := gcompress.UnZipFile(d.DocZipFile, d.TempDir)
if err != nil {
mlog.Print("Failed to unzip the file, please run again:", err)
gfile.Remove(d.DocZipFile)
return err
}

mlog.Print("Download and unzip successful")
return nil
}