Skip to content

Commit

Permalink
Merge branch 'gogf:master' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
swift-fs authored Jun 19, 2024
2 parents e2c450c + 4abb32e commit 1f5e375
Show file tree
Hide file tree
Showing 28 changed files with 613 additions and 732 deletions.
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
}
61 changes: 45 additions & 16 deletions cmd/gf/internal/cmd/cmd_run.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ package cmd
import (
"context"
"fmt"
"os"
"path/filepath"
"runtime"
"strings"
Expand Down Expand Up @@ -55,7 +56,7 @@ The "run" command is used for running go codes with hot-compiled-like feature,
which compiles and runs the go codes asynchronously when codes change.
`
cRunFileBrief = `building file path.`
cRunPathBrief = `output directory path for built binary file. it's "manifest/output" in default`
cRunPathBrief = `output directory path for built binary file. it's "./" in default`
cRunExtraBrief = `the same options as "go run"/"go build" except some options as follows defined`
cRunArgsBrief = `custom arguments for your process`
cRunWatchPathsBrief = `watch additional paths for live reload, separated by ",". i.e. "manifest/config/*.yaml"`
Expand Down Expand Up @@ -104,13 +105,14 @@ func (c cRun) Index(ctx context.Context, in cRunInput) (out *cRunOutput, err err

app := &cRunApp{
File: in.File,
Path: in.Path,
Path: filepath.FromSlash(in.Path),
Options: in.Extra,
Args: in.Args,
WatchPaths: in.WatchPaths,
}
dirty := gtype.NewBool()

var outputPath = app.genOutputPath()
callbackFunc := func(event *gfsnotify.Event) {
if gfile.ExtName(event.Path) != "go" {
return
Expand All @@ -125,7 +127,7 @@ func (c cRun) Index(ctx context.Context, in cRunInput) (out *cRunOutput, err err
gtimer.SetTimeout(ctx, 1500*gtime.MS, func(ctx context.Context) {
defer dirty.Set(false)
mlog.Printf(`watched file changes: %s`, event.String())
app.Run(ctx)
app.Run(ctx, outputPath)
})
}

Expand All @@ -143,24 +145,21 @@ func (c cRun) Index(ctx context.Context, in cRunInput) (out *cRunOutput, err err
}
}

go app.Run(ctx)
go app.Run(ctx, outputPath)

gproc.AddSigHandlerShutdown(func(sig os.Signal) {
app.End(ctx, sig, outputPath)
os.Exit(0)
})
gproc.Listen()

select {}
}

func (app *cRunApp) Run(ctx context.Context) {
func (app *cRunApp) Run(ctx context.Context, outputPath string) {
// Rebuild and run the codes.
renamePath := ""
mlog.Printf("build: %s", app.File)
outputPath := gfile.Join(app.Path, gfile.Name(app.File))
if runtime.GOOS == "windows" {
outputPath += ".exe"
if gfile.Exists(outputPath) {
renamePath = outputPath + "~"
if err := gfile.Rename(outputPath, renamePath); err != nil {
mlog.Print(err)
}
}
}

// In case of `pipe: too many open files` error.
// Build the app.
buildCommand := fmt.Sprintf(
Expand Down Expand Up @@ -198,6 +197,36 @@ func (app *cRunApp) Run(ctx context.Context) {
}
}

func (app *cRunApp) End(ctx context.Context, sig os.Signal, outputPath string) {
// Delete the binary file.
// firstly, kill the process.
if process != nil {
if err := process.Kill(); err != nil {
mlog.Debugf("kill process error: %s", err.Error())
}
}
if err := gfile.Remove(outputPath); err != nil {
mlog.Printf("delete binary file error: %s", err.Error())
} else {
mlog.Printf("deleted binary file: %s", outputPath)
}
}

func (app *cRunApp) genOutputPath() (outputPath string) {
var renamePath string
outputPath = gfile.Join(app.Path, gfile.Name(app.File))
if runtime.GOOS == "windows" {
outputPath += ".exe"
if gfile.Exists(outputPath) {
renamePath = outputPath + "~"
if err := gfile.Rename(outputPath, renamePath); err != nil {
mlog.Print(err)
}
}
}
return filepath.FromSlash(outputPath)
}

func matchWatchPaths(watchPaths []string, eventPath string) bool {
for _, path := range watchPaths {
absPath, err := filepath.Abs(path)
Expand Down
1 change: 1 addition & 0 deletions cmd/gf/internal/cmd/gendao/gendao.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ generated json tag case for model struct, cases are as follows:
tplVarGroupName = `{TplGroupName}`
tplVarDatetimeStr = `{TplDatetimeStr}`
tplVarCreatedAtDatetimeStr = `{TplCreatedAtDatetimeStr}`
tplVarPackageName = `{TplPackageName}`
)

var (
Expand Down
1 change: 1 addition & 0 deletions cmd/gf/internal/cmd/gendao/gendao_dao.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ func generateDaoIndex(in generateDaoIndexInput) {
tplVarTableName: in.TableName,
tplVarTableNameCamelCase: in.TableNameCamelCase,
tplVarTableNameCamelLowerCase: in.TableNameCamelLowerCase,
tplVarPackageName: filepath.Base(in.DaoPath),
})
indexContent = replaceDefaultVar(in.CGenDaoInternalInput, indexContent)
if err := gfile.PutContents(path, strings.TrimSpace(indexContent)); err != nil {
Expand Down
1 change: 1 addition & 0 deletions cmd/gf/internal/cmd/gendao/gendao_do.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ func generateDoContent(
tplVarPackageImports: getImportPartContent(ctx, structDefine, true, nil),
tplVarTableNameCamelCase: tableNameCamelCase,
tplVarStructDefine: structDefine,
tplVarPackageName: filepath.Base(in.DoPath),
},
)
doContent = replaceDefaultVar(in, doContent)
Expand Down
1 change: 1 addition & 0 deletions cmd/gf/internal/cmd/gendao/gendao_entity.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ func generateEntityContent(
tplVarPackageImports: getImportPartContent(ctx, structDefine, false, appendImports),
tplVarTableNameCamelCase: tableNameCamelCase,
tplVarStructDefine: structDefine,
tplVarPackageName: filepath.Base(in.EntityPath),
},
)
entityContent = replaceDefaultVar(in, entityContent)
Expand Down
2 changes: 1 addition & 1 deletion cmd/gf/internal/consts/consts_gen_dao_template_dao.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const TemplateGenDaoIndexContent = `
// This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish.
// =================================================================================
package dao
package {TplPackageName}
import (
"{TplImportPrefix}/internal"
Expand Down
2 changes: 1 addition & 1 deletion cmd/gf/internal/consts/consts_gen_dao_template_do.go

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

2 changes: 1 addition & 1 deletion cmd/gf/internal/consts/consts_gen_dao_template_entity.go

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

Loading

0 comments on commit 1f5e375

Please sign in to comment.