mirror of
https://gitee.com/johng/gf
synced 2026-06-18 14:27:31 +08:00
Compare commits
3 Commits
feat/gdb-p
...
fix/3108
| Author | SHA1 | Date | |
|---|---|---|---|
| b500b715bf | |||
| 10573cd694 | |||
| 9aa2745684 |
4
.github/FUNDING.yml
vendored
4
.github/FUNDING.yml
vendored
@ -1,6 +1,6 @@
|
|||||||
# These are supported funding model platforms
|
# These are supported funding model platforms
|
||||||
|
|
||||||
github: [gogf] # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
|
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
|
||||||
patreon: # Replace with a single Patreon username
|
patreon: # Replace with a single Patreon username
|
||||||
open_collective: # Replace with a single Open Collective username
|
open_collective: # Replace with a single Open Collective username
|
||||||
ko_fi: # Replace with a single Ko-fi username
|
ko_fi: # Replace with a single Ko-fi username
|
||||||
@ -9,4 +9,4 @@ community_bridge: # Replace with a single Community Bridge project-name e.g., cl
|
|||||||
liberapay: # Replace with a single Liberapay username
|
liberapay: # Replace with a single Liberapay username
|
||||||
issuehunt: # Replace with a single IssueHunt username
|
issuehunt: # Replace with a single IssueHunt username
|
||||||
otechie: # Replace with a single Otechie username
|
otechie: # Replace with a single Otechie username
|
||||||
custom: # custom
|
custom: https://github.com/gogf/gf#donators
|
||||||
|
|||||||
38
.github/ISSUE_TEMPLATE.MD
vendored
Normal file
38
.github/ISSUE_TEMPLATE.MD
vendored
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
<!-- Please answer these questions before submitting your issue. Thanks! -->
|
||||||
|
|
||||||
|
<!-- 为高效处理您的疑问,如果觉得是BUG类问题,请您务必提供可复现该问题的最小可运行代码!否则issue可能会被延期处理! -->
|
||||||
|
<!-- 为高效处理您的疑问,如果觉得是BUG类问题,请您务必提供可复现该问题的最小可运行代码!否则issue可能会被延期处理! -->
|
||||||
|
<!-- 为高效处理您的疑问,如果觉得是BUG类问题,请您务必提供可复现该问题的最小可运行代码!否则issue可能会被延期处理! -->
|
||||||
|
<!-- 重要的事情说三遍! -->
|
||||||
|
|
||||||
|
### 1. What version of `Go` and system type/arch are you using?
|
||||||
|
<!--
|
||||||
|
Please paste the output of command `go version` from your terminal.
|
||||||
|
What expect to see is like: `go 1.12, linux/amd64`
|
||||||
|
-->
|
||||||
|
|
||||||
|
|
||||||
|
### 2. What version of `GoFrame` are you using?
|
||||||
|
<!-- You can find the GF version from your `go.mod`, or from the `version.go` in `GF` -->
|
||||||
|
|
||||||
|
|
||||||
|
### 3. Can this issue be re-produced with the latest release?
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### 4. What did you do?
|
||||||
|
<!--
|
||||||
|
If possible, provide a copy of shortest codes for reproducing the error.
|
||||||
|
A complete runnable program is best.
|
||||||
|
-->
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### 5. What did you expect to see?
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### 6. What did you see instead?
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
71
.github/ISSUE_TEMPLATE/00-bug.yml
vendored
71
.github/ISSUE_TEMPLATE/00-bug.yml
vendored
@ -1,71 +0,0 @@
|
|||||||
# https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/configuring-issue-templates-for-your-repository#creating-issue-forms
|
|
||||||
# https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-githubs-form-schema
|
|
||||||
name: Bugs
|
|
||||||
description: GoFrame command, module, or anything else
|
|
||||||
title: "os/gtime: issue title"
|
|
||||||
labels:
|
|
||||||
- bug
|
|
||||||
|
|
||||||
body:
|
|
||||||
- type: markdown
|
|
||||||
attributes:
|
|
||||||
value: |
|
|
||||||
Thanks for helping us improve! 🙏 Please answer these questions and provide as much information as possible about your problem.
|
|
||||||
|
|
||||||
The issue title uses the format of the package name goes before the colon. Thanks!
|
|
||||||
|
|
||||||
标题使用包名在冒号前的格式!谢谢!
|
|
||||||
|
|
||||||
- type: input
|
|
||||||
id: go-version
|
|
||||||
attributes:
|
|
||||||
label: Go version
|
|
||||||
description: |
|
|
||||||
What version of Go are you using (`go version`)?
|
|
||||||
placeholder: ex. go version go1.20.7 darwin/arm64
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: input
|
|
||||||
id: gf-version
|
|
||||||
attributes:
|
|
||||||
label: GoFrame version
|
|
||||||
description: |
|
|
||||||
What version of GoFrame are you using (`gf version`)?
|
|
||||||
placeholder: ex. 2.7.0
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: dropdown
|
|
||||||
id: is-reproducible
|
|
||||||
attributes:
|
|
||||||
label: Can this bug be reproduced with the latest release?
|
|
||||||
options:
|
|
||||||
- Option Yes
|
|
||||||
- Option No
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
id: what-did-you-do
|
|
||||||
attributes:
|
|
||||||
label: "What did you do?"
|
|
||||||
description: "If possible, provide a recipe for reproducing the error. A complete runnable program is good. A link on [go.dev/play](https://go.dev/play) is best."
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
id: actual-behavior
|
|
||||||
attributes:
|
|
||||||
label: "What did you see happen?"
|
|
||||||
description: Command invocations and their associated output, functions with their arguments and return results, full stacktraces for panics (upload a file if it is very long), etc. Prefer copying text output over using screenshots.
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
id: expected-behavior
|
|
||||||
attributes:
|
|
||||||
label: "What did you expect to see?"
|
|
||||||
description: Why is the current output incorrect, and any additional context we may need to understand the issue.
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
32
.github/ISSUE_TEMPLATE/01-enhance.yml
vendored
32
.github/ISSUE_TEMPLATE/01-enhance.yml
vendored
@ -1,32 +0,0 @@
|
|||||||
# https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/configuring-issue-templates-for-your-repository#creating-issue-forms
|
|
||||||
# https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-githubs-form-schema
|
|
||||||
name: Enhancements
|
|
||||||
description: Enhance an idea for this project
|
|
||||||
title: "os/gtime: issue title"
|
|
||||||
labels:
|
|
||||||
- enhancement
|
|
||||||
|
|
||||||
body:
|
|
||||||
- type: markdown
|
|
||||||
attributes:
|
|
||||||
value: |
|
|
||||||
Thanks for helping us improve! 🙏 Please answer these questions and provide as much information as possible about your problem.
|
|
||||||
|
|
||||||
The issue title uses the format of the package name goes before the colon. Thanks!
|
|
||||||
|
|
||||||
标题使用包名在冒号前的格式!谢谢!
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
id: description
|
|
||||||
attributes:
|
|
||||||
label: "Description"
|
|
||||||
description: "Please describe your idea in detail."
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
id: additional
|
|
||||||
attributes:
|
|
||||||
label: "Additional"
|
|
||||||
validations:
|
|
||||||
required: false
|
|
||||||
48
.github/ISSUE_TEMPLATE/02-feature.yml
vendored
48
.github/ISSUE_TEMPLATE/02-feature.yml
vendored
@ -1,48 +0,0 @@
|
|||||||
# https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/configuring-issue-templates-for-your-repository#creating-issue-forms
|
|
||||||
# https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-githubs-form-schema
|
|
||||||
name: Features
|
|
||||||
description: Suggest an idea for this project
|
|
||||||
title: "os/gtime: issue title"
|
|
||||||
labels:
|
|
||||||
- feature
|
|
||||||
|
|
||||||
body:
|
|
||||||
- type: markdown
|
|
||||||
attributes:
|
|
||||||
value: |
|
|
||||||
Thanks for helping us improve! 🙏 Please answer these questions and provide as much information as possible about your problem.
|
|
||||||
|
|
||||||
The issue title uses the format of the package name goes before the colon. Thanks!
|
|
||||||
|
|
||||||
标题使用包名在冒号前的格式!谢谢!
|
|
||||||
|
|
||||||
- type: dropdown
|
|
||||||
id: is-problem
|
|
||||||
attributes:
|
|
||||||
label: Is your feature request related to a problem?
|
|
||||||
options:
|
|
||||||
- Option Yes
|
|
||||||
- Option No
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
id: description-solution
|
|
||||||
attributes:
|
|
||||||
label: "Describe the solution you'd like"
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
id: description-considered
|
|
||||||
attributes:
|
|
||||||
label: "Describe alternatives you've considered"
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
id: additional
|
|
||||||
attributes:
|
|
||||||
label: "Additional"
|
|
||||||
validations:
|
|
||||||
required: false
|
|
||||||
25
.github/ISSUE_TEMPLATE/03-question.yml
vendored
25
.github/ISSUE_TEMPLATE/03-question.yml
vendored
@ -1,25 +0,0 @@
|
|||||||
# https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/configuring-issue-templates-for-your-repository#creating-issue-forms
|
|
||||||
# https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-githubs-form-schema
|
|
||||||
name: Questions
|
|
||||||
description: I want to ask a question
|
|
||||||
title: "os/gtime: issue title"
|
|
||||||
labels:
|
|
||||||
- question
|
|
||||||
|
|
||||||
body:
|
|
||||||
- type: markdown
|
|
||||||
attributes:
|
|
||||||
value: |
|
|
||||||
Please read the document carefully. 请先仔细阅读文档
|
|
||||||
|
|
||||||
The issue title uses the format of the package name goes before the colon. Thanks!
|
|
||||||
|
|
||||||
标题使用包名在冒号前的格式!谢谢!
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
id: ask
|
|
||||||
attributes:
|
|
||||||
label: "What do you want to ask?"
|
|
||||||
description: "Please describe the details of your questions. 请详细描述你的问题。"
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
44
.github/PULL_REQUEST_TEMPLATE.MD
vendored
44
.github/PULL_REQUEST_TEMPLATE.MD
vendored
@ -1,44 +0,0 @@
|
|||||||
**Please ensure you adhere to every item in this list.**
|
|
||||||
+ The PR title is formatted as follows: `<type>[optional scope]: <description>` For example, `fix(os/gtime): fix time zone issue`
|
|
||||||
+ `<type>` is mandatory and can be one of `fix`, `feat`, `build`, `ci`, `docs`, `style`, `refactor`, `perf`, `test`, `chore`
|
|
||||||
+ `fix`: Used when a bug has been fixed.
|
|
||||||
+ `feat`: Used when a new feature has been added.
|
|
||||||
+ `build`: Used for modifications to the project build system, such as changes to dependencies, external interfaces, or upgrading Node version.
|
|
||||||
+ `ci`: Used for modifications to continuous integration processes, such as changes to Travis, Jenkins workflow configurations.
|
|
||||||
+ `docs`: Used for modifications to documentation, such as changes to README files, API documentation, etc.
|
|
||||||
+ `style`: Used for changes to code style, such as adjustments to indentation, spaces, blank lines, etc.
|
|
||||||
+ `refactor`: Used for code refactoring, such as changes to code structure, variable names, function names, without altering functionality.
|
|
||||||
+ `perf`: Used for performance optimization, such as improving code performance, reducing memory usage, etc.
|
|
||||||
+ `test`: Used for modifications to test cases, such as adding, deleting, or modifying test cases for code.
|
|
||||||
+ `chore`: Used for modifications to non-business-related code, such as changes to build processes or tool configurations.
|
|
||||||
+ After `<type>`, specify the affected package name or scope in parentheses, for example, `(os/gtime)`.
|
|
||||||
+ The part after the colon uses the verb tense + phrase that completes the blank in
|
|
||||||
+ Lowercase verb after the colon
|
|
||||||
+ No trailing period
|
|
||||||
+ Keep the title as short as possible. ideally under 76 characters or shorter
|
|
||||||
+ [Reference Documentation](https://www.conventionalcommits.org/en/v1.0.0/)
|
|
||||||
+ If there is a corresponding issue, add either `Fixes #1234` or `Updates #1234`
|
|
||||||
(the latter if this is not a complete fix) to this comment
|
|
||||||
+ Delete these instructions once you have read and applied them
|
|
||||||
|
|
||||||
**提交前请遵守每个事项,感谢!**
|
|
||||||
+ PR 标题格式如下:`<类型>[可选 范围]: <描述>` 例如 `fix(os/gtime): fix time zone issue`
|
|
||||||
+ `<类型>`是必须的,可以是 `fix`、`feat`、`build`、`ci`、`docs`、`style`、`refactor`、`perf`、`test`、`chore` 中的一个
|
|
||||||
+ fix: 用于修复了一个 bug
|
|
||||||
+ feat: 用于新增了一个功能
|
|
||||||
+ build: 用于修改项目构建系统,例如修改依赖库、外部接口或者升级 Node 版本等
|
|
||||||
+ ci: 用于修改持续集成流程,例如修改 Travis、Jenkins 等工作流配置
|
|
||||||
+ docs: 用于修改文档,例如修改 README 文件、API 文档等
|
|
||||||
+ style: 用于修改代码的样式,例如调整缩进、空格、空行等
|
|
||||||
+ refactor: 用于重构代码,例如修改代码结构、变量名、函数名等但不修改功能逻辑
|
|
||||||
+ perf: 用于优化性能,例如提升代码的性能、减少内存占用等
|
|
||||||
+ test: 用于修改测试用例,例如添加、删除、修改代码的测试用例等
|
|
||||||
+ chore: 用于对非业务性代码进行修改,例如修改构建流程或者工具配置等
|
|
||||||
+ `<类型>`后在括号中填写受影响的包名或范围,例如 `(os/gtime)`
|
|
||||||
+ 冒号后使用动词时态 + 短语
|
|
||||||
+ 冒号后的动词小写
|
|
||||||
+ 不要有结尾句号
|
|
||||||
+ 标题尽量保持简短,最好在 76 个字符或更短
|
|
||||||
+ [参考文档](https://www.conventionalcommits.org/zh-hans/v1.0.0/)
|
|
||||||
+ 如果有对应的 issue,请在此评论中添加 `Fixes #1234`,如果不是完全修复则添加 `Updates #1234`
|
|
||||||
+ 应用这些规则后删除所有的说明
|
|
||||||
4
.github/workflows/apollo/docker-compose.yml
vendored
4
.github/workflows/apollo/docker-compose.yml
vendored
@ -20,7 +20,7 @@ services:
|
|||||||
#APOLLO_PORTAL_DB_PASSWORD: 'apollo'
|
#APOLLO_PORTAL_DB_PASSWORD: 'apollo'
|
||||||
|
|
||||||
apollo-db:
|
apollo-db:
|
||||||
image: "mysql:5.7"
|
image: "loads/mysql:5.7"
|
||||||
container_name: apollo-db
|
container_name: apollo-db
|
||||||
environment:
|
environment:
|
||||||
TZ: Asia/Shanghai
|
TZ: Asia/Shanghai
|
||||||
@ -36,7 +36,7 @@ services:
|
|||||||
- apollo-dbdata
|
- apollo-dbdata
|
||||||
|
|
||||||
apollo-dbdata:
|
apollo-dbdata:
|
||||||
image: "alpine:3.8"
|
image: "loads/alpine:3.8"
|
||||||
container_name: apollo-dbdata
|
container_name: apollo-dbdata
|
||||||
volumes:
|
volumes:
|
||||||
- /var/lib/mysql
|
- /var/lib/mysql
|
||||||
|
|||||||
6
.github/workflows/before_script.sh
vendored
Normal file
6
.github/workflows/before_script.sh
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
find . -name "*.go" | xargs gofmt -w
|
||||||
|
git diff --name-only --exit-code || if [ $? != 0 ]; then echo "Notice: gofmt check failed,please gofmt before pr." && exit 1; fi
|
||||||
|
echo "gofmt check pass."
|
||||||
|
sudo echo "127.0.0.1 local" | sudo tee -a /etc/hosts
|
||||||
88
.github/workflows/ci-main.sh
vendored
Normal file
88
.github/workflows/ci-main.sh
vendored
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
coverage=$1
|
||||||
|
|
||||||
|
# find all path that contains go.mod.
|
||||||
|
for file in `find . -name go.mod`; do
|
||||||
|
dirpath=$(dirname $file)
|
||||||
|
echo $dirpath
|
||||||
|
|
||||||
|
if [[ $file =~ "/testdata/" ]]; then
|
||||||
|
echo "ignore testdata path $file"
|
||||||
|
continue 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# package kuhecm needs golang >= v1.19
|
||||||
|
if [ "kubecm" = $(basename $dirpath) ]; then
|
||||||
|
continue 1
|
||||||
|
if ! go version|grep -qE "go1.19|go1.[2-9][0-9]"; then
|
||||||
|
echo "ignore kubecm as go version: $(go version)"
|
||||||
|
continue 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# package consul needs golang >= v1.19
|
||||||
|
if [ "consul" = $(basename $dirpath) ]; then
|
||||||
|
continue 1
|
||||||
|
if ! go version|grep -qE "go1.19|go1.[2-9][0-9]"; then
|
||||||
|
echo "ignore consul as go version: $(go version)"
|
||||||
|
continue 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# package etcd needs golang >= v1.19
|
||||||
|
if [ "etcd" = $(basename $dirpath) ]; then
|
||||||
|
if ! go version|grep -qE "go1.19|go1.[2-9][0-9]"; then
|
||||||
|
echo "ignore etcd as go version: $(go version)"
|
||||||
|
continue 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# package polaris needs golang >= v1.19
|
||||||
|
if [ "polaris" = $(basename $dirpath) ]; then
|
||||||
|
if ! go version|grep -qE "go1.19|go1.[2-9][0-9]"; then
|
||||||
|
echo "ignore polaris as go version: $(go version)"
|
||||||
|
continue 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# package example needs golang >= v1.20
|
||||||
|
if [ "example" = $(basename $dirpath) ]; then
|
||||||
|
if ! go version|grep -qE "go1.[2-9][0-9]"; then
|
||||||
|
echo "ignore example as go version: $(go version)"
|
||||||
|
continue 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# package otlpgrpc needs golang >= v1.20
|
||||||
|
if [ "otlpgrpc" = $(basename $dirpath) ]; then
|
||||||
|
if ! go version|grep -qE "go1.[2-9][0-9]"; then
|
||||||
|
echo "ignore otlpgrpc as go version: $(go version)"
|
||||||
|
continue 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# package otlphttp needs golang >= v1.20
|
||||||
|
if [ "otlphttp" = $(basename $dirpath) ]; then
|
||||||
|
if ! go version|grep -qE "go1.[2-9][0-9]"; then
|
||||||
|
echo "ignore otlphttp as go version: $(go version)"
|
||||||
|
continue 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
cd $dirpath
|
||||||
|
go mod tidy
|
||||||
|
go build ./...
|
||||||
|
# check coverage
|
||||||
|
if [ "${coverage}" = "coverage" ]; then
|
||||||
|
go test ./... -race -coverprofile=coverage.out -covermode=atomic -coverpkg=./...,github.com/gogf/gf/... || exit 1
|
||||||
|
|
||||||
|
if grep -q "/gogf/gf/.*/v2" go.mod; then
|
||||||
|
sed -i "s/gogf\/gf\(\/.*\)\/v2/gogf\/gf\/v2\1/g" coverage.out
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
go test ./... -race || exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
cd -
|
||||||
|
done
|
||||||
169
.github/workflows/ci-main.yml
vendored
169
.github/workflows/ci-main.yml
vendored
@ -20,13 +20,6 @@ on:
|
|||||||
- feature/**
|
- feature/**
|
||||||
- enhance/**
|
- enhance/**
|
||||||
- fix/**
|
- fix/**
|
||||||
workflow_dispatch:
|
|
||||||
inputs:
|
|
||||||
debug:
|
|
||||||
type: boolean
|
|
||||||
description: 'Enable tmate Debug'
|
|
||||||
required: false
|
|
||||||
default: false
|
|
||||||
|
|
||||||
# This allows a subsequently queued workflow run to interrupt previous runs
|
# This allows a subsequently queued workflow run to interrupt previous runs
|
||||||
concurrency:
|
concurrency:
|
||||||
@ -35,28 +28,18 @@ concurrency:
|
|||||||
|
|
||||||
env:
|
env:
|
||||||
TZ: "Asia/Shanghai"
|
TZ: "Asia/Shanghai"
|
||||||
# for unit testing cases of some components that only execute on the latest go version.
|
|
||||||
LATEST_GO_VERSION: "1.25"
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
code-test:
|
code-test:
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
# 🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥
|
|
||||||
# When adding new go version to the list, make sure:
|
|
||||||
# 1. Update the `LATEST_GO_VERSION` env variable.
|
|
||||||
# 🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥
|
|
||||||
go-version: [ "1.23", "1.24", "1.25" ]
|
|
||||||
goarch: [ "386", "amd64" ]
|
|
||||||
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
# Service containers to run with `code-test`
|
# Service containers to run with `code-test`
|
||||||
services:
|
services:
|
||||||
# Etcd service.
|
# Etcd service.
|
||||||
# docker run -p 2379:2379 -e ALLOW_NONE_AUTHENTICATION=yes bitnamilegacy/etcd:3.4.24
|
# docker run -d --name etcd -p 2379:2379 -e ALLOW_NONE_AUTHENTICATION=yes loads/etcd:3.4.24
|
||||||
etcd:
|
etcd:
|
||||||
image: bitnamilegacy/etcd:3.4.24
|
image: loads/etcd:3.4.24
|
||||||
env:
|
env:
|
||||||
ALLOW_NONE_AUTHENTICATION: yes
|
ALLOW_NONE_AUTHENTICATION: yes
|
||||||
ports:
|
ports:
|
||||||
@ -64,7 +47,7 @@ jobs:
|
|||||||
|
|
||||||
# Redis backend server.
|
# Redis backend server.
|
||||||
redis:
|
redis:
|
||||||
image : redis:7.0
|
image : loads/redis:7.0
|
||||||
options: >-
|
options: >-
|
||||||
--health-cmd "redis-cli ping"
|
--health-cmd "redis-cli ping"
|
||||||
--health-interval 10s
|
--health-interval 10s
|
||||||
@ -75,43 +58,20 @@ jobs:
|
|||||||
- 6379:6379
|
- 6379:6379
|
||||||
|
|
||||||
# MySQL backend server.
|
# MySQL backend server.
|
||||||
# docker run \
|
|
||||||
# -p 3306:3306 \
|
|
||||||
# -e MYSQL_DATABASE=test \
|
|
||||||
# -e MYSQL_ROOT_PASSWORD=12345678 \
|
|
||||||
# mysql:5.7
|
|
||||||
mysql:
|
mysql:
|
||||||
image: mysql:5.7
|
image: loads/mysql:5.7
|
||||||
env:
|
env:
|
||||||
MYSQL_DATABASE : test
|
MYSQL_DATABASE : test
|
||||||
MYSQL_ROOT_PASSWORD: 12345678
|
MYSQL_ROOT_PASSWORD: 12345678
|
||||||
ports:
|
ports:
|
||||||
- 3306:3306
|
- 3306:3306
|
||||||
|
|
||||||
# MariaDb backend server.
|
|
||||||
# docker run \
|
|
||||||
# -p 3307:3306 \
|
|
||||||
# -e MYSQL_DATABASE=test \
|
|
||||||
# -e MYSQL_ROOT_PASSWORD=12345678 \
|
|
||||||
# mariadb:11.4
|
|
||||||
mariadb:
|
|
||||||
image: mariadb:11.4
|
|
||||||
env:
|
|
||||||
MARIADB_DATABASE: test
|
|
||||||
MARIADB_ROOT_PASSWORD: 12345678
|
|
||||||
ports:
|
|
||||||
- 3307:3306
|
|
||||||
|
|
||||||
# PostgreSQL backend server.
|
# PostgreSQL backend server.
|
||||||
# docker run \
|
# docker run -d --name postgres -p 5432:5432 \
|
||||||
# -p 5432:5432 \
|
# -e POSTGRES_PASSWORD=12345678 -e POSTGRES_USER=postgres -e POSTGRES_DB=test \
|
||||||
# -e POSTGRES_PASSWORD=12345678 \
|
# -v postgres:/Users/john/Temp/postgresql/data loads/postgres:13
|
||||||
# -e POSTGRES_USER=postgres \
|
|
||||||
# -e POSTGRES_DB=test \
|
|
||||||
# -v postgres:/Users/john/Temp/postgresql/data \
|
|
||||||
# postgres:17-alpine
|
|
||||||
postgres:
|
postgres:
|
||||||
image: postgres:17-alpine
|
image: loads/postgres:13
|
||||||
env:
|
env:
|
||||||
POSTGRES_PASSWORD: 12345678
|
POSTGRES_PASSWORD: 12345678
|
||||||
POSTGRES_USER: postgres
|
POSTGRES_USER: postgres
|
||||||
@ -127,45 +87,46 @@ jobs:
|
|||||||
--health-retries 5
|
--health-retries 5
|
||||||
|
|
||||||
# MSSQL backend server.
|
# MSSQL backend server.
|
||||||
# docker run \
|
# docker run -d --name mssql -p 1433:1433 \
|
||||||
# -p 1433:1433 \
|
|
||||||
# -e ACCEPT_EULA=Y \
|
# -e ACCEPT_EULA=Y \
|
||||||
# -e SA_PASSWORD=LoremIpsum86 \
|
# -e SA_PASSWORD=LoremIpsum86 \
|
||||||
|
# -e MSSQL_DB=test \
|
||||||
# -e MSSQL_USER=root \
|
# -e MSSQL_USER=root \
|
||||||
# -e MSSQL_PASSWORD=LoremIpsum86 \
|
# -e MSSQL_PASSWORD=LoremIpsum86 \
|
||||||
# mcr.microsoft.com/mssql/server:2022-latest
|
# loads/mssqldocker:14.0.3391.2
|
||||||
mssql:
|
mssql:
|
||||||
image: mcr.microsoft.com/mssql/server:2022-latest
|
image: loads/mssqldocker:14.0.3391.2
|
||||||
env:
|
env:
|
||||||
TZ: Asia/Shanghai
|
ACCEPT_EULA: Y
|
||||||
ACCEPT_EULA: Y
|
SA_PASSWORD: LoremIpsum86
|
||||||
MSSQL_SA_PASSWORD: LoremIpsum86
|
MSSQL_DB: test
|
||||||
|
MSSQL_USER: root
|
||||||
|
MSSQL_PASSWORD: LoremIpsum86
|
||||||
ports:
|
ports:
|
||||||
- 1433:1433
|
- 1433:1433
|
||||||
options: >-
|
options: >-
|
||||||
--health-cmd="/opt/mssql-tools18/bin/sqlcmd -S localhost -U sa -P ${MSSQL_SA_PASSWORD} -N -C -l 30 -Q \"SELECT 1\" || exit 1"
|
--health-cmd="/opt/mssql-tools/bin/sqlcmd -S localhost -U sa -P LoremIpsum86 -l 30 -Q \"SELECT 1\" || exit 1"
|
||||||
--health-start-period 10s
|
--health-start-period 10s
|
||||||
--health-interval 10s
|
--health-interval 10s
|
||||||
--health-timeout 5s
|
--health-timeout 5s
|
||||||
--health-retries 10
|
--health-retries 10
|
||||||
|
|
||||||
# ClickHouse backend server.
|
# ClickHouse backend server.
|
||||||
# docker run \
|
# docker run -d --name clickhouse \
|
||||||
# -p 9000:9000 -p 8123:8123 -p 9001:9001 \
|
# -p 9000:9000 -p 8123:8123 -p 9001:9001 \
|
||||||
# clickhouse/clickhouse-server:24.11.1.2557-alpine
|
# loads/clickhouse-server:22.1.3.7
|
||||||
clickhouse-server:
|
clickhouse-server:
|
||||||
image: clickhouse/clickhouse-server:24.11.1.2557-alpine
|
image: loads/clickhouse-server:22.1.3.7
|
||||||
ports:
|
ports:
|
||||||
- 9000:9000
|
- 9000:9000
|
||||||
- 8123:8123
|
- 8123:8123
|
||||||
- 9001:9001
|
- 9001:9001
|
||||||
|
|
||||||
# Polaris backend server.
|
# Polaris backend server.
|
||||||
# docker run \
|
# docker run -d --name polaris -p 8090:8090 -p 8091:8091 -p 8093:8093 -p 9090:9090 -p 9091:9091 loads/polaris-server-standalone:1.11.2
|
||||||
# -p 8090:8090 -p 8091:8091 -p 8093:8093 -p 9090:9090 -p 9091:9091 \
|
# docker run -d --name polaris -p 8090:8090 -p 8091:8091 -p 8093:8093 -p 9090:9090 -p 9091:9091 loads/polaris-standalone:v1.16.3
|
||||||
# polarismesh/polaris-standalone:v1.17.2
|
|
||||||
polaris:
|
polaris:
|
||||||
image: polarismesh/polaris-standalone:v1.17.2
|
image: loads/polaris-standalone:v1.17.2
|
||||||
ports:
|
ports:
|
||||||
- 8090:8090
|
- 8090:8090
|
||||||
- 8091:8091
|
- 8091:8091
|
||||||
@ -173,14 +134,7 @@ jobs:
|
|||||||
- 9090:9090
|
- 9090:9090
|
||||||
- 9091:9091
|
- 9091:9091
|
||||||
|
|
||||||
# Oracle 11g server.
|
# Oracle 11g server
|
||||||
# docker run \
|
|
||||||
# -e ORACLE_ALLOW_REMOTE=true \
|
|
||||||
# -e ORACLE_SID=XE \
|
|
||||||
# -e ORACLE_DB_USER_NAME=system \
|
|
||||||
# -e ORACLE_DB_PASSWORD=oracle \
|
|
||||||
# -p 1521:1521 \
|
|
||||||
# loads/oracle-xe-11g-r2:11.2.0
|
|
||||||
oracle-server:
|
oracle-server:
|
||||||
image: loads/oracle-xe-11g-r2:11.2.0
|
image: loads/oracle-xe-11g-r2:11.2.0
|
||||||
env:
|
env:
|
||||||
@ -192,98 +146,75 @@ jobs:
|
|||||||
- 1521:1521
|
- 1521:1521
|
||||||
|
|
||||||
# dm8 server
|
# dm8 server
|
||||||
# docker run -p 5236:5236 loads/dm:v8.1.2.128_ent_x86_64_ctm_pack4
|
# docker run -d --name dm -p 5236:5236 loads/dm:v8.1.2.128_ent_x86_64_ctm_pack4
|
||||||
dm-server:
|
dm-server:
|
||||||
image: loads/dm:v8.1.2.128_ent_x86_64_ctm_pack4
|
image: loads/dm:v8.1.2.128_ent_x86_64_ctm_pack4
|
||||||
ports:
|
ports:
|
||||||
- 5236:5236
|
- 5236:5236
|
||||||
|
|
||||||
zookeeper:
|
zookeeper:
|
||||||
image: zookeeper:3.8
|
image: loads/zookeeper:3.8
|
||||||
ports:
|
ports:
|
||||||
- 2181:2181
|
- 2181:2181
|
||||||
|
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
go-version: [ "1.18", "1.19", "1.20", "1.21" ]
|
||||||
|
goarch: [ "386", "amd64" ]
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
# TODO: szenius/set-timezone update to node16
|
# TODO: szenius/set-timezone update to node16
|
||||||
# sudo ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
|
|
||||||
- name: Setup Timezone
|
- name: Setup Timezone
|
||||||
uses: szenius/set-timezone@v2.0
|
uses: szenius/set-timezone@v1.1
|
||||||
with:
|
with:
|
||||||
timezoneLinux: "Asia/Shanghai"
|
timezoneLinux: "Asia/Shanghai"
|
||||||
|
|
||||||
- name: Checkout Repository
|
- name: Checkout Repository
|
||||||
uses: actions/checkout@v5
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Setup tmate Session
|
|
||||||
uses: mxschmitt/action-tmate@v3
|
|
||||||
if: ${{ github.event_name == 'workflow_dispatch' && inputs.debug }}
|
|
||||||
with:
|
|
||||||
detached: true
|
|
||||||
limit-access-to-actor: false
|
|
||||||
|
|
||||||
- name: Free Disk Space
|
|
||||||
run: |
|
|
||||||
df -h /
|
|
||||||
sudo rm -rf /usr/share/dotnet /usr/local/lib/android /opt/hostedtoolcache/CodeQL /opt/hostedtoolcache/Python || true
|
|
||||||
df -h /
|
|
||||||
|
|
||||||
- name: Start Apollo Containers
|
- name: Start Apollo Containers
|
||||||
run: docker compose -f ".github/workflows/apollo/docker-compose.yml" up -d --build
|
run: docker-compose -f ".github/workflows/apollo/docker-compose.yml" up -d --build
|
||||||
|
|
||||||
- name: Start Nacos Containers
|
- name: Start Nacos Containers
|
||||||
run: docker compose -f ".github/workflows/nacos/docker-compose.yml" up -d --build
|
run: docker-compose -f ".github/workflows/nacos/docker-compose.yml" up -d --build
|
||||||
|
|
||||||
- name: Start Redis Cluster Containers
|
- name: Start Redis Cluster Containers
|
||||||
run: docker compose -f ".github/workflows/redis/docker-compose.yml" up -d --build
|
run: docker-compose -f ".github/workflows/redis/docker-compose.yml" up -d --build
|
||||||
|
|
||||||
- name: Start Consul Containers
|
- name: Start Consul Containers
|
||||||
run: docker compose -f ".github/workflows/consul/docker-compose.yml" up -d --build
|
run: docker-compose -f ".github/workflows/consul/docker-compose.yml" up -d --build
|
||||||
|
|
||||||
- name: Setup Golang ${{ matrix.go-version }}
|
- name: Setup Golang ${{ matrix.go-version }}
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@v4
|
||||||
with:
|
with:
|
||||||
go-version: ${{ matrix.go-version }}
|
go-version: ${{ matrix.go-version }}
|
||||||
cache-dependency-path: '**/go.sum'
|
cache-dependency-path: '**/go.sum'
|
||||||
|
|
||||||
- name: Install Protoc
|
|
||||||
uses: arduino/setup-protoc@v3
|
|
||||||
with:
|
|
||||||
version: "31.x"
|
|
||||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
|
|
||||||
- name: Install the protocol compiler plugins for Go
|
|
||||||
run: |
|
|
||||||
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
|
|
||||||
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
|
|
||||||
export PATH="$PATH:$(go env GOPATH)/bin"
|
|
||||||
|
|
||||||
- name: Before Script
|
- name: Before Script
|
||||||
run: bash .github/workflows/scripts/before_script.sh
|
run: bash .github/workflows/before_script.sh
|
||||||
|
|
||||||
- name: Build & Test
|
- name: Build & Test
|
||||||
if: ${{ (github.event_name == 'push' && github.ref != 'refs/heads/master') || github.event_name == 'pull_request' }}
|
if: ${{ (github.event_name == 'push' && github.ref != 'refs/heads/master') || github.event_name == 'pull_request' }}
|
||||||
run: bash .github/workflows/scripts/ci-main.sh
|
run: bash .github/workflows/ci-main.sh
|
||||||
|
|
||||||
- name: Build & Test & Coverage
|
- name: Build & Test & Coverage
|
||||||
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }}
|
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }}
|
||||||
run: bash .github/workflows/scripts/ci-main.sh coverage
|
run: bash .github/workflows/ci-main.sh coverage
|
||||||
|
|
||||||
- name: Stop Redis Cluster Containers
|
- name: Stop Redis Cluster Containers
|
||||||
run: docker compose -f ".github/workflows/redis/docker-compose.yml" down
|
run: docker-compose -f ".github/workflows/redis/docker-compose.yml" down
|
||||||
|
|
||||||
- name: Stop Apollo Containers
|
- name: Stop Apollo Containers
|
||||||
run: docker compose -f ".github/workflows/apollo/docker-compose.yml" down
|
run: docker-compose -f ".github/workflows/apollo/docker-compose.yml" down
|
||||||
|
|
||||||
- name: Stop Nacos Containers
|
- name: Stop Nacos Containers
|
||||||
run: docker compose -f ".github/workflows/nacos/docker-compose.yml" down
|
run: docker-compose -f ".github/workflows/nacos/docker-compose.yml" down
|
||||||
|
|
||||||
- name: Stop Consul Containers
|
- name: Stop Consul Containers
|
||||||
run: docker compose -f ".github/workflows/consul/docker-compose.yml" down
|
run: docker-compose -f ".github/workflows/consul/docker-compose.yml" down
|
||||||
|
|
||||||
- name: Report Coverage
|
- name: Report Coverage
|
||||||
uses: codecov/codecov-action@v4
|
uses: codecov/codecov-action@v3
|
||||||
# Only report coverage on the latest go version
|
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }}
|
||||||
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' && matrix.go-version == env.LATEST_GO_VERSION }}
|
|
||||||
with:
|
with:
|
||||||
flags: go-${{ matrix.go-version }}-${{ matrix.goarch }}
|
flags: go-${{ matrix.go-version }}-${{ matrix.goarch }}
|
||||||
token: ${{ secrets.CODECOV_TOKEN }}
|
|
||||||
|
|||||||
27
.github/workflows/ci-sub.sh
vendored
Normal file
27
.github/workflows/ci-sub.sh
vendored
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
coverage=$1
|
||||||
|
|
||||||
|
# find all path that contains go.mod.
|
||||||
|
for file in `find . -name go.mod`; do
|
||||||
|
dirpath=$(dirname $file)
|
||||||
|
echo $dirpath
|
||||||
|
|
||||||
|
# package kuhecm needs golang >= v1.19
|
||||||
|
if [ "kubecm" = $(basename $dirpath) ]; then
|
||||||
|
if ! go version|grep -qE "go1.19|go1.[2-9][0-9]"; then
|
||||||
|
echo "ignore kubecm as go version: $(go version)"
|
||||||
|
continue 1
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
continue 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
cd $dirpath
|
||||||
|
|
||||||
|
go mod tidy
|
||||||
|
go build ./...
|
||||||
|
go test ./... -race || exit 1
|
||||||
|
|
||||||
|
cd -
|
||||||
|
done
|
||||||
23
.github/workflows/ci-sub.yml
vendored
23
.github/workflows/ci-sub.yml
vendored
@ -29,44 +29,39 @@ concurrency:
|
|||||||
|
|
||||||
env:
|
env:
|
||||||
TZ: "Asia/Shanghai"
|
TZ: "Asia/Shanghai"
|
||||||
# for unit testing cases of some components that only execute on the latest go version.
|
|
||||||
LATEST_GO_VERSION: "1.25"
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
code-test:
|
code-test:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
# 🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥
|
go-version: [ "1.18", "1.19", "1.20", "1.21" ]
|
||||||
# When adding new go version to the list, make sure:
|
|
||||||
# 1. Update the `LATEST_GO_VERSION` env variable.
|
|
||||||
# 🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥
|
|
||||||
go-version: [ "1.23", "1.24", "1.25" ]
|
|
||||||
goarch: [ "386", "amd64" ]
|
goarch: [ "386", "amd64" ]
|
||||||
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Setup Timezone
|
- name: Setup Timezone
|
||||||
uses: szenius/set-timezone@v2.0
|
uses: szenius/set-timezone@v1.1
|
||||||
with:
|
with:
|
||||||
timezoneLinux: "Asia/Shanghai"
|
timezoneLinux: "Asia/Shanghai"
|
||||||
|
|
||||||
- name: Checkout Repository
|
- name: Checkout Repository
|
||||||
uses: actions/checkout@v5
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Start Minikube
|
- name: Start Minikube
|
||||||
uses: medyagh/setup-minikube@master
|
uses: medyagh/setup-minikube@master
|
||||||
|
|
||||||
- name: Setup Golang ${{ matrix.go-version }}
|
- name: Setup Golang ${{ matrix.go-version }}
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@v4
|
||||||
with:
|
with:
|
||||||
go-version: ${{ matrix.go-version }}
|
go-version: ${{ matrix.go-version }}
|
||||||
cache-dependency-path: '**/go.sum'
|
cache-dependency-path: '**/go.sum'
|
||||||
|
|
||||||
- name: Before Script
|
- name: Before Script
|
||||||
run: bash .github/workflows/scripts/before_script.sh
|
run: bash .github/workflows/before_script.sh
|
||||||
|
|
||||||
- name: Build & Test
|
- name: Build & Test
|
||||||
run: bash .github/workflows/scripts/ci-sub.sh
|
run: bash .github/workflows/ci-sub.sh
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
100
.github/workflows/codeql.yml
vendored
100
.github/workflows/codeql.yml
vendored
@ -1,100 +0,0 @@
|
|||||||
# For most projects, this workflow file will not need changing; you simply need
|
|
||||||
# to commit it to your repository.
|
|
||||||
#
|
|
||||||
# You may wish to alter this file to override the set of languages analyzed,
|
|
||||||
# or to provide custom queries or build logic.
|
|
||||||
#
|
|
||||||
# ******** NOTE ********
|
|
||||||
# We have attempted to detect the languages in your repository. Please check
|
|
||||||
# the `language` matrix defined below to confirm you have the correct set of
|
|
||||||
# supported CodeQL languages.
|
|
||||||
#
|
|
||||||
name: "CodeQL Advanced"
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [ "master", "develop" ]
|
|
||||||
pull_request:
|
|
||||||
branches: [ "master", "develop" ]
|
|
||||||
schedule:
|
|
||||||
- cron: '0 21 * * *'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
analyze:
|
|
||||||
name: Analyze (${{ matrix.language }})
|
|
||||||
# Runner size impacts CodeQL analysis time. To learn more, please see:
|
|
||||||
# - https://gh.io/recommended-hardware-resources-for-running-codeql
|
|
||||||
# - https://gh.io/supported-runners-and-hardware-resources
|
|
||||||
# - https://gh.io/using-larger-runners (GitHub.com only)
|
|
||||||
# Consider using larger runners or machines with greater resources for possible analysis time improvements.
|
|
||||||
runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }}
|
|
||||||
permissions:
|
|
||||||
# required for all workflows
|
|
||||||
security-events: write
|
|
||||||
|
|
||||||
# required to fetch internal or private CodeQL packs
|
|
||||||
packages: read
|
|
||||||
|
|
||||||
# only required for workflows in private repositories
|
|
||||||
actions: read
|
|
||||||
contents: read
|
|
||||||
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
include:
|
|
||||||
- language: actions
|
|
||||||
build-mode: none
|
|
||||||
- language: go
|
|
||||||
build-mode: autobuild
|
|
||||||
# CodeQL supports the following values keywords for 'language': 'actions', 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'rust', 'swift'
|
|
||||||
# Use `c-cpp` to analyze code written in C, C++ or both
|
|
||||||
# Use 'java-kotlin' to analyze code written in Java, Kotlin or both
|
|
||||||
# Use 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both
|
|
||||||
# To learn more about changing the languages that are analyzed or customizing the build mode for your analysis,
|
|
||||||
# see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning.
|
|
||||||
# If you are analyzing a compiled language, you can modify the 'build-mode' for that language to customize how
|
|
||||||
# your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages
|
|
||||||
steps:
|
|
||||||
- name: Checkout repository
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
# Add any setup steps before running the `github/codeql-action/init` action.
|
|
||||||
# This includes steps like installing compilers or runtimes (`actions/setup-node`
|
|
||||||
# or others). This is typically only required for manual builds.
|
|
||||||
# - name: Setup runtime (example)
|
|
||||||
# uses: actions/setup-example@v1
|
|
||||||
|
|
||||||
# Initializes the CodeQL tools for scanning.
|
|
||||||
- name: Initialize CodeQL
|
|
||||||
uses: github/codeql-action/init@v3
|
|
||||||
with:
|
|
||||||
languages: ${{ matrix.language }}
|
|
||||||
build-mode: ${{ matrix.build-mode }}
|
|
||||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
|
||||||
# By default, queries listed here will override any specified in a config file.
|
|
||||||
# Prefix the list here with "+" to use these queries and those in the config file.
|
|
||||||
|
|
||||||
# For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
|
|
||||||
# queries: security-extended,security-and-quality
|
|
||||||
|
|
||||||
# If the analyze step fails for one of the languages you are analyzing with
|
|
||||||
# "We were unable to automatically build your code", modify the matrix above
|
|
||||||
# to set the build mode to "manual" for that language. Then modify this step
|
|
||||||
# to build your code.
|
|
||||||
# ℹ️ Command-line programs to run using the OS shell.
|
|
||||||
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
|
|
||||||
- if: matrix.build-mode == 'manual'
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
echo 'If you are using a "manual" build mode for one or more of the' \
|
|
||||||
'languages you are analyzing, replace this with the commands to build' \
|
|
||||||
'your code, for example:'
|
|
||||||
echo ' make bootstrap'
|
|
||||||
echo ' make release'
|
|
||||||
exit 1
|
|
||||||
|
|
||||||
- name: Perform CodeQL Analysis
|
|
||||||
uses: github/codeql-action/analyze@v3
|
|
||||||
with:
|
|
||||||
category: "/language:${{matrix.language}}"
|
|
||||||
4
.github/workflows/consul/docker-compose.yml
vendored
4
.github/workflows/consul/docker-compose.yml
vendored
@ -3,7 +3,7 @@ version: '3.7'
|
|||||||
services:
|
services:
|
||||||
|
|
||||||
consul-server:
|
consul-server:
|
||||||
image: consul:1.15
|
image: loads/consul:1.15
|
||||||
container_name: consul-server
|
container_name: consul-server
|
||||||
restart: always
|
restart: always
|
||||||
volumes:
|
volumes:
|
||||||
@ -17,7 +17,7 @@ services:
|
|||||||
command: "agent"
|
command: "agent"
|
||||||
|
|
||||||
consul-client:
|
consul-client:
|
||||||
image: consul:1.15
|
image: loads/consul:1.15
|
||||||
container_name: consul-client
|
container_name: consul-client
|
||||||
restart: always
|
restart: always
|
||||||
volumes:
|
volumes:
|
||||||
|
|||||||
61
.github/workflows/format-code-on-push.yml
vendored
61
.github/workflows/format-code-on-push.yml
vendored
@ -1,61 +0,0 @@
|
|||||||
name: Format Code on Push
|
|
||||||
|
|
||||||
on:
|
|
||||||
push
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
format-code:
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
go-version: [ 'stable' ]
|
|
||||||
name: format-code-by-gci
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout code
|
|
||||||
uses: actions/checkout@v5
|
|
||||||
- name: Setup Golang ${{ matrix.go-version }}
|
|
||||||
uses: actions/setup-go@v5
|
|
||||||
with:
|
|
||||||
go-version: ${{ matrix.go-version }}
|
|
||||||
- name: Install gci
|
|
||||||
run: go install github.com/daixiang0/gci@latest
|
|
||||||
- name: Run gci
|
|
||||||
run: |
|
|
||||||
gci write --custom-order \
|
|
||||||
--skip-generated \
|
|
||||||
--skip-vendor \
|
|
||||||
-s standard \
|
|
||||||
-s blank \
|
|
||||||
-s default \
|
|
||||||
-s dot \
|
|
||||||
-s "prefix(github.com/gogf/gf/v2)" \
|
|
||||||
-s "prefix(github.com/gogf/gf/cmd)" \
|
|
||||||
-s "prefix(github.com/gogf/gf/contrib)" \
|
|
||||||
-s "prefix(github.com/gogf/gf/example)" \
|
|
||||||
./
|
|
||||||
- name: Check for changes
|
|
||||||
run: |
|
|
||||||
if [[ -n "$(git status --porcelain)" ]]; then
|
|
||||||
echo "HAS_CHANGES=true" >> $GITHUB_ENV
|
|
||||||
else
|
|
||||||
echo "HAS_CHANGES=false" >> $GITHUB_ENV
|
|
||||||
fi
|
|
||||||
- name: Configure Git
|
|
||||||
run: |
|
|
||||||
if [[ "$HAS_CHANGES" == 'true' ]]; then
|
|
||||||
git config --global user.name "github-actions[bot]"
|
|
||||||
git config --global user.email "github-actions[bot]@users.noreply.github.com"
|
|
||||||
else
|
|
||||||
echo "HAS_CHANGES= $HAS_CHANGES "
|
|
||||||
fi
|
|
||||||
- name: Commit and push changes
|
|
||||||
run: |
|
|
||||||
if [[ "$HAS_CHANGES" == 'true' ]]; then
|
|
||||||
git add .
|
|
||||||
git commit -m "Apply gci import order changes"
|
|
||||||
git push origin ${{ github.event.pull_request.head.ref }}
|
|
||||||
else
|
|
||||||
echo "No change to commit push"
|
|
||||||
fi
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
8
.github/workflows/gitee-sync.yml
vendored
8
.github/workflows/gitee-sync.yml
vendored
@ -1,7 +1,7 @@
|
|||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- master
|
- main
|
||||||
tags:
|
tags:
|
||||||
- "*"
|
- "*"
|
||||||
|
|
||||||
@ -12,9 +12,9 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout source code
|
- name: Checkout source code
|
||||||
uses: actions/checkout@v5
|
uses: actions/checkout@v4
|
||||||
- name: Mirror GitHub to Gitee
|
- name: Mirror Github to Gitee
|
||||||
uses: Yikun/hub-mirror-action@v1.4
|
uses: Yikun/hub-mirror-action@v1.2
|
||||||
with:
|
with:
|
||||||
src: github/gogf
|
src: github/gogf
|
||||||
dst: gitee/johng
|
dst: gitee/johng
|
||||||
|
|||||||
46
.github/workflows/golangci-lint.yml
vendored
46
.github/workflows/golangci-lint.yml
vendored
@ -1,10 +1,19 @@
|
|||||||
# Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
|
# Tencent is pleased to support the open source community by making Polaris available.
|
||||||
#
|
#
|
||||||
# This Source Code Form is subject to the terms of the MIT License.
|
# Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
|
||||||
# If a copy of the MIT was not distributed with this file,
|
#
|
||||||
# You can obtain one at https://github.com/gogf/gf.
|
# Licensed under the BSD 3-Clause License (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# https://opensource.org/licenses/BSD-3-Clause
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software distributed
|
||||||
|
# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||||
|
# CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||||
|
# specific language governing permissions and limitations under the License.
|
||||||
|
|
||||||
name: golangci-lint
|
name: GolangCI-Lint
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
@ -14,7 +23,6 @@ on:
|
|||||||
- feature/**
|
- feature/**
|
||||||
- enhance/**
|
- enhance/**
|
||||||
- fix/**
|
- fix/**
|
||||||
- feat/**
|
|
||||||
pull_request:
|
pull_request:
|
||||||
branches:
|
branches:
|
||||||
- master
|
- master
|
||||||
@ -23,30 +31,24 @@ on:
|
|||||||
- feature/**
|
- feature/**
|
||||||
- enhance/**
|
- enhance/**
|
||||||
- fix/**
|
- fix/**
|
||||||
- feat/**
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
golang-ci:
|
golangci:
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
go-version: [ "stable" ]
|
go-version: [ '1.18','1.19','1.20','1.21' ]
|
||||||
|
name: golangci-lint
|
||||||
name: golang-ci-lint
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v5
|
uses: actions/checkout@v4
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
- name: Setup Golang ${{ matrix.go-version }}
|
- name: Setup Golang ${{ matrix.go-version }}
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@v4
|
||||||
with:
|
with:
|
||||||
go-version: ${{ matrix.go-version }}
|
go-version: ${{ matrix.go-version }}
|
||||||
- name: golang-ci-lint
|
- name: golangci-lint
|
||||||
uses: golangci/golangci-lint-action@v8
|
uses: golangci/golangci-lint-action@v3
|
||||||
with:
|
with:
|
||||||
# Required: specify the golangci-lint version without the patch version to always use the latest patch.
|
# Required: the version of golangci-lint is required and must be specified without patch version: we always use the latest patch version.
|
||||||
only-new-issues: true
|
version: v1.52.2
|
||||||
skip-cache: true
|
args: --timeout 3m0s
|
||||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
args: --config=.golangci.yml -v
|
|
||||||
|
|||||||
8
.github/workflows/issue-check-inactive.yml
vendored
8
.github/workflows/issue-check-inactive.yml
vendored
@ -1,12 +1,12 @@
|
|||||||
# Rule description: Execute the ISSUE once a day at 3 a.m. (GMT+8) and set the non-bug issue that has not been active in the last 7 days to inactive
|
# 规则描述:每天凌晨3点(GMT+8)执行一次,将最近7天没有活跃且非BUG的ISSUE设置标签:inactive
|
||||||
name: Issue Check Inactive
|
name: Issue Check Inactive
|
||||||
|
|
||||||
on:
|
on:
|
||||||
schedule:
|
schedule:
|
||||||
- cron: "0 19 * * *"
|
- cron: "0 19 * * *"
|
||||||
|
|
||||||
env: # Set environment variables
|
env: # 设置环境变量
|
||||||
TZ: Asia/Shanghai #Time zone (setting the time zone allows the 'Last Updated' on the page to use the time zone)
|
TZ: Asia/Shanghai #时区(设置时区可使页面中的`最近更新时间`使用时区时间)
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
@ -23,6 +23,6 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
actions: 'check-inactive'
|
actions: 'check-inactive'
|
||||||
inactive-label: 'inactive'
|
inactive-label: 'inactive'
|
||||||
inactive-day: 30
|
inactive-day: 7
|
||||||
issue-state: open
|
issue-state: open
|
||||||
exclude-labels: 'bug,planned,$exclude-empty'
|
exclude-labels: 'bug,planned,$exclude-empty'
|
||||||
6
.github/workflows/issue-close-inactive.yml
vendored
6
.github/workflows/issue-close-inactive.yml
vendored
@ -1,12 +1,12 @@
|
|||||||
# RULE DESCRIPTION: EXECUTED ONCE A DAY AT 4 A.M. (GMT+8) TO CLOSE NON-BUG ISSUES THAT HAVE NOT BEEN ACTIVE IN THE LAST 30 DAYS
|
# 规则描述:每天凌晨 4 点 (GMT+8) 执行一次,将最近 30 天没有活跃且非 BUG 的 ISSUE 关闭
|
||||||
name: Issue Close Inactive
|
name: Issue Close Inactive
|
||||||
|
|
||||||
on:
|
on:
|
||||||
schedule:
|
schedule:
|
||||||
- cron: "0 20 * * *"
|
- cron: "0 20 * * *"
|
||||||
|
|
||||||
env: # Set environment variables
|
env: # 设置环境变量
|
||||||
TZ: Asia/Shanghai #Time zone (setting the time zone allows the 'Last Updated' on the page to use the time zone)
|
TZ: Asia/Shanghai #时区(设置时区可使页面中的`最近更新时间`使用时区时间)
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
close-issues:
|
close-issues:
|
||||||
|
|||||||
6
.github/workflows/issue-labeled.yml
vendored
6
.github/workflows/issue-labeled.yml
vendored
@ -1,4 +1,4 @@
|
|||||||
## Rule description: Add comments when an issue is marked as help wanted
|
## 规则描述:当 issue 被标记为 help wanted 时,增加评论
|
||||||
|
|
||||||
name: Issue Labeled
|
name: Issue Labeled
|
||||||
|
|
||||||
@ -6,8 +6,8 @@ on:
|
|||||||
issues:
|
issues:
|
||||||
types: [labeled]
|
types: [labeled]
|
||||||
|
|
||||||
env: # Set environment variables
|
env: # 设置环境变量
|
||||||
TZ: Asia/Shanghai # Time zone (setting the time zone allows the 'Last Updated' on the page to use the time zone)
|
TZ: Asia/Shanghai # 时区(设置时区可使页面中的`最近更新时间`使用时区时间)
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
reply-labeled:
|
reply-labeled:
|
||||||
|
|||||||
6
.github/workflows/issue-remove-inactive.yml
vendored
6
.github/workflows/issue-remove-inactive.yml
vendored
@ -1,4 +1,4 @@
|
|||||||
# Rule description: If an issue author updates or comments on an issue while it is not active and has not been closed, the inactive tag will be removed
|
# 规则描述:在 issue 没有活跃且尚未被关闭期间,若 issue 作者更新或评论该 ISSUE,则移除其 inactive 标签
|
||||||
name: Issue Remove Inactive
|
name: Issue Remove Inactive
|
||||||
|
|
||||||
on:
|
on:
|
||||||
@ -7,8 +7,8 @@ on:
|
|||||||
issue_comment:
|
issue_comment:
|
||||||
types: [created, edited]
|
types: [created, edited]
|
||||||
|
|
||||||
env: # Set environment variables
|
env: # 设置环境变量
|
||||||
TZ: Asia/Shanghai #Time zone (setting the time zone allows the 'Last Updated' on the page to use the time zone)
|
TZ: Asia/Shanghai #时区(设置时区可使页面中的`最近更新时间`使用时区时间)
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
# Rule Description: For issues that need more details and are not yet closed, remove the "need more details" tag after the issue author comments
|
# 规则描述:将需要提供更多细节且暂未关闭的 issue,在 issue 作者评论后,移除 need more details 标签
|
||||||
name: Issue Remove Need More Details
|
name: Issue Remove Need More Details
|
||||||
|
|
||||||
on:
|
on:
|
||||||
@ -7,8 +7,8 @@ on:
|
|||||||
issue_comment:
|
issue_comment:
|
||||||
types: [created, edited]
|
types: [created, edited]
|
||||||
|
|
||||||
env: # Set environment variables
|
env: # 设置环境变量
|
||||||
TZ: Asia/Shanghai #Time zone (setting the time zone allows the 'Last Updated' on the page to use the time zone)
|
TZ: Asia/Shanghai #时区(设置时区可使页面中的`最近更新时间`使用时区时间)
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
contents: read
|
contents: read
|
||||||
|
|||||||
4
.github/workflows/nacos/docker-compose.yml
vendored
4
.github/workflows/nacos/docker-compose.yml
vendored
@ -2,7 +2,7 @@ version: "3.8"
|
|||||||
|
|
||||||
services:
|
services:
|
||||||
nacos:
|
nacos:
|
||||||
image: nacos/nacos-server:v2.1.2
|
image: loads/nacos-server:v2.1.2
|
||||||
container_name: nacos
|
container_name: nacos
|
||||||
env_file:
|
env_file:
|
||||||
- ./env/nacos.env
|
- ./env/nacos.env
|
||||||
@ -17,7 +17,7 @@ services:
|
|||||||
retries: 10
|
retries: 10
|
||||||
|
|
||||||
initializer:
|
initializer:
|
||||||
image: alpine/curl:latest
|
image: loads/curl:latest
|
||||||
depends_on:
|
depends_on:
|
||||||
nacos:
|
nacos:
|
||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
|
|||||||
13
.github/workflows/release.yml
vendored
13
.github/workflows/release.yml
vendored
@ -16,13 +16,12 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout Github Code
|
- name: Checkout Github Code
|
||||||
uses: actions/checkout@v5
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Set Up Golang Environment
|
- name: Set Up Golang Environment
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@v4
|
||||||
with:
|
with:
|
||||||
go-version: 1.25
|
go-version: 1.20.8
|
||||||
cache: false
|
|
||||||
|
|
||||||
- name: Build CLI Binary
|
- name: Build CLI Binary
|
||||||
run: |
|
run: |
|
||||||
@ -35,7 +34,7 @@ jobs:
|
|||||||
- name: Build CLI Binary For All Platform
|
- name: Build CLI Binary For All Platform
|
||||||
run: |
|
run: |
|
||||||
cd cmd/gf
|
cd cmd/gf
|
||||||
gf build main.go -n gf -a all -s linux,windows,darwin,freebsd,netbsd,openbsd -p temp
|
gf build main.go -n gf -a all -s all
|
||||||
|
|
||||||
- name: Move Files Before Release
|
- name: Move Files Before Release
|
||||||
run: |
|
run: |
|
||||||
@ -53,7 +52,7 @@ jobs:
|
|||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
with:
|
with:
|
||||||
tag_name: ${{ github.ref }}
|
tag_name: ${{ github.ref }}
|
||||||
name: GoFrame Release ${{ github.ref_name }}
|
name: GoFrame Release ${{ github.ref }}
|
||||||
draft: false
|
draft: false
|
||||||
prerelease: false
|
prerelease: false
|
||||||
|
|
||||||
|
|||||||
80
.github/workflows/scorecard.yml
vendored
80
.github/workflows/scorecard.yml
vendored
@ -1,80 +0,0 @@
|
|||||||
# This workflow uses actions that are not certified by GitHub. They are provided
|
|
||||||
# by a third-party and are governed by separate terms of service, privacy
|
|
||||||
# policy, and support documentation.
|
|
||||||
|
|
||||||
name: Scorecard supply-chain security
|
|
||||||
on:
|
|
||||||
# For Branch-Protection check. Only the default branch is supported. See
|
|
||||||
# https://github.com/ossf/scorecard/blob/main/docs/checks.md#branch-protection
|
|
||||||
branch_protection_rule:
|
|
||||||
# To guarantee Maintained check is occasionally updated. See
|
|
||||||
# https://github.com/ossf/scorecard/blob/main/docs/checks.md#maintained
|
|
||||||
schedule:
|
|
||||||
- cron: '0 21 * * *'
|
|
||||||
push:
|
|
||||||
branches: [ "master" ]
|
|
||||||
pull_request:
|
|
||||||
branches: [ "master" ]
|
|
||||||
|
|
||||||
# Declare default permissions as read only.
|
|
||||||
permissions: read-all
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
analysis:
|
|
||||||
name: Scorecard analysis
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
# `publish_results: true` only works when run from the default branch. conditional can be removed if disabled.
|
|
||||||
if: github.event.repository.default_branch == github.ref_name || github.event_name == 'pull_request'
|
|
||||||
permissions:
|
|
||||||
# Needed to upload the results to code-scanning dashboard.
|
|
||||||
security-events: write
|
|
||||||
# Needed to publish results and get a badge (see publish_results below).
|
|
||||||
id-token: write
|
|
||||||
# Uncomment the permissions below if installing in a private repository.
|
|
||||||
# contents: read
|
|
||||||
# actions: read
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: "Checkout code"
|
|
||||||
uses: actions/checkout@v4.2.2
|
|
||||||
with:
|
|
||||||
persist-credentials: false
|
|
||||||
|
|
||||||
- name: "Run analysis"
|
|
||||||
uses: ossf/scorecard-action@v2.4.1
|
|
||||||
with:
|
|
||||||
results_file: results.sarif
|
|
||||||
results_format: sarif
|
|
||||||
# (Optional) "write" PAT token. Uncomment the `repo_token` line below if:
|
|
||||||
# - you want to enable the Branch-Protection check on a *public* repository, or
|
|
||||||
# - you are installing Scorecard on a *private* repository
|
|
||||||
# To create the PAT, follow the steps in https://github.com/ossf/scorecard-action?tab=readme-ov-file#authentication-with-fine-grained-pat-optional.
|
|
||||||
# repo_token: ${{ secrets.SCORECARD_TOKEN }}
|
|
||||||
|
|
||||||
# Public repositories:
|
|
||||||
# - Publish results to OpenSSF REST API for easy access by consumers
|
|
||||||
# - Allows the repository to include the Scorecard badge.
|
|
||||||
# - See https://github.com/ossf/scorecard-action#publishing-results.
|
|
||||||
# For private repositories:
|
|
||||||
# - `publish_results` will always be set to `false`, regardless
|
|
||||||
# of the value entered here.
|
|
||||||
publish_results: true
|
|
||||||
|
|
||||||
# (Optional) Uncomment file_mode if you have a .gitattributes with files marked export-ignore
|
|
||||||
# file_mode: git
|
|
||||||
|
|
||||||
# Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF
|
|
||||||
# format to the repository Actions tab.
|
|
||||||
- name: "Upload artifact"
|
|
||||||
uses: actions/upload-artifact@v4.6.1
|
|
||||||
with:
|
|
||||||
name: SARIF file
|
|
||||||
path: results.sarif
|
|
||||||
retention-days: 5
|
|
||||||
|
|
||||||
# Upload the results to GitHub's code scanning dashboard (optional).
|
|
||||||
# Commenting out will disable upload of results to your repo's Code Scanning dashboard
|
|
||||||
- name: "Upload to code-scanning"
|
|
||||||
uses: github/codeql-action/upload-sarif@v3
|
|
||||||
with:
|
|
||||||
sarif_file: results.sarif
|
|
||||||
36
.github/workflows/scripts/before_script.sh
vendored
36
.github/workflows/scripts/before_script.sh
vendored
@ -1,36 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
# Install gci
|
|
||||||
echo "Installing gci..."
|
|
||||||
go install github.com/daixiang0/gci@latest
|
|
||||||
|
|
||||||
# Check if the GCI is installed successfully
|
|
||||||
if ! command -v gci &> /dev/null
|
|
||||||
then
|
|
||||||
echo "gci could not be installed. Please check your Go setup."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Use GCI to format the code
|
|
||||||
echo "Running gci to format code..."
|
|
||||||
gci write \
|
|
||||||
--custom-order \
|
|
||||||
--skip-generated \
|
|
||||||
--skip-vendor \
|
|
||||||
-s standard \
|
|
||||||
-s blank \
|
|
||||||
-s default \
|
|
||||||
-s dot \
|
|
||||||
-s "prefix(github.com/gogf/gf/v2)" \
|
|
||||||
-s "prefix(github.com/gogf/gf/cmd)" \
|
|
||||||
-s "prefix(github.com/gogf/gf/contrib)" \
|
|
||||||
-s "prefix(github.com/gogf/gf/example)" \
|
|
||||||
./
|
|
||||||
|
|
||||||
# Check the code for changes
|
|
||||||
git diff --name-only --exit-code || if [ $? != 0 ]; then echo "Notice: gci check failed, please gci before pr." && exit 1; fi
|
|
||||||
echo "gci check pass."
|
|
||||||
|
|
||||||
# Add the local domain name to `/etc/hosts`
|
|
||||||
echo "Adding local domain to /etc/hosts..."
|
|
||||||
sudo echo "127.0.0.1 local" | sudo tee -a /etc/hosts
|
|
||||||
250
.github/workflows/scripts/ci-main-clean.sh
vendored
250
.github/workflows/scripts/ci-main-clean.sh
vendored
@ -1,250 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
dirpath=$1
|
|
||||||
|
|
||||||
# Extract the base directory name for pattern matching
|
|
||||||
if [ -n "$dirpath" ]; then
|
|
||||||
dirname=$(basename "$dirpath")
|
|
||||||
echo "Cleaning Docker resources for path: $dirpath (pattern: $dirname)"
|
|
||||||
df -h /
|
|
||||||
|
|
||||||
# Process containers and images based on the directory
|
|
||||||
case "$dirname" in
|
|
||||||
# "mysql")
|
|
||||||
# echo "Cleaning mysql resources..."
|
|
||||||
# containers=$(docker ps -aq --filter "name=$dirname" 2>/dev/null)
|
|
||||||
# if [ -n "$containers" ]; then
|
|
||||||
# echo "Stopping and removing mysql containers..."
|
|
||||||
# docker stop $containers 2>/dev/null || true
|
|
||||||
# docker rm -f $containers 2>/dev/null || true
|
|
||||||
# fi
|
|
||||||
# docker rmi -f $(docker images -q mysql 2>/dev/null) 2>/dev/null || true
|
|
||||||
# ;;
|
|
||||||
"mssql")
|
|
||||||
echo "Cleaning mssql resources..."
|
|
||||||
containers=$(docker ps -aq --filter "name=$dirname" 2>/dev/null)
|
|
||||||
if [ -n "$containers" ]; then
|
|
||||||
echo "Stopping and removing mssql containers..."
|
|
||||||
docker stop $containers 2>/dev/null || true
|
|
||||||
docker rm -f $containers 2>/dev/null || true
|
|
||||||
fi
|
|
||||||
docker rmi -f $(docker images -q mcr.microsoft.com/mssql/server 2>/dev/null) 2>/dev/null || true
|
|
||||||
;;
|
|
||||||
"pgsql")
|
|
||||||
echo "Cleaning postgres resources..."
|
|
||||||
containers=$(docker ps -aq --filter "name=$dirname" 2>/dev/null)
|
|
||||||
if [ -n "$containers" ]; then
|
|
||||||
echo "Stopping and removing postgres containers..."
|
|
||||||
docker stop $containers 2>/dev/null || true
|
|
||||||
docker rm -f $containers 2>/dev/null || true
|
|
||||||
fi
|
|
||||||
docker rmi -f $(docker images -q postgres 2>/dev/null) 2>/dev/null || true
|
|
||||||
;;
|
|
||||||
"oracle")
|
|
||||||
echo "Cleaning oracle resources..."
|
|
||||||
containers=$(docker ps -aq --filter "name=$dirname" 2>/dev/null)
|
|
||||||
if [ -n "$containers" ]; then
|
|
||||||
echo "Stopping and removing oracle containers..."
|
|
||||||
docker stop $containers 2>/dev/null || true
|
|
||||||
docker rm -f $containers 2>/dev/null || true
|
|
||||||
fi
|
|
||||||
docker rmi -f $(docker images -q loads/oracle-xe-11g-r2 2>/dev/null) 2>/dev/null || true
|
|
||||||
;;
|
|
||||||
"dm")
|
|
||||||
echo "Cleaning dm resources..."
|
|
||||||
containers=$(docker ps -aq --filter "name=$dirname" 2>/dev/null)
|
|
||||||
if [ -n "$containers" ]; then
|
|
||||||
echo "Stopping and removing dm containers..."
|
|
||||||
docker stop $containers 2>/dev/null || true
|
|
||||||
docker rm -f $containers 2>/dev/null || true
|
|
||||||
fi
|
|
||||||
docker rmi -f $(docker images -q loads/dm 2>/dev/null) 2>/dev/null || true
|
|
||||||
;;
|
|
||||||
"clickhouse")
|
|
||||||
echo "Cleaning clickhouse resources..."
|
|
||||||
containers=$(docker ps -aq --filter "name=$dirname" 2>/dev/null)
|
|
||||||
if [ -n "$containers" ]; then
|
|
||||||
echo "Stopping and removing clickhouse containers..."
|
|
||||||
docker stop $containers 2>/dev/null || true
|
|
||||||
docker rm -f $containers 2>/dev/null || true
|
|
||||||
fi
|
|
||||||
docker rmi -f $(docker images -q clickhouse/clickhouse-server 2>/dev/null) 2>/dev/null || true
|
|
||||||
;;
|
|
||||||
# "redis")
|
|
||||||
# echo "Cleaning redis resources..."
|
|
||||||
# containers=$(docker ps -aq --filter "name=$dirname" 2>/dev/null)
|
|
||||||
# if [ -n "$containers" ]; then
|
|
||||||
# echo "Stopping and removing redis containers..."
|
|
||||||
# docker stop $containers 2>/dev/null || true
|
|
||||||
# docker rm -f $containers 2>/dev/null || true
|
|
||||||
# fi
|
|
||||||
# docker rmi -f $(docker images -q redis loads/redis loads/redis-sentinel 2>/dev/null) 2>/dev/null || true
|
|
||||||
# ;;
|
|
||||||
"etcd")
|
|
||||||
echo "Cleaning etcd resources..."
|
|
||||||
containers=$(docker ps -aq --filter "name=$dirname" 2>/dev/null)
|
|
||||||
if [ -n "$containers" ]; then
|
|
||||||
echo "Stopping and removing etcd containers..."
|
|
||||||
docker stop $containers 2>/dev/null || true
|
|
||||||
docker rm -f $containers 2>/dev/null || true
|
|
||||||
fi
|
|
||||||
docker rmi -f $(docker images -q bitnamilegacy/etcd 2>/dev/null) 2>/dev/null || true
|
|
||||||
;;
|
|
||||||
# "consul")
|
|
||||||
# echo "Cleaning consul resources..."
|
|
||||||
# containers=$(docker ps -aq --filter "name=$dirname" 2>/dev/null)
|
|
||||||
# if [ -n "$containers" ]; then
|
|
||||||
# echo "Stopping and removing consul containers..."
|
|
||||||
# docker stop $containers 2>/dev/null || true
|
|
||||||
# docker rm -f $containers 2>/dev/null || true
|
|
||||||
# fi
|
|
||||||
# docker rmi -f $(docker images -q consul 2>/dev/null) 2>/dev/null || true
|
|
||||||
# ;;
|
|
||||||
# "nacos")
|
|
||||||
# echo "Cleaning nacos resources..."
|
|
||||||
# containers=$(docker ps -aq --filter "name=$dirname" 2>/dev/null)
|
|
||||||
# if [ -n "$containers" ]; then
|
|
||||||
# echo "Stopping and removing nacos containers..."
|
|
||||||
# docker stop $containers 2>/dev/null || true
|
|
||||||
# docker rm -f $containers 2>/dev/null || true
|
|
||||||
# fi
|
|
||||||
# docker rmi -f $(docker images -q nacos/nacos-server 2>/dev/null) 2>/dev/null || true
|
|
||||||
# ;;
|
|
||||||
# "polaris")
|
|
||||||
# echo "Cleaning polaris resources..."
|
|
||||||
# containers=$(docker ps -aq --filter "name=$dirname" 2>/dev/null)
|
|
||||||
# if [ -n "$containers" ]; then
|
|
||||||
# echo "Stopping and removing polaris containers..."
|
|
||||||
# docker stop $containers 2>/dev/null || true
|
|
||||||
# docker rm -f $containers 2>/dev/null || true
|
|
||||||
# fi
|
|
||||||
# docker rmi -f $(docker images -q polarismesh/polaris-standalone 2>/dev/null) 2>/dev/null || true
|
|
||||||
# ;;
|
|
||||||
"zookeeper")
|
|
||||||
echo "Cleaning zookeeper resources..."
|
|
||||||
containers=$(docker ps -aq --filter "name=$dirname" 2>/dev/null)
|
|
||||||
if [ -n "$containers" ]; then
|
|
||||||
echo "Stopping and removing zookeeper containers..."
|
|
||||||
docker stop $containers 2>/dev/null || true
|
|
||||||
docker rm -f $containers 2>/dev/null || true
|
|
||||||
fi
|
|
||||||
docker rmi -f $(docker images -q zookeeper 2>/dev/null) 2>/dev/null || true
|
|
||||||
;;
|
|
||||||
# "apollo")
|
|
||||||
# echo "Cleaning apollo resources..."
|
|
||||||
# containers=$(docker ps -aq --filter "name=$dirname" 2>/dev/null)
|
|
||||||
# if [ -n "$containers" ]; then
|
|
||||||
# echo "Stopping and removing apollo containers..."
|
|
||||||
# docker stop $containers 2>/dev/null || true
|
|
||||||
# docker rm -f $containers 2>/dev/null || true
|
|
||||||
# fi
|
|
||||||
# docker rmi -f $(docker images -q loads/apollo-quick-start 2>/dev/null) 2>/dev/null || true
|
|
||||||
# ;;
|
|
||||||
*)
|
|
||||||
# No matching pattern, skip cleanup
|
|
||||||
echo "No specific Docker cleanup rule for '$dirname', skipping cleanup"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
# Remove dangling images and volumes to free up space
|
|
||||||
echo "Removing dangling images and unused volumes..."
|
|
||||||
docker image prune -f 2>/dev/null || true
|
|
||||||
docker volume prune -f 2>/dev/null || true
|
|
||||||
|
|
||||||
echo "Docker cleanup completed for $dirname"
|
|
||||||
docker system df
|
|
||||||
df -h /
|
|
||||||
fi
|
|
||||||
|
|
||||||
# df -h /
|
|
||||||
# Filesystem Size Used Avail Use% Mounted on
|
|
||||||
# /dev/root 72G 67G 5.4G 93% /
|
|
||||||
# tmpfs 7.9G 84K 7.9G 1% /dev/shm
|
|
||||||
# tmpfs 3.2G 2.6M 3.2G 1% /run
|
|
||||||
# tmpfs 5.0M 0 5.0M 0% /run/lock
|
|
||||||
# /dev/sdb16 881M 62M 758M 8% /boot
|
|
||||||
# /dev/sdb15 105M 6.2M 99M 6% /boot/efi
|
|
||||||
# /dev/sda1 74G 4.1G 66G 6% /mnt
|
|
||||||
# tmpfs 1.6G 12K 1.6G 1% /run/user/1001
|
|
||||||
|
|
||||||
# runner@runnervmg1sw1:~/work/gf/gf$ docker system df
|
|
||||||
# TYPE TOTAL ACTIVE SIZE RECLAIMABLE
|
|
||||||
# Images 18 11 8.326GB 1.644GB (19%)
|
|
||||||
# Containers 11 11 2.692GB 0B (0%)
|
|
||||||
# Local Volumes 11 8 665.7MB 211.9MB (31%)
|
|
||||||
# Build Cache 0 0 0B 0B
|
|
||||||
|
|
||||||
# runner@runnervmg1sw1:~/work/gf/gf$ docker images
|
|
||||||
# REPOSITORY TAG IMAGE ID CREATED SIZE
|
|
||||||
# alpine/curl latest 99fd43792a61 2 days ago 13.5MB
|
|
||||||
# postgres 17-alpine b6bf692a8125 9 days ago 278MB
|
|
||||||
# zookeeper 3.8 2f26c02b94ca 10 days ago 306MB
|
|
||||||
# mariadb 11.4 063fb6684f96 10 days ago 332MB
|
|
||||||
# mcr.microsoft.com/mssql/server 2022-latest a2fbff321505 4 weeks ago 1.61GB
|
|
||||||
# clickhouse/clickhouse-server 24.11.1.2557-alpine 2eee9fd3ae74 12 months ago 539MB
|
|
||||||
# redis 7.0 7705dd2858c1 18 months ago 109MB
|
|
||||||
# consul 1.15 686495461132 20 months ago 155MB
|
|
||||||
# mysql 5.7 5107333e08a8 23 months ago 501MB
|
|
||||||
# polarismesh/polaris-standalone v1.17.2 b7a8cf0a8438 2 years ago 545MB
|
|
||||||
# bitnamilegacy/etcd 3.4.24 74ae5e205ac5 2 years ago 134MB
|
|
||||||
# nacos/nacos-server v2.1.2 a978644d9246 2 years ago 1.06GB
|
|
||||||
# loads/redis 7.0-sentinel 6f12d40540ba 3 years ago 114MB
|
|
||||||
# loads/dm v8.1.2.128_ent_x86_64_ctm_pack4 ccb727ce9dce 3 years ago 432MB
|
|
||||||
# loads/redis-sentinel 7.0 6818c626f5ca 3 years ago 104MB
|
|
||||||
# loads/apollo-quick-start latest 8490de672148 3 years ago 190MB
|
|
||||||
# alpine 3.8 c8bccc0af957 5 years ago 4.41MB
|
|
||||||
# loads/oracle-xe-11g-r2 11.2.0 0d19fd2e072e 6 years ago 2.1GB
|
|
||||||
|
|
||||||
# runner@runnervmg1sw1:~/work/gf/gf$ docker ps -s
|
|
||||||
# CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES SIZE
|
|
||||||
# 8214f83420c6 zookeeper:3.8 "/docker-entrypoint.…" 6 minutes ago Up 6 minutes 2888/tcp, 3888/tcp, 0.0.0.0:2181->2181/tcp, [::]:2181->2181/tcp, 8080/tcp d66bac92ae9646f688f70ed4b5176f14_zookeeper38_3a22ef 33kB (virtual 306MB)
|
|
||||||
# 8938d73842e8 loads/dm:v8.1.2.128_ent_x86_64_ctm_pack4 "/bin/bash /opt/star…" 6 minutes ago Up 6 minutes 0.0.0.0:5236->5236/tcp, [::]:5236->5236/tcp ca280fbdb86f40c2acf86d7d526c6285_loadsdmv812128_ent_x86_64_ctm_pack4_770a59 844MB (virtual 1.28GB)
|
|
||||||
# 0d3a653fe1f2 loads/oracle-xe-11g-r2:11.2.0 "/bin/sh -c '/usr/sb…" 6 minutes ago Up 6 minutes 22/tcp, 8080/tcp, 0.0.0.0:1521->1521/tcp, [::]:1521->1521/tcp 2048856d428c4967b1c35193eb8c9192_loadsoraclexe11gr21120_295d54 1.3GB (virtual 3.4GB)
|
|
||||||
# ca3936189166 polarismesh/polaris-standalone:v1.17.2 "/bin/bash run.sh" 6 minutes ago Up 6 minutes 0.0.0.0:8090-8091->8090-8091/tcp, [::]:8090-8091->8090-8091/tcp, 8080/tcp, 8100-8101/tcp, 0.0.0.0:8093->8093/tcp, [::]:8093->8093/tcp, 8761/tcp, 15010/tcp, 0.0.0.0:9090-9091->9090-9091/tcp, [::]:9090-9091->9090-9091/tcp cbd43dceef754e2d8aab507e33167be7_polarismeshpolarisstandalonev1172_ca40b6 299MB (virtual 844MB)
|
|
||||||
# 26169dad485e clickhouse/clickhouse-server:24.11.1.2557-alpine "/entrypoint.sh" 6 minutes ago Up 6 minutes 0.0.0.0:8123->8123/tcp, [::]:8123->8123/tcp, 0.0.0.0:9000-9001->9000-9001/tcp, [::]:9000-9001->9000-9001/tcp, 9009/tcp f1c7766fbe36401792a6f735d7acf123_clickhouseclickhouseserver241112557alpine_cfc034 338kB (virtual 539MB)
|
|
||||||
# 04689a1d581f mcr.microsoft.com/mssql/server:2022-latest "/opt/mssql/bin/laun…" 6 minutes ago Up 6 minutes (healthy) 0.0.0.0:1433->1433/tcp, [::]:1433->1433/tcp 41d685349a7640b28230db8d0f60efe7_mcrmicrosoftcommssqlserver2022latest_fe29fb 108MB (virtual 1.72GB)
|
|
||||||
# d5fbc5f811af postgres:17-alpine "docker-entrypoint.s…" 6 minutes ago Up 6 minutes (healthy) 0.0.0.0:5432->5432/tcp, [::]:5432->5432/tcp 2783be71b5ce417ab9a31428e7b4d8f2_postgres17alpine_c60840 63B (virtual 278MB)
|
|
||||||
# da96a7ad7a01 mariadb:11.4 "docker-entrypoint.s…" 7 minutes ago Up 7 minutes 0.0.0.0:3307->3306/tcp, [::]:3307->3306/tcp 45eed646fa6c4a698893ee11cda95a4c_mariadb114_3a9cd6 2B (virtual 332MB)
|
|
||||||
# 27ba1904ba3a mysql:5.7 "docker-entrypoint.s…" 7 minutes ago Up 7 minutes 0.0.0.0:3306->3306/tcp, [::]:3306->3306/tcp, 33060/tcp ea6d7a4c207d427a95b5ae0db91fdf56_mysql57_c21053 4B (virtual 501MB)
|
|
||||||
# 518e785d1bb6 redis:7.0 "docker-entrypoint.s…" 7 minutes ago Up 7 minutes (healthy) 0.0.0.0:6379->6379/tcp, [::]:6379->6379/tcp af6044fc849e441bbc6c48f7a5ec5fec_redis70_b11994 0B (virtual 109MB)
|
|
||||||
# 7495ec2cd8e3 bitnamilegacy/etcd:3.4.24 "/opt/bitnami/script…" 7 minutes ago Up 7 minutes 0.0.0.0:2379->2379/tcp, [::]:2379->2379/tcp, 2380/tcp 49f2a2a6bf3a4fae842cc950bbc3658a_bitnamilegacyetcd3424_1265e1 145MB (virtual 279MB)
|
|
||||||
|
|
||||||
# runner@runnervmg1sw1:~/work/gf/gf$ du -ah --max-depth=1 /usr | sort -n
|
|
||||||
# 4.0K /usr/games
|
|
||||||
# 4.0K /usr/lib64
|
|
||||||
# 6.6G /usr/lib
|
|
||||||
# 9.3G /usr/share
|
|
||||||
# 15M /usr/lib32
|
|
||||||
# 24G /usr/local
|
|
||||||
# 41G /usr
|
|
||||||
# 95M /usr/sbin
|
|
||||||
# 156M /usr/include
|
|
||||||
# 158M /usr/src
|
|
||||||
# 402M /usr/libexec
|
|
||||||
# 841M /usr/bin
|
|
||||||
|
|
||||||
# runner@runnervmg1sw1:~/work/gf/gf$ du -ah --max-depth=1 /opt | sort -n
|
|
||||||
# 4.0K /opt/pipx_bin
|
|
||||||
# 5.8G /opt/hostedtoolcache
|
|
||||||
# 8.5G /opt
|
|
||||||
# 12K /opt/containerd
|
|
||||||
# 14M /opt/hca
|
|
||||||
# 16K /opt/post-generation
|
|
||||||
# 217M /opt/runner-cache
|
|
||||||
# 243M /opt/actionarchivecache
|
|
||||||
# 374M /opt/google
|
|
||||||
# 515M /opt/pipx
|
|
||||||
# 655M /opt/az
|
|
||||||
# 783M /opt/microsoft
|
|
||||||
|
|
||||||
# runner@runnervmg1sw1:~/work/gf/gf$ du -ah --max-depth=1 /opt/hostedtoolcache/ | sort -n
|
|
||||||
# 1.1G /opt/hostedtoolcache/go
|
|
||||||
# 1.6G /opt/hostedtoolcache/CodeQL
|
|
||||||
# 1.9G /opt/hostedtoolcache/Python
|
|
||||||
# 5.8G /opt/hostedtoolcache/
|
|
||||||
# 9.9M /opt/hostedtoolcache/protoc
|
|
||||||
# 24K /opt/hostedtoolcache/Java_Temurin-Hotspot_jdk
|
|
||||||
# 217M /opt/hostedtoolcache/Ruby
|
|
||||||
# 520M /opt/hostedtoolcache/PyPy
|
|
||||||
# 574M /opt/hostedtoolcache/node
|
|
||||||
|
|
||||||
59
.github/workflows/scripts/ci-main.sh
vendored
59
.github/workflows/scripts/ci-main.sh
vendored
@ -1,59 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
coverage=$1
|
|
||||||
|
|
||||||
# find all path that contains go.mod.
|
|
||||||
for file in `find . -name go.mod`; do
|
|
||||||
dirpath=$(dirname $file)
|
|
||||||
echo $dirpath
|
|
||||||
|
|
||||||
# package kubecm was moved to sub ci procedure.
|
|
||||||
if [ "kubecm" = $(basename $dirpath) ]; then
|
|
||||||
continue 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# examples directory was moved to sub ci procedure.
|
|
||||||
if [[ $dirpath =~ "/examples/" ]]; then
|
|
||||||
continue 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ $file =~ "/testdata/" ]]; then
|
|
||||||
echo "ignore testdata path $file"
|
|
||||||
continue 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Check if it's a contrib directory
|
|
||||||
if [[ $dirpath =~ "/contrib/" ]]; then
|
|
||||||
# Check if go version meets the requirement
|
|
||||||
if ! go version | grep -qE "go${LATEST_GO_VERSION}"; then
|
|
||||||
echo "ignore path $dirpath as go version is not ${LATEST_GO_VERSION}: $(go version)"
|
|
||||||
# clean docker containers and images to free disk space
|
|
||||||
# bash .github/workflows/scripts/ci-main-clean.sh "$dirpath"
|
|
||||||
continue 1
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# if [[ $dirpath = "." ]]; then
|
|
||||||
# # No space left on device error sometimes occurs in CI pipelines, so clean the cache before tests.
|
|
||||||
# go clean -cache
|
|
||||||
# fi
|
|
||||||
|
|
||||||
cd $dirpath
|
|
||||||
go mod tidy
|
|
||||||
go build ./...
|
|
||||||
|
|
||||||
# test with coverage
|
|
||||||
if [ "${coverage}" = "coverage" ]; then
|
|
||||||
go test ./... -count=1 -race -coverprofile=coverage.out -covermode=atomic -coverpkg=./...,github.com/gogf/gf/... || exit 1
|
|
||||||
|
|
||||||
if grep -q "/gogf/gf/.*/v2" go.mod; then
|
|
||||||
sed -i "s/gogf\/gf\(\/.*\)\/v2/gogf\/gf\/v2\1/g" coverage.out
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
go test ./... -count=1 -race || exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
cd -
|
|
||||||
# clean docker containers and images to free disk space
|
|
||||||
# bash .github/workflows/scripts/ci-main-clean.sh "$dirpath"
|
|
||||||
done
|
|
||||||
86
.github/workflows/scripts/ci-sub.sh
vendored
86
.github/workflows/scripts/ci-sub.sh
vendored
@ -1,86 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
coverage=$1
|
|
||||||
|
|
||||||
# update code of submodules
|
|
||||||
git clone https://github.com/gogf/examples
|
|
||||||
|
|
||||||
# update go.mod in examples directory to replace github.com/gogf/gf packages with local directory
|
|
||||||
bash .github/workflows/scripts/replace_examples_gomod.sh
|
|
||||||
|
|
||||||
# Function to compare version numbers
|
|
||||||
version_compare() {
|
|
||||||
local ver1=$1
|
|
||||||
local ver2=$2
|
|
||||||
|
|
||||||
# Remove 'go' prefix and 'v' if present
|
|
||||||
ver1=$(echo "$ver1" | sed 's/^go//; s/^v//')
|
|
||||||
ver2=$(echo "$ver2" | sed 's/^go//; s/^v//')
|
|
||||||
|
|
||||||
# Split versions into major.minor format
|
|
||||||
local major1=$(echo "$ver1" | cut -d. -f1)
|
|
||||||
local minor1=$(echo "$ver1" | cut -d. -f2)
|
|
||||||
local major2=$(echo "$ver2" | cut -d. -f1)
|
|
||||||
local minor2=$(echo "$ver2" | cut -d. -f2)
|
|
||||||
|
|
||||||
# Compare versions: return 0 if ver1 <= ver2, 1 otherwise
|
|
||||||
if [ "$major1" -lt "$major2" ]; then
|
|
||||||
return 0
|
|
||||||
elif [ "$major1" -eq "$major2" ] && [ "$minor1" -le "$minor2" ]; then
|
|
||||||
return 0
|
|
||||||
else
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# Get current Go version
|
|
||||||
current_go_version=$(go version | grep -oE 'go[0-9]+\.[0-9]+')
|
|
||||||
|
|
||||||
# find all path that contains go.mod.
|
|
||||||
for file in `find . -name go.mod`; do
|
|
||||||
dirpath=$(dirname $file)
|
|
||||||
echo "Processing: $dirpath"
|
|
||||||
|
|
||||||
# Only process examples and kubecm directories
|
|
||||||
|
|
||||||
# Process examples directory (only build, no tests)
|
|
||||||
if [[ $dirpath =~ "/examples/" ]]; then
|
|
||||||
echo " the examples directory only needs to be built, not unit tests."
|
|
||||||
cd $dirpath
|
|
||||||
go mod tidy
|
|
||||||
go build ./...
|
|
||||||
cd -
|
|
||||||
continue 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Process kubecm directory
|
|
||||||
if [ "kubecm" != $(basename $dirpath) ]; then
|
|
||||||
echo " Skipping: not kubecm directory"
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
|
|
||||||
cd $dirpath
|
|
||||||
|
|
||||||
# Read Go version requirement from go.mod
|
|
||||||
if [ -f "go.mod" ]; then
|
|
||||||
go_mod_version=$(grep '^go ' go.mod | awk '{print $2}' | head -1)
|
|
||||||
|
|
||||||
if [ -n "$go_mod_version" ]; then
|
|
||||||
echo " go.mod requires: go$go_mod_version"
|
|
||||||
echo " current version: $current_go_version"
|
|
||||||
|
|
||||||
# Check if go.mod version requirement is satisfied by current Go version
|
|
||||||
if version_compare "$go_mod_version" "$current_go_version"; then
|
|
||||||
echo " ✓ Version requirement satisfied, proceeding with build and test"
|
|
||||||
|
|
||||||
go mod tidy
|
|
||||||
go build ./...
|
|
||||||
go test ./... -race || exit 1
|
|
||||||
else
|
|
||||||
echo " ✗ Current Go version ($current_go_version) does not meet requirement (go$go_mod_version), skipping"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
cd -
|
|
||||||
done
|
|
||||||
@ -1,81 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
# Get the absolute path to the repository root
|
|
||||||
repo_root=$(pwd)
|
|
||||||
workdir=$repo_root/examples
|
|
||||||
|
|
||||||
echo "Prepare to process go.mod files in the ${workdir} directory"
|
|
||||||
|
|
||||||
# Check if examples directory exists
|
|
||||||
if [ ! -d "${workdir}" ]; then
|
|
||||||
echo "Error: examples directory not found at ${workdir}"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Check if find command is available
|
|
||||||
if ! command -v find &> /dev/null; then
|
|
||||||
echo "Error: find command not found!"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
for file in `find ${workdir} -name go.mod`; do
|
|
||||||
goModPath=$(dirname $file)
|
|
||||||
echo ""
|
|
||||||
echo "Processing dir: $goModPath"
|
|
||||||
|
|
||||||
# Calculate relative path to root
|
|
||||||
# First get the relative path from go.mod to repo root
|
|
||||||
relativePath=""
|
|
||||||
current="$goModPath"
|
|
||||||
while [ "$current" != "$repo_root" ]; do
|
|
||||||
relativePath="../$relativePath"
|
|
||||||
current=$(dirname "$current")
|
|
||||||
done
|
|
||||||
relativePath=${relativePath%/} # Remove trailing slash
|
|
||||||
echo "Relative path to root: $relativePath"
|
|
||||||
|
|
||||||
# Get all github.com/gogf/gf dependencies
|
|
||||||
# Use awk to get package names without version numbers
|
|
||||||
dependencies=$(awk '/^[[:space:]]*github\.com\/gogf\/gf\// {print $1}' "$file" | sort -u)
|
|
||||||
|
|
||||||
if [ -n "$dependencies" ]; then
|
|
||||||
echo "Found GoFrame dependencies:"
|
|
||||||
echo "$dependencies"
|
|
||||||
echo "Adding replace directives..."
|
|
||||||
|
|
||||||
# Create temporary file
|
|
||||||
temp_file="${file}.tmp"
|
|
||||||
# Remove existing replace directives and copy to temp file
|
|
||||||
sed '/^replace.*github\.com\/gogf\/gf.*/d' "$file" > "$temp_file"
|
|
||||||
|
|
||||||
# Add new replace block
|
|
||||||
echo "" >> "$temp_file"
|
|
||||||
echo "replace (" >> "$temp_file"
|
|
||||||
|
|
||||||
while IFS= read -r dep; do
|
|
||||||
# Skip empty lines
|
|
||||||
[ -z "$dep" ] && continue
|
|
||||||
|
|
||||||
# Calculate the relative path for the replacement
|
|
||||||
if [[ "$dep" == "github.com/gogf/gf/v2" ]]; then
|
|
||||||
replacement="$relativePath"
|
|
||||||
else
|
|
||||||
# Extract the path after v2 and remove trailing version
|
|
||||||
subpath=$(echo "$dep" | sed -E 's/github\.com\/gogf\/gf\/(contrib\/[^/]+\/[^/]+)\/v2.*/\1/')
|
|
||||||
replacement="$relativePath/$subpath"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo " $dep => $replacement/" >> "$temp_file"
|
|
||||||
done <<< "$dependencies"
|
|
||||||
|
|
||||||
echo ")" >> "$temp_file"
|
|
||||||
|
|
||||||
# Replace original file with temporary file
|
|
||||||
mv "$temp_file" "$file"
|
|
||||||
echo "Replace directives added to $file"
|
|
||||||
else
|
|
||||||
echo "No GoFrame dependencies found in $file"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
echo "\nAll go.mod files have been processed successfully."
|
|
||||||
50
.github/workflows/scripts/update_version.sh
vendored
50
.github/workflows/scripts/update_version.sh
vendored
@ -1,50 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
# Check if the number of parameters is 2
|
|
||||||
if [ $# -ne 2 ]; then
|
|
||||||
echo "Invalid parameters, please execute in format: version.sh [directory] [version]"
|
|
||||||
echo "Example: version.sh ./contrib v1.0.0"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Check if the first parameter is a directory and exists
|
|
||||||
if [ ! -d "$1" ]; then
|
|
||||||
echo "Error: Directory does not exist"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Check if the second parameter starts with 'v'
|
|
||||||
if [[ "$2" != v* ]]; then
|
|
||||||
echo "Error: Version number does not start with 'v'"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
workdir=$1
|
|
||||||
newVersion=$2
|
|
||||||
echo "Preparing to replace version numbers in all go.mod files under ${workdir} directory to ${newVersion}"
|
|
||||||
|
|
||||||
|
|
||||||
# Check if file exists
|
|
||||||
if [ -f "go.work" ]; then
|
|
||||||
# File exists, rename it
|
|
||||||
mv go.work go.work.${newVersion}
|
|
||||||
echo "Backup go.work file to avoid affecting the upgrade"
|
|
||||||
fi
|
|
||||||
|
|
||||||
for file in `find ${workdir} -name go.mod`; do
|
|
||||||
goModPath=$(dirname $file)
|
|
||||||
echo ""
|
|
||||||
echo "processing dir: $goModPath"
|
|
||||||
cd $goModPath
|
|
||||||
go mod tidy
|
|
||||||
go list -f "{{if and (not .Indirect) (not .Main)}}{{.Path}}@${newVersion}{{end}}" -m all | grep "^github.com/gogf/gf"
|
|
||||||
go list -f "{{if and (not .Indirect) (not .Main)}}{{.Path}}@${newVersion}{{end}}" -m all | grep "^github.com/gogf/gf" | xargs -L1 go get -v
|
|
||||||
go mod tidy
|
|
||||||
cd -
|
|
||||||
done
|
|
||||||
|
|
||||||
if [ -f "go.work.${newVersion}" ]; then
|
|
||||||
# File exists, rename it back
|
|
||||||
mv go.work.${newVersion} go.work
|
|
||||||
echo "Restore go.work file"
|
|
||||||
fi
|
|
||||||
38
.github/workflows/tag.yml
vendored
38
.github/workflows/tag.yml
vendored
@ -4,56 +4,36 @@ on:
|
|||||||
push:
|
push:
|
||||||
# Sequence of patterns matched against refs/tags
|
# Sequence of patterns matched against refs/tags
|
||||||
tags:
|
tags:
|
||||||
- 'v*' # Push events to matching v*, i.e. v1.0, v20.15.10
|
- 'v*' # Push events to matching v*, i.e. v1.0, v20.15.10
|
||||||
|
|
||||||
env:
|
env:
|
||||||
TZ: Asia/Shanghai
|
TZ: Asia/Shanghai
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
name: Auto Creating Tags
|
name: Auto Creating Tags
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout Github Code
|
- name: Checkout Github Code
|
||||||
uses: actions/checkout@v5
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Auto Creating Tags For Contrib Packages
|
- name: Auto Creating Tags For Contrib Packages
|
||||||
run: |
|
run: |
|
||||||
git config --global user.email "tagrobot@goframe.org"
|
git config --global user.email "tagrobot@goframe.org"
|
||||||
git config --global user.name "TagRobot"
|
git config --global user.name "TagRobot"
|
||||||
|
|
||||||
# auto create tags for contrib packages.
|
# auto create tags for contrib packages.
|
||||||
for file in `find contrib -name go.mod`; do
|
for file in `find contrib -name go.mod`; do
|
||||||
tag=$(dirname $file)/${{ github.ref_name }}
|
tag=$(dirname $file)/$GITHUB_REF_NAME
|
||||||
git tag $tag
|
git tag $tag
|
||||||
git push origin $tag
|
git push origin $tag
|
||||||
done
|
done
|
||||||
- name: update dependencies
|
|
||||||
run: |
|
|
||||||
go env -w GOPRIVATE=github.com/gogf/gf
|
|
||||||
.github/workflows/scripts/update_version.sh ./cmd/gf ${{ github.ref_name }}
|
|
||||||
- name: Create Pull Request
|
|
||||||
uses: peter-evans/create-pull-request@v4
|
|
||||||
with:
|
|
||||||
commit-message: 'update gf cli to ${{ github.ref_name }}'
|
|
||||||
title: 'fix: update gf cli to ${{ github.ref_name }}'
|
|
||||||
base: master
|
|
||||||
branch: fix/${{ github.ref_name }}
|
|
||||||
delete-branch: true
|
|
||||||
- name: Commit & Push changes
|
|
||||||
uses: actions-js/push@master
|
|
||||||
with:
|
|
||||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
branch: fix/${{ github.ref_name }}
|
|
||||||
author_name: TagRobot
|
|
||||||
author_email: tagrobot@goframe.org
|
|
||||||
message: 'fix: update gf cli to ${{ github.ref_name }}'
|
|
||||||
- name: Auto Creating Tags For cli tool
|
|
||||||
run: |
|
|
||||||
git config --global user.email "tagrobot@goframe.org"
|
|
||||||
git config --global user.name "TagRobot"
|
|
||||||
# auto create tag for cli tool
|
# auto create tag for cli tool
|
||||||
for file in `find cmd -name go.mod -not -path "*/testdata/*"`; do
|
for file in `find cmd -name go.mod`; do
|
||||||
tag=$(dirname $file)/${{ github.ref_name }}
|
tag=$(dirname $file)/$GITHUB_REF_NAME
|
||||||
git tag $tag
|
git tag $tag
|
||||||
git push origin $tag
|
git push origin $tag
|
||||||
done
|
done
|
||||||
|
|||||||
12
.gitignore
vendored
12
.gitignore
vendored
@ -7,21 +7,13 @@
|
|||||||
.settings/
|
.settings/
|
||||||
.vscode/
|
.vscode/
|
||||||
vendor/
|
vendor/
|
||||||
|
pkg/
|
||||||
bin/
|
bin/
|
||||||
**/.DS_Store
|
**/.DS_Store
|
||||||
.test/
|
.test/
|
||||||
cmd/gf/main
|
cmd/gf/main
|
||||||
cmd/gf/gf
|
cmd/gf/gf
|
||||||
temp/
|
temp/
|
||||||
example/log
|
|
||||||
go.work
|
go.work
|
||||||
go.work.sum
|
go.work.sum
|
||||||
!cmd/gf/go.work
|
!cmd/gf/go.work
|
||||||
.windsurfrules
|
|
||||||
|
|
||||||
# Ignore for docs
|
|
||||||
node_modules
|
|
||||||
.docusaurus
|
|
||||||
output
|
|
||||||
.example/
|
|
||||||
.golangci.bck.yml
|
|
||||||
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -1,3 +0,0 @@
|
|||||||
[submodule "examples"]
|
|
||||||
path = examples
|
|
||||||
url = git@github.com:gogf/examples.git
|
|
||||||
490
.golangci.yml
490
.golangci.yml
@ -1,220 +1,282 @@
|
|||||||
version: "2"
|
## This file contains all available configuration options
|
||||||
|
## with their default values.
|
||||||
|
|
||||||
|
# See https://github.com/golangci/golangci-lint#config-file
|
||||||
|
# See https://golangci-lint.run/usage/configuration/
|
||||||
|
|
||||||
|
# Options for analysis running.
|
||||||
run:
|
run:
|
||||||
concurrency: 4
|
# Exit code when at least one issue was found.
|
||||||
go: "1.25"
|
# Default: 1
|
||||||
modules-download-mode: readonly
|
|
||||||
issues-exit-code: 2
|
issues-exit-code: 2
|
||||||
|
|
||||||
|
# Include test files or not.
|
||||||
|
# Default: true
|
||||||
tests: false
|
tests: false
|
||||||
allow-parallel-runners: true
|
|
||||||
allow-serial-runners: true
|
# Which dirs to skip: issues from them won't be reported.
|
||||||
|
# Can use regexp here: `generated.*`, regexp is applied on full path.
|
||||||
|
# Default value is empty list,
|
||||||
|
# but default dirs are skipped independently of this option's value (see skip-dirs-use-default).
|
||||||
|
# "/" will be replaced by current OS file path separator to properly work on Windows.
|
||||||
|
skip-dirs: []
|
||||||
|
|
||||||
|
# Which files to skip: they will be analyzed, but issues from them won't be reported.
|
||||||
|
# Default value is empty list,
|
||||||
|
# but there is no need to include all autogenerated files,
|
||||||
|
# we confidently recognize autogenerated files.
|
||||||
|
# If it's not please let us know.
|
||||||
|
# "/" will be replaced by current OS file path separator to properly work on Windows.
|
||||||
|
skip-files: []
|
||||||
|
|
||||||
|
|
||||||
|
# Main linters configurations.
|
||||||
|
# See https://golangci-lint.run/usage/linters
|
||||||
linters:
|
linters:
|
||||||
default: none
|
# Disable all default enabled linters.
|
||||||
|
disable-all: true
|
||||||
|
# Custom enable linters we want to use.
|
||||||
enable:
|
enable:
|
||||||
- errcheck
|
- errcheck # Errcheck is a program for checking for unchecked errors in go programs.
|
||||||
- errchkjson
|
- errchkjson # Checks types passed to the json encoding functions. Reports unsupported types and optionally reports occasions, where the check for the returned error can be omitted.
|
||||||
- funlen
|
- funlen # Tool for detection of long functions
|
||||||
- goconst
|
- goconst # Finds repeated strings that could be replaced by a constant
|
||||||
- gocritic
|
- gocritic # Provides diagnostics that check for bugs, performance and style issues.
|
||||||
- govet
|
- gofmt # Gofmt checks whether code was gofmt-ed. By default this tool runs with -s option to check for code simplification
|
||||||
- misspell
|
- gosimple # Linter for Go source code that specializes in simplifying code
|
||||||
- nolintlint
|
- govet # Vet examines Go source code and reports suspicious constructs, such as Printf calls whose arguments do not align with the format string
|
||||||
- revive
|
- misspell # Finds commonly misspelled English words in comments
|
||||||
- staticcheck
|
- nolintlint # Reports ill-formed or insufficient nolint directives
|
||||||
- usestdlibvars
|
- revive # Fast, configurable, extensible, flexible, and beautiful linter for Go. Drop-in replacement of golint.
|
||||||
- whitespace
|
- staticcheck # It's a set of rules from staticcheck. It's not the same thing as the staticcheck binary.
|
||||||
settings:
|
- typecheck # Like the front-end of a Go compiler, parses and type-checks Go code
|
||||||
funlen:
|
- usestdlibvars # A linter that detect the possibility to use variables/constants from the Go standard library.
|
||||||
lines: 340
|
- whitespace # Tool for detection of leading and trailing whitespace
|
||||||
statements: -1
|
|
||||||
goconst:
|
|
||||||
match-constant: false
|
issues:
|
||||||
min-len: 4
|
exclude-rules:
|
||||||
min-occurrences: 30
|
# helpers in tests often (rightfully) pass a *testing.T as their first argument
|
||||||
numbers: true
|
- path: _test\.go
|
||||||
min: 5
|
text: "context.Context should be the first parameter of a function"
|
||||||
max: 20
|
linters:
|
||||||
ignore-calls: false
|
- revive
|
||||||
gocritic:
|
# Yes, they are, but it's okay in a test
|
||||||
disabled-checks:
|
- path: _test\.go
|
||||||
- ifElseChain
|
text: "exported func.*returns unexported type.*which can be annoying to use"
|
||||||
- assignOp
|
linters:
|
||||||
- appendAssign
|
- revive
|
||||||
- singleCaseSwitch
|
# https://github.com/go-critic/go-critic/issues/926
|
||||||
- regexpMust
|
- linters:
|
||||||
- typeSwitchVar
|
- gocritic
|
||||||
- elseif
|
text: "unnecessaryDefer:"
|
||||||
govet:
|
|
||||||
disable:
|
|
||||||
- asmdecl
|
# https://golangci-lint.run/usage/linters
|
||||||
- assign
|
linters-settings:
|
||||||
- atomic
|
# https://golangci-lint.run/usage/linters/#misspell
|
||||||
- atomicalign
|
misspell:
|
||||||
- bools
|
locale: US
|
||||||
- buildtag
|
ignore-words:
|
||||||
- cgocall
|
- cancelled
|
||||||
- composites
|
|
||||||
- copylocks
|
# https://golangci-lint.run/usage/linters/#revive
|
||||||
- deepequalerrors
|
# https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md
|
||||||
- errorsas
|
revive:
|
||||||
- fieldalignment
|
ignore-generated-header: true
|
||||||
- findcall
|
severity: error
|
||||||
- framepointer
|
|
||||||
- httpresponse
|
|
||||||
- ifaceassert
|
|
||||||
- loopclosure
|
|
||||||
- lostcancel
|
|
||||||
- nilfunc
|
|
||||||
- nilness
|
|
||||||
- reflectvaluecompare
|
|
||||||
- shift
|
|
||||||
- shadow
|
|
||||||
- sigchanyzer
|
|
||||||
- sortslice
|
|
||||||
- stdmethods
|
|
||||||
- stringintconv
|
|
||||||
- structtag
|
|
||||||
- testinggoroutine
|
|
||||||
- tests
|
|
||||||
- unmarshal
|
|
||||||
- unreachable
|
|
||||||
- unsafeptr
|
|
||||||
- unusedwrite
|
|
||||||
enable-all: true
|
|
||||||
settings:
|
|
||||||
printf:
|
|
||||||
funcs:
|
|
||||||
- (github.com/golangci/golangci-lint/pkg/logutils.Log).Infof
|
|
||||||
- (github.com/golangci/golangci-lint/pkg/logutils.Log).Warnf
|
|
||||||
- (github.com/golangci/golangci-lint/pkg/logutils.Log).Errorf
|
|
||||||
- (github.com/golangci/golangci-lint/pkg/logutils.Log).Fatalf
|
|
||||||
unusedresult:
|
|
||||||
funcs:
|
|
||||||
- pkg.MyFunc
|
|
||||||
- context.WithCancel
|
|
||||||
stringmethods:
|
|
||||||
- MyMethod
|
|
||||||
misspell:
|
|
||||||
locale: US
|
|
||||||
ignore-rules:
|
|
||||||
- cancelled
|
|
||||||
revive:
|
|
||||||
severity: error
|
|
||||||
rules:
|
|
||||||
- name: atomic
|
|
||||||
- name: line-length-limit
|
|
||||||
arguments:
|
|
||||||
- 380
|
|
||||||
severity: error
|
|
||||||
- name: unhandled-error
|
|
||||||
severity: warning
|
|
||||||
disabled: true
|
|
||||||
- name: var-naming
|
|
||||||
arguments:
|
|
||||||
- - ID
|
|
||||||
- URL
|
|
||||||
- IP
|
|
||||||
- HTTP
|
|
||||||
- JSON
|
|
||||||
- API
|
|
||||||
- UID
|
|
||||||
- Id
|
|
||||||
- Api
|
|
||||||
- Uid
|
|
||||||
- Http
|
|
||||||
- Json
|
|
||||||
- Ip
|
|
||||||
- Url
|
|
||||||
- - VM
|
|
||||||
severity: warning
|
|
||||||
disabled: true
|
|
||||||
- name: string-format
|
|
||||||
arguments:
|
|
||||||
- - core.WriteError[1].Message
|
|
||||||
- /^([^A-Z]|$)/
|
|
||||||
- must not start with a capital letter
|
|
||||||
- - fmt.Errorf[0]
|
|
||||||
- /(^|[^\.!?])$/
|
|
||||||
- must not end in punctuation
|
|
||||||
- - panic
|
|
||||||
- /^[^\n]*$/
|
|
||||||
- must not contain line breaks
|
|
||||||
severity: warning
|
|
||||||
disabled: false
|
|
||||||
- name: function-result-limit
|
|
||||||
arguments:
|
|
||||||
- 4
|
|
||||||
severity: warning
|
|
||||||
disabled: false
|
|
||||||
staticcheck:
|
|
||||||
checks: [ "all","-S1000","-S1009","-S1016","-S1023","-S1025","-S1029","-S1034","-S1040","-SA1016","-SA1019","-SA1029","-SA4006","-SA4015","-SA6003","-SA9003","-ST1003","-QF1001","-QF1002","-QF1003","-QF1006","-QF1007","-QF1008","-QF1011","-QF1012","-ST1011" ]
|
|
||||||
initialisms: [ "ACL", "API", "ASCII", "CPU", "CSS", "DNS", "EOF", "GUID", "HTML", "HTTP", "HTTPS", "ID", "IP", "JSON", "QPS", "RAM", "RPC", "SLA", "SMTP", "SQL", "SSH", "TCP", "TLS", "TTL", "UDP", "UI", "GID", "UID", "UUID", "URI", "URL", "UTF8", "VM", "XML", "XMPP", "XSRF", "XSS", "SIP", "RTP", "AMQP", "DB", "TS" ]
|
|
||||||
dot-import-whitelist: [ "fmt" ]
|
|
||||||
http-status-code-whitelist: [ "200", "400", "404", "500" ]
|
|
||||||
exclusions:
|
|
||||||
generated: lax
|
|
||||||
presets:
|
|
||||||
- comments
|
|
||||||
- common-false-positives
|
|
||||||
- legacy
|
|
||||||
- std-error-handling
|
|
||||||
rules:
|
rules:
|
||||||
- linters:
|
- name: atomic
|
||||||
- revive
|
- name: line-length-limit
|
||||||
path: _test\.go
|
severity: error
|
||||||
text: context.Context should be the first parameter of a function
|
arguments: [ 380 ]
|
||||||
- linters:
|
- name: unhandled-error
|
||||||
- revive
|
severity: warning
|
||||||
path: _test\.go
|
disabled: true
|
||||||
text: exported func.*returns unexported type.*which can be annoying to use
|
arguments: []
|
||||||
- linters:
|
- name: var-naming
|
||||||
- gocritic
|
severity: warning
|
||||||
text: 'unnecessaryDefer:'
|
disabled: true
|
||||||
- linters:
|
arguments:
|
||||||
- goconst
|
# AllowList
|
||||||
path: (.+)_test\.go
|
- [ "ID","URL","IP","HTTP","JSON","API","UID","Id","Api","Uid","Http","Json","Ip","Url" ]
|
||||||
paths:
|
# DenyList
|
||||||
- third_party$
|
- [ "VM" ]
|
||||||
- builtin$
|
- name: string-format
|
||||||
- examples$
|
severity: warning
|
||||||
formatters:
|
disabled: false
|
||||||
enable:
|
arguments:
|
||||||
- gci
|
- - 'core.WriteError[1].Message'
|
||||||
- gofmt
|
- '/^([^A-Z]|$)/'
|
||||||
- goimports
|
- must not start with a capital letter
|
||||||
settings:
|
- - 'fmt.Errorf[0]'
|
||||||
gci:
|
- '/(^|[^\.!?])$/'
|
||||||
sections:
|
- must not end in punctuation
|
||||||
- standard
|
- - panic
|
||||||
- blank
|
- '/^[^\n]*$/'
|
||||||
- default
|
- must not contain line breaks
|
||||||
- dot
|
- name: function-result-limit
|
||||||
- prefix(github.com/gogf/gf/v2)
|
severity: warning
|
||||||
- prefix(github.com/gogf/gf/cmd)
|
disabled: false
|
||||||
- prefix(github.com/gogf/gfcontrib)
|
arguments: [ 4 ]
|
||||||
- prefix(github.com/gogf/gf/example)
|
|
||||||
custom-order: true
|
# https://golangci-lint.run/usage/linters/#funlen
|
||||||
no-lex-order: false
|
funlen:
|
||||||
gofmt:
|
# Checks the number of lines in a function.
|
||||||
simplify: true
|
# If lower than 0, disable the check.
|
||||||
rewrite-rules:
|
# Default: 60
|
||||||
- pattern: 'interface{}'
|
lines: 330
|
||||||
replacement: 'any'
|
# Checks the number of statements in a function.
|
||||||
- pattern: 'reflect.Ptr'
|
# If lower than 0, disable the check.
|
||||||
replacement: 'reflect.Pointer'
|
# Default: 40
|
||||||
- pattern: 'ioutil.ReadAll'
|
statements: -1
|
||||||
replacement: 'io.ReadAll'
|
|
||||||
- pattern: 'ioutil.WriteFile'
|
# https://golangci-lint.run/usage/linters/#goconst
|
||||||
replacement: 'os.WriteFile'
|
goconst:
|
||||||
- pattern: 'ioutil.ReadFile'
|
# Minimal length of string constant.
|
||||||
replacement: 'os.ReadFile'
|
# Default: 3
|
||||||
- pattern: 'ioutil.NopCloser'
|
min-len: 4
|
||||||
replacement: 'io.NopCloser'
|
# Minimum occurrences of constant string count to trigger issue.
|
||||||
goimports:
|
# Default: 3
|
||||||
local-prefixes:
|
# For subsequent optimization, the value is reduced.
|
||||||
- github.com/gogf/gf/v2
|
min-occurrences: 30
|
||||||
exclusions:
|
# Ignore test files.
|
||||||
generated: lax
|
# Default: false
|
||||||
paths:
|
ignore-tests: true
|
||||||
- third_party$
|
# Look for existing constants matching the values.
|
||||||
- builtin$
|
# Default: true
|
||||||
- examples$
|
match-constant: false
|
||||||
|
# Search also for duplicated numbers.
|
||||||
|
# Default: false
|
||||||
|
numbers: true
|
||||||
|
# Minimum value, only works with goconst.numbers
|
||||||
|
# Default: 3
|
||||||
|
min: 5
|
||||||
|
# Maximum value, only works with goconst.numbers
|
||||||
|
# Default: 3
|
||||||
|
max: 20
|
||||||
|
# Ignore when constant is not used as function argument.
|
||||||
|
# Default: true
|
||||||
|
ignore-calls: false
|
||||||
|
|
||||||
|
# https://golangci-lint.run/usage/linters/#gocritic
|
||||||
|
gocritic:
|
||||||
|
disabled-checks:
|
||||||
|
- ifElseChain
|
||||||
|
- assignOp
|
||||||
|
- appendAssign
|
||||||
|
- singleCaseSwitch
|
||||||
|
- regexpMust
|
||||||
|
- typeSwitchVar
|
||||||
|
- elseif
|
||||||
|
|
||||||
|
# https://golangci-lint.run/usage/linters/#gosimple
|
||||||
|
gosimple:
|
||||||
|
# Select the Go version to target.
|
||||||
|
# Default: 1.13
|
||||||
|
# Deprecated: use the global `run.go` instead.
|
||||||
|
go: "1.15"
|
||||||
|
# Sxxxx checks in https://staticcheck.io/docs/configuration/options/#checks
|
||||||
|
# Default: ["*"]
|
||||||
|
checks: [
|
||||||
|
"all", "-S1000", "-S1001", "-S1002", "-S1008", "-S1009", "-S1016", "-S1023", "-S1025", "-S1029", "-S1034", "-S1040"
|
||||||
|
]
|
||||||
|
|
||||||
|
# https://golangci-lint.run/usage/linters/#govet
|
||||||
|
govet:
|
||||||
|
# Report about shadowed variables.
|
||||||
|
# Default: false
|
||||||
|
check-shadowing: true
|
||||||
|
# Settings per analyzer.
|
||||||
|
settings:
|
||||||
|
# Analyzer name, run `go tool vet help` to see all analyzers.
|
||||||
|
printf:
|
||||||
|
# Comma-separated list of print function names to check (in addition to default, see `go tool vet help printf`).
|
||||||
|
# Default: []
|
||||||
|
funcs:
|
||||||
|
- (github.com/golangci/golangci-lint/pkg/logutils.Log).Infof
|
||||||
|
- (github.com/golangci/golangci-lint/pkg/logutils.Log).Warnf
|
||||||
|
- (github.com/golangci/golangci-lint/pkg/logutils.Log).Errorf
|
||||||
|
- (github.com/golangci/golangci-lint/pkg/logutils.Log).Fatalf
|
||||||
|
# shadow:
|
||||||
|
# Whether to be strict about shadowing; can be noisy.
|
||||||
|
# Default: false
|
||||||
|
# strict: false
|
||||||
|
unusedresult:
|
||||||
|
# Comma-separated list of functions whose results must be used
|
||||||
|
# (in addition to defaults context.WithCancel,context.WithDeadline,context.WithTimeout,context.WithValue,
|
||||||
|
# errors.New,fmt.Errorf,fmt.Sprint,fmt.Sprintf,sort.Reverse)
|
||||||
|
# Default []
|
||||||
|
funcs:
|
||||||
|
- pkg.MyFunc
|
||||||
|
- context.WithCancel
|
||||||
|
# Comma-separated list of names of methods of type func() string whose results must be used
|
||||||
|
# (in addition to default Error,String)
|
||||||
|
# Default []
|
||||||
|
stringmethods:
|
||||||
|
- MyMethod
|
||||||
|
# Enable all analyzers.
|
||||||
|
# Default: false
|
||||||
|
enable-all: true
|
||||||
|
# Disable analyzers by name.
|
||||||
|
# Run `go tool vet help` to see all analyzers.
|
||||||
|
# Default: []
|
||||||
|
disable:
|
||||||
|
- asmdecl
|
||||||
|
- assign
|
||||||
|
- atomic
|
||||||
|
- atomicalign
|
||||||
|
- bools
|
||||||
|
- buildtag
|
||||||
|
- cgocall
|
||||||
|
- composites
|
||||||
|
- copylocks
|
||||||
|
- deepequalerrors
|
||||||
|
- errorsas
|
||||||
|
- fieldalignment
|
||||||
|
- findcall
|
||||||
|
- framepointer
|
||||||
|
- httpresponse
|
||||||
|
- ifaceassert
|
||||||
|
- loopclosure
|
||||||
|
- lostcancel
|
||||||
|
- nilfunc
|
||||||
|
- nilness
|
||||||
|
- reflectvaluecompare
|
||||||
|
- shift
|
||||||
|
- shadow
|
||||||
|
- sigchanyzer
|
||||||
|
- sortslice
|
||||||
|
- stdmethods
|
||||||
|
- stringintconv
|
||||||
|
- structtag
|
||||||
|
- testinggoroutine
|
||||||
|
- tests
|
||||||
|
- unmarshal
|
||||||
|
- unreachable
|
||||||
|
- unsafeptr
|
||||||
|
- unusedwrite
|
||||||
|
|
||||||
|
# https://golangci-lint.run/usage/linters/#staticcheck
|
||||||
|
staticcheck:
|
||||||
|
# Select the Go version to target.
|
||||||
|
# Default: "1.13"
|
||||||
|
# Deprecated: use the global `run.go` instead.
|
||||||
|
go: "1.15"
|
||||||
|
# SAxxxx checks in https://staticcheck.io/docs/configuration/options/#checks
|
||||||
|
# Default: ["*"]
|
||||||
|
checks: [ "all","-SA1019","-SA4015","-SA1029","-SA1016","-SA9003","-SA4006","-SA6003" ]
|
||||||
|
|
||||||
|
# https://golangci-lint.run/usage/linters/#gofmt
|
||||||
|
gofmt:
|
||||||
|
# Simplify code: gofmt with `-s` option.
|
||||||
|
# Default: true
|
||||||
|
simplify: true
|
||||||
|
# Apply the rewrite rules to the source before reformatting.
|
||||||
|
# https://pkg.go.dev/cmd/gofmt
|
||||||
|
# Default: []
|
||||||
|
rewrite-rules: [ ]
|
||||||
|
# - pattern: 'interface{}'
|
||||||
|
# replacement: 'any'
|
||||||
|
# - pattern: 'a[b:len(a)]'
|
||||||
|
# replacement: 'a[b:]'
|
||||||
|
|||||||
@ -1,35 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
workdir=.
|
|
||||||
echo "Prepare to tidy all go.mod files in the ${workdir} directory"
|
|
||||||
|
|
||||||
# check find command support or not
|
|
||||||
output=$(find "${workdir}" -name go.mod 2>&1)
|
|
||||||
if [[ $? -ne 0 ]]; then
|
|
||||||
echo "Error: please use bash or zsh to run!"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
for file in `find ${workdir} -name go.mod`; do
|
|
||||||
goModPath=$(dirname $file)
|
|
||||||
echo ""
|
|
||||||
echo "processing dir: $goModPath"
|
|
||||||
|
|
||||||
if [[ $goModPath =~ "/testdata/" ]]; then
|
|
||||||
echo "ignore testdata path $goModPath"
|
|
||||||
continue 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ $goModPath =~ "/examples/" ]]; then
|
|
||||||
echo "ignore examples path $goModPath"
|
|
||||||
continue 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
cd $goModPath
|
|
||||||
# Remove indirect dependencies
|
|
||||||
sed -i '/\/\/ indirect/d' go.mod
|
|
||||||
go mod tidy
|
|
||||||
# Remove toolchain line if exists
|
|
||||||
sed -i '' '/^toolchain/d' go.mod
|
|
||||||
cd - > /dev/null
|
|
||||||
done
|
|
||||||
@ -1,19 +1,5 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
# Function to detect OS and set sed parameters
|
|
||||||
setup_sed() {
|
|
||||||
if [[ "$OSTYPE" == "darwin"* ]]; then
|
|
||||||
# macOS
|
|
||||||
SED_INPLACE="sed -i ''"
|
|
||||||
else
|
|
||||||
# Linux/Windows Git Bash
|
|
||||||
SED_INPLACE="sed -i"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# Initialize sed command
|
|
||||||
setup_sed
|
|
||||||
|
|
||||||
if [ $# -ne 2 ]; then
|
if [ $# -ne 2 ]; then
|
||||||
echo "Parameter exception, please execute in the format of $0 [directory] [version number]"
|
echo "Parameter exception, please execute in the format of $0 [directory] [version number]"
|
||||||
echo "PS:$0 ./ v2.4.0"
|
echo "PS:$0 ./ v2.4.0"
|
||||||
@ -32,21 +18,15 @@ fi
|
|||||||
|
|
||||||
workdir=.
|
workdir=.
|
||||||
newVersion=$2
|
newVersion=$2
|
||||||
echo "Prepare to replace the GoFrame library version numbers in all go.mod files in the ${workdir} directory with ${newVersion}"
|
echo "Prepare to replace the GF library version numbers in all go.mod files in the ${workdir} directory with ${newVersion}"
|
||||||
|
|
||||||
# check find command support or not
|
|
||||||
output=$(find "${workdir}" -name go.mod 2>&1)
|
|
||||||
if [[ $? -ne 0 ]]; then
|
|
||||||
echo "Error: please use bash or zsh to run!"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ true ]]; then
|
if [[ true ]]; then
|
||||||
# Use sed to replace the version number in version.go
|
echo "package gf" > version.go
|
||||||
$SED_INPLACE 's/VERSION = ".*"/VERSION = "'${newVersion}'"/' version.go
|
echo "" >> version.go
|
||||||
|
echo "const (" >> version.go
|
||||||
# Use sed to replace the version number in README.MD
|
echo -e "\t// VERSION is the current GoFrame version." >> version.go
|
||||||
$SED_INPLACE 's/version=[^"]*/version='${newVersion}'/' README.MD
|
echo -e "\tVERSION = \"${newVersion}\"" >> version.go
|
||||||
|
echo ")" >> version.go
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -f "go.work" ]; then
|
if [ -f "go.work" ]; then
|
||||||
@ -58,17 +38,6 @@ for file in `find ${workdir} -name go.mod`; do
|
|||||||
goModPath=$(dirname $file)
|
goModPath=$(dirname $file)
|
||||||
echo ""
|
echo ""
|
||||||
echo "processing dir: $goModPath"
|
echo "processing dir: $goModPath"
|
||||||
|
|
||||||
if [[ $goModPath =~ "/testdata/" ]]; then
|
|
||||||
echo "ignore testdata path $goModPath"
|
|
||||||
continue 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ $goModPath =~ "/examples/" ]]; then
|
|
||||||
echo "ignore examples path $goModPath"
|
|
||||||
continue 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
cd $goModPath
|
cd $goModPath
|
||||||
if [ $goModPath = "./cmd/gf" ]; then
|
if [ $goModPath = "./cmd/gf" ]; then
|
||||||
mv go.work go.work.version.bak
|
mv go.work go.work.version.bak
|
||||||
@ -79,22 +48,15 @@ for file in `find ${workdir} -name go.mod`; do
|
|||||||
go mod edit -replace github.com/gogf/gf/contrib/drivers/oracle/v2=../../contrib/drivers/oracle
|
go mod edit -replace github.com/gogf/gf/contrib/drivers/oracle/v2=../../contrib/drivers/oracle
|
||||||
go mod edit -replace github.com/gogf/gf/contrib/drivers/pgsql/v2=../../contrib/drivers/pgsql
|
go mod edit -replace github.com/gogf/gf/contrib/drivers/pgsql/v2=../../contrib/drivers/pgsql
|
||||||
go mod edit -replace github.com/gogf/gf/contrib/drivers/sqlite/v2=../../contrib/drivers/sqlite
|
go mod edit -replace github.com/gogf/gf/contrib/drivers/sqlite/v2=../../contrib/drivers/sqlite
|
||||||
|
# else
|
||||||
|
# cd -
|
||||||
|
# continue 1
|
||||||
fi
|
fi
|
||||||
# Remove indirect dependencies
|
|
||||||
sed -i '/\/\/ indirect/d' go.mod
|
|
||||||
go mod tidy
|
go mod tidy
|
||||||
# Remove toolchain line if exists
|
# Upgrading only GF related libraries, sometimes even if a version number is specified, it may not be possible to successfully upgrade. Please confirm before submitting the code
|
||||||
$SED_INPLACE '/^toolchain/d' go.mod
|
|
||||||
|
|
||||||
# Upgrading only GoFrame related libraries, sometimes even if a version number is specified,
|
|
||||||
# it may not be possible to successfully upgrade. Please confirm before submitting the code
|
|
||||||
go list -f "{{if and (not .Indirect) (not .Main)}}{{.Path}}@${newVersion}{{end}}" -m all | grep "^github.com/gogf/gf"
|
go list -f "{{if and (not .Indirect) (not .Main)}}{{.Path}}@${newVersion}{{end}}" -m all | grep "^github.com/gogf/gf"
|
||||||
go list -f "{{if and (not .Indirect) (not .Main)}}{{.Path}}@${newVersion}{{end}}" -m all | grep "^github.com/gogf/gf" | xargs -L1 go get -v
|
go list -f "{{if and (not .Indirect) (not .Main)}}{{.Path}}@${newVersion}{{end}}" -m all | grep "^github.com/gogf/gf" | xargs -L1 go get -v
|
||||||
# Remove indirect dependencies
|
|
||||||
sed -i '/\/\/ indirect/d' go.mod
|
|
||||||
go mod tidy
|
go mod tidy
|
||||||
# Remove toolchain line if exists
|
|
||||||
$SED_INPLACE '/^toolchain/d' go.mod
|
|
||||||
if [ $goModPath = "./cmd/gf" ]; then
|
if [ $goModPath = "./cmd/gf" ]; then
|
||||||
go mod edit -dropreplace github.com/gogf/gf/v2
|
go mod edit -dropreplace github.com/gogf/gf/v2
|
||||||
go mod edit -dropreplace github.com/gogf/gf/contrib/drivers/clickhouse/v2
|
go mod edit -dropreplace github.com/gogf/gf/contrib/drivers/clickhouse/v2
|
||||||
@ -1,17 +0,0 @@
|
|||||||
# Contributing
|
|
||||||
|
|
||||||
Thanks for taking the time to join our community and start contributing!
|
|
||||||
|
|
||||||
## With issues
|
|
||||||
|
|
||||||
- Use the search tool before opening a new issue.
|
|
||||||
- Please provide source code and commit sha if you found a bug.
|
|
||||||
- Review existing issues and provide feedback or react to them.
|
|
||||||
|
|
||||||
## With pull requests
|
|
||||||
|
|
||||||
- Open your pull request against `master`
|
|
||||||
- Your pull request should have no more than two commits, if not you should squash them.
|
|
||||||
- It should pass all tests in the available continuous integrations systems such as GitHub CI.
|
|
||||||
- You should add/modify tests to cover your proposed code changes.
|
|
||||||
- If your pull request contains a new feature, please document it on the README.
|
|
||||||
2
LICENSE
2
LICENSE
@ -1,6 +1,6 @@
|
|||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2017 GoFrame Team https://goframe.org
|
Copyright (c) 2017 john@goframe.org https://goframe.org
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
71
Makefile
71
Makefile
@ -1,77 +1,26 @@
|
|||||||
SHELL := /bin/bash
|
SHELL := /bin/bash
|
||||||
|
|
||||||
# execute "go mod tidy" on all folders that have go.mod file
|
|
||||||
.PHONY: tidy
|
.PHONY: tidy
|
||||||
tidy:
|
tidy:
|
||||||
./.make_tidy.sh
|
$(eval files=$(shell find . -name go.mod))
|
||||||
|
@set -e; \
|
||||||
|
for file in ${files}; do \
|
||||||
|
goModPath=$$(dirname $$file); \
|
||||||
|
cd $$goModPath; \
|
||||||
|
go mod tidy; \
|
||||||
|
cd -; \
|
||||||
|
done
|
||||||
|
|
||||||
# execute "golangci-lint" to check code style
|
|
||||||
.PHONY: lint
|
.PHONY: lint
|
||||||
lint:
|
lint:
|
||||||
golangci-lint run -c .golangci.yml
|
golangci-lint run
|
||||||
|
|
||||||
# make branch to=v2.4.0
|
|
||||||
.PHONY: branch
|
|
||||||
branch:
|
|
||||||
@set -e; \
|
|
||||||
newVersion=$(to); \
|
|
||||||
if [ -z "$$newVersion" ]; then \
|
|
||||||
echo "Error: 'to' variable is required. Usage: make branch to=vX.Y.Z"; \
|
|
||||||
exit 1; \
|
|
||||||
fi; \
|
|
||||||
branchName=fix/$$newVersion; \
|
|
||||||
echo "Switching to master branch..."; \
|
|
||||||
git checkout master; \
|
|
||||||
echo "Pulling latest changes from master..."; \
|
|
||||||
git pull origin master; \
|
|
||||||
echo "Creating and switching to branch $$branchName from master..."; \
|
|
||||||
git checkout -b $$branchName; \
|
|
||||||
echo "Branch $$branchName created successfully!"
|
|
||||||
|
|
||||||
# make version to=v2.4.0
|
# make version to=v2.4.0
|
||||||
.PHONY: version
|
.PHONY: version
|
||||||
version:
|
version:
|
||||||
@set -e; \
|
@set -e; \
|
||||||
newVersion=$(to); \
|
newVersion=$(to); \
|
||||||
./.make_version.sh ./ $$newVersion; \
|
./.set_version.sh ./ $$newVersion; \
|
||||||
echo "make version to=$(to) done"
|
echo "make version to=$(to) done"
|
||||||
|
|
||||||
# make tag to=v2.4.0
|
|
||||||
.PHONY: tag
|
|
||||||
tag:
|
|
||||||
@set -e; \
|
|
||||||
newVersion=$(to); \
|
|
||||||
echo "Switching to master branch..."; \
|
|
||||||
git checkout master; \
|
|
||||||
echo "Pulling latest changes from master..."; \
|
|
||||||
git pull origin master; \
|
|
||||||
echo "Creating annotated tag $$newVersion..."; \
|
|
||||||
git tag -a $$newVersion -m "Release $$newVersion"; \
|
|
||||||
echo "Pushing tag $$newVersion..."; \
|
|
||||||
git push origin $$newVersion; \
|
|
||||||
echo "Tag $$newVersion created and pushed successfully!"
|
|
||||||
|
|
||||||
# update submodules
|
|
||||||
.PHONY: subup
|
|
||||||
subup:
|
|
||||||
@set -e; \
|
|
||||||
echo "Updating submodules..."; \
|
|
||||||
git submodule init;\
|
|
||||||
git submodule update;
|
|
||||||
|
|
||||||
# update and commit submodules
|
|
||||||
.PHONY: subsync
|
|
||||||
subsync: subup
|
|
||||||
@set -e; \
|
|
||||||
echo "";\
|
|
||||||
cd examples; \
|
|
||||||
echo "Checking for changes..."; \
|
|
||||||
if git diff-index --quiet HEAD --; then \
|
|
||||||
echo "No changes to commit"; \
|
|
||||||
else \
|
|
||||||
echo "Found changes, committing..."; \
|
|
||||||
git add -A; \
|
|
||||||
git commit -m "examples update"; \
|
|
||||||
git push origin; \
|
|
||||||
fi; \
|
|
||||||
cd ..;
|
|
||||||
|
|||||||
108
README.MD
108
README.MD
@ -1,46 +1,94 @@
|
|||||||
English | [简体中文](README.zh_CN.MD)
|
# GoFrame
|
||||||
|
|
||||||
<div align=center>
|
<div align=center>
|
||||||
<img src="https://goframe.org/img/logo_full.png" width="300" alt="goframe gf logo"/>
|
<img src="https://goframe.org/statics/image/logo2.png?v=1" width="300"/>
|
||||||
|
|
||||||
[](https://pkg.go.dev/github.com/gogf/gf/v2)
|
[](https://pkg.go.dev/github.com/gogf/gf/v2)
|
||||||
[](https://github.com/gogf/gf/actions/workflows/ci-main.yml)
|
[](https://github.com/gogf/gf/actions/workflows/ci-main.yml)
|
||||||
[](https://scorecard.dev/viewer/?uri=github.com/gogf/gf)
|
|
||||||
[](https://bestpractices.coreinfrastructure.org/projects/9233)
|
|
||||||
[](https://goreportcard.com/report/github.com/gogf/gf/v2)
|
[](https://goreportcard.com/report/github.com/gogf/gf/v2)
|
||||||
[](https://codecov.io/gh/gogf/gf)
|
[](https://codecov.io/gh/gogf/gf)
|
||||||
[](https://github.com/gogf/gf)
|
[](https://github.com/gogf/gf)
|
||||||
[](https://github.com/gogf/gf)
|
[](https://github.com/gogf/gf)
|
||||||
|
|
||||||
[](https://github.com/gogf/gf/releases)
|
|
||||||
[](https://github.com/gogf/gf/pulls)
|
|
||||||
[](https://github.com/gogf/gf/pulls?q=is%3Apr+is%3Aclosed)
|
|
||||||
[](https://github.com/gogf/gf/issues)
|
|
||||||
[](https://github.com/gogf/gf/issues?q=is%3Aissue+is%3Aclosed)
|
|
||||||

|
|
||||||

|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
A powerful framework for faster, easier, and more efficient project development.
|
`GoFrame` is a modular, powerful, high-performance and enterprise-class application development framework of Golang.
|
||||||
|
|
||||||
## Documentation
|
# Features
|
||||||
|
|
||||||
- Official Site: [https://goframe.org](https://goframe.org)
|
- modular, loosely coupled design
|
||||||
- Official Site(en): [https://goframe.org/en](https://goframe.org/en)
|
- rich components, out-of-the-box
|
||||||
- 国内镜像: [https://goframe.org.cn](https://goframe.org.cn)
|
- automatic codes generating for efficiency
|
||||||
- Mirror Site: [Github Pages](https://pages.goframe.org)
|
- simple and easy to use, detailed documentation
|
||||||
- Mirror Site: [Offline Docs](https://github.com/gogf/goframe.org-pdf?tab=readme-ov-file#%E6%9C%80%E6%96%B0%E7%89%88%E6%9C%AC)
|
- interface designed components, with high scalability
|
||||||
|
- fully supported tracing and error stack feature
|
||||||
|
- specially developed and powerful ORM component
|
||||||
|
- robust engineering design specifications
|
||||||
|
- convenient development CLI tool provide
|
||||||
|
- OpenTelemetry observability features support
|
||||||
|
- OpenAPIV3 documentation generating, automatically
|
||||||
|
- much, much more...ready to explore?
|
||||||
|
|
||||||
|
# Installation
|
||||||
|
|
||||||
|
Enter your repo. directory and execute following command:
|
||||||
|
|
||||||
|
## primary module
|
||||||
|
|
||||||
|
```bash
|
||||||
|
go get -u -v github.com/gogf/gf/v2
|
||||||
|
```
|
||||||
|
|
||||||
|
## cli tool
|
||||||
|
|
||||||
|
```bash
|
||||||
|
go install github.com/gogf/gf/cmd/gf/v2@latest
|
||||||
|
```
|
||||||
|
|
||||||
|
# Limitation
|
||||||
|
|
||||||
|
```
|
||||||
|
golang version >= 1.18
|
||||||
|
```
|
||||||
|
|
||||||
|
# Documentation
|
||||||
|
|
||||||
|
- Chinese Official Site(中文官网): [https://goframe.org](https://goframe.org/display/gf)
|
||||||
- GoDoc API: [https://pkg.go.dev/github.com/gogf/gf/v2](https://pkg.go.dev/github.com/gogf/gf/v2)
|
- GoDoc API: [https://pkg.go.dev/github.com/gogf/gf/v2](https://pkg.go.dev/github.com/gogf/gf/v2)
|
||||||
|
|
||||||
## Contributors
|
# License
|
||||||
|
|
||||||
💖 [Thanks to all the contributors who made GoFrame possible](https://github.com/gogf/gf/graphs/contributors) 💖
|
|
||||||
|
|
||||||
<a href="https://github.com/gogf/gf/graphs/contributors">
|
|
||||||
<img src="https://goframe.org/img/contributors.svg?version=v2.9.6" alt="goframe contributors"/>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
## License
|
|
||||||
|
|
||||||
`GoFrame` is licensed under the [MIT License](LICENSE), 100% free and open-source, forever.
|
`GoFrame` is licensed under the [MIT License](LICENSE), 100% free and open-source, forever.
|
||||||
|
|
||||||
|
# Part Of Users
|
||||||
|
|
||||||
|
- [Tencent](https://www.tencent.com/)
|
||||||
|
- [ZTE](https://www.zte.com.cn/china/)
|
||||||
|
- [Ant Financial Services](https://www.antfin.com/)
|
||||||
|
- [VIVO](https://www.vivo.com/)
|
||||||
|
- [MedLinker](https://www.medlinker.com/)
|
||||||
|
- [KuCoin](https://www.kucoin.io/)
|
||||||
|
- [LeYouJia](https://www.leyoujia.com/)
|
||||||
|
- [IGG](https://igg.com)
|
||||||
|
- [37](https://www.37.com)
|
||||||
|
- [XiMaLaYa](https://www.ximalaya.com)
|
||||||
|
- [ZYBang](https://www.zybang.com/)
|
||||||
|
|
||||||
|
> We list part of the users here, if your company or products are using `GoFrame`, please let us know [here](https://goframe.org/pages/viewpage.action?pageId=1114415).
|
||||||
|
|
||||||
|
# Contributors
|
||||||
|
|
||||||
|
This project exists thanks to all the people who contribute. [[Contributors](https://github.com/gogf/gf/graphs/contributors)].
|
||||||
|
<a href="https://github.com/gogf/gf/graphs/contributors"><img src="https://contributors-img.web.app/image?repo=gogf/gf" /></a>
|
||||||
|
|
||||||
|
# Donators
|
||||||
|
|
||||||
|
If you love `GoFrame`, why not [buy developer a cup of coffee](https://goframe.org/pages/viewpage.action?pageId=1115633)?
|
||||||
|
|
||||||
|
# Sponsors
|
||||||
|
|
||||||
|
We appreciate any kind of sponsorship for `GoFrame` development. If you've got some interesting, please contact WeChat `389961817` / Email `john@goframe.org`.
|
||||||
|
|
||||||
|
# Thanks
|
||||||
|
|
||||||
|
<a href="https://www.jetbrains.com/?from=GoFrame"><img src="https://goframe.org/download/thumbnails/1114119/jetbrains.png" height="120" alt="JetBrains"/></a>
|
||||||
|
<a href="https://www.atlassian.com/?from=GoFrame"><img src="https://goframe.org/download/attachments/1114119/atlassian.jpg" height="120" alt="Atlassian"/></a>
|
||||||
|
|||||||
@ -1,46 +0,0 @@
|
|||||||
[English](README.MD) | 简体中文
|
|
||||||
|
|
||||||
<div align=center>
|
|
||||||
<img src="https://goframe.org/img/logo_full.png" width="300" alt="goframe gf logo"/>
|
|
||||||
|
|
||||||
[](https://pkg.go.dev/github.com/gogf/gf/v2)
|
|
||||||
[](https://github.com/gogf/gf/actions/workflows/ci-main.yml)
|
|
||||||
[](https://scorecard.dev/viewer/?uri=github.com/gogf/gf)
|
|
||||||
[](https://bestpractices.coreinfrastructure.org/projects/9233)
|
|
||||||
[](https://goreportcard.com/report/github.com/gogf/gf/v2)
|
|
||||||
[](https://codecov.io/gh/gogf/gf)
|
|
||||||
[](https://github.com/gogf/gf)
|
|
||||||
[](https://github.com/gogf/gf)
|
|
||||||
|
|
||||||
[](https://github.com/gogf/gf/releases)
|
|
||||||
[](https://github.com/gogf/gf/pulls)
|
|
||||||
[](https://github.com/gogf/gf/pulls?q=is%3Apr+is%3Aclosed)
|
|
||||||
[](https://github.com/gogf/gf/issues)
|
|
||||||
[](https://github.com/gogf/gf/issues?q=is%3Aissue+is%3Aclosed)
|
|
||||||

|
|
||||||

|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
一个强大的框架,为了更快、更轻松、更高效的项目开发。
|
|
||||||
|
|
||||||
## 文档
|
|
||||||
|
|
||||||
- 官方网站: [https://goframe.org](https://goframe.org)
|
|
||||||
- 官方网站(en): [https://goframe.org/en](https://goframe.org/en)
|
|
||||||
- 国内镜像: [https://goframe.org.cn](https://goframe.org.cn)
|
|
||||||
- 镜像网站: [Github Pages](https://pages.goframe.org)
|
|
||||||
- 镜像网站: [离线文档](https://github.com/gogf/goframe.org-pdf?tab=readme-ov-file#%E6%9C%80%E6%96%B0%E7%89%88%E6%9C%AC)
|
|
||||||
- GoDoc API: [https://pkg.go.dev/github.com/gogf/gf/v2](https://pkg.go.dev/github.com/gogf/gf/v2)
|
|
||||||
|
|
||||||
## 贡献者
|
|
||||||
|
|
||||||
💖 [感谢所有使 GoFrame 成为可能的贡献者](https://github.com/gogf/gf/graphs/contributors) 💖
|
|
||||||
|
|
||||||
<a href="https://github.com/gogf/gf/graphs/contributors">
|
|
||||||
<img src="https://goframe.org/img/contributors.svg?version=v2.9.5" alt="goframe contributors"/>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
## 许可证
|
|
||||||
|
|
||||||
`GoFrame` 采用 [MIT License](LICENSE) 许可,100% 免费和开源,永久保持。
|
|
||||||
@ -1,6 +1,5 @@
|
|||||||
.DEFAULT_GOAL := pack
|
|
||||||
|
|
||||||
pack: pack.template-single pack.template-mono pack.template-mono-app
|
pack: pack.template-single pack.template-mono
|
||||||
|
|
||||||
pack.template-single:
|
pack.template-single:
|
||||||
@rm -fr temp
|
@rm -fr temp
|
||||||
@ -16,21 +15,4 @@ pack.template-mono:
|
|||||||
@cd temp && git clone https://github.com/gogf/template-mono
|
@cd temp && git clone https://github.com/gogf/template-mono
|
||||||
@rm -fr temp/template-mono/.git
|
@rm -fr temp/template-mono/.git
|
||||||
@cd temp && gf pack template-mono ../internal/packed/template-mono.go -n=packed -y
|
@cd temp && gf pack template-mono ../internal/packed/template-mono.go -n=packed -y
|
||||||
@rm -fr temp
|
|
||||||
|
|
||||||
# Note:
|
|
||||||
# command `sed` only works on MacOS.
|
|
||||||
# use `grep -irl 'template-single' temp| xargs sed -i'' -e 's/template-single/template-mono-app/g'` on other platforms.
|
|
||||||
pack.template-mono-app:
|
|
||||||
@rm -fr temp
|
|
||||||
@mkdir temp || exit 0
|
|
||||||
@cd temp && git clone https://github.com/gogf/template-single
|
|
||||||
@cd temp && mv template-single template-mono-app
|
|
||||||
@rm -fr temp/template-mono-app/.git
|
|
||||||
@rm -fr temp/template-mono-app/.gitattributes
|
|
||||||
@rm -fr temp/template-mono-app/.gitignore
|
|
||||||
@rm -fr temp/template-mono-app/go.mod
|
|
||||||
@rm -fr temp/template-mono-app/go.sum
|
|
||||||
@grep -irl 'template-single' temp| xargs sed -i '' -e 's/template-single/template-mono-app/g'
|
|
||||||
@cd temp && gf pack template-mono-app ../internal/packed/template-mono-app.go -n=packed -y
|
|
||||||
@rm -fr temp
|
@rm -fr temp
|
||||||
@ -1,5 +1,3 @@
|
|||||||
English | [简体中文](README.zh_CN.MD)
|
|
||||||
|
|
||||||
# gf
|
# gf
|
||||||
|
|
||||||
`gf` is a powerful CLI tool for building [GoFrame](https://goframe.org) application with convenience.
|
`gf` is a powerful CLI tool for building [GoFrame](https://goframe.org) application with convenience.
|
||||||
@ -23,18 +21,18 @@ You can also install `gf` tool using pre-built binaries: <https://github.com/gog
|
|||||||
|
|
||||||
3. Database support
|
3. Database support
|
||||||
|
|
||||||
| DB | builtin support | remarks |
|
| DB | builtin support | remarks |
|
||||||
| :--------: | :-------------: | :-------------------------------------------------------------------------------------------------------------------------------------------------------------: |
|
|:----------:|:---------------:|:----------------------------------------------------------------------------------------------------------------------------------------------------------------:|
|
||||||
| mysql | yes | - |
|
| mysql | yes | - |
|
||||||
| mariadb | yes | - |
|
| mariadb | yes | - |
|
||||||
| tidb | yes | - |
|
| tidb | yes | - |
|
||||||
| mssql | yes | - |
|
| mssql | yes | - |
|
||||||
| oracle | yes | - |
|
| oracle | yes | - |
|
||||||
| pgsql | yes | - |
|
| pgsql | yes | - |
|
||||||
| sqlite | yes | - |
|
| sqlite | yes | - |
|
||||||
| sqlitecgo | no | to support sqlite database on 32bit architecture systems, manually add package import to the [source codes](./internal/cmd/cmd_gen_dao.go) and do the building. |
|
| sqlitecgo | no | to support sqlite database on 32bit architecture systems, manually add package import to the [source codes](./internal/cmd/cmd_gen_dao.go) and do the building. |
|
||||||
| clickhouse | yes | - |
|
| clickhouse | no | manually add package import to the [source codes](./internal/cmd/cmd_gen_dao.go) and do the building. |
|
||||||
| dm | no | manually add package import to the [source codes](./internal/cmd/cmd_gen_dao.go) and do the building. |
|
| dm | no | manually add package import to the [source codes](./internal/cmd/cmd_gen_dao.go) and do the building. |
|
||||||
|
|
||||||
## 2) Manually Install
|
## 2) Manually Install
|
||||||
|
|
||||||
@ -45,31 +43,30 @@ go install github.com/gogf/gf/cmd/gf/v2@v2.5.5 # certain version(should be >= v2
|
|||||||
|
|
||||||
## 2. Commands
|
## 2. Commands
|
||||||
|
|
||||||
```shell
|
```html
|
||||||
$ gf -h
|
$ gf
|
||||||
USAGE
|
USAGE
|
||||||
gf COMMAND [OPTION]
|
gf COMMAND [OPTION]
|
||||||
|
|
||||||
COMMAND
|
COMMAND
|
||||||
up upgrade GoFrame version/tool to latest one in current project
|
up upgrade GoFrame version/tool to latest one in current project
|
||||||
env show current Golang environment variables
|
env show current Golang environment variables
|
||||||
fix auto fixing codes after upgrading to new GoFrame version
|
fix auto fixing codes after upgrading to new GoFrame version
|
||||||
run running go codes with hot-compiled-like feature
|
run running go codes with hot-compiled-like feature
|
||||||
gen automatically generate go files for dao/do/entity/pb/pbentity
|
gen automatically generate go files for dao/do/entity/pb/pbentity
|
||||||
tpl template parsing and building commands
|
tpl template parsing and building commands
|
||||||
init create and initialize an empty GoFrame project
|
init create and initialize an empty GoFrame project
|
||||||
pack packing any file/directory to a resource file, or a go file
|
pack packing any file/directory to a resource file, or a go file
|
||||||
build cross-building go project for lots of platforms
|
build cross-building go project for lots of platforms
|
||||||
docker build docker image for current GoFrame project
|
docker build docker image for current GoFrame project
|
||||||
install install gf binary to system (might need root/admin permission)
|
install install gf binary to system (might need root/admin permission)
|
||||||
version show version information of current binary
|
version show version information of current binary
|
||||||
doc download https://pages.goframe.org/ to run locally
|
|
||||||
|
|
||||||
OPTION
|
OPTION
|
||||||
-y, --yes all yes for all command without prompt ask
|
-y, --yes all yes for all command without prompt ask
|
||||||
-v, --version show version information of current binary
|
-v, --version show version information of current binary
|
||||||
-d, --debug show internal detailed debugging information
|
-d, --debug show internal detailed debugging information
|
||||||
-h, --help more information about this command
|
-h, --help more information about this command
|
||||||
|
|
||||||
ADDITIONAL
|
ADDITIONAL
|
||||||
Use "gf COMMAND -h" for details about a command.
|
Use "gf COMMAND -h" for details about a command.
|
||||||
|
|||||||
@ -1,82 +0,0 @@
|
|||||||
[English](README.MD) | 简体中文
|
|
||||||
|
|
||||||
# gf
|
|
||||||
|
|
||||||
`gf` 是一个强大的 CLI 工具,用于便捷地构建 [GoFrame](https://goframe.org) 应用程序。
|
|
||||||
|
|
||||||
## 1. 安装
|
|
||||||
|
|
||||||
## 1) 预编译二进制文件
|
|
||||||
|
|
||||||
您也可以使用预构建的二进制文件安装 `gf` 工具:<https://github.com/gogf/gf/releases>
|
|
||||||
|
|
||||||
1. `Mac` & `Linux`
|
|
||||||
|
|
||||||
```shell
|
|
||||||
wget -O gf https://github.com/gogf/gf/releases/latest/download/gf_$(go env GOOS)_$(go env GOARCH) && chmod +x gf && ./gf install -y && rm ./gf
|
|
||||||
```
|
|
||||||
|
|
||||||
> 如果您使用 `zsh`,您可能需要通过命令 `alias gf=gf` 重命名别名以解决 `gf` 和 `git fetch` 之间的冲突。
|
|
||||||
|
|
||||||
2. `Windows`
|
|
||||||
手动下载,在命令行中执行,然后按照说明操作。
|
|
||||||
|
|
||||||
3. 数据库支持
|
|
||||||
|
|
||||||
| 数据库 | 内置支持 | 说明 |
|
|
||||||
| :--------: | :-------------: | :-------------------------------------------------------------------------------------------------------------------------------------------------------------: |
|
|
||||||
| mysql | 是 | - |
|
|
||||||
| mariadb | 是 | - |
|
|
||||||
| tidb | 是 | - |
|
|
||||||
| mssql | 是 | - |
|
|
||||||
| oracle | 是 | - |
|
|
||||||
| pgsql | 是 | - |
|
|
||||||
| sqlite | 是 | - |
|
|
||||||
| sqlitecgo | 否 | 要在 32 位架构系统上支持 sqlite 数据库,请手动向[源代码](./internal/cmd/cmd_gen_dao.go)添加包导入并进行构建。 |
|
|
||||||
| clickhouse | 是 | - |
|
|
||||||
| dm | 否 | 手动向[源代码](./internal/cmd/cmd_gen_dao.go)添加包导入并进行构建。 |
|
|
||||||
|
|
||||||
## 2) 手动安装
|
|
||||||
|
|
||||||
```shell
|
|
||||||
go install github.com/gogf/gf/cmd/gf/v2@latest # 最新版本
|
|
||||||
go install github.com/gogf/gf/cmd/gf/v2@v2.5.5 # 特定版本(应该 >= v2.5.5)
|
|
||||||
```
|
|
||||||
|
|
||||||
## 2. 命令
|
|
||||||
|
|
||||||
```shell
|
|
||||||
$ gf -h
|
|
||||||
用法
|
|
||||||
gf 命令 [选项]
|
|
||||||
|
|
||||||
命令
|
|
||||||
up 升级项目中的 GoFrame 版本/工具到最新版本
|
|
||||||
env 显示当前 Golang 环境变量
|
|
||||||
fix 升级到新 GoFrame 版本后自动修复代码
|
|
||||||
run 运行 go 代码,具有热编译功能
|
|
||||||
gen 自动生成 dao/do/entity/pb/pbentity 的 go 文件
|
|
||||||
tpl 模板解析和构建命令
|
|
||||||
init 创建并初始化一个空的 GoFrame 项目
|
|
||||||
pack 将任何文件/目录打包到资源文件或 go 文件
|
|
||||||
build 为多个平台交叉编译 go 项目
|
|
||||||
docker 为当前 GoFrame 项目构建 docker 镜像
|
|
||||||
install 将 gf 二进制文件安装到系统(可能需要 root/admin 权限)
|
|
||||||
version 显示当前二进制文件的版本信息
|
|
||||||
doc 下载 https://pages.goframe.org/ 本地运行
|
|
||||||
|
|
||||||
选项
|
|
||||||
-y, --yes 对所有命令都使用 yes,不再提示
|
|
||||||
-v, --version 显示当前二进制文件的版本信息
|
|
||||||
-d, --debug 显示内部详细的调试信息
|
|
||||||
-h, --help 显示此命令的更多信息
|
|
||||||
|
|
||||||
附加信息
|
|
||||||
使用 "gf 命令 -h" 获取有关命令的详细信息。
|
|
||||||
```
|
|
||||||
|
|
||||||
## 3. 常见问题
|
|
||||||
|
|
||||||
### 1). 命令 `gf run` 返回 `pipe: too many open files`
|
|
||||||
|
|
||||||
请使用 `ulimit -n 65535` 扩大系统配置以增加当前终端 shell 会话的最大打开文件数,然后再运行 `gf run`。
|
|
||||||
@ -4,29 +4,28 @@
|
|||||||
// If a copy of the MIT was not distributed with this file,
|
// If a copy of the MIT was not distributed with this file,
|
||||||
// You can obtain one at https://github.com/gogf/gf.
|
// You can obtain one at https://github.com/gogf/gf.
|
||||||
|
|
||||||
// Package gfcmd provides the management of CLI commands for `gf` tool.
|
|
||||||
package gfcmd
|
package gfcmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"runtime"
|
|
||||||
|
|
||||||
_ "github.com/gogf/gf/cmd/gf/v2/internal/packed"
|
_ "github.com/gogf/gf/cmd/gf/v2/internal/packed"
|
||||||
|
|
||||||
"github.com/gogf/gf/v2/errors/gcode"
|
"github.com/gogf/gf/v2/errors/gcode"
|
||||||
"github.com/gogf/gf/v2/errors/gerror"
|
"github.com/gogf/gf/v2/errors/gerror"
|
||||||
|
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/gogf/gf/cmd/gf/v2/internal/cmd"
|
||||||
|
"github.com/gogf/gf/cmd/gf/v2/internal/utility/allyes"
|
||||||
|
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
|
||||||
"github.com/gogf/gf/v2/frame/g"
|
"github.com/gogf/gf/v2/frame/g"
|
||||||
"github.com/gogf/gf/v2/os/gcfg"
|
"github.com/gogf/gf/v2/os/gcfg"
|
||||||
"github.com/gogf/gf/v2/os/gcmd"
|
"github.com/gogf/gf/v2/os/gcmd"
|
||||||
"github.com/gogf/gf/v2/os/gfile"
|
"github.com/gogf/gf/v2/os/gfile"
|
||||||
"github.com/gogf/gf/v2/text/gstr"
|
"github.com/gogf/gf/v2/text/gstr"
|
||||||
|
|
||||||
"github.com/gogf/gf/cmd/gf/v2/internal/cmd"
|
|
||||||
"github.com/gogf/gf/cmd/gf/v2/internal/utility/allyes"
|
|
||||||
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const cliFolderName = `hack`
|
const (
|
||||||
|
cliFolderName = `hack`
|
||||||
|
)
|
||||||
|
|
||||||
// Command manages the CLI command of `gf`.
|
// Command manages the CLI command of `gf`.
|
||||||
// This struct can be globally accessible and extended with custom struct.
|
// This struct can be globally accessible and extended with custom struct.
|
||||||
@ -73,7 +72,7 @@ func (c *Command) Run(ctx context.Context) {
|
|||||||
func GetCommand(ctx context.Context) (*Command, error) {
|
func GetCommand(ctx context.Context) (*Command, error) {
|
||||||
root, err := gcmd.NewFromObject(cmd.GF)
|
root, err := gcmd.NewFromObject(cmd.GF)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
panic(err)
|
||||||
}
|
}
|
||||||
err = root.AddObject(
|
err = root.AddObject(
|
||||||
cmd.Up,
|
cmd.Up,
|
||||||
@ -88,7 +87,6 @@ func GetCommand(ctx context.Context) (*Command, error) {
|
|||||||
cmd.Docker,
|
cmd.Docker,
|
||||||
cmd.Install,
|
cmd.Install,
|
||||||
cmd.Version,
|
cmd.Version,
|
||||||
cmd.Doc,
|
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -101,9 +99,6 @@ func GetCommand(ctx context.Context) (*Command, error) {
|
|||||||
|
|
||||||
// zsh alias "git fetch" conflicts checks.
|
// zsh alias "git fetch" conflicts checks.
|
||||||
func handleZshAlias() {
|
func handleZshAlias() {
|
||||||
if runtime.GOOS == "windows" {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if home, err := gfile.Home(); err == nil {
|
if home, err := gfile.Home(); err == nil {
|
||||||
zshPath := gfile.Join(home, ".zshrc")
|
zshPath := gfile.Join(home, ".zshrc")
|
||||||
if gfile.Exists(zshPath) {
|
if gfile.Exists(zshPath) {
|
||||||
|
|||||||
@ -1,66 +1,57 @@
|
|||||||
module github.com/gogf/gf/cmd/gf/v2
|
module github.com/gogf/gf/cmd/gf/v2
|
||||||
|
|
||||||
go 1.23.0
|
go 1.18
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/gogf/gf/contrib/drivers/clickhouse/v2 v2.9.6
|
github.com/gogf/gf/contrib/drivers/clickhouse/v2 v2.5.6
|
||||||
github.com/gogf/gf/contrib/drivers/mssql/v2 v2.9.6
|
github.com/gogf/gf/contrib/drivers/mssql/v2 v2.5.6
|
||||||
github.com/gogf/gf/contrib/drivers/mysql/v2 v2.9.6
|
github.com/gogf/gf/contrib/drivers/mysql/v2 v2.5.6
|
||||||
github.com/gogf/gf/contrib/drivers/oracle/v2 v2.9.6
|
github.com/gogf/gf/contrib/drivers/oracle/v2 v2.5.6
|
||||||
github.com/gogf/gf/contrib/drivers/pgsql/v2 v2.9.6
|
github.com/gogf/gf/contrib/drivers/pgsql/v2 v2.5.6
|
||||||
github.com/gogf/gf/contrib/drivers/sqlite/v2 v2.9.6
|
github.com/gogf/gf/contrib/drivers/sqlite/v2 v2.5.6
|
||||||
github.com/gogf/gf/v2 v2.9.6
|
github.com/gogf/gf/v2 v2.5.6
|
||||||
github.com/gogf/selfupdate v0.0.0-20231215043001-5c48c528462f
|
github.com/minio/selfupdate v0.6.0
|
||||||
github.com/olekukonko/tablewriter v1.1.0
|
github.com/olekukonko/tablewriter v0.0.5
|
||||||
github.com/schollz/progressbar/v3 v3.15.0
|
golang.org/x/mod v0.9.0
|
||||||
golang.org/x/mod v0.25.0
|
golang.org/x/tools v0.7.0
|
||||||
golang.org/x/tools v0.26.0
|
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
aead.dev/minisign v0.2.0 // indirect
|
aead.dev/minisign v0.2.0 // indirect
|
||||||
github.com/BurntSushi/toml v1.5.0 // indirect
|
github.com/BurntSushi/toml v1.2.0 // indirect
|
||||||
github.com/ClickHouse/clickhouse-go/v2 v2.0.15 // indirect
|
github.com/ClickHouse/clickhouse-go/v2 v2.0.15 // indirect
|
||||||
github.com/clbanning/mxj/v2 v2.7.0 // indirect
|
github.com/clbanning/mxj/v2 v2.7.0 // indirect
|
||||||
|
github.com/denisenkom/go-mssqldb v0.12.3 // indirect
|
||||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||||
github.com/emirpasic/gods/v2 v2.0.0-alpha // indirect
|
github.com/fatih/color v1.15.0 // indirect
|
||||||
github.com/fatih/color v1.18.0 // indirect
|
github.com/fsnotify/fsnotify v1.6.0 // indirect
|
||||||
github.com/fsnotify/fsnotify v1.9.0 // indirect
|
|
||||||
github.com/glebarez/go-sqlite v1.21.2 // indirect
|
github.com/glebarez/go-sqlite v1.21.2 // indirect
|
||||||
github.com/go-logr/logr v1.4.3 // indirect
|
github.com/go-logr/logr v1.2.4 // indirect
|
||||||
github.com/go-logr/stdr v1.2.2 // indirect
|
github.com/go-logr/stdr v1.2.2 // indirect
|
||||||
github.com/go-sql-driver/mysql v1.7.1 // indirect
|
github.com/go-sql-driver/mysql v1.7.1 // indirect
|
||||||
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 // indirect
|
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe // indirect
|
||||||
github.com/golang-sql/sqlexp v0.1.0 // indirect
|
github.com/golang-sql/sqlexp v0.1.0 // indirect
|
||||||
github.com/google/uuid v1.6.0 // indirect
|
github.com/google/uuid v1.3.0 // indirect
|
||||||
github.com/gorilla/websocket v1.5.3 // indirect
|
github.com/gorilla/websocket v1.5.0 // indirect
|
||||||
github.com/grokify/html-strip-tags-go v0.1.0 // indirect
|
github.com/grokify/html-strip-tags-go v0.0.1 // indirect
|
||||||
github.com/lib/pq v1.10.9 // indirect
|
github.com/lib/pq v1.10.9 // indirect
|
||||||
github.com/magiconair/properties v1.8.10 // indirect
|
github.com/magiconair/properties v1.8.6 // indirect
|
||||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
github.com/mattn/go-isatty v0.0.19 // indirect
|
||||||
github.com/mattn/go-runewidth v0.0.16 // indirect
|
github.com/mattn/go-runewidth v0.0.15 // indirect
|
||||||
github.com/microsoft/go-mssqldb v1.7.1 // indirect
|
|
||||||
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db // indirect
|
|
||||||
github.com/olekukonko/errors v1.1.0 // indirect
|
|
||||||
github.com/olekukonko/ll v0.0.9 // indirect
|
|
||||||
github.com/paulmach/orb v0.7.1 // indirect
|
github.com/paulmach/orb v0.7.1 // indirect
|
||||||
github.com/pierrec/lz4/v4 v4.1.14 // indirect
|
github.com/pierrec/lz4/v4 v4.1.14 // indirect
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
||||||
github.com/rivo/uniseg v0.4.7 // indirect
|
github.com/rivo/uniseg v0.4.4 // indirect
|
||||||
github.com/shopspring/decimal v1.3.1 // indirect
|
github.com/shopspring/decimal v1.3.1 // indirect
|
||||||
github.com/sijms/go-ora/v2 v2.7.10 // indirect
|
github.com/sijms/go-ora/v2 v2.7.10 // indirect
|
||||||
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
|
go.opentelemetry.io/otel v1.14.0 // indirect
|
||||||
go.opentelemetry.io/otel v1.38.0 // indirect
|
go.opentelemetry.io/otel/sdk v1.14.0 // indirect
|
||||||
go.opentelemetry.io/otel/metric v1.38.0 // indirect
|
go.opentelemetry.io/otel/trace v1.14.0 // indirect
|
||||||
go.opentelemetry.io/otel/sdk v1.38.0 // indirect
|
golang.org/x/crypto v0.14.0 // indirect
|
||||||
go.opentelemetry.io/otel/trace v1.38.0 // indirect
|
golang.org/x/net v0.17.0 // indirect
|
||||||
golang.org/x/crypto v0.38.0 // indirect
|
golang.org/x/sys v0.13.0 // indirect
|
||||||
golang.org/x/net v0.40.0 // indirect
|
golang.org/x/text v0.13.0 // indirect
|
||||||
golang.org/x/sync v0.14.0 // indirect
|
|
||||||
golang.org/x/sys v0.35.0 // indirect
|
|
||||||
golang.org/x/term v0.32.0 // indirect
|
|
||||||
golang.org/x/text v0.25.0 // indirect
|
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
modernc.org/libc v1.22.5 // indirect
|
modernc.org/libc v1.22.5 // indirect
|
||||||
modernc.org/mathutil v1.5.0 // indirect
|
modernc.org/mathutil v1.5.0 // indirect
|
||||||
|
|||||||
191
cmd/gf/go.sum
191
cmd/gf/go.sum
@ -1,19 +1,10 @@
|
|||||||
aead.dev/minisign v0.2.0 h1:kAWrq/hBRu4AARY6AlciO83xhNnW9UaC8YipS2uhLPk=
|
aead.dev/minisign v0.2.0 h1:kAWrq/hBRu4AARY6AlciO83xhNnW9UaC8YipS2uhLPk=
|
||||||
aead.dev/minisign v0.2.0/go.mod h1:zdq6LdSd9TbuSxchxwhpA9zEb9YXcVGoE8JakuiGaIQ=
|
aead.dev/minisign v0.2.0/go.mod h1:zdq6LdSd9TbuSxchxwhpA9zEb9YXcVGoE8JakuiGaIQ=
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.1 h1:lGlwhPtrX6EVml1hO0ivjkUxsSyl4dsiw9qcA1k/3IQ=
|
github.com/Azure/azure-sdk-for-go/sdk/azcore v0.19.0/go.mod h1:h6H6c8enJmmocHUbLiiGY6sx7f9i+X3m1CHdd5c6Rdw=
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.1/go.mod h1:RKUqNu35KJYcVG/fqTRqmuXJZYNhYkBrnC/hX7yGbTA=
|
github.com/Azure/azure-sdk-for-go/sdk/azidentity v0.11.0/go.mod h1:HcM1YX14R7CJcghJGOYCgdezslRSVzqwLf/q+4Y2r/0=
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.5.1 h1:sO0/P7g68FrryJzljemN+6GTssUXdANk6aJ7T1ZxnsQ=
|
github.com/Azure/azure-sdk-for-go/sdk/internal v0.7.0/go.mod h1:yqy467j36fJxcRV2TzfVZ1pCb5vxm4BtZPUdYWe/Xo8=
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.5.1/go.mod h1:h8hyGFDsU5HMivxiS2iYFZsgDbU9OnnJ163x5UGVKYo=
|
github.com/BurntSushi/toml v1.2.0 h1:Rt8g24XnyGTyglgET/PRUNlrUeu9F5L+7FilkXfZgs0=
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.1 h1:6oNBlSdi1QqM1PNW7FPA6xOGA5UNsXnkaYZz9vdPGhA=
|
github.com/BurntSushi/toml v1.2.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.1/go.mod h1:s4kgfzA0covAXNicZHDMN58jExvcng2mC/DepXiF1EI=
|
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys v1.0.1 h1:MyVTgWR8qd/Jw1Le0NZebGBUCLbtak3bJ3z1OlqZBpw=
|
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys v1.0.1/go.mod h1:GpPjLhVR9dnUoJMyHWSPy71xY9/lcmpzIPZXmF0FCVY=
|
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.0.0 h1:D3occbWoio4EBLkbkevetNMAVX197GkzbUMtqjGWn80=
|
|
||||||
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.0.0/go.mod h1:bTSOgj05NGRuHHhQwAdPnYr9TOdNmKlZTgGLL6nyAdI=
|
|
||||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.1 h1:DzHpqpoJVaCgOUdVHxE8QB52S6NiVdDQvGlny1qvPqA=
|
|
||||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.1/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI=
|
|
||||||
github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg=
|
|
||||||
github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
|
|
||||||
github.com/ClickHouse/clickhouse-go v1.5.4/go.mod h1:EaI/sW7Azgz9UATzd5ZdZHRUhHgv5+JMS9NSr2smCJI=
|
github.com/ClickHouse/clickhouse-go v1.5.4/go.mod h1:EaI/sW7Azgz9UATzd5ZdZHRUhHgv5+JMS9NSr2smCJI=
|
||||||
github.com/ClickHouse/clickhouse-go/v2 v2.0.15 h1:lLAZliqrZEygkxosLaW1qHyeTb4Ho7fVCZ0WKCpLocU=
|
github.com/ClickHouse/clickhouse-go/v2 v2.0.15 h1:lLAZliqrZEygkxosLaW1qHyeTb4Ho7fVCZ0WKCpLocU=
|
||||||
github.com/ClickHouse/clickhouse-go/v2 v2.0.15/go.mod h1:Z21o82zD8FFqefOQDg93c0XITlxGbTsWQuRm588Azkk=
|
github.com/ClickHouse/clickhouse-go/v2 v2.0.15/go.mod h1:Z21o82zD8FFqefOQDg93c0XITlxGbTsWQuRm588Azkk=
|
||||||
@ -25,20 +16,21 @@ github.com/cloudflare/golz4 v0.0.0-20150217214814-ef862a3cdc58/go.mod h1:EOBUe0h
|
|||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
github.com/denisenkom/go-mssqldb v0.12.3 h1:pBSGx9Tq67pBOTLmxNuirNTeB8Vjmf886Kx+8Y+8shw=
|
||||||
|
github.com/denisenkom/go-mssqldb v0.12.3/go.mod h1:k0mtMFOnU+AihqFxPMiF05rtiDrorD1Vrm1KEz5hxDo=
|
||||||
|
github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ=
|
||||||
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
||||||
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
||||||
github.com/emirpasic/gods/v2 v2.0.0-alpha h1:dwFlh8pBg1VMOXWGipNMRt8v96dKAIvBehtCt6OtunU=
|
github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs=
|
||||||
github.com/emirpasic/gods/v2 v2.0.0-alpha/go.mod h1:W0y4M2dtBB9U5z3YlghmpuUhiaZT2h6yoeE+C1sCp6A=
|
github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw=
|
||||||
github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=
|
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
|
||||||
github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU=
|
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
|
||||||
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
|
|
||||||
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
|
|
||||||
github.com/glebarez/go-sqlite v1.21.2 h1:3a6LFC4sKahUunAmynQKLZceZCOzUthkRkEAl9gAXWo=
|
github.com/glebarez/go-sqlite v1.21.2 h1:3a6LFC4sKahUunAmynQKLZceZCOzUthkRkEAl9gAXWo=
|
||||||
github.com/glebarez/go-sqlite v1.21.2/go.mod h1:sfxdZyhQjTM2Wry3gVYWaW072Ri1WMdWJi0k6+3382k=
|
github.com/glebarez/go-sqlite v1.21.2/go.mod h1:sfxdZyhQjTM2Wry3gVYWaW072Ri1WMdWJi0k6+3382k=
|
||||||
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||||
github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||||
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
|
github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
|
||||||
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||||
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||||
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||||
github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM=
|
github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM=
|
||||||
@ -46,99 +38,62 @@ github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiU
|
|||||||
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
||||||
github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI=
|
github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI=
|
||||||
github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
|
github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
|
||||||
github.com/gogf/gf/contrib/drivers/clickhouse/v2 v2.9.6 h1:rJzRmA5TGWMeKDebdDosYODoUrMUHqfA5pWO1MBC5b0=
|
|
||||||
github.com/gogf/gf/contrib/drivers/clickhouse/v2 v2.9.6/go.mod h1:u+bUsuftf8qpKpPZPdOFhzh3F5KQzo6Wqa9JFTCLFqg=
|
|
||||||
github.com/gogf/gf/contrib/drivers/mssql/v2 v2.9.6 h1:3QTlIbSdrVYvRMNUF6nckspA6Eh5Uy2NqwB3/auxIwk=
|
|
||||||
github.com/gogf/gf/contrib/drivers/mssql/v2 v2.9.6/go.mod h1:oMteYgkWImPpUVe1aqPKtZ8jX1dG3v60lS7IA87MwFQ=
|
|
||||||
github.com/gogf/gf/contrib/drivers/mysql/v2 v2.9.6 h1:BY1ThxMo0bTx2P18PuCe57ARmjHuEithSdob/CbH/rw=
|
|
||||||
github.com/gogf/gf/contrib/drivers/mysql/v2 v2.9.6/go.mod h1:v/jKO9JJdLctlPlnUSnnG0SNSEpElM51Qx3KoI5crkU=
|
|
||||||
github.com/gogf/gf/contrib/drivers/oracle/v2 v2.9.6 h1:12+sWI/hm1D4KxG+1FMZpfoU3PwtSLJ9KbLNa20roLg=
|
|
||||||
github.com/gogf/gf/contrib/drivers/oracle/v2 v2.9.6/go.mod h1:gjjhgxqjafnORK0F4Fa5W8TJlassw7svKy7RFj5GKss=
|
|
||||||
github.com/gogf/gf/contrib/drivers/pgsql/v2 v2.9.6 h1:LG/bTOJEpyNu6+IdREqFyi6J8LdZIeceeyxhuyV58LQ=
|
|
||||||
github.com/gogf/gf/contrib/drivers/pgsql/v2 v2.9.6/go.mod h1:Ekd5IgUGyBlbfqKD/69hkIL9vHF6F4V2FeEP3h/pH08=
|
|
||||||
github.com/gogf/gf/contrib/drivers/sqlite/v2 v2.9.6 h1:3QZvWIlz3dLjNELQU+5ZZZWuzEx9gsRFLU+qIKVUG6M=
|
|
||||||
github.com/gogf/gf/contrib/drivers/sqlite/v2 v2.9.6/go.mod h1:7EEAe8UYI5dLeuwCWN3HgC62OhjIYbkynaoavw1U/k4=
|
|
||||||
github.com/gogf/gf/v2 v2.9.6 h1:fQ6uPtS1Ra8qY+OuzPPZTlgksJ4eOXmTZ1/a2l3Idog=
|
|
||||||
github.com/gogf/gf/v2 v2.9.6/go.mod h1:Svl1N+E8G/QshU2DUbh/3J/AJauqCgUnxHurXWR4Qx0=
|
|
||||||
github.com/gogf/selfupdate v0.0.0-20231215043001-5c48c528462f h1:7xfXR/BhG3JDqO1s45n65Oyx9t4E/UqDOXep6jXdLCM=
|
|
||||||
github.com/gogf/selfupdate v0.0.0-20231215043001-5c48c528462f/go.mod h1:HnYoio6S7VaFJdryKcD/r9HgX+4QzYfr00XiXUo/xz0=
|
|
||||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||||
github.com/golang-jwt/jwt/v5 v5.2.0 h1:d/ix8ftRUorsN+5eMIlF4T6J8CAt9rch3My2winC1Jw=
|
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY=
|
||||||
github.com/golang-jwt/jwt/v5 v5.2.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
|
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
|
||||||
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 h1:au07oEsX2xN0ktxqI+Sida1w446QrXBRJ0nee3SNZlA=
|
|
||||||
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
|
|
||||||
github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A=
|
github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A=
|
||||||
github.com/golang-sql/sqlexp v0.1.0/go.mod h1:J4ad9Vo8ZCWQ2GMrC4UCQy1JpCbwU9m3EOqtpKwwwHI=
|
github.com/golang-sql/sqlexp v0.1.0/go.mod h1:J4ad9Vo8ZCWQ2GMrC4UCQy1JpCbwU9m3EOqtpKwwwHI=
|
||||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
|
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
|
||||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
|
||||||
github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ=
|
github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ=
|
||||||
github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo=
|
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
|
||||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
|
||||||
github.com/gorilla/handlers v1.4.2/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ=
|
github.com/gorilla/handlers v1.4.2/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ=
|
||||||
github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||||
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
|
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
|
||||||
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||||
github.com/grokify/html-strip-tags-go v0.1.0 h1:03UrQLjAny8xci+R+qjCce/MYnpNXCtgzltlQbOBae4=
|
github.com/grokify/html-strip-tags-go v0.0.1 h1:0fThFwLbW7P/kOiTBs03FsJSV9RM2M/Q/MOnCQxKMo0=
|
||||||
github.com/grokify/html-strip-tags-go v0.1.0/go.mod h1:ZdzgfHEzAfz9X6Xe5eBLVblWIxXfYSQ40S/VKrAOGpc=
|
github.com/grokify/html-strip-tags-go v0.0.1/go.mod h1:2Su6romC5/1VXOQMaWL2yb618ARB8iVo6/DR99A6d78=
|
||||||
github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks=
|
github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks=
|
||||||
github.com/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213/go.mod h1:vNUNkEQ1e29fT/6vq2aBdFsgNPmy8qMdSay1npru+Sw=
|
|
||||||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
|
||||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
|
||||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
|
||||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
|
||||||
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
|
|
||||||
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
|
|
||||||
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||||
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
|
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
|
||||||
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||||
github.com/magiconair/properties v1.8.10 h1:s31yESBquKXCV9a/ScB3ESkOjUYYv+X0rg8SYxI99mE=
|
github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo=
|
||||||
github.com/magiconair/properties v1.8.10/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
|
github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
|
||||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||||
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
|
||||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||||
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
|
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||||
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
|
||||||
|
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||||
github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
||||||
github.com/microsoft/go-mssqldb v1.7.1 h1:KU/g8aWeM3Hx7IMOFpiwYiUkU+9zeISb4+tx3ScVfsM=
|
github.com/minio/selfupdate v0.6.0 h1:i76PgT0K5xO9+hjzKcacQtO7+MjJ4JKA8Ak8XQ9DDwU=
|
||||||
github.com/microsoft/go-mssqldb v1.7.1/go.mod h1:kOvZKUdrhhFQmxLZqbwUV0rHkNkZpthMITIb2Ko1IoA=
|
github.com/minio/selfupdate v0.6.0/go.mod h1:bO02GTIPCMQFTEvE5h4DjYB58bCoZ35XLeBf0buTDdM=
|
||||||
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db h1:62I3jR2EmQ4l5rM/4FEfDWcRD+abF5XlKShorW5LRoQ=
|
|
||||||
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db/go.mod h1:l0dey0ia/Uv7NcFFVbCLtqEBQbrT4OCwCSKTEv6enCw=
|
|
||||||
github.com/mkevac/debugcharts v0.0.0-20191222103121-ae1c48aa8615/go.mod h1:Ad7oeElCZqA1Ufj0U9/liOF4BtVepxRcTvr2ey7zTvM=
|
github.com/mkevac/debugcharts v0.0.0-20191222103121-ae1c48aa8615/go.mod h1:Ad7oeElCZqA1Ufj0U9/liOF4BtVepxRcTvr2ey7zTvM=
|
||||||
github.com/olekukonko/errors v1.1.0 h1:RNuGIh15QdDenh+hNvKrJkmxxjV4hcS50Db478Ou5sM=
|
github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3PzxT8aQXRPkAt8xlV/e7d7w8GM5g0fa5F0D8=
|
||||||
github.com/olekukonko/errors v1.1.0/go.mod h1:ppzxA5jBKcO1vIpCXQ9ZqgDh8iwODz6OXIGKU8r5m4Y=
|
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
|
||||||
github.com/olekukonko/ll v0.0.9 h1:Y+1YqDfVkqMWuEQMclsF9HUR5+a82+dxJuL1HHSRpxI=
|
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
|
||||||
github.com/olekukonko/ll v0.0.9/go.mod h1:En+sEW0JNETl26+K8eZ6/W4UQ7CYSrrgg/EdIYT2H8g=
|
|
||||||
github.com/olekukonko/tablewriter v1.1.0 h1:N0LHrshF4T39KvI96fn6GT8HEjXRXYNDrDjKFDB7RIY=
|
|
||||||
github.com/olekukonko/tablewriter v1.1.0/go.mod h1:5c+EBPeSqvXnLLgkm9isDdzR3wjfBkHR9Nhfp3NWrzo=
|
|
||||||
github.com/paulmach/orb v0.7.1 h1:Zha++Z5OX/l168sqHK3k4z18LDvr+YAO/VjK0ReQ9rU=
|
github.com/paulmach/orb v0.7.1 h1:Zha++Z5OX/l168sqHK3k4z18LDvr+YAO/VjK0ReQ9rU=
|
||||||
github.com/paulmach/orb v0.7.1/go.mod h1:FWRlTgl88VI1RBx/MkrwWDRhQ96ctqMCh8boXhmqB/A=
|
github.com/paulmach/orb v0.7.1/go.mod h1:FWRlTgl88VI1RBx/MkrwWDRhQ96ctqMCh8boXhmqB/A=
|
||||||
github.com/paulmach/protoscan v0.2.1/go.mod h1:SpcSwydNLrxUGSDvXvO0P7g7AuhJ7lcKfDlhJCDw2gY=
|
github.com/paulmach/protoscan v0.2.1/go.mod h1:SpcSwydNLrxUGSDvXvO0P7g7AuhJ7lcKfDlhJCDw2gY=
|
||||||
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
|
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
|
||||||
github.com/pierrec/lz4/v4 v4.1.14 h1:+fL8AQEZtz/ijeNnpduH0bROTu0O3NZAlPjQxGn8LwE=
|
github.com/pierrec/lz4/v4 v4.1.14 h1:+fL8AQEZtz/ijeNnpduH0bROTu0O3NZAlPjQxGn8LwE=
|
||||||
github.com/pierrec/lz4/v4 v4.1.14/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
|
github.com/pierrec/lz4/v4 v4.1.14/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
|
||||||
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ=
|
github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4/go.mod h1:4OwLy04Bl9Ef3GJJCoec+30X3LQs/0/m4HFRt/2LUSA=
|
||||||
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU=
|
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||||
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
|
github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis=
|
||||||
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||||
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
|
|
||||||
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
|
|
||||||
github.com/schollz/progressbar/v3 v3.15.0 h1:cNZmcNiVyea6oofBTg80ZhVXxf3wG/JoAhqCCwopkQo=
|
|
||||||
github.com/schollz/progressbar/v3 v3.15.0/go.mod h1:ncBdc++eweU0dQoeZJ3loXoAc+bjaallHRIm8pVVeQM=
|
|
||||||
github.com/shirou/gopsutil v2.19.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
|
github.com/shirou/gopsutil v2.19.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
|
||||||
github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
|
github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
|
||||||
github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4/go.mod h1:qsXQc7+bwAM3Q1u/4XEfrquwF8Lw7D7y5cD8CuHnfIc=
|
github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4/go.mod h1:qsXQc7+bwAM3Q1u/4XEfrquwF8Lw7D7y5cD8CuHnfIc=
|
||||||
@ -149,91 +104,91 @@ github.com/sijms/go-ora/v2 v2.7.10/go.mod h1:EHxlY6x7y9HAsdfumurRfTd+v8NrEOTR3Xl
|
|||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
|
github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
|
||||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
|
||||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
|
||||||
github.com/tklauser/go-sysconf v0.3.10/go.mod h1:C8XykCvCb+Gn0oNCWPIlcb0RuglQTYaQ2hGm7jmxEFk=
|
github.com/tklauser/go-sysconf v0.3.10/go.mod h1:C8XykCvCb+Gn0oNCWPIlcb0RuglQTYaQ2hGm7jmxEFk=
|
||||||
github.com/tklauser/numcpus v0.4.0/go.mod h1:1+UI3pD8NW14VMwdgJNJ1ESk2UnwhAnz5hMwiKKqXCQ=
|
github.com/tklauser/numcpus v0.4.0/go.mod h1:1+UI3pD8NW14VMwdgJNJ1ESk2UnwhAnz5hMwiKKqXCQ=
|
||||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
|
github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
|
||||||
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
|
|
||||||
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
|
|
||||||
go.opentelemetry.io/otel v1.7.0/go.mod h1:5BdUoMIz5WEs0vt0CUEMtSSaTSHBBVwrhnz7+nrD5xk=
|
go.opentelemetry.io/otel v1.7.0/go.mod h1:5BdUoMIz5WEs0vt0CUEMtSSaTSHBBVwrhnz7+nrD5xk=
|
||||||
go.opentelemetry.io/otel v1.38.0 h1:RkfdswUDRimDg0m2Az18RKOsnI8UDzppJAtj01/Ymk8=
|
go.opentelemetry.io/otel v1.14.0 h1:/79Huy8wbf5DnIPhemGB+zEPVwnN6fuQybr/SRXa6hM=
|
||||||
go.opentelemetry.io/otel v1.38.0/go.mod h1:zcmtmQ1+YmQM9wrNsTGV/q/uyusom3P8RxwExxkZhjM=
|
go.opentelemetry.io/otel v1.14.0/go.mod h1:o4buv+dJzx8rohcUeRmWUZhqupFvzWis188WlggnNeU=
|
||||||
go.opentelemetry.io/otel/metric v1.38.0 h1:Kl6lzIYGAh5M159u9NgiRkmoMKjvbsKtYRwgfrA6WpA=
|
go.opentelemetry.io/otel/sdk v1.14.0 h1:PDCppFRDq8A1jL9v6KMI6dYesaq+DFcDZvjsoGvxGzY=
|
||||||
go.opentelemetry.io/otel/metric v1.38.0/go.mod h1:kB5n/QoRM8YwmUahxvI3bO34eVtQf2i4utNVLr9gEmI=
|
go.opentelemetry.io/otel/sdk v1.14.0/go.mod h1:bwIC5TjrNG6QDCHNWvW4HLHtUQ4I+VQDsnjhvyZCALM=
|
||||||
go.opentelemetry.io/otel/sdk v1.38.0 h1:l48sr5YbNf2hpCUj/FoGhW9yDkl+Ma+LrVl8qaM5b+E=
|
|
||||||
go.opentelemetry.io/otel/sdk v1.38.0/go.mod h1:ghmNdGlVemJI3+ZB5iDEuk4bWA3GkTpW+DOoZMYBVVg=
|
|
||||||
go.opentelemetry.io/otel/sdk/metric v1.38.0 h1:aSH66iL0aZqo//xXzQLYozmWrXxyFkBJ6qT5wthqPoM=
|
|
||||||
go.opentelemetry.io/otel/sdk/metric v1.38.0/go.mod h1:dg9PBnW9XdQ1Hd6ZnRz689CbtrUp0wMMs9iPcgT9EZA=
|
|
||||||
go.opentelemetry.io/otel/trace v1.7.0/go.mod h1:fzLSB9nqR2eXzxPXb2JW9IKE+ScyXA48yyE4TNvoHqU=
|
go.opentelemetry.io/otel/trace v1.7.0/go.mod h1:fzLSB9nqR2eXzxPXb2JW9IKE+ScyXA48yyE4TNvoHqU=
|
||||||
go.opentelemetry.io/otel/trace v1.38.0 h1:Fxk5bKrDZJUH+AMyyIXGcFAPah0oRcT+LuNtJrmcNLE=
|
go.opentelemetry.io/otel/trace v1.14.0 h1:wp2Mmvj41tDsyAJXiWDWpfNsOiIyd38fy85pyKcFq/M=
|
||||||
go.opentelemetry.io/otel/trace v1.38.0/go.mod h1:j1P9ivuFsTceSWe1oY+EeW3sc+Pp42sO++GHkg4wwhs=
|
go.opentelemetry.io/otel/trace v1.14.0/go.mod h1:8avnQLK+CG77yNLUae4ea2JDQ6iT+gozhnZjy/rw9G8=
|
||||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
|
||||||
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
|
golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||||
golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8=
|
golang.org/x/crypto v0.0.0-20211209193657-4570a0811e8b/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||||
golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw=
|
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||||
|
golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
|
||||||
|
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
|
||||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/mod v0.25.0 h1:n7a+ZbQKQA/Ysbyb0/6IbB1H/X41mKgbhfv7AfG/44w=
|
golang.org/x/mod v0.9.0 h1:KENHtAZL2y3NLMYZeHY9DW8HW8V+kQyJsY/V9JlKvCs=
|
||||||
golang.org/x/mod v0.25.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
|
golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||||
golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY=
|
golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds=
|
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
|
golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
|
||||||
|
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ=
|
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
|
||||||
golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191220220014-0732a990476f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191220220014-0732a990476f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210228012217-479acdf4ea46/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210228012217-479acdf4ea46/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220429233432-b5fbb4746d32/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220429233432-b5fbb4746d32/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
|
||||||
golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
|
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
|
||||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||||
golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg=
|
|
||||||
golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ=
|
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4=
|
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA=
|
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
|
||||||
|
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ=
|
golang.org/x/tools v0.7.0 h1:W4OVu8VVOaIO0yzWMNdepAulS7YfoS3Zabrm8DOXXU4=
|
||||||
golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0=
|
golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s=
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||||
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||||
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
|
||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
|
||||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
modernc.org/libc v1.22.5 h1:91BNch/e5B0uPbJFgqbxXuOnxBQjlS//icfQEGmvyjE=
|
modernc.org/libc v1.22.5 h1:91BNch/e5B0uPbJFgqbxXuOnxBQjlS//icfQEGmvyjE=
|
||||||
|
|||||||
@ -1,6 +1,8 @@
|
|||||||
go 1.23.0
|
go 1.18
|
||||||
|
|
||||||
use ./
|
use (
|
||||||
|
./
|
||||||
|
)
|
||||||
|
|
||||||
// =====================================================================================================
|
// =====================================================================================================
|
||||||
// NOTE:
|
// NOTE:
|
||||||
|
|||||||
@ -4,7 +4,6 @@
|
|||||||
// If a copy of the MIT was not distributed with this file,
|
// If a copy of the MIT was not distributed with this file,
|
||||||
// You can obtain one at https://github.com/gogf/gf.
|
// You can obtain one at https://github.com/gogf/gf.
|
||||||
|
|
||||||
// Package cmd provides the management of CLI commands for `gf` tool.
|
|
||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -20,8 +19,9 @@ import (
|
|||||||
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
|
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
|
||||||
)
|
)
|
||||||
|
|
||||||
// GF is the management object for `gf` command line tool.
|
var (
|
||||||
var GF = cGF{}
|
GF = cGF{}
|
||||||
|
)
|
||||||
|
|
||||||
type cGF struct {
|
type cGF struct {
|
||||||
g.Meta `name:"gf" ad:"{cGFAd}"`
|
g.Meta `name:"gf" ad:"{cGFAd}"`
|
||||||
@ -55,11 +55,10 @@ func (c cGF) Index(ctx context.Context, in cGFInput) (out *cGFOutput, err error)
|
|||||||
_, err = Version.Index(ctx, cVersionInput{})
|
_, err = Version.Index(ctx, cVersionInput{})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
answer := "n"
|
answer := "n"
|
||||||
// No argument or option, do installation checks.
|
// No argument or option, do installation checks.
|
||||||
if data, isInstalled := service.Install.IsInstalled(); !isInstalled {
|
if data, isInstalled := service.Install.IsInstalled(); !isInstalled {
|
||||||
mlog.Print("hi, it seems it's the first time you installing gf cli.")
|
mlog.Print("hi, it seams it's the first time you installing gf cli.")
|
||||||
answer = gcmd.Scanf("do you want to install gf(%s) binary to your system? [y/n]: ", gf.VERSION)
|
answer = gcmd.Scanf("do you want to install gf(%s) binary to your system? [y/n]: ", gf.VERSION)
|
||||||
} else if !data.IsSelf {
|
} else if !data.IsSelf {
|
||||||
mlog.Print("hi, you have installed gf cli.")
|
mlog.Print("hi, you have installed gf cli.")
|
||||||
@ -72,7 +71,6 @@ func (c cGF) Index(ctx context.Context, in cGFInput) (out *cGFOutput, err error)
|
|||||||
gcmd.Scan("press `Enter` to exit...")
|
gcmd.Scan("press `Enter` to exit...")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Print help content.
|
// Print help content.
|
||||||
gcmd.CommandFromCtx(ctx).Print()
|
gcmd.CommandFromCtx(ctx).Print()
|
||||||
return
|
return
|
||||||
|
|||||||
@ -30,10 +30,12 @@ import (
|
|||||||
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
|
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
|
||||||
)
|
)
|
||||||
|
|
||||||
var Build = cBuild{
|
var (
|
||||||
nodeNameInConfigFile: "gfcli.build",
|
Build = cBuild{
|
||||||
packedGoFileName: "internal/packed/build_pack_data.go",
|
nodeNameInConfigFile: "gfcli.build",
|
||||||
}
|
packedGoFileName: "internal/packed/build_pack_data.go",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
type cBuild struct {
|
type cBuild struct {
|
||||||
g.Meta `name:"build" brief:"{cBuildBrief}" dc:"{cBuildDc}" eg:"{cBuildEg}" ad:"{cBuildAd}"`
|
g.Meta `name:"build" brief:"{cBuildBrief}" dc:"{cBuildDc}" eg:"{cBuildEg}" ad:"{cBuildAd}"`
|
||||||
@ -42,9 +44,8 @@ type cBuild struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
cBuildDefaultFile = "main.go"
|
cBuildBrief = `cross-building go project for lots of platforms`
|
||||||
cBuildBrief = `cross-building go project for lots of platforms`
|
cBuildEg = `
|
||||||
cBuildEg = `
|
|
||||||
gf build main.go
|
gf build main.go
|
||||||
gf build main.go --ps public,template
|
gf build main.go --ps public,template
|
||||||
gf build main.go --cgo
|
gf build main.go --cgo
|
||||||
@ -63,67 +64,45 @@ It provides much more features for building binary:
|
|||||||
`
|
`
|
||||||
cBuildAd = `
|
cBuildAd = `
|
||||||
PLATFORMS
|
PLATFORMS
|
||||||
aix ppc64
|
|
||||||
android 386,amd64,arm,arm64
|
|
||||||
darwin amd64,arm64
|
darwin amd64,arm64
|
||||||
dragonfly amd64
|
|
||||||
freebsd 386,amd64,arm
|
freebsd 386,amd64,arm
|
||||||
illumos amd64
|
linux 386,amd64,arm,arm64,ppc64,ppc64le,mips,mipsle,mips64,mips64le
|
||||||
ios arm64
|
|
||||||
js wasm
|
|
||||||
linux 386,amd64,arm,arm64,loong64,mips,mipsle,mips64,mips64le,ppc64,ppc64le,riscv64,s390x
|
|
||||||
netbsd 386,amd64,arm
|
netbsd 386,amd64,arm
|
||||||
openbsd 386,amd64,arm,arm64
|
openbsd 386,amd64,arm
|
||||||
plan9 386,amd64,arm
|
windows 386,amd64
|
||||||
solaris amd64
|
|
||||||
wasip1 wasm
|
|
||||||
windows 386,amd64,arm,arm64
|
|
||||||
`
|
`
|
||||||
// https://golang.google.cn/doc/install/source
|
// https://golang.google.cn/doc/install/source
|
||||||
cBuildPlatforms = `
|
cBuildPlatforms = `
|
||||||
aix ppc64
|
|
||||||
android 386
|
|
||||||
android amd64
|
|
||||||
android arm
|
|
||||||
android arm64
|
|
||||||
darwin amd64
|
darwin amd64
|
||||||
darwin arm64
|
darwin arm64
|
||||||
dragonfly amd64
|
ios amd64
|
||||||
|
ios arm64
|
||||||
freebsd 386
|
freebsd 386
|
||||||
freebsd amd64
|
freebsd amd64
|
||||||
freebsd arm
|
freebsd arm
|
||||||
illumos amd64
|
|
||||||
ios arm64
|
|
||||||
js wasm
|
|
||||||
linux 386
|
linux 386
|
||||||
linux amd64
|
linux amd64
|
||||||
linux arm
|
linux arm
|
||||||
linux arm64
|
linux arm64
|
||||||
linux loong64
|
linux ppc64
|
||||||
|
linux ppc64le
|
||||||
linux mips
|
linux mips
|
||||||
linux mipsle
|
linux mipsle
|
||||||
linux mips64
|
linux mips64
|
||||||
linux mips64le
|
linux mips64le
|
||||||
linux ppc64
|
|
||||||
linux ppc64le
|
|
||||||
linux riscv64
|
|
||||||
linux s390x
|
|
||||||
netbsd 386
|
netbsd 386
|
||||||
netbsd amd64
|
netbsd amd64
|
||||||
netbsd arm
|
netbsd arm
|
||||||
openbsd 386
|
openbsd 386
|
||||||
openbsd amd64
|
openbsd amd64
|
||||||
openbsd arm
|
openbsd arm
|
||||||
openbsd arm64
|
|
||||||
plan9 386
|
|
||||||
plan9 amd64
|
|
||||||
plan9 arm
|
|
||||||
solaris amd64
|
|
||||||
wasip1 wasm
|
|
||||||
windows 386
|
windows 386
|
||||||
windows amd64
|
windows amd64
|
||||||
windows arm
|
android arm
|
||||||
windows arm64
|
dragonfly amd64
|
||||||
|
plan9 386
|
||||||
|
plan9 amd64
|
||||||
|
solaris amd64
|
||||||
`
|
`
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -144,7 +123,7 @@ type cBuildInput struct {
|
|||||||
Arch string `short:"a" name:"arch" brief:"output binary architecture, multiple arch separated with ','"`
|
Arch string `short:"a" name:"arch" brief:"output binary architecture, multiple arch separated with ','"`
|
||||||
System string `short:"s" name:"system" brief:"output binary system, multiple os separated with ','"`
|
System string `short:"s" name:"system" brief:"output binary system, multiple os separated with ','"`
|
||||||
Output string `short:"o" name:"output" brief:"output binary path, used when building single binary file"`
|
Output string `short:"o" name:"output" brief:"output binary path, used when building single binary file"`
|
||||||
Path string `short:"p" name:"path" brief:"output binary directory path, default is '.'" d:"."`
|
Path string `short:"p" name:"path" brief:"output binary directory path, default is './temp'" d:"./temp"`
|
||||||
Extra string `short:"e" name:"extra" brief:"extra custom \"go build\" options"`
|
Extra string `short:"e" name:"extra" brief:"extra custom \"go build\" options"`
|
||||||
Mod string `short:"m" name:"mod" brief:"like \"-mod\" option of \"go build\", use \"-m none\" to disable go module"`
|
Mod string `short:"m" name:"mod" brief:"like \"-mod\" option of \"go build\", use \"-m none\" to disable go module"`
|
||||||
Cgo bool `short:"c" name:"cgo" brief:"enable or disable cgo feature, it's disabled in default" orphan:"true"`
|
Cgo bool `short:"c" name:"cgo" brief:"enable or disable cgo feature, it's disabled in default" orphan:"true"`
|
||||||
@ -158,6 +137,11 @@ type cBuildInput struct {
|
|||||||
type cBuildOutput struct{}
|
type cBuildOutput struct{}
|
||||||
|
|
||||||
func (c cBuild) Index(ctx context.Context, in cBuildInput) (out *cBuildOutput, err error) {
|
func (c cBuild) Index(ctx context.Context, in cBuildInput) (out *cBuildOutput, err error) {
|
||||||
|
// print used go env
|
||||||
|
if in.DumpENV {
|
||||||
|
_, _ = Env.Index(ctx, cEnvInput{})
|
||||||
|
}
|
||||||
|
|
||||||
mlog.SetHeaderPrint(true)
|
mlog.SetHeaderPrint(true)
|
||||||
|
|
||||||
mlog.Debugf(`build command input: %+v`, in)
|
mlog.Debugf(`build command input: %+v`, in)
|
||||||
@ -168,15 +152,14 @@ func (c cBuild) Index(ctx context.Context, in cBuildInput) (out *cBuildOutput, e
|
|||||||
|
|
||||||
var (
|
var (
|
||||||
parser = gcmd.ParserFromCtx(ctx)
|
parser = gcmd.ParserFromCtx(ctx)
|
||||||
file = in.File
|
file = parser.GetArg(2).String()
|
||||||
)
|
)
|
||||||
if file == "" {
|
if len(file) < 1 {
|
||||||
file = parser.GetArg(2).String()
|
|
||||||
// Check and use the main.go file.
|
// Check and use the main.go file.
|
||||||
if gfile.Exists(cBuildDefaultFile) {
|
if gfile.Exists("main.go") {
|
||||||
file = cBuildDefaultFile
|
file = "main.go"
|
||||||
} else {
|
} else {
|
||||||
mlog.Fatal("build file path is empty or main.go not found in current working directory")
|
mlog.Fatal("build file path cannot be empty")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if in.Name == "" {
|
if in.Name == "" {
|
||||||
@ -232,7 +215,7 @@ func (c cBuild) Index(ctx context.Context, in cBuildInput) (out *cBuildOutput, e
|
|||||||
if !gfile.Exists(in.PackDst) {
|
if !gfile.Exists(in.PackDst) {
|
||||||
// Remove the go file that is automatically packed resource.
|
// Remove the go file that is automatically packed resource.
|
||||||
defer func() {
|
defer func() {
|
||||||
_ = gfile.RemoveFile(in.PackDst)
|
_ = gfile.Remove(in.PackDst)
|
||||||
mlog.Printf(`remove the automatically generated resource go file: %s`, in.PackDst)
|
mlog.Printf(`remove the automatically generated resource go file: %s`, in.PackDst)
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
@ -256,11 +239,13 @@ func (c cBuild) Index(ctx context.Context, in cBuildInput) (out *cBuildOutput, e
|
|||||||
} else {
|
} else {
|
||||||
genv.MustSet("CGO_ENABLED", "0")
|
genv.MustSet("CGO_ENABLED", "0")
|
||||||
}
|
}
|
||||||
// print used go env
|
var (
|
||||||
if in.DumpENV {
|
cmd = ""
|
||||||
_, _ = Env.Index(ctx, cEnvInput{})
|
ext = ""
|
||||||
}
|
)
|
||||||
for system, item := range platformMap {
|
for system, item := range platformMap {
|
||||||
|
cmd = ""
|
||||||
|
ext = ""
|
||||||
if len(customSystems) > 0 && customSystems[0] != "all" && !gstr.InArray(customSystems, system) {
|
if len(customSystems) > 0 && customSystems[0] != "all" && !gstr.InArray(customSystems, system) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -269,26 +254,45 @@ func (c cBuild) Index(ctx context.Context, in cBuildInput) (out *cBuildOutput, e
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if len(customSystems) == 0 && len(customArches) == 0 {
|
if len(customSystems) == 0 && len(customArches) == 0 {
|
||||||
|
if runtime.GOOS == "windows" {
|
||||||
|
ext = ".exe"
|
||||||
|
}
|
||||||
// Single binary building, output the binary to current working folder.
|
// Single binary building, output the binary to current working folder.
|
||||||
// For example:
|
output := ""
|
||||||
// `gf build`
|
if len(in.Output) > 0 {
|
||||||
// `gf build -o main.exe`
|
output = "-o " + in.Output + ext
|
||||||
c.doBinaryBuild(
|
} else {
|
||||||
ctx, file,
|
output = "-o " + in.Name + ext
|
||||||
in.Output, in.Path,
|
}
|
||||||
runtime.GOOS, runtime.GOARCH, in.Name, ldFlags, in.Extra,
|
cmd = fmt.Sprintf(`go build %s -ldflags "%s" %s %s`, output, ldFlags, in.Extra, file)
|
||||||
in.ExitWhenError,
|
|
||||||
true,
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
c.doBinaryBuild(
|
// Cross-building, output the compiled binary to specified path.
|
||||||
ctx, file,
|
if system == "windows" {
|
||||||
in.Output, in.Path,
|
ext = ".exe"
|
||||||
system, arch, in.Name, ldFlags, in.Extra,
|
}
|
||||||
in.ExitWhenError,
|
genv.MustSet("GOOS", system)
|
||||||
false,
|
genv.MustSet("GOARCH", arch)
|
||||||
|
cmd = fmt.Sprintf(
|
||||||
|
`go build -o %s/%s/%s%s -ldflags "%s" %s%s`,
|
||||||
|
in.Path, system+"_"+arch, in.Name, ext, ldFlags, in.Extra, file,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
mlog.Debug(cmd)
|
||||||
|
// It's not necessary printing the complete command string.
|
||||||
|
cmdShow, _ := gregex.ReplaceString(`\s+(-ldflags ".+?")\s+`, " ", cmd)
|
||||||
|
mlog.Print(cmdShow)
|
||||||
|
if result, err := gproc.ShellExec(ctx, cmd); err != nil {
|
||||||
|
mlog.Printf(
|
||||||
|
"failed to build, os:%s, arch:%s, error:\n%s\n\n%s\n",
|
||||||
|
system, arch, gstr.Trim(result),
|
||||||
|
`you may use command option "--debug" to enable debug info and check the details`,
|
||||||
|
)
|
||||||
|
if in.ExitWhenError {
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
mlog.Debug(gstr.Trim(result))
|
||||||
|
}
|
||||||
// single binary building.
|
// single binary building.
|
||||||
if len(customSystems) == 0 && len(customArches) == 0 {
|
if len(customSystems) == 0 && len(customArches) == 0 {
|
||||||
goto buildDone
|
goto buildDone
|
||||||
@ -301,68 +305,6 @@ buildDone:
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c cBuild) doBinaryBuild(
|
|
||||||
ctx context.Context,
|
|
||||||
filePath string,
|
|
||||||
outputPath, dirPath string,
|
|
||||||
system, arch, name, ldFlags, extra string,
|
|
||||||
exitWhenError bool,
|
|
||||||
singleBuild bool,
|
|
||||||
) {
|
|
||||||
var (
|
|
||||||
cmd string
|
|
||||||
ext string
|
|
||||||
)
|
|
||||||
// Cross-building, output the compiled binary to specified path.
|
|
||||||
if system == "windows" {
|
|
||||||
ext = ".exe"
|
|
||||||
}
|
|
||||||
genv.MustSet("GOOS", system)
|
|
||||||
genv.MustSet("GOARCH", arch)
|
|
||||||
|
|
||||||
if outputPath != "" {
|
|
||||||
outputPath = "-o " + outputPath
|
|
||||||
} else {
|
|
||||||
if dirPath == "" {
|
|
||||||
dirPath = "."
|
|
||||||
} else {
|
|
||||||
dirPath = gstr.TrimRight(dirPath, "/")
|
|
||||||
}
|
|
||||||
if singleBuild {
|
|
||||||
outputPath = fmt.Sprintf(
|
|
||||||
"-o %s/%s%s",
|
|
||||||
dirPath, name, ext,
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
outputPath = fmt.Sprintf(
|
|
||||||
"-o %s/%s/%s%s",
|
|
||||||
dirPath, system+"_"+arch, name, ext,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cmd = fmt.Sprintf(
|
|
||||||
`go build %s -ldflags "%s" %s%s`,
|
|
||||||
outputPath, ldFlags, extra, filePath,
|
|
||||||
)
|
|
||||||
mlog.Debug(fmt.Sprintf("build for GOOS=%s GOARCH=%s", system, arch))
|
|
||||||
mlog.Debug(cmd)
|
|
||||||
// It's not necessary printing the complete command string, filtering ldFlags.
|
|
||||||
cmdShow, _ := gregex.ReplaceString(`\s+(-ldflags ".+?")\s+`, " ", cmd)
|
|
||||||
mlog.Print(cmdShow)
|
|
||||||
if result, err := gproc.ShellExec(ctx, cmd); err != nil {
|
|
||||||
mlog.Printf(
|
|
||||||
"failed to build, os:%s, arch:%s, error:\n%s\n\n%s\n",
|
|
||||||
system, arch, gstr.Trim(result),
|
|
||||||
`you may use command option "--debug" to enable debug info and check the details`,
|
|
||||||
)
|
|
||||||
if exitWhenError {
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
mlog.Debug(gstr.Trim(result))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// getBuildInVarStr retrieves and returns the custom build-in variables in configuration
|
// getBuildInVarStr retrieves and returns the custom build-in variables in configuration
|
||||||
// file as json.
|
// file as json.
|
||||||
func (c cBuild) getBuildInVarStr(ctx context.Context, in cBuildInput) string {
|
func (c cBuild) getBuildInVarStr(ctx context.Context, in cBuildInput) string {
|
||||||
|
|||||||
@ -1,184 +0,0 @@
|
|||||||
// 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"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"net/http"
|
|
||||||
"os"
|
|
||||||
"path"
|
|
||||||
"path/filepath"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/gogf/gf/v2/encoding/gcompress"
|
|
||||||
"github.com/gogf/gf/v2/frame/g"
|
|
||||||
"github.com/gogf/gf/v2/os/gfile"
|
|
||||||
|
|
||||||
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
GitName = "gf-site"
|
|
||||||
BranchName = "gh-pages"
|
|
||||||
|
|
||||||
SiteFileName = GitName + "-" + BranchName
|
|
||||||
// DocURL is the download address of the document
|
|
||||||
DocURL = "https://github.com/gogf/" + GitName + "/archive/refs/heads/" + BranchName + ".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
|
|
||||||
}
|
|
||||||
|
|
||||||
http.Handle("/", http.FileServer(http.Dir(docs.DocDir)))
|
|
||||||
mlog.Printf("Access address http://127.0.0.1:%d in %s", in.Port, docs.DocDir)
|
|
||||||
err = http.ListenAndServe(fmt.Sprintf(":%d", in.Port), nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
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 := SiteFileName + ".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, SiteFileName)),
|
|
||||||
DocURL: in.Proxy + DocURL,
|
|
||||||
DocZipFile: filepath.FromSlash(path.Join(tempDir, fileName)),
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clean cleans the temporary directory
|
|
||||||
func (d *DocSetting) Clean() error {
|
|
||||||
if _, err := os.Stat(d.TempDir); err == nil {
|
|
||||||
err = gfile.RemoveAll(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.RemoveFile(d.DocZipFile)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
mlog.Print("Download and unzip successful")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
@ -11,8 +11,6 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/olekukonko/tablewriter"
|
"github.com/olekukonko/tablewriter"
|
||||||
"github.com/olekukonko/tablewriter/renderer"
|
|
||||||
"github.com/olekukonko/tablewriter/tw"
|
|
||||||
|
|
||||||
"github.com/gogf/gf/v2/frame/g"
|
"github.com/gogf/gf/v2/frame/g"
|
||||||
"github.com/gogf/gf/v2/os/gproc"
|
"github.com/gogf/gf/v2/os/gproc"
|
||||||
@ -63,23 +61,10 @@ func (c cEnv) Index(ctx context.Context, in cEnvInput) (out *cEnvOutput, err err
|
|||||||
}
|
}
|
||||||
array = append(array, []string{gstr.Trim(match[1]), gstr.Trim(match[2])})
|
array = append(array, []string{gstr.Trim(match[1]), gstr.Trim(match[2])})
|
||||||
}
|
}
|
||||||
table := tablewriter.NewTable(buffer,
|
tw := tablewriter.NewWriter(buffer)
|
||||||
tablewriter.WithRenderer(renderer.NewBlueprint(tw.Rendition{
|
tw.SetColumnAlignment([]int{tablewriter.ALIGN_LEFT, tablewriter.ALIGN_LEFT})
|
||||||
Settings: tw.Settings{
|
tw.AppendBulk(array)
|
||||||
Separators: tw.Separators{BetweenRows: tw.Off, BetweenColumns: tw.On},
|
tw.Render()
|
||||||
},
|
|
||||||
Symbols: tw.NewSymbols(tw.StyleASCII),
|
|
||||||
})),
|
|
||||||
tablewriter.WithConfig(tablewriter.Config{
|
|
||||||
Row: tw.CellConfig{
|
|
||||||
Formatting: tw.CellFormatting{AutoWrap: tw.WrapNone},
|
|
||||||
Alignment: tw.CellAlignment{PerColumn: []tw.Align{tw.AlignLeft, tw.AlignLeft}},
|
|
||||||
ColMaxWidths: tw.CellWidth{Global: 84},
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
table.Bulk(array)
|
|
||||||
table.Render()
|
|
||||||
mlog.Print(buffer.String())
|
mlog.Print(buffer.String())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,14 +9,14 @@ package cmd
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
|
"github.com/gogf/gf/v2/os/gproc"
|
||||||
|
"github.com/gogf/gf/v2/text/gregex"
|
||||||
|
|
||||||
|
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
|
||||||
"github.com/gogf/gf/v2/errors/gerror"
|
"github.com/gogf/gf/v2/errors/gerror"
|
||||||
"github.com/gogf/gf/v2/frame/g"
|
"github.com/gogf/gf/v2/frame/g"
|
||||||
"github.com/gogf/gf/v2/os/gfile"
|
"github.com/gogf/gf/v2/os/gfile"
|
||||||
"github.com/gogf/gf/v2/os/gproc"
|
|
||||||
"github.com/gogf/gf/v2/text/gregex"
|
|
||||||
"github.com/gogf/gf/v2/text/gstr"
|
"github.com/gogf/gf/v2/text/gstr"
|
||||||
|
|
||||||
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|||||||
@ -14,9 +14,6 @@ import (
|
|||||||
_ "github.com/gogf/gf/contrib/drivers/pgsql/v2"
|
_ "github.com/gogf/gf/contrib/drivers/pgsql/v2"
|
||||||
_ "github.com/gogf/gf/contrib/drivers/sqlite/v2"
|
_ "github.com/gogf/gf/contrib/drivers/sqlite/v2"
|
||||||
|
|
||||||
// do not add dm in cli pre-compilation,
|
|
||||||
// the dm driver does not support certain target platforms.
|
|
||||||
// _ "github.com/gogf/gf/contrib/drivers/dm/v2"
|
|
||||||
"github.com/gogf/gf/cmd/gf/v2/internal/cmd/gendao"
|
"github.com/gogf/gf/cmd/gf/v2/internal/cmd/gendao"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@ -7,25 +7,38 @@
|
|||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/gogf/gf/cmd/gf/v2/internal/cmd/gendao"
|
||||||
"github.com/gogf/gf/v2/database/gdb"
|
"github.com/gogf/gf/v2/database/gdb"
|
||||||
"github.com/gogf/gf/v2/os/gfile"
|
"github.com/gogf/gf/v2/os/gfile"
|
||||||
"github.com/gogf/gf/v2/test/gtest"
|
"github.com/gogf/gf/v2/test/gtest"
|
||||||
"github.com/gogf/gf/v2/text/gstr"
|
"github.com/gogf/gf/v2/text/gstr"
|
||||||
"github.com/gogf/gf/v2/util/guid"
|
"github.com/gogf/gf/v2/util/guid"
|
||||||
"github.com/gogf/gf/v2/util/gutil"
|
"github.com/gogf/gf/v2/util/gutil"
|
||||||
|
|
||||||
"github.com/gogf/gf/cmd/gf/v2/internal/cmd/gendao"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var ctx = context.Background()
|
||||||
|
|
||||||
|
func dropTableWithDb(db gdb.DB, table string) {
|
||||||
|
dropTableStmt := fmt.Sprintf("DROP TABLE IF EXISTS `%s`", table)
|
||||||
|
if _, err := db.Exec(ctx, dropTableStmt); err != nil {
|
||||||
|
gtest.Error(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func Test_Gen_Dao_Default(t *testing.T) {
|
func Test_Gen_Dao_Default(t *testing.T) {
|
||||||
|
link := "mysql:root:12345678@tcp(127.0.0.1:3306)/test?loc=Local&parseTime=true"
|
||||||
|
db, err := gdb.New(gdb.ConfigNode{
|
||||||
|
Link: link,
|
||||||
|
})
|
||||||
|
gtest.AssertNil(err)
|
||||||
|
|
||||||
gtest.C(t, func(t *gtest.T) {
|
gtest.C(t, func(t *gtest.T) {
|
||||||
var (
|
var (
|
||||||
err error
|
|
||||||
db = testDB
|
|
||||||
table = "table_user"
|
table = "table_user"
|
||||||
sqlContent = fmt.Sprintf(
|
sqlContent = fmt.Sprintf(
|
||||||
gtest.DataContent(`gendao`, `user.tpl.sql`),
|
gtest.DataContent(`gendao`, `user.tpl.sql`),
|
||||||
@ -69,9 +82,7 @@ func Test_Gen_Dao_Default(t *testing.T) {
|
|||||||
NoJsonTag: false,
|
NoJsonTag: false,
|
||||||
NoModelComment: false,
|
NoModelComment: false,
|
||||||
Clear: false,
|
Clear: false,
|
||||||
GenTable: false,
|
|
||||||
TypeMapping: nil,
|
TypeMapping: nil,
|
||||||
FieldMapping: nil,
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
err = gutil.FillStructWithDefault(&in)
|
err = gutil.FillStructWithDefault(&in)
|
||||||
@ -108,17 +119,21 @@ func Test_Gen_Dao_Default(t *testing.T) {
|
|||||||
filepath.FromSlash(testPath + "/model/do/table_user.go"),
|
filepath.FromSlash(testPath + "/model/do/table_user.go"),
|
||||||
filepath.FromSlash(testPath + "/model/entity/table_user.go"),
|
filepath.FromSlash(testPath + "/model/entity/table_user.go"),
|
||||||
}
|
}
|
||||||
for i := range files {
|
for i, _ := range files {
|
||||||
t.Assert(gfile.GetContents(files[i]), gfile.GetContents(expectFiles[i]))
|
t.Assert(gfile.GetContents(files[i]), gfile.GetContents(expectFiles[i]))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func Test_Gen_Dao_TypeMapping(t *testing.T) {
|
func Test_Gen_Dao_TypeMapping(t *testing.T) {
|
||||||
|
link := "mysql:root:12345678@tcp(127.0.0.1:3306)/test?loc=Local&parseTime=true"
|
||||||
|
db, err := gdb.New(gdb.ConfigNode{
|
||||||
|
Link: link,
|
||||||
|
})
|
||||||
|
gtest.AssertNil(err)
|
||||||
|
|
||||||
gtest.C(t, func(t *gtest.T) {
|
gtest.C(t, func(t *gtest.T) {
|
||||||
var (
|
var (
|
||||||
err error
|
|
||||||
db = testDB
|
|
||||||
table = "table_user"
|
table = "table_user"
|
||||||
sqlContent = fmt.Sprintf(
|
sqlContent = fmt.Sprintf(
|
||||||
gtest.DataContent(`gendao`, `user.tpl.sql`),
|
gtest.DataContent(`gendao`, `user.tpl.sql`),
|
||||||
@ -162,7 +177,6 @@ func Test_Gen_Dao_TypeMapping(t *testing.T) {
|
|||||||
NoJsonTag: false,
|
NoJsonTag: false,
|
||||||
NoModelComment: false,
|
NoModelComment: false,
|
||||||
Clear: false,
|
Clear: false,
|
||||||
GenTable: false,
|
|
||||||
TypeMapping: map[gendao.DBFieldTypeName]gendao.CustomAttributeType{
|
TypeMapping: map[gendao.DBFieldTypeName]gendao.CustomAttributeType{
|
||||||
"int": {
|
"int": {
|
||||||
Type: "int64",
|
Type: "int64",
|
||||||
@ -173,7 +187,6 @@ func Test_Gen_Dao_TypeMapping(t *testing.T) {
|
|||||||
Import: "github.com/shopspring/decimal",
|
Import: "github.com/shopspring/decimal",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
FieldMapping: nil,
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
err = gutil.FillStructWithDefault(&in)
|
err = gutil.FillStructWithDefault(&in)
|
||||||
@ -210,204 +223,7 @@ func Test_Gen_Dao_TypeMapping(t *testing.T) {
|
|||||||
filepath.FromSlash(testPath + "/model/do/table_user.go"),
|
filepath.FromSlash(testPath + "/model/do/table_user.go"),
|
||||||
filepath.FromSlash(testPath + "/model/entity/table_user.go"),
|
filepath.FromSlash(testPath + "/model/entity/table_user.go"),
|
||||||
}
|
}
|
||||||
for i := range files {
|
for i, _ := range files {
|
||||||
//_ = gfile.PutContents(expectFiles[i], gfile.GetContents(files[i]))
|
|
||||||
t.Assert(gfile.GetContents(files[i]), gfile.GetContents(expectFiles[i]))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_Gen_Dao_FieldMapping(t *testing.T) {
|
|
||||||
gtest.C(t, func(t *gtest.T) {
|
|
||||||
var (
|
|
||||||
err error
|
|
||||||
db = testDB
|
|
||||||
table = "table_user"
|
|
||||||
sqlContent = fmt.Sprintf(
|
|
||||||
gtest.DataContent(`gendao`, `user.tpl.sql`),
|
|
||||||
table,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
defer dropTableWithDb(db, table)
|
|
||||||
array := gstr.SplitAndTrim(sqlContent, ";")
|
|
||||||
for _, v := range array {
|
|
||||||
if _, err = db.Exec(ctx, v); err != nil {
|
|
||||||
t.AssertNil(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
defer dropTableWithDb(db, table)
|
|
||||||
|
|
||||||
var (
|
|
||||||
path = gfile.Temp(guid.S())
|
|
||||||
group = "test"
|
|
||||||
in = gendao.CGenDaoInput{
|
|
||||||
Path: path,
|
|
||||||
Link: link,
|
|
||||||
Tables: "",
|
|
||||||
TablesEx: "",
|
|
||||||
Group: group,
|
|
||||||
Prefix: "",
|
|
||||||
RemovePrefix: "",
|
|
||||||
JsonCase: "",
|
|
||||||
ImportPrefix: "",
|
|
||||||
DaoPath: "",
|
|
||||||
DoPath: "",
|
|
||||||
EntityPath: "",
|
|
||||||
TplDaoIndexPath: "",
|
|
||||||
TplDaoInternalPath: "",
|
|
||||||
TplDaoDoPath: "",
|
|
||||||
TplDaoEntityPath: "",
|
|
||||||
StdTime: false,
|
|
||||||
WithTime: false,
|
|
||||||
GJsonSupport: false,
|
|
||||||
OverwriteDao: false,
|
|
||||||
DescriptionTag: false,
|
|
||||||
NoJsonTag: false,
|
|
||||||
NoModelComment: false,
|
|
||||||
Clear: false,
|
|
||||||
GenTable: false,
|
|
||||||
TypeMapping: map[gendao.DBFieldTypeName]gendao.CustomAttributeType{
|
|
||||||
"int": {
|
|
||||||
Type: "int64",
|
|
||||||
Import: "",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
FieldMapping: map[gendao.DBTableFieldName]gendao.CustomAttributeType{
|
|
||||||
"table_user.score": {
|
|
||||||
Type: "decimal.Decimal",
|
|
||||||
Import: "github.com/shopspring/decimal",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
)
|
|
||||||
err = gutil.FillStructWithDefault(&in)
|
|
||||||
t.AssertNil(err)
|
|
||||||
|
|
||||||
err = gfile.Mkdir(path)
|
|
||||||
t.AssertNil(err)
|
|
||||||
|
|
||||||
// for go mod import path auto retrieve.
|
|
||||||
err = gfile.Copy(
|
|
||||||
gtest.DataPath("gendao", "go.mod.txt"),
|
|
||||||
gfile.Join(path, "go.mod"),
|
|
||||||
)
|
|
||||||
t.AssertNil(err)
|
|
||||||
|
|
||||||
_, err = gendao.CGenDao{}.Dao(ctx, in)
|
|
||||||
t.AssertNil(err)
|
|
||||||
defer gfile.Remove(path)
|
|
||||||
|
|
||||||
// files
|
|
||||||
files, err := gfile.ScanDir(path, "*.go", true)
|
|
||||||
t.AssertNil(err)
|
|
||||||
t.Assert(files, []string{
|
|
||||||
filepath.FromSlash(path + "/dao/internal/table_user.go"),
|
|
||||||
filepath.FromSlash(path + "/dao/table_user.go"),
|
|
||||||
filepath.FromSlash(path + "/model/do/table_user.go"),
|
|
||||||
filepath.FromSlash(path + "/model/entity/table_user.go"),
|
|
||||||
})
|
|
||||||
// content
|
|
||||||
testPath := gtest.DataPath("gendao", "generated_user_field_mapping")
|
|
||||||
expectFiles := []string{
|
|
||||||
filepath.FromSlash(testPath + "/dao/internal/table_user.go"),
|
|
||||||
filepath.FromSlash(testPath + "/dao/table_user.go"),
|
|
||||||
filepath.FromSlash(testPath + "/model/do/table_user.go"),
|
|
||||||
filepath.FromSlash(testPath + "/model/entity/table_user.go"),
|
|
||||||
}
|
|
||||||
for i := range files {
|
|
||||||
//_ = gfile.PutContents(expectFiles[i], gfile.GetContents(files[i]))
|
|
||||||
t.Assert(gfile.GetContents(files[i]), gfile.GetContents(expectFiles[i]))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func execSqlFile(db gdb.DB, filePath string, args ...any) error {
|
|
||||||
sqlContent := fmt.Sprintf(
|
|
||||||
gfile.GetContents(filePath),
|
|
||||||
args...,
|
|
||||||
)
|
|
||||||
array := gstr.SplitAndTrim(sqlContent, ";")
|
|
||||||
for _, v := range array {
|
|
||||||
if _, err := db.Exec(ctx, v); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_Gen_Dao_Sqlite3(t *testing.T) {
|
|
||||||
gtest.C(t, func(t *gtest.T) {
|
|
||||||
var (
|
|
||||||
err error
|
|
||||||
table = "table_user"
|
|
||||||
path = gfile.Temp(guid.S())
|
|
||||||
linkSqlite3 = fmt.Sprintf("sqlite::@file(%s/db.sqlite3)", path)
|
|
||||||
sqlContent = fmt.Sprintf(
|
|
||||||
gtest.DataContent(`gendao`, `sqlite3`, `user.sqlite3.sql`),
|
|
||||||
table,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
err = gfile.Mkdir(path)
|
|
||||||
t.AssertNil(err)
|
|
||||||
defer gfile.Remove(path)
|
|
||||||
|
|
||||||
dbSqlite3, err := gdb.New(gdb.ConfigNode{
|
|
||||||
Link: linkSqlite3,
|
|
||||||
})
|
|
||||||
t.AssertNil(err)
|
|
||||||
|
|
||||||
array := gstr.SplitAndTrim(sqlContent, ";")
|
|
||||||
for _, v := range array {
|
|
||||||
if v == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if _, err = dbSqlite3.Exec(ctx, v); err != nil {
|
|
||||||
t.AssertNil(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
group = "test"
|
|
||||||
in = gendao.CGenDaoInput{
|
|
||||||
Path: path,
|
|
||||||
Link: linkSqlite3,
|
|
||||||
Group: group,
|
|
||||||
Tables: table,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
err = gutil.FillStructWithDefault(&in)
|
|
||||||
t.AssertNil(err)
|
|
||||||
|
|
||||||
// for go mod import path auto retrieve.
|
|
||||||
err = gfile.Copy(
|
|
||||||
gtest.DataPath("gendao", "go.mod.txt"),
|
|
||||||
gfile.Join(path, "go.mod"),
|
|
||||||
)
|
|
||||||
t.AssertNil(err)
|
|
||||||
|
|
||||||
_, err = gendao.CGenDao{}.Dao(ctx, in)
|
|
||||||
t.AssertNil(err)
|
|
||||||
defer gfile.Remove(path)
|
|
||||||
|
|
||||||
// files
|
|
||||||
files, err := gfile.ScanDir(path, "*.go", true)
|
|
||||||
t.AssertNil(err)
|
|
||||||
t.Assert(files, []string{
|
|
||||||
filepath.FromSlash(path + "/dao/internal/table_user.go"),
|
|
||||||
filepath.FromSlash(path + "/dao/table_user.go"),
|
|
||||||
filepath.FromSlash(path + "/model/do/table_user.go"),
|
|
||||||
filepath.FromSlash(path + "/model/entity/table_user.go"),
|
|
||||||
})
|
|
||||||
// content
|
|
||||||
testPath := gtest.DataPath("gendao", "generated_user_sqlite3")
|
|
||||||
expectFiles := []string{
|
|
||||||
filepath.FromSlash(testPath + "/dao/internal/table_user.go"),
|
|
||||||
filepath.FromSlash(testPath + "/dao/table_user.go"),
|
|
||||||
filepath.FromSlash(testPath + "/model/do/table_user.go"),
|
|
||||||
filepath.FromSlash(testPath + "/model/entity/table_user.go"),
|
|
||||||
}
|
|
||||||
for i := range files {
|
|
||||||
//_ = gfile.PutContents(expectFiles[i], gfile.GetContents(files[i]))
|
|
||||||
t.Assert(gfile.GetContents(files[i]), gfile.GetContents(expectFiles[i]))
|
t.Assert(gfile.GetContents(files[i]), gfile.GetContents(expectFiles[i]))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -22,11 +22,9 @@ import (
|
|||||||
|
|
||||||
"github.com/gogf/gf/cmd/gf/v2/internal/utility/allyes"
|
"github.com/gogf/gf/cmd/gf/v2/internal/utility/allyes"
|
||||||
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
|
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
|
||||||
"github.com/gogf/gf/cmd/gf/v2/internal/utility/utils"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// Init .
|
|
||||||
Init = cInit{}
|
Init = cInit{}
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -35,15 +33,13 @@ type cInit struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
cInitRepoPrefix = `github.com/gogf/`
|
cInitRepoPrefix = `github.com/gogf/`
|
||||||
cInitMonoRepo = `template-mono`
|
cInitMonoRepo = `template-mono`
|
||||||
cInitMonoRepoApp = `template-mono-app`
|
cInitSingleRepo = `template-single`
|
||||||
cInitSingleRepo = `template-single`
|
cInitBrief = `create and initialize an empty GoFrame project`
|
||||||
cInitBrief = `create and initialize an empty GoFrame project`
|
cInitEg = `
|
||||||
cInitEg = `
|
|
||||||
gf init my-project
|
gf init my-project
|
||||||
gf init my-mono-repo -m
|
gf init my-mono-repo -m
|
||||||
gf init my-mono-repo -a
|
|
||||||
`
|
`
|
||||||
cInitNameBrief = `
|
cInitNameBrief = `
|
||||||
name for the project. It will create a folder with NAME in current directory.
|
name for the project. It will create a folder with NAME in current directory.
|
||||||
@ -64,18 +60,18 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type cInitInput struct {
|
type cInitInput struct {
|
||||||
g.Meta `name:"init"`
|
g.Meta `name:"init"`
|
||||||
Name string `name:"NAME" arg:"true" v:"required" brief:"{cInitNameBrief}"`
|
Name string `name:"NAME" arg:"true" v:"required" brief:"{cInitNameBrief}"`
|
||||||
Mono bool `name:"mono" short:"m" brief:"initialize a mono-repo instead a single-repo" orphan:"true"`
|
Mono bool `name:"mono" short:"m" brief:"initialize a mono-repo instead a single-repo" orphan:"true"`
|
||||||
MonoApp bool `name:"monoApp" short:"a" brief:"initialize a mono-repo-app instead a single-repo" orphan:"true"`
|
Update bool `name:"update" short:"u" brief:"update to the latest goframe version" orphan:"true"`
|
||||||
Update bool `name:"update" short:"u" brief:"update to the latest goframe version" orphan:"true"`
|
|
||||||
Module string `name:"module" short:"g" brief:"custom go module"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type cInitOutput struct{}
|
type cInitOutput struct{}
|
||||||
|
|
||||||
func (c cInit) Index(ctx context.Context, in cInitInput) (out *cInitOutput, err error) {
|
func (c cInit) Index(ctx context.Context, in cInitInput) (out *cInitOutput, err error) {
|
||||||
var overwrote = false
|
var (
|
||||||
|
overwrote = false
|
||||||
|
)
|
||||||
if !gfile.IsEmpty(in.Name) && !allyes.Check() {
|
if !gfile.IsEmpty(in.Name) && !allyes.Check() {
|
||||||
s := gcmd.Scanf(`the folder "%s" is not empty, files might be overwrote, continue? [y/n]: `, in.Name)
|
s := gcmd.Scanf(`the folder "%s" is not empty, files might be overwrote, continue? [y/n]: `, in.Name)
|
||||||
if strings.EqualFold(s, "n") {
|
if strings.EqualFold(s, "n") {
|
||||||
@ -90,15 +86,11 @@ func (c cInit) Index(ctx context.Context, in cInitInput) (out *cInitOutput, err
|
|||||||
templateRepoName string
|
templateRepoName string
|
||||||
gitignoreFile = in.Name + "/" + cInitGitignore
|
gitignoreFile = in.Name + "/" + cInitGitignore
|
||||||
)
|
)
|
||||||
|
|
||||||
if in.Mono {
|
if in.Mono {
|
||||||
templateRepoName = cInitMonoRepo
|
templateRepoName = cInitMonoRepo
|
||||||
} else if in.MonoApp {
|
|
||||||
templateRepoName = cInitMonoRepoApp
|
|
||||||
} else {
|
} else {
|
||||||
templateRepoName = cInitSingleRepo
|
templateRepoName = cInitSingleRepo
|
||||||
}
|
}
|
||||||
|
|
||||||
err = gres.Export(templateRepoName, in.Name, gres.ExportOption{
|
err = gres.Export(templateRepoName, in.Name, gres.ExportOption{
|
||||||
RemovePrefix: templateRepoName,
|
RemovePrefix: templateRepoName,
|
||||||
})
|
})
|
||||||
@ -109,12 +101,11 @@ func (c cInit) Index(ctx context.Context, in cInitInput) (out *cInitOutput, err
|
|||||||
// build ignoreFiles from the .gitignore file
|
// build ignoreFiles from the .gitignore file
|
||||||
ignoreFiles := make([]string, 0, 10)
|
ignoreFiles := make([]string, 0, 10)
|
||||||
ignoreFiles = append(ignoreFiles, cInitGitDir)
|
ignoreFiles = append(ignoreFiles, cInitGitDir)
|
||||||
// in.MonoApp is a mono-repo-app, it should ignore the .gitignore file
|
if overwrote {
|
||||||
if overwrote && !in.MonoApp {
|
|
||||||
err = gfile.ReadLines(gitignoreFile, func(line string) error {
|
err = gfile.ReadLines(gitignoreFile, func(line string) error {
|
||||||
// Add only hidden files or directories
|
// Add only hidden files or directories
|
||||||
// If other directories are added, it may cause the entire directory to be ignored
|
// If other directories are added, it may cause the entire directory to be ignored
|
||||||
// such as 'main' in the .gitignore file, but the path is ' D:\main\my-project '
|
// such as 'main' in the .gitignore file, but the path is 'D:\main\my-project'
|
||||||
if line != "" && strings.HasPrefix(line, ".") {
|
if line != "" && strings.HasPrefix(line, ".") {
|
||||||
ignoreFiles = append(ignoreFiles, line)
|
ignoreFiles = append(ignoreFiles, line)
|
||||||
}
|
}
|
||||||
@ -127,15 +118,6 @@ func (c cInit) Index(ctx context.Context, in cInitInput) (out *cInitOutput, err
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get template name and module name.
|
|
||||||
if in.Module == "" {
|
|
||||||
in.Module = gfile.Basename(gfile.RealPath(in.Name))
|
|
||||||
}
|
|
||||||
if in.MonoApp {
|
|
||||||
pwd := gfile.Pwd() + string(os.PathSeparator) + in.Name
|
|
||||||
in.Module = utils.GetImportPath(pwd)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Replace template name to project name.
|
// Replace template name to project name.
|
||||||
err = gfile.ReplaceDirFunc(func(path, content string) string {
|
err = gfile.ReplaceDirFunc(func(path, content string) string {
|
||||||
for _, ignoreFile := range ignoreFiles {
|
for _, ignoreFile := range ignoreFiles {
|
||||||
@ -143,7 +125,7 @@ func (c cInit) Index(ctx context.Context, in cInitInput) (out *cInitOutput, err
|
|||||||
return content
|
return content
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return gstr.Replace(gfile.GetContents(path), cInitRepoPrefix+templateRepoName, in.Module)
|
return gstr.Replace(gfile.GetContents(path), cInitRepoPrefix+templateRepoName, gfile.Basename(gfile.RealPath(in.Name)))
|
||||||
}, in.Name, "*", true)
|
}, in.Name, "*", true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
|
|||||||
@ -63,7 +63,7 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type cPackInput struct {
|
type cPackInput struct {
|
||||||
g.Meta `name:"pack" config:"gfcli.pack"`
|
g.Meta `name:"pack"`
|
||||||
Src string `name:"SRC" arg:"true" v:"required" brief:"{cPackSrcBrief}"`
|
Src string `name:"SRC" arg:"true" v:"required" brief:"{cPackSrcBrief}"`
|
||||||
Dst string `name:"DST" arg:"true" v:"required" brief:"{cPackDstBrief}"`
|
Dst string `name:"DST" arg:"true" v:"required" brief:"{cPackDstBrief}"`
|
||||||
Name string `name:"name" short:"n" brief:"{cPackNameBrief}"`
|
Name string `name:"name" short:"n" brief:"{cPackNameBrief}"`
|
||||||
|
|||||||
@ -9,11 +9,9 @@ package cmd
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/gogf/gf/v2/container/gtype"
|
"github.com/gogf/gf/v2/container/gtype"
|
||||||
"github.com/gogf/gf/v2/frame/g"
|
"github.com/gogf/gf/v2/frame/g"
|
||||||
@ -27,7 +25,9 @@ import (
|
|||||||
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
|
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
|
||||||
)
|
)
|
||||||
|
|
||||||
var Run = cRun{}
|
var (
|
||||||
|
Run = cRun{}
|
||||||
|
)
|
||||||
|
|
||||||
type cRun struct {
|
type cRun struct {
|
||||||
g.Meta `name:"run" usage:"{cRunUsage}" brief:"{cRunBrief}" eg:"{cRunEg}" dc:"{cRunDc}"`
|
g.Meta `name:"run" usage:"{cRunUsage}" brief:"{cRunBrief}" eg:"{cRunEg}" dc:"{cRunDc}"`
|
||||||
@ -55,13 +55,15 @@ 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.
|
which compiles and runs the go codes asynchronously when codes change.
|
||||||
`
|
`
|
||||||
cRunFileBrief = `building file path.`
|
cRunFileBrief = `building file path.`
|
||||||
cRunPathBrief = `output directory path for built binary file. it's "./" in default`
|
cRunPathBrief = `output directory path for built binary file. it's "manifest/output" in default`
|
||||||
cRunExtraBrief = `the same options as "go run"/"go build" except some options as follows defined`
|
cRunExtraBrief = `the same options as "go run"/"go build" except some options as follows defined`
|
||||||
cRunArgsBrief = `custom arguments for your process`
|
cRunArgsBrief = `custom arguments for your process`
|
||||||
cRunWatchPathsBrief = `watch additional paths for live reload, separated by ",". i.e. "manifest/config/*.yaml"`
|
cRunWatchPathsBrief = `watch additional paths for live reload, separated by ",". i.e. "manifest/config/*.yaml"`
|
||||||
)
|
)
|
||||||
|
|
||||||
var process *gproc.Process
|
var (
|
||||||
|
process *gproc.Process
|
||||||
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
gtag.Sets(g.MapStrStr{
|
gtag.Sets(g.MapStrStr{
|
||||||
@ -79,49 +81,32 @@ func init() {
|
|||||||
|
|
||||||
type (
|
type (
|
||||||
cRunInput struct {
|
cRunInput struct {
|
||||||
g.Meta `name:"run" config:"gfcli.run"`
|
g.Meta `name:"run"`
|
||||||
File string `name:"FILE" arg:"true" brief:"{cRunFileBrief}" v:"required"`
|
File string `name:"FILE" arg:"true" brief:"{cRunFileBrief}" v:"required"`
|
||||||
Path string `name:"path" short:"p" brief:"{cRunPathBrief}" d:"./"`
|
Path string `name:"path" short:"p" brief:"{cRunPathBrief}" d:"./"`
|
||||||
Extra string `name:"extra" short:"e" brief:"{cRunExtraBrief}"`
|
Extra string `name:"extra" short:"e" brief:"{cRunExtraBrief}"`
|
||||||
Args string `name:"args" short:"a" brief:"{cRunArgsBrief}"`
|
Args string `name:"args" short:"a" brief:"{cRunArgsBrief}"`
|
||||||
WatchPaths []string `name:"watchPaths" short:"w" brief:"{cRunWatchPathsBrief}"`
|
WatchPaths string `name:"watchPaths" short:"w" brief:"{cRunWatchPathsBrief}"`
|
||||||
}
|
}
|
||||||
cRunOutput struct{}
|
cRunOutput struct{}
|
||||||
)
|
)
|
||||||
|
|
||||||
func (c cRun) Index(ctx context.Context, in cRunInput) (out *cRunOutput, err error) {
|
func (c cRun) Index(ctx context.Context, in cRunInput) (out *cRunOutput, err error) {
|
||||||
if !gfile.Exists(in.File) {
|
|
||||||
mlog.Fatalf(`given file "%s" not found`, in.File)
|
|
||||||
}
|
|
||||||
if !gfile.IsFile(in.File) {
|
|
||||||
mlog.Fatalf(`given "%s" is not a file`, in.File)
|
|
||||||
}
|
|
||||||
// Necessary check.
|
// Necessary check.
|
||||||
if gproc.SearchBinary("go") == "" {
|
if gproc.SearchBinary("go") == "" {
|
||||||
mlog.Fatalf(`command "go" not found in your environment, please install golang first to proceed this command`)
|
mlog.Fatalf(`command "go" not found in your environment, please install golang first to proceed this command`)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(in.WatchPaths) == 1 {
|
|
||||||
in.WatchPaths = strings.Split(in.WatchPaths[0], ",")
|
|
||||||
mlog.Printf("watchPaths: %v", in.WatchPaths)
|
|
||||||
}
|
|
||||||
|
|
||||||
app := &cRunApp{
|
app := &cRunApp{
|
||||||
File: in.File,
|
File: in.File,
|
||||||
Path: filepath.FromSlash(in.Path),
|
Path: in.Path,
|
||||||
Options: in.Extra,
|
Options: in.Extra,
|
||||||
Args: in.Args,
|
Args: in.Args,
|
||||||
WatchPaths: in.WatchPaths,
|
WatchPaths: strings.Split(in.WatchPaths, ","),
|
||||||
}
|
}
|
||||||
dirty := gtype.NewBool()
|
dirty := gtype.NewBool()
|
||||||
|
_, err = gfsnotify.Add(gfile.RealPath("."), func(event *gfsnotify.Event) {
|
||||||
outputPath := app.genOutputPath()
|
if gfile.ExtName(event.Path) != "go" && !matchWatchPaths(app.WatchPaths, event.Path) {
|
||||||
callbackFunc := func(event *gfsnotify.Event) {
|
|
||||||
if !event.IsWrite() && !event.IsCreate() && !event.IsRemove() && !event.IsRename() {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if gfile.ExtName(event.Path) != "go" {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -134,39 +119,30 @@ func (c cRun) Index(ctx context.Context, in cRunInput) (out *cRunOutput, err err
|
|||||||
gtimer.SetTimeout(ctx, 1500*gtime.MS, func(ctx context.Context) {
|
gtimer.SetTimeout(ctx, 1500*gtime.MS, func(ctx context.Context) {
|
||||||
defer dirty.Set(false)
|
defer dirty.Set(false)
|
||||||
mlog.Printf(`watched file changes: %s`, event.String())
|
mlog.Printf(`watched file changes: %s`, event.String())
|
||||||
app.Run(ctx, outputPath)
|
app.Run(ctx)
|
||||||
})
|
})
|
||||||
}
|
|
||||||
|
|
||||||
if len(app.WatchPaths) > 0 {
|
|
||||||
for _, path := range app.WatchPaths {
|
|
||||||
_, err = gfsnotify.Add(gfile.RealPath(path), callbackFunc)
|
|
||||||
if err != nil {
|
|
||||||
mlog.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
_, err = gfsnotify.Add(gfile.RealPath("."), callbackFunc)
|
|
||||||
if err != nil {
|
|
||||||
mlog.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
go app.Run(ctx, outputPath)
|
|
||||||
|
|
||||||
gproc.AddSigHandlerShutdown(func(sig os.Signal) {
|
|
||||||
app.End(ctx, sig, outputPath)
|
|
||||||
os.Exit(0)
|
|
||||||
})
|
})
|
||||||
gproc.Listen()
|
if err != nil {
|
||||||
|
mlog.Fatal(err)
|
||||||
|
}
|
||||||
|
go app.Run(ctx)
|
||||||
select {}
|
select {}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (app *cRunApp) Run(ctx context.Context, outputPath string) {
|
func (app *cRunApp) Run(ctx context.Context) {
|
||||||
// Rebuild and run the codes.
|
// Rebuild and run the codes.
|
||||||
|
renamePath := ""
|
||||||
mlog.Printf("build: %s", app.File)
|
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.
|
// In case of `pipe: too many open files` error.
|
||||||
// Build the app.
|
// Build the app.
|
||||||
buildCommand := fmt.Sprintf(
|
buildCommand := fmt.Sprintf(
|
||||||
@ -204,65 +180,6 @@ func (app *cRunApp) Run(ctx context.Context, outputPath string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (app *cRunApp) End(ctx context.Context, sig os.Signal, outputPath string) {
|
|
||||||
// Delete the binary file.
|
|
||||||
// firstly, kill the process.
|
|
||||||
if process != nil {
|
|
||||||
if sig != nil && runtime.GOOS != "windows" {
|
|
||||||
if err := process.Signal(sig); err != nil {
|
|
||||||
mlog.Debugf("send signal to process error: %s", err.Error())
|
|
||||||
if err := process.Kill(); err != nil {
|
|
||||||
mlog.Debugf("kill process error: %s", err.Error())
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
waitCtx, cancel := context.WithTimeout(ctx, 30*time.Second)
|
|
||||||
defer cancel()
|
|
||||||
done := make(chan error, 1)
|
|
||||||
go func() {
|
|
||||||
select {
|
|
||||||
case <-waitCtx.Done():
|
|
||||||
done <- waitCtx.Err()
|
|
||||||
case done <- process.Wait():
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
err := <-done
|
|
||||||
if err != nil {
|
|
||||||
mlog.Debugf("process wait error: %s", err.Error())
|
|
||||||
if err := process.Kill(); err != nil {
|
|
||||||
mlog.Debugf("kill process error: %s", err.Error())
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
mlog.Debug("process exited gracefully")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if err := process.Kill(); err != nil {
|
|
||||||
mlog.Debugf("kill process error: %s", err.Error())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if err := gfile.RemoveFile(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 {
|
func matchWatchPaths(watchPaths []string, eventPath string) bool {
|
||||||
for _, path := range watchPaths {
|
for _, path := range watchPaths {
|
||||||
absPath, err := filepath.Abs(path)
|
absPath, err := filepath.Abs(path)
|
||||||
|
|||||||
@ -47,7 +47,7 @@ gf tpl parse -p ./template -v values.json -o ./template.parsed
|
|||||||
|
|
||||||
type (
|
type (
|
||||||
cTplParseInput struct {
|
cTplParseInput struct {
|
||||||
g.Meta `name:"parse" config:"gfcli.tpl.parse" brief:"{cTplParseBrief}" eg:"{cTplParseEg}"`
|
g.Meta `name:"parse" brief:"{cTplParseBrief}" eg:"{cTplParseEg}"`
|
||||||
Path string `name:"path" short:"p" brief:"template file or folder path" v:"required"`
|
Path string `name:"path" short:"p" brief:"template file or folder path" v:"required"`
|
||||||
Pattern string `name:"pattern" short:"n" brief:"template file pattern when path is a folder, default is:*" d:"*"`
|
Pattern string `name:"pattern" short:"n" brief:"template file pattern when path is a folder, default is:*" d:"*"`
|
||||||
Recursive bool `name:"recursive" short:"c" brief:"recursively parsing files if path is folder, default is:true" d:"true"`
|
Recursive bool `name:"recursive" short:"c" brief:"recursively parsing files if path is folder, default is:true" d:"true"`
|
||||||
|
|||||||
@ -11,18 +11,16 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
|
||||||
"github.com/gogf/selfupdate"
|
"github.com/minio/selfupdate"
|
||||||
|
|
||||||
|
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
|
||||||
|
"github.com/gogf/gf/cmd/gf/v2/internal/utility/utils"
|
||||||
"github.com/gogf/gf/v2/container/gset"
|
"github.com/gogf/gf/v2/container/gset"
|
||||||
"github.com/gogf/gf/v2/frame/g"
|
"github.com/gogf/gf/v2/frame/g"
|
||||||
"github.com/gogf/gf/v2/os/genv"
|
|
||||||
"github.com/gogf/gf/v2/os/gfile"
|
"github.com/gogf/gf/v2/os/gfile"
|
||||||
"github.com/gogf/gf/v2/os/gproc"
|
"github.com/gogf/gf/v2/os/gproc"
|
||||||
"github.com/gogf/gf/v2/text/gstr"
|
"github.com/gogf/gf/v2/text/gstr"
|
||||||
"github.com/gogf/gf/v2/util/gtag"
|
"github.com/gogf/gf/v2/util/gtag"
|
||||||
|
|
||||||
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
|
|
||||||
"github.com/gogf/gf/cmd/gf/v2/internal/utility/utils"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -40,11 +38,7 @@ gf up
|
|||||||
gf up -a
|
gf up -a
|
||||||
gf up -c
|
gf up -c
|
||||||
gf up -cf
|
gf up -cf
|
||||||
gf up -a -m=install
|
|
||||||
gf up -a -m=install -p=github.com/gogf/gf/cmd/gf/v2@latest
|
|
||||||
`
|
`
|
||||||
cliMethodHttpDownload = "http"
|
|
||||||
cliMethodGoInstall = "install"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@ -54,14 +48,10 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type cUpInput struct {
|
type cUpInput struct {
|
||||||
g.Meta `name:"up" config:"gfcli.up"`
|
g.Meta `name:"up" config:"gfcli.up"`
|
||||||
All bool `name:"all" short:"a" brief:"upgrade both version and cli, auto fix codes" orphan:"true"`
|
All bool `name:"all" short:"a" brief:"upgrade both version and cli, auto fix codes" orphan:"true"`
|
||||||
Cli bool `name:"cli" short:"c" brief:"also upgrade CLI tool" orphan:"true"`
|
Cli bool `name:"cli" short:"c" brief:"also upgrade CLI tool" orphan:"true"`
|
||||||
Fix bool `name:"fix" short:"f" brief:"auto fix codes(it only make sense if cli is to be upgraded)" orphan:"true"`
|
Fix bool `name:"fix" short:"f" brief:"auto fix codes(it only make sense if cli is to be upgraded)" orphan:"true"`
|
||||||
CliDownloadingMethod string `name:"cli-download-method" short:"m" brief:"cli upgrade method: http=download binary via HTTP GET, install=upgrade via go install" d:"http"`
|
|
||||||
// CliModulePath specifies the module path for CLI installation via go install.
|
|
||||||
// This is used when CliDownloadingMethod is set to "install".
|
|
||||||
CliModulePath string `name:"cli-module-path" short:"p" brief:"custom cli module path for upgrade CLI tool with go install method" d:"github.com/gogf/gf/cmd/gf/v2@latest"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type cUpOutput struct{}
|
type cUpOutput struct{}
|
||||||
@ -85,7 +75,7 @@ func (c cUp) Index(ctx context.Context, in cUpInput) (out *cUpOutput, err error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if in.Cli {
|
if in.Cli {
|
||||||
if err = c.doUpgradeCLI(ctx, in); err != nil {
|
if err = c.doUpgradeCLI(ctx); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -152,9 +142,8 @@ func (c cUp) doUpgradeVersion(ctx context.Context, in cUpInput) (out *doUpgradeV
|
|||||||
}
|
}
|
||||||
for _, pkg := range packages {
|
for _, pkg := range packages {
|
||||||
mlog.Printf(`upgrading "%s" from "%s" to "latest"`, pkg.Name, pkg.Version)
|
mlog.Printf(`upgrading "%s" from "%s" to "latest"`, pkg.Name, pkg.Version)
|
||||||
mlog.Printf(`running command: go get %s@latest`, pkg.Name)
|
// go get -u
|
||||||
// go get @latest
|
command := fmt.Sprintf(`cd %s && go get -u %s@latest`, dirPath, pkg.Name)
|
||||||
command := fmt.Sprintf(`cd %s && go get %s@latest`, dirPath, pkg.Name)
|
|
||||||
if err = gproc.ShellRun(ctx, command); err != nil {
|
if err = gproc.ShellRun(ctx, command); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -179,22 +168,8 @@ func (c cUp) doUpgradeVersion(ctx context.Context, in cUpInput) (out *doUpgradeV
|
|||||||
}
|
}
|
||||||
|
|
||||||
// doUpgradeCLI downloads the new version binary with process.
|
// doUpgradeCLI downloads the new version binary with process.
|
||||||
func (c cUp) doUpgradeCLI(ctx context.Context, in cUpInput) (err error) {
|
func (c cUp) doUpgradeCLI(ctx context.Context) (err error) {
|
||||||
mlog.Print(`start upgrading cli...`)
|
mlog.Print(`start upgrading cli...`)
|
||||||
fmt.Println(` cli upgrade method:`, in.CliDownloadingMethod)
|
|
||||||
switch in.CliDownloadingMethod {
|
|
||||||
case cliMethodHttpDownload:
|
|
||||||
return c.doUpgradeCLIWithHttpDownload(ctx)
|
|
||||||
case cliMethodGoInstall:
|
|
||||||
return c.doUpgradeCLIWithGoInstall(ctx, in)
|
|
||||||
default:
|
|
||||||
mlog.Fatalf(`invalid cli upgrade method: "%s", please use "http" or "install"`, in.CliDownloadingMethod)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c cUp) doUpgradeCLIWithHttpDownload(ctx context.Context) (err error) {
|
|
||||||
mlog.Print(`start upgrading cli with http get download...`)
|
|
||||||
var (
|
var (
|
||||||
downloadUrl = fmt.Sprintf(
|
downloadUrl = fmt.Sprintf(
|
||||||
`https://github.com/gogf/gf/releases/latest/download/gf_%s_%s`,
|
`https://github.com/gogf/gf/releases/latest/download/gf_%s_%s`,
|
||||||
@ -216,7 +191,7 @@ func (c cUp) doUpgradeCLIWithHttpDownload(ctx context.Context) (err error) {
|
|||||||
defer func() {
|
defer func() {
|
||||||
mlog.Printf(`new version cli binary is successfully installed to "%s"`, gfile.SelfPath())
|
mlog.Printf(`new version cli binary is successfully installed to "%s"`, gfile.SelfPath())
|
||||||
mlog.Printf(`remove temporary buffer file "%s"`, localSaveFilePath)
|
mlog.Printf(`remove temporary buffer file "%s"`, localSaveFilePath)
|
||||||
_ = gfile.RemoveFile(localSaveFilePath)
|
_ = gfile.Remove(localSaveFilePath)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// It fails if file not exist or its size is less than 1MB.
|
// It fails if file not exist or its size is less than 1MB.
|
||||||
@ -236,41 +211,6 @@ func (c cUp) doUpgradeCLIWithHttpDownload(ctx context.Context) (err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c cUp) doUpgradeCLIWithGoInstall(ctx context.Context, in cUpInput) (err error) {
|
|
||||||
mlog.Print(`upgrading cli with go install...`)
|
|
||||||
if !genv.Contains("GOPATH") {
|
|
||||||
mlog.Fatal(`"GOPATH" environment variable does not exist, please check your go installation`)
|
|
||||||
}
|
|
||||||
|
|
||||||
command := fmt.Sprintf(`go install %s`, in.CliModulePath)
|
|
||||||
mlog.Printf(`running command: %s`, command)
|
|
||||||
err = gproc.ShellRun(ctx, command)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
cliFilePath := gfile.Join(genv.Get("GOPATH").String(), "bin/gf")
|
|
||||||
if runtime.GOOS == "windows" {
|
|
||||||
cliFilePath += ".exe"
|
|
||||||
}
|
|
||||||
|
|
||||||
// It fails if file not exist or its size is less than 1MB.
|
|
||||||
if !gfile.Exists(cliFilePath) || gfile.Size(cliFilePath) < 1024*1024 {
|
|
||||||
mlog.Fatalf(`go install %s failed, "%s" does not exist or its size is less than 1MB`, in.CliModulePath, cliFilePath)
|
|
||||||
}
|
|
||||||
|
|
||||||
newFile, err := gfile.Open(cliFilePath)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
// selfupdate
|
|
||||||
err = selfupdate.Apply(newFile, selfupdate.Options{})
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c cUp) doAutoFixing(ctx context.Context, dirPath string, version string) (err error) {
|
func (c cUp) doAutoFixing(ctx context.Context, dirPath string, version string) (err error) {
|
||||||
mlog.Printf(`auto fixing directory path "%s" from version "%s" ...`, dirPath, version)
|
mlog.Printf(`auto fixing directory path "%s" from version "%s" ...`, dirPath, version)
|
||||||
command := fmt.Sprintf(`gf fix -p %s`, dirPath)
|
command := fmt.Sprintf(`gf fix -p %s`, dirPath)
|
||||||
|
|||||||
@ -7,19 +7,14 @@
|
|||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"runtime"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/gogf/gf/v2"
|
"github.com/gogf/gf/v2"
|
||||||
"github.com/gogf/gf/v2/errors/gerror"
|
"github.com/gogf/gf/v2/errors/gerror"
|
||||||
"github.com/gogf/gf/v2/frame/g"
|
"github.com/gogf/gf/v2/frame/g"
|
||||||
"github.com/gogf/gf/v2/os/gbuild"
|
"github.com/gogf/gf/v2/os/gbuild"
|
||||||
"github.com/gogf/gf/v2/os/gfile"
|
"github.com/gogf/gf/v2/os/gfile"
|
||||||
"github.com/gogf/gf/v2/os/gproc"
|
|
||||||
"github.com/gogf/gf/v2/text/gregex"
|
"github.com/gogf/gf/v2/text/gregex"
|
||||||
"github.com/gogf/gf/v2/text/gstr"
|
"github.com/gogf/gf/v2/text/gstr"
|
||||||
|
|
||||||
@ -30,10 +25,6 @@ var (
|
|||||||
Version = cVersion{}
|
Version = cVersion{}
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
|
||||||
defaultIndent = "{{indent}}"
|
|
||||||
)
|
|
||||||
|
|
||||||
type cVersion struct {
|
type cVersion struct {
|
||||||
g.Meta `name:"version" brief:"show version information of current binary"`
|
g.Meta `name:"version" brief:"show version information of current binary"`
|
||||||
}
|
}
|
||||||
@ -45,90 +36,34 @@ type cVersionInput struct {
|
|||||||
type cVersionOutput struct{}
|
type cVersionOutput struct{}
|
||||||
|
|
||||||
func (c cVersion) Index(ctx context.Context, in cVersionInput) (*cVersionOutput, error) {
|
func (c cVersion) Index(ctx context.Context, in cVersionInput) (*cVersionOutput, error) {
|
||||||
detailBuffer := &detailBuffer{}
|
|
||||||
detailBuffer.WriteString(fmt.Sprintf("%s", gf.VERSION))
|
|
||||||
|
|
||||||
detailBuffer.appendLine(0, "Welcome to GoFrame!")
|
|
||||||
|
|
||||||
detailBuffer.appendLine(0, "Env Detail:")
|
|
||||||
goVersion, ok := getGoVersion()
|
|
||||||
if ok {
|
|
||||||
detailBuffer.appendLine(1, fmt.Sprintf("Go Version: %s", goVersion))
|
|
||||||
detailBuffer.appendLine(1, fmt.Sprintf("GF Version(go.mod): %s", getGoFrameVersion(2)))
|
|
||||||
} else {
|
|
||||||
v, err := c.getGFVersionOfCurrentProject()
|
|
||||||
if err == nil {
|
|
||||||
detailBuffer.appendLine(1, fmt.Sprintf("GF Version(go.mod): %s", v))
|
|
||||||
} else {
|
|
||||||
detailBuffer.appendLine(1, fmt.Sprintf("GF Version(go.mod): %s", err.Error()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
detailBuffer.appendLine(0, "CLI Detail:")
|
|
||||||
detailBuffer.appendLine(1, fmt.Sprintf("Installed At: %s", gfile.SelfPath()))
|
|
||||||
info := gbuild.Info()
|
info := gbuild.Info()
|
||||||
if info.GoFrame == "" {
|
if info.Git == "" {
|
||||||
detailBuffer.appendLine(1, fmt.Sprintf("Built Go Version: %s", runtime.Version()))
|
info.Git = "none"
|
||||||
detailBuffer.appendLine(1, fmt.Sprintf("Built GF Version: %s", gf.VERSION))
|
}
|
||||||
|
mlog.Printf(`GoFrame CLI Tool %s, https://goframe.org`, gf.VERSION)
|
||||||
|
gfVersion, err := c.getGFVersionOfCurrentProject()
|
||||||
|
if err != nil {
|
||||||
|
gfVersion = err.Error()
|
||||||
} else {
|
} else {
|
||||||
if info.Git == "" {
|
gfVersion = gfVersion + " in current go.mod"
|
||||||
info.Git = "none"
|
}
|
||||||
}
|
mlog.Printf(`GoFrame Version: %s`, gfVersion)
|
||||||
detailBuffer.appendLine(1, fmt.Sprintf("Built Go Version: %s", info.Golang))
|
mlog.Printf(`CLI Installed At: %s`, gfile.SelfPath())
|
||||||
detailBuffer.appendLine(1, fmt.Sprintf("Built GF Version: %s", info.GoFrame))
|
if info.GoFrame == "" {
|
||||||
detailBuffer.appendLine(1, fmt.Sprintf("Git Commit: %s", info.Git))
|
mlog.Print(`Current is a custom installed version, no installation information.`)
|
||||||
detailBuffer.appendLine(1, fmt.Sprintf("Built Time: %s", info.Time))
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
detailBuffer.appendLine(0, "Others Detail:")
|
mlog.Print(gstr.Trim(fmt.Sprintf(`
|
||||||
detailBuffer.appendLine(1, "Docs: https://goframe.org")
|
CLI Built Detail:
|
||||||
detailBuffer.appendLine(1, fmt.Sprintf("Now : %s", time.Now().Format(time.RFC3339)))
|
Go Version: %s
|
||||||
|
GF Version: %s
|
||||||
mlog.Print(detailBuffer.replaceAllIndent(" "))
|
Git Commit: %s
|
||||||
|
Build Time: %s
|
||||||
|
`, info.Golang, info.GoFrame, info.Git, info.Time)))
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// detailBuffer is a buffer for detail information.
|
|
||||||
type detailBuffer struct {
|
|
||||||
bytes.Buffer
|
|
||||||
}
|
|
||||||
|
|
||||||
// appendLine appends a line to the buffer with given indent level.
|
|
||||||
func (d *detailBuffer) appendLine(indentLevel int, line string) {
|
|
||||||
d.WriteString(fmt.Sprintf("\n%s%s", strings.Repeat(defaultIndent, indentLevel), line))
|
|
||||||
}
|
|
||||||
|
|
||||||
// replaceAllIndent replaces the tab with given indent string and prints the buffer content.
|
|
||||||
func (d *detailBuffer) replaceAllIndent(indentStr string) string {
|
|
||||||
return strings.ReplaceAll(d.String(), defaultIndent, indentStr)
|
|
||||||
}
|
|
||||||
|
|
||||||
// getGoFrameVersion returns the goframe version of current project using.
|
|
||||||
func getGoFrameVersion(indentLevel int) (gfVersion string) {
|
|
||||||
pkgInfo, err := gproc.ShellExec(context.Background(), `go list -f "{{if (not .Main)}}{{.Path}}@{{.Version}}{{end}}" -m all`)
|
|
||||||
if err != nil {
|
|
||||||
return "cannot find go.mod"
|
|
||||||
}
|
|
||||||
pkgList := gstr.Split(pkgInfo, "\n")
|
|
||||||
for _, v := range pkgList {
|
|
||||||
if strings.HasPrefix(v, "github.com/gogf/gf") {
|
|
||||||
gfVersion += fmt.Sprintf("\n%s%s", strings.Repeat(defaultIndent, indentLevel), v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// getGoVersion returns the go version
|
|
||||||
func getGoVersion() (goVersion string, ok bool) {
|
|
||||||
goVersion, err := gproc.ShellExec(context.Background(), "go version")
|
|
||||||
if err != nil {
|
|
||||||
return "", false
|
|
||||||
}
|
|
||||||
goVersion = gstr.TrimLeftStr(goVersion, "go version ")
|
|
||||||
goVersion = gstr.TrimRightStr(goVersion, "\n")
|
|
||||||
return goVersion, true
|
|
||||||
}
|
|
||||||
|
|
||||||
// getGFVersionOfCurrentProject checks and returns the GoFrame version current project using.
|
// getGFVersionOfCurrentProject checks and returns the GoFrame version current project using.
|
||||||
func (c cVersion) getGFVersionOfCurrentProject() (string, error) {
|
func (c cVersion) getGFVersionOfCurrentProject() (string, error) {
|
||||||
goModPath := gfile.Join(gfile.Pwd(), "go.mod")
|
goModPath := gfile.Join(gfile.Pwd(), "go.mod")
|
||||||
|
|||||||
@ -1,38 +0,0 @@
|
|||||||
// 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"
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/gogf/gf/v2/database/gdb"
|
|
||||||
"github.com/gogf/gf/v2/test/gtest"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
ctx = context.Background()
|
|
||||||
testDB gdb.DB
|
|
||||||
link = "mysql:root:12345678@tcp(127.0.0.1:3306)/test?loc=Local&parseTime=true"
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
var err error
|
|
||||||
testDB, err = gdb.New(gdb.ConfigNode{
|
|
||||||
Link: link,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func dropTableWithDb(db gdb.DB, table string) {
|
|
||||||
dropTableStmt := fmt.Sprintf("DROP TABLE IF EXISTS `%s`", table)
|
|
||||||
if _, err := db.Exec(ctx, dropTableStmt); err != nil {
|
|
||||||
gtest.Error(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,151 +0,0 @@
|
|||||||
// 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 (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/gogf/gf/v2/os/gfile"
|
|
||||||
"github.com/gogf/gf/v2/os/gproc"
|
|
||||||
"github.com/gogf/gf/v2/test/gtest"
|
|
||||||
"github.com/gogf/gf/v2/text/gstr"
|
|
||||||
)
|
|
||||||
|
|
||||||
func Test_Build_Single(t *testing.T) {
|
|
||||||
gtest.C(t, func(t *gtest.T) {
|
|
||||||
var (
|
|
||||||
buildPath = gtest.DataPath(`build`, `single`)
|
|
||||||
pwd = gfile.Pwd()
|
|
||||||
binaryName = `t.test`
|
|
||||||
binaryPath = gtest.DataPath(`build`, `single`, binaryName)
|
|
||||||
f = cBuild{}
|
|
||||||
)
|
|
||||||
defer gfile.Chdir(pwd)
|
|
||||||
defer gfile.Remove(binaryPath)
|
|
||||||
err := gfile.Chdir(buildPath)
|
|
||||||
t.AssertNil(err)
|
|
||||||
|
|
||||||
t.Assert(gfile.Exists(binaryPath), false)
|
|
||||||
_, err = f.Index(ctx, cBuildInput{
|
|
||||||
File: cBuildDefaultFile,
|
|
||||||
Name: binaryName,
|
|
||||||
})
|
|
||||||
t.AssertNil(err)
|
|
||||||
t.Assert(gfile.Exists(binaryPath), true)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_Build_Single_Output(t *testing.T) {
|
|
||||||
gtest.C(t, func(t *gtest.T) {
|
|
||||||
var (
|
|
||||||
buildPath = gtest.DataPath(`build`, `single`)
|
|
||||||
pwd = gfile.Pwd()
|
|
||||||
binaryName = `tt`
|
|
||||||
binaryDirPath = gtest.DataPath(`build`, `single`, `tt`)
|
|
||||||
binaryPath = gtest.DataPath(`build`, `single`, `tt`, binaryName)
|
|
||||||
f = cBuild{}
|
|
||||||
)
|
|
||||||
defer gfile.Chdir(pwd)
|
|
||||||
defer gfile.Remove(binaryDirPath)
|
|
||||||
err := gfile.Chdir(buildPath)
|
|
||||||
t.AssertNil(err)
|
|
||||||
|
|
||||||
t.Assert(gfile.Exists(binaryPath), false)
|
|
||||||
_, err = f.Index(ctx, cBuildInput{
|
|
||||||
Output: "./tt/tt",
|
|
||||||
})
|
|
||||||
t.AssertNil(err)
|
|
||||||
t.Assert(gfile.Exists(binaryPath), true)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_Build_Single_Path(t *testing.T) {
|
|
||||||
gtest.C(t, func(t *gtest.T) {
|
|
||||||
var (
|
|
||||||
buildPath = gtest.DataPath(`build`, `single`)
|
|
||||||
pwd = gfile.Pwd()
|
|
||||||
dirName = "ttt"
|
|
||||||
binaryName = `main`
|
|
||||||
binaryDirPath = gtest.DataPath(`build`, `single`, dirName)
|
|
||||||
binaryPath = gtest.DataPath(`build`, `single`, dirName, binaryName)
|
|
||||||
f = cBuild{}
|
|
||||||
)
|
|
||||||
defer gfile.Chdir(pwd)
|
|
||||||
defer gfile.Remove(binaryDirPath)
|
|
||||||
err := gfile.Chdir(buildPath)
|
|
||||||
t.AssertNil(err)
|
|
||||||
|
|
||||||
t.Assert(gfile.Exists(binaryPath), false)
|
|
||||||
_, err = f.Index(ctx, cBuildInput{
|
|
||||||
Path: "ttt",
|
|
||||||
})
|
|
||||||
t.AssertNil(err)
|
|
||||||
t.Assert(gfile.Exists(binaryPath), true)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_Build_Single_VarMap(t *testing.T) {
|
|
||||||
gtest.C(t, func(t *gtest.T) {
|
|
||||||
var (
|
|
||||||
buildPath = gtest.DataPath(`build`, `varmap`)
|
|
||||||
pwd = gfile.Pwd()
|
|
||||||
binaryName = `main`
|
|
||||||
binaryPath = gtest.DataPath(`build`, `varmap`, binaryName)
|
|
||||||
f = cBuild{}
|
|
||||||
)
|
|
||||||
defer gfile.Chdir(pwd)
|
|
||||||
defer gfile.Remove(binaryPath)
|
|
||||||
err := gfile.Chdir(buildPath)
|
|
||||||
t.AssertNil(err)
|
|
||||||
|
|
||||||
t.Assert(gfile.Exists(binaryPath), false)
|
|
||||||
_, err = f.Index(ctx, cBuildInput{
|
|
||||||
VarMap: map[string]any{
|
|
||||||
"a": "1",
|
|
||||||
"b": "2",
|
|
||||||
},
|
|
||||||
})
|
|
||||||
t.AssertNil(err)
|
|
||||||
t.Assert(gfile.Exists(binaryPath), true)
|
|
||||||
|
|
||||||
result, err := gproc.ShellExec(ctx, binaryPath)
|
|
||||||
t.AssertNil(err)
|
|
||||||
t.Assert(gstr.Contains(result, `a: 1`), true)
|
|
||||||
t.Assert(gstr.Contains(result, `b: 2`), true)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_Build_Multiple(t *testing.T) {
|
|
||||||
gtest.C(t, func(t *gtest.T) {
|
|
||||||
var (
|
|
||||||
buildPath = gtest.DataPath(`build`, `multiple`)
|
|
||||||
pwd = gfile.Pwd()
|
|
||||||
binaryDirPath = gtest.DataPath(`build`, `multiple`, `temp`)
|
|
||||||
binaryPathLinux = gtest.DataPath(`build`, `multiple`, `temp`, `v1.1`, `linux_amd64`, `ttt`)
|
|
||||||
binaryPathWindows = gtest.DataPath(`build`, `multiple`, `temp`, `v1.1`, `windows_amd64`, `ttt.exe`)
|
|
||||||
f = cBuild{}
|
|
||||||
)
|
|
||||||
defer gfile.Chdir(pwd)
|
|
||||||
defer gfile.Remove(binaryDirPath)
|
|
||||||
err := gfile.Chdir(buildPath)
|
|
||||||
t.AssertNil(err)
|
|
||||||
|
|
||||||
t.Assert(gfile.Exists(binaryPathLinux), false)
|
|
||||||
t.Assert(gfile.Exists(binaryPathWindows), false)
|
|
||||||
_, err = f.Index(ctx, cBuildInput{
|
|
||||||
File: "multiple.go",
|
|
||||||
Name: "ttt",
|
|
||||||
Version: "v1.1",
|
|
||||||
Arch: "amd64",
|
|
||||||
System: "linux, windows",
|
|
||||||
Path: "temp",
|
|
||||||
})
|
|
||||||
t.AssertNil(err)
|
|
||||||
t.Assert(gfile.Exists(binaryPathLinux), true)
|
|
||||||
t.Assert(gfile.Exists(binaryPathWindows), true)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
@ -1,310 +0,0 @@
|
|||||||
// 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 (
|
|
||||||
"path/filepath"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/gogf/gf/v2/os/gfile"
|
|
||||||
"github.com/gogf/gf/v2/test/gtest"
|
|
||||||
"github.com/gogf/gf/v2/util/guid"
|
|
||||||
"github.com/gogf/gf/v2/util/gutil"
|
|
||||||
|
|
||||||
"github.com/gogf/gf/cmd/gf/v2/internal/cmd/genctrl"
|
|
||||||
)
|
|
||||||
|
|
||||||
func Test_Gen_Ctrl_Default(t *testing.T) {
|
|
||||||
gtest.C(t, func(t *gtest.T) {
|
|
||||||
var (
|
|
||||||
path = gfile.Temp(guid.S())
|
|
||||||
apiFolder = gtest.DataPath("genctrl", "api")
|
|
||||||
in = genctrl.CGenCtrlInput{
|
|
||||||
SrcFolder: apiFolder,
|
|
||||||
DstFolder: path,
|
|
||||||
WatchFile: "",
|
|
||||||
SdkPath: "",
|
|
||||||
SdkStdVersion: false,
|
|
||||||
SdkNoV1: false,
|
|
||||||
Clear: false,
|
|
||||||
Merge: false,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
err := gutil.FillStructWithDefault(&in)
|
|
||||||
t.AssertNil(err)
|
|
||||||
|
|
||||||
err = gfile.Mkdir(path)
|
|
||||||
t.AssertNil(err)
|
|
||||||
defer gfile.Remove(path)
|
|
||||||
|
|
||||||
_, err = genctrl.CGenCtrl{}.Ctrl(ctx, in)
|
|
||||||
t.AssertNil(err)
|
|
||||||
|
|
||||||
// apiInterface file
|
|
||||||
var (
|
|
||||||
genApi = apiFolder + filepath.FromSlash("/article/article.go")
|
|
||||||
genApiExpect = apiFolder + filepath.FromSlash("/article/article_expect.go")
|
|
||||||
)
|
|
||||||
defer gfile.Remove(genApi)
|
|
||||||
t.Assert(gfile.GetContents(genApi), gfile.GetContents(genApiExpect))
|
|
||||||
|
|
||||||
// files
|
|
||||||
files, err := gfile.ScanDir(path, "*.go", true)
|
|
||||||
t.AssertNil(err)
|
|
||||||
t.Assert(files, []string{
|
|
||||||
path + filepath.FromSlash("/article/article.go"),
|
|
||||||
path + filepath.FromSlash("/article/article_new.go"),
|
|
||||||
path + filepath.FromSlash("/article/article_v1_create.go"),
|
|
||||||
path + filepath.FromSlash("/article/article_v1_get_list.go"),
|
|
||||||
path + filepath.FromSlash("/article/article_v1_get_one.go"),
|
|
||||||
path + filepath.FromSlash("/article/article_v1_update.go"),
|
|
||||||
path + filepath.FromSlash("/article/article_v2_create.go"),
|
|
||||||
path + filepath.FromSlash("/article/article_v2_update.go"),
|
|
||||||
})
|
|
||||||
|
|
||||||
// content
|
|
||||||
testPath := gtest.DataPath("genctrl", "controller")
|
|
||||||
expectFiles := []string{
|
|
||||||
testPath + filepath.FromSlash("/article/article.go"),
|
|
||||||
testPath + filepath.FromSlash("/article/article_new.go"),
|
|
||||||
testPath + filepath.FromSlash("/article/article_v1_create.go"),
|
|
||||||
testPath + filepath.FromSlash("/article/article_v1_get_list.go"),
|
|
||||||
testPath + filepath.FromSlash("/article/article_v1_get_one.go"),
|
|
||||||
testPath + filepath.FromSlash("/article/article_v1_update.go"),
|
|
||||||
testPath + filepath.FromSlash("/article/article_v2_create.go"),
|
|
||||||
testPath + filepath.FromSlash("/article/article_v2_update.go"),
|
|
||||||
}
|
|
||||||
for i := range files {
|
|
||||||
t.Assert(gfile.GetContents(files[i]), gfile.GetContents(expectFiles[i]))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func expectFilesContent(t *gtest.T, paths []string, expectPaths []string) {
|
|
||||||
for i, expectFile := range expectPaths {
|
|
||||||
val := gfile.GetContents(paths[i])
|
|
||||||
expect := gfile.GetContents(expectFile)
|
|
||||||
t.Assert(val, expect)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// gf gen ctrl -m
|
|
||||||
// In the same module, different API files are added
|
|
||||||
func Test_Gen_Ctrl_UseMerge_AddNewFile(t *testing.T) {
|
|
||||||
gtest.C(t, func(t *gtest.T) {
|
|
||||||
var (
|
|
||||||
ctrlPath = gfile.Temp(guid.S())
|
|
||||||
//ctrlPath = gtest.DataPath("issue", "3460", "controller")
|
|
||||||
apiFolder = gtest.DataPath("genctrl-merge", "add_new_file", "api")
|
|
||||||
in = genctrl.CGenCtrlInput{
|
|
||||||
SrcFolder: apiFolder,
|
|
||||||
DstFolder: ctrlPath,
|
|
||||||
Merge: true,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
const testNewApiFile = `
|
|
||||||
package v1
|
|
||||||
import "github.com/gogf/gf/v2/frame/g"
|
|
||||||
type DictTypeAddReq struct {
|
|
||||||
g.Meta
|
|
||||||
}
|
|
||||||
type DictTypeAddRes struct {
|
|
||||||
}
|
|
||||||
`
|
|
||||||
|
|
||||||
err := gfile.Mkdir(ctrlPath)
|
|
||||||
t.AssertNil(err)
|
|
||||||
defer gfile.Remove(ctrlPath)
|
|
||||||
|
|
||||||
_, err = genctrl.CGenCtrl{}.Ctrl(ctx, in)
|
|
||||||
t.AssertNil(err)
|
|
||||||
|
|
||||||
var (
|
|
||||||
genApi = filepath.Join(apiFolder, "/dict/dict.go")
|
|
||||||
genApiExpect = filepath.Join(apiFolder, "/dict/dict_expect.go")
|
|
||||||
)
|
|
||||||
defer gfile.Remove(genApi)
|
|
||||||
t.Assert(gfile.GetContents(genApi), gfile.GetContents(genApiExpect))
|
|
||||||
|
|
||||||
genCtrlFiles, err := gfile.ScanDir(ctrlPath, "*.go", true)
|
|
||||||
t.AssertNil(err)
|
|
||||||
t.Assert(genCtrlFiles, []string{
|
|
||||||
filepath.Join(ctrlPath, "/dict/dict.go"),
|
|
||||||
filepath.Join(ctrlPath, "/dict/dict_new.go"),
|
|
||||||
filepath.Join(ctrlPath, "/dict/dict_v1_dict_type.go"),
|
|
||||||
})
|
|
||||||
|
|
||||||
expectCtrlPath := gtest.DataPath("genctrl-merge", "add_new_file", "controller")
|
|
||||||
expectFiles := []string{
|
|
||||||
filepath.Join(expectCtrlPath, "/dict/dict.go"),
|
|
||||||
filepath.Join(expectCtrlPath, "/dict/dict_new.go"),
|
|
||||||
filepath.Join(expectCtrlPath, "/dict/dict_v1_dict_type.go"),
|
|
||||||
}
|
|
||||||
|
|
||||||
// Line Feed maybe \r\n or \n
|
|
||||||
expectFilesContent(t, genCtrlFiles, expectFiles)
|
|
||||||
|
|
||||||
// Add a new API file
|
|
||||||
newApiFilePath := filepath.Join(apiFolder, "/dict/v1/test_new.go")
|
|
||||||
err = gfile.PutContents(newApiFilePath, testNewApiFile)
|
|
||||||
t.AssertNil(err)
|
|
||||||
defer gfile.Remove(newApiFilePath)
|
|
||||||
|
|
||||||
// Then execute the command
|
|
||||||
_, err = genctrl.CGenCtrl{}.Ctrl(ctx, in)
|
|
||||||
t.AssertNil(err)
|
|
||||||
|
|
||||||
genApi = filepath.Join(apiFolder, "/dict.go")
|
|
||||||
genApiExpect = filepath.Join(apiFolder, "/dict_add_new_ctrl_expect.gotest")
|
|
||||||
|
|
||||||
t.Assert(gfile.GetContents(genApi), gfile.GetContents(genApiExpect))
|
|
||||||
|
|
||||||
genCtrlFiles = append(genCtrlFiles, filepath.Join(ctrlPath, "/dict/dict_v1_test_new.go"))
|
|
||||||
// Use the gotest suffix, otherwise the IDE will delete the import
|
|
||||||
expectFiles = append(expectFiles, filepath.Join(expectCtrlPath, "/dict/dict_v1_test_new.gotest"))
|
|
||||||
// Line Feed maybe \r\n or \n
|
|
||||||
expectFilesContent(t, genCtrlFiles, expectFiles)
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// gf gen ctrl -m
|
|
||||||
// In the same module, Add the same file to the API
|
|
||||||
func Test_Gen_Ctrl_UseMerge_AddNewCtrl(t *testing.T) {
|
|
||||||
gtest.C(t, func(t *gtest.T) {
|
|
||||||
var (
|
|
||||||
ctrlPath = gfile.Temp(guid.S())
|
|
||||||
//ctrlPath = gtest.DataPath("issue", "3460", "controller")
|
|
||||||
apiFolder = gtest.DataPath("genctrl-merge", "add_new_ctrl", "api")
|
|
||||||
in = genctrl.CGenCtrlInput{
|
|
||||||
SrcFolder: apiFolder,
|
|
||||||
DstFolder: ctrlPath,
|
|
||||||
Merge: true,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
err := gfile.Mkdir(ctrlPath)
|
|
||||||
t.AssertNil(err)
|
|
||||||
defer gfile.Remove(ctrlPath)
|
|
||||||
|
|
||||||
_, err = genctrl.CGenCtrl{}.Ctrl(ctx, in)
|
|
||||||
t.AssertNil(err)
|
|
||||||
|
|
||||||
var (
|
|
||||||
genApi = filepath.Join(apiFolder, "/dict/dict.go")
|
|
||||||
genApiExpect = filepath.Join(apiFolder, "/dict/dict_expect.go")
|
|
||||||
)
|
|
||||||
defer gfile.Remove(genApi)
|
|
||||||
t.Assert(gfile.GetContents(genApi), gfile.GetContents(genApiExpect))
|
|
||||||
|
|
||||||
genCtrlFiles, err := gfile.ScanDir(ctrlPath, "*.go", true)
|
|
||||||
t.AssertNil(err)
|
|
||||||
t.Assert(genCtrlFiles, []string{
|
|
||||||
filepath.Join(ctrlPath, "/dict/dict.go"),
|
|
||||||
filepath.Join(ctrlPath, "/dict/dict_new.go"),
|
|
||||||
filepath.Join(ctrlPath, "/dict/dict_v1_dict_type.go"),
|
|
||||||
})
|
|
||||||
|
|
||||||
expectCtrlPath := gtest.DataPath("genctrl-merge", "add_new_ctrl", "controller")
|
|
||||||
expectFiles := []string{
|
|
||||||
filepath.Join(expectCtrlPath, "/dict/dict.go"),
|
|
||||||
filepath.Join(expectCtrlPath, "/dict/dict_new.go"),
|
|
||||||
filepath.Join(expectCtrlPath, "/dict/dict_v1_dict_type.go"),
|
|
||||||
}
|
|
||||||
|
|
||||||
// Line Feed maybe \r\n or \n
|
|
||||||
expectFilesContent(t, genCtrlFiles, expectFiles)
|
|
||||||
|
|
||||||
const testNewApiFile = `
|
|
||||||
|
|
||||||
type DictTypeAddReq struct {
|
|
||||||
g.Meta
|
|
||||||
}
|
|
||||||
type DictTypeAddRes struct {
|
|
||||||
}
|
|
||||||
`
|
|
||||||
dictModuleFileName := filepath.Join(apiFolder, "/dict/v1/dict_type.go")
|
|
||||||
// Save the contents of the file before the changes
|
|
||||||
apiFileContents := gfile.GetContents(dictModuleFileName)
|
|
||||||
|
|
||||||
// Add a new API file
|
|
||||||
err = gfile.PutContentsAppend(dictModuleFileName, testNewApiFile)
|
|
||||||
t.AssertNil(err)
|
|
||||||
|
|
||||||
//==================================
|
|
||||||
// Then execute the command
|
|
||||||
_, err = genctrl.CGenCtrl{}.Ctrl(ctx, in)
|
|
||||||
t.AssertNil(err)
|
|
||||||
|
|
||||||
genApi = filepath.Join(apiFolder, "/dict.go")
|
|
||||||
genApiExpect = filepath.Join(apiFolder, "/dict_add_new_ctrl_expect.gotest")
|
|
||||||
t.Assert(gfile.GetContents(genApi), gfile.GetContents(genApiExpect))
|
|
||||||
|
|
||||||
// Use the gotest suffix, otherwise the IDE will delete the import
|
|
||||||
expectFiles[2] = filepath.Join(expectCtrlPath, "/dict/dict_v1_test_new.gotest")
|
|
||||||
// Line Feed maybe \r\n or \n
|
|
||||||
expectFilesContent(t, genCtrlFiles, expectFiles)
|
|
||||||
|
|
||||||
// Restore the contents of the original API file
|
|
||||||
err = gfile.PutContents(dictModuleFileName, apiFileContents)
|
|
||||||
t.AssertNil(err)
|
|
||||||
})
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://github.com/gogf/gf/issues/3460
|
|
||||||
func Test_Gen_Ctrl_UseMerge_Issue3460(t *testing.T) {
|
|
||||||
gtest.C(t, func(t *gtest.T) {
|
|
||||||
var (
|
|
||||||
ctrlPath = gfile.Temp(guid.S())
|
|
||||||
//ctrlPath = gtest.DataPath("issue", "3460", "controller")
|
|
||||||
apiFolder = gtest.DataPath("issue", "3460", "api")
|
|
||||||
in = genctrl.CGenCtrlInput{
|
|
||||||
SrcFolder: apiFolder,
|
|
||||||
DstFolder: ctrlPath,
|
|
||||||
WatchFile: "",
|
|
||||||
SdkPath: "",
|
|
||||||
SdkStdVersion: false,
|
|
||||||
SdkNoV1: false,
|
|
||||||
Clear: false,
|
|
||||||
Merge: true,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
err := gfile.Mkdir(ctrlPath)
|
|
||||||
t.AssertNil(err)
|
|
||||||
defer gfile.Remove(ctrlPath)
|
|
||||||
|
|
||||||
_, err = genctrl.CGenCtrl{}.Ctrl(ctx, in)
|
|
||||||
t.AssertNil(err)
|
|
||||||
|
|
||||||
files, err := gfile.ScanDir(ctrlPath, "*.go", true)
|
|
||||||
t.AssertNil(err)
|
|
||||||
t.Assert(files, []string{
|
|
||||||
filepath.Join(ctrlPath, "/hello/hello.go"),
|
|
||||||
filepath.Join(ctrlPath, "/hello/hello_new.go"),
|
|
||||||
filepath.Join(ctrlPath, "/hello/hello_v1_req.go"),
|
|
||||||
filepath.Join(ctrlPath, "/hello/hello_v2_req.go"),
|
|
||||||
})
|
|
||||||
|
|
||||||
expectCtrlPath := gtest.DataPath("issue", "3460", "controller")
|
|
||||||
expectFiles := []string{
|
|
||||||
filepath.Join(expectCtrlPath, "/hello/hello.go"),
|
|
||||||
filepath.Join(expectCtrlPath, "/hello/hello_new.go"),
|
|
||||||
filepath.Join(expectCtrlPath, "/hello/hello_v1_req.go"),
|
|
||||||
filepath.Join(expectCtrlPath, "/hello/hello_v2_req.go"),
|
|
||||||
}
|
|
||||||
|
|
||||||
// Line Feed maybe \r\n or \n
|
|
||||||
for i, expectFile := range expectFiles {
|
|
||||||
val := gfile.GetContents(files[i])
|
|
||||||
expect := gfile.GetContents(expectFile)
|
|
||||||
t.Assert(val, expect)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
@ -1,462 +0,0 @@
|
|||||||
// 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 (
|
|
||||||
"fmt"
|
|
||||||
"path/filepath"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/gogf/gf/v2/database/gdb"
|
|
||||||
"github.com/gogf/gf/v2/frame/g"
|
|
||||||
"github.com/gogf/gf/v2/os/gcfg"
|
|
||||||
"github.com/gogf/gf/v2/os/gfile"
|
|
||||||
"github.com/gogf/gf/v2/test/gtest"
|
|
||||||
"github.com/gogf/gf/v2/text/gstr"
|
|
||||||
"github.com/gogf/gf/v2/util/guid"
|
|
||||||
"github.com/gogf/gf/v2/util/gutil"
|
|
||||||
|
|
||||||
"github.com/gogf/gf/cmd/gf/v2/internal/cmd/gendao"
|
|
||||||
)
|
|
||||||
|
|
||||||
// https://github.com/gogf/gf/issues/2572
|
|
||||||
func Test_Gen_Dao_Issue2572(t *testing.T) {
|
|
||||||
gtest.C(t, func(t *gtest.T) {
|
|
||||||
var (
|
|
||||||
err error
|
|
||||||
db = testDB
|
|
||||||
table1 = "user1"
|
|
||||||
table2 = "user2"
|
|
||||||
issueDirPath = gtest.DataPath(`issue`, `2572`)
|
|
||||||
)
|
|
||||||
t.AssertNil(execSqlFile(db, gtest.DataPath(`issue`, `2572`, `sql1.sql`)))
|
|
||||||
t.AssertNil(execSqlFile(db, gtest.DataPath(`issue`, `2572`, `sql2.sql`)))
|
|
||||||
defer dropTableWithDb(db, table1)
|
|
||||||
defer dropTableWithDb(db, table2)
|
|
||||||
|
|
||||||
var (
|
|
||||||
path = gfile.Temp(guid.S())
|
|
||||||
group = "test"
|
|
||||||
in = gendao.CGenDaoInput{
|
|
||||||
Path: path,
|
|
||||||
Link: "",
|
|
||||||
Tables: "",
|
|
||||||
TablesEx: "",
|
|
||||||
Group: group,
|
|
||||||
Prefix: "",
|
|
||||||
RemovePrefix: "",
|
|
||||||
JsonCase: "SnakeScreaming",
|
|
||||||
ImportPrefix: "",
|
|
||||||
DaoPath: "",
|
|
||||||
DoPath: "",
|
|
||||||
EntityPath: "",
|
|
||||||
TplDaoIndexPath: "",
|
|
||||||
TplDaoInternalPath: "",
|
|
||||||
TplDaoDoPath: "",
|
|
||||||
TplDaoEntityPath: "",
|
|
||||||
StdTime: false,
|
|
||||||
WithTime: false,
|
|
||||||
GJsonSupport: false,
|
|
||||||
OverwriteDao: false,
|
|
||||||
DescriptionTag: false,
|
|
||||||
NoJsonTag: false,
|
|
||||||
NoModelComment: false,
|
|
||||||
Clear: false,
|
|
||||||
GenTable: false,
|
|
||||||
TypeMapping: nil,
|
|
||||||
FieldMapping: nil,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
err = gutil.FillStructWithDefault(&in)
|
|
||||||
t.AssertNil(err)
|
|
||||||
|
|
||||||
err = gfile.Copy(issueDirPath, path)
|
|
||||||
t.AssertNil(err)
|
|
||||||
|
|
||||||
defer gfile.Remove(path)
|
|
||||||
|
|
||||||
pwd := gfile.Pwd()
|
|
||||||
err = gfile.Chdir(path)
|
|
||||||
t.AssertNil(err)
|
|
||||||
|
|
||||||
defer gfile.Chdir(pwd)
|
|
||||||
|
|
||||||
_, err = gendao.CGenDao{}.Dao(ctx, in)
|
|
||||||
t.AssertNil(err)
|
|
||||||
|
|
||||||
generatedFiles, err := gfile.ScanDir(path, "*.go", true)
|
|
||||||
t.AssertNil(err)
|
|
||||||
t.Assert(len(generatedFiles), 8)
|
|
||||||
for i, generatedFile := range generatedFiles {
|
|
||||||
generatedFiles[i] = gstr.TrimLeftStr(generatedFile, path)
|
|
||||||
}
|
|
||||||
t.Assert(gstr.InArray(generatedFiles,
|
|
||||||
filepath.FromSlash("/dao/internal/user_1.go")), true)
|
|
||||||
t.Assert(gstr.InArray(generatedFiles,
|
|
||||||
filepath.FromSlash("/dao/internal/user_2.go")), true)
|
|
||||||
t.Assert(gstr.InArray(generatedFiles,
|
|
||||||
filepath.FromSlash("/dao/user_1.go")), true)
|
|
||||||
t.Assert(gstr.InArray(generatedFiles,
|
|
||||||
filepath.FromSlash("/dao/user_2.go")), true)
|
|
||||||
t.Assert(gstr.InArray(generatedFiles,
|
|
||||||
filepath.FromSlash("/model/do/user_1.go")), true)
|
|
||||||
t.Assert(gstr.InArray(generatedFiles,
|
|
||||||
filepath.FromSlash("/model/do/user_2.go")), true)
|
|
||||||
t.Assert(gstr.InArray(generatedFiles,
|
|
||||||
filepath.FromSlash("/model/entity/user_1.go")), true)
|
|
||||||
t.Assert(gstr.InArray(generatedFiles,
|
|
||||||
filepath.FromSlash("/model/entity/user_2.go")), true)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://github.com/gogf/gf/issues/2616
|
|
||||||
func Test_Gen_Dao_Issue2616(t *testing.T) {
|
|
||||||
gtest.C(t, func(t *gtest.T) {
|
|
||||||
var (
|
|
||||||
err error
|
|
||||||
db = testDB
|
|
||||||
table1 = "user1"
|
|
||||||
table2 = "user2"
|
|
||||||
issueDirPath = gtest.DataPath(`issue`, `2616`)
|
|
||||||
)
|
|
||||||
t.AssertNil(execSqlFile(db, gtest.DataPath(`issue`, `2616`, `sql1.sql`)))
|
|
||||||
t.AssertNil(execSqlFile(db, gtest.DataPath(`issue`, `2616`, `sql2.sql`)))
|
|
||||||
defer dropTableWithDb(db, table1)
|
|
||||||
defer dropTableWithDb(db, table2)
|
|
||||||
|
|
||||||
var (
|
|
||||||
path = gfile.Temp(guid.S())
|
|
||||||
group = "test"
|
|
||||||
in = gendao.CGenDaoInput{
|
|
||||||
Path: path,
|
|
||||||
Link: "",
|
|
||||||
Tables: "",
|
|
||||||
TablesEx: "",
|
|
||||||
Group: group,
|
|
||||||
Prefix: "",
|
|
||||||
RemovePrefix: "",
|
|
||||||
JsonCase: "SnakeScreaming",
|
|
||||||
ImportPrefix: "",
|
|
||||||
DaoPath: "",
|
|
||||||
DoPath: "",
|
|
||||||
EntityPath: "",
|
|
||||||
TplDaoIndexPath: "",
|
|
||||||
TplDaoInternalPath: "",
|
|
||||||
TplDaoDoPath: "",
|
|
||||||
TplDaoEntityPath: "",
|
|
||||||
StdTime: false,
|
|
||||||
WithTime: false,
|
|
||||||
GJsonSupport: false,
|
|
||||||
OverwriteDao: false,
|
|
||||||
DescriptionTag: false,
|
|
||||||
NoJsonTag: false,
|
|
||||||
NoModelComment: false,
|
|
||||||
Clear: false,
|
|
||||||
GenTable: false,
|
|
||||||
TypeMapping: nil,
|
|
||||||
FieldMapping: nil,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
err = gutil.FillStructWithDefault(&in)
|
|
||||||
t.AssertNil(err)
|
|
||||||
|
|
||||||
err = gfile.Copy(issueDirPath, path)
|
|
||||||
t.AssertNil(err)
|
|
||||||
|
|
||||||
defer gfile.Remove(path)
|
|
||||||
|
|
||||||
pwd := gfile.Pwd()
|
|
||||||
err = gfile.Chdir(path)
|
|
||||||
t.AssertNil(err)
|
|
||||||
|
|
||||||
defer gfile.Chdir(pwd)
|
|
||||||
|
|
||||||
_, err = gendao.CGenDao{}.Dao(ctx, in)
|
|
||||||
t.AssertNil(err)
|
|
||||||
|
|
||||||
generatedFiles, err := gfile.ScanDir(path, "*.go", true)
|
|
||||||
t.AssertNil(err)
|
|
||||||
t.Assert(len(generatedFiles), 8)
|
|
||||||
for i, generatedFile := range generatedFiles {
|
|
||||||
generatedFiles[i] = gstr.TrimLeftStr(generatedFile, path)
|
|
||||||
}
|
|
||||||
t.Assert(gstr.InArray(generatedFiles,
|
|
||||||
filepath.FromSlash("/dao/internal/user_1.go")), true)
|
|
||||||
t.Assert(gstr.InArray(generatedFiles,
|
|
||||||
filepath.FromSlash("/dao/internal/user_2.go")), true)
|
|
||||||
t.Assert(gstr.InArray(generatedFiles,
|
|
||||||
filepath.FromSlash("/dao/user_1.go")), true)
|
|
||||||
t.Assert(gstr.InArray(generatedFiles,
|
|
||||||
filepath.FromSlash("/dao/user_2.go")), true)
|
|
||||||
t.Assert(gstr.InArray(generatedFiles,
|
|
||||||
filepath.FromSlash("/model/do/user_1.go")), true)
|
|
||||||
t.Assert(gstr.InArray(generatedFiles,
|
|
||||||
filepath.FromSlash("/model/do/user_2.go")), true)
|
|
||||||
t.Assert(gstr.InArray(generatedFiles,
|
|
||||||
filepath.FromSlash("/model/entity/user_1.go")), true)
|
|
||||||
t.Assert(gstr.InArray(generatedFiles,
|
|
||||||
filepath.FromSlash("/model/entity/user_2.go")), true)
|
|
||||||
|
|
||||||
// Key string to check if overwrite the dao files.
|
|
||||||
// dao user1 is not be overwritten as configured in config.yaml.
|
|
||||||
// dao user2 is to be overwritten as configured in config.yaml.
|
|
||||||
var (
|
|
||||||
keyStr = `// I am not overwritten.`
|
|
||||||
daoUser1Content = gfile.GetContents(path + "/dao/user_1.go")
|
|
||||||
daoUser2Content = gfile.GetContents(path + "/dao/user_2.go")
|
|
||||||
)
|
|
||||||
t.Assert(gstr.Contains(daoUser1Content, keyStr), true)
|
|
||||||
t.Assert(gstr.Contains(daoUser2Content, keyStr), false)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://github.com/gogf/gf/issues/2746
|
|
||||||
func Test_Gen_Dao_Issue2746(t *testing.T) {
|
|
||||||
gtest.C(t, func(t *gtest.T) {
|
|
||||||
var (
|
|
||||||
err error
|
|
||||||
mdb gdb.DB
|
|
||||||
link2746 = "mariadb:root:12345678@tcp(127.0.0.1:3307)/test?loc=Local&parseTime=true"
|
|
||||||
table = "issue2746"
|
|
||||||
sqlContent = fmt.Sprintf(
|
|
||||||
gtest.DataContent(`issue`, `2746`, `sql.sql`),
|
|
||||||
table,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
mdb, err = gdb.New(gdb.ConfigNode{
|
|
||||||
Link: link2746,
|
|
||||||
})
|
|
||||||
t.AssertNil(err)
|
|
||||||
|
|
||||||
array := gstr.SplitAndTrim(sqlContent, ";")
|
|
||||||
for _, v := range array {
|
|
||||||
if _, err = mdb.Exec(ctx, v); err != nil {
|
|
||||||
t.AssertNil(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
defer dropTableWithDb(mdb, table)
|
|
||||||
|
|
||||||
var (
|
|
||||||
path = gfile.Temp(guid.S())
|
|
||||||
group = "test"
|
|
||||||
in = gendao.CGenDaoInput{
|
|
||||||
Path: path,
|
|
||||||
Link: link2746,
|
|
||||||
Tables: "",
|
|
||||||
TablesEx: "",
|
|
||||||
Group: group,
|
|
||||||
Prefix: "",
|
|
||||||
RemovePrefix: "",
|
|
||||||
JsonCase: "SnakeScreaming",
|
|
||||||
ImportPrefix: "",
|
|
||||||
DaoPath: "",
|
|
||||||
DoPath: "",
|
|
||||||
EntityPath: "",
|
|
||||||
TplDaoIndexPath: "",
|
|
||||||
TplDaoInternalPath: "",
|
|
||||||
TplDaoDoPath: "",
|
|
||||||
TplDaoEntityPath: "",
|
|
||||||
StdTime: false,
|
|
||||||
WithTime: false,
|
|
||||||
GJsonSupport: true,
|
|
||||||
OverwriteDao: false,
|
|
||||||
DescriptionTag: false,
|
|
||||||
NoJsonTag: false,
|
|
||||||
NoModelComment: false,
|
|
||||||
Clear: false,
|
|
||||||
GenTable: false,
|
|
||||||
TypeMapping: nil,
|
|
||||||
FieldMapping: nil,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
err = gutil.FillStructWithDefault(&in)
|
|
||||||
t.AssertNil(err)
|
|
||||||
|
|
||||||
err = gfile.Mkdir(path)
|
|
||||||
t.AssertNil(err)
|
|
||||||
|
|
||||||
_, err = gendao.CGenDao{}.Dao(ctx, in)
|
|
||||||
t.AssertNil(err)
|
|
||||||
defer gfile.Remove(path)
|
|
||||||
|
|
||||||
var (
|
|
||||||
file = filepath.FromSlash(path + "/model/entity/issue_2746.go")
|
|
||||||
expectContent = gtest.DataContent(`issue`, `2746`, `issue_2746.go`)
|
|
||||||
)
|
|
||||||
t.Assert(expectContent, gfile.GetContents(file))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://github.com/gogf/gf/issues/3459
|
|
||||||
func Test_Gen_Dao_Issue3459(t *testing.T) {
|
|
||||||
gtest.C(t, func(t *gtest.T) {
|
|
||||||
var (
|
|
||||||
err error
|
|
||||||
db = testDB
|
|
||||||
table = "table_user"
|
|
||||||
sqlContent = fmt.Sprintf(
|
|
||||||
gtest.DataContent(`gendao`, `user.tpl.sql`),
|
|
||||||
table,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
dropTableWithDb(db, table)
|
|
||||||
array := gstr.SplitAndTrim(sqlContent, ";")
|
|
||||||
for _, v := range array {
|
|
||||||
if _, err = db.Exec(ctx, v); err != nil {
|
|
||||||
t.AssertNil(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
defer dropTableWithDb(db, table)
|
|
||||||
|
|
||||||
var (
|
|
||||||
confDir = gtest.DataPath("issue", "3459")
|
|
||||||
path = gfile.Temp(guid.S())
|
|
||||||
group = "test"
|
|
||||||
in = gendao.CGenDaoInput{
|
|
||||||
Path: path,
|
|
||||||
Link: link,
|
|
||||||
Tables: "",
|
|
||||||
TablesEx: "",
|
|
||||||
Group: group,
|
|
||||||
Prefix: "",
|
|
||||||
RemovePrefix: "",
|
|
||||||
JsonCase: "SnakeScreaming",
|
|
||||||
ImportPrefix: "",
|
|
||||||
DaoPath: "",
|
|
||||||
DoPath: "",
|
|
||||||
EntityPath: "",
|
|
||||||
TplDaoIndexPath: "",
|
|
||||||
TplDaoInternalPath: "",
|
|
||||||
TplDaoDoPath: "",
|
|
||||||
TplDaoEntityPath: "",
|
|
||||||
StdTime: false,
|
|
||||||
WithTime: false,
|
|
||||||
GJsonSupport: false,
|
|
||||||
OverwriteDao: false,
|
|
||||||
DescriptionTag: false,
|
|
||||||
NoJsonTag: false,
|
|
||||||
NoModelComment: false,
|
|
||||||
Clear: false,
|
|
||||||
GenTable: false,
|
|
||||||
TypeMapping: nil,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
err = g.Cfg().GetAdapter().(*gcfg.AdapterFile).SetPath(confDir)
|
|
||||||
t.AssertNil(err)
|
|
||||||
|
|
||||||
err = gutil.FillStructWithDefault(&in)
|
|
||||||
t.AssertNil(err)
|
|
||||||
|
|
||||||
err = gfile.Mkdir(path)
|
|
||||||
t.AssertNil(err)
|
|
||||||
|
|
||||||
// for go mod import path auto retrieve.
|
|
||||||
err = gfile.Copy(
|
|
||||||
gtest.DataPath("gendao", "go.mod.txt"),
|
|
||||||
gfile.Join(path, "go.mod"),
|
|
||||||
)
|
|
||||||
t.AssertNil(err)
|
|
||||||
|
|
||||||
_, err = gendao.CGenDao{}.Dao(ctx, in)
|
|
||||||
t.AssertNil(err)
|
|
||||||
defer gfile.Remove(path)
|
|
||||||
|
|
||||||
// files
|
|
||||||
files, err := gfile.ScanDir(path, "*.go", true)
|
|
||||||
t.AssertNil(err)
|
|
||||||
t.Assert(files, []string{
|
|
||||||
filepath.FromSlash(path + "/dao/internal/table_user.go"),
|
|
||||||
filepath.FromSlash(path + "/dao/table_user.go"),
|
|
||||||
filepath.FromSlash(path + "/model/do/table_user.go"),
|
|
||||||
filepath.FromSlash(path + "/model/entity/table_user.go"),
|
|
||||||
})
|
|
||||||
// content
|
|
||||||
testPath := gtest.DataPath("gendao", "generated_user")
|
|
||||||
expectFiles := []string{
|
|
||||||
filepath.FromSlash(testPath + "/dao/internal/table_user.go"),
|
|
||||||
filepath.FromSlash(testPath + "/dao/table_user.go"),
|
|
||||||
filepath.FromSlash(testPath + "/model/do/table_user.go"),
|
|
||||||
filepath.FromSlash(testPath + "/model/entity/table_user.go"),
|
|
||||||
}
|
|
||||||
for i := range files {
|
|
||||||
//_ = gfile.PutContents(expectFiles[i], gfile.GetContents(files[i]))
|
|
||||||
t.Assert(gfile.GetContents(files[i]), gfile.GetContents(expectFiles[i]))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://github.com/gogf/gf/issues/3749
|
|
||||||
func Test_Gen_Dao_Issue3749(t *testing.T) {
|
|
||||||
gtest.C(t, func(t *gtest.T) {
|
|
||||||
var (
|
|
||||||
err error
|
|
||||||
db = testDB
|
|
||||||
table = "table_user"
|
|
||||||
sqlContent = fmt.Sprintf(
|
|
||||||
gtest.DataContent(`issue`, `3749`, `user.tpl.sql`),
|
|
||||||
table,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
dropTableWithDb(db, table)
|
|
||||||
array := gstr.SplitAndTrim(sqlContent, ";")
|
|
||||||
for _, v := range array {
|
|
||||||
if _, err = db.Exec(ctx, v); err != nil {
|
|
||||||
t.AssertNil(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
defer dropTableWithDb(db, table)
|
|
||||||
|
|
||||||
var (
|
|
||||||
path = gfile.Temp(guid.S())
|
|
||||||
group = "test"
|
|
||||||
in = gendao.CGenDaoInput{
|
|
||||||
Path: path,
|
|
||||||
Link: link,
|
|
||||||
Group: group,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
err = gutil.FillStructWithDefault(&in)
|
|
||||||
t.AssertNil(err)
|
|
||||||
|
|
||||||
err = gfile.Mkdir(path)
|
|
||||||
t.AssertNil(err)
|
|
||||||
|
|
||||||
// for go mod import path auto retrieve.
|
|
||||||
err = gfile.Copy(
|
|
||||||
gtest.DataPath("gendao", "go.mod.txt"),
|
|
||||||
gfile.Join(path, "go.mod"),
|
|
||||||
)
|
|
||||||
t.AssertNil(err)
|
|
||||||
|
|
||||||
_, err = gendao.CGenDao{}.Dao(ctx, in)
|
|
||||||
t.AssertNil(err)
|
|
||||||
defer gfile.Remove(path)
|
|
||||||
|
|
||||||
// files
|
|
||||||
files, err := gfile.ScanDir(path, "*.go", true)
|
|
||||||
t.AssertNil(err)
|
|
||||||
t.Assert(files, []string{
|
|
||||||
filepath.FromSlash(path + "/dao/internal/table_user.go"),
|
|
||||||
filepath.FromSlash(path + "/dao/table_user.go"),
|
|
||||||
filepath.FromSlash(path + "/model/do/table_user.go"),
|
|
||||||
filepath.FromSlash(path + "/model/entity/table_user.go"),
|
|
||||||
})
|
|
||||||
// content
|
|
||||||
testPath := gtest.DataPath(`issue`, `3749`)
|
|
||||||
expectFiles := []string{
|
|
||||||
filepath.FromSlash(testPath + "/dao/internal/table_user.go"),
|
|
||||||
filepath.FromSlash(testPath + "/dao/table_user.go"),
|
|
||||||
filepath.FromSlash(testPath + "/model/do/table_user.go"),
|
|
||||||
filepath.FromSlash(testPath + "/model/entity/table_user.go"),
|
|
||||||
}
|
|
||||||
for i := range files {
|
|
||||||
//_ = gfile.PutContents(expectFiles[i], gfile.GetContents(files[i]))
|
|
||||||
t.Assert(gfile.GetContents(files[i]), gfile.GetContents(expectFiles[i]))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
@ -1,89 +0,0 @@
|
|||||||
// 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 (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/gogf/gf/v2/os/gfile"
|
|
||||||
"github.com/gogf/gf/v2/test/gtest"
|
|
||||||
"github.com/gogf/gf/v2/text/gstr"
|
|
||||||
"github.com/gogf/gf/v2/util/guid"
|
|
||||||
"github.com/gogf/gf/v2/util/gutil"
|
|
||||||
|
|
||||||
"github.com/gogf/gf/cmd/gf/v2/internal/cmd/gendao"
|
|
||||||
)
|
|
||||||
|
|
||||||
func Test_Gen_Dao_Sharding(t *testing.T) {
|
|
||||||
gtest.C(t, func(t *gtest.T) {
|
|
||||||
var (
|
|
||||||
err error
|
|
||||||
db = testDB
|
|
||||||
tableSingle = "single_table"
|
|
||||||
table1 = "users_0001"
|
|
||||||
table2 = "users_0002"
|
|
||||||
table3 = "orders_0001"
|
|
||||||
table4 = "orders_0002"
|
|
||||||
sqlFilePath = gtest.DataPath(`gendao`, `sharding`, `sharding.sql`)
|
|
||||||
)
|
|
||||||
dropTableWithDb(db, tableSingle)
|
|
||||||
dropTableWithDb(db, table1)
|
|
||||||
dropTableWithDb(db, table2)
|
|
||||||
dropTableWithDb(db, table3)
|
|
||||||
dropTableWithDb(db, table4)
|
|
||||||
t.AssertNil(execSqlFile(db, sqlFilePath))
|
|
||||||
defer dropTableWithDb(db, tableSingle)
|
|
||||||
defer dropTableWithDb(db, table1)
|
|
||||||
defer dropTableWithDb(db, table2)
|
|
||||||
defer dropTableWithDb(db, table3)
|
|
||||||
defer dropTableWithDb(db, table4)
|
|
||||||
|
|
||||||
var (
|
|
||||||
path = gfile.Temp(guid.S())
|
|
||||||
// path = "/Users/john/Temp/gen_dao_sharding"
|
|
||||||
group = "test"
|
|
||||||
in = gendao.CGenDaoInput{
|
|
||||||
Path: path,
|
|
||||||
Link: link,
|
|
||||||
Group: group,
|
|
||||||
Prefix: "",
|
|
||||||
ShardingPattern: []string{
|
|
||||||
`users_?`,
|
|
||||||
`orders_?`,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
)
|
|
||||||
err = gutil.FillStructWithDefault(&in)
|
|
||||||
t.AssertNil(err)
|
|
||||||
|
|
||||||
err = gfile.Mkdir(path)
|
|
||||||
t.AssertNil(err)
|
|
||||||
|
|
||||||
pwd := gfile.Pwd()
|
|
||||||
err = gfile.Chdir(path)
|
|
||||||
t.AssertNil(err)
|
|
||||||
defer gfile.Chdir(pwd)
|
|
||||||
defer gfile.RemoveAll(path)
|
|
||||||
|
|
||||||
_, err = gendao.CGenDao{}.Dao(ctx, in)
|
|
||||||
t.AssertNil(err)
|
|
||||||
|
|
||||||
generatedFiles, err := gfile.ScanDir(path, "*.go", true)
|
|
||||||
t.AssertNil(err)
|
|
||||||
t.Assert(len(generatedFiles), 12)
|
|
||||||
var (
|
|
||||||
daoSingleTableContent = gfile.GetContents(gfile.Join(path, "dao", "single_table.go"))
|
|
||||||
daoUsersContent = gfile.GetContents(gfile.Join(path, "dao", "users.go"))
|
|
||||||
daoOrdersContent = gfile.GetContents(gfile.Join(path, "dao", "orders.go"))
|
|
||||||
)
|
|
||||||
t.Assert(gstr.Contains(daoSingleTableContent, "SingleTable = singleTableDao{internal.NewSingleTableDao()}"), true)
|
|
||||||
t.Assert(gstr.Contains(daoUsersContent, "Users = usersDao{internal.NewUsersDao(usersShardingHandler)}"), true)
|
|
||||||
t.Assert(gstr.Contains(daoUsersContent, "m.Sharding(gdb.ShardingConfig{"), true)
|
|
||||||
t.Assert(gstr.Contains(daoOrdersContent, "Orders = ordersDao{internal.NewOrdersDao(ordersShardingHandler)}"), true)
|
|
||||||
t.Assert(gstr.Contains(daoOrdersContent, "m.Sharding(gdb.ShardingConfig{"), true)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
@ -1,90 +0,0 @@
|
|||||||
// 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 (
|
|
||||||
"path/filepath"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/gogf/gf/v2/os/gfile"
|
|
||||||
"github.com/gogf/gf/v2/test/gtest"
|
|
||||||
"github.com/gogf/gf/v2/text/gstr"
|
|
||||||
"github.com/gogf/gf/v2/util/guid"
|
|
||||||
|
|
||||||
"github.com/gogf/gf/cmd/gf/v2/internal/cmd/genpb"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestGenPbIssue3882(t *testing.T) {
|
|
||||||
gtest.C(t, func(t *gtest.T) {
|
|
||||||
var (
|
|
||||||
outputPath = gfile.Temp(guid.S())
|
|
||||||
outputApiPath = filepath.Join(outputPath, "api")
|
|
||||||
outputCtrlPath = filepath.Join(outputPath, "controller")
|
|
||||||
|
|
||||||
protobufFolder = gtest.DataPath("issue", "3882")
|
|
||||||
in = genpb.CGenPbInput{
|
|
||||||
Path: protobufFolder,
|
|
||||||
OutputApi: outputApiPath,
|
|
||||||
OutputCtrl: outputCtrlPath,
|
|
||||||
}
|
|
||||||
err error
|
|
||||||
)
|
|
||||||
err = gfile.Mkdir(outputApiPath)
|
|
||||||
t.AssertNil(err)
|
|
||||||
err = gfile.Mkdir(outputCtrlPath)
|
|
||||||
t.AssertNil(err)
|
|
||||||
defer gfile.Remove(outputPath)
|
|
||||||
|
|
||||||
_, err = genpb.CGenPb{}.Pb(ctx, in)
|
|
||||||
t.AssertNil(err)
|
|
||||||
|
|
||||||
var (
|
|
||||||
genContent = gfile.GetContents(filepath.Join(outputApiPath, "issue3882.pb.go"))
|
|
||||||
exceptText = `dc:"Some comment on field with 'one' 'two' 'three' in the comment."`
|
|
||||||
)
|
|
||||||
t.Assert(gstr.Contains(genContent, exceptText), true)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// This issue only occurs when executing multiple times
|
|
||||||
// and the subsequent OutputApi is the parent directory of the previous execution
|
|
||||||
func TestGenPbIssue3953(t *testing.T) {
|
|
||||||
gtest.C(t, func(t *gtest.T) {
|
|
||||||
var (
|
|
||||||
outputPath = gfile.Temp("f" + guid.S())
|
|
||||||
outputApiPath = filepath.Join(outputPath, "api")
|
|
||||||
outputCtrlPath = filepath.Join(outputPath, "controller")
|
|
||||||
|
|
||||||
protobufFolder = gtest.DataPath("issue", "3953")
|
|
||||||
in = genpb.CGenPbInput{
|
|
||||||
Path: protobufFolder,
|
|
||||||
OutputApi: outputApiPath,
|
|
||||||
OutputCtrl: outputCtrlPath,
|
|
||||||
}
|
|
||||||
err error
|
|
||||||
)
|
|
||||||
err = gfile.Mkdir(outputApiPath)
|
|
||||||
t.AssertNil(err)
|
|
||||||
err = gfile.Mkdir(outputCtrlPath)
|
|
||||||
t.AssertNil(err)
|
|
||||||
defer gfile.Remove(outputPath)
|
|
||||||
|
|
||||||
_, err = genpb.CGenPb{}.Pb(ctx, in)
|
|
||||||
// do twice,and set outputApi to outputPath
|
|
||||||
in.OutputApi = outputPath
|
|
||||||
_, err = genpb.CGenPb{}.Pb(ctx, in)
|
|
||||||
t.AssertNil(err)
|
|
||||||
|
|
||||||
var (
|
|
||||||
genContent = gfile.GetContents(filepath.Join(outputApiPath, "issue3953.pb.go"))
|
|
||||||
// The old version would have appeared `v:"required" v:"required"`
|
|
||||||
// but the new version of the code will appear `v:"required"` only once
|
|
||||||
notExceptText = `v:"required" v:"required"`
|
|
||||||
)
|
|
||||||
t.Assert(gstr.Contains(genContent, notExceptText), false)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
@ -1,511 +0,0 @@
|
|||||||
// 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 (
|
|
||||||
"fmt"
|
|
||||||
"path/filepath"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/gogf/gf/v2/os/gfile"
|
|
||||||
"github.com/gogf/gf/v2/test/gtest"
|
|
||||||
"github.com/gogf/gf/v2/text/gstr"
|
|
||||||
"github.com/gogf/gf/v2/util/guid"
|
|
||||||
"github.com/gogf/gf/v2/util/gutil"
|
|
||||||
|
|
||||||
"github.com/gogf/gf/cmd/gf/v2/internal/cmd/genpbentity"
|
|
||||||
)
|
|
||||||
|
|
||||||
func Test_Gen_Pbentity_Default(t *testing.T) {
|
|
||||||
gtest.C(t, func(t *gtest.T) {
|
|
||||||
var (
|
|
||||||
err error
|
|
||||||
db = testDB
|
|
||||||
table = "table_user"
|
|
||||||
sqlContent = fmt.Sprintf(
|
|
||||||
gtest.DataContent(`genpbentity`, `user.tpl.sql`),
|
|
||||||
table,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
dropTableWithDb(db, table)
|
|
||||||
array := gstr.SplitAndTrim(sqlContent, ";")
|
|
||||||
for _, v := range array {
|
|
||||||
if _, err = db.Exec(ctx, v); err != nil {
|
|
||||||
t.AssertNil(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
defer dropTableWithDb(db, table)
|
|
||||||
|
|
||||||
var (
|
|
||||||
path = gfile.Temp(guid.S())
|
|
||||||
in = genpbentity.CGenPbEntityInput{
|
|
||||||
Path: path,
|
|
||||||
Package: "unittest",
|
|
||||||
Link: link,
|
|
||||||
Tables: "",
|
|
||||||
Prefix: "",
|
|
||||||
RemovePrefix: "",
|
|
||||||
RemoveFieldPrefix: "",
|
|
||||||
NameCase: "",
|
|
||||||
JsonCase: "",
|
|
||||||
Option: "",
|
|
||||||
TypeMapping: nil,
|
|
||||||
FieldMapping: nil,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
err = gutil.FillStructWithDefault(&in)
|
|
||||||
t.AssertNil(err)
|
|
||||||
|
|
||||||
err = gfile.Mkdir(path)
|
|
||||||
t.AssertNil(err)
|
|
||||||
defer gfile.Remove(path)
|
|
||||||
|
|
||||||
_, err = genpbentity.CGenPbEntity{}.PbEntity(ctx, in)
|
|
||||||
t.AssertNil(err)
|
|
||||||
|
|
||||||
// files
|
|
||||||
files, err := gfile.ScanDir(path, "*.proto", false)
|
|
||||||
t.AssertNil(err)
|
|
||||||
t.Assert(files, []string{
|
|
||||||
path + filepath.FromSlash("/table_user.proto"),
|
|
||||||
})
|
|
||||||
|
|
||||||
// contents
|
|
||||||
testPath := gtest.DataPath("genpbentity", "generated")
|
|
||||||
expectFiles := []string{
|
|
||||||
testPath + filepath.FromSlash("/table_user.proto"),
|
|
||||||
}
|
|
||||||
for i := range files {
|
|
||||||
t.Assert(gfile.GetContents(files[i]), gfile.GetContents(expectFiles[i]))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_Gen_Pbentity_NameCase_SnakeScreaming(t *testing.T) {
|
|
||||||
gtest.C(t, func(t *gtest.T) {
|
|
||||||
var (
|
|
||||||
err error
|
|
||||||
db = testDB
|
|
||||||
table = "table_user"
|
|
||||||
sqlContent = fmt.Sprintf(
|
|
||||||
gtest.DataContent(`genpbentity`, `user.tpl.sql`),
|
|
||||||
table,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
dropTableWithDb(db, table)
|
|
||||||
array := gstr.SplitAndTrim(sqlContent, ";")
|
|
||||||
for _, v := range array {
|
|
||||||
if _, err = db.Exec(ctx, v); err != nil {
|
|
||||||
t.AssertNil(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
defer dropTableWithDb(db, table)
|
|
||||||
|
|
||||||
var (
|
|
||||||
path = gfile.Temp(guid.S())
|
|
||||||
in = genpbentity.CGenPbEntityInput{
|
|
||||||
Path: path,
|
|
||||||
Package: "unittest",
|
|
||||||
Link: link,
|
|
||||||
Tables: "",
|
|
||||||
Prefix: "",
|
|
||||||
RemovePrefix: "",
|
|
||||||
RemoveFieldPrefix: "",
|
|
||||||
NameCase: "SnakeScreaming",
|
|
||||||
JsonCase: "",
|
|
||||||
Option: "",
|
|
||||||
TypeMapping: nil,
|
|
||||||
FieldMapping: nil,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
err = gutil.FillStructWithDefault(&in)
|
|
||||||
t.AssertNil(err)
|
|
||||||
|
|
||||||
err = gfile.Mkdir(path)
|
|
||||||
t.AssertNil(err)
|
|
||||||
defer gfile.Remove(path)
|
|
||||||
|
|
||||||
_, err = genpbentity.CGenPbEntity{}.PbEntity(ctx, in)
|
|
||||||
t.AssertNil(err)
|
|
||||||
|
|
||||||
// files
|
|
||||||
files, err := gfile.ScanDir(path, "*.proto", false)
|
|
||||||
t.AssertNil(err)
|
|
||||||
t.Assert(files, []string{
|
|
||||||
path + filepath.FromSlash("/table_user.proto"),
|
|
||||||
})
|
|
||||||
|
|
||||||
// contents
|
|
||||||
testPath := gtest.DataPath("genpbentity", "generated")
|
|
||||||
expectFiles := []string{
|
|
||||||
testPath + filepath.FromSlash("/table_user_snake_screaming.proto"),
|
|
||||||
}
|
|
||||||
for i := range files {
|
|
||||||
t.Assert(gfile.GetContents(files[i]), gfile.GetContents(expectFiles[i]))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://github.com/gogf/gf/issues/3545
|
|
||||||
func Test_Issue_3545(t *testing.T) {
|
|
||||||
gtest.C(t, func(t *gtest.T) {
|
|
||||||
var (
|
|
||||||
err error
|
|
||||||
db = testDB
|
|
||||||
table = "table_user"
|
|
||||||
sqlContent = fmt.Sprintf(
|
|
||||||
gtest.DataContent(`genpbentity`, `user.tpl.sql`),
|
|
||||||
table,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
dropTableWithDb(db, table)
|
|
||||||
array := gstr.SplitAndTrim(sqlContent, ";")
|
|
||||||
for _, v := range array {
|
|
||||||
if _, err = db.Exec(ctx, v); err != nil {
|
|
||||||
t.AssertNil(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
defer dropTableWithDb(db, table)
|
|
||||||
|
|
||||||
var (
|
|
||||||
path = gfile.Temp(guid.S())
|
|
||||||
in = genpbentity.CGenPbEntityInput{
|
|
||||||
Path: path,
|
|
||||||
Package: "",
|
|
||||||
Link: link,
|
|
||||||
Tables: "",
|
|
||||||
Prefix: "",
|
|
||||||
RemovePrefix: "",
|
|
||||||
RemoveFieldPrefix: "",
|
|
||||||
NameCase: "",
|
|
||||||
JsonCase: "",
|
|
||||||
Option: "",
|
|
||||||
TypeMapping: nil,
|
|
||||||
FieldMapping: nil,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
err = gutil.FillStructWithDefault(&in)
|
|
||||||
t.AssertNil(err)
|
|
||||||
|
|
||||||
err = gfile.Mkdir(path)
|
|
||||||
t.AssertNil(err)
|
|
||||||
defer gfile.Remove(path)
|
|
||||||
|
|
||||||
_, err = genpbentity.CGenPbEntity{}.PbEntity(ctx, in)
|
|
||||||
t.AssertNil(err)
|
|
||||||
|
|
||||||
// files
|
|
||||||
files, err := gfile.ScanDir(path, "*.proto", false)
|
|
||||||
t.AssertNil(err)
|
|
||||||
t.Assert(files, []string{
|
|
||||||
path + filepath.FromSlash("/table_user.proto"),
|
|
||||||
})
|
|
||||||
|
|
||||||
// contents
|
|
||||||
testPath := gtest.DataPath("issue", "3545")
|
|
||||||
expectFiles := []string{
|
|
||||||
testPath + filepath.FromSlash("/table_user.proto"),
|
|
||||||
}
|
|
||||||
for i := range files {
|
|
||||||
t.Assert(gfile.GetContents(files[i]), gfile.GetContents(expectFiles[i]))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://github.com/gogf/gf/issues/3685
|
|
||||||
func Test_Issue_3685(t *testing.T) {
|
|
||||||
gtest.C(t, func(t *gtest.T) {
|
|
||||||
var (
|
|
||||||
err error
|
|
||||||
db = testDB
|
|
||||||
table = "table_user"
|
|
||||||
sqlContent = fmt.Sprintf(
|
|
||||||
gtest.DataContent(`issue`, `3685`, `user.tpl.sql`),
|
|
||||||
table,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
dropTableWithDb(db, table)
|
|
||||||
array := gstr.SplitAndTrim(sqlContent, ";")
|
|
||||||
for _, v := range array {
|
|
||||||
if _, err = db.Exec(ctx, v); err != nil {
|
|
||||||
t.AssertNil(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
defer dropTableWithDb(db, table)
|
|
||||||
|
|
||||||
var (
|
|
||||||
path = gfile.Temp(guid.S())
|
|
||||||
in = genpbentity.CGenPbEntityInput{
|
|
||||||
Path: path,
|
|
||||||
Package: "",
|
|
||||||
Link: link,
|
|
||||||
Tables: "",
|
|
||||||
Prefix: "",
|
|
||||||
RemovePrefix: "",
|
|
||||||
RemoveFieldPrefix: "",
|
|
||||||
NameCase: "",
|
|
||||||
JsonCase: "",
|
|
||||||
Option: "",
|
|
||||||
TypeMapping: map[genpbentity.DBFieldTypeName]genpbentity.CustomAttributeType{
|
|
||||||
"json": {
|
|
||||||
Type: "google.protobuf.Value",
|
|
||||||
Import: "google/protobuf/struct.proto",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
FieldMapping: nil,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
err = gutil.FillStructWithDefault(&in)
|
|
||||||
t.AssertNil(err)
|
|
||||||
|
|
||||||
err = gfile.Mkdir(path)
|
|
||||||
t.AssertNil(err)
|
|
||||||
defer gfile.Remove(path)
|
|
||||||
|
|
||||||
_, err = genpbentity.CGenPbEntity{}.PbEntity(ctx, in)
|
|
||||||
t.AssertNil(err)
|
|
||||||
|
|
||||||
// files
|
|
||||||
files, err := gfile.ScanDir(path, "*.proto", false)
|
|
||||||
t.AssertNil(err)
|
|
||||||
t.Assert(files, []string{
|
|
||||||
path + filepath.FromSlash("/table_user.proto"),
|
|
||||||
})
|
|
||||||
|
|
||||||
// contents
|
|
||||||
testPath := gtest.DataPath("issue", "3685")
|
|
||||||
expectFiles := []string{
|
|
||||||
testPath + filepath.FromSlash("/table_user.proto"),
|
|
||||||
}
|
|
||||||
for i := range files {
|
|
||||||
t.Assert(gfile.GetContents(files[i]), gfile.GetContents(expectFiles[i]))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://github.com/gogf/gf/issues/3955
|
|
||||||
func Test_Issue_3955(t *testing.T) {
|
|
||||||
gtest.C(t, func(t *gtest.T) {
|
|
||||||
var (
|
|
||||||
err error
|
|
||||||
db = testDB
|
|
||||||
table1 = "table_user_a"
|
|
||||||
table2 = "table_user_b"
|
|
||||||
sqlContent = fmt.Sprintf(
|
|
||||||
gtest.DataContent(`genpbentity`, `user.tpl.sql`),
|
|
||||||
table1,
|
|
||||||
)
|
|
||||||
sqlContent2 = fmt.Sprintf(
|
|
||||||
gtest.DataContent(`genpbentity`, `user.tpl.sql`),
|
|
||||||
table2,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
dropTableWithDb(db, table1)
|
|
||||||
dropTableWithDb(db, table2)
|
|
||||||
|
|
||||||
array := gstr.SplitAndTrim(sqlContent, ";")
|
|
||||||
for _, v := range array {
|
|
||||||
if _, err = db.Exec(ctx, v); err != nil {
|
|
||||||
t.AssertNil(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
array = gstr.SplitAndTrim(sqlContent2, ";")
|
|
||||||
for _, v := range array {
|
|
||||||
if _, err = db.Exec(ctx, v); err != nil {
|
|
||||||
t.AssertNil(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
defer dropTableWithDb(db, table1)
|
|
||||||
defer dropTableWithDb(db, table2)
|
|
||||||
|
|
||||||
var (
|
|
||||||
path = gfile.Temp(guid.S())
|
|
||||||
in = genpbentity.CGenPbEntityInput{
|
|
||||||
Path: path,
|
|
||||||
Package: "unittest",
|
|
||||||
Link: link,
|
|
||||||
Tables: "",
|
|
||||||
Prefix: "",
|
|
||||||
RemovePrefix: "",
|
|
||||||
RemoveFieldPrefix: "",
|
|
||||||
NameCase: "",
|
|
||||||
JsonCase: "",
|
|
||||||
Option: "",
|
|
||||||
TablesEx: "table_user_a",
|
|
||||||
}
|
|
||||||
)
|
|
||||||
err = gutil.FillStructWithDefault(&in)
|
|
||||||
t.AssertNil(err)
|
|
||||||
|
|
||||||
err = gfile.Mkdir(path)
|
|
||||||
t.AssertNil(err)
|
|
||||||
defer gfile.Remove(path)
|
|
||||||
|
|
||||||
_, err = genpbentity.CGenPbEntity{}.PbEntity(ctx, in)
|
|
||||||
t.AssertNil(err)
|
|
||||||
|
|
||||||
files, err := gfile.ScanDir(path, "*.proto", false)
|
|
||||||
t.AssertNil(err)
|
|
||||||
|
|
||||||
t.AssertEQ(len(files), 1)
|
|
||||||
|
|
||||||
t.Assert(files, []string{
|
|
||||||
path + filepath.FromSlash("/table_user_b.proto"),
|
|
||||||
})
|
|
||||||
|
|
||||||
expectFiles := []string{
|
|
||||||
path + filepath.FromSlash("/table_user_b.proto"),
|
|
||||||
}
|
|
||||||
for i := range files {
|
|
||||||
t.Assert(gfile.GetContents(files[i]), gfile.GetContents(expectFiles[i]))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_Issue_4330_TypeMapping_Ineffective(t *testing.T) {
|
|
||||||
gtest.C(t, func(t *gtest.T) {
|
|
||||||
var (
|
|
||||||
err error
|
|
||||||
db = testDB
|
|
||||||
table = "table_user"
|
|
||||||
sqlContent = fmt.Sprintf(
|
|
||||||
gtest.DataContent(`issue`, `3685`, `user.tpl.sql`),
|
|
||||||
table,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
dropTableWithDb(db, table)
|
|
||||||
array := gstr.SplitAndTrim(sqlContent, ";")
|
|
||||||
for _, v := range array {
|
|
||||||
if _, err = db.Exec(ctx, v); err != nil {
|
|
||||||
t.AssertNil(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
defer dropTableWithDb(db, table)
|
|
||||||
|
|
||||||
var (
|
|
||||||
path = gfile.Temp(guid.S())
|
|
||||||
in = genpbentity.CGenPbEntityInput{
|
|
||||||
Path: path,
|
|
||||||
Package: "",
|
|
||||||
Link: link,
|
|
||||||
Tables: "",
|
|
||||||
Prefix: "",
|
|
||||||
RemovePrefix: "",
|
|
||||||
RemoveFieldPrefix: "",
|
|
||||||
NameCase: "",
|
|
||||||
JsonCase: "",
|
|
||||||
Option: "",
|
|
||||||
TypeMapping: map[genpbentity.DBFieldTypeName]genpbentity.CustomAttributeType{
|
|
||||||
"json": {
|
|
||||||
Type: "google.protobuf.Value",
|
|
||||||
Import: "google/protobuf/struct.proto",
|
|
||||||
},
|
|
||||||
"decimal": {
|
|
||||||
Type: "double",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
FieldMapping: nil,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
err = gutil.FillStructWithDefault(&in)
|
|
||||||
t.AssertNil(err)
|
|
||||||
|
|
||||||
err = gfile.Mkdir(path)
|
|
||||||
t.AssertNil(err)
|
|
||||||
defer gfile.Remove(path)
|
|
||||||
|
|
||||||
_, err = genpbentity.CGenPbEntity{}.PbEntity(ctx, in)
|
|
||||||
t.AssertNil(err)
|
|
||||||
|
|
||||||
// files
|
|
||||||
files, err := gfile.ScanDir(path, "*.proto", false)
|
|
||||||
t.AssertNil(err)
|
|
||||||
t.Assert(files, []string{
|
|
||||||
path + filepath.FromSlash("/table_user.proto"),
|
|
||||||
})
|
|
||||||
|
|
||||||
// contents
|
|
||||||
testPath := gtest.DataPath("issue", "4330")
|
|
||||||
expectFiles := []string{
|
|
||||||
testPath + filepath.FromSlash("/issue4330_double.proto"),
|
|
||||||
}
|
|
||||||
for i := range files {
|
|
||||||
t.Assert(gfile.GetContents(files[i]), gfile.GetContents(expectFiles[i]))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func Test_Gen_Pbentity_Sharding(t *testing.T) {
|
|
||||||
gtest.C(t, func(t *gtest.T) {
|
|
||||||
var (
|
|
||||||
err error
|
|
||||||
db = testDB
|
|
||||||
tableSingle = "single_table"
|
|
||||||
table1 = "users_0001"
|
|
||||||
table2 = "users_0002"
|
|
||||||
table3 = "orders_0001"
|
|
||||||
table4 = "orders_0002"
|
|
||||||
sqlFilePath = gtest.DataPath(`gendao`, `sharding`, `sharding.sql`)
|
|
||||||
)
|
|
||||||
dropTableWithDb(db, tableSingle)
|
|
||||||
dropTableWithDb(db, table1)
|
|
||||||
dropTableWithDb(db, table2)
|
|
||||||
dropTableWithDb(db, table3)
|
|
||||||
dropTableWithDb(db, table4)
|
|
||||||
t.AssertNil(execSqlFile(db, sqlFilePath))
|
|
||||||
defer dropTableWithDb(db, tableSingle)
|
|
||||||
defer dropTableWithDb(db, table1)
|
|
||||||
defer dropTableWithDb(db, table2)
|
|
||||||
defer dropTableWithDb(db, table3)
|
|
||||||
defer dropTableWithDb(db, table4)
|
|
||||||
|
|
||||||
var (
|
|
||||||
path = gfile.Temp(guid.S())
|
|
||||||
in = genpbentity.CGenPbEntityInput{
|
|
||||||
Path: path,
|
|
||||||
Package: "unittest",
|
|
||||||
Link: link,
|
|
||||||
Tables: "",
|
|
||||||
RemovePrefix: "",
|
|
||||||
RemoveFieldPrefix: "",
|
|
||||||
NameCase: "",
|
|
||||||
JsonCase: "",
|
|
||||||
Option: "",
|
|
||||||
TypeMapping: nil,
|
|
||||||
FieldMapping: nil,
|
|
||||||
ShardingPattern: []string{
|
|
||||||
`users_?`,
|
|
||||||
`orders_?`,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
)
|
|
||||||
err = gutil.FillStructWithDefault(&in)
|
|
||||||
t.AssertNil(err)
|
|
||||||
|
|
||||||
err = gfile.Mkdir(path)
|
|
||||||
t.AssertNil(err)
|
|
||||||
defer gfile.Remove(path)
|
|
||||||
|
|
||||||
_, err = genpbentity.CGenPbEntity{}.PbEntity(ctx, in)
|
|
||||||
t.AssertNil(err)
|
|
||||||
|
|
||||||
// files
|
|
||||||
t.AssertNil(err)
|
|
||||||
generatedFiles, err := gfile.ScanDir(path, "*.proto", true)
|
|
||||||
t.Assert(len(generatedFiles), 3)
|
|
||||||
var (
|
|
||||||
msgSingleTableContent = gfile.GetContents(gfile.Join(path, "single_table.proto"))
|
|
||||||
msgUsersContent = gfile.GetContents(gfile.Join(path, "users.proto"))
|
|
||||||
msgOrdersContent = gfile.GetContents(gfile.Join(path, "orders.proto"))
|
|
||||||
)
|
|
||||||
t.Assert(gstr.Contains(msgSingleTableContent, "message SingleTable {"), true)
|
|
||||||
t.Assert(gstr.Contains(msgUsersContent, "message Users {"), true)
|
|
||||||
t.Assert(gstr.Contains(msgOrdersContent, "message Orders {"), true)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
@ -1,158 +0,0 @@
|
|||||||
// 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 (
|
|
||||||
"path/filepath"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/gogf/gf/v2/os/gfile"
|
|
||||||
"github.com/gogf/gf/v2/test/gtest"
|
|
||||||
"github.com/gogf/gf/v2/util/guid"
|
|
||||||
"github.com/gogf/gf/v2/util/gutil"
|
|
||||||
|
|
||||||
"github.com/gogf/gf/cmd/gf/v2/internal/cmd/genservice"
|
|
||||||
)
|
|
||||||
|
|
||||||
func Test_Gen_Service_Default(t *testing.T) {
|
|
||||||
gtest.C(t, func(t *gtest.T) {
|
|
||||||
var (
|
|
||||||
path = gfile.Temp(guid.S())
|
|
||||||
dstFolder = path + filepath.FromSlash("/service")
|
|
||||||
srvFolder = gtest.DataPath("genservice", "logic")
|
|
||||||
in = genservice.CGenServiceInput{
|
|
||||||
SrcFolder: srvFolder,
|
|
||||||
DstFolder: dstFolder,
|
|
||||||
DstFileNameCase: "Snake",
|
|
||||||
WatchFile: "",
|
|
||||||
StPattern: "",
|
|
||||||
Packages: nil,
|
|
||||||
ImportPrefix: "",
|
|
||||||
Clear: false,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
err := gutil.FillStructWithDefault(&in)
|
|
||||||
t.AssertNil(err)
|
|
||||||
|
|
||||||
err = gfile.Mkdir(path)
|
|
||||||
t.AssertNil(err)
|
|
||||||
defer gfile.Remove(path)
|
|
||||||
|
|
||||||
_, err = genservice.CGenService{}.Service(ctx, in)
|
|
||||||
t.AssertNil(err)
|
|
||||||
|
|
||||||
// logic file
|
|
||||||
var (
|
|
||||||
genSrv = srvFolder + filepath.FromSlash("/logic.go")
|
|
||||||
genSrvExpect = srvFolder + filepath.FromSlash("/logic_expect.go")
|
|
||||||
)
|
|
||||||
defer gfile.Remove(genSrv)
|
|
||||||
t.Assert(gfile.GetContents(genSrv), gfile.GetContents(genSrvExpect))
|
|
||||||
|
|
||||||
// files
|
|
||||||
files, err := gfile.ScanDir(dstFolder, "*.go", true)
|
|
||||||
t.AssertNil(err)
|
|
||||||
t.Assert(files, []string{
|
|
||||||
dstFolder + filepath.FromSlash("/article.go"),
|
|
||||||
dstFolder + filepath.FromSlash("/base.go"),
|
|
||||||
dstFolder + filepath.FromSlash("/delivery.go"),
|
|
||||||
dstFolder + filepath.FromSlash("/user.go"),
|
|
||||||
})
|
|
||||||
|
|
||||||
// contents
|
|
||||||
testPath := gtest.DataPath("genservice", "service")
|
|
||||||
expectFiles := []string{
|
|
||||||
testPath + filepath.FromSlash("/article.go"),
|
|
||||||
testPath + filepath.FromSlash("/base.go"),
|
|
||||||
testPath + filepath.FromSlash("/delivery.go"),
|
|
||||||
testPath + filepath.FromSlash("/user.go"),
|
|
||||||
}
|
|
||||||
for i := range files {
|
|
||||||
t.Assert(gfile.GetContents(files[i]), gfile.GetContents(expectFiles[i]))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://github.com/gogf/gf/issues/3328
|
|
||||||
func Test_Issue3328(t *testing.T) {
|
|
||||||
gtest.C(t, func(t *gtest.T) {
|
|
||||||
var (
|
|
||||||
path = gfile.Temp(guid.S())
|
|
||||||
dstFolder = path + filepath.FromSlash("/service")
|
|
||||||
srvFolder = gtest.DataPath("issue", "3328", "logic")
|
|
||||||
logicGoPath = srvFolder + filepath.FromSlash("/logic.go")
|
|
||||||
in = genservice.CGenServiceInput{
|
|
||||||
SrcFolder: srvFolder,
|
|
||||||
DstFolder: dstFolder,
|
|
||||||
DstFileNameCase: "Snake",
|
|
||||||
WatchFile: "",
|
|
||||||
StPattern: "",
|
|
||||||
Packages: nil,
|
|
||||||
ImportPrefix: "",
|
|
||||||
Clear: false,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
gfile.Remove(logicGoPath)
|
|
||||||
defer gfile.Remove(logicGoPath)
|
|
||||||
|
|
||||||
err := gutil.FillStructWithDefault(&in)
|
|
||||||
t.AssertNil(err)
|
|
||||||
|
|
||||||
err = gfile.Mkdir(path)
|
|
||||||
t.AssertNil(err)
|
|
||||||
defer gfile.Remove(path)
|
|
||||||
|
|
||||||
_, err = genservice.CGenService{}.Service(ctx, in)
|
|
||||||
t.AssertNil(err)
|
|
||||||
|
|
||||||
files, err := gfile.ScanDir(srvFolder, "*", true)
|
|
||||||
for _, file := range files {
|
|
||||||
if file == logicGoPath {
|
|
||||||
if gfile.IsDir(logicGoPath) {
|
|
||||||
t.Fatalf("%s should not is folder", logicGoPath)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://github.com/gogf/gf/issues/3835
|
|
||||||
func Test_Issue3835(t *testing.T) {
|
|
||||||
gtest.C(t, func(t *gtest.T) {
|
|
||||||
var (
|
|
||||||
path = gfile.Temp(guid.S())
|
|
||||||
dstFolder = path + filepath.FromSlash("/service")
|
|
||||||
srvFolder = gtest.DataPath("issue", "3835", "logic")
|
|
||||||
in = genservice.CGenServiceInput{
|
|
||||||
SrcFolder: srvFolder,
|
|
||||||
DstFolder: dstFolder,
|
|
||||||
DstFileNameCase: "Snake",
|
|
||||||
WatchFile: "",
|
|
||||||
StPattern: "",
|
|
||||||
Packages: nil,
|
|
||||||
ImportPrefix: "",
|
|
||||||
Clear: false,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
err := gutil.FillStructWithDefault(&in)
|
|
||||||
t.AssertNil(err)
|
|
||||||
|
|
||||||
err = gfile.Mkdir(path)
|
|
||||||
t.AssertNil(err)
|
|
||||||
defer gfile.Remove(path)
|
|
||||||
|
|
||||||
_, err = genservice.CGenService{}.Service(ctx, in)
|
|
||||||
t.AssertNil(err)
|
|
||||||
|
|
||||||
// contents
|
|
||||||
var (
|
|
||||||
genFile = dstFolder + filepath.FromSlash("/issue_3835.go")
|
|
||||||
expectFile = gtest.DataPath("issue", "3835", "service", "issue_3835.go")
|
|
||||||
)
|
|
||||||
t.Assert(gfile.GetContents(genFile), gfile.GetContents(expectFile))
|
|
||||||
})
|
|
||||||
}
|
|
||||||
@ -13,6 +13,7 @@ import (
|
|||||||
"github.com/gogf/gf/v2/frame/g"
|
"github.com/gogf/gf/v2/frame/g"
|
||||||
"github.com/gogf/gf/v2/os/gfile"
|
"github.com/gogf/gf/v2/os/gfile"
|
||||||
"github.com/gogf/gf/v2/os/gtime"
|
"github.com/gogf/gf/v2/os/gtime"
|
||||||
|
"github.com/gogf/gf/v2/text/gregex"
|
||||||
"github.com/gogf/gf/v2/util/gconv"
|
"github.com/gogf/gf/v2/util/gconv"
|
||||||
"github.com/gogf/gf/v2/util/gtag"
|
"github.com/gogf/gf/v2/util/gtag"
|
||||||
|
|
||||||
@ -37,6 +38,7 @@ gf gen ctrl
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
PatternApiDefinition = `type\s+(\w+)Req\s+struct\s+{([\s\S]+?)}`
|
||||||
PatternCtrlDefinition = `func\s+\(.+?\)\s+\w+\(.+?\*(\w+)\.(\w+)Req\)\s+\(.+?\*(\w+)\.(\w+)Res,\s+\w+\s+error\)\s+{`
|
PatternCtrlDefinition = `func\s+\(.+?\)\s+\w+\(.+?\*(\w+)\.(\w+)Req\)\s+\(.+?\*(\w+)\.(\w+)Res,\s+\w+\s+error\)\s+{`
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -72,7 +74,7 @@ type (
|
|||||||
SdkStdVersion bool `short:"v" name:"sdkStdVersion" brief:"{CGenCtrlBriefSdkStdVersion}" orphan:"true"`
|
SdkStdVersion bool `short:"v" name:"sdkStdVersion" brief:"{CGenCtrlBriefSdkStdVersion}" orphan:"true"`
|
||||||
SdkNoV1 bool `short:"n" name:"sdkNoV1" brief:"{CGenCtrlBriefSdkNoV1}" orphan:"true"`
|
SdkNoV1 bool `short:"n" name:"sdkNoV1" brief:"{CGenCtrlBriefSdkNoV1}" orphan:"true"`
|
||||||
Clear bool `short:"c" name:"clear" brief:"{CGenCtrlBriefClear}" orphan:"true"`
|
Clear bool `short:"c" name:"clear" brief:"{CGenCtrlBriefClear}" orphan:"true"`
|
||||||
Merge bool `short:"m" name:"merge" brief:"{CGenCtrlControllerMerge}" orphan:"true"`
|
Merge bool `short:"m" name:"merge" brief:"{CGenCtrlControllerMerge}" orphan:"true"`
|
||||||
}
|
}
|
||||||
CGenCtrlOutput struct{}
|
CGenCtrlOutput struct{}
|
||||||
)
|
)
|
||||||
@ -129,7 +131,7 @@ func (c CGenCtrl) generateByWatchFile(watchFile, sdkPath string, sdkStdVersion,
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
defer gfile.RemoveFile(flockFilePath)
|
defer gfile.Remove(flockFilePath)
|
||||||
_ = gfile.PutContents(flockFilePath, gtime.TimestampStr())
|
_ = gfile.PutContents(flockFilePath, gtime.TimestampStr())
|
||||||
|
|
||||||
// check this updated file is an api file.
|
// check this updated file is an api file.
|
||||||
@ -144,11 +146,7 @@ func (c CGenCtrl) generateByWatchFile(watchFile, sdkPath string, sdkStdVersion,
|
|||||||
}
|
}
|
||||||
// watch file should have api definitions.
|
// watch file should have api definitions.
|
||||||
if gfile.Exists(watchFile) {
|
if gfile.Exists(watchFile) {
|
||||||
structsInfo, err := c.getStructsNameInSrc(watchFile)
|
if !gregex.IsMatchString(PatternApiDefinition, gfile.GetContents(watchFile)) {
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if len(structsInfo) == 0 {
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,11 +6,7 @@
|
|||||||
|
|
||||||
package genctrl
|
package genctrl
|
||||||
|
|
||||||
import (
|
import "github.com/gogf/gf/v2/text/gstr"
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/gogf/gf/v2/text/gstr"
|
|
||||||
)
|
|
||||||
|
|
||||||
type apiItem struct {
|
type apiItem struct {
|
||||||
Import string `eg:"demo.com/api/user/v1"`
|
Import string `eg:"demo.com/api/user/v1"`
|
||||||
@ -18,7 +14,6 @@ type apiItem struct {
|
|||||||
Module string `eg:"user"`
|
Module string `eg:"user"`
|
||||||
Version string `eg:"v1"`
|
Version string `eg:"v1"`
|
||||||
MethodName string `eg:"GetList"`
|
MethodName string `eg:"GetList"`
|
||||||
Comment string `eg:"GetList get list"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a apiItem) String() string {
|
func (a apiItem) String() string {
|
||||||
@ -26,12 +21,3 @@ func (a apiItem) String() string {
|
|||||||
a.Import, a.Module, a.Version, a.MethodName,
|
a.Import, a.Module, a.Version, a.MethodName,
|
||||||
}, ",")
|
}, ",")
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetComment returns the comment of apiItem.
|
|
||||||
func (a apiItem) GetComment() string {
|
|
||||||
if a.Comment == "" {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
// format for handling comments
|
|
||||||
return fmt.Sprintf("\n// %s %s", a.MethodName, a.Comment)
|
|
||||||
}
|
|
||||||
|
|||||||
@ -1,95 +0,0 @@
|
|||||||
// 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 genctrl
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"go/ast"
|
|
||||||
"go/parser"
|
|
||||||
"go/printer"
|
|
||||||
"go/token"
|
|
||||||
|
|
||||||
"github.com/gogf/gf/v2/os/gfile"
|
|
||||||
"github.com/gogf/gf/v2/text/gstr"
|
|
||||||
)
|
|
||||||
|
|
||||||
type structInfo struct {
|
|
||||||
structName string
|
|
||||||
comment string
|
|
||||||
}
|
|
||||||
|
|
||||||
// getStructsNameInSrc retrieves all struct names and comment
|
|
||||||
// that end in "Req" and have "g.Meta" in their body.
|
|
||||||
func (c CGenCtrl) getStructsNameInSrc(filePath string) (structInfos []*structInfo, err error) {
|
|
||||||
var (
|
|
||||||
fileContent = gfile.GetContents(filePath)
|
|
||||||
fileSet = token.NewFileSet()
|
|
||||||
)
|
|
||||||
|
|
||||||
node, err := parser.ParseFile(fileSet, "", fileContent, parser.ParseComments)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
ast.Inspect(node, func(n ast.Node) bool {
|
|
||||||
if typeSpec, ok := n.(*ast.TypeSpec); ok {
|
|
||||||
structName := typeSpec.Name.Name
|
|
||||||
if !gstr.HasSuffix(structName, "Req") {
|
|
||||||
// ignore struct name that do not end in "Req"
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if structType, ok := typeSpec.Type.(*ast.StructType); ok {
|
|
||||||
var buf bytes.Buffer
|
|
||||||
if err := printer.Fprint(&buf, fileSet, structType); err != nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
// ignore struct name that match a request, but has no g.Meta in its body.
|
|
||||||
if !gstr.Contains(buf.String(), `g.Meta`) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
comment := typeSpec.Doc.Text()
|
|
||||||
// remove the struct name from the comment
|
|
||||||
if gstr.HasPrefix(comment, structName) {
|
|
||||||
comment = gstr.TrimLeftStr(comment, structName, 1)
|
|
||||||
}
|
|
||||||
// remove the comment \n or space
|
|
||||||
comment = gstr.Trim(comment)
|
|
||||||
|
|
||||||
structInfos = append(structInfos, &structInfo{
|
|
||||||
structName: structName,
|
|
||||||
comment: comment,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// getImportsInDst retrieves all import paths in the file.
|
|
||||||
func (c CGenCtrl) getImportsInDst(filePath string) (imports []string, err error) {
|
|
||||||
var (
|
|
||||||
fileContent = gfile.GetContents(filePath)
|
|
||||||
fileSet = token.NewFileSet()
|
|
||||||
)
|
|
||||||
|
|
||||||
node, err := parser.ParseFile(fileSet, "", fileContent, parser.ParseComments)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
ast.Inspect(node, func(n ast.Node) bool {
|
|
||||||
if imp, ok := n.(*ast.ImportSpec); ok {
|
|
||||||
imports = append(imports, imp.Path.Value)
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
@ -1,43 +0,0 @@
|
|||||||
// 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 genctrl
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"go/ast"
|
|
||||||
"go/parser"
|
|
||||||
"go/printer"
|
|
||||||
"go/token"
|
|
||||||
|
|
||||||
"github.com/gogf/gf/v2/os/gfile"
|
|
||||||
)
|
|
||||||
|
|
||||||
// getFuncInDst retrieves all function declarations and bodies in the file.
|
|
||||||
func (c *controllerClearer) getFuncInDst(filePath string) (funcs []string, err error) {
|
|
||||||
var (
|
|
||||||
fileContent = gfile.GetContents(filePath)
|
|
||||||
fileSet = token.NewFileSet()
|
|
||||||
)
|
|
||||||
|
|
||||||
node, err := parser.ParseFile(fileSet, "", fileContent, parser.ParseComments)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
ast.Inspect(node, func(n ast.Node) bool {
|
|
||||||
if fun, ok := n.(*ast.FuncDecl); ok {
|
|
||||||
var buf bytes.Buffer
|
|
||||||
if err := printer.Fprint(&buf, fileSet, fun); err != nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
funcs = append(funcs, buf.String())
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
@ -7,15 +7,17 @@
|
|||||||
package genctrl
|
package genctrl
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/gogf/gf/cmd/gf/v2/internal/utility/utils"
|
||||||
"github.com/gogf/gf/v2/os/gfile"
|
"github.com/gogf/gf/v2/os/gfile"
|
||||||
"github.com/gogf/gf/v2/text/gregex"
|
"github.com/gogf/gf/v2/text/gregex"
|
||||||
"github.com/gogf/gf/v2/text/gstr"
|
"github.com/gogf/gf/v2/text/gstr"
|
||||||
|
|
||||||
"github.com/gogf/gf/cmd/gf/v2/internal/utility/utils"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (c CGenCtrl) getApiItemsInSrc(apiModuleFolderPath string) (items []apiItem, err error) {
|
func (c CGenCtrl) getApiItemsInSrc(apiModuleFolderPath string) (items []apiItem, err error) {
|
||||||
var importPath string
|
var (
|
||||||
|
fileContent string
|
||||||
|
importPath string
|
||||||
|
)
|
||||||
// The second level folders: versions.
|
// The second level folders: versions.
|
||||||
apiVersionFolderPaths, err := gfile.ScanDir(apiModuleFolderPath, "*", false)
|
apiVersionFolderPaths, err := gfile.ScanDir(apiModuleFolderPath, "*", false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -35,20 +37,26 @@ func (c CGenCtrl) getApiItemsInSrc(apiModuleFolderPath string) (items []apiItem,
|
|||||||
if gfile.IsDir(apiFileFolderPath) {
|
if gfile.IsDir(apiFileFolderPath) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
structsInfo, err := c.getStructsNameInSrc(apiFileFolderPath)
|
fileContent = gfile.GetContents(apiFileFolderPath)
|
||||||
|
matches, err := gregex.MatchAllString(PatternApiDefinition, fileContent)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
for _, s := range structsInfo {
|
for _, match := range matches {
|
||||||
// remove end "Req"
|
var (
|
||||||
methodName := gstr.TrimRightStr(s.structName, "Req", 1)
|
methodName = match[1]
|
||||||
|
structBody = match[2]
|
||||||
|
)
|
||||||
|
// ignore struct name that match a request, but has no g.Meta in its body.
|
||||||
|
if !gstr.Contains(structBody, `g.Meta`) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
item := apiItem{
|
item := apiItem{
|
||||||
Import: gstr.Trim(importPath, `"`),
|
Import: gstr.Trim(importPath, `"`),
|
||||||
FileName: gfile.Name(apiFileFolderPath),
|
FileName: gfile.Name(apiFileFolderPath),
|
||||||
Module: gfile.Basename(apiModuleFolderPath),
|
Module: gfile.Basename(apiModuleFolderPath),
|
||||||
Version: gfile.Basename(apiVersionFolderPath),
|
Version: gfile.Basename(apiVersionFolderPath),
|
||||||
MethodName: methodName,
|
MethodName: methodName,
|
||||||
Comment: s.comment,
|
|
||||||
}
|
}
|
||||||
items = append(items, item)
|
items = append(items, item)
|
||||||
}
|
}
|
||||||
@ -65,22 +73,26 @@ func (c CGenCtrl) getApiItemsInDst(dstFolder string) (items []apiItem, err error
|
|||||||
Path string
|
Path string
|
||||||
Alias string
|
Alias string
|
||||||
}
|
}
|
||||||
|
var fileContent string
|
||||||
filePaths, err := gfile.ScanDir(dstFolder, "*.go", true)
|
filePaths, err := gfile.ScanDir(dstFolder, "*.go", true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
for _, filePath := range filePaths {
|
for _, filePath := range filePaths {
|
||||||
var (
|
fileContent = gfile.GetContents(filePath)
|
||||||
array []string
|
match, err := gregex.MatchString(`import\s+\(([\s\S]+?)\)`, fileContent)
|
||||||
importItems []importItem
|
|
||||||
importLines []string
|
|
||||||
module = gfile.Basename(gfile.Dir(filePath))
|
|
||||||
)
|
|
||||||
importLines, err = c.getImportsInDst(filePath)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
if len(match) < 2 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
var (
|
||||||
|
array []string
|
||||||
|
importItems []importItem
|
||||||
|
importLines = gstr.SplitAndTrim(match[1], "\n")
|
||||||
|
module = gfile.Basename(gfile.Dir(filePath))
|
||||||
|
)
|
||||||
// retrieve all imports.
|
// retrieve all imports.
|
||||||
for _, importLine := range importLines {
|
for _, importLine := range importLines {
|
||||||
array = gstr.SplitAndTrim(importLine, " ")
|
array = gstr.SplitAndTrim(importLine, " ")
|
||||||
@ -96,15 +108,11 @@ func (c CGenCtrl) getApiItemsInDst(dstFolder string) (items []apiItem, err error
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// retrieve all api usages.
|
// retrieve all api usages.
|
||||||
// retrieve it without using AST, but use regular expressions to retrieve.
|
|
||||||
// It's because the api definition is simple and regular.
|
|
||||||
// Use regular expressions to get better performance.
|
|
||||||
fileContent := gfile.GetContents(filePath)
|
|
||||||
matches, err := gregex.MatchAllString(PatternCtrlDefinition, fileContent)
|
matches, err := gregex.MatchAllString(PatternCtrlDefinition, fileContent)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
for _, match := range matches {
|
for _, match = range matches {
|
||||||
// try to find the import path of the api.
|
// try to find the import path of the api.
|
||||||
var (
|
var (
|
||||||
importPath string
|
importPath string
|
||||||
|
|||||||
@ -9,15 +9,13 @@ package genctrl
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
|
||||||
|
|
||||||
|
"github.com/gogf/gf/cmd/gf/v2/internal/consts"
|
||||||
|
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
|
||||||
"github.com/gogf/gf/v2/container/gset"
|
"github.com/gogf/gf/v2/container/gset"
|
||||||
"github.com/gogf/gf/v2/frame/g"
|
"github.com/gogf/gf/v2/frame/g"
|
||||||
"github.com/gogf/gf/v2/os/gfile"
|
"github.com/gogf/gf/v2/os/gfile"
|
||||||
"github.com/gogf/gf/v2/text/gstr"
|
"github.com/gogf/gf/v2/text/gstr"
|
||||||
|
|
||||||
"github.com/gogf/gf/cmd/gf/v2/internal/consts"
|
|
||||||
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type controllerGenerator struct{}
|
type controllerGenerator struct{}
|
||||||
@ -44,16 +42,8 @@ func (c *controllerGenerator) Generate(dstModuleFolderPath string, apiModuleApiI
|
|||||||
); err != nil {
|
); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// use -merge
|
|
||||||
if merge {
|
|
||||||
err = c.doGenerateCtrlMergeItem(dstModuleFolderPath, subItems, doneApiItemSet)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, subItem := range subItems {
|
for _, subItem := range subItems {
|
||||||
err = c.doGenerateCtrlItem(dstModuleFolderPath, subItem)
|
if err = c.doGenerateCtrlItem(dstModuleFolderPath, subItem, merge); err != nil {
|
||||||
if err != nil {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
doneApiItemSet.Add(subItem.String())
|
doneApiItemSet.Add(subItem.String())
|
||||||
@ -90,7 +80,7 @@ func (c *controllerGenerator) doGenerateCtrlNewByModuleAndVersion(
|
|||||||
if err = gfile.PutContents(moduleFilePath, gstr.TrimLeft(content)); err != nil {
|
if err = gfile.PutContents(moduleFilePath, gstr.TrimLeft(content)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
mlog.Printf(`generated: %s`, gfile.RealPath(moduleFilePath))
|
mlog.Printf(`generated: %s`, moduleFilePath)
|
||||||
}
|
}
|
||||||
if !gfile.Exists(moduleFilePathNew) {
|
if !gfile.Exists(moduleFilePathNew) {
|
||||||
content := gstr.ReplaceByMap(consts.TemplateGenCtrlControllerNewEmpty, g.MapStrStr{
|
content := gstr.ReplaceByMap(consts.TemplateGenCtrlControllerNewEmpty, g.MapStrStr{
|
||||||
@ -100,7 +90,7 @@ func (c *controllerGenerator) doGenerateCtrlNewByModuleAndVersion(
|
|||||||
if err = gfile.PutContents(moduleFilePathNew, gstr.TrimLeft(content)); err != nil {
|
if err = gfile.PutContents(moduleFilePathNew, gstr.TrimLeft(content)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
mlog.Printf(`generated: %s`, gfile.RealPath(moduleFilePathNew))
|
mlog.Printf(`generated: %s`, moduleFilePathNew)
|
||||||
}
|
}
|
||||||
filePaths, err := gfile.ScanDir(dstModuleFolderPath, "*.go", false)
|
filePaths, err := gfile.ScanDir(dstModuleFolderPath, "*.go", false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -118,7 +108,7 @@ func (c *controllerGenerator) doGenerateCtrlNewByModuleAndVersion(
|
|||||||
"{NewFuncName}": newFuncName,
|
"{NewFuncName}": newFuncName,
|
||||||
"{InterfaceName}": interfaceName,
|
"{InterfaceName}": interfaceName,
|
||||||
})
|
})
|
||||||
err = gfile.PutContentsAppend(moduleFilePathNew, content)
|
err = gfile.PutContentsAppend(moduleFilePathNew, gstr.TrimLeft(content))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -126,7 +116,7 @@ func (c *controllerGenerator) doGenerateCtrlNewByModuleAndVersion(
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *controllerGenerator) doGenerateCtrlItem(dstModuleFolderPath string, item apiItem) (err error) {
|
func (c *controllerGenerator) doGenerateCtrlItem(dstModuleFolderPath string, item apiItem, merge bool) (err error) {
|
||||||
var (
|
var (
|
||||||
methodNameSnake = gstr.CaseSnake(item.MethodName)
|
methodNameSnake = gstr.CaseSnake(item.MethodName)
|
||||||
ctrlName = fmt.Sprintf(`Controller%s`, gstr.UcFirst(item.Version))
|
ctrlName = fmt.Sprintf(`Controller%s`, gstr.UcFirst(item.Version))
|
||||||
@ -136,16 +126,22 @@ func (c *controllerGenerator) doGenerateCtrlItem(dstModuleFolderPath string, ite
|
|||||||
)
|
)
|
||||||
var content string
|
var content string
|
||||||
|
|
||||||
|
if merge {
|
||||||
|
methodFilePath = gfile.Join(dstModuleFolderPath, fmt.Sprintf(
|
||||||
|
`%s_%s_%s.go`, item.Module, item.Version, item.FileName,
|
||||||
|
))
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
if gfile.Exists(methodFilePath) {
|
if gfile.Exists(methodFilePath) {
|
||||||
content = gstr.ReplaceByMap(consts.TemplateGenCtrlControllerMethodFuncMerge, g.MapStrStr{
|
content = gstr.ReplaceByMap(consts.TemplateGenCtrlControllerMethodFuncMerge, g.MapStrStr{
|
||||||
"{Module}": item.Module,
|
"{Module}": item.Module,
|
||||||
"{CtrlName}": ctrlName,
|
"{CtrlName}": ctrlName,
|
||||||
"{Version}": item.Version,
|
"{Version}": item.Version,
|
||||||
"{MethodName}": item.MethodName,
|
"{MethodName}": item.MethodName,
|
||||||
"{MethodComment}": item.GetComment(),
|
|
||||||
})
|
})
|
||||||
|
|
||||||
if gstr.Contains(gfile.GetContents(methodFilePath), fmt.Sprintf(`func (c *%v) %v(`, ctrlName, item.MethodName)) {
|
if gstr.Contains(gfile.GetContents(methodFilePath), fmt.Sprintf(`func (c *%v) %v`, ctrlName, item.MethodName)) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if err = gfile.PutContentsAppend(methodFilePath, gstr.TrimLeft(content)); err != nil {
|
if err = gfile.PutContentsAppend(methodFilePath, gstr.TrimLeft(content)); err != nil {
|
||||||
@ -153,79 +149,16 @@ func (c *controllerGenerator) doGenerateCtrlItem(dstModuleFolderPath string, ite
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
content = gstr.ReplaceByMap(consts.TemplateGenCtrlControllerMethodFunc, g.MapStrStr{
|
content = gstr.ReplaceByMap(consts.TemplateGenCtrlControllerMethodFunc, g.MapStrStr{
|
||||||
"{Module}": item.Module,
|
"{Module}": item.Module,
|
||||||
"{ImportPath}": item.Import,
|
"{ImportPath}": item.Import,
|
||||||
"{CtrlName}": ctrlName,
|
"{CtrlName}": ctrlName,
|
||||||
"{Version}": item.Version,
|
"{Version}": item.Version,
|
||||||
"{MethodName}": item.MethodName,
|
"{MethodName}": item.MethodName,
|
||||||
"{MethodComment}": item.GetComment(),
|
|
||||||
})
|
})
|
||||||
if err = gfile.PutContents(methodFilePath, gstr.TrimLeft(content)); err != nil {
|
if err = gfile.PutContents(methodFilePath, gstr.TrimLeft(content)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mlog.Printf(`generated: %s`, gfile.RealPath(methodFilePath))
|
mlog.Printf(`generated: %s`, methodFilePath)
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// use -merge
|
|
||||||
func (c *controllerGenerator) doGenerateCtrlMergeItem(dstModuleFolderPath string, apiItems []apiItem, doneApiSet *gset.StrSet) (err error) {
|
|
||||||
|
|
||||||
type controllerFileItem struct {
|
|
||||||
module string
|
|
||||||
version string
|
|
||||||
importPath string
|
|
||||||
// Each ctrlFileItem has multiple CTRLs
|
|
||||||
controllers strings.Builder
|
|
||||||
}
|
|
||||||
// It is possible that there are multiple files under one module
|
|
||||||
ctrlFileItemMap := make(map[string]*controllerFileItem)
|
|
||||||
|
|
||||||
for _, api := range apiItems {
|
|
||||||
ctrlFileItem, found := ctrlFileItemMap[api.FileName]
|
|
||||||
if !found {
|
|
||||||
ctrlFileItem = &controllerFileItem{
|
|
||||||
module: api.Module,
|
|
||||||
version: api.Version,
|
|
||||||
controllers: strings.Builder{},
|
|
||||||
importPath: api.Import,
|
|
||||||
}
|
|
||||||
ctrlFileItemMap[api.FileName] = ctrlFileItem
|
|
||||||
}
|
|
||||||
|
|
||||||
ctrl := gstr.TrimLeft(gstr.ReplaceByMap(consts.TemplateGenCtrlControllerMethodFuncMerge, g.MapStrStr{
|
|
||||||
"{Module}": api.Module,
|
|
||||||
"{CtrlName}": fmt.Sprintf(`Controller%s`, gstr.UcFirst(api.Version)),
|
|
||||||
"{Version}": api.Version,
|
|
||||||
"{MethodName}": api.MethodName,
|
|
||||||
"{MethodComment}": api.GetComment(),
|
|
||||||
}))
|
|
||||||
ctrlFileItem.controllers.WriteString(ctrl)
|
|
||||||
doneApiSet.Add(api.String())
|
|
||||||
}
|
|
||||||
|
|
||||||
for ctrlFileName, ctrlFileItem := range ctrlFileItemMap {
|
|
||||||
ctrlFilePath := gfile.Join(dstModuleFolderPath, fmt.Sprintf(
|
|
||||||
`%s_%s_%s.go`, ctrlFileItem.module, ctrlFileItem.version, ctrlFileName,
|
|
||||||
))
|
|
||||||
|
|
||||||
// This logic is only followed when a new ctrlFileItem is generated
|
|
||||||
// Most of the rest of the time, the following logic is followed
|
|
||||||
if !gfile.Exists(ctrlFilePath) {
|
|
||||||
ctrlFileHeader := gstr.TrimLeft(gstr.ReplaceByMap(consts.TemplateGenCtrlControllerHeader, g.MapStrStr{
|
|
||||||
"{Module}": ctrlFileItem.module,
|
|
||||||
"{ImportPath}": ctrlFileItem.importPath,
|
|
||||||
}))
|
|
||||||
err = gfile.PutContents(ctrlFilePath, ctrlFileHeader)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = gfile.PutContentsAppend(ctrlFilePath, ctrlFileItem.controllers.String()); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
mlog.Printf(`generated: %s`, gfile.RealPath(ctrlFilePath))
|
|
||||||
}
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,10 +9,10 @@ package genctrl
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/gogf/gf/v2/os/gfile"
|
|
||||||
"github.com/gogf/gf/v2/text/gstr"
|
|
||||||
|
|
||||||
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
|
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
|
||||||
|
"github.com/gogf/gf/v2/os/gfile"
|
||||||
|
"github.com/gogf/gf/v2/text/gregex"
|
||||||
|
"github.com/gogf/gf/v2/text/gstr"
|
||||||
)
|
)
|
||||||
|
|
||||||
type controllerClearer struct{}
|
type controllerClearer struct{}
|
||||||
@ -36,21 +36,21 @@ func (c *controllerClearer) doClear(dstModuleFolderPath string, item apiItem) (e
|
|||||||
methodFilePath = gfile.Join(dstModuleFolderPath, fmt.Sprintf(
|
methodFilePath = gfile.Join(dstModuleFolderPath, fmt.Sprintf(
|
||||||
`%s_%s_%s.go`, item.Module, item.Version, methodNameSnake,
|
`%s_%s_%s.go`, item.Module, item.Version, methodNameSnake,
|
||||||
))
|
))
|
||||||
|
fileContent = gstr.Trim(gfile.GetContents(methodFilePath))
|
||||||
)
|
)
|
||||||
|
match, err := gregex.MatchString(`.+?Req.+?Res.+?{([\s\S]+?)}`, fileContent)
|
||||||
funcs, err := c.getFuncInDst(methodFilePath)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if len(match) > 1 {
|
||||||
if len(funcs) > 1 {
|
implements := gstr.Trim(match[1])
|
||||||
// One line.
|
// One line.
|
||||||
if !gstr.Contains(funcs[0], "\n") && gstr.Contains(funcs[0], `CodeNotImplemented`) {
|
if !gstr.Contains(implements, "\n") && gstr.Contains(implements, `CodeNotImplemented`) {
|
||||||
mlog.Printf(
|
mlog.Printf(
|
||||||
`remove unimplemented and of no api definitions controller file: %s`,
|
`remove unimplemented and of no api definitions controller file: %s`,
|
||||||
methodFilePath,
|
methodFilePath,
|
||||||
)
|
)
|
||||||
err = gfile.RemoveFile(methodFilePath)
|
err = gfile.Remove(methodFilePath)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
|
|||||||
@ -10,16 +10,15 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
|
"github.com/gogf/gf/cmd/gf/v2/internal/consts"
|
||||||
|
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
|
||||||
|
"github.com/gogf/gf/cmd/gf/v2/internal/utility/utils"
|
||||||
"github.com/gogf/gf/v2/container/gmap"
|
"github.com/gogf/gf/v2/container/gmap"
|
||||||
"github.com/gogf/gf/v2/container/gset"
|
"github.com/gogf/gf/v2/container/gset"
|
||||||
"github.com/gogf/gf/v2/frame/g"
|
"github.com/gogf/gf/v2/frame/g"
|
||||||
"github.com/gogf/gf/v2/os/gfile"
|
"github.com/gogf/gf/v2/os/gfile"
|
||||||
"github.com/gogf/gf/v2/text/gstr"
|
"github.com/gogf/gf/v2/text/gstr"
|
||||||
"github.com/gogf/gf/v2/util/gconv"
|
"github.com/gogf/gf/v2/util/gconv"
|
||||||
|
|
||||||
"github.com/gogf/gf/cmd/gf/v2/internal/consts"
|
|
||||||
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
|
|
||||||
"github.com/gogf/gf/cmd/gf/v2/internal/utility/utils"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type apiInterfaceGenerator struct{}
|
type apiInterfaceGenerator struct{}
|
||||||
@ -51,7 +50,8 @@ func (c *apiInterfaceGenerator) doGenerate(apiModuleFolderPath string, module st
|
|||||||
moduleFilePath = filepath.FromSlash(gfile.Join(apiModuleFolderPath, fmt.Sprintf(`%s.if.go`, module)))
|
moduleFilePath = filepath.FromSlash(gfile.Join(apiModuleFolderPath, fmt.Sprintf(`%s.if.go`, module)))
|
||||||
}
|
}
|
||||||
// all import paths.
|
// all import paths.
|
||||||
importPathMap.Set("\t"+`"context"`+"\n", 1)
|
importPathMap.Set("\t"+`"context"`, 1)
|
||||||
|
importPathMap.Set("\t"+``, 1)
|
||||||
for _, item := range items {
|
for _, item := range items {
|
||||||
importPathMap.Set(fmt.Sprintf("\t"+`"%s"`, item.Import), 1)
|
importPathMap.Set(fmt.Sprintf("\t"+`"%s"`, item.Import), 1)
|
||||||
}
|
}
|
||||||
@ -92,10 +92,10 @@ func (c *apiInterfaceGenerator) doGenerate(apiModuleFolderPath string, module st
|
|||||||
interfaceDefinition += "\n\n"
|
interfaceDefinition += "\n\n"
|
||||||
}
|
}
|
||||||
interfaceContent = gstr.TrimLeft(gstr.ReplaceByMap(interfaceContent, g.MapStrStr{
|
interfaceContent = gstr.TrimLeft(gstr.ReplaceByMap(interfaceContent, g.MapStrStr{
|
||||||
"{Interfaces}": gstr.TrimRightStr(interfaceDefinition, "\n", 2),
|
"{Interfaces}": interfaceDefinition,
|
||||||
}))
|
}))
|
||||||
err = gfile.PutContents(moduleFilePath, interfaceContent)
|
err = gfile.PutContents(moduleFilePath, interfaceContent)
|
||||||
mlog.Printf(`generated: %s`, gfile.RealPath(moduleFilePath))
|
mlog.Printf(`generated: %s`, moduleFilePath)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -10,14 +10,13 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
|
"github.com/gogf/gf/cmd/gf/v2/internal/consts"
|
||||||
|
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
|
||||||
"github.com/gogf/gf/v2/container/gset"
|
"github.com/gogf/gf/v2/container/gset"
|
||||||
"github.com/gogf/gf/v2/frame/g"
|
"github.com/gogf/gf/v2/frame/g"
|
||||||
"github.com/gogf/gf/v2/os/gfile"
|
"github.com/gogf/gf/v2/os/gfile"
|
||||||
"github.com/gogf/gf/v2/text/gregex"
|
"github.com/gogf/gf/v2/text/gregex"
|
||||||
"github.com/gogf/gf/v2/text/gstr"
|
"github.com/gogf/gf/v2/text/gstr"
|
||||||
|
|
||||||
"github.com/gogf/gf/cmd/gf/v2/internal/consts"
|
|
||||||
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type apiSdkGenerator struct{}
|
type apiSdkGenerator struct{}
|
||||||
@ -66,7 +65,7 @@ func (c *apiSdkGenerator) doGenerateSdkPkgFile(sdkFolderPath string) (err error)
|
|||||||
"{PkgName}": pkgName,
|
"{PkgName}": pkgName,
|
||||||
}))
|
}))
|
||||||
err = gfile.PutContents(pkgFilePath, fileContent)
|
err = gfile.PutContents(pkgFilePath, fileContent)
|
||||||
mlog.Printf(`generated: %s`, gfile.RealPath(pkgFilePath))
|
mlog.Printf(`generated: %s`, pkgFilePath)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,7 +103,6 @@ func (c *apiSdkGenerator) doGenerateSdkIClient(
|
|||||||
// append the import path to current import paths.
|
// append the import path to current import paths.
|
||||||
if !gstr.Contains(fileContent, moduleImportPath) {
|
if !gstr.Contains(fileContent, moduleImportPath) {
|
||||||
isDirty = true
|
isDirty = true
|
||||||
// It is without using AST, because it is from a template.
|
|
||||||
fileContent, err = gregex.ReplaceString(
|
fileContent, err = gregex.ReplaceString(
|
||||||
`(import \([\s\S]*?)\)`,
|
`(import \([\s\S]*?)\)`,
|
||||||
fmt.Sprintf("$1\t%s\n)", moduleImportPath),
|
fmt.Sprintf("$1\t%s\n)", moduleImportPath),
|
||||||
@ -118,7 +116,6 @@ func (c *apiSdkGenerator) doGenerateSdkIClient(
|
|||||||
// append the function definition to interface definition.
|
// append the function definition to interface definition.
|
||||||
if !gstr.Contains(fileContent, interfaceFuncDefinition) {
|
if !gstr.Contains(fileContent, interfaceFuncDefinition) {
|
||||||
isDirty = true
|
isDirty = true
|
||||||
// It is without using AST, because it is from a template.
|
|
||||||
fileContent, err = gregex.ReplaceString(
|
fileContent, err = gregex.ReplaceString(
|
||||||
`(type IClient interface {[\s\S]*?)}`,
|
`(type IClient interface {[\s\S]*?)}`,
|
||||||
fmt.Sprintf("$1\t%s\n}", interfaceFuncDefinition),
|
fmt.Sprintf("$1\t%s\n}", interfaceFuncDefinition),
|
||||||
@ -131,9 +128,9 @@ func (c *apiSdkGenerator) doGenerateSdkIClient(
|
|||||||
if isDirty {
|
if isDirty {
|
||||||
err = gfile.PutContents(iClientFilePath, fileContent)
|
err = gfile.PutContents(iClientFilePath, fileContent)
|
||||||
if isExist {
|
if isExist {
|
||||||
mlog.Printf(`updated: %s`, gfile.RealPath(iClientFilePath))
|
mlog.Printf(`updated: %s`, iClientFilePath)
|
||||||
} else {
|
} else {
|
||||||
mlog.Printf(`generated: %s`, gfile.RealPath(iClientFilePath))
|
mlog.Printf(`generated: %s`, iClientFilePath)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
@ -180,12 +177,11 @@ func (c *apiSdkGenerator) doGenerateSdkImplementer(
|
|||||||
"{Version}": item.Version,
|
"{Version}": item.Version,
|
||||||
"{MethodName}": item.MethodName,
|
"{MethodName}": item.MethodName,
|
||||||
"{ImplementerName}": implementerName,
|
"{ImplementerName}": implementerName,
|
||||||
"{MethodComment}": item.GetComment(),
|
|
||||||
}))
|
}))
|
||||||
implementerFileContent += "\n"
|
implementerFileContent += "\n"
|
||||||
}
|
}
|
||||||
err = gfile.PutContents(implementerFilePath, implementerFileContent)
|
err = gfile.PutContents(implementerFilePath, implementerFileContent)
|
||||||
mlog.Printf(`generated: %s`, gfile.RealPath(implementerFilePath))
|
mlog.Printf(`generated: %s`, implementerFilePath)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
@ -9,88 +9,112 @@ package gendao
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"golang.org/x/mod/modfile"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/olekukonko/tablewriter"
|
"github.com/gogf/gf/cmd/gf/v2/internal/utility/utils"
|
||||||
"github.com/olekukonko/tablewriter/renderer"
|
|
||||||
"github.com/olekukonko/tablewriter/tw"
|
|
||||||
"golang.org/x/mod/modfile"
|
|
||||||
|
|
||||||
"github.com/gogf/gf/v2/container/garray"
|
"github.com/gogf/gf/v2/container/garray"
|
||||||
"github.com/gogf/gf/v2/container/gset"
|
|
||||||
"github.com/gogf/gf/v2/database/gdb"
|
"github.com/gogf/gf/v2/database/gdb"
|
||||||
"github.com/gogf/gf/v2/frame/g"
|
"github.com/gogf/gf/v2/frame/g"
|
||||||
"github.com/gogf/gf/v2/os/gfile"
|
"github.com/gogf/gf/v2/os/gfile"
|
||||||
"github.com/gogf/gf/v2/os/gproc"
|
"github.com/gogf/gf/v2/os/gproc"
|
||||||
"github.com/gogf/gf/v2/os/gtime"
|
"github.com/gogf/gf/v2/os/gtime"
|
||||||
"github.com/gogf/gf/v2/os/gview"
|
|
||||||
"github.com/gogf/gf/v2/text/gregex"
|
|
||||||
"github.com/gogf/gf/v2/text/gstr"
|
"github.com/gogf/gf/v2/text/gstr"
|
||||||
|
"github.com/gogf/gf/v2/util/gtag"
|
||||||
|
|
||||||
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
|
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
|
||||||
"github.com/gogf/gf/cmd/gf/v2/internal/utility/utils"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
const (
|
||||||
CGenDao struct{}
|
CGenDaoConfig = `gfcli.gen.dao`
|
||||||
CGenDaoInput struct {
|
CGenDaoUsage = `gf gen dao [OPTION]`
|
||||||
g.Meta `name:"dao" config:"{CGenDaoConfig}" usage:"{CGenDaoUsage}" brief:"{CGenDaoBrief}" eg:"{CGenDaoEg}" ad:"{CGenDaoAd}"`
|
CGenDaoBrief = `automatically generate go files for dao/do/entity`
|
||||||
Path string `name:"path" short:"p" brief:"{CGenDaoBriefPath}" d:"internal"`
|
CGenDaoEg = `
|
||||||
Link string `name:"link" short:"l" brief:"{CGenDaoBriefLink}"`
|
gf gen dao
|
||||||
Tables string `name:"tables" short:"t" brief:"{CGenDaoBriefTables}"`
|
gf gen dao -l "mysql:root:12345678@tcp(127.0.0.1:3306)/test"
|
||||||
TablesEx string `name:"tablesEx" short:"x" brief:"{CGenDaoBriefTablesEx}"`
|
gf gen dao -p ./model -g user-center -t user,user_detail,user_login
|
||||||
ShardingPattern []string `name:"shardingPattern" short:"sp" brief:"{CGenDaoBriefShardingPattern}"`
|
gf gen dao -r user_
|
||||||
Group string `name:"group" short:"g" brief:"{CGenDaoBriefGroup}" d:"default"`
|
`
|
||||||
Prefix string `name:"prefix" short:"f" brief:"{CGenDaoBriefPrefix}"`
|
|
||||||
RemovePrefix string `name:"removePrefix" short:"r" brief:"{CGenDaoBriefRemovePrefix}"`
|
|
||||||
RemoveFieldPrefix string `name:"removeFieldPrefix" short:"rf" brief:"{CGenDaoBriefRemoveFieldPrefix}"`
|
|
||||||
JsonCase string `name:"jsonCase" short:"j" brief:"{CGenDaoBriefJsonCase}" d:"CamelLower"`
|
|
||||||
ImportPrefix string `name:"importPrefix" short:"i" brief:"{CGenDaoBriefImportPrefix}"`
|
|
||||||
DaoPath string `name:"daoPath" short:"d" brief:"{CGenDaoBriefDaoPath}" d:"dao"`
|
|
||||||
TablePath string `name:"tablePath" short:"tp" brief:"{CGenDaoBriefTablePath}" d:"table"`
|
|
||||||
DoPath string `name:"doPath" short:"o" brief:"{CGenDaoBriefDoPath}" d:"model/do"`
|
|
||||||
EntityPath string `name:"entityPath" short:"e" brief:"{CGenDaoBriefEntityPath}" d:"model/entity"`
|
|
||||||
TplDaoTablePath string `name:"tplDaoTablePath" short:"t0" brief:"{CGenDaoBriefTplDaoTablePath}"`
|
|
||||||
TplDaoIndexPath string `name:"tplDaoIndexPath" short:"t1" brief:"{CGenDaoBriefTplDaoIndexPath}"`
|
|
||||||
TplDaoInternalPath string `name:"tplDaoInternalPath" short:"t2" brief:"{CGenDaoBriefTplDaoInternalPath}"`
|
|
||||||
TplDaoDoPath string `name:"tplDaoDoPath" short:"t3" brief:"{CGenDaoBriefTplDaoDoPathPath}"`
|
|
||||||
TplDaoEntityPath string `name:"tplDaoEntityPath" short:"t4" brief:"{CGenDaoBriefTplDaoEntityPath}"`
|
|
||||||
StdTime bool `name:"stdTime" short:"s" brief:"{CGenDaoBriefStdTime}" orphan:"true"`
|
|
||||||
WithTime bool `name:"withTime" short:"w" brief:"{CGenDaoBriefWithTime}" orphan:"true"`
|
|
||||||
GJsonSupport bool `name:"gJsonSupport" short:"n" brief:"{CGenDaoBriefGJsonSupport}" orphan:"true"`
|
|
||||||
OverwriteDao bool `name:"overwriteDao" short:"v" brief:"{CGenDaoBriefOverwriteDao}" orphan:"true"`
|
|
||||||
DescriptionTag bool `name:"descriptionTag" short:"c" brief:"{CGenDaoBriefDescriptionTag}" orphan:"true"`
|
|
||||||
NoJsonTag bool `name:"noJsonTag" short:"k" brief:"{CGenDaoBriefNoJsonTag}" orphan:"true"`
|
|
||||||
NoModelComment bool `name:"noModelComment" short:"m" brief:"{CGenDaoBriefNoModelComment}" orphan:"true"`
|
|
||||||
Clear bool `name:"clear" short:"a" brief:"{CGenDaoBriefClear}" orphan:"true"`
|
|
||||||
GenTable bool `name:"genTable" short:"gt" brief:"{CGenDaoBriefGenTable}" orphan:"true"`
|
|
||||||
|
|
||||||
TypeMapping map[DBFieldTypeName]CustomAttributeType `name:"typeMapping" short:"y" brief:"{CGenDaoBriefTypeMapping}" orphan:"true"`
|
CGenDaoAd = `
|
||||||
FieldMapping map[DBTableFieldName]CustomAttributeType `name:"fieldMapping" short:"fm" brief:"{CGenDaoBriefFieldMapping}" orphan:"true"`
|
CONFIGURATION SUPPORT
|
||||||
|
Options are also supported by configuration file.
|
||||||
|
It's suggested using configuration file instead of command line arguments making producing.
|
||||||
|
The configuration node name is "gfcli.gen.dao", which also supports multiple databases, for example(config.yaml):
|
||||||
|
gfcli:
|
||||||
|
gen:
|
||||||
|
dao:
|
||||||
|
- link: "mysql:root:12345678@tcp(127.0.0.1:3306)/test"
|
||||||
|
tables: "order,products"
|
||||||
|
jsonCase: "CamelLower"
|
||||||
|
- link: "mysql:root:12345678@tcp(127.0.0.1:3306)/primary"
|
||||||
|
path: "./my-app"
|
||||||
|
prefix: "primary_"
|
||||||
|
tables: "user, userDetail"
|
||||||
|
typeMapping:
|
||||||
|
decimal:
|
||||||
|
type: decimal.Decimal
|
||||||
|
import: github.com/shopspring/decimal
|
||||||
|
numeric:
|
||||||
|
type: string
|
||||||
|
`
|
||||||
|
CGenDaoBriefPath = `directory path for generated files`
|
||||||
|
CGenDaoBriefLink = `database configuration, the same as the ORM configuration of GoFrame`
|
||||||
|
CGenDaoBriefTables = `generate models only for given tables, multiple table names separated with ','`
|
||||||
|
CGenDaoBriefTablesEx = `generate models excluding given tables, multiple table names separated with ','`
|
||||||
|
CGenDaoBriefPrefix = `add prefix for all table of specified link/database tables`
|
||||||
|
CGenDaoBriefRemovePrefix = `remove specified prefix of the table, multiple prefix separated with ','`
|
||||||
|
CGenDaoBriefStdTime = `use time.Time from stdlib instead of gtime.Time for generated time/date fields of tables`
|
||||||
|
CGenDaoBriefWithTime = `add created time for auto produced go files`
|
||||||
|
CGenDaoBriefGJsonSupport = `use gJsonSupport to use *gjson.Json instead of string for generated json fields of tables`
|
||||||
|
CGenDaoBriefImportPrefix = `custom import prefix for generated go files`
|
||||||
|
CGenDaoBriefDaoPath = `directory path for storing generated dao files under path`
|
||||||
|
CGenDaoBriefDoPath = `directory path for storing generated do files under path`
|
||||||
|
CGenDaoBriefEntityPath = `directory path for storing generated entity files under path`
|
||||||
|
CGenDaoBriefOverwriteDao = `overwrite all dao files both inside/outside internal folder`
|
||||||
|
CGenDaoBriefModelFile = `custom file name for storing generated model content`
|
||||||
|
CGenDaoBriefModelFileForDao = `custom file name generating model for DAO operations like Where/Data. It's empty in default`
|
||||||
|
CGenDaoBriefDescriptionTag = `add comment to description tag for each field`
|
||||||
|
CGenDaoBriefNoJsonTag = `no json tag will be added for each field`
|
||||||
|
CGenDaoBriefNoModelComment = `no model comment will be added for each field`
|
||||||
|
CGenDaoBriefClear = `delete all generated go files that do not exist in database`
|
||||||
|
CGenDaoBriefTypeMapping = `custom local type mapping for generated struct attributes relevant to fields of table`
|
||||||
|
CGenDaoBriefGroup = `
|
||||||
|
specifying the configuration group name of database for generated ORM instance,
|
||||||
|
it's not necessary and the default value is "default"
|
||||||
|
`
|
||||||
|
CGenDaoBriefJsonCase = `
|
||||||
|
generated json tag case for model struct, cases are as follows:
|
||||||
|
| Case | Example |
|
||||||
|
|---------------- |--------------------|
|
||||||
|
| Camel | AnyKindOfString |
|
||||||
|
| CamelLower | anyKindOfString | default
|
||||||
|
| Snake | any_kind_of_string |
|
||||||
|
| SnakeScreaming | ANY_KIND_OF_STRING |
|
||||||
|
| SnakeFirstUpper | rgb_code_md5 |
|
||||||
|
| Kebab | any-kind-of-string |
|
||||||
|
| KebabScreaming | ANY-KIND-OF-STRING |
|
||||||
|
`
|
||||||
|
CGenDaoBriefTplDaoIndexPath = `template file path for dao index file`
|
||||||
|
CGenDaoBriefTplDaoInternalPath = `template file path for dao internal file`
|
||||||
|
CGenDaoBriefTplDaoDoPathPath = `template file path for dao do file`
|
||||||
|
CGenDaoBriefTplDaoEntityPath = `template file path for dao entity file`
|
||||||
|
|
||||||
// internal usage purpose.
|
tplVarTableName = `{TplTableName}`
|
||||||
genItems *CGenDaoInternalGenItems
|
tplVarTableNameCamelCase = `{TplTableNameCamelCase}`
|
||||||
}
|
tplVarTableNameCamelLowerCase = `{TplTableNameCamelLowerCase}`
|
||||||
CGenDaoOutput struct{}
|
tplVarPackageImports = `{TplPackageImports}`
|
||||||
|
tplVarImportPrefix = `{TplImportPrefix}`
|
||||||
CGenDaoInternalInput struct {
|
tplVarStructDefine = `{TplStructDefine}`
|
||||||
CGenDaoInput
|
tplVarColumnDefine = `{TplColumnDefine}`
|
||||||
DB gdb.DB
|
tplVarColumnNames = `{TplColumnNames}`
|
||||||
TableNames []string
|
tplVarGroupName = `{TplGroupName}`
|
||||||
NewTableNames []string
|
tplVarDatetimeStr = `{TplDatetimeStr}`
|
||||||
ShardingTableSet *gset.StrSet
|
tplVarCreatedAtDatetimeStr = `{TplCreatedAtDatetimeStr}`
|
||||||
}
|
|
||||||
DBTableFieldName = string
|
|
||||||
DBFieldTypeName = string
|
|
||||||
CustomAttributeType struct {
|
|
||||||
Type string `brief:"custom attribute type name"`
|
|
||||||
Import string `brief:"custom import for this type"`
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
createdAt = gtime.Now()
|
createdAt = gtime.Now()
|
||||||
tplView = gview.New()
|
|
||||||
defaultTypeMapping = map[DBFieldTypeName]CustomAttributeType{
|
defaultTypeMapping = map[DBFieldTypeName]CustomAttributeType{
|
||||||
"decimal": {
|
"decimal": {
|
||||||
Type: "float64",
|
Type: "float64",
|
||||||
@ -105,27 +129,94 @@ var (
|
|||||||
Type: "float64",
|
Type: "float64",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
)
|
||||||
|
|
||||||
// tablewriter Options
|
func init() {
|
||||||
twRenderer = tablewriter.WithRenderer(renderer.NewBlueprint(tw.Rendition{
|
gtag.Sets(g.MapStrStr{
|
||||||
Borders: tw.Border{Top: tw.Off, Bottom: tw.Off, Left: tw.Off, Right: tw.Off},
|
`CGenDaoConfig`: CGenDaoConfig,
|
||||||
Settings: tw.Settings{
|
`CGenDaoUsage`: CGenDaoUsage,
|
||||||
Separators: tw.Separators{BetweenRows: tw.Off, BetweenColumns: tw.Off},
|
`CGenDaoBrief`: CGenDaoBrief,
|
||||||
},
|
`CGenDaoEg`: CGenDaoEg,
|
||||||
Symbols: tw.NewSymbols(tw.StyleASCII),
|
`CGenDaoAd`: CGenDaoAd,
|
||||||
}))
|
`CGenDaoBriefPath`: CGenDaoBriefPath,
|
||||||
twConfig = tablewriter.WithConfig(tablewriter.Config{
|
`CGenDaoBriefLink`: CGenDaoBriefLink,
|
||||||
Row: tw.CellConfig{
|
`CGenDaoBriefTables`: CGenDaoBriefTables,
|
||||||
Formatting: tw.CellFormatting{AutoWrap: tw.WrapNone},
|
`CGenDaoBriefTablesEx`: CGenDaoBriefTablesEx,
|
||||||
},
|
`CGenDaoBriefPrefix`: CGenDaoBriefPrefix,
|
||||||
|
`CGenDaoBriefRemovePrefix`: CGenDaoBriefRemovePrefix,
|
||||||
|
`CGenDaoBriefStdTime`: CGenDaoBriefStdTime,
|
||||||
|
`CGenDaoBriefWithTime`: CGenDaoBriefWithTime,
|
||||||
|
`CGenDaoBriefDaoPath`: CGenDaoBriefDaoPath,
|
||||||
|
`CGenDaoBriefDoPath`: CGenDaoBriefDoPath,
|
||||||
|
`CGenDaoBriefEntityPath`: CGenDaoBriefEntityPath,
|
||||||
|
`CGenDaoBriefGJsonSupport`: CGenDaoBriefGJsonSupport,
|
||||||
|
`CGenDaoBriefImportPrefix`: CGenDaoBriefImportPrefix,
|
||||||
|
`CGenDaoBriefOverwriteDao`: CGenDaoBriefOverwriteDao,
|
||||||
|
`CGenDaoBriefModelFile`: CGenDaoBriefModelFile,
|
||||||
|
`CGenDaoBriefModelFileForDao`: CGenDaoBriefModelFileForDao,
|
||||||
|
`CGenDaoBriefDescriptionTag`: CGenDaoBriefDescriptionTag,
|
||||||
|
`CGenDaoBriefNoJsonTag`: CGenDaoBriefNoJsonTag,
|
||||||
|
`CGenDaoBriefNoModelComment`: CGenDaoBriefNoModelComment,
|
||||||
|
`CGenDaoBriefClear`: CGenDaoBriefClear,
|
||||||
|
`CGenDaoBriefTypeMapping`: CGenDaoBriefTypeMapping,
|
||||||
|
`CGenDaoBriefGroup`: CGenDaoBriefGroup,
|
||||||
|
`CGenDaoBriefJsonCase`: CGenDaoBriefJsonCase,
|
||||||
|
`CGenDaoBriefTplDaoIndexPath`: CGenDaoBriefTplDaoIndexPath,
|
||||||
|
`CGenDaoBriefTplDaoInternalPath`: CGenDaoBriefTplDaoInternalPath,
|
||||||
|
`CGenDaoBriefTplDaoDoPathPath`: CGenDaoBriefTplDaoDoPathPath,
|
||||||
|
`CGenDaoBriefTplDaoEntityPath`: CGenDaoBriefTplDaoEntityPath,
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
type (
|
||||||
|
CGenDao struct{}
|
||||||
|
CGenDaoInput struct {
|
||||||
|
g.Meta `name:"dao" config:"{CGenDaoConfig}" usage:"{CGenDaoUsage}" brief:"{CGenDaoBrief}" eg:"{CGenDaoEg}" ad:"{CGenDaoAd}"`
|
||||||
|
Path string `name:"path" short:"p" brief:"{CGenDaoBriefPath}" d:"internal"`
|
||||||
|
Link string `name:"link" short:"l" brief:"{CGenDaoBriefLink}"`
|
||||||
|
Tables string `name:"tables" short:"t" brief:"{CGenDaoBriefTables}"`
|
||||||
|
TablesEx string `name:"tablesEx" short:"x" brief:"{CGenDaoBriefTablesEx}"`
|
||||||
|
Group string `name:"group" short:"g" brief:"{CGenDaoBriefGroup}" d:"default"`
|
||||||
|
Prefix string `name:"prefix" short:"f" brief:"{CGenDaoBriefPrefix}"`
|
||||||
|
RemovePrefix string `name:"removePrefix" short:"r" brief:"{CGenDaoBriefRemovePrefix}"`
|
||||||
|
JsonCase string `name:"jsonCase" short:"j" brief:"{CGenDaoBriefJsonCase}" d:"CamelLower"`
|
||||||
|
ImportPrefix string `name:"importPrefix" short:"i" brief:"{CGenDaoBriefImportPrefix}"`
|
||||||
|
DaoPath string `name:"daoPath" short:"d" brief:"{CGenDaoBriefDaoPath}" d:"dao"`
|
||||||
|
DoPath string `name:"doPath" short:"o" brief:"{CGenDaoBriefDoPath}" d:"model/do"`
|
||||||
|
EntityPath string `name:"entityPath" short:"e" brief:"{CGenDaoBriefEntityPath}" d:"model/entity"`
|
||||||
|
TplDaoIndexPath string `name:"tplDaoIndexPath" short:"t1" brief:"{CGenDaoBriefTplDaoIndexPath}"`
|
||||||
|
TplDaoInternalPath string `name:"tplDaoInternalPath" short:"t2" brief:"{CGenDaoBriefTplDaoInternalPath}"`
|
||||||
|
TplDaoDoPath string `name:"tplDaoDoPath" short:"t3" brief:"{CGenDaoBriefTplDaoDoPathPath}"`
|
||||||
|
TplDaoEntityPath string `name:"tplDaoEntityPath" short:"t4" brief:"{CGenDaoBriefTplDaoEntityPath}"`
|
||||||
|
StdTime bool `name:"stdTime" short:"s" brief:"{CGenDaoBriefStdTime}" orphan:"true"`
|
||||||
|
WithTime bool `name:"withTime" short:"w" brief:"{CGenDaoBriefWithTime}" orphan:"true"`
|
||||||
|
GJsonSupport bool `name:"gJsonSupport" short:"n" brief:"{CGenDaoBriefGJsonSupport}" orphan:"true"`
|
||||||
|
OverwriteDao bool `name:"overwriteDao" short:"v" brief:"{CGenDaoBriefOverwriteDao}" orphan:"true"`
|
||||||
|
DescriptionTag bool `name:"descriptionTag" short:"c" brief:"{CGenDaoBriefDescriptionTag}" orphan:"true"`
|
||||||
|
NoJsonTag bool `name:"noJsonTag" short:"k" brief:"{CGenDaoBriefNoJsonTag}" orphan:"true"`
|
||||||
|
NoModelComment bool `name:"noModelComment" short:"m" brief:"{CGenDaoBriefNoModelComment}" orphan:"true"`
|
||||||
|
Clear bool `name:"clear" short:"a" brief:"{CGenDaoBriefClear}" orphan:"true"`
|
||||||
|
|
||||||
|
TypeMapping map[DBFieldTypeName]CustomAttributeType `name:"typeMapping" short:"y" brief:"{CGenDaoBriefTypeMapping}" orphan:"true"`
|
||||||
|
}
|
||||||
|
CGenDaoOutput struct{}
|
||||||
|
|
||||||
|
CGenDaoInternalInput struct {
|
||||||
|
CGenDaoInput
|
||||||
|
DB gdb.DB
|
||||||
|
TableNames []string
|
||||||
|
NewTableNames []string
|
||||||
|
}
|
||||||
|
|
||||||
|
DBFieldTypeName = string
|
||||||
|
CustomAttributeType struct {
|
||||||
|
Type string `brief:"custom attribute type name"`
|
||||||
|
Import string `brief:"custom import for this type"`
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
func (c CGenDao) Dao(ctx context.Context, in CGenDaoInput) (out *CGenDaoOutput, err error) {
|
func (c CGenDao) Dao(ctx context.Context, in CGenDaoInput) (out *CGenDaoOutput, err error) {
|
||||||
in.genItems = newCGenDaoInternalGenItems()
|
if g.Cfg().Available(ctx) {
|
||||||
if in.Link != "" {
|
|
||||||
doGenDaoForArray(ctx, -1, in)
|
|
||||||
} else if g.Cfg().Available(ctx) {
|
|
||||||
v := g.Cfg().MustGet(ctx, CGenDaoConfig)
|
v := g.Cfg().MustGet(ctx, CGenDaoConfig)
|
||||||
if v.IsSlice() {
|
if v.IsSlice() {
|
||||||
for i := 0; i < len(v.Interfaces()); i++ {
|
for i := 0; i < len(v.Interfaces()); i++ {
|
||||||
@ -137,7 +228,6 @@ func (c CGenDao) Dao(ctx context.Context, in CGenDaoInput) (out *CGenDaoOutput,
|
|||||||
} else {
|
} else {
|
||||||
doGenDaoForArray(ctx, -1, in)
|
doGenDaoForArray(ctx, -1, in)
|
||||||
}
|
}
|
||||||
doClear(in.genItems)
|
|
||||||
mlog.Print("done!")
|
mlog.Print("done!")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -165,12 +255,9 @@ func doGenDaoForArray(ctx context.Context, index int, in CGenDaoInput) {
|
|||||||
// It uses user passed database configuration.
|
// It uses user passed database configuration.
|
||||||
if in.Link != "" {
|
if in.Link != "" {
|
||||||
var tempGroup = gtime.TimestampNanoStr()
|
var tempGroup = gtime.TimestampNanoStr()
|
||||||
err = gdb.AddConfigNode(tempGroup, gdb.ConfigNode{
|
gdb.AddConfigNode(tempGroup, gdb.ConfigNode{
|
||||||
Link: in.Link,
|
Link: in.Link,
|
||||||
})
|
})
|
||||||
if err != nil {
|
|
||||||
mlog.Fatalf(`database configuration failed: %+v`, err)
|
|
||||||
}
|
|
||||||
if db, err = gdb.Instance(tempGroup); err != nil {
|
if db, err = gdb.Instance(tempGroup); err != nil {
|
||||||
mlog.Fatalf(`database initialization failed: %+v`, err)
|
mlog.Fatalf(`database initialization failed: %+v`, err)
|
||||||
}
|
}
|
||||||
@ -193,29 +280,8 @@ func doGenDaoForArray(ctx context.Context, index int, in CGenDaoInput) {
|
|||||||
// Table excluding.
|
// Table excluding.
|
||||||
if in.TablesEx != "" {
|
if in.TablesEx != "" {
|
||||||
array := garray.NewStrArrayFrom(tableNames)
|
array := garray.NewStrArrayFrom(tableNames)
|
||||||
for _, p := range gstr.SplitAndTrim(in.TablesEx, ",") {
|
for _, v := range gstr.SplitAndTrim(in.TablesEx, ",") {
|
||||||
if gstr.Contains(p, "*") || gstr.Contains(p, "?") {
|
array.RemoveValue(v)
|
||||||
p = gstr.ReplaceByMap(p, map[string]string{
|
|
||||||
"\r": "",
|
|
||||||
"\n": "",
|
|
||||||
})
|
|
||||||
p = gstr.ReplaceByMap(p, map[string]string{
|
|
||||||
"*": "\r",
|
|
||||||
"?": "\n",
|
|
||||||
})
|
|
||||||
p = gregex.Quote(p)
|
|
||||||
p = gstr.ReplaceByMap(p, map[string]string{
|
|
||||||
"\r": ".*",
|
|
||||||
"\n": ".",
|
|
||||||
})
|
|
||||||
for _, v := range array.Clone().Slice() {
|
|
||||||
if gregex.IsMatchString(p, v) {
|
|
||||||
array.RemoveValue(v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
array.RemoveValue(p)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
tableNames = array.Slice()
|
tableNames = array.Slice()
|
||||||
}
|
}
|
||||||
@ -232,63 +298,22 @@ func doGenDaoForArray(ctx context.Context, index int, in CGenDaoInput) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Generating dao & model go files one by one according to given table name.
|
// Generating dao & model go files one by one according to given table name.
|
||||||
var (
|
newTableNames := make([]string, len(tableNames))
|
||||||
newTableNames = make([]string, len(tableNames))
|
|
||||||
shardingNewTableSet = gset.NewStrSet()
|
|
||||||
)
|
|
||||||
for i, tableName := range tableNames {
|
for i, tableName := range tableNames {
|
||||||
newTableName := tableName
|
newTableName := tableName
|
||||||
for _, v := range removePrefixArray {
|
for _, v := range removePrefixArray {
|
||||||
newTableName = gstr.TrimLeftStr(newTableName, v, 1)
|
newTableName = gstr.TrimLeftStr(newTableName, v, 1)
|
||||||
}
|
}
|
||||||
if len(in.ShardingPattern) > 0 {
|
|
||||||
for _, pattern := range in.ShardingPattern {
|
|
||||||
var (
|
|
||||||
match []string
|
|
||||||
regPattern = gstr.Replace(pattern, "?", `(.+)`)
|
|
||||||
)
|
|
||||||
match, err = gregex.MatchString(regPattern, newTableName)
|
|
||||||
if err != nil {
|
|
||||||
mlog.Fatalf(`invalid sharding pattern "%s": %+v`, pattern, err)
|
|
||||||
}
|
|
||||||
if len(match) < 2 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
newTableName = gstr.Replace(pattern, "?", "")
|
|
||||||
newTableName = gstr.Trim(newTableName, `_.-`)
|
|
||||||
if shardingNewTableSet.Contains(newTableName) {
|
|
||||||
tableNames[i] = ""
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
// Add prefix to sharding table name, if not, the isSharding check would not match.
|
|
||||||
shardingNewTableSet.Add(in.Prefix + newTableName)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
newTableName = in.Prefix + newTableName
|
newTableName = in.Prefix + newTableName
|
||||||
if tableNames[i] != "" {
|
newTableNames[i] = newTableName
|
||||||
// If shardingNewTableSet contains newTableName (tableName is empty), it should not be added to tableNames, make it empty and filter later.
|
|
||||||
newTableNames[i] = newTableName
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
tableNames = garray.NewStrArrayFrom(tableNames).FilterEmpty().Slice()
|
|
||||||
newTableNames = garray.NewStrArrayFrom(newTableNames).FilterEmpty().Slice() // Filter empty table names. make sure that newTableNames and tableNames have the same length.
|
|
||||||
in.genItems.Scale()
|
|
||||||
|
|
||||||
// Dao: index and internal.
|
// Dao: index and internal.
|
||||||
generateDao(ctx, CGenDaoInternalInput{
|
generateDao(ctx, CGenDaoInternalInput{
|
||||||
CGenDaoInput: in,
|
CGenDaoInput: in,
|
||||||
DB: db,
|
DB: db,
|
||||||
TableNames: tableNames,
|
TableNames: tableNames,
|
||||||
NewTableNames: newTableNames,
|
NewTableNames: newTableNames,
|
||||||
ShardingTableSet: shardingNewTableSet,
|
|
||||||
})
|
|
||||||
// Table: table fields.
|
|
||||||
generateTable(ctx, CGenDaoInternalInput{
|
|
||||||
CGenDaoInput: in,
|
|
||||||
DB: db,
|
|
||||||
TableNames: tableNames,
|
|
||||||
NewTableNames: newTableNames,
|
|
||||||
ShardingTableSet: shardingNewTableSet,
|
|
||||||
})
|
})
|
||||||
// Do.
|
// Do.
|
||||||
generateDo(ctx, CGenDaoInternalInput{
|
generateDo(ctx, CGenDaoInternalInput{
|
||||||
@ -304,8 +329,6 @@ func doGenDaoForArray(ctx context.Context, index int, in CGenDaoInput) {
|
|||||||
TableNames: tableNames,
|
TableNames: tableNames,
|
||||||
NewTableNames: newTableNames,
|
NewTableNames: newTableNames,
|
||||||
})
|
})
|
||||||
|
|
||||||
in.genItems.SetClear(in.Clear)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func getImportPartContent(ctx context.Context, source string, isDo bool, appendImports []string) string {
|
func getImportPartContent(ctx context.Context, source string, isDo bool, appendImports []string) string {
|
||||||
@ -327,7 +350,7 @@ func getImportPartContent(ctx context.Context, source string, isDo bool, appendI
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check and update imports in go.mod
|
// Check and update imports in go.mod
|
||||||
if len(appendImports) > 0 {
|
if appendImports != nil && len(appendImports) > 0 {
|
||||||
goModPath := utils.GetModPath()
|
goModPath := utils.GetModPath()
|
||||||
if goModPath == "" {
|
if goModPath == "" {
|
||||||
mlog.Fatal("go.mod not found in current project")
|
mlog.Fatal("go.mod not found in current project")
|
||||||
@ -345,9 +368,8 @@ func getImportPartContent(ctx context.Context, source string, isDo bool, appendI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !found {
|
if !found {
|
||||||
if err = gproc.ShellRun(ctx, `go get `+appendImport); err != nil {
|
err = gproc.ShellRun(ctx, `go get `+appendImport)
|
||||||
mlog.Fatalf(`%+v`, err)
|
mlog.Fatalf(`%+v`, err)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
packageImportsArray.Append(fmt.Sprintf(`"%s"`, appendImport))
|
packageImportsArray.Append(fmt.Sprintf(`"%s"`, appendImport))
|
||||||
}
|
}
|
||||||
@ -361,15 +383,13 @@ func getImportPartContent(ctx context.Context, source string, isDo bool, appendI
|
|||||||
return packageImportsStr
|
return packageImportsStr
|
||||||
}
|
}
|
||||||
|
|
||||||
func assignDefaultVar(view *gview.View, in CGenDaoInternalInput) {
|
func replaceDefaultVar(in CGenDaoInternalInput, origin string) string {
|
||||||
var (
|
var tplCreatedAtDatetimeStr string
|
||||||
tplCreatedAtDatetimeStr string
|
var tplDatetimeStr string = createdAt.String()
|
||||||
tplDatetimeStr = createdAt.String()
|
|
||||||
)
|
|
||||||
if in.WithTime {
|
if in.WithTime {
|
||||||
tplCreatedAtDatetimeStr = fmt.Sprintf(`Created at %s`, tplDatetimeStr)
|
tplCreatedAtDatetimeStr = fmt.Sprintf(`Created at %s`, tplDatetimeStr)
|
||||||
}
|
}
|
||||||
view.Assigns(g.Map{
|
return gstr.ReplaceByMap(origin, g.MapStrStr{
|
||||||
tplVarDatetimeStr: tplDatetimeStr,
|
tplVarDatetimeStr: tplDatetimeStr,
|
||||||
tplVarCreatedAtDatetimeStr: tplCreatedAtDatetimeStr,
|
tplVarCreatedAtDatetimeStr: tplCreatedAtDatetimeStr,
|
||||||
})
|
})
|
||||||
|
|||||||
@ -7,40 +7,22 @@
|
|||||||
package gendao
|
package gendao
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
"github.com/gogf/gf/v2/os/gfile"
|
"github.com/gogf/gf/v2/os/gfile"
|
||||||
"github.com/gogf/gf/v2/text/gstr"
|
|
||||||
|
|
||||||
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
|
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
|
||||||
|
"github.com/gogf/gf/cmd/gf/v2/internal/utility/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
func doClear(items *CGenDaoInternalGenItems) {
|
func doClear(ctx context.Context, dirPath string, force bool) {
|
||||||
var allGeneratedFilePaths = make([]string, 0)
|
files, err := gfile.ScanDirFile(dirPath, "*.go", true)
|
||||||
for _, item := range items.Items {
|
if err != nil {
|
||||||
allGeneratedFilePaths = append(allGeneratedFilePaths, item.GeneratedFilePaths...)
|
mlog.Fatal(err)
|
||||||
}
|
}
|
||||||
for i, v := range allGeneratedFilePaths {
|
for _, file := range files {
|
||||||
allGeneratedFilePaths[i] = gfile.RealPath(v)
|
if force || utils.IsFileDoNotEdit(file) {
|
||||||
}
|
if err = gfile.Remove(file); err != nil {
|
||||||
for _, item := range items.Items {
|
|
||||||
if !item.Clear {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
doClearItem(item, allGeneratedFilePaths)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func doClearItem(item CGenDaoInternalGenItem, allGeneratedFilePaths []string) {
|
|
||||||
var generatedFilePaths = make([]string, 0)
|
|
||||||
for _, dirPath := range item.StorageDirPaths {
|
|
||||||
filePaths, err := gfile.ScanDirFile(dirPath, "*.go", true)
|
|
||||||
if err != nil {
|
|
||||||
mlog.Fatal(err)
|
|
||||||
}
|
|
||||||
generatedFilePaths = append(generatedFilePaths, filePaths...)
|
|
||||||
}
|
|
||||||
for _, filePath := range generatedFilePaths {
|
|
||||||
if !gstr.InArray(allGeneratedFilePaths, filePath) {
|
|
||||||
if err := gfile.RemoveFile(filePath); err != nil {
|
|
||||||
mlog.Print(err)
|
mlog.Print(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -18,7 +18,6 @@ import (
|
|||||||
"github.com/gogf/gf/v2/database/gdb"
|
"github.com/gogf/gf/v2/database/gdb"
|
||||||
"github.com/gogf/gf/v2/frame/g"
|
"github.com/gogf/gf/v2/frame/g"
|
||||||
"github.com/gogf/gf/v2/os/gfile"
|
"github.com/gogf/gf/v2/os/gfile"
|
||||||
"github.com/gogf/gf/v2/os/gview"
|
|
||||||
"github.com/gogf/gf/v2/text/gstr"
|
"github.com/gogf/gf/v2/text/gstr"
|
||||||
|
|
||||||
"github.com/gogf/gf/cmd/gf/v2/internal/consts"
|
"github.com/gogf/gf/cmd/gf/v2/internal/consts"
|
||||||
@ -31,32 +30,26 @@ func generateDao(ctx context.Context, in CGenDaoInternalInput) {
|
|||||||
dirPathDao = gfile.Join(in.Path, in.DaoPath)
|
dirPathDao = gfile.Join(in.Path, in.DaoPath)
|
||||||
dirPathDaoInternal = gfile.Join(dirPathDao, "internal")
|
dirPathDaoInternal = gfile.Join(dirPathDao, "internal")
|
||||||
)
|
)
|
||||||
in.genItems.AppendDirPath(dirPathDao)
|
if in.Clear {
|
||||||
|
doClear(ctx, dirPathDao, true)
|
||||||
|
}
|
||||||
for i := 0; i < len(in.TableNames); i++ {
|
for i := 0; i < len(in.TableNames); i++ {
|
||||||
var (
|
|
||||||
realTableName = in.TableNames[i]
|
|
||||||
newTableName = in.NewTableNames[i]
|
|
||||||
)
|
|
||||||
generateDaoSingle(ctx, generateDaoSingleInput{
|
generateDaoSingle(ctx, generateDaoSingleInput{
|
||||||
CGenDaoInternalInput: in,
|
CGenDaoInternalInput: in,
|
||||||
TableName: realTableName,
|
TableName: in.TableNames[i],
|
||||||
NewTableName: newTableName,
|
NewTableName: in.NewTableNames[i],
|
||||||
DirPathDao: dirPathDao,
|
DirPathDao: dirPathDao,
|
||||||
DirPathDaoInternal: dirPathDaoInternal,
|
DirPathDaoInternal: dirPathDaoInternal,
|
||||||
IsSharding: in.ShardingTableSet.Contains(newTableName),
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type generateDaoSingleInput struct {
|
type generateDaoSingleInput struct {
|
||||||
CGenDaoInternalInput
|
CGenDaoInternalInput
|
||||||
// TableName specifies the table name of the table.
|
TableName string // TableName specifies the table name of the table.
|
||||||
TableName string
|
NewTableName string // NewTableName specifies the prefix-stripped name of the table.
|
||||||
// NewTableName specifies the prefix-stripped or custom edited name of the table.
|
|
||||||
NewTableName string
|
|
||||||
DirPathDao string
|
DirPathDao string
|
||||||
DirPathDaoInternal string
|
DirPathDaoInternal string
|
||||||
IsSharding bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// generateDaoSingle generates the dao and model content of given table.
|
// generateDaoSingle generates the dao and model content of given table.
|
||||||
@ -67,8 +60,8 @@ func generateDaoSingle(ctx context.Context, in generateDaoSingleInput) {
|
|||||||
mlog.Fatalf(`fetching tables fields failed for table "%s": %+v`, in.TableName, err)
|
mlog.Fatalf(`fetching tables fields failed for table "%s": %+v`, in.TableName, err)
|
||||||
}
|
}
|
||||||
var (
|
var (
|
||||||
tableNameCamelCase = formatFieldName(in.NewTableName, FieldNameCaseCamel)
|
tableNameCamelCase = gstr.CaseCamel(in.NewTableName)
|
||||||
tableNameCamelLowerCase = formatFieldName(in.NewTableName, FieldNameCaseCamelLower)
|
tableNameCamelLowerCase = gstr.CaseCamelLower(in.NewTableName)
|
||||||
tableNameSnakeCase = gstr.CaseSnake(in.NewTableName)
|
tableNameSnakeCase = gstr.CaseSnake(in.NewTableName)
|
||||||
importPrefix = in.ImportPrefix
|
importPrefix = in.ImportPrefix
|
||||||
)
|
)
|
||||||
@ -115,34 +108,21 @@ type generateDaoIndexInput struct {
|
|||||||
|
|
||||||
func generateDaoIndex(in generateDaoIndexInput) {
|
func generateDaoIndex(in generateDaoIndexInput) {
|
||||||
path := filepath.FromSlash(gfile.Join(in.DirPathDao, in.FileName+".go"))
|
path := filepath.FromSlash(gfile.Join(in.DirPathDao, in.FileName+".go"))
|
||||||
// It should add path to result slice whenever it would generate the path file or not.
|
|
||||||
in.genItems.AppendGeneratedFilePath(path)
|
|
||||||
if in.OverwriteDao || !gfile.Exists(path) {
|
if in.OverwriteDao || !gfile.Exists(path) {
|
||||||
var (
|
indexContent := gstr.ReplaceByMap(
|
||||||
ctx = context.Background()
|
getTemplateFromPathOrDefault(in.TplDaoIndexPath, consts.TemplateGenDaoIndexContent),
|
||||||
tplContent = getTemplateFromPathOrDefault(
|
g.MapStrStr{
|
||||||
in.TplDaoIndexPath, consts.TemplateGenDaoIndexContent,
|
tplVarImportPrefix: in.ImportPrefix,
|
||||||
)
|
tplVarTableName: in.TableName,
|
||||||
)
|
tplVarTableNameCamelCase: in.TableNameCamelCase,
|
||||||
tplView.ClearAssigns()
|
tplVarTableNameCamelLowerCase: in.TableNameCamelLowerCase,
|
||||||
tplView.Assigns(gview.Params{
|
})
|
||||||
tplVarTableSharding: in.IsSharding,
|
indexContent = replaceDefaultVar(in.CGenDaoInternalInput, indexContent)
|
||||||
tplVarTableShardingPrefix: in.NewTableName + "_",
|
if err := gfile.PutContents(path, strings.TrimSpace(indexContent)); err != nil {
|
||||||
tplVarImportPrefix: in.ImportPrefix,
|
|
||||||
tplVarTableName: in.TableName,
|
|
||||||
tplVarTableNameCamelCase: in.TableNameCamelCase,
|
|
||||||
tplVarTableNameCamelLowerCase: in.TableNameCamelLowerCase,
|
|
||||||
tplVarPackageName: filepath.Base(in.DaoPath),
|
|
||||||
})
|
|
||||||
indexContent, err := tplView.ParseContent(ctx, tplContent)
|
|
||||||
if err != nil {
|
|
||||||
mlog.Fatalf("parsing template content failed: %v", err)
|
|
||||||
}
|
|
||||||
if err = gfile.PutContents(path, strings.TrimSpace(indexContent)); err != nil {
|
|
||||||
mlog.Fatalf("writing content to '%s' failed: %v", path, err)
|
mlog.Fatalf("writing content to '%s' failed: %v", path, err)
|
||||||
} else {
|
} else {
|
||||||
utils.GoFmt(path)
|
utils.GoFmt(path)
|
||||||
mlog.Print("generated:", gfile.RealPath(path))
|
mlog.Print("generated:", path)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -157,63 +137,49 @@ type generateDaoInternalInput struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func generateDaoInternal(in generateDaoInternalInput) {
|
func generateDaoInternal(in generateDaoInternalInput) {
|
||||||
var (
|
|
||||||
ctx = context.Background()
|
|
||||||
removeFieldPrefixArray = gstr.SplitAndTrim(in.RemoveFieldPrefix, ",")
|
|
||||||
tplContent = getTemplateFromPathOrDefault(
|
|
||||||
in.TplDaoInternalPath, consts.TemplateGenDaoInternalContent,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
tplView.ClearAssigns()
|
|
||||||
tplView.Assigns(gview.Params{
|
|
||||||
tplVarImportPrefix: in.ImportPrefix,
|
|
||||||
tplVarTableName: in.TableName,
|
|
||||||
tplVarGroupName: in.Group,
|
|
||||||
tplVarTableNameCamelCase: in.TableNameCamelCase,
|
|
||||||
tplVarTableNameCamelLowerCase: in.TableNameCamelLowerCase,
|
|
||||||
tplVarColumnDefine: gstr.Trim(generateColumnDefinitionForDao(in.FieldMap, removeFieldPrefixArray)),
|
|
||||||
tplVarColumnNames: gstr.Trim(generateColumnNamesForDao(in.FieldMap, removeFieldPrefixArray)),
|
|
||||||
})
|
|
||||||
assignDefaultVar(tplView, in.CGenDaoInternalInput)
|
|
||||||
modelContent, err := tplView.ParseContent(ctx, tplContent)
|
|
||||||
if err != nil {
|
|
||||||
mlog.Fatalf("parsing template content failed: %v", err)
|
|
||||||
}
|
|
||||||
path := filepath.FromSlash(gfile.Join(in.DirPathDaoInternal, in.FileName+".go"))
|
path := filepath.FromSlash(gfile.Join(in.DirPathDaoInternal, in.FileName+".go"))
|
||||||
in.genItems.AppendGeneratedFilePath(path)
|
modelContent := gstr.ReplaceByMap(
|
||||||
|
getTemplateFromPathOrDefault(in.TplDaoInternalPath, consts.TemplateGenDaoInternalContent),
|
||||||
|
g.MapStrStr{
|
||||||
|
tplVarImportPrefix: in.ImportPrefix,
|
||||||
|
tplVarTableName: in.TableName,
|
||||||
|
tplVarGroupName: in.Group,
|
||||||
|
tplVarTableNameCamelCase: in.TableNameCamelCase,
|
||||||
|
tplVarTableNameCamelLowerCase: in.TableNameCamelLowerCase,
|
||||||
|
tplVarColumnDefine: gstr.Trim(generateColumnDefinitionForDao(in.FieldMap)),
|
||||||
|
tplVarColumnNames: gstr.Trim(generateColumnNamesForDao(in.FieldMap)),
|
||||||
|
})
|
||||||
|
modelContent = replaceDefaultVar(in.CGenDaoInternalInput, modelContent)
|
||||||
if err := gfile.PutContents(path, strings.TrimSpace(modelContent)); err != nil {
|
if err := gfile.PutContents(path, strings.TrimSpace(modelContent)); err != nil {
|
||||||
mlog.Fatalf("writing content to '%s' failed: %v", path, err)
|
mlog.Fatalf("writing content to '%s' failed: %v", path, err)
|
||||||
} else {
|
} else {
|
||||||
utils.GoFmt(path)
|
utils.GoFmt(path)
|
||||||
mlog.Print("generated:", gfile.RealPath(path))
|
mlog.Print("generated:", path)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// generateColumnNamesForDao generates and returns the column names assignment content of column struct
|
// generateColumnNamesForDao generates and returns the column names assignment content of column struct
|
||||||
// for specified table.
|
// for specified table.
|
||||||
func generateColumnNamesForDao(fieldMap map[string]*gdb.TableField, removeFieldPrefixArray []string) string {
|
func generateColumnNamesForDao(fieldMap map[string]*gdb.TableField) string {
|
||||||
var (
|
var (
|
||||||
buffer = bytes.NewBuffer(nil)
|
buffer = bytes.NewBuffer(nil)
|
||||||
array = make([][]string, len(fieldMap))
|
array = make([][]string, len(fieldMap))
|
||||||
names = sortFieldKeyForDao(fieldMap)
|
names = sortFieldKeyForDao(fieldMap)
|
||||||
)
|
)
|
||||||
|
|
||||||
for index, name := range names {
|
for index, name := range names {
|
||||||
field := fieldMap[name]
|
field := fieldMap[name]
|
||||||
|
|
||||||
newFiledName := field.Name
|
|
||||||
for _, v := range removeFieldPrefixArray {
|
|
||||||
newFiledName = gstr.TrimLeftStr(newFiledName, v, 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
array[index] = []string{
|
array[index] = []string{
|
||||||
" #" + formatFieldName(newFiledName, FieldNameCaseCamel) + ":",
|
" #" + gstr.CaseCamel(field.Name) + ":",
|
||||||
fmt.Sprintf(` #"%s",`, field.Name),
|
fmt.Sprintf(` #"%s",`, field.Name),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
table := tablewriter.NewTable(buffer, twRenderer, twConfig)
|
tw := tablewriter.NewWriter(buffer)
|
||||||
table.Bulk(array)
|
tw.SetBorder(false)
|
||||||
table.Render()
|
tw.SetRowLine(false)
|
||||||
|
tw.SetAutoWrapText(false)
|
||||||
|
tw.SetColumnSeparator("")
|
||||||
|
tw.AppendBulk(array)
|
||||||
|
tw.Render()
|
||||||
namesContent := buffer.String()
|
namesContent := buffer.String()
|
||||||
// Let's do this hack of table writer for indent!
|
// Let's do this hack of table writer for indent!
|
||||||
namesContent = gstr.Replace(namesContent, " #", "")
|
namesContent = gstr.Replace(namesContent, " #", "")
|
||||||
@ -223,13 +189,12 @@ func generateColumnNamesForDao(fieldMap map[string]*gdb.TableField, removeFieldP
|
|||||||
}
|
}
|
||||||
|
|
||||||
// generateColumnDefinitionForDao generates and returns the column names definition for specified table.
|
// generateColumnDefinitionForDao generates and returns the column names definition for specified table.
|
||||||
func generateColumnDefinitionForDao(fieldMap map[string]*gdb.TableField, removeFieldPrefixArray []string) string {
|
func generateColumnDefinitionForDao(fieldMap map[string]*gdb.TableField) string {
|
||||||
var (
|
var (
|
||||||
buffer = bytes.NewBuffer(nil)
|
buffer = bytes.NewBuffer(nil)
|
||||||
array = make([][]string, len(fieldMap))
|
array = make([][]string, len(fieldMap))
|
||||||
names = sortFieldKeyForDao(fieldMap)
|
names = sortFieldKeyForDao(fieldMap)
|
||||||
)
|
)
|
||||||
|
|
||||||
for index, name := range names {
|
for index, name := range names {
|
||||||
var (
|
var (
|
||||||
field = fieldMap[name]
|
field = fieldMap[name]
|
||||||
@ -238,19 +203,19 @@ func generateColumnDefinitionForDao(fieldMap map[string]*gdb.TableField, removeF
|
|||||||
"\r", " ",
|
"\r", " ",
|
||||||
}))
|
}))
|
||||||
)
|
)
|
||||||
newFiledName := field.Name
|
|
||||||
for _, v := range removeFieldPrefixArray {
|
|
||||||
newFiledName = gstr.TrimLeftStr(newFiledName, v, 1)
|
|
||||||
}
|
|
||||||
array[index] = []string{
|
array[index] = []string{
|
||||||
" #" + formatFieldName(newFiledName, FieldNameCaseCamel),
|
" #" + gstr.CaseCamel(field.Name),
|
||||||
" # " + "string",
|
" # " + "string",
|
||||||
" #" + fmt.Sprintf(`// %s`, comment),
|
" #" + fmt.Sprintf(`// %s`, comment),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
table := tablewriter.NewTable(buffer, twRenderer, twConfig)
|
tw := tablewriter.NewWriter(buffer)
|
||||||
table.Bulk(array)
|
tw.SetBorder(false)
|
||||||
table.Render()
|
tw.SetRowLine(false)
|
||||||
|
tw.SetAutoWrapText(false)
|
||||||
|
tw.SetColumnSeparator("")
|
||||||
|
tw.AppendBulk(array)
|
||||||
|
tw.Render()
|
||||||
defineContent := buffer.String()
|
defineContent := buffer.String()
|
||||||
// Let's do this hack of table writer for indent!
|
// Let's do this hack of table writer for indent!
|
||||||
defineContent = gstr.Replace(defineContent, " #", "")
|
defineContent = gstr.Replace(defineContent, " #", "")
|
||||||
|
|||||||
@ -12,8 +12,8 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/gogf/gf/v2/frame/g"
|
||||||
"github.com/gogf/gf/v2/os/gfile"
|
"github.com/gogf/gf/v2/os/gfile"
|
||||||
"github.com/gogf/gf/v2/os/gview"
|
|
||||||
"github.com/gogf/gf/v2/text/gregex"
|
"github.com/gogf/gf/v2/text/gregex"
|
||||||
"github.com/gogf/gf/v2/text/gstr"
|
"github.com/gogf/gf/v2/text/gstr"
|
||||||
|
|
||||||
@ -24,7 +24,9 @@ import (
|
|||||||
|
|
||||||
func generateDo(ctx context.Context, in CGenDaoInternalInput) {
|
func generateDo(ctx context.Context, in CGenDaoInternalInput) {
|
||||||
var dirPathDo = filepath.FromSlash(gfile.Join(in.Path, in.DoPath))
|
var dirPathDo = filepath.FromSlash(gfile.Join(in.Path, in.DoPath))
|
||||||
in.genItems.AppendDirPath(dirPathDo)
|
if in.Clear {
|
||||||
|
doClear(ctx, dirPathDo, false)
|
||||||
|
}
|
||||||
in.NoJsonTag = true
|
in.NoJsonTag = true
|
||||||
in.DescriptionTag = false
|
in.DescriptionTag = false
|
||||||
in.NoModelComment = false
|
in.NoModelComment = false
|
||||||
@ -40,19 +42,19 @@ func generateDo(ctx context.Context, in CGenDaoInternalInput) {
|
|||||||
structDefinition, _ = generateStructDefinition(ctx, generateStructDefinitionInput{
|
structDefinition, _ = generateStructDefinition(ctx, generateStructDefinitionInput{
|
||||||
CGenDaoInternalInput: in,
|
CGenDaoInternalInput: in,
|
||||||
TableName: tableName,
|
TableName: tableName,
|
||||||
StructName: formatFieldName(newTableName, FieldNameCaseCamel),
|
StructName: gstr.CaseCamel(newTableName),
|
||||||
FieldMap: fieldMap,
|
FieldMap: fieldMap,
|
||||||
IsDo: true,
|
IsDo: true,
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
// replace all types to any.
|
// replace all types to interface{}.
|
||||||
structDefinition, _ = gregex.ReplaceStringFuncMatch(
|
structDefinition, _ = gregex.ReplaceStringFuncMatch(
|
||||||
"([A-Z]\\w*?)\\s+([\\w\\*\\.]+?)\\s+(//)",
|
"([A-Z]\\w*?)\\s+([\\w\\*\\.]+?)\\s+(//)",
|
||||||
structDefinition,
|
structDefinition,
|
||||||
func(match []string) string {
|
func(match []string) string {
|
||||||
// If the type is already a pointer/slice/map, it does nothing.
|
// If the type is already a pointer/slice/map, it does nothing.
|
||||||
if !gstr.HasPrefix(match[2], "*") && !gstr.HasPrefix(match[2], "[]") && !gstr.HasPrefix(match[2], "map") {
|
if !gstr.HasPrefix(match[2], "*") && !gstr.HasPrefix(match[2], "[]") && !gstr.HasPrefix(match[2], "map") {
|
||||||
return fmt.Sprintf(`%s any %s`, match[1], match[3])
|
return fmt.Sprintf(`%s interface{} %s`, match[1], match[3])
|
||||||
}
|
}
|
||||||
return match[0]
|
return match[0]
|
||||||
},
|
},
|
||||||
@ -61,16 +63,15 @@ func generateDo(ctx context.Context, in CGenDaoInternalInput) {
|
|||||||
ctx,
|
ctx,
|
||||||
in,
|
in,
|
||||||
tableName,
|
tableName,
|
||||||
formatFieldName(newTableName, FieldNameCaseCamel),
|
gstr.CaseCamel(newTableName),
|
||||||
structDefinition,
|
structDefinition,
|
||||||
)
|
)
|
||||||
in.genItems.AppendGeneratedFilePath(doFilePath)
|
|
||||||
err = gfile.PutContents(doFilePath, strings.TrimSpace(modelContent))
|
err = gfile.PutContents(doFilePath, strings.TrimSpace(modelContent))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
mlog.Fatalf(`writing content to "%s" failed: %v`, doFilePath, err)
|
mlog.Fatalf(`writing content to "%s" failed: %v`, doFilePath, err)
|
||||||
} else {
|
} else {
|
||||||
utils.GoFmt(doFilePath)
|
utils.GoFmt(doFilePath)
|
||||||
mlog.Print("generated:", gfile.RealPath(doFilePath))
|
mlog.Print("generated:", doFilePath)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -78,23 +79,15 @@ func generateDo(ctx context.Context, in CGenDaoInternalInput) {
|
|||||||
func generateDoContent(
|
func generateDoContent(
|
||||||
ctx context.Context, in CGenDaoInternalInput, tableName, tableNameCamelCase, structDefine string,
|
ctx context.Context, in CGenDaoInternalInput, tableName, tableNameCamelCase, structDefine string,
|
||||||
) string {
|
) string {
|
||||||
var (
|
doContent := gstr.ReplaceByMap(
|
||||||
tplContent = getTemplateFromPathOrDefault(
|
getTemplateFromPathOrDefault(in.TplDaoDoPath, consts.TemplateGenDaoDoContent),
|
||||||
in.TplDaoDoPath, consts.TemplateGenDaoDoContent,
|
g.MapStrStr{
|
||||||
)
|
tplVarTableName: tableName,
|
||||||
|
tplVarPackageImports: getImportPartContent(ctx, structDefine, true, nil),
|
||||||
|
tplVarTableNameCamelCase: tableNameCamelCase,
|
||||||
|
tplVarStructDefine: structDefine,
|
||||||
|
},
|
||||||
)
|
)
|
||||||
tplView.ClearAssigns()
|
doContent = replaceDefaultVar(in, doContent)
|
||||||
tplView.Assigns(gview.Params{
|
|
||||||
tplVarTableName: tableName,
|
|
||||||
tplVarPackageImports: getImportPartContent(ctx, structDefine, true, nil),
|
|
||||||
tplVarTableNameCamelCase: tableNameCamelCase,
|
|
||||||
tplVarStructDefine: structDefine,
|
|
||||||
tplVarPackageName: filepath.Base(in.DoPath),
|
|
||||||
})
|
|
||||||
assignDefaultVar(tplView, in)
|
|
||||||
doContent, err := tplView.ParseContent(ctx, tplContent)
|
|
||||||
if err != nil {
|
|
||||||
mlog.Fatalf("parsing template content failed: %v", err)
|
|
||||||
}
|
|
||||||
return doContent
|
return doContent
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,8 +11,8 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/gogf/gf/v2/frame/g"
|
||||||
"github.com/gogf/gf/v2/os/gfile"
|
"github.com/gogf/gf/v2/os/gfile"
|
||||||
"github.com/gogf/gf/v2/os/gview"
|
|
||||||
"github.com/gogf/gf/v2/text/gstr"
|
"github.com/gogf/gf/v2/text/gstr"
|
||||||
|
|
||||||
"github.com/gogf/gf/cmd/gf/v2/internal/consts"
|
"github.com/gogf/gf/cmd/gf/v2/internal/consts"
|
||||||
@ -22,7 +22,9 @@ import (
|
|||||||
|
|
||||||
func generateEntity(ctx context.Context, in CGenDaoInternalInput) {
|
func generateEntity(ctx context.Context, in CGenDaoInternalInput) {
|
||||||
var dirPathEntity = gfile.Join(in.Path, in.EntityPath)
|
var dirPathEntity = gfile.Join(in.Path, in.EntityPath)
|
||||||
in.genItems.AppendDirPath(dirPathEntity)
|
if in.Clear {
|
||||||
|
doClear(ctx, dirPathEntity, false)
|
||||||
|
}
|
||||||
// Model content.
|
// Model content.
|
||||||
for i, tableName := range in.TableNames {
|
for i, tableName := range in.TableNames {
|
||||||
fieldMap, err := in.DB.TableFields(ctx, tableName)
|
fieldMap, err := in.DB.TableFields(ctx, tableName)
|
||||||
@ -36,7 +38,7 @@ func generateEntity(ctx context.Context, in CGenDaoInternalInput) {
|
|||||||
structDefinition, appendImports = generateStructDefinition(ctx, generateStructDefinitionInput{
|
structDefinition, appendImports = generateStructDefinition(ctx, generateStructDefinitionInput{
|
||||||
CGenDaoInternalInput: in,
|
CGenDaoInternalInput: in,
|
||||||
TableName: tableName,
|
TableName: tableName,
|
||||||
StructName: formatFieldName(newTableName, FieldNameCaseCamel),
|
StructName: gstr.CaseCamel(newTableName),
|
||||||
FieldMap: fieldMap,
|
FieldMap: fieldMap,
|
||||||
IsDo: false,
|
IsDo: false,
|
||||||
})
|
})
|
||||||
@ -44,18 +46,18 @@ func generateEntity(ctx context.Context, in CGenDaoInternalInput) {
|
|||||||
ctx,
|
ctx,
|
||||||
in,
|
in,
|
||||||
newTableName,
|
newTableName,
|
||||||
formatFieldName(newTableName, FieldNameCaseCamel),
|
gstr.CaseCamel(newTableName),
|
||||||
structDefinition,
|
structDefinition,
|
||||||
appendImports,
|
appendImports,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
in.genItems.AppendGeneratedFilePath(entityFilePath)
|
|
||||||
err = gfile.PutContents(entityFilePath, strings.TrimSpace(entityContent))
|
err = gfile.PutContents(entityFilePath, strings.TrimSpace(entityContent))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
mlog.Fatalf("writing content to '%s' failed: %v", entityFilePath, err)
|
mlog.Fatalf("writing content to '%s' failed: %v", entityFilePath, err)
|
||||||
} else {
|
} else {
|
||||||
utils.GoFmt(entityFilePath)
|
utils.GoFmt(entityFilePath)
|
||||||
mlog.Print("generated:", gfile.RealPath(entityFilePath))
|
mlog.Print("generated:", entityFilePath)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -63,23 +65,15 @@ func generateEntity(ctx context.Context, in CGenDaoInternalInput) {
|
|||||||
func generateEntityContent(
|
func generateEntityContent(
|
||||||
ctx context.Context, in CGenDaoInternalInput, tableName, tableNameCamelCase, structDefine string, appendImports []string,
|
ctx context.Context, in CGenDaoInternalInput, tableName, tableNameCamelCase, structDefine string, appendImports []string,
|
||||||
) string {
|
) string {
|
||||||
var (
|
entityContent := gstr.ReplaceByMap(
|
||||||
tplContent = getTemplateFromPathOrDefault(
|
getTemplateFromPathOrDefault(in.TplDaoEntityPath, consts.TemplateGenDaoEntityContent),
|
||||||
in.TplDaoEntityPath, consts.TemplateGenDaoEntityContent,
|
g.MapStrStr{
|
||||||
)
|
tplVarTableName: tableName,
|
||||||
|
tplVarPackageImports: getImportPartContent(ctx, structDefine, false, appendImports),
|
||||||
|
tplVarTableNameCamelCase: tableNameCamelCase,
|
||||||
|
tplVarStructDefine: structDefine,
|
||||||
|
},
|
||||||
)
|
)
|
||||||
tplView.ClearAssigns()
|
entityContent = replaceDefaultVar(in, entityContent)
|
||||||
tplView.Assigns(gview.Params{
|
|
||||||
tplVarTableName: tableName,
|
|
||||||
tplVarPackageImports: getImportPartContent(ctx, structDefine, false, appendImports),
|
|
||||||
tplVarTableNameCamelCase: tableNameCamelCase,
|
|
||||||
tplVarStructDefine: structDefine,
|
|
||||||
tplVarPackageName: filepath.Base(in.EntityPath),
|
|
||||||
})
|
|
||||||
assignDefaultVar(tplView, in)
|
|
||||||
entityContent, err := tplView.ParseContent(ctx, tplContent)
|
|
||||||
if err != nil {
|
|
||||||
mlog.Fatalf("parsing template content failed: %v", err)
|
|
||||||
}
|
|
||||||
return entityContent
|
return entityContent
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,53 +0,0 @@
|
|||||||
// 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 gendao
|
|
||||||
|
|
||||||
type (
|
|
||||||
CGenDaoInternalGenItems struct {
|
|
||||||
index int
|
|
||||||
Items []CGenDaoInternalGenItem
|
|
||||||
}
|
|
||||||
CGenDaoInternalGenItem struct {
|
|
||||||
Clear bool
|
|
||||||
StorageDirPaths []string
|
|
||||||
GeneratedFilePaths []string
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
func newCGenDaoInternalGenItems() *CGenDaoInternalGenItems {
|
|
||||||
return &CGenDaoInternalGenItems{
|
|
||||||
index: -1,
|
|
||||||
Items: make([]CGenDaoInternalGenItem, 0),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i *CGenDaoInternalGenItems) Scale() {
|
|
||||||
i.Items = append(i.Items, CGenDaoInternalGenItem{
|
|
||||||
StorageDirPaths: make([]string, 0),
|
|
||||||
GeneratedFilePaths: make([]string, 0),
|
|
||||||
Clear: false,
|
|
||||||
})
|
|
||||||
i.index++
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i *CGenDaoInternalGenItems) SetClear(clear bool) {
|
|
||||||
i.Items[i.index].Clear = clear
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i *CGenDaoInternalGenItems) AppendDirPath(storageDirPath string) {
|
|
||||||
i.Items[i.index].StorageDirPaths = append(
|
|
||||||
i.Items[i.index].StorageDirPaths,
|
|
||||||
storageDirPath,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i *CGenDaoInternalGenItems) AppendGeneratedFilePath(generatedFilePath string) {
|
|
||||||
i.Items[i.index].GeneratedFilePaths = append(
|
|
||||||
i.Items[i.index].GeneratedFilePaths,
|
|
||||||
generatedFilePath,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@ -10,9 +10,8 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/olekukonko/tablewriter"
|
"github.com/olekukonko/tablewriter"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/gogf/gf/v2/database/gdb"
|
"github.com/gogf/gf/v2/database/gdb"
|
||||||
"github.com/gogf/gf/v2/frame/g"
|
"github.com/gogf/gf/v2/frame/g"
|
||||||
@ -41,55 +40,28 @@ func generateStructDefinition(ctx context.Context, in generateStructDefinitionIn
|
|||||||
appendImports = append(appendImports, imports)
|
appendImports = append(appendImports, imports)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
table := tablewriter.NewTable(buffer, twRenderer, twConfig)
|
tw := tablewriter.NewWriter(buffer)
|
||||||
table.Bulk(array)
|
tw.SetBorder(false)
|
||||||
table.Render()
|
tw.SetRowLine(false)
|
||||||
|
tw.SetAutoWrapText(false)
|
||||||
|
tw.SetColumnSeparator("")
|
||||||
|
tw.AppendBulk(array)
|
||||||
|
tw.Render()
|
||||||
stContent := buffer.String()
|
stContent := buffer.String()
|
||||||
// Let's do this hack of table writer for indent!
|
// Let's do this hack of table writer for indent!
|
||||||
stContent = gstr.Replace(stContent, " #", "")
|
stContent = gstr.Replace(stContent, " #", "")
|
||||||
stContent = gstr.Replace(stContent, "` ", "`")
|
stContent = gstr.Replace(stContent, "` ", "`")
|
||||||
stContent = gstr.Replace(stContent, "``", "")
|
stContent = gstr.Replace(stContent, "``", "")
|
||||||
buffer.Reset()
|
buffer.Reset()
|
||||||
fmt.Fprintf(buffer, "type %s struct {\n", in.StructName)
|
buffer.WriteString(fmt.Sprintf("type %s struct {\n", in.StructName))
|
||||||
if in.IsDo {
|
if in.IsDo {
|
||||||
fmt.Fprintf(buffer, "g.Meta `orm:\"table:%s, do:true\"`\n", in.TableName)
|
buffer.WriteString(fmt.Sprintf("g.Meta `orm:\"table:%s, do:true\"`\n", in.TableName))
|
||||||
}
|
}
|
||||||
buffer.WriteString(stContent)
|
buffer.WriteString(stContent)
|
||||||
buffer.WriteString("}")
|
buffer.WriteString("}")
|
||||||
return buffer.String(), appendImports
|
return buffer.String(), appendImports
|
||||||
}
|
}
|
||||||
|
|
||||||
func getTypeMappingInfo(
|
|
||||||
ctx context.Context, fieldType string, inTypeMapping map[DBFieldTypeName]CustomAttributeType,
|
|
||||||
) (typeNameStr, importStr string) {
|
|
||||||
if typeMapping, ok := inTypeMapping[strings.ToLower(fieldType)]; ok {
|
|
||||||
typeNameStr = typeMapping.Type
|
|
||||||
importStr = typeMapping.Import
|
|
||||||
return
|
|
||||||
}
|
|
||||||
tryTypeMatch, _ := gregex.MatchString(`(.+?)\(([^\(\)]+)\)([\s\)]*)`, fieldType)
|
|
||||||
var (
|
|
||||||
tryTypeName string
|
|
||||||
moreTry bool
|
|
||||||
)
|
|
||||||
if len(tryTypeMatch) == 4 {
|
|
||||||
tryTypeMatch3, _ := gregex.ReplaceString(`\s+`, "", tryTypeMatch[3])
|
|
||||||
tryTypeName = gstr.Trim(tryTypeMatch[1]) + tryTypeMatch3
|
|
||||||
moreTry = tryTypeMatch3 != ""
|
|
||||||
} else {
|
|
||||||
tryTypeName = gstr.Split(fieldType, " ")[0]
|
|
||||||
}
|
|
||||||
if tryTypeName != "" {
|
|
||||||
if typeMapping, ok := inTypeMapping[strings.ToLower(tryTypeName)]; ok {
|
|
||||||
typeNameStr = typeMapping.Type
|
|
||||||
importStr = typeMapping.Import
|
|
||||||
} else if moreTry {
|
|
||||||
typeNameStr, importStr = getTypeMappingInfo(ctx, tryTypeName, inTypeMapping)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// generateStructFieldDefinition generates and returns the attribute definition for specified field.
|
// generateStructFieldDefinition generates and returns the attribute definition for specified field.
|
||||||
func generateStructFieldDefinition(
|
func generateStructFieldDefinition(
|
||||||
ctx context.Context, field *gdb.TableField, in generateStructDefinitionInput,
|
ctx context.Context, field *gdb.TableField, in generateStructDefinitionInput,
|
||||||
@ -98,11 +70,25 @@ func generateStructFieldDefinition(
|
|||||||
err error
|
err error
|
||||||
localTypeName gdb.LocalType
|
localTypeName gdb.LocalType
|
||||||
localTypeNameStr string
|
localTypeNameStr string
|
||||||
jsonTag = gstr.CaseConvert(field.Name, gstr.CaseTypeMatch(in.JsonCase))
|
jsonTag = getJsonTagFromCase(field.Name, in.JsonCase)
|
||||||
)
|
)
|
||||||
|
|
||||||
if in.TypeMapping != nil && len(in.TypeMapping) > 0 {
|
if in.TypeMapping != nil && len(in.TypeMapping) > 0 {
|
||||||
localTypeNameStr, appendImport = getTypeMappingInfo(ctx, field.Type, in.TypeMapping)
|
var (
|
||||||
|
tryTypeName string
|
||||||
|
)
|
||||||
|
tryTypeMatch, _ := gregex.MatchString(`(.+?)\((.+)\)`, field.Type)
|
||||||
|
if len(tryTypeMatch) == 3 {
|
||||||
|
tryTypeName = gstr.Trim(tryTypeMatch[1])
|
||||||
|
} else {
|
||||||
|
tryTypeName = gstr.Split(field.Type, " ")[0]
|
||||||
|
}
|
||||||
|
if tryTypeName != "" {
|
||||||
|
if typeMapping, ok := in.TypeMapping[strings.ToLower(tryTypeName)]; ok {
|
||||||
|
localTypeNameStr = typeMapping.Type
|
||||||
|
appendImport = typeMapping.Import
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if localTypeNameStr == "" {
|
if localTypeNameStr == "" {
|
||||||
@ -112,7 +98,7 @@ func generateStructFieldDefinition(
|
|||||||
}
|
}
|
||||||
localTypeNameStr = string(localTypeName)
|
localTypeNameStr = string(localTypeName)
|
||||||
switch localTypeName {
|
switch localTypeName {
|
||||||
case gdb.LocalTypeDate, gdb.LocalTypeTime, gdb.LocalTypeDatetime:
|
case gdb.LocalTypeDate, gdb.LocalTypeDatetime:
|
||||||
if in.StdTime {
|
if in.StdTime {
|
||||||
localTypeNameStr = "time.Time"
|
localTypeNameStr = "time.Time"
|
||||||
} else {
|
} else {
|
||||||
@ -139,31 +125,13 @@ func generateStructFieldDefinition(
|
|||||||
tagKey = "`"
|
tagKey = "`"
|
||||||
descriptionTag = gstr.Replace(formatComment(field.Comment), `"`, `\"`)
|
descriptionTag = gstr.Replace(formatComment(field.Comment), `"`, `\"`)
|
||||||
)
|
)
|
||||||
removeFieldPrefixArray := gstr.SplitAndTrim(in.RemoveFieldPrefix, ",")
|
|
||||||
newFiledName := field.Name
|
|
||||||
for _, v := range removeFieldPrefixArray {
|
|
||||||
newFiledName = gstr.TrimLeftStr(newFiledName, v, 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
if in.FieldMapping != nil && len(in.FieldMapping) > 0 {
|
|
||||||
if typeMapping, ok := in.FieldMapping[fmt.Sprintf("%s.%s", in.TableName, newFiledName)]; ok {
|
|
||||||
localTypeNameStr = typeMapping.Type
|
|
||||||
appendImport = typeMapping.Import
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
attrLines = []string{
|
attrLines = []string{
|
||||||
" #" + formatFieldName(newFiledName, FieldNameCaseCamel),
|
" #" + gstr.CaseCamel(field.Name),
|
||||||
" #" + localTypeNameStr,
|
" #" + localTypeNameStr,
|
||||||
}
|
}
|
||||||
attrLines = append(attrLines, fmt.Sprintf(` #%sjson:"%s"`, tagKey, jsonTag))
|
attrLines = append(attrLines, " #"+fmt.Sprintf(tagKey+`json:"%s"`, jsonTag))
|
||||||
// orm tag
|
attrLines = append(attrLines, " #"+fmt.Sprintf(`description:"%s"`+tagKey, descriptionTag))
|
||||||
if !in.IsDo {
|
attrLines = append(attrLines, " #"+fmt.Sprintf(`// %s`, formatComment(field.Comment)))
|
||||||
// entity
|
|
||||||
attrLines = append(attrLines, fmt.Sprintf(` #orm:"%s"`, field.Name))
|
|
||||||
}
|
|
||||||
attrLines = append(attrLines, fmt.Sprintf(` #description:"%s"%s`, descriptionTag, tagKey))
|
|
||||||
attrLines = append(attrLines, fmt.Sprintf(` #// %s`, formatComment(field.Comment)))
|
|
||||||
|
|
||||||
for k, v := range attrLines {
|
for k, v := range attrLines {
|
||||||
if in.NoJsonTag {
|
if in.NoJsonTag {
|
||||||
@ -180,43 +148,6 @@ func generateStructFieldDefinition(
|
|||||||
return attrLines, appendImport
|
return attrLines, appendImport
|
||||||
}
|
}
|
||||||
|
|
||||||
type FieldNameCase string
|
|
||||||
|
|
||||||
const (
|
|
||||||
FieldNameCaseCamel FieldNameCase = "CaseCamel"
|
|
||||||
FieldNameCaseCamelLower FieldNameCase = "CaseCamelLower"
|
|
||||||
)
|
|
||||||
|
|
||||||
// formatFieldName formats and returns a new field name that is used for golang codes generating.
|
|
||||||
func formatFieldName(fieldName string, nameCase FieldNameCase) string {
|
|
||||||
// For normal databases like mysql, pgsql, sqlite,
|
|
||||||
// field/table names of that are in normal case.
|
|
||||||
var newFieldName = fieldName
|
|
||||||
if isAllUpper(fieldName) {
|
|
||||||
// For special databases like dm, oracle,
|
|
||||||
// field/table names of that are in upper case.
|
|
||||||
newFieldName = strings.ToLower(fieldName)
|
|
||||||
}
|
|
||||||
switch nameCase {
|
|
||||||
case FieldNameCaseCamel:
|
|
||||||
return gstr.CaseCamel(newFieldName)
|
|
||||||
case FieldNameCaseCamelLower:
|
|
||||||
return gstr.CaseCamelLower(newFieldName)
|
|
||||||
default:
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// isAllUpper checks and returns whether given `fieldName` all letters are upper case.
|
|
||||||
func isAllUpper(fieldName string) bool {
|
|
||||||
for _, b := range fieldName {
|
|
||||||
if b >= 'a' && b <= 'z' {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// formatComment formats the comment string to fit the golang code without any lines.
|
// formatComment formats the comment string to fit the golang code without any lines.
|
||||||
func formatComment(comment string) string {
|
func formatComment(comment string) string {
|
||||||
comment = gstr.ReplaceByArray(comment, g.SliceStr{
|
comment = gstr.ReplaceByArray(comment, g.SliceStr{
|
||||||
@ -227,3 +158,30 @@ func formatComment(comment string) string {
|
|||||||
comment = gstr.Trim(comment)
|
comment = gstr.Trim(comment)
|
||||||
return comment
|
return comment
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getJsonTagFromCase call gstr.Case* function to convert the s to specified case.
|
||||||
|
func getJsonTagFromCase(str, caseStr string) string {
|
||||||
|
switch gstr.ToLower(caseStr) {
|
||||||
|
case gstr.ToLower("Camel"):
|
||||||
|
return gstr.CaseCamel(str)
|
||||||
|
|
||||||
|
case gstr.ToLower("CamelLower"):
|
||||||
|
return gstr.CaseCamelLower(str)
|
||||||
|
|
||||||
|
case gstr.ToLower("Kebab"):
|
||||||
|
return gstr.CaseKebab(str)
|
||||||
|
|
||||||
|
case gstr.ToLower("KebabScreaming"):
|
||||||
|
return gstr.CaseKebabScreaming(str)
|
||||||
|
|
||||||
|
case gstr.ToLower("Snake"):
|
||||||
|
return gstr.CaseSnake(str)
|
||||||
|
|
||||||
|
case gstr.ToLower("SnakeFirstUpper"):
|
||||||
|
return gstr.CaseSnakeFirstUpper(str)
|
||||||
|
|
||||||
|
case gstr.ToLower("SnakeScreaming"):
|
||||||
|
return gstr.CaseSnakeScreaming(str)
|
||||||
|
}
|
||||||
|
return str
|
||||||
|
}
|
||||||
|
|||||||
@ -1,147 +0,0 @@
|
|||||||
// 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 gendao
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"context"
|
|
||||||
"path/filepath"
|
|
||||||
"sort"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/gogf/gf/v2/database/gdb"
|
|
||||||
"github.com/gogf/gf/v2/os/gfile"
|
|
||||||
"github.com/gogf/gf/v2/os/gview"
|
|
||||||
"github.com/gogf/gf/v2/text/gstr"
|
|
||||||
"github.com/gogf/gf/v2/util/gconv"
|
|
||||||
|
|
||||||
"github.com/gogf/gf/cmd/gf/v2/internal/consts"
|
|
||||||
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
|
|
||||||
"github.com/gogf/gf/cmd/gf/v2/internal/utility/utils"
|
|
||||||
)
|
|
||||||
|
|
||||||
// generateTable generates dao files for given tables.
|
|
||||||
func generateTable(ctx context.Context, in CGenDaoInternalInput) {
|
|
||||||
dirPathTable := gfile.Join(in.Path, in.TablePath)
|
|
||||||
if !in.GenTable {
|
|
||||||
if gfile.Exists(dirPathTable) {
|
|
||||||
in.genItems.AppendDirPath(dirPathTable)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
in.genItems.AppendDirPath(dirPathTable)
|
|
||||||
for i := 0; i < len(in.TableNames); i++ {
|
|
||||||
var (
|
|
||||||
realTableName = in.TableNames[i]
|
|
||||||
newTableName = in.NewTableNames[i]
|
|
||||||
)
|
|
||||||
generateTableSingle(ctx, generateTableSingleInput{
|
|
||||||
CGenDaoInternalInput: in,
|
|
||||||
TableName: realTableName,
|
|
||||||
NewTableName: newTableName,
|
|
||||||
DirPathTable: dirPathTable,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// generateTableSingleInput is the input parameter for generateTableSingle.
|
|
||||||
type generateTableSingleInput struct {
|
|
||||||
CGenDaoInternalInput
|
|
||||||
// TableName specifies the table name of the table.
|
|
||||||
TableName string
|
|
||||||
// NewTableName specifies the prefix-stripped or custom edited name of the table.
|
|
||||||
NewTableName string
|
|
||||||
DirPathTable string
|
|
||||||
}
|
|
||||||
|
|
||||||
// generateTableSingle generates dao files for a single table.
|
|
||||||
func generateTableSingle(ctx context.Context, in generateTableSingleInput) {
|
|
||||||
// Generating table data preparing.
|
|
||||||
fieldMap, err := in.DB.TableFields(ctx, in.TableName)
|
|
||||||
if err != nil {
|
|
||||||
mlog.Fatalf(`fetching tables fields failed for table "%s": %+v`, in.TableName, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
tableNameSnakeCase := gstr.CaseSnake(in.NewTableName)
|
|
||||||
fileName := gstr.Trim(tableNameSnakeCase, "-_.")
|
|
||||||
if len(fileName) > 5 && fileName[len(fileName)-5:] == "_test" {
|
|
||||||
// Add suffix to avoid the table name which contains "_test",
|
|
||||||
// which would make the go file a testing file.
|
|
||||||
fileName += "_table"
|
|
||||||
}
|
|
||||||
path := filepath.FromSlash(gfile.Join(in.DirPathTable, fileName+".go"))
|
|
||||||
in.genItems.AppendGeneratedFilePath(path)
|
|
||||||
if in.OverwriteDao || !gfile.Exists(path) {
|
|
||||||
var (
|
|
||||||
ctx = context.Background()
|
|
||||||
tplContent = getTemplateFromPathOrDefault(
|
|
||||||
in.TplDaoTablePath, consts.TemplateGenTableContent,
|
|
||||||
)
|
|
||||||
)
|
|
||||||
tplView.ClearAssigns()
|
|
||||||
tplView.Assigns(gview.Params{
|
|
||||||
tplVarGroupName: in.Group,
|
|
||||||
tplVarTableName: in.TableName,
|
|
||||||
tplVarTableNameCamelCase: formatFieldName(in.NewTableName, FieldNameCaseCamel),
|
|
||||||
tplVarPackageName: filepath.Base(in.TablePath),
|
|
||||||
tplVarTableFields: generateTableFields(fieldMap),
|
|
||||||
})
|
|
||||||
indexContent, err := tplView.ParseContent(ctx, tplContent)
|
|
||||||
if err != nil {
|
|
||||||
mlog.Fatalf("parsing template content failed: %v", err)
|
|
||||||
}
|
|
||||||
if err = gfile.PutContents(path, strings.TrimSpace(indexContent)); err != nil {
|
|
||||||
mlog.Fatalf("writing content to '%s' failed: %v", path, err)
|
|
||||||
} else {
|
|
||||||
utils.GoFmt(path)
|
|
||||||
mlog.Print("generated:", gfile.RealPath(path))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// generateTableFields generates and returns the field definition content for specified table.
|
|
||||||
func generateTableFields(fields map[string]*gdb.TableField) string {
|
|
||||||
var buf bytes.Buffer
|
|
||||||
fieldNames := make([]string, 0, len(fields))
|
|
||||||
for fieldName := range fields {
|
|
||||||
fieldNames = append(fieldNames, fieldName)
|
|
||||||
}
|
|
||||||
sort.Slice(fieldNames, func(i, j int) bool {
|
|
||||||
return fields[fieldNames[i]].Index < fields[fieldNames[j]].Index // asc
|
|
||||||
})
|
|
||||||
for index, fieldName := range fieldNames {
|
|
||||||
field := fields[fieldName]
|
|
||||||
buf.WriteString(" " + strconv.Quote(field.Name) + ": {\n")
|
|
||||||
buf.WriteString(" Index: " + gconv.String(field.Index) + ",\n")
|
|
||||||
buf.WriteString(" Name: " + strconv.Quote(field.Name) + ",\n")
|
|
||||||
buf.WriteString(" Type: " + strconv.Quote(field.Type) + ",\n")
|
|
||||||
buf.WriteString(" Null: " + gconv.String(field.Null) + ",\n")
|
|
||||||
buf.WriteString(" Key: " + strconv.Quote(field.Key) + ",\n")
|
|
||||||
buf.WriteString(" Default: " + generateDefaultValue(field.Default) + ",\n")
|
|
||||||
buf.WriteString(" Extra: " + strconv.Quote(field.Extra) + ",\n")
|
|
||||||
buf.WriteString(" Comment: " + strconv.Quote(field.Comment) + ",\n")
|
|
||||||
buf.WriteString(" },")
|
|
||||||
if index != len(fieldNames)-1 {
|
|
||||||
buf.WriteString("\n")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return buf.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
// generateDefaultValue generates and returns the default value definition for specified field.
|
|
||||||
func generateDefaultValue(value interface{}) string {
|
|
||||||
if value == nil {
|
|
||||||
return "nil"
|
|
||||||
}
|
|
||||||
switch v := value.(type) {
|
|
||||||
case string:
|
|
||||||
return strconv.Quote(v)
|
|
||||||
default:
|
|
||||||
return gconv.String(v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,155 +0,0 @@
|
|||||||
// 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 gendao
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/gogf/gf/v2/frame/g"
|
|
||||||
"github.com/gogf/gf/v2/util/gtag"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
CGenDaoConfig = `gfcli.gen.dao`
|
|
||||||
CGenDaoUsage = `gf gen dao [OPTION]`
|
|
||||||
CGenDaoBrief = `automatically generate go files for dao/do/entity`
|
|
||||||
CGenDaoEg = `
|
|
||||||
gf gen dao
|
|
||||||
gf gen dao -l "mysql:root:12345678@tcp(127.0.0.1:3306)/test"
|
|
||||||
gf gen dao -p ./model -g user-center -t user,user_detail,user_login
|
|
||||||
gf gen dao -r user_
|
|
||||||
`
|
|
||||||
|
|
||||||
CGenDaoAd = `
|
|
||||||
CONFIGURATION SUPPORT
|
|
||||||
Options are also supported by configuration file.
|
|
||||||
It's suggested using configuration file instead of command line arguments making producing.
|
|
||||||
The configuration node name is "gfcli.gen.dao", which also supports multiple databases, for example(config.yaml):
|
|
||||||
gfcli:
|
|
||||||
gen:
|
|
||||||
dao:
|
|
||||||
- link: "mysql:root:12345678@tcp(127.0.0.1:3306)/test"
|
|
||||||
tables: "order,products"
|
|
||||||
jsonCase: "CamelLower"
|
|
||||||
- link: "mysql:root:12345678@tcp(127.0.0.1:3306)/primary"
|
|
||||||
path: "./my-app"
|
|
||||||
prefix: "primary_"
|
|
||||||
tables: "user, userDetail"
|
|
||||||
typeMapping:
|
|
||||||
decimal:
|
|
||||||
type: decimal.Decimal
|
|
||||||
import: github.com/shopspring/decimal
|
|
||||||
numeric:
|
|
||||||
type: string
|
|
||||||
fieldMapping:
|
|
||||||
table_name.field_name:
|
|
||||||
type: decimal.Decimal
|
|
||||||
import: github.com/shopspring/decimal
|
|
||||||
`
|
|
||||||
CGenDaoBriefPath = `directory path for generated files`
|
|
||||||
CGenDaoBriefLink = `database configuration, the same as the ORM configuration of GoFrame`
|
|
||||||
CGenDaoBriefTables = `generate models only for given tables, multiple table names separated with ','`
|
|
||||||
CGenDaoBriefTablesEx = `generate models excluding given tables, multiple table names separated with ','`
|
|
||||||
CGenDaoBriefPrefix = `add prefix for all table of specified link/database tables`
|
|
||||||
CGenDaoBriefRemovePrefix = `remove specified prefix of the table, multiple prefix separated with ','`
|
|
||||||
CGenDaoBriefRemoveFieldPrefix = `remove specified prefix of the field, multiple prefix separated with ','`
|
|
||||||
CGenDaoBriefStdTime = `use time.Time from stdlib instead of gtime.Time for generated time/date fields of tables`
|
|
||||||
CGenDaoBriefWithTime = `add created time for auto produced go files`
|
|
||||||
CGenDaoBriefGJsonSupport = `use gJsonSupport to use *gjson.Json instead of string for generated json fields of tables`
|
|
||||||
CGenDaoBriefImportPrefix = `custom import prefix for generated go files`
|
|
||||||
CGenDaoBriefDaoPath = `directory path for storing generated dao files under path`
|
|
||||||
CGenDaoBriefTablePath = `directory path for storing generated table files under path`
|
|
||||||
CGenDaoBriefDoPath = `directory path for storing generated do files under path`
|
|
||||||
CGenDaoBriefEntityPath = `directory path for storing generated entity files under path`
|
|
||||||
CGenDaoBriefOverwriteDao = `overwrite all dao files both inside/outside internal folder`
|
|
||||||
CGenDaoBriefModelFile = `custom file name for storing generated model content`
|
|
||||||
CGenDaoBriefModelFileForDao = `custom file name generating model for DAO operations like Where/Data. It's empty in default`
|
|
||||||
CGenDaoBriefDescriptionTag = `add comment to description tag for each field`
|
|
||||||
CGenDaoBriefNoJsonTag = `no json tag will be added for each field`
|
|
||||||
CGenDaoBriefNoModelComment = `no model comment will be added for each field`
|
|
||||||
CGenDaoBriefClear = `delete all generated go files that do not exist in database`
|
|
||||||
CGenDaoBriefGenTable = `generate table files`
|
|
||||||
CGenDaoBriefTypeMapping = `custom local type mapping for generated struct attributes relevant to fields of table`
|
|
||||||
CGenDaoBriefFieldMapping = `custom local type mapping for generated struct attributes relevant to specific fields of table`
|
|
||||||
CGenDaoBriefShardingPattern = `sharding pattern for table name, e.g. "users_?" will be replace tables "users_001,users_002,..." to "users" dao`
|
|
||||||
CGenDaoBriefGroup = `
|
|
||||||
specifying the configuration group name of database for generated ORM instance,
|
|
||||||
it's not necessary and the default value is "default"
|
|
||||||
`
|
|
||||||
CGenDaoBriefJsonCase = `
|
|
||||||
generated json tag case for model struct, cases are as follows:
|
|
||||||
| Case | Example |
|
|
||||||
|---------------- |--------------------|
|
|
||||||
| Camel | AnyKindOfString |
|
|
||||||
| CamelLower | anyKindOfString | default
|
|
||||||
| Snake | any_kind_of_string |
|
|
||||||
| SnakeScreaming | ANY_KIND_OF_STRING |
|
|
||||||
| SnakeFirstUpper | rgb_code_md5 |
|
|
||||||
| Kebab | any-kind-of-string |
|
|
||||||
| KebabScreaming | ANY-KIND-OF-STRING |
|
|
||||||
`
|
|
||||||
CGenDaoBriefTplDaoIndexPath = `template file path for dao index file`
|
|
||||||
CGenDaoBriefTplDaoInternalPath = `template file path for dao internal file`
|
|
||||||
CGenDaoBriefTplDaoDoPathPath = `template file path for dao do file`
|
|
||||||
CGenDaoBriefTplDaoEntityPath = `template file path for dao entity file`
|
|
||||||
|
|
||||||
tplVarTableName = `TplTableName`
|
|
||||||
tplVarTableNameCamelCase = `TplTableNameCamelCase`
|
|
||||||
tplVarTableNameCamelLowerCase = `TplTableNameCamelLowerCase`
|
|
||||||
tplVarTableSharding = `TplTableSharding`
|
|
||||||
tplVarTableShardingPrefix = `TplTableShardingPrefix`
|
|
||||||
tplVarTableFields = `TplTableFields`
|
|
||||||
tplVarPackageImports = `TplPackageImports`
|
|
||||||
tplVarImportPrefix = `TplImportPrefix`
|
|
||||||
tplVarStructDefine = `TplStructDefine`
|
|
||||||
tplVarColumnDefine = `TplColumnDefine`
|
|
||||||
tplVarColumnNames = `TplColumnNames`
|
|
||||||
tplVarGroupName = `TplGroupName`
|
|
||||||
tplVarDatetimeStr = `TplDatetimeStr`
|
|
||||||
tplVarCreatedAtDatetimeStr = `TplCreatedAtDatetimeStr`
|
|
||||||
tplVarPackageName = `TplPackageName`
|
|
||||||
)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
gtag.Sets(g.MapStrStr{
|
|
||||||
`CGenDaoConfig`: CGenDaoConfig,
|
|
||||||
`CGenDaoUsage`: CGenDaoUsage,
|
|
||||||
`CGenDaoBrief`: CGenDaoBrief,
|
|
||||||
`CGenDaoEg`: CGenDaoEg,
|
|
||||||
`CGenDaoAd`: CGenDaoAd,
|
|
||||||
`CGenDaoBriefPath`: CGenDaoBriefPath,
|
|
||||||
`CGenDaoBriefLink`: CGenDaoBriefLink,
|
|
||||||
`CGenDaoBriefTables`: CGenDaoBriefTables,
|
|
||||||
`CGenDaoBriefTablesEx`: CGenDaoBriefTablesEx,
|
|
||||||
`CGenDaoBriefPrefix`: CGenDaoBriefPrefix,
|
|
||||||
`CGenDaoBriefRemovePrefix`: CGenDaoBriefRemovePrefix,
|
|
||||||
`CGenDaoBriefRemoveFieldPrefix`: CGenDaoBriefRemoveFieldPrefix,
|
|
||||||
`CGenDaoBriefStdTime`: CGenDaoBriefStdTime,
|
|
||||||
`CGenDaoBriefWithTime`: CGenDaoBriefWithTime,
|
|
||||||
`CGenDaoBriefDaoPath`: CGenDaoBriefDaoPath,
|
|
||||||
`CGenDaoBriefTablePath`: CGenDaoBriefTablePath,
|
|
||||||
`CGenDaoBriefDoPath`: CGenDaoBriefDoPath,
|
|
||||||
`CGenDaoBriefEntityPath`: CGenDaoBriefEntityPath,
|
|
||||||
`CGenDaoBriefGJsonSupport`: CGenDaoBriefGJsonSupport,
|
|
||||||
`CGenDaoBriefImportPrefix`: CGenDaoBriefImportPrefix,
|
|
||||||
`CGenDaoBriefOverwriteDao`: CGenDaoBriefOverwriteDao,
|
|
||||||
`CGenDaoBriefModelFile`: CGenDaoBriefModelFile,
|
|
||||||
`CGenDaoBriefModelFileForDao`: CGenDaoBriefModelFileForDao,
|
|
||||||
`CGenDaoBriefDescriptionTag`: CGenDaoBriefDescriptionTag,
|
|
||||||
`CGenDaoBriefNoJsonTag`: CGenDaoBriefNoJsonTag,
|
|
||||||
`CGenDaoBriefNoModelComment`: CGenDaoBriefNoModelComment,
|
|
||||||
`CGenDaoBriefClear`: CGenDaoBriefClear,
|
|
||||||
`CGenDaoBriefGenTable`: CGenDaoBriefGenTable,
|
|
||||||
`CGenDaoBriefTypeMapping`: CGenDaoBriefTypeMapping,
|
|
||||||
`CGenDaoBriefFieldMapping`: CGenDaoBriefFieldMapping,
|
|
||||||
`CGenDaoBriefShardingPattern`: CGenDaoBriefShardingPattern,
|
|
||||||
`CGenDaoBriefGroup`: CGenDaoBriefGroup,
|
|
||||||
`CGenDaoBriefJsonCase`: CGenDaoBriefJsonCase,
|
|
||||||
`CGenDaoBriefTplDaoIndexPath`: CGenDaoBriefTplDaoIndexPath,
|
|
||||||
`CGenDaoBriefTplDaoInternalPath`: CGenDaoBriefTplDaoInternalPath,
|
|
||||||
`CGenDaoBriefTplDaoDoPathPath`: CGenDaoBriefTplDaoDoPathPath,
|
|
||||||
`CGenDaoBriefTplDaoEntityPath`: CGenDaoBriefTplDaoEntityPath,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
@ -8,24 +8,22 @@ package genenums
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"golang.org/x/tools/go/packages"
|
"golang.org/x/tools/go/packages"
|
||||||
|
|
||||||
|
"github.com/gogf/gf/cmd/gf/v2/internal/consts"
|
||||||
|
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
|
||||||
"github.com/gogf/gf/v2/frame/g"
|
"github.com/gogf/gf/v2/frame/g"
|
||||||
"github.com/gogf/gf/v2/os/gfile"
|
"github.com/gogf/gf/v2/os/gfile"
|
||||||
"github.com/gogf/gf/v2/text/gstr"
|
"github.com/gogf/gf/v2/text/gstr"
|
||||||
"github.com/gogf/gf/v2/util/gtag"
|
"github.com/gogf/gf/v2/util/gtag"
|
||||||
|
|
||||||
"github.com/gogf/gf/cmd/gf/v2/internal/consts"
|
|
||||||
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
CGenEnums struct{}
|
CGenEnums struct{}
|
||||||
CGenEnumsInput struct {
|
CGenEnumsInput struct {
|
||||||
g.Meta `name:"enums" config:"{CGenEnumsConfig}" brief:"{CGenEnumsBrief}" eg:"{CGenEnumsEg}"`
|
g.Meta `name:"enums" config:"{CGenEnumsConfig}" brief:"{CGenEnumsBrief}" eg:"{CGenEnumsEg}"`
|
||||||
Src string `name:"src" short:"s" dc:"source folder path to be parsed" d:"api"`
|
Src string `name:"src" short:"s" dc:"source folder path to be parsed" d:"."`
|
||||||
Path string `name:"path" short:"p" dc:"output go file path storing enums content" d:"internal/packed/packed_enums.go"`
|
Path string `name:"path" short:"p" dc:"output go file path storing enums content" d:"internal/boot/boot_enums.go"`
|
||||||
Prefixes []string `name:"prefixes" short:"x" dc:"only exports packages that starts with specified prefixes"`
|
Prefixes []string `name:"prefixes" short:"x" dc:"only exports packages that starts with specified prefixes"`
|
||||||
}
|
}
|
||||||
CGenEnumsOutput struct{}
|
CGenEnumsOutput struct{}
|
||||||
@ -36,8 +34,8 @@ const (
|
|||||||
CGenEnumsBrief = `parse go files in current project and generate enums go file`
|
CGenEnumsBrief = `parse go files in current project and generate enums go file`
|
||||||
CGenEnumsEg = `
|
CGenEnumsEg = `
|
||||||
gf gen enums
|
gf gen enums
|
||||||
gf gen enums -p internal/packed/packed_enums.go
|
gf gen enums -p internal/boot/boot_enums.go
|
||||||
gf gen enums -p internal/packed/packed_enums.go -s .
|
gf gen enums -p internal/boot/boot_enums.go -s .
|
||||||
gf gen enums -x github.com/gogf
|
gf gen enums -x github.com/gogf
|
||||||
`
|
`
|
||||||
)
|
)
|
||||||
|
|||||||
@ -9,7 +9,6 @@ package genenums
|
|||||||
import (
|
import (
|
||||||
"go/constant"
|
"go/constant"
|
||||||
"go/types"
|
"go/types"
|
||||||
|
|
||||||
"golang.org/x/tools/go/packages"
|
"golang.org/x/tools/go/packages"
|
||||||
|
|
||||||
"github.com/gogf/gf/v2/encoding/gjson"
|
"github.com/gogf/gf/v2/encoding/gjson"
|
||||||
@ -20,10 +19,9 @@ import (
|
|||||||
const pkgLoadMode = 0xffffff
|
const pkgLoadMode = 0xffffff
|
||||||
|
|
||||||
type EnumsParser struct {
|
type EnumsParser struct {
|
||||||
enums []EnumItem
|
enums []EnumItem
|
||||||
parsedPkg map[string]struct{}
|
parsedPkg map[string]struct{}
|
||||||
prefixes []string
|
prefixes []string
|
||||||
standardPackages map[string]struct{}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type EnumItem struct {
|
type EnumItem struct {
|
||||||
@ -33,12 +31,23 @@ type EnumItem struct {
|
|||||||
Type string // Pkg.ID + TypeName
|
Type string // Pkg.ID + TypeName
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var standardPackages = make(map[string]struct{})
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
stdPackages, err := packages.Load(nil, "std")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
for _, p := range stdPackages {
|
||||||
|
standardPackages[p.ID] = struct{}{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func NewEnumsParser(prefixes []string) *EnumsParser {
|
func NewEnumsParser(prefixes []string) *EnumsParser {
|
||||||
return &EnumsParser{
|
return &EnumsParser{
|
||||||
enums: make([]EnumItem, 0),
|
enums: make([]EnumItem, 0),
|
||||||
parsedPkg: make(map[string]struct{}),
|
parsedPkg: make(map[string]struct{}),
|
||||||
prefixes: prefixes,
|
prefixes: prefixes,
|
||||||
standardPackages: getStandardPackages(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,7 +59,7 @@ func (p *EnumsParser) ParsePackages(pkgs []*packages.Package) {
|
|||||||
|
|
||||||
func (p *EnumsParser) ParsePackage(pkg *packages.Package) {
|
func (p *EnumsParser) ParsePackage(pkg *packages.Package) {
|
||||||
// Ignore std packages.
|
// Ignore std packages.
|
||||||
if _, ok := p.standardPackages[pkg.ID]; ok {
|
if _, ok := standardPackages[pkg.ID]; ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// Ignore pared packages.
|
// Ignore pared packages.
|
||||||
@ -113,12 +122,12 @@ func (p *EnumsParser) ParsePackage(pkg *packages.Package) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (p *EnumsParser) Export() string {
|
func (p *EnumsParser) Export() string {
|
||||||
var typeEnumMap = make(map[string][]any)
|
var typeEnumMap = make(map[string][]interface{})
|
||||||
for _, enum := range p.enums {
|
for _, enum := range p.enums {
|
||||||
if typeEnumMap[enum.Type] == nil {
|
if typeEnumMap[enum.Type] == nil {
|
||||||
typeEnumMap[enum.Type] = make([]any, 0)
|
typeEnumMap[enum.Type] = make([]interface{}, 0)
|
||||||
}
|
}
|
||||||
var value any
|
var value interface{}
|
||||||
switch enum.Kind {
|
switch enum.Kind {
|
||||||
case constant.Int:
|
case constant.Int:
|
||||||
value = gconv.Int64(enum.Value)
|
value = gconv.Int64(enum.Value)
|
||||||
@ -135,15 +144,3 @@ func (p *EnumsParser) Export() string {
|
|||||||
}
|
}
|
||||||
return gjson.MustEncodeString(typeEnumMap)
|
return gjson.MustEncodeString(typeEnumMap)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getStandardPackages() map[string]struct{} {
|
|
||||||
standardPackages := make(map[string]struct{})
|
|
||||||
stdPackages, err := packages.Load(nil, "std")
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
for _, p := range stdPackages {
|
|
||||||
standardPackages[p.ID] = struct{}{}
|
|
||||||
}
|
|
||||||
return standardPackages
|
|
||||||
}
|
|
||||||
|
|||||||
@ -9,12 +9,11 @@ package genpb
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
|
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
|
||||||
"github.com/gogf/gf/v2/frame/g"
|
"github.com/gogf/gf/v2/frame/g"
|
||||||
"github.com/gogf/gf/v2/os/gfile"
|
"github.com/gogf/gf/v2/os/gfile"
|
||||||
"github.com/gogf/gf/v2/os/gproc"
|
"github.com/gogf/gf/v2/os/gproc"
|
||||||
"github.com/gogf/gf/v2/util/gtag"
|
"github.com/gogf/gf/v2/util/gtag"
|
||||||
|
|
||||||
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
@ -95,9 +94,6 @@ func (c CGenPb) Pb(ctx context.Context, in CGenPbInput) (out *CGenPbOutput, err
|
|||||||
mlog.Fatalf(`no proto files found in folder "%s"`, in.Path)
|
mlog.Fatalf(`no proto files found in folder "%s"`, in.Path)
|
||||||
}
|
}
|
||||||
|
|
||||||
var originPwd = gfile.Pwd()
|
|
||||||
defer gfile.Chdir(originPwd)
|
|
||||||
|
|
||||||
if err = gfile.Chdir(protoPath); err != nil {
|
if err = gfile.Chdir(protoPath); err != nil {
|
||||||
mlog.Fatal(err)
|
mlog.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,12 +11,11 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/gogf/gf/cmd/gf/v2/internal/utility/utils"
|
||||||
"github.com/gogf/gf/v2/frame/g"
|
"github.com/gogf/gf/v2/frame/g"
|
||||||
"github.com/gogf/gf/v2/os/gfile"
|
"github.com/gogf/gf/v2/os/gfile"
|
||||||
"github.com/gogf/gf/v2/text/gregex"
|
"github.com/gogf/gf/v2/text/gregex"
|
||||||
"github.com/gogf/gf/v2/text/gstr"
|
"github.com/gogf/gf/v2/text/gstr"
|
||||||
|
|
||||||
"github.com/gogf/gf/cmd/gf/v2/internal/utility/utils"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type generateControllerInput struct {
|
type generateControllerInput struct {
|
||||||
|
|||||||
@ -10,14 +10,12 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/gogf/gf/cmd/gf/v2/internal/utility/utils"
|
||||||
"github.com/gogf/gf/v2/container/gmap"
|
"github.com/gogf/gf/v2/container/gmap"
|
||||||
"github.com/gogf/gf/v2/frame/g"
|
|
||||||
"github.com/gogf/gf/v2/os/gfile"
|
"github.com/gogf/gf/v2/os/gfile"
|
||||||
"github.com/gogf/gf/v2/text/gregex"
|
"github.com/gogf/gf/v2/text/gregex"
|
||||||
"github.com/gogf/gf/v2/text/gstr"
|
"github.com/gogf/gf/v2/text/gstr"
|
||||||
"github.com/gogf/gf/v2/util/gconv"
|
"github.com/gogf/gf/v2/util/gconv"
|
||||||
|
|
||||||
"github.com/gogf/gf/cmd/gf/v2/internal/utility/utils"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type generateStructTagInput struct {
|
type generateStructTagInput struct {
|
||||||
@ -72,10 +70,6 @@ func (c CGenPb) doTagReplacement(ctx context.Context, content string) (string, e
|
|||||||
if !lineTagMap.IsEmpty() {
|
if !lineTagMap.IsEmpty() {
|
||||||
tagContent := c.listMapToStructTag(lineTagMap)
|
tagContent := c.listMapToStructTag(lineTagMap)
|
||||||
lineTagMap.Clear()
|
lineTagMap.Clear()
|
||||||
// If already have it, don't add it anymore
|
|
||||||
if gstr.Contains(gstr.StrTill(line, "` //"), tagContent) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
line, _ = gregex.ReplaceString("`(.+)`", fmt.Sprintf("`$1 %s`", tagContent), line)
|
line, _ = gregex.ReplaceString("`(.+)`", fmt.Sprintf("`$1 %s`", tagContent), line)
|
||||||
}
|
}
|
||||||
lines[index] = line
|
lines[index] = line
|
||||||
@ -96,12 +90,8 @@ func (c CGenPb) tagCommentIntoListMap(comment string, lineTagMap *gmap.ListMap)
|
|||||||
lineTagMap.Set(tagName, lineTagMap.GetVar(tagName).String()+tagContent)
|
lineTagMap.Set(tagName, lineTagMap.GetVar(tagName).String()+tagContent)
|
||||||
} else {
|
} else {
|
||||||
var (
|
var (
|
||||||
tagName = "dc"
|
tagName = "dc"
|
||||||
// Convert backticks and double quotes to single quotes.
|
tagContent = comment
|
||||||
tagContent = gstr.ReplaceByMap(comment, g.MapStrStr{
|
|
||||||
"`": `'`,
|
|
||||||
`"`: `'`,
|
|
||||||
})
|
|
||||||
)
|
)
|
||||||
lineTagMap.Set(tagName, lineTagMap.GetVar(tagName).String()+tagContent)
|
lineTagMap.Set(tagName, lineTagMap.GetVar(tagName).String()+tagContent)
|
||||||
}
|
}
|
||||||
@ -109,7 +99,7 @@ func (c CGenPb) tagCommentIntoListMap(comment string, lineTagMap *gmap.ListMap)
|
|||||||
|
|
||||||
func (c CGenPb) listMapToStructTag(lineTagMap *gmap.ListMap) string {
|
func (c CGenPb) listMapToStructTag(lineTagMap *gmap.ListMap) string {
|
||||||
var tag string
|
var tag string
|
||||||
lineTagMap.Iterator(func(key, value any) bool {
|
lineTagMap.Iterator(func(key, value interface{}) bool {
|
||||||
if tag != "" {
|
if tag != "" {
|
||||||
tag += " "
|
tag += " "
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,15 +11,12 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"regexp"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/olekukonko/tablewriter"
|
"github.com/olekukonko/tablewriter"
|
||||||
"github.com/olekukonko/tablewriter/renderer"
|
|
||||||
"github.com/olekukonko/tablewriter/tw"
|
|
||||||
|
|
||||||
"github.com/gogf/gf/v2/container/garray"
|
"github.com/gogf/gf/cmd/gf/v2/internal/consts"
|
||||||
"github.com/gogf/gf/v2/container/gset"
|
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
|
||||||
"github.com/gogf/gf/v2/database/gdb"
|
"github.com/gogf/gf/v2/database/gdb"
|
||||||
"github.com/gogf/gf/v2/frame/g"
|
"github.com/gogf/gf/v2/frame/g"
|
||||||
"github.com/gogf/gf/v2/os/gctx"
|
"github.com/gogf/gf/v2/os/gctx"
|
||||||
@ -29,32 +26,21 @@ import (
|
|||||||
"github.com/gogf/gf/v2/text/gstr"
|
"github.com/gogf/gf/v2/text/gstr"
|
||||||
"github.com/gogf/gf/v2/util/gconv"
|
"github.com/gogf/gf/v2/util/gconv"
|
||||||
"github.com/gogf/gf/v2/util/gtag"
|
"github.com/gogf/gf/v2/util/gtag"
|
||||||
|
|
||||||
"github.com/gogf/gf/cmd/gf/v2/internal/consts"
|
|
||||||
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
|
|
||||||
"github.com/gogf/gf/cmd/gf/v2/internal/utility/utils"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
CGenPbEntity struct{}
|
CGenPbEntity struct{}
|
||||||
CGenPbEntityInput struct {
|
CGenPbEntityInput struct {
|
||||||
g.Meta `name:"pbentity" config:"{CGenPbEntityConfig}" brief:"{CGenPbEntityBrief}" eg:"{CGenPbEntityEg}" ad:"{CGenPbEntityAd}"`
|
g.Meta `name:"pbentity" config:"{CGenPbEntityConfig}" brief:"{CGenPbEntityBrief}" eg:"{CGenPbEntityEg}" ad:"{CGenPbEntityAd}"`
|
||||||
Path string `name:"path" short:"p" brief:"{CGenPbEntityBriefPath}" d:"manifest/protobuf/pbentity"`
|
Path string `name:"path" short:"p" brief:"{CGenPbEntityBriefPath}" d:"manifest/protobuf/pbentity"`
|
||||||
Package string `name:"package" short:"k" brief:"{CGenPbEntityBriefPackage}"`
|
Package string `name:"package" short:"k" brief:"{CGenPbEntityBriefPackage}"`
|
||||||
GoPackage string `name:"goPackage" short:"g" brief:"{CGenPbEntityBriefGoPackage}"`
|
Link string `name:"link" short:"l" brief:"{CGenPbEntityBriefLink}"`
|
||||||
Link string `name:"link" short:"l" brief:"{CGenPbEntityBriefLink}"`
|
Tables string `name:"tables" short:"t" brief:"{CGenPbEntityBriefTables}"`
|
||||||
Tables string `name:"tables" short:"t" brief:"{CGenPbEntityBriefTables}"`
|
Prefix string `name:"prefix" short:"f" brief:"{CGenPbEntityBriefPrefix}"`
|
||||||
Prefix string `name:"prefix" short:"f" brief:"{CGenPbEntityBriefPrefix}"`
|
RemovePrefix string `name:"removePrefix" short:"r" brief:"{CGenPbEntityBriefRemovePrefix}"`
|
||||||
RemovePrefix string `name:"removePrefix" short:"r" brief:"{CGenPbEntityBriefRemovePrefix}"`
|
NameCase string `name:"nameCase" short:"n" brief:"{CGenPbEntityBriefNameCase}" d:"Camel"`
|
||||||
RemoveFieldPrefix string `name:"removeFieldPrefix" short:"rf" brief:"{CGenPbEntityBriefRemoveFieldPrefix}"`
|
JsonCase string `name:"jsonCase" short:"j" brief:"{CGenPbEntityBriefJsonCase}" d:"CamelLower"`
|
||||||
TablesEx string `name:"tablesEx" short:"x" brief:"{CGenDaoBriefTablesEx}"`
|
Option string `name:"option" short:"o" brief:"{CGenPbEntityBriefOption}"`
|
||||||
NameCase string `name:"nameCase" short:"n" brief:"{CGenPbEntityBriefNameCase}" d:"Camel"`
|
|
||||||
JsonCase string `name:"jsonCase" short:"j" brief:"{CGenPbEntityBriefJsonCase}" d:"none"`
|
|
||||||
Option string `name:"option" short:"o" brief:"{CGenPbEntityBriefOption}"`
|
|
||||||
ShardingPattern []string `name:"shardingPattern" short:"sp" brief:"{CGenDaoBriefShardingPattern}"`
|
|
||||||
|
|
||||||
TypeMapping map[DBFieldTypeName]CustomAttributeType `name:"typeMapping" short:"y" brief:"{CGenPbEntityBriefTypeMapping}" orphan:"true"`
|
|
||||||
FieldMapping map[DBTableFieldName]CustomAttributeType `name:"fieldMapping" short:"fm" brief:"{CGenPbEntityBriefFieldMapping}" orphan:"true"`
|
|
||||||
}
|
}
|
||||||
CGenPbEntityOutput struct{}
|
CGenPbEntityOutput struct{}
|
||||||
|
|
||||||
@ -64,13 +50,6 @@ type (
|
|||||||
TableName string // TableName specifies the table name of the table.
|
TableName string // TableName specifies the table name of the table.
|
||||||
NewTableName string // NewTableName specifies the prefix-stripped name of the table.
|
NewTableName string // NewTableName specifies the prefix-stripped name of the table.
|
||||||
}
|
}
|
||||||
|
|
||||||
DBTableFieldName = string
|
|
||||||
DBFieldTypeName = string
|
|
||||||
CustomAttributeType struct {
|
|
||||||
Type string `brief:"custom attribute type name"`
|
|
||||||
Import string `brief:"custom import for this type"`
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -88,7 +67,7 @@ gf gen pbentity -r user_
|
|||||||
CGenPbEntityAd = `
|
CGenPbEntityAd = `
|
||||||
CONFIGURATION SUPPORT
|
CONFIGURATION SUPPORT
|
||||||
Options are also supported by configuration file.
|
Options are also supported by configuration file.
|
||||||
It's suggested using configuration file instead of command line arguments making producing.
|
It's suggested using configuration file instead of command line arguments making producing.
|
||||||
The configuration node name is "gf.gen.pbentity", which also supports multiple databases, for example(config.yaml):
|
The configuration node name is "gf.gen.pbentity", which also supports multiple databases, for example(config.yaml):
|
||||||
gfcli:
|
gfcli:
|
||||||
gen:
|
gen:
|
||||||
@ -107,26 +86,15 @@ CONFIGURATION SUPPORT
|
|||||||
option go_package = "protobuf/demos";
|
option go_package = "protobuf/demos";
|
||||||
option java_package = "protobuf/demos";
|
option java_package = "protobuf/demos";
|
||||||
option php_namespace = "protobuf/demos";
|
option php_namespace = "protobuf/demos";
|
||||||
typeMapping:
|
|
||||||
json:
|
|
||||||
type: google.protobuf.Value
|
|
||||||
import: google/protobuf/struct.proto
|
|
||||||
jsonb:
|
|
||||||
type: google.protobuf.Value
|
|
||||||
import: google/protobuf/struct.proto
|
|
||||||
`
|
`
|
||||||
CGenPbEntityBriefPath = `directory path for generated files storing`
|
CGenPbEntityBriefPath = `directory path for generated files storing`
|
||||||
CGenPbEntityBriefPackage = `package path for all entity proto files`
|
CGenPbEntityBriefPackage = `package path for all entity proto files`
|
||||||
CGenPbEntityBriefGoPackage = `go package path for all entity proto files`
|
CGenPbEntityBriefLink = `database configuration, the same as the ORM configuration of GoFrame`
|
||||||
CGenPbEntityBriefLink = `database configuration, the same as the ORM configuration of GoFrame`
|
CGenPbEntityBriefTables = `generate models only for given tables, multiple table names separated with ','`
|
||||||
CGenPbEntityBriefTables = `generate models only for given tables, multiple table names separated with ','`
|
CGenPbEntityBriefPrefix = `add specified prefix for all entity names and entity proto files`
|
||||||
CGenPbEntityBriefPrefix = `add specified prefix for all entity names and entity proto files`
|
CGenPbEntityBriefRemovePrefix = `remove specified prefix of the table, multiple prefix separated with ','`
|
||||||
CGenPbEntityBriefRemovePrefix = `remove specified prefix of the table, multiple prefix separated with ','`
|
CGenPbEntityBriefOption = `extra protobuf options`
|
||||||
CGenPbEntityBriefTablesEx = `generate all models exclude the specified tables, multiple prefix separated with ','`
|
CGenPbEntityBriefGroup = `
|
||||||
CGenPbEntityBriefRemoveFieldPrefix = `remove specified prefix of the field, multiple prefix separated with ','`
|
|
||||||
CGenPbEntityBriefOption = `extra protobuf options`
|
|
||||||
CGenPbEntityBriefShardingPattern = `sharding pattern for table name, e.g. "users_?" will replace tables "users_001,users_002,..." to "users" pbentity`
|
|
||||||
CGenPbEntityBriefGroup = `
|
|
||||||
specifying the configuration group name of database for generated ORM instance,
|
specifying the configuration group name of database for generated ORM instance,
|
||||||
it's not necessary and the default value is "default"
|
it's not necessary and the default value is "default"
|
||||||
`
|
`
|
||||||
@ -135,7 +103,7 @@ it's not necessary and the default value is "default"
|
|||||||
case for message attribute names, default is "Camel":
|
case for message attribute names, default is "Camel":
|
||||||
| Case | Example |
|
| Case | Example |
|
||||||
|---------------- |--------------------|
|
|---------------- |--------------------|
|
||||||
| Camel | AnyKindOfString |
|
| Camel | AnyKindOfString |
|
||||||
| CamelLower | anyKindOfString | default
|
| CamelLower | anyKindOfString | default
|
||||||
| Snake | any_kind_of_string |
|
| Snake | any_kind_of_string |
|
||||||
| SnakeScreaming | ANY_KIND_OF_STRING |
|
| SnakeScreaming | ANY_KIND_OF_STRING |
|
||||||
@ -148,117 +116,24 @@ case for message attribute names, default is "Camel":
|
|||||||
case for message json tag, cases are the same as "nameCase", default "CamelLower".
|
case for message json tag, cases are the same as "nameCase", default "CamelLower".
|
||||||
set it to "none" to ignore json tag generating.
|
set it to "none" to ignore json tag generating.
|
||||||
`
|
`
|
||||||
|
|
||||||
CGenPbEntityBriefTypeMapping = `custom local type mapping for generated struct attributes relevant to fields of table`
|
|
||||||
CGenPbEntityBriefFieldMapping = `custom local type mapping for generated struct attributes relevant to specific fields of table`
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var defaultTypeMapping = map[DBFieldTypeName]CustomAttributeType{
|
|
||||||
// gdb.LocalTypeString
|
|
||||||
"string": {
|
|
||||||
Type: "string",
|
|
||||||
},
|
|
||||||
// gdb.LocalTypeTime
|
|
||||||
// "time": {
|
|
||||||
// Type: "google.protobuf.Duration",
|
|
||||||
// Import: "google/protobuf/duration.proto",
|
|
||||||
// },
|
|
||||||
// gdb.LocalTypeDate
|
|
||||||
"date": {
|
|
||||||
Type: "google.protobuf.Timestamp",
|
|
||||||
Import: "google/protobuf/timestamp.proto",
|
|
||||||
},
|
|
||||||
// gdb.LocalTypeDatetime
|
|
||||||
"datetime": {
|
|
||||||
Type: "google.protobuf.Timestamp",
|
|
||||||
Import: "google/protobuf/timestamp.proto",
|
|
||||||
},
|
|
||||||
// gdb.LocalTypeInt
|
|
||||||
"int": {
|
|
||||||
Type: "int32",
|
|
||||||
},
|
|
||||||
// gdb.LocalTypeUint
|
|
||||||
"uint": {
|
|
||||||
Type: "uint32",
|
|
||||||
},
|
|
||||||
// gdb.LocalTypeInt64
|
|
||||||
"int64": {
|
|
||||||
Type: "int64",
|
|
||||||
},
|
|
||||||
// gdb.LocalTypeUint64
|
|
||||||
"uint64": {
|
|
||||||
Type: "uint64",
|
|
||||||
},
|
|
||||||
// gdb.LocalTypeIntSlice
|
|
||||||
"[]int": {
|
|
||||||
Type: "repeated int32",
|
|
||||||
},
|
|
||||||
// gdb.LocalTypeInt64Slice
|
|
||||||
"[]int64": {
|
|
||||||
Type: "repeated int64",
|
|
||||||
},
|
|
||||||
// gdb.LocalTypeUint64Slice
|
|
||||||
"[]uint64": {
|
|
||||||
Type: "repeated uint64",
|
|
||||||
},
|
|
||||||
// gdb.LocalTypeInt64Bytes
|
|
||||||
"int64-bytes": {
|
|
||||||
Type: "repeated int64",
|
|
||||||
},
|
|
||||||
// gdb.LocalTypeUint64Bytes
|
|
||||||
"uint64-bytes": {
|
|
||||||
Type: "repeated uint64",
|
|
||||||
},
|
|
||||||
// gdb.LocalTypeFloat32
|
|
||||||
"float32": {
|
|
||||||
Type: "float",
|
|
||||||
},
|
|
||||||
// gdb.LocalTypeFloat64
|
|
||||||
"float64": {
|
|
||||||
Type: "double",
|
|
||||||
},
|
|
||||||
// gdb.LocalTypeBytes
|
|
||||||
"[]byte": {
|
|
||||||
Type: "bytes",
|
|
||||||
},
|
|
||||||
// gdb.LocalTypeBool
|
|
||||||
"bool": {
|
|
||||||
Type: "bool",
|
|
||||||
},
|
|
||||||
// gdb.LocalTypeJson
|
|
||||||
// "json": {
|
|
||||||
// Type: "google.protobuf.Value",
|
|
||||||
// Import: "google/protobuf/struct.proto",
|
|
||||||
// },
|
|
||||||
// gdb.LocalTypeJsonb
|
|
||||||
// "jsonb": {
|
|
||||||
// Type: "google.protobuf.Value",
|
|
||||||
// Import: "google/protobuf/struct.proto",
|
|
||||||
// },
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
gtag.Sets(g.MapStrStr{
|
gtag.Sets(g.MapStrStr{
|
||||||
`CGenPbEntityConfig`: CGenPbEntityConfig,
|
`CGenPbEntityConfig`: CGenPbEntityConfig,
|
||||||
`CGenPbEntityBrief`: CGenPbEntityBrief,
|
`CGenPbEntityBrief`: CGenPbEntityBrief,
|
||||||
`CGenPbEntityEg`: CGenPbEntityEg,
|
`CGenPbEntityEg`: CGenPbEntityEg,
|
||||||
`CGenPbEntityAd`: CGenPbEntityAd,
|
`CGenPbEntityAd`: CGenPbEntityAd,
|
||||||
`CGenPbEntityBriefPath`: CGenPbEntityBriefPath,
|
`CGenPbEntityBriefPath`: CGenPbEntityBriefPath,
|
||||||
`CGenPbEntityBriefPackage`: CGenPbEntityBriefPackage,
|
`CGenPbEntityBriefPackage`: CGenPbEntityBriefPackage,
|
||||||
`CGenPbEntityBriefGoPackage`: CGenPbEntityBriefGoPackage,
|
`CGenPbEntityBriefLink`: CGenPbEntityBriefLink,
|
||||||
`CGenPbEntityBriefLink`: CGenPbEntityBriefLink,
|
`CGenPbEntityBriefTables`: CGenPbEntityBriefTables,
|
||||||
`CGenPbEntityBriefTables`: CGenPbEntityBriefTables,
|
`CGenPbEntityBriefPrefix`: CGenPbEntityBriefPrefix,
|
||||||
`CGenPbEntityBriefPrefix`: CGenPbEntityBriefPrefix,
|
`CGenPbEntityBriefRemovePrefix`: CGenPbEntityBriefRemovePrefix,
|
||||||
`CGenPbEntityBriefRemovePrefix`: CGenPbEntityBriefRemovePrefix,
|
`CGenPbEntityBriefGroup`: CGenPbEntityBriefGroup,
|
||||||
`CGenPbEntityBriefTablesEx`: CGenPbEntityBriefTablesEx,
|
`CGenPbEntityBriefNameCase`: CGenPbEntityBriefNameCase,
|
||||||
`CGenPbEntityBriefRemoveFieldPrefix`: CGenPbEntityBriefRemoveFieldPrefix,
|
`CGenPbEntityBriefJsonCase`: CGenPbEntityBriefJsonCase,
|
||||||
`CGenPbEntityBriefGroup`: CGenPbEntityBriefGroup,
|
`CGenPbEntityBriefOption`: CGenPbEntityBriefOption,
|
||||||
`CGenPbEntityBriefNameCase`: CGenPbEntityBriefNameCase,
|
|
||||||
`CGenPbEntityBriefJsonCase`: CGenPbEntityBriefJsonCase,
|
|
||||||
`CGenPbEntityBriefOption`: CGenPbEntityBriefOption,
|
|
||||||
`CGenPbEntityBriefShardingPattern`: CGenPbEntityBriefShardingPattern,
|
|
||||||
`CGenPbEntityBriefTypeMapping`: CGenPbEntityBriefTypeMapping,
|
|
||||||
`CGenPbEntityBriefFieldMapping`: CGenPbEntityBriefFieldMapping,
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -298,13 +173,22 @@ func doGenPbEntityForArray(ctx context.Context, index int, in CGenPbEntityInput)
|
|||||||
}
|
}
|
||||||
if in.Package == "" {
|
if in.Package == "" {
|
||||||
mlog.Debug(`package parameter is empty, trying calculating the package path using go.mod`)
|
mlog.Debug(`package parameter is empty, trying calculating the package path using go.mod`)
|
||||||
modName := utils.GetImportPath(gfile.Pwd())
|
if !gfile.Exists("go.mod") {
|
||||||
in.Package = modName + "/" + defaultPackageSuffix
|
mlog.Fatal("go.mod does not exist in current working directory")
|
||||||
|
}
|
||||||
|
var (
|
||||||
|
modName string
|
||||||
|
goModContent = gfile.GetContents("go.mod")
|
||||||
|
match, _ = gregex.MatchString(`^module\s+(.+)\s*`, goModContent)
|
||||||
|
)
|
||||||
|
if len(match) > 1 {
|
||||||
|
modName = gstr.Trim(match[1])
|
||||||
|
in.Package = modName + "/" + defaultPackageSuffix
|
||||||
|
} else {
|
||||||
|
mlog.Fatal("module name does not found in go.mod")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
removePrefixArray := gstr.SplitAndTrim(in.RemovePrefix, ",")
|
removePrefixArray := gstr.SplitAndTrim(in.RemovePrefix, ",")
|
||||||
|
|
||||||
excludeTables := gset.NewStrSetFrom(gstr.SplitAndTrim(in.TablesEx, ","))
|
|
||||||
|
|
||||||
// It uses user passed database configuration.
|
// It uses user passed database configuration.
|
||||||
if in.Link != "" {
|
if in.Link != "" {
|
||||||
var (
|
var (
|
||||||
@ -314,7 +198,7 @@ func doGenPbEntityForArray(ctx context.Context, index int, in CGenPbEntityInput)
|
|||||||
if len(match) == 3 {
|
if len(match) == 3 {
|
||||||
gdb.AddConfigNode(tempGroup, gdb.ConfigNode{
|
gdb.AddConfigNode(tempGroup, gdb.ConfigNode{
|
||||||
Type: gstr.Trim(match[1]),
|
Type: gstr.Trim(match[1]),
|
||||||
Link: in.Link,
|
Link: gstr.Trim(match[2]),
|
||||||
})
|
})
|
||||||
db, _ = gdb.Instance(tempGroup)
|
db, _ = gdb.Instance(tempGroup)
|
||||||
}
|
}
|
||||||
@ -326,7 +210,6 @@ func doGenPbEntityForArray(ctx context.Context, index int, in CGenPbEntityInput)
|
|||||||
}
|
}
|
||||||
|
|
||||||
tableNames := ([]string)(nil)
|
tableNames := ([]string)(nil)
|
||||||
shardingNewTableSet := gset.NewStrSet()
|
|
||||||
if in.Tables != "" {
|
if in.Tables != "" {
|
||||||
tableNames = gstr.SplitAndTrim(in.Tables, ",")
|
tableNames = gstr.SplitAndTrim(in.Tables, ",")
|
||||||
} else {
|
} else {
|
||||||
@ -335,50 +218,12 @@ func doGenPbEntityForArray(ctx context.Context, index int, in CGenPbEntityInput)
|
|||||||
mlog.Fatalf("fetching tables failed: \n %v", err)
|
mlog.Fatalf("fetching tables failed: \n %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// merge default typeMapping to input typeMapping.
|
|
||||||
if in.TypeMapping == nil {
|
|
||||||
in.TypeMapping = defaultTypeMapping
|
|
||||||
} else {
|
|
||||||
for key, typeMapping := range defaultTypeMapping {
|
|
||||||
if _, ok := in.TypeMapping[key]; !ok {
|
|
||||||
in.TypeMapping[key] = typeMapping
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, tableName := range tableNames {
|
for _, tableName := range tableNames {
|
||||||
if excludeTables.Contains(tableName) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
newTableName := tableName
|
newTableName := tableName
|
||||||
for _, v := range removePrefixArray {
|
for _, v := range removePrefixArray {
|
||||||
newTableName = gstr.TrimLeftStr(newTableName, v, 1)
|
newTableName = gstr.TrimLeftStr(newTableName, v, 1)
|
||||||
}
|
}
|
||||||
var shardingTableName string
|
|
||||||
if len(in.ShardingPattern) > 0 {
|
|
||||||
for _, pattern := range in.ShardingPattern {
|
|
||||||
var (
|
|
||||||
match []string
|
|
||||||
regPattern = gstr.Replace(pattern, "?", `(.+)`)
|
|
||||||
)
|
|
||||||
match, err = gregex.MatchString(regPattern, newTableName)
|
|
||||||
if err != nil {
|
|
||||||
mlog.Fatalf(`invalid sharding pattern "%s": %+v`, pattern, err)
|
|
||||||
}
|
|
||||||
if len(match) < 2 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
shardingTableName = gstr.Replace(pattern, "?", "")
|
|
||||||
shardingTableName = gstr.Trim(shardingTableName, `_.-`)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if shardingTableName != "" {
|
|
||||||
if shardingNewTableSet.Contains(shardingTableName) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
shardingNewTableSet.Add(shardingTableName)
|
|
||||||
newTableName = shardingTableName
|
|
||||||
}
|
|
||||||
generatePbEntityContentFile(ctx, CGenPbEntityInternalInput{
|
generatePbEntityContentFile(ctx, CGenPbEntityInternalInput{
|
||||||
CGenPbEntityInput: in,
|
CGenPbEntityInput: in,
|
||||||
DB: db,
|
DB: db,
|
||||||
@ -397,113 +242,91 @@ func generatePbEntityContentFile(ctx context.Context, in CGenPbEntityInternalInp
|
|||||||
// Change the `newTableName` if `Prefix` is given.
|
// Change the `newTableName` if `Prefix` is given.
|
||||||
newTableName := in.Prefix + in.NewTableName
|
newTableName := in.Prefix + in.NewTableName
|
||||||
var (
|
var (
|
||||||
tableNameCamelCase = gstr.CaseCamel(newTableName)
|
imports string
|
||||||
tableNameSnakeCase = gstr.CaseSnake(newTableName)
|
tableNameCamelCase = gstr.CaseCamel(newTableName)
|
||||||
entityMessageDefine, appendImports = generateEntityMessageDefinition(tableNameCamelCase, fieldMap, in)
|
tableNameSnakeCase = gstr.CaseSnake(newTableName)
|
||||||
fileName = gstr.Trim(tableNameSnakeCase, "-_.")
|
entityMessageDefine = generateEntityMessageDefinition(tableNameCamelCase, fieldMap, in)
|
||||||
path = filepath.FromSlash(gfile.Join(in.Path, fileName+".proto"))
|
fileName = gstr.Trim(tableNameSnakeCase, "-_.")
|
||||||
|
path = filepath.FromSlash(gfile.Join(in.Path, fileName+".proto"))
|
||||||
)
|
)
|
||||||
packageImportStr := ""
|
if gstr.Contains(entityMessageDefine, "google.protobuf.Timestamp") {
|
||||||
var packageImportsArray = garray.NewStrArray()
|
imports = `import "google/protobuf/timestamp.proto";`
|
||||||
if len(appendImports) > 0 {
|
|
||||||
for _, appendImport := range appendImports {
|
|
||||||
packageImportStr = fmt.Sprintf(`import "%s";`, appendImport)
|
|
||||||
if packageImportsArray.Search(packageImportStr) == -1 {
|
|
||||||
packageImportsArray.Append(packageImportStr)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if in.GoPackage == "" {
|
|
||||||
in.GoPackage = in.Package
|
|
||||||
}
|
}
|
||||||
entityContent := gstr.ReplaceByMap(getTplPbEntityContent(""), g.MapStrStr{
|
entityContent := gstr.ReplaceByMap(getTplPbEntityContent(""), g.MapStrStr{
|
||||||
"{Imports}": packageImportsArray.Join("\n"),
|
"{Imports}": imports,
|
||||||
"{PackageName}": gfile.Basename(in.Package),
|
"{PackageName}": gfile.Basename(in.Package),
|
||||||
"{GoPackage}": in.GoPackage,
|
"{GoPackage}": in.Package,
|
||||||
"{OptionContent}": in.Option,
|
"{OptionContent}": in.Option,
|
||||||
"{EntityMessage}": entityMessageDefine,
|
"{EntityMessage}": entityMessageDefine,
|
||||||
})
|
})
|
||||||
if err := gfile.PutContents(path, strings.TrimSpace(entityContent)); err != nil {
|
if err := gfile.PutContents(path, strings.TrimSpace(entityContent)); err != nil {
|
||||||
mlog.Fatalf("writing content to '%s' failed: %v", path, err)
|
mlog.Fatalf("writing content to '%s' failed: %v", path, err)
|
||||||
} else {
|
} else {
|
||||||
mlog.Print("generated:", gfile.RealPath(path))
|
mlog.Print("generated:", path)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// generateEntityMessageDefinition generates and returns the message definition for specified table.
|
// generateEntityMessageDefinition generates and returns the message definition for specified table.
|
||||||
func generateEntityMessageDefinition(entityName string, fieldMap map[string]*gdb.TableField, in CGenPbEntityInternalInput) (string, []string) {
|
func generateEntityMessageDefinition(entityName string, fieldMap map[string]*gdb.TableField, in CGenPbEntityInternalInput) string {
|
||||||
var (
|
var (
|
||||||
appendImports []string
|
buffer = bytes.NewBuffer(nil)
|
||||||
buffer = bytes.NewBuffer(nil)
|
array = make([][]string, len(fieldMap))
|
||||||
array = make([][]string, len(fieldMap))
|
names = sortFieldKeyForPbEntity(fieldMap)
|
||||||
names = sortFieldKeyForPbEntity(fieldMap)
|
|
||||||
)
|
)
|
||||||
for index, name := range names {
|
for index, name := range names {
|
||||||
var imports string
|
array[index] = generateMessageFieldForPbEntity(index+1, fieldMap[name], in)
|
||||||
array[index], imports = generateMessageFieldForPbEntity(index+1, fieldMap[name], in)
|
|
||||||
if imports != "" {
|
|
||||||
appendImports = append(appendImports, imports)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
table := tablewriter.NewTable(buffer,
|
tw := tablewriter.NewWriter(buffer)
|
||||||
tablewriter.WithRenderer(renderer.NewBlueprint(tw.Rendition{
|
tw.SetBorder(false)
|
||||||
Borders: tw.Border{Top: tw.Off, Bottom: tw.Off, Left: tw.On, Right: tw.Off},
|
tw.SetRowLine(false)
|
||||||
Settings: tw.Settings{
|
tw.SetAutoWrapText(false)
|
||||||
Separators: tw.Separators{BetweenRows: tw.Off, BetweenColumns: tw.Off},
|
tw.SetColumnSeparator("")
|
||||||
},
|
tw.AppendBulk(array)
|
||||||
Symbols: tw.NewSymbolCustom("Proto").WithColumn(" "),
|
tw.Render()
|
||||||
})),
|
|
||||||
tablewriter.WithConfig(tablewriter.Config{
|
|
||||||
Row: tw.CellConfig{
|
|
||||||
Formatting: tw.CellFormatting{AutoWrap: tw.WrapNone},
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
table.Bulk(array)
|
|
||||||
table.Render()
|
|
||||||
stContent := buffer.String()
|
stContent := buffer.String()
|
||||||
// Let's do this hack of table writer for indent!
|
// Let's do this hack of table writer for indent!
|
||||||
stContent = regexp.MustCompile(`\s+\n`).ReplaceAllString(gstr.Replace(stContent, " #", ""), "\n")
|
stContent = gstr.Replace(stContent, " #", "")
|
||||||
buffer.Reset()
|
buffer.Reset()
|
||||||
buffer.WriteString(fmt.Sprintf("message %s {\n", entityName))
|
buffer.WriteString(fmt.Sprintf("message %s {\n", entityName))
|
||||||
buffer.WriteString(stContent)
|
buffer.WriteString(stContent)
|
||||||
buffer.WriteString("}")
|
buffer.WriteString("}")
|
||||||
return buffer.String(), appendImports
|
return buffer.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
// generateMessageFieldForPbEntity generates and returns the message definition for specified field.
|
// generateMessageFieldForPbEntity generates and returns the message definition for specified field.
|
||||||
func generateMessageFieldForPbEntity(index int, field *gdb.TableField, in CGenPbEntityInternalInput) (attrLines []string, appendImport string) {
|
func generateMessageFieldForPbEntity(index int, field *gdb.TableField, in CGenPbEntityInternalInput) []string {
|
||||||
var (
|
var (
|
||||||
localTypeNameStr string
|
localTypeName gdb.LocalType
|
||||||
localTypeName gdb.LocalType
|
comment string
|
||||||
comment string
|
jsonTagStr string
|
||||||
jsonTagStr string
|
err error
|
||||||
err error
|
ctx = gctx.GetInitCtx()
|
||||||
ctx = gctx.GetInitCtx()
|
|
||||||
)
|
)
|
||||||
if in.TypeMapping != nil && len(in.TypeMapping) > 0 {
|
localTypeName, err = in.DB.CheckLocalTypeForField(ctx, field.Type, nil)
|
||||||
// match typeMapping after local type transform.
|
if err != nil {
|
||||||
// eg: double => string, varchar => string etc.
|
panic(err)
|
||||||
localTypeName, err = in.DB.CheckLocalTypeForField(ctx, field.Type, nil)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
if localTypeName != "" {
|
|
||||||
if typeMappingLocal, localOk := in.TypeMapping[strings.ToLower(string(localTypeName))]; localOk {
|
|
||||||
localTypeNameStr = typeMappingLocal.Type
|
|
||||||
appendImport = typeMappingLocal.Import
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Try match unknown / string localTypeName with db type.
|
|
||||||
if localTypeName == "" || localTypeName == gdb.LocalTypeString {
|
|
||||||
formattedFieldType, _ := in.DB.GetFormattedDBTypeNameForField(field.Type)
|
|
||||||
if typeMapping, ok := in.TypeMapping[strings.ToLower(formattedFieldType)]; ok {
|
|
||||||
localTypeNameStr = typeMapping.Type
|
|
||||||
appendImport = typeMapping.Import
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
var typeMapping = map[gdb.LocalType]string{
|
||||||
|
gdb.LocalTypeString: "string",
|
||||||
|
gdb.LocalTypeDate: "google.protobuf.Timestamp",
|
||||||
|
gdb.LocalTypeDatetime: "google.protobuf.Timestamp",
|
||||||
|
gdb.LocalTypeInt: "int32",
|
||||||
|
gdb.LocalTypeUint: "uint32",
|
||||||
|
gdb.LocalTypeInt64: "int64",
|
||||||
|
gdb.LocalTypeUint64: "uint64",
|
||||||
|
gdb.LocalTypeIntSlice: "repeated int32",
|
||||||
|
gdb.LocalTypeInt64Slice: "repeated int64",
|
||||||
|
gdb.LocalTypeUint64Slice: "repeated uint64",
|
||||||
|
gdb.LocalTypeInt64Bytes: "repeated int64",
|
||||||
|
gdb.LocalTypeUint64Bytes: "repeated uint64",
|
||||||
|
gdb.LocalTypeFloat32: "float",
|
||||||
|
gdb.LocalTypeFloat64: "double",
|
||||||
|
gdb.LocalTypeBytes: "bytes",
|
||||||
|
gdb.LocalTypeBool: "bool",
|
||||||
|
gdb.LocalTypeJson: "string",
|
||||||
|
gdb.LocalTypeJsonb: "string",
|
||||||
|
}
|
||||||
|
localTypeNameStr := typeMapping[localTypeName]
|
||||||
if localTypeNameStr == "" {
|
if localTypeNameStr == "" {
|
||||||
localTypeNameStr = "string"
|
localTypeNameStr = "string"
|
||||||
}
|
}
|
||||||
@ -516,7 +339,6 @@ func generateMessageFieldForPbEntity(index int, field *gdb.TableField, in CGenPb
|
|||||||
comment = gstr.Replace(comment, `\n`, " ")
|
comment = gstr.Replace(comment, `\n`, " ")
|
||||||
comment, _ = gregex.ReplaceString(`\s{2,}`, ` `, comment)
|
comment, _ = gregex.ReplaceString(`\s{2,}`, ` `, comment)
|
||||||
if jsonTagName := formatCase(field.Name, in.JsonCase); jsonTagName != "" {
|
if jsonTagName := formatCase(field.Name, in.JsonCase); jsonTagName != "" {
|
||||||
jsonTagStr = fmt.Sprintf(`[json_name = "%s"]`, jsonTagName)
|
|
||||||
// beautiful indent.
|
// beautiful indent.
|
||||||
if index < 10 {
|
if index < 10 {
|
||||||
// 3 spaces
|
// 3 spaces
|
||||||
@ -529,26 +351,12 @@ func generateMessageFieldForPbEntity(index int, field *gdb.TableField, in CGenPb
|
|||||||
jsonTagStr = " " + jsonTagStr
|
jsonTagStr = " " + jsonTagStr
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
removeFieldPrefixArray := gstr.SplitAndTrim(in.RemoveFieldPrefix, ",")
|
|
||||||
newFiledName := field.Name
|
|
||||||
for _, v := range removeFieldPrefixArray {
|
|
||||||
newFiledName = gstr.TrimLeftStr(newFiledName, v, 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
if in.FieldMapping != nil && len(in.FieldMapping) > 0 {
|
|
||||||
if typeMapping, ok := in.FieldMapping[fmt.Sprintf("%s.%s", in.TableName, newFiledName)]; ok {
|
|
||||||
localTypeNameStr = typeMapping.Type
|
|
||||||
appendImport = typeMapping.Import
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return []string{
|
return []string{
|
||||||
" #" + localTypeNameStr,
|
" #" + localTypeNameStr,
|
||||||
" #" + formatCase(newFiledName, in.NameCase),
|
" #" + formatCase(field.Name, in.NameCase),
|
||||||
" #= " + gconv.String(index) + jsonTagStr + ";",
|
" #= " + gconv.String(index) + jsonTagStr + ";",
|
||||||
" #" + fmt.Sprintf(`// %s`, comment),
|
" #" + fmt.Sprintf(`// %s`, comment),
|
||||||
}, appendImport
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func getTplPbEntityContent(tplEntityPath string) string {
|
func getTplPbEntityContent(tplEntityPath string) string {
|
||||||
@ -560,10 +368,32 @@ func getTplPbEntityContent(tplEntityPath string) string {
|
|||||||
|
|
||||||
// formatCase call gstr.Case* function to convert the s to specified case.
|
// formatCase call gstr.Case* function to convert the s to specified case.
|
||||||
func formatCase(str, caseStr string) string {
|
func formatCase(str, caseStr string) string {
|
||||||
if caseStr == "none" {
|
switch gstr.ToLower(caseStr) {
|
||||||
|
case gstr.ToLower("Camel"):
|
||||||
|
return gstr.CaseCamel(str)
|
||||||
|
|
||||||
|
case gstr.ToLower("CamelLower"):
|
||||||
|
return gstr.CaseCamelLower(str)
|
||||||
|
|
||||||
|
case gstr.ToLower("Kebab"):
|
||||||
|
return gstr.CaseKebab(str)
|
||||||
|
|
||||||
|
case gstr.ToLower("KebabScreaming"):
|
||||||
|
return gstr.CaseKebabScreaming(str)
|
||||||
|
|
||||||
|
case gstr.ToLower("Snake"):
|
||||||
|
return gstr.CaseSnake(str)
|
||||||
|
|
||||||
|
case gstr.ToLower("SnakeFirstUpper"):
|
||||||
|
return gstr.CaseSnakeFirstUpper(str)
|
||||||
|
|
||||||
|
case gstr.ToLower("SnakeScreaming"):
|
||||||
|
return gstr.CaseSnakeScreaming(str)
|
||||||
|
|
||||||
|
case "none":
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
return gstr.CaseConvert(str, gstr.CaseTypeMatch(caseStr))
|
return str
|
||||||
}
|
}
|
||||||
|
|
||||||
func sortFieldKeyForPbEntity(fieldMap map[string]*gdb.TableField) []string {
|
func sortFieldKeyForPbEntity(fieldMap map[string]*gdb.TableField) []string {
|
||||||
|
|||||||
@ -9,9 +9,6 @@ package genservice
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"path/filepath"
|
|
||||||
"sync"
|
|
||||||
"sync/atomic"
|
|
||||||
|
|
||||||
"github.com/gogf/gf/v2/container/garray"
|
"github.com/gogf/gf/v2/container/garray"
|
||||||
"github.com/gogf/gf/v2/container/gmap"
|
"github.com/gogf/gf/v2/container/gmap"
|
||||||
@ -95,25 +92,11 @@ const (
|
|||||||
genServiceFileLockSeconds = 10
|
genServiceFileLockSeconds = 10
|
||||||
)
|
)
|
||||||
|
|
||||||
type fileInfo struct {
|
|
||||||
PkgItems []pkgItem
|
|
||||||
FuncItems []funcItem
|
|
||||||
}
|
|
||||||
|
|
||||||
type folderInfo struct {
|
|
||||||
SrcPackageName string
|
|
||||||
SrcImportedPackages *garray.SortedStrArray
|
|
||||||
SrcStructFunctions *gmap.ListMap
|
|
||||||
DstFilePath string
|
|
||||||
|
|
||||||
FileInfos []*fileInfo
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c CGenService) Service(ctx context.Context, in CGenServiceInput) (out *CGenServiceOutput, err error) {
|
func (c CGenService) Service(ctx context.Context, in CGenServiceInput) (out *CGenServiceOutput, err error) {
|
||||||
in.SrcFolder = filepath.ToSlash(in.SrcFolder)
|
in.SrcFolder = gstr.TrimRight(in.SrcFolder, `\/`)
|
||||||
in.SrcFolder = gstr.TrimRight(in.SrcFolder, `/`)
|
in.SrcFolder = gstr.Replace(in.SrcFolder, "\\", "/")
|
||||||
in.WatchFile = filepath.ToSlash(in.WatchFile)
|
in.WatchFile = gstr.TrimRight(in.WatchFile, `\/`)
|
||||||
in.WatchFile = gstr.TrimRight(in.WatchFile, `/`)
|
in.WatchFile = gstr.Replace(in.WatchFile, "\\", "/")
|
||||||
|
|
||||||
// Watch file handling.
|
// Watch file handling.
|
||||||
if in.WatchFile != "" {
|
if in.WatchFile != "" {
|
||||||
@ -129,7 +112,7 @@ func (c CGenService) Service(ctx context.Context, in CGenServiceInput) (out *CGe
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
defer gfile.RemoveFile(flockFilePath)
|
defer gfile.Remove(flockFilePath)
|
||||||
_ = gfile.PutContents(flockFilePath, gtime.TimestampStr())
|
_ = gfile.PutContents(flockFilePath, gtime.TimestampStr())
|
||||||
|
|
||||||
// It works only if given WatchFile is in SrcFolder.
|
// It works only if given WatchFile is in SrcFolder.
|
||||||
@ -163,27 +146,19 @@ func (c CGenService) Service(ctx context.Context, in CGenServiceInput) (out *CGe
|
|||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
isDirty atomic.Value // Temp boolean.
|
isDirty bool // Temp boolean.
|
||||||
files []string // Temp file array.
|
files []string // Temp file array.
|
||||||
|
fileContent string // Temp file content for handling go file.
|
||||||
initImportSrcPackages []string // Used for generating logic.go.
|
initImportSrcPackages []string // Used for generating logic.go.
|
||||||
inputPackages = in.Packages // Custom packages.
|
inputPackages = in.Packages // Custom packages.
|
||||||
dstPackageName = gstr.ToLower(gfile.Basename(in.DstFolder)) // Package name for generated go files.
|
dstPackageName = gstr.ToLower(gfile.Basename(in.DstFolder)) // Package name for generated go files.
|
||||||
generatedDstFilePathSet = gset.NewStrSet() // All generated file path set.
|
generatedDstFilePathSet = gset.NewStrSet() // All generated file path set.
|
||||||
)
|
)
|
||||||
isDirty.Store(false)
|
|
||||||
|
|
||||||
// The first level folders.
|
// The first level folders.
|
||||||
srcFolderPaths, err := gfile.ScanDir(in.SrcFolder, "*", false)
|
srcFolderPaths, err := gfile.ScanDir(in.SrcFolder, "*", false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
// it will use goroutine to generate service files for each package.
|
|
||||||
var (
|
|
||||||
folderInfos []folderInfo
|
|
||||||
wg = sync.WaitGroup{}
|
|
||||||
allStructItems = make(map[string][]string)
|
|
||||||
)
|
|
||||||
|
|
||||||
for _, srcFolderPath := range srcFolderPaths {
|
for _, srcFolderPath := range srcFolderPaths {
|
||||||
if !gfile.IsDir(srcFolderPath) {
|
if !gfile.IsDir(srcFolderPath) {
|
||||||
continue
|
continue
|
||||||
@ -195,64 +170,113 @@ func (c CGenService) Service(ctx context.Context, in CGenServiceInput) (out *CGe
|
|||||||
if len(files) == 0 {
|
if len(files) == 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
|
||||||
srcPackageName = gfile.Basename(srcFolderPath)
|
|
||||||
srcImportedPackages = garray.NewSortedStrArray().SetUnique(true)
|
|
||||||
srcStructFunctions = gmap.NewListMap()
|
|
||||||
dstFilePath = gfile.Join(in.DstFolder,
|
|
||||||
c.getDstFileNameCase(srcPackageName, in.DstFileNameCase)+".go",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
folder := folderInfo{
|
|
||||||
SrcPackageName: srcPackageName,
|
|
||||||
SrcImportedPackages: srcImportedPackages,
|
|
||||||
SrcStructFunctions: srcStructFunctions,
|
|
||||||
DstFilePath: dstFilePath,
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, file := range files {
|
|
||||||
pkgItems, structItems, funcItems, err := c.parseItemsInSrc(file)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
for k, v := range structItems {
|
|
||||||
allStructItems[k] = v
|
|
||||||
}
|
|
||||||
folder.FileInfos = append(folder.FileInfos, &fileInfo{
|
|
||||||
PkgItems: pkgItems,
|
|
||||||
FuncItems: funcItems,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
folderInfos = append(folderInfos, folder)
|
|
||||||
}
|
|
||||||
|
|
||||||
folderInfos = c.calculateStructEmbeddedFuncInfos(folderInfos, allStructItems)
|
|
||||||
|
|
||||||
for _, folder := range folderInfos {
|
|
||||||
// Parse single logic package folder.
|
// Parse single logic package folder.
|
||||||
var (
|
var (
|
||||||
srcPackageName = folder.SrcPackageName
|
// StructName => FunctionDefinitions
|
||||||
srcImportedPackages = folder.SrcImportedPackages
|
srcPkgInterfaceMap = make(map[string]*garray.StrArray)
|
||||||
srcStructFunctions = folder.SrcStructFunctions
|
srcImportedPackages = garray.NewSortedStrArray().SetUnique(true)
|
||||||
dstFilePath = folder.DstFilePath
|
importAliasToPathMap = gmap.NewStrStrMap() // for conflict imports check. alias => import path(with `"`)
|
||||||
|
importPathToAliasMap = gmap.NewStrStrMap() // for conflict imports check. import path(with `"`) => alias
|
||||||
|
srcPackageName = gfile.Basename(srcFolderPath)
|
||||||
|
ok bool
|
||||||
|
dstFilePath = gfile.Join(in.DstFolder,
|
||||||
|
c.getDstFileNameCase(srcPackageName, in.DstFileNameCase)+".go",
|
||||||
|
)
|
||||||
|
srcCodeCommentedMap = make(map[string]string)
|
||||||
)
|
)
|
||||||
generatedDstFilePathSet.Add(dstFilePath)
|
generatedDstFilePathSet.Add(dstFilePath)
|
||||||
// if it were to use goroutine,
|
for _, file := range files {
|
||||||
// it would cause the order of the generated functions in the file to be disordered.
|
var packageItems []packageItem
|
||||||
for _, file := range folder.FileInfos {
|
fileContent = gfile.GetContents(file)
|
||||||
pkgItems, funcItems := file.PkgItems, file.FuncItems
|
// Calculate code comments in source Go files.
|
||||||
|
err = c.calculateCodeCommented(in, fileContent, srcCodeCommentedMap)
|
||||||
// Calculate imported packages for service generating.
|
|
||||||
err = c.calculateImportedItems(in, pkgItems, funcItems, srcImportedPackages)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
// remove all comments.
|
||||||
|
fileContent, err = gregex.ReplaceString(`(//.*)|((?s)/\*.*?\*/)`, "", fileContent)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate imported packages of source go files.
|
||||||
|
packageItems, err = c.calculateImportedPackages(fileContent)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
// try finding the conflicts imports between files.
|
||||||
|
for _, item := range packageItems {
|
||||||
|
var alias = item.Alias
|
||||||
|
if alias == "" {
|
||||||
|
alias = gfile.Basename(gstr.Trim(item.Path, `"`))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ignore unused import paths, which do not exist in function definitions.
|
||||||
|
if !gregex.IsMatchString(fmt.Sprintf(`func .+?([^\w])%s(\.\w+).+?{`, alias), fileContent) {
|
||||||
|
mlog.Debugf(`ignore unused package: %s`, item.RawImport)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// find the exist alias with the same import path.
|
||||||
|
var existAlias = importPathToAliasMap.Get(item.Path)
|
||||||
|
if existAlias != "" {
|
||||||
|
fileContent, err = gregex.ReplaceStringFuncMatch(
|
||||||
|
fmt.Sprintf(`([^\w])%s(\.\w+)`, alias), fileContent,
|
||||||
|
func(match []string) string {
|
||||||
|
return match[1] + existAlias + match[2]
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// resolve alias conflicts.
|
||||||
|
var importPath = importAliasToPathMap.Get(alias)
|
||||||
|
if importPath == "" {
|
||||||
|
importAliasToPathMap.Set(alias, item.Path)
|
||||||
|
importPathToAliasMap.Set(item.Path, alias)
|
||||||
|
srcImportedPackages.Add(item.RawImport)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if importPath != item.Path {
|
||||||
|
// update the conflicted alias for import path with suffix.
|
||||||
|
// eg:
|
||||||
|
// v1 -> v10
|
||||||
|
// v11 -> v110
|
||||||
|
for aliasIndex := 0; ; aliasIndex++ {
|
||||||
|
item.Alias = fmt.Sprintf(`%s%d`, alias, aliasIndex)
|
||||||
|
var existPathForAlias = importAliasToPathMap.Get(item.Alias)
|
||||||
|
if existPathForAlias != "" {
|
||||||
|
if existPathForAlias == item.Path {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
importPathToAliasMap.Set(item.Path, item.Alias)
|
||||||
|
importAliasToPathMap.Set(item.Alias, item.Path)
|
||||||
|
// reformat the import path with alias.
|
||||||
|
item.RawImport = fmt.Sprintf(`%s %s`, item.Alias, item.Path)
|
||||||
|
|
||||||
|
// update the file content with new alias import.
|
||||||
|
fileContent, err = gregex.ReplaceStringFuncMatch(
|
||||||
|
fmt.Sprintf(`([^\w])%s(\.\w+)`, alias), fileContent,
|
||||||
|
func(match []string) string {
|
||||||
|
return match[1] + item.Alias + match[2]
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
srcImportedPackages.Add(item.RawImport)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Calculate functions and interfaces for service generating.
|
// Calculate functions and interfaces for service generating.
|
||||||
err = c.calculateFuncItems(in, funcItems, srcStructFunctions)
|
err = c.calculateInterfaceFunctions(in, fileContent, srcPkgInterfaceMap)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -270,28 +294,22 @@ func (c CGenService) Service(ctx context.Context, in CGenServiceInput) (out *CGe
|
|||||||
)
|
)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generating service go file for single logic package.
|
// Generating service go file for single logic package.
|
||||||
wg.Add(1)
|
if ok, err = c.generateServiceFile(generateServiceFilesInput{
|
||||||
go func(generateServiceFilesInput generateServiceFilesInput) {
|
|
||||||
defer wg.Done()
|
|
||||||
ok, err := c.generateServiceFile(generateServiceFilesInput)
|
|
||||||
if err != nil {
|
|
||||||
mlog.Printf(`error generating service file "%s": %v`, generateServiceFilesInput.DstFilePath, err)
|
|
||||||
}
|
|
||||||
if !isDirty.Load().(bool) && ok {
|
|
||||||
isDirty.Store(true)
|
|
||||||
}
|
|
||||||
}(generateServiceFilesInput{
|
|
||||||
CGenServiceInput: in,
|
CGenServiceInput: in,
|
||||||
SrcPackageName: srcPackageName,
|
SrcStructFunctions: srcPkgInterfaceMap,
|
||||||
SrcImportedPackages: srcImportedPackages.Slice(),
|
SrcImportedPackages: srcImportedPackages.Slice(),
|
||||||
SrcStructFunctions: srcStructFunctions,
|
SrcPackageName: srcPackageName,
|
||||||
DstPackageName: dstPackageName,
|
DstPackageName: dstPackageName,
|
||||||
DstFilePath: dstFilePath,
|
DstFilePath: dstFilePath,
|
||||||
})
|
SrcCodeCommentedMap: srcCodeCommentedMap,
|
||||||
|
}); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if ok {
|
||||||
|
isDirty = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
wg.Wait()
|
|
||||||
|
|
||||||
if in.Clear {
|
if in.Clear {
|
||||||
files, err = gfile.ScanDirFile(in.DstFolder, "*.go", false)
|
files, err = gfile.ScanDirFile(in.DstFolder, "*.go", false)
|
||||||
@ -301,18 +319,16 @@ func (c CGenService) Service(ctx context.Context, in CGenServiceInput) (out *CGe
|
|||||||
var relativeFilePath string
|
var relativeFilePath string
|
||||||
for _, file := range files {
|
for _, file := range files {
|
||||||
relativeFilePath = gstr.SubStrFromR(file, in.DstFolder)
|
relativeFilePath = gstr.SubStrFromR(file, in.DstFolder)
|
||||||
if !generatedDstFilePathSet.Contains(relativeFilePath) &&
|
if !generatedDstFilePathSet.Contains(relativeFilePath) && utils.IsFileDoNotEdit(relativeFilePath) {
|
||||||
utils.IsFileDoNotEdit(relativeFilePath) {
|
|
||||||
|
|
||||||
mlog.Printf(`remove no longer used service file: %s`, relativeFilePath)
|
mlog.Printf(`remove no longer used service file: %s`, relativeFilePath)
|
||||||
if err = gfile.RemoveFile(file); err != nil {
|
if err = gfile.Remove(file); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if isDirty.Load().(bool) {
|
if isDirty {
|
||||||
// Generate initialization go file.
|
// Generate initialization go file.
|
||||||
if len(initImportSrcPackages) > 0 {
|
if len(initImportSrcPackages) > 0 {
|
||||||
if err = c.generateInitializationFile(in, initImportSrcPackages); err != nil {
|
if err = c.generateInitializationFile(in, initImportSrcPackages); err != nil {
|
||||||
@ -341,7 +357,7 @@ func (c CGenService) checkAndUpdateMain(srcFolder string) (err error) {
|
|||||||
var (
|
var (
|
||||||
logicPackageName = gstr.ToLower(gfile.Basename(srcFolder))
|
logicPackageName = gstr.ToLower(gfile.Basename(srcFolder))
|
||||||
logicFilePath = gfile.Join(srcFolder, logicPackageName+".go")
|
logicFilePath = gfile.Join(srcFolder, logicPackageName+".go")
|
||||||
importPath = utils.GetImportPath(srcFolder)
|
importPath = utils.GetImportPath(logicFilePath)
|
||||||
importStr = fmt.Sprintf(`_ "%s"`, importPath)
|
importStr = fmt.Sprintf(`_ "%s"`, importPath)
|
||||||
mainFilePath = gfile.Join(gfile.Dir(gfile.Dir(gfile.Dir(logicFilePath))), "main.go")
|
mainFilePath = gfile.Join(gfile.Dir(gfile.Dir(gfile.Dir(logicFilePath))), "main.go")
|
||||||
mainFileContent = gfile.GetContents(mainFilePath)
|
mainFileContent = gfile.GetContents(mainFilePath)
|
||||||
|
|||||||
@ -1,319 +0,0 @@
|
|||||||
// 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 genservice
|
|
||||||
|
|
||||||
import (
|
|
||||||
"go/ast"
|
|
||||||
"go/parser"
|
|
||||||
"go/token"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/gogf/gf/v2/os/gfile"
|
|
||||||
"github.com/gogf/gf/v2/os/gstructs"
|
|
||||||
"github.com/gogf/gf/v2/text/gstr"
|
|
||||||
)
|
|
||||||
|
|
||||||
type pkgItem struct {
|
|
||||||
Alias string `eg:"gdbas"`
|
|
||||||
Path string `eg:"github.com/gogf/gf/v2/database/gdb"`
|
|
||||||
RawImport string `eg:"gdbas github.com/gogf/gf/v2/database/gdb"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type funcItem struct {
|
|
||||||
Receiver string `eg:"sUser"`
|
|
||||||
MethodName string `eg:"GetList"`
|
|
||||||
Params []map[string]string `eg:"ctx: context.Context, cond: *SearchInput"`
|
|
||||||
Results []map[string]string `eg:"list: []*User, err: error"`
|
|
||||||
Comment string `eg:"Get user list"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// parseItemsInSrc parses the pkgItem and funcItem from the specified file.
|
|
||||||
// It can't skip the private methods.
|
|
||||||
// It can't skip the imported packages of import alias equal to `_`.
|
|
||||||
func (c CGenService) parseItemsInSrc(filePath string) (pkgItems []pkgItem, structItems map[string][]string, funcItems []funcItem, err error) {
|
|
||||||
var (
|
|
||||||
fileContent = gfile.GetContents(filePath)
|
|
||||||
fileSet = token.NewFileSet()
|
|
||||||
)
|
|
||||||
|
|
||||||
node, err := parser.ParseFile(fileSet, "", fileContent, parser.ParseComments)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
structItems = make(map[string][]string)
|
|
||||||
pkg := node.Name.Name
|
|
||||||
pkgAliasMap := make(map[string]string)
|
|
||||||
ast.Inspect(node, func(n ast.Node) bool {
|
|
||||||
switch x := n.(type) {
|
|
||||||
case *ast.ImportSpec:
|
|
||||||
// parse the imported packages.
|
|
||||||
pkgItem := c.parseImportPackages(x)
|
|
||||||
pkgItems = append(pkgItems, pkgItem)
|
|
||||||
pkgPath := strings.Trim(pkgItem.Path, "\"")
|
|
||||||
pkgPath = strings.ReplaceAll(pkgPath, "\\", "/")
|
|
||||||
tmp := strings.Split(pkgPath, "/")
|
|
||||||
srcPkg := tmp[len(tmp)-1]
|
|
||||||
if srcPkg != pkgItem.Alias {
|
|
||||||
pkgAliasMap[pkgItem.Alias] = srcPkg
|
|
||||||
}
|
|
||||||
case *ast.TypeSpec: // type define
|
|
||||||
switch xType := x.Type.(type) {
|
|
||||||
case *ast.StructType: // define struct
|
|
||||||
// parse the struct declaration.
|
|
||||||
var structName = pkg + "." + x.Name.Name
|
|
||||||
var structEmbeddedStruct []string
|
|
||||||
for _, field := range xType.Fields.List {
|
|
||||||
if len(field.Names) > 0 || field.Tag == nil { // not anonymous field
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
tagValue := strings.Trim(field.Tag.Value, "`")
|
|
||||||
tagValue = strings.TrimSpace(tagValue)
|
|
||||||
if len(tagValue) == 0 { // not set tag
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
tags := gstructs.ParseTag(tagValue)
|
|
||||||
|
|
||||||
if v, ok := tags["gen"]; !ok || v != "extend" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
var embeddedStruct string
|
|
||||||
switch v := field.Type.(type) {
|
|
||||||
case *ast.Ident:
|
|
||||||
if embeddedStruct, err = c.astExprToString(v); err != nil {
|
|
||||||
embeddedStruct = ""
|
|
||||||
break
|
|
||||||
}
|
|
||||||
embeddedStruct = pkg + "." + embeddedStruct
|
|
||||||
case *ast.StarExpr:
|
|
||||||
if embeddedStruct, err = c.astExprToString(v.X); err != nil {
|
|
||||||
embeddedStruct = ""
|
|
||||||
break
|
|
||||||
}
|
|
||||||
embeddedStruct = pkg + "." + embeddedStruct
|
|
||||||
case *ast.SelectorExpr:
|
|
||||||
var pkg string
|
|
||||||
if pkg, err = c.astExprToString(v.X); err != nil {
|
|
||||||
embeddedStruct = ""
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if v, ok := pkgAliasMap[pkg]; ok {
|
|
||||||
pkg = v
|
|
||||||
}
|
|
||||||
if embeddedStruct, err = c.astExprToString(v.Sel); err != nil {
|
|
||||||
embeddedStruct = ""
|
|
||||||
break
|
|
||||||
}
|
|
||||||
embeddedStruct = pkg + "." + embeddedStruct
|
|
||||||
}
|
|
||||||
|
|
||||||
if embeddedStruct == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
structEmbeddedStruct = append(structEmbeddedStruct, embeddedStruct)
|
|
||||||
|
|
||||||
}
|
|
||||||
if len(structEmbeddedStruct) > 0 {
|
|
||||||
structItems[structName] = structEmbeddedStruct
|
|
||||||
}
|
|
||||||
case *ast.Ident: // define ident
|
|
||||||
var (
|
|
||||||
structName = pkg + "." + x.Name.Name
|
|
||||||
typeName = pkg + "." + xType.Name
|
|
||||||
)
|
|
||||||
structItems[structName] = []string{typeName}
|
|
||||||
case *ast.SelectorExpr: // define selector
|
|
||||||
var (
|
|
||||||
structName = pkg + "." + x.Name.Name
|
|
||||||
selecotrPkg string
|
|
||||||
typeName string
|
|
||||||
)
|
|
||||||
if selecotrPkg, err = c.astExprToString(xType.X); err != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if v, ok := pkgAliasMap[selecotrPkg]; ok {
|
|
||||||
selecotrPkg = v
|
|
||||||
}
|
|
||||||
if typeName, err = c.astExprToString(xType.Sel); err != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
typeName = selecotrPkg + "." + typeName
|
|
||||||
structItems[structName] = []string{typeName}
|
|
||||||
}
|
|
||||||
|
|
||||||
case *ast.FuncDecl:
|
|
||||||
// parse the function items.
|
|
||||||
if x.Recv == nil {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
var funcName = x.Name.Name
|
|
||||||
funcItems = append(funcItems, funcItem{
|
|
||||||
Receiver: c.parseFuncReceiverTypeName(x),
|
|
||||||
MethodName: funcName,
|
|
||||||
Params: c.parseFuncParams(x),
|
|
||||||
Results: c.parseFuncResults(x),
|
|
||||||
Comment: c.parseFuncComment(x),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// parseImportPackages retrieves the imported packages from the specified ast.ImportSpec.
|
|
||||||
func (c CGenService) parseImportPackages(node *ast.ImportSpec) (packages pkgItem) {
|
|
||||||
if node.Path == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
var (
|
|
||||||
alias string
|
|
||||||
path = node.Path.Value
|
|
||||||
rawImport string
|
|
||||||
)
|
|
||||||
|
|
||||||
if node.Name != nil {
|
|
||||||
alias = node.Name.Name
|
|
||||||
rawImport = node.Name.Name + " " + path
|
|
||||||
} else {
|
|
||||||
rawImport = path
|
|
||||||
}
|
|
||||||
|
|
||||||
// if the alias is empty, it will further retrieve the real alias.
|
|
||||||
if alias == "" {
|
|
||||||
alias = c.getRealAlias(path)
|
|
||||||
}
|
|
||||||
|
|
||||||
return pkgItem{
|
|
||||||
Alias: alias,
|
|
||||||
Path: path,
|
|
||||||
RawImport: rawImport,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// getRealAlias retrieves the real alias of the package.
|
|
||||||
// If package is "github.com/gogf/gf", the alias is "gf".
|
|
||||||
// If package is "github.com/gogf/gf/v2", the alias is "gf" instead of "v2".
|
|
||||||
func (c CGenService) getRealAlias(importPath string) (pkgName string) {
|
|
||||||
importPath = gstr.Trim(importPath, `"`)
|
|
||||||
parts := gstr.Split(importPath, "/")
|
|
||||||
if len(parts) == 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
pkgName = parts[len(parts)-1]
|
|
||||||
|
|
||||||
if !gstr.HasPrefix(pkgName, "v") {
|
|
||||||
return pkgName
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(parts) < 2 {
|
|
||||||
return pkgName
|
|
||||||
}
|
|
||||||
|
|
||||||
if gstr.IsNumeric(gstr.SubStr(pkgName, 1)) {
|
|
||||||
pkgName = parts[len(parts)-2]
|
|
||||||
}
|
|
||||||
|
|
||||||
return pkgName
|
|
||||||
}
|
|
||||||
|
|
||||||
// parseFuncReceiverTypeName retrieves the receiver type of the function.
|
|
||||||
// For example:
|
|
||||||
//
|
|
||||||
// func(s *sArticle) -> *sArticle
|
|
||||||
// func(s sArticle) -> sArticle
|
|
||||||
func (c CGenService) parseFuncReceiverTypeName(node *ast.FuncDecl) (receiverType string) {
|
|
||||||
if node.Recv == nil {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
receiverType, err := c.astExprToString(node.Recv.List[0].Type)
|
|
||||||
if err != nil {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// parseFuncParams retrieves the input parameters of the function.
|
|
||||||
// It returns the name and type of the input parameters.
|
|
||||||
// For example:
|
|
||||||
//
|
|
||||||
// []map[string]string{paramName:ctx paramType:context.Context, paramName:info paramType:struct{}}
|
|
||||||
func (c CGenService) parseFuncParams(node *ast.FuncDecl) (params []map[string]string) {
|
|
||||||
if node.Type.Params == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
for _, param := range node.Type.Params.List {
|
|
||||||
if param.Names == nil {
|
|
||||||
// No name for the return value.
|
|
||||||
resultType, err := c.astExprToString(param.Type)
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
params = append(params, map[string]string{
|
|
||||||
"paramName": "",
|
|
||||||
"paramType": resultType,
|
|
||||||
})
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
for _, name := range param.Names {
|
|
||||||
paramType, err := c.astExprToString(param.Type)
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
params = append(params, map[string]string{
|
|
||||||
"paramName": name.Name,
|
|
||||||
"paramType": paramType,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// parseFuncResults retrieves the output parameters of the function.
|
|
||||||
// It returns the name and type of the output parameters.
|
|
||||||
// For example:
|
|
||||||
//
|
|
||||||
// []map[string]string{resultName:list resultType:[]*User, resultName:err resultType:error}
|
|
||||||
// []map[string]string{resultName: "", resultType: error}
|
|
||||||
func (c CGenService) parseFuncResults(node *ast.FuncDecl) (results []map[string]string) {
|
|
||||||
if node.Type.Results == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
for _, result := range node.Type.Results.List {
|
|
||||||
if result.Names == nil {
|
|
||||||
// No name for the return value.
|
|
||||||
resultType, err := c.astExprToString(result.Type)
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
results = append(results, map[string]string{
|
|
||||||
"resultName": "",
|
|
||||||
"resultType": resultType,
|
|
||||||
})
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
for _, name := range result.Names {
|
|
||||||
resultType, err := c.astExprToString(result.Type)
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
results = append(results, map[string]string{
|
|
||||||
"resultName": name.Name,
|
|
||||||
"resultType": resultType,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// parseFuncComment retrieves the comment of the function.
|
|
||||||
func (c CGenService) parseFuncComment(node *ast.FuncDecl) string {
|
|
||||||
return c.astCommentToString(node.Doc)
|
|
||||||
}
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user