mirror of
https://gitee.com/johng/gf
synced 2026-06-07 18:26:02 +08:00
Compare commits
339 Commits
v2.4.1
...
contrib/dr
| Author | SHA1 | Date | |
|---|---|---|---|
| b040654574 | |||
| 505fc25a64 | |||
| 83ba887df7 | |||
| 911f1cb1de | |||
| 1b7aea0ced | |||
| db5eed17b1 | |||
| 1ffb510a77 | |||
| f039393b2b | |||
| 00ba053ce6 | |||
| dcf1f19ff7 | |||
| 06826750ed | |||
| e0a2645f4a | |||
| 509fdf45c6 | |||
| 1e7d897b66 | |||
| 6df0a9ca66 | |||
| 1c12f3a30d | |||
| 3a9e0e34ca | |||
| 8669512f42 | |||
| 313d9d138f | |||
| 040118b7c6 | |||
| b3f48212f1 | |||
| cade0775e8 | |||
| 164aad48c3 | |||
| 04756d05a7 | |||
| 409041b965 | |||
| 11f7187367 | |||
| 4feda4c395 | |||
| a8713da97f | |||
| 199737cd0f | |||
| 3a8f246569 | |||
| 607f079b23 | |||
| cab6b89446 | |||
| 6ed3038312 | |||
| 9b48da459e | |||
| fbd266fad0 | |||
| 240dadff92 | |||
| 290f4a3e65 | |||
| 97fcd9d726 | |||
| df15d70466 | |||
| 680ae8616b | |||
| 4feb8219fa | |||
| 509cc47d3f | |||
| 849b104c31 | |||
| ce3ef13e6a | |||
| c8a73f8c25 | |||
| b71ee13ccd | |||
| a347cdc30e | |||
| 39a88ef650 | |||
| 8b156e25c4 | |||
| eb0c4b3824 | |||
| 56ef0c0735 | |||
| a1a9465e52 | |||
| d64a31fd1a | |||
| 6cdf044320 | |||
| 5307f0742e | |||
| 51326f3d02 | |||
| e1fa99013a | |||
| 72014689e4 | |||
| 2acdf4bb47 | |||
| 85c5b7f19e | |||
| 42ec1a0076 | |||
| 553cc45e54 | |||
| 7415ec32c8 | |||
| 14568562e3 | |||
| cc79d23334 | |||
| ef2b47d180 | |||
| adc056f547 | |||
| 8266a16b4e | |||
| c4a51f4c2f | |||
| 4ddc9c3909 | |||
| 0a2f8abb40 | |||
| 81de5d3f25 | |||
| e6d61e6e14 | |||
| 4fb739615b | |||
| ba39323d30 | |||
| 383937fe69 | |||
| f919f90bf5 | |||
| b4f6f06ab5 | |||
| 73fbca40ca | |||
| e8d3fcac6b | |||
| f87182d5b8 | |||
| 951f8921cd | |||
| d26b7c5437 | |||
| 9407fda197 | |||
| 905913f7be | |||
| 4b8eaac73f | |||
| ca242ff401 | |||
| 42e3c5f39a | |||
| 4f4d2c2f8e | |||
| 5a01798481 | |||
| 8af1eb693e | |||
| 335ccb32af | |||
| e1f2666499 | |||
| 22fcfdf755 | |||
| 1e21b61a19 | |||
| 6abd8bd864 | |||
| 4876ae0e2b | |||
| 63bdf41d40 | |||
| 984cca8b82 | |||
| 9f7ce42c74 | |||
| 16a43bcb6c | |||
| 85d95e3e27 | |||
| 4cce8557e6 | |||
| d60d7674d7 | |||
| 7f9467d1f8 | |||
| d08e3ef838 | |||
| 645c5ff5b5 | |||
| 7975e391f0 | |||
| 565790036e | |||
| 44819b135e | |||
| bb19877430 | |||
| fc02e06423 | |||
| dd8a5dcf32 | |||
| 33584506ab | |||
| ee2cf92479 | |||
| 0b6dd6fb13 | |||
| 993467bb3c | |||
| c7c9f0011a | |||
| 9aa872e705 | |||
| ea5d52cb2f | |||
| b1754f8254 | |||
| 83f08b3135 | |||
| d3d1f94e40 | |||
| fc8572e8dd | |||
| 85acd3d31d | |||
| 9694a68211 | |||
| 0be8b29e42 | |||
| 5580ac9475 | |||
| 84ed66018e | |||
| 4d7f9552fe | |||
| d4b14fd717 | |||
| 0bd15bdab5 | |||
| 0b407c5e6d | |||
| 5f5b82188c | |||
| a17849bc39 | |||
| f3e3a5af5a | |||
| dc71c0d28f | |||
| eb99f5ebfe | |||
| 007fe0ea1a | |||
| 50b04c658c | |||
| cbea89e6f7 | |||
| e2e12fadb0 | |||
| 47eaa513c0 | |||
| 3bbc0fdd21 | |||
| 9393072745 | |||
| e42aa64d75 | |||
| b6935a7285 | |||
| b0367e4a62 | |||
| 0b71bc43a8 | |||
| afeca8cf9d | |||
| 33c396fb74 | |||
| 4903ef7887 | |||
| ab5ab4c675 | |||
| 3ea61d084e | |||
| 2433b2ce99 | |||
| 927758a2a9 | |||
| cb0d018fa4 | |||
| 49f69f6ade | |||
| bcb479aabb | |||
| db59f4232f | |||
| aa625d24bc | |||
| 36cfbaaa22 | |||
| f8462b5218 | |||
| b2bd12a371 | |||
| acf2307eb9 | |||
| 93964ee231 | |||
| 943939ba2b | |||
| f1b5a223bf | |||
| bb9cd37fab | |||
| 972f8c3aff | |||
| 34e522306d | |||
| 7c92c2f7e8 | |||
| 5204bdb60d | |||
| 6ab8d065d1 | |||
| d4e686226b | |||
| 19d7714503 | |||
| f464f30e6f | |||
| 0e7d7d1eee | |||
| 6af66a0201 | |||
| 81f3ad043d | |||
| ca7450f595 | |||
| 65192a7f92 | |||
| 8c309ac9fe | |||
| 7f1ce2aff3 | |||
| 10b67fc7b0 | |||
| 3cd005911d | |||
| d10d96800f | |||
| 35e5f1f204 | |||
| 1efdb72990 | |||
| 8d925d4741 | |||
| d6362cad16 | |||
| 00e83fed3f | |||
| 02f1cc7b40 | |||
| 32a60c2e96 | |||
| 30040332a7 | |||
| 569cbb09bf | |||
| 130191f4ed | |||
| e6732039c6 | |||
| df92c483d0 | |||
| 7c9eefef3d | |||
| 42de1c1dbe | |||
| 395df940d7 | |||
| ef1e18df19 | |||
| e684eae878 | |||
| 5219c5c37e | |||
| 5059abd88e | |||
| e2ed058e3b | |||
| ccc959a2d3 | |||
| a5a7d23792 | |||
| 5bc9acdab3 | |||
| ab1970e7d6 | |||
| 1582714325 | |||
| 7391a4d45a | |||
| 7e16d9b63e | |||
| d49dccb147 | |||
| 6cddfdb313 | |||
| 912316d765 | |||
| b9e2b05f04 | |||
| 887803e495 | |||
| eb11061bd2 | |||
| 000c7a92ed | |||
| 097b26f318 | |||
| 3da5e5e865 | |||
| e60262fec9 | |||
| 74bf1b4bc3 | |||
| 3f69e0db36 | |||
| 7d4c59ac5a | |||
| 3841f05e02 | |||
| bcd409ab1c | |||
| 4dd43aa018 | |||
| aed695313a | |||
| cf299273c4 | |||
| 53323f3cf9 | |||
| 24ee5341ec | |||
| ed4d1554ab | |||
| ac3481ed43 | |||
| 3df5969348 | |||
| ea6a773d60 | |||
| 35a326e169 | |||
| 4020eb9b4c | |||
| 243fe73c57 | |||
| 932f8c48ef | |||
| 7c1be3eb63 | |||
| 5de2cfbfa1 | |||
| b593c00d97 | |||
| 7798e96190 | |||
| 55ac18d90a | |||
| a409db5540 | |||
| dd5d56674e | |||
| 79617570ca | |||
| a4e7cc4700 | |||
| 2fbe4125dd | |||
| 47915816b5 | |||
| 0f53660453 | |||
| f3437dc00f | |||
| 574d63b4fd | |||
| 53e5a04073 | |||
| c51785125e | |||
| 5230f8304e | |||
| e0e00434cc | |||
| b95cb3180d | |||
| dec66dbd05 | |||
| cb44c40a9c | |||
| 2c22f4e17d | |||
| 83fa3593b1 | |||
| 4ad508c04d | |||
| 0d52386236 | |||
| 16a5318d32 | |||
| b1da02dff6 | |||
| b99db92113 | |||
| c0dff1dc16 | |||
| ef6ef506d6 | |||
| b71ac868b7 | |||
| d72997da04 | |||
| 41c0dde9bf | |||
| 498b72f75a | |||
| 5e231f3d61 | |||
| a2fec50500 | |||
| 6d7edb1479 | |||
| ce72f9a84b | |||
| 4fc24e1391 | |||
| 160bddecd3 | |||
| 39810a520c | |||
| 0dc47609b5 | |||
| 8fb4636cb4 | |||
| 30cf3dbbe6 | |||
| c90e9311e3 | |||
| ba2a7e4417 | |||
| 740dfa58a6 | |||
| 9620b15ea1 | |||
| 3fab7a341d | |||
| 5804547bc5 | |||
| 70d0d20750 | |||
| 92e21c275c | |||
| 8aff08581f | |||
| 6eb0de42f8 | |||
| 8c4a0b61b8 | |||
| 22696566d6 | |||
| c5c2938380 | |||
| d6433de4a6 | |||
| 15eaac35a8 | |||
| 46f3196297 | |||
| 842e5a6774 | |||
| 2ece368810 | |||
| 1bbfc56121 | |||
| 835b252b5d | |||
| 9bc9fc4545 | |||
| 8cc5338870 | |||
| 9191003391 | |||
| 99236fd93b | |||
| b34d560bb7 | |||
| 7bb4ddcfd5 | |||
| 00190abad8 | |||
| aa8eabd853 | |||
| 4914517f6b | |||
| 0865dbbf75 | |||
| d3a3ad0228 | |||
| e075432c40 | |||
| e816ab05de | |||
| a4762d0e02 | |||
| 2329622564 | |||
| 368312c816 | |||
| f6dbe1a40c | |||
| 032d085619 | |||
| a6fff37be8 | |||
| 879283685d | |||
| 0f4f2a6672 | |||
| ff6f5ce237 | |||
| dc0467e934 | |||
| f0d22fe570 | |||
| 05ee4d489a | |||
| 3c1ded22fd | |||
| bda5d252b2 | |||
| 0c3e66d6a0 | |||
| f31bf76f94 | |||
| 0afedee49d | |||
| 43d439a1cd | |||
| b8aeb4f0ee | |||
| 1408385612 |
2
.codecov.yml
Normal file
2
.codecov.yml
Normal file
@ -0,0 +1,2 @@
|
||||
ignore:
|
||||
- "cmd" # ignore cmd folders and all its contents
|
||||
38
.github/ISSUE_TEMPLATE.MD
vendored
38
.github/ISSUE_TEMPLATE.MD
vendored
@ -1,38 +0,0 @@
|
||||
<!-- 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?
|
||||
|
||||
|
||||
|
||||
41
.github/ISSUE_TEMPLATE/bug-report.md
vendored
Normal file
41
.github/ISSUE_TEMPLATE/bug-report.md
vendored
Normal file
@ -0,0 +1,41 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: ''
|
||||
labels: bug
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
<!-- Please answer these questions before submitting your issue. Thanks! -->
|
||||
|
||||
<!-- 为高效处理 Bug,请您务必提供可复现该问题的最小可运行代码!否则 issue 可能会被延期处理! -->
|
||||
<!-- 为高效处理 Bug,请您务必提供可复现该问题的最小可运行代码!否则 issue 可能会被延期处理! -->
|
||||
<!-- 为高效处理 Bug,如请您务必提供可复现该问题的最小可运行代码!否则 issue 可能会被延期处理! -->
|
||||
<!-- 重要的事情说三遍! -->
|
||||
|
||||
**What version of `Go` and system type/arch are you using?**
|
||||
<!--
|
||||
Please paste the output of command `go version` from your terminal.
|
||||
What expects to see is like: `go 1.12, linux/amd64`
|
||||
-->
|
||||
|
||||
|
||||
**What version of `GoFrame` are you using?**
|
||||
<!-- You can find the GF version from your `go.mod`, or from the `version.go` in `GF` -->
|
||||
|
||||
|
||||
**Can this bug be re-produced with the latest release?**
|
||||
|
||||
|
||||
**What did you do?**
|
||||
<!--
|
||||
If possible, provide a copy of shortest codes for reproducing the error.
|
||||
A complete runnable program is best.
|
||||
-->
|
||||
|
||||
|
||||
**What did you expect to see?**
|
||||
|
||||
|
||||
**What did you see instead?**
|
||||
16
.github/ISSUE_TEMPLATE/enhancement-request.md
vendored
Normal file
16
.github/ISSUE_TEMPLATE/enhancement-request.md
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
---
|
||||
name: Enhancement request
|
||||
about: Enhance an idea for this project
|
||||
title: ''
|
||||
labels: enhancement
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Package that You wish to enhance**
|
||||
|
||||
|
||||
**Enhancement description**
|
||||
|
||||
|
||||
**Additional**
|
||||
19
.github/ISSUE_TEMPLATE/feature-request.md
vendored
Normal file
19
.github/ISSUE_TEMPLATE/feature-request.md
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: ''
|
||||
labels: feature
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
|
||||
|
||||
**Describe the solution you'd like**
|
||||
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
|
||||
|
||||
**Additional**
|
||||
11
.github/ISSUE_TEMPLATE/question.md
vendored
Normal file
11
.github/ISSUE_TEMPLATE/question.md
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
---
|
||||
name: Question
|
||||
about: I want to ask a question
|
||||
title: ''
|
||||
labels: question
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
<!-- 请优先仔细阅读文档 -->
|
||||
**What do you want to ask**
|
||||
BIN
.github/logo.png
vendored
Normal file
BIN
.github/logo.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 232 KiB |
49
.github/workflows/build_and_test.sh
vendored
49
.github/workflows/build_and_test.sh
vendored
@ -1,49 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
for file in `find . -name go.mod`; do
|
||||
dirpath=$(dirname $file)
|
||||
echo $dirpath
|
||||
|
||||
# package oracle needs golang >= v1.17
|
||||
if [ "oracle" = $(basename $dirpath) ]; then
|
||||
if ! go version|grep -q "1.17"; then
|
||||
echo "ignore oracle as go version: $(go version)"
|
||||
continue 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# package kuhecm needs golang >= v1.18
|
||||
if [ "kubecm" = $(basename $dirpath) ]; then
|
||||
if ! go version|grep -q "1.18"; then
|
||||
echo "ignore kubecm as go version: $(go version)"
|
||||
continue 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# package example needs golang >= v1.18
|
||||
if [ "example" = $(basename $dirpath) ]; then
|
||||
if ! go version|grep -q "1.18"; then
|
||||
echo "ignore example as go version: $(go version)"
|
||||
continue 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# package cmd/gf needs golang >= v1.18
|
||||
if [ "gf" = $(basename $dirpath) ]; then
|
||||
if ! go version|grep -q "1.18"; then
|
||||
echo "ignore example as go version: $(go version)"
|
||||
continue 1
|
||||
fi
|
||||
fi
|
||||
|
||||
cd $dirpath
|
||||
go mod tidy
|
||||
go build ./...
|
||||
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
|
||||
|
||||
cd -
|
||||
done
|
||||
96
.github/workflows/ci-main.sh
vendored
Normal file
96
.github/workflows/ci-main.sh
vendored
Normal file
@ -0,0 +1,96 @@
|
||||
#!/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
|
||||
|
||||
# package otelmetric needs golang >= v1.20
|
||||
if [ "otelmetric" = $(basename $dirpath) ]; then
|
||||
if ! go version|grep -qE "go1.[2-9][0-9]"; then
|
||||
echo "ignore otelmetric 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
|
||||
@ -1,3 +1,4 @@
|
||||
# The main codes build and unit testing running workflow.
|
||||
name: GoFrame Main CI
|
||||
|
||||
|
||||
@ -65,10 +66,23 @@ jobs:
|
||||
ports:
|
||||
- 3306:3306
|
||||
|
||||
# MariaDb backend server.
|
||||
mariadb:
|
||||
image: loads/mariadb:10.4
|
||||
env:
|
||||
MARIADB_DATABASE: test
|
||||
MARIADB_ROOT_PASSWORD: 12345678
|
||||
ports:
|
||||
- 3307:3306
|
||||
|
||||
# PostgreSQL backend server.
|
||||
# docker run -d --name postgres -p 5432:5432 \
|
||||
# -e POSTGRES_PASSWORD=12345678 -e POSTGRES_USER=postgres -e POSTGRES_DB=test \
|
||||
# -v postgres:/Users/john/Temp/postgresql/data loads/postgres:13
|
||||
# docker run -d --name postgres \
|
||||
# -p 5432:5432 \
|
||||
# -e POSTGRES_PASSWORD=12345678 \
|
||||
# -e POSTGRES_USER=postgres \
|
||||
# -e POSTGRES_DB=test \
|
||||
# -v postgres:/Users/john/Temp/postgresql/data \
|
||||
# loads/postgres:13
|
||||
postgres:
|
||||
image: loads/postgres:13
|
||||
env:
|
||||
@ -86,7 +100,8 @@ jobs:
|
||||
--health-retries 5
|
||||
|
||||
# MSSQL backend server.
|
||||
# docker run -d --name mssql -p 1433:1433 \
|
||||
# docker run \
|
||||
# -p 1433:1433 \
|
||||
# -e ACCEPT_EULA=Y \
|
||||
# -e SA_PASSWORD=LoremIpsum86 \
|
||||
# -e MSSQL_DB=test \
|
||||
@ -111,7 +126,9 @@ jobs:
|
||||
--health-retries 10
|
||||
|
||||
# ClickHouse backend server.
|
||||
# docker run -d --name clickhouse -p 9000:9000 -p 8123:8123 -p 9001:9001 loads/clickhouse-server:22.1.3.7
|
||||
# docker run -d --name clickhouse \
|
||||
# -p 9000:9000 -p 8123:8123 -p 9001:9001 \
|
||||
# loads/clickhouse-server:22.1.3.7
|
||||
clickhouse-server:
|
||||
image: loads/clickhouse-server:22.1.3.7
|
||||
ports:
|
||||
@ -120,10 +137,15 @@ jobs:
|
||||
- 9001:9001
|
||||
|
||||
# Polaris backend server.
|
||||
# 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
|
||||
# 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
|
||||
# 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
|
||||
#
|
||||
# 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
|
||||
polaris:
|
||||
image: loads/polaris-standalone:v1.16.4
|
||||
image: loads/polaris-standalone:v1.17.2
|
||||
ports:
|
||||
- 8090:8090
|
||||
- 8091:8091
|
||||
@ -131,7 +153,14 @@ jobs:
|
||||
- 9090:9090
|
||||
- 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:
|
||||
image: loads/oracle-xe-11g-r2:11.2.0
|
||||
env:
|
||||
@ -143,7 +172,7 @@ jobs:
|
||||
- 1521:1521
|
||||
|
||||
# dm8 server
|
||||
# docker run -d --name dm -p 5236:5236 loads/dm:v8.1.2.128_ent_x86_64_ctm_pack4
|
||||
# docker run -p 5236:5236 loads/dm:v8.1.2.128_ent_x86_64_ctm_pack4
|
||||
dm-server:
|
||||
image: loads/dm:v8.1.2.128_ent_x86_64_ctm_pack4
|
||||
ports:
|
||||
@ -156,7 +185,7 @@ jobs:
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
go-version: [ "1.15", "1.16", "1.17", "1.18" ]
|
||||
go-version: [ "1.18", "1.19", "1.20", "1.21", "1.22" ]
|
||||
goarch: [ "386", "amd64" ]
|
||||
|
||||
steps:
|
||||
@ -167,44 +196,51 @@ jobs:
|
||||
timezoneLinux: "Asia/Shanghai"
|
||||
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- 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
|
||||
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
|
||||
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 Minikube
|
||||
uses: medyagh/setup-minikube@master
|
||||
- name: Start Consul Containers
|
||||
run: docker compose -f ".github/workflows/consul/docker-compose.yml" up -d --build
|
||||
|
||||
- name: Setup Golang ${{ matrix.go-version }}
|
||||
uses: actions/setup-go@v3
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: ${{ matrix.go-version }}
|
||||
cache: true
|
||||
cache-dependency-path: '**/go.sum'
|
||||
cache-dependency-path: '**/go.sum'
|
||||
|
||||
- name: Before Script
|
||||
run: bash .github/workflows/before_script.sh
|
||||
|
||||
- name: Build & Test
|
||||
run: bash .github/workflows/build_and_test.sh
|
||||
if: ${{ (github.event_name == 'push' && github.ref != 'refs/heads/master') || github.event_name == 'pull_request' }}
|
||||
run: bash .github/workflows/ci-main.sh
|
||||
|
||||
- name: Build & Test & Coverage
|
||||
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }}
|
||||
run: bash .github/workflows/ci-main.sh coverage
|
||||
|
||||
- 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
|
||||
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
|
||||
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
|
||||
run: docker compose -f ".github/workflows/consul/docker-compose.yml" down
|
||||
|
||||
- name: Report Coverage
|
||||
uses: codecov/codecov-action@v3
|
||||
uses: codecov/codecov-action@v4
|
||||
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }}
|
||||
with:
|
||||
flags: go-${{ matrix.go-version }}-${{ matrix.goarch }}
|
||||
|
||||
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
|
||||
67
.github/workflows/ci-sub.yml
vendored
Normal file
67
.github/workflows/ci-sub.yml
vendored
Normal file
@ -0,0 +1,67 @@
|
||||
# The sub codes build and unit testing running workflow.
|
||||
# It maintains the ci of unimportant packages.
|
||||
name: GoFrame Sub CI
|
||||
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- develop
|
||||
- personal/**
|
||||
- feature/**
|
||||
- enhance/**
|
||||
- fix/**
|
||||
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
- develop
|
||||
- personal/**
|
||||
- feature/**
|
||||
- enhance/**
|
||||
- fix/**
|
||||
|
||||
# This allows a subsequently queued workflow run to interrupt previous runs
|
||||
concurrency:
|
||||
group: '${{ github.workflow }} @ ${{ github.event.pull_request.head.label || github.head_ref || github.ref }}'
|
||||
cancel-in-progress: true
|
||||
|
||||
env:
|
||||
TZ: "Asia/Shanghai"
|
||||
|
||||
|
||||
jobs:
|
||||
code-test:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
go-version: [ "1.18", "1.19", "1.20", "1.22" ]
|
||||
goarch: [ "386", "amd64" ]
|
||||
|
||||
steps:
|
||||
- name: Setup Timezone
|
||||
uses: szenius/set-timezone@v1.1
|
||||
with:
|
||||
timezoneLinux: "Asia/Shanghai"
|
||||
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Start Minikube
|
||||
uses: medyagh/setup-minikube@master
|
||||
|
||||
- name: Setup Golang ${{ matrix.go-version }}
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: ${{ matrix.go-version }}
|
||||
cache-dependency-path: '**/go.sum'
|
||||
|
||||
- name: Before Script
|
||||
run: bash .github/workflows/before_script.sh
|
||||
|
||||
- name: Build & Test
|
||||
run: bash .github/workflows/ci-sub.sh
|
||||
|
||||
|
||||
7
.github/workflows/consul/client.json
vendored
Normal file
7
.github/workflows/consul/client.json
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"node_name": "consul-client",
|
||||
"data_dir": "/consul/data",
|
||||
"retry_join":[
|
||||
"consul-server"
|
||||
]
|
||||
}
|
||||
31
.github/workflows/consul/docker-compose.yml
vendored
Normal file
31
.github/workflows/consul/docker-compose.yml
vendored
Normal file
@ -0,0 +1,31 @@
|
||||
version: '3.7'
|
||||
|
||||
services:
|
||||
|
||||
consul-server:
|
||||
image: loads/consul:1.15
|
||||
container_name: consul-server
|
||||
restart: always
|
||||
volumes:
|
||||
- ./server.json:/consul/config/server.json:ro
|
||||
networks:
|
||||
- consul
|
||||
ports:
|
||||
- "8500:8500"
|
||||
- "8600:8600/tcp"
|
||||
- "8600:8600/udp"
|
||||
command: "agent"
|
||||
|
||||
consul-client:
|
||||
image: loads/consul:1.15
|
||||
container_name: consul-client
|
||||
restart: always
|
||||
volumes:
|
||||
- ./client.json:/consul/config/client.json:ro
|
||||
networks:
|
||||
- consul
|
||||
command: "agent"
|
||||
|
||||
networks:
|
||||
consul:
|
||||
driver: bridge
|
||||
12
.github/workflows/consul/server.json
vendored
Normal file
12
.github/workflows/consul/server.json
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"node_name": "consul-server",
|
||||
"server": true,
|
||||
"bootstrap" : true,
|
||||
"ui_config": {
|
||||
"enabled" : true
|
||||
},
|
||||
"data_dir": "/consul/data",
|
||||
"addresses": {
|
||||
"http" : "0.0.0.0"
|
||||
}
|
||||
}
|
||||
38
.github/workflows/doc-build.yml
vendored
Normal file
38
.github/workflows/doc-build.yml
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
name: Deploy to GitHub Pages
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- 'doc-build'
|
||||
schedule:
|
||||
- cron: '0 15 * * *'
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
name: Deploy to GitHub Pages
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
ref: doc-build
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18
|
||||
cache: npm
|
||||
- name: Set Up Golang Environment
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: 1.20.4
|
||||
cache: false
|
||||
- name: download goframe docs
|
||||
run: ./download.sh
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
- name: Build website
|
||||
run: npm run build
|
||||
- name: Deploy to GitHub Pages
|
||||
uses: peaceiris/actions-gh-pages@v3
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
publish_dir: ./build
|
||||
cname: pages.goframe.org
|
||||
28
.github/workflows/gitee-sync.yml
vendored
Normal file
28
.github/workflows/gitee-sync.yml
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
tags:
|
||||
- "*"
|
||||
|
||||
name: Sync to Gitee
|
||||
jobs:
|
||||
run:
|
||||
name: Run
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout source code
|
||||
uses: actions/checkout@v4
|
||||
- name: Mirror GitHub to Gitee
|
||||
uses: Yikun/hub-mirror-action@v1.3
|
||||
with:
|
||||
src: github/gogf
|
||||
dst: gitee/johng
|
||||
dst_key: ${{ secrets.GITEE_PRIVATE_KEY }}
|
||||
dst_token: ${{ secrets.GITEE_TOKEN }}
|
||||
src_account_type: org
|
||||
dst_account_type: user
|
||||
timeout: 600
|
||||
debug: true
|
||||
force_update: true
|
||||
static_list: "gf"
|
||||
38
.github/workflows/golangci-lint.yml
vendored
38
.github/workflows/golangci-lint.yml
vendored
@ -17,34 +17,38 @@ name: GolangCI-Lint
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- develop
|
||||
- personal/**
|
||||
- feature/**
|
||||
- enhance/**
|
||||
- fix/**
|
||||
- master
|
||||
- develop
|
||||
- personal/**
|
||||
- feature/**
|
||||
- enhance/**
|
||||
- fix/**
|
||||
pull_request:
|
||||
branches:
|
||||
- master
|
||||
- develop
|
||||
- personal/**
|
||||
- feature/**
|
||||
- enhance/**
|
||||
- fix/**
|
||||
- master
|
||||
- develop
|
||||
- personal/**
|
||||
- feature/**
|
||||
- enhance/**
|
||||
- fix/**
|
||||
|
||||
jobs:
|
||||
golangci:
|
||||
strategy:
|
||||
matrix:
|
||||
go-version: [1.15.x,1.16.x,1.17.x,1.18.x]
|
||||
go-version: [ '1.18','1.19','1.20','1.21.4','1.22' ]
|
||||
name: golangci-lint
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/setup-go@v3
|
||||
- uses: actions/checkout@v3
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
- name: Setup Golang ${{ matrix.go-version }}
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: ${{ matrix.go-version }}
|
||||
- name: golangci-lint
|
||||
uses: golangci/golangci-lint-action@v3.3.0
|
||||
uses: golangci/golangci-lint-action@v4
|
||||
with:
|
||||
# Required: the version of golangci-lint is required and must be specified without patch version: we always use the latest patch version.
|
||||
version: latest
|
||||
version: v1.56.2
|
||||
args: --timeout 3m0s
|
||||
|
||||
4
.github/workflows/issue-check-inactive.yml
vendored
4
.github/workflows/issue-check-inactive.yml
vendored
@ -14,8 +14,8 @@ permissions:
|
||||
jobs:
|
||||
issue-check-inactive:
|
||||
permissions:
|
||||
issues: write # for actions-cool/issues-helper to update issues
|
||||
# pull-requests: write # for actions-cool/issues-helper to update PRs
|
||||
issues: write # for actions-cool/issues-helper to update issues
|
||||
# pull-requests: write # for actions-cool/issues-helper to update PRs
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: check-inactive
|
||||
|
||||
2
.github/workflows/issue-close-inactive.yml
vendored
2
.github/workflows/issue-close-inactive.yml
vendored
@ -1,4 +1,4 @@
|
||||
# 规则描述:每天凌晨4点(GMT+8)执行一次,将最近30天没有活跃且非BUG的ISSUE关闭
|
||||
# 规则描述:每天凌晨 4 点 (GMT+8) 执行一次,将最近 30 天没有活跃且非 BUG 的 ISSUE 关闭
|
||||
name: Issue Close Inactive
|
||||
|
||||
on:
|
||||
|
||||
2
.github/workflows/issue-labeled.yml
vendored
2
.github/workflows/issue-labeled.yml
vendored
@ -1,4 +1,4 @@
|
||||
## 规则描述:当issue被标记为help wanted 时,增加评论
|
||||
## 规则描述:当 issue 被标记为 help wanted 时,增加评论
|
||||
|
||||
name: Issue Labeled
|
||||
|
||||
|
||||
8
.github/workflows/issue-remove-inactive.yml
vendored
8
.github/workflows/issue-remove-inactive.yml
vendored
@ -1,4 +1,4 @@
|
||||
# 规则描述:在issue没有活跃且尚未被关闭期间,若issue作者更新或评论该ISSUE,则移除其inactive标签
|
||||
# 规则描述:在 issue 没有活跃且尚未被关闭期间,若 issue 作者更新或评论该 ISSUE,则移除其 inactive 标签
|
||||
name: Issue Remove Inactive
|
||||
|
||||
on:
|
||||
@ -17,13 +17,13 @@ jobs:
|
||||
issue-remove-inactive:
|
||||
permissions:
|
||||
issues: write # for actions-cool/issues-helper to update issues
|
||||
# pull-requests: write # for actions-cool/issues-helper to update PRs
|
||||
# pull-requests: write # for actions-cool/issues-helper to update PRs
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: remove inactive
|
||||
if: github.event.issue.state == 'open' && github.actor == github.event.issue.user.login
|
||||
if: github.event.issue.state == 'open'
|
||||
uses: actions-cool/issues-helper@v3
|
||||
with:
|
||||
actions: 'remove-labels'
|
||||
issue-number: ${{ github.event.issue.number }}
|
||||
labels: 'inactive'
|
||||
labels: 'inactive'
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
# 规则描述:将需要提供更多细节且暂未关闭的issue,在issue作者评论后,移除 need more details 标签
|
||||
# 规则描述:将需要提供更多细节且暂未关闭的 issue,在 issue 作者评论后,移除 need more details 标签
|
||||
name: Issue Remove Need More Details
|
||||
|
||||
on:
|
||||
@ -16,8 +16,8 @@ permissions:
|
||||
jobs:
|
||||
issue-remove-need-more-details:
|
||||
permissions:
|
||||
issues: write # for actions-cool/issues-helper to update issues
|
||||
# pull-requests: write # for actions-cool/issues-helper to update PRs
|
||||
issues: write # for actions-cool/issues-helper to update issues
|
||||
# pull-requests: write # for actions-cool/issues-helper to update PRs
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: remove need more details
|
||||
|
||||
16
.github/workflows/nacos/docker-compose.yml
vendored
16
.github/workflows/nacos/docker-compose.yml
vendored
@ -15,22 +15,6 @@ services:
|
||||
interval: 5s
|
||||
timeout: 3s
|
||||
retries: 10
|
||||
depends_on:
|
||||
mysql:
|
||||
condition: service_healthy
|
||||
|
||||
mysql:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: ./image/mysql/Dockerfile
|
||||
container_name: mysql
|
||||
env_file:
|
||||
- ./env/mysql.env
|
||||
healthcheck:
|
||||
test: [ "CMD", "mysqladmin" ,"ping", "-h", "localhost" ]
|
||||
interval: 5s
|
||||
timeout: 3s
|
||||
retries: 10
|
||||
|
||||
initializer:
|
||||
image: loads/curl:latest
|
||||
|
||||
4
.github/workflows/nacos/env/mysql.env
vendored
4
.github/workflows/nacos/env/mysql.env
vendored
@ -1,4 +0,0 @@
|
||||
MYSQL_ROOT_PASSWORD=root
|
||||
MYSQL_DATABASE=nacos_devtest
|
||||
MYSQL_USER=nacos
|
||||
MYSQL_PASSWORD=nacos
|
||||
7
.github/workflows/nacos/env/nacos.env
vendored
7
.github/workflows/nacos/env/nacos.env
vendored
@ -1,9 +1,2 @@
|
||||
PREFER_HOST_MODE=hostname
|
||||
MODE=standalone
|
||||
SPRING_DATASOURCE_PLATFORM=mysql
|
||||
MYSQL_SERVICE_HOST=mysql
|
||||
MYSQL_SERVICE_DB_NAME=nacos_devtest
|
||||
MYSQL_SERVICE_PORT=3306
|
||||
MYSQL_SERVICE_USER=nacos
|
||||
MYSQL_SERVICE_PASSWORD=nacos
|
||||
MYSQL_SERVICE_DB_PARAM=characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useSSL=false&allowPublicKeyRetrieval=true
|
||||
@ -1,5 +0,0 @@
|
||||
FROM loads/mysql:5.7
|
||||
ADD https://raw.githubusercontent.com/alibaba/nacos/develop/distribution/conf/mysql-schema.sql /docker-entrypoint-initdb.d/nacos-mysql.sql
|
||||
RUN chown -R mysql:mysql /docker-entrypoint-initdb.d/nacos-mysql.sql
|
||||
EXPOSE 3306
|
||||
CMD ["mysqld", "--character-set-server=utf8mb4", "--collation-server=utf8mb4_unicode_ci"]
|
||||
@ -1,4 +1,4 @@
|
||||
name: GoFrame CLI Build Release
|
||||
name: GoFrame Release
|
||||
|
||||
on:
|
||||
push:
|
||||
@ -16,12 +16,12 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout Github Code
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set Up Golang Environment
|
||||
uses: actions/setup-go@v4
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: 1.20.3
|
||||
go-version: 1.20.8
|
||||
|
||||
- name: Build CLI Binary
|
||||
run: |
|
||||
@ -34,7 +34,7 @@ jobs:
|
||||
- name: Build CLI Binary For All Platform
|
||||
run: |
|
||||
cd cmd/gf
|
||||
gf build main.go -n gf -a all -s all
|
||||
gf build main.go -n gf -a all -s all -p temp
|
||||
|
||||
- name: Move Files Before Release
|
||||
run: |
|
||||
11
.github/workflows/tag.yml
vendored
11
.github/workflows/tag.yml
vendored
@ -17,14 +17,23 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout Github Code
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Auto Creating Tags For Contrib Packages
|
||||
run: |
|
||||
git config --global user.email "tagrobot@goframe.org"
|
||||
git config --global user.name "TagRobot"
|
||||
|
||||
# auto create tags for contrib packages.
|
||||
for file in `find contrib -name go.mod`; do
|
||||
tag=$(dirname $file)/$GITHUB_REF_NAME
|
||||
git tag $tag
|
||||
git push origin $tag
|
||||
done
|
||||
|
||||
# auto create tag for cli tool
|
||||
for file in `find cmd -name go.mod`; do
|
||||
tag=$(dirname $file)/$GITHUB_REF_NAME
|
||||
git tag $tag
|
||||
git push origin $tag
|
||||
done
|
||||
|
||||
8
.gitignore
vendored
8
.gitignore
vendored
@ -13,6 +13,12 @@ bin/
|
||||
.test/
|
||||
cmd/gf/main
|
||||
cmd/gf/gf
|
||||
temp/
|
||||
go.work
|
||||
go.work.sum
|
||||
temp/
|
||||
!cmd/gf/go.work
|
||||
|
||||
# Ignore for docs
|
||||
node_modules
|
||||
.docusaurus
|
||||
output
|
||||
|
||||
@ -262,7 +262,7 @@ linters-settings:
|
||||
# Select the Go version to target.
|
||||
# Default: "1.13"
|
||||
# Deprecated: use the global `run.go` instead.
|
||||
go: "1.15"
|
||||
go: "1.20"
|
||||
# SAxxxx checks in https://staticcheck.io/docs/configuration/options/#checks
|
||||
# Default: ["*"]
|
||||
checks: [ "all","-SA1019","-SA4015","-SA1029","-SA1016","-SA9003","-SA4006","-SA6003" ]
|
||||
|
||||
82
.set_version.sh
Executable file
82
.set_version.sh
Executable file
@ -0,0 +1,82 @@
|
||||
#!/usr/bin/env bash
|
||||
if [ $# -ne 2 ]; then
|
||||
echo "Parameter exception, please execute in the format of $0 [directory] [version number]"
|
||||
echo "PS:$0 ./ v2.4.0"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -d "$1" ]; then
|
||||
echo "Error: Directory does not exist"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ "$2" != v* ]]; then
|
||||
echo "Error: Version number must start with v"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
workdir=.
|
||||
newVersion=$2
|
||||
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
|
||||
echo "package gf" > version.go
|
||||
echo "" >> version.go
|
||||
echo "const (" >> version.go
|
||||
echo -e "\t// VERSION is the current GoFrame version." >> version.go
|
||||
echo -e "\tVERSION = \"${newVersion}\"" >> version.go
|
||||
echo ")" >> version.go
|
||||
fi
|
||||
|
||||
if [ -f "go.work" ]; then
|
||||
mv go.work go.work.version.bak
|
||||
echo "Back up the 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
|
||||
if [ $goModPath = "./cmd/gf" ]; then
|
||||
mv go.work go.work.version.bak
|
||||
go mod edit -replace github.com/gogf/gf/v2=../../
|
||||
go mod edit -replace github.com/gogf/gf/contrib/drivers/clickhouse/v2=../../contrib/drivers/clickhouse
|
||||
go mod edit -replace github.com/gogf/gf/contrib/drivers/mssql/v2=../../contrib/drivers/mssql
|
||||
go mod edit -replace github.com/gogf/gf/contrib/drivers/mysql/v2=../../contrib/drivers/mysql
|
||||
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/sqlite/v2=../../contrib/drivers/sqlite
|
||||
# else
|
||||
# cd -
|
||||
# continue 1
|
||||
fi
|
||||
go mod tidy
|
||||
# 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
|
||||
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
|
||||
if [ $goModPath = "./cmd/gf" ]; then
|
||||
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/mssql/v2
|
||||
go mod edit -dropreplace github.com/gogf/gf/contrib/drivers/mysql/v2
|
||||
go mod edit -dropreplace github.com/gogf/gf/contrib/drivers/oracle/v2
|
||||
go mod edit -dropreplace github.com/gogf/gf/contrib/drivers/pgsql/v2
|
||||
go mod edit -dropreplace github.com/gogf/gf/contrib/drivers/sqlite/v2
|
||||
mv go.work.version.bak go.work
|
||||
fi
|
||||
cd -
|
||||
done
|
||||
|
||||
if [ -f "go.work.version.bak" ]; then
|
||||
mv go.work.version.bak go.work
|
||||
echo "Restore the go.work file"
|
||||
fi
|
||||
28
Makefile
28
Makefile
@ -18,33 +18,9 @@ lint:
|
||||
# make version to=v2.4.0
|
||||
.PHONY: version
|
||||
version:
|
||||
$(eval files=$(shell find . -name go.mod))
|
||||
@set -e; \
|
||||
newVersion=$(to); \
|
||||
echo "The version will be set to $$newVersion"; \
|
||||
if [[ $$newVersion =~ "v" ]]; then \
|
||||
latestVersion=$$newVersion; \
|
||||
echo "package gf" > version.go; \
|
||||
echo "" >> version.go; \
|
||||
echo "const (" >> version.go; \
|
||||
echo -e "\t// VERSION is the current GoFrame version." >> version.go; \
|
||||
echo -e "\tVERSION = \"$$latestVersion\"" >> version.go; \
|
||||
echo ")" >> version.go; \
|
||||
else \
|
||||
latestVersion=latest; \
|
||||
fi; \
|
||||
for file in ${files}; do \
|
||||
goModPath=$$(dirname $$file); \
|
||||
if [[ $$goModPath =~ "./contrib" || $$goModPath =~ "./cmd/gf" || $$goModPath =~ "./example" ]]; then \
|
||||
echo "" ; \
|
||||
echo "processing dir: $$goModPath"; \
|
||||
cd $$goModPath; \
|
||||
go mod tidy; \
|
||||
go list -f "{{if and (not .Indirect) (not .Main)}}{{.Path}}@$$latestVersion{{end}}" -m all | grep "^github.com/gogf/gf/contrib" | xargs -L1 go get -v; \
|
||||
go get -v github.com/gogf/gf/v2@$$latestVersion; \
|
||||
go mod tidy; \
|
||||
cd -; \
|
||||
fi \
|
||||
done
|
||||
./.set_version.sh ./ $$newVersion; \
|
||||
echo "make version to=$(to) done"
|
||||
|
||||
|
||||
|
||||
29
README.MD
29
README.MD
@ -1,14 +1,23 @@
|
||||
# GoFrame
|
||||
|
||||
<div align=center>
|
||||
<img src="https://goframe.org/statics/image/gf-head-large.png" width="100"/>
|
||||
<img src="https://goframe.org/statics/image/logo2.png?v=1" width="300"/>
|
||||
|
||||
[](https://godoc.org/github.com/gogf/gf)
|
||||
[](https://github.com/gogf/gf/actions/workflows/gf.yml)
|
||||
[](https://pkg.go.dev/github.com/gogf/gf/v2)
|
||||
[](https://github.com/gogf/gf/actions/workflows/ci-main.yml)
|
||||
[](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)
|
||||
|
||||
[](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>
|
||||
|
||||
`GoFrame` is a modular, powerful, high-performance and enterprise-class application development framework of Golang.
|
||||
@ -41,24 +50,20 @@ go get -u -v github.com/gogf/gf/v2
|
||||
## cli tool
|
||||
|
||||
```bash
|
||||
go install github.com/gogf/gf/cmd/gf/v2
|
||||
go install github.com/gogf/gf/cmd/gf/v2@latest
|
||||
```
|
||||
|
||||
# Limitation
|
||||
|
||||
```
|
||||
golang version >= 1.15
|
||||
golang version >= 1.18
|
||||
```
|
||||
|
||||
# Architecture
|
||||
|
||||
<div align=center>
|
||||
<img src="https://goframe.org/download/attachments/1114119/arch.png"/>
|
||||
</div>
|
||||
|
||||
# Documentation
|
||||
|
||||
- Chinese Official Site(中文官网): [https://goframe.org](https://goframe.org/display/gf)
|
||||
- Chinese Pages Document(中文镜像文档): [https://pages.goframe.org](https://pages.goframe.org)
|
||||
- Chinese Offline Document(中文离线文档): [https://github.com/gogf/goframe.org-pdf](https://github.com/gogf/goframe.org-pdf)
|
||||
- GoDoc API: [https://pkg.go.dev/github.com/gogf/gf/v2](https://pkg.go.dev/github.com/gogf/gf/v2)
|
||||
|
||||
# License
|
||||
|
||||
@ -21,22 +21,24 @@ You can also install `gf` tool using pre-built binaries: <https://github.com/gog
|
||||
|
||||
3. Database support
|
||||
|
||||
| DB | support | remarks |
|
||||
| :------: | :------: | :------: |
|
||||
| mysql | yes | - |
|
||||
| mariadb | yes | - |
|
||||
| tidb | yes | - |
|
||||
| mssql | yes | - |
|
||||
| oracle | yes | - |
|
||||
| pgsql | yes | - |
|
||||
| sqlite | yes | - |
|
||||
| clickhouse | no | manually make some changes to the [source codes](./internal/cmd/cmd_gen_dao.go) and do the building. |
|
||||
| dm | no | manually make some changes to the [source codes](./internal/cmd/cmd_gen_dao.go) and do the building. |
|
||||
| DB | builtin support | remarks |
|
||||
|:----------:|:---------------:|:----------------------------------------------------------------------------------------------------------------------------------------------------------------:|
|
||||
| mysql | yes | - |
|
||||
| mariadb | yes | - |
|
||||
| tidb | yes | - |
|
||||
| mssql | yes | - |
|
||||
| oracle | yes | - |
|
||||
| pgsql | 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. |
|
||||
| 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. |
|
||||
|
||||
## 2) Manually Install
|
||||
|
||||
```shell
|
||||
git clone https://github.com/gogf/gf && cd gf/cmd/gf && go install
|
||||
go install github.com/gogf/gf/cmd/gf/v2@latest # latest version
|
||||
go install github.com/gogf/gf/cmd/gf/v2@v2.5.5 # certain version(should be >= v2.5.5)
|
||||
```
|
||||
|
||||
## 2. Commands
|
||||
@ -47,22 +49,24 @@ USAGE
|
||||
gf COMMAND [OPTION]
|
||||
|
||||
COMMAND
|
||||
env show current Golang environment variables
|
||||
run running go codes with hot-compiled-like feature
|
||||
gen automatically generate go files for dao/do/entity/pb/pbentity
|
||||
tpl template parsing and building commands
|
||||
init create and initialize an empty GoFrame project
|
||||
pack packing any file/directory to a resource file, or a go file
|
||||
build cross-building go project for lots of platforms
|
||||
docker build docker image for current GoFrame project
|
||||
install install gf binary to system (might need root/admin permission)
|
||||
version show version information of current binary
|
||||
up upgrade GoFrame version/tool to latest one in current project
|
||||
env show current Golang environment variables
|
||||
fix auto fixing codes after upgrading to new GoFrame version
|
||||
run running go codes with hot-compiled-like feature
|
||||
gen automatically generate go files for dao/do/entity/pb/pbentity
|
||||
tpl template parsing and building commands
|
||||
init create and initialize an empty GoFrame project
|
||||
pack packing any file/directory to a resource file, or a go file
|
||||
build cross-building go project for lots of platforms
|
||||
docker build docker image for current GoFrame project
|
||||
install install gf binary to system (might need root/admin permission)
|
||||
version show version information of current binary
|
||||
|
||||
OPTION
|
||||
-y, --yes all yes for all command without prompt ask
|
||||
-v, --version show version information of current binary
|
||||
-d, --debug show internal detailed debugging information
|
||||
-h, --help more information about this command
|
||||
-y, --yes all yes for all command without prompt ask
|
||||
-v, --version show version information of current binary
|
||||
-d, --debug show internal detailed debugging information
|
||||
-h, --help more information about this command
|
||||
|
||||
ADDITIONAL
|
||||
Use "gf COMMAND -h" for details about a command.
|
||||
|
||||
118
cmd/gf/gfcmd/gfcmd.go
Normal file
118
cmd/gf/gfcmd/gfcmd.go
Normal file
@ -0,0 +1,118 @@
|
||||
// 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 gfcmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"runtime"
|
||||
|
||||
"github.com/gogf/gf/v2/errors/gcode"
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gcfg"
|
||||
"github.com/gogf/gf/v2/os/gcmd"
|
||||
"github.com/gogf/gf/v2/os/gfile"
|
||||
"github.com/gogf/gf/v2/text/gstr"
|
||||
|
||||
"github.com/gogf/gf/cmd/gf/v2/internal/cmd"
|
||||
_ "github.com/gogf/gf/cmd/gf/v2/internal/packed"
|
||||
"github.com/gogf/gf/cmd/gf/v2/internal/utility/allyes"
|
||||
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
|
||||
)
|
||||
|
||||
const (
|
||||
cliFolderName = `hack`
|
||||
)
|
||||
|
||||
// Command manages the CLI command of `gf`.
|
||||
// This struct can be globally accessible and extended with custom struct.
|
||||
type Command struct {
|
||||
*gcmd.Command
|
||||
}
|
||||
|
||||
// Run starts running the command according the command line arguments and options.
|
||||
func (c *Command) Run(ctx context.Context) {
|
||||
defer func() {
|
||||
if exception := recover(); exception != nil {
|
||||
if err, ok := exception.(error); ok {
|
||||
mlog.Print(err.Error())
|
||||
} else {
|
||||
panic(gerror.NewCodef(gcode.CodeInternalPanic, "%+v", exception))
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
// CLI configuration, using the `hack/config.yaml` in priority.
|
||||
if path, _ := gfile.Search(cliFolderName); path != "" {
|
||||
if adapter, ok := g.Cfg().GetAdapter().(*gcfg.AdapterFile); ok {
|
||||
if err := adapter.SetPath(path); err != nil {
|
||||
mlog.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// zsh alias "git fetch" conflicts checks.
|
||||
handleZshAlias()
|
||||
|
||||
// -y option checks.
|
||||
allyes.Init()
|
||||
|
||||
// just run.
|
||||
if err := c.RunWithError(ctx); err != nil {
|
||||
// Exit with error message and exit code 1.
|
||||
// It is very important to exit the command process with code 1.
|
||||
mlog.Fatalf(`%+v`, err)
|
||||
}
|
||||
}
|
||||
|
||||
// GetCommand retrieves and returns the root command of CLI `gf`.
|
||||
func GetCommand(ctx context.Context) (*Command, error) {
|
||||
root, err := gcmd.NewFromObject(cmd.GF)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
err = root.AddObject(
|
||||
cmd.Up,
|
||||
cmd.Env,
|
||||
cmd.Fix,
|
||||
cmd.Run,
|
||||
cmd.Gen,
|
||||
cmd.Tpl,
|
||||
cmd.Init,
|
||||
cmd.Pack,
|
||||
cmd.Build,
|
||||
cmd.Docker,
|
||||
cmd.Install,
|
||||
cmd.Version,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
command := &Command{
|
||||
root,
|
||||
}
|
||||
return command, nil
|
||||
}
|
||||
|
||||
// zsh alias "git fetch" conflicts checks.
|
||||
func handleZshAlias() {
|
||||
if runtime.GOOS == "windows" {
|
||||
return
|
||||
}
|
||||
if home, err := gfile.Home(); err == nil {
|
||||
zshPath := gfile.Join(home, ".zshrc")
|
||||
if gfile.Exists(zshPath) {
|
||||
var (
|
||||
aliasCommand = `alias gf=gf`
|
||||
content = gfile.GetContents(zshPath)
|
||||
)
|
||||
if !gstr.Contains(content, aliasCommand) {
|
||||
_ = gfile.PutContentsAppend(zshPath, "\n"+aliasCommand+"\n")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3,63 +3,58 @@ module github.com/gogf/gf/cmd/gf/v2
|
||||
go 1.18
|
||||
|
||||
require (
|
||||
github.com/gogf/gf/contrib/drivers/clickhouse/v2 v2.4.1
|
||||
github.com/gogf/gf/contrib/drivers/mssql/v2 v2.4.1
|
||||
github.com/gogf/gf/contrib/drivers/mysql/v2 v2.4.1
|
||||
github.com/gogf/gf/contrib/drivers/oracle/v2 v2.4.1
|
||||
github.com/gogf/gf/contrib/drivers/pgsql/v2 v2.4.1
|
||||
github.com/gogf/gf/contrib/drivers/sqlite/v2 v2.4.1
|
||||
github.com/gogf/gf/v2 v2.4.1
|
||||
github.com/gogf/gf/contrib/drivers/clickhouse/v2 v2.7.0
|
||||
github.com/gogf/gf/contrib/drivers/mssql/v2 v2.7.0
|
||||
github.com/gogf/gf/contrib/drivers/mysql/v2 v2.7.0
|
||||
github.com/gogf/gf/contrib/drivers/oracle/v2 v2.7.0
|
||||
github.com/gogf/gf/contrib/drivers/pgsql/v2 v2.7.0
|
||||
github.com/gogf/gf/contrib/drivers/sqlite/v2 v2.7.0
|
||||
github.com/gogf/gf/v2 v2.7.0
|
||||
github.com/gogf/selfupdate v0.0.0-20231215043001-5c48c528462f
|
||||
github.com/olekukonko/tablewriter v0.0.5
|
||||
golang.org/x/mod v0.9.0
|
||||
golang.org/x/tools v0.7.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/BurntSushi/toml v1.1.0 // indirect
|
||||
aead.dev/minisign v0.2.0 // indirect
|
||||
github.com/BurntSushi/toml v1.2.0 // indirect
|
||||
github.com/ClickHouse/clickhouse-go/v2 v2.0.15 // indirect
|
||||
github.com/clbanning/mxj/v2 v2.5.5 // indirect
|
||||
github.com/denisenkom/go-mssqldb v0.11.0 // indirect
|
||||
github.com/fatih/color v1.13.0 // indirect
|
||||
github.com/fsnotify/fsnotify v1.5.4 // indirect
|
||||
github.com/glebarez/go-sqlite v1.17.3 // indirect
|
||||
github.com/go-logr/logr v1.2.3 // 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/fatih/color v1.15.0 // indirect
|
||||
github.com/fsnotify/fsnotify v1.7.0 // indirect
|
||||
github.com/glebarez/go-sqlite v1.21.2 // indirect
|
||||
github.com/go-logr/logr v1.2.4 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/go-sql-driver/mysql v1.6.0 // indirect
|
||||
github.com/go-sql-driver/mysql v1.7.1 // indirect
|
||||
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe // indirect
|
||||
github.com/golang-sql/sqlexp v0.1.0 // indirect
|
||||
github.com/google/uuid v1.3.0 // indirect
|
||||
github.com/gorilla/websocket v1.5.0 // indirect
|
||||
github.com/grokify/html-strip-tags-go v0.0.1 // indirect
|
||||
github.com/lib/pq v1.10.4 // indirect
|
||||
github.com/lib/pq v1.10.9 // indirect
|
||||
github.com/magiconair/properties v1.8.6 // indirect
|
||||
github.com/mattn/go-colorable v0.1.9 // indirect
|
||||
github.com/mattn/go-isatty v0.0.14 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.9 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.15 // indirect
|
||||
github.com/paulmach/orb v0.7.1 // indirect
|
||||
github.com/pierrec/lz4/v4 v4.1.14 // indirect
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 // indirect
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
||||
github.com/rivo/uniseg v0.4.4 // indirect
|
||||
github.com/shopspring/decimal v1.3.1 // indirect
|
||||
github.com/sijms/go-ora/v2 v2.4.20 // indirect
|
||||
go.opentelemetry.io/otel v1.7.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk v1.7.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.7.0 // indirect
|
||||
golang.org/x/crypto v0.1.0 // indirect
|
||||
golang.org/x/mod v0.9.0 // indirect
|
||||
golang.org/x/net v0.8.0 // indirect
|
||||
golang.org/x/sys v0.6.0 // indirect
|
||||
golang.org/x/text v0.8.0 // indirect
|
||||
github.com/sijms/go-ora/v2 v2.7.10 // indirect
|
||||
go.opentelemetry.io/otel v1.14.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk v1.14.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.14.0 // indirect
|
||||
golang.org/x/crypto v0.14.0 // indirect
|
||||
golang.org/x/net v0.17.0 // indirect
|
||||
golang.org/x/sys v0.13.0 // indirect
|
||||
golang.org/x/text v0.13.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
modernc.org/libc v1.16.8 // indirect
|
||||
modernc.org/mathutil v1.4.1 // indirect
|
||||
modernc.org/memory v1.1.1 // indirect
|
||||
modernc.org/sqlite v1.17.3 // indirect
|
||||
)
|
||||
|
||||
replace (
|
||||
github.com/gogf/gf/contrib/drivers/clickhouse/v2 => ../../contrib/drivers/clickhouse/
|
||||
github.com/gogf/gf/contrib/drivers/mssql/v2 => ../../contrib/drivers/mssql/
|
||||
github.com/gogf/gf/contrib/drivers/mysql/v2 => ../../contrib/drivers/mysql/
|
||||
github.com/gogf/gf/contrib/drivers/oracle/v2 => ../../contrib/drivers/oracle/
|
||||
github.com/gogf/gf/contrib/drivers/pgsql/v2 => ../../contrib/drivers/pgsql/
|
||||
github.com/gogf/gf/contrib/drivers/sqlite/v2 => ../../contrib/drivers/sqlite/
|
||||
github.com/gogf/gf/v2 => ../../
|
||||
modernc.org/libc v1.22.5 // indirect
|
||||
modernc.org/mathutil v1.5.0 // indirect
|
||||
modernc.org/memory v1.5.0 // indirect
|
||||
modernc.org/sqlite v1.23.1 // indirect
|
||||
)
|
||||
|
||||
171
cmd/gf/go.sum
171
cmd/gf/go.sum
@ -1,42 +1,55 @@
|
||||
github.com/BurntSushi/toml v1.1.0 h1:ksErzDEI1khOiGPgpwuI7x2ebx/uXQNw7xJpn9Eq1+I=
|
||||
github.com/BurntSushi/toml v1.1.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
|
||||
aead.dev/minisign v0.2.0 h1:kAWrq/hBRu4AARY6AlciO83xhNnW9UaC8YipS2uhLPk=
|
||||
aead.dev/minisign v0.2.0/go.mod h1:zdq6LdSd9TbuSxchxwhpA9zEb9YXcVGoE8JakuiGaIQ=
|
||||
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/azidentity v0.11.0/go.mod h1:HcM1YX14R7CJcghJGOYCgdezslRSVzqwLf/q+4Y2r/0=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v0.7.0/go.mod h1:yqy467j36fJxcRV2TzfVZ1pCb5vxm4BtZPUdYWe/Xo8=
|
||||
github.com/BurntSushi/toml v1.2.0 h1:Rt8g24XnyGTyglgET/PRUNlrUeu9F5L+7FilkXfZgs0=
|
||||
github.com/BurntSushi/toml v1.2.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
|
||||
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/go.mod h1:Z21o82zD8FFqefOQDg93c0XITlxGbTsWQuRm588Azkk=
|
||||
github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
|
||||
github.com/bkaradzic/go-lz4 v1.0.0/go.mod h1:0YdlkowM3VswSROI7qDxhRvJ3sLhlFrRRwjwegp5jy4=
|
||||
github.com/clbanning/mxj/v2 v2.5.5 h1:oT81vUeEiQQ/DcHbzSytRngP6Ky9O+L+0Bw0zSJag9E=
|
||||
github.com/clbanning/mxj/v2 v2.5.5/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn/Qo+ve2s=
|
||||
github.com/clbanning/mxj/v2 v2.7.0 h1:WA/La7UGCanFe5NpHF0Q3DNtnCsVoxbPKuyBNHWRyME=
|
||||
github.com/clbanning/mxj/v2 v2.7.0/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn/Qo+ve2s=
|
||||
github.com/cloudflare/golz4 v0.0.0-20150217214814-ef862a3cdc58/go.mod h1:EOBUe0h4xcZ5GoxqC5SDxFQ8gwyZPKQoEzownBlhI80=
|
||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/denisenkom/go-mssqldb v0.11.0 h1:9rHa233rhdOyrz2GcP9NM+gi2psgJZ4GWDpL/7ND8HI=
|
||||
github.com/denisenkom/go-mssqldb v0.11.0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
|
||||
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w=
|
||||
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
|
||||
github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI=
|
||||
github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU=
|
||||
github.com/glebarez/go-sqlite v1.17.3 h1:Rji9ROVSTTfjuWD6j5B+8DtkNvPILoUC3xRhkQzGxvk=
|
||||
github.com/glebarez/go-sqlite v1.17.3/go.mod h1:Hg+PQuhUy98XCxWEJEaWob8x7lhJzhNYF1nZbUiRGIY=
|
||||
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/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/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
||||
github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs=
|
||||
github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw=
|
||||
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
|
||||
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
|
||||
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/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0=
|
||||
github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
|
||||
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/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.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
||||
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
||||
github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE=
|
||||
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
||||
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/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/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY=
|
||||
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
|
||||
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/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/google/go-cmp v0.5.3/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 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o=
|
||||
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
|
||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||
github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ=
|
||||
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/gorilla/handlers v1.4.2/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ=
|
||||
@ -46,24 +59,24 @@ github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/ad
|
||||
github.com/grokify/html-strip-tags-go v0.0.1 h1:0fThFwLbW7P/kOiTBs03FsJSV9RM2M/Q/MOnCQxKMo0=
|
||||
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/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
|
||||
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/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/lib/pq v1.10.4 h1:SO9z7FRPzA03QhHKJrH5BXA6HU1rS4V2nIVrrNC1iYk=
|
||||
github.com/lib/pq v1.10.4/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
|
||||
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo=
|
||||
github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
|
||||
github.com/mattn/go-colorable v0.1.9 h1:sqDoxXbdeALODt0DAeJCVp38ps9ZogZEAXjus69YV3U=
|
||||
github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
|
||||
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
||||
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
|
||||
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-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.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||
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.14.12/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
|
||||
github.com/mkevac/debugcharts v0.0.0-20191222103121-ae1c48aa8615/go.mod h1:Ad7oeElCZqA1Ufj0U9/liOF4BtVepxRcTvr2ey7zTvM=
|
||||
github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3PzxT8aQXRPkAt8xlV/e7d7w8GM5g0fa5F0D8=
|
||||
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
|
||||
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
|
||||
github.com/paulmach/orb v0.7.1 h1:Zha++Z5OX/l168sqHK3k4z18LDvr+YAO/VjK0ReQ9rU=
|
||||
@ -72,91 +85,93 @@ github.com/paulmach/protoscan v0.2.1/go.mod h1:SpcSwydNLrxUGSDvXvO0P7g7AuhJ7lcKf
|
||||
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/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
|
||||
github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4/go.mod h1:4OwLy04Bl9Ef3GJJCoec+30X3LQs/0/m4HFRt/2LUSA=
|
||||
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/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6OkFY5QxjkYwrChwuRruF69c169dPK26NUlk=
|
||||
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/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis=
|
||||
github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||
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/w32 v0.0.0-20160930032740-bb4de0191aa4/go.mod h1:qsXQc7+bwAM3Q1u/4XEfrquwF8Lw7D7y5cD8CuHnfIc=
|
||||
github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8=
|
||||
github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
|
||||
github.com/sijms/go-ora/v2 v2.4.20 h1:9e3z7VLBQXRAHGiIda1GEFtRhfxata0LghyMZqvLKew=
|
||||
github.com/sijms/go-ora/v2 v2.4.20/go.mod h1:EHxlY6x7y9HAsdfumurRfTd+v8NrEOTR3Xl4FWlH6xk=
|
||||
github.com/sijms/go-ora/v2 v2.7.10 h1:GSLdj0PYYgSndhsnm7b6p32OqgnwnUZSkFb3j+htfhI=
|
||||
github.com/sijms/go-ora/v2 v2.7.10/go.mod h1:EHxlY6x7y9HAsdfumurRfTd+v8NrEOTR3Xl4FWlH6xk=
|
||||
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.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.2 h1:4jaiDzPyXQvSd7D0EjG45355tLlV3VOECpq10pLC+8s=
|
||||
github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
|
||||
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
|
||||
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/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.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
|
||||
go.opentelemetry.io/otel v1.7.0 h1:Z2lA3Tdch0iDcrhJXDIlC94XE+bxok1F9B+4Lz/lGsM=
|
||||
go.opentelemetry.io/otel v1.7.0/go.mod h1:5BdUoMIz5WEs0vt0CUEMtSSaTSHBBVwrhnz7+nrD5xk=
|
||||
go.opentelemetry.io/otel/sdk v1.7.0 h1:4OmStpcKVOfvDOgCt7UriAPtKolwIhxpnSNI/yK+1B0=
|
||||
go.opentelemetry.io/otel/sdk v1.7.0/go.mod h1:uTEOTwaqIVuTGiJN7ii13Ibp75wJmYUDe374q6cZwUU=
|
||||
go.opentelemetry.io/otel/trace v1.7.0 h1:O37Iogk1lEkMRXewVtZ1BBTVn5JEp8GrJvP92bJqC6o=
|
||||
go.opentelemetry.io/otel v1.14.0 h1:/79Huy8wbf5DnIPhemGB+zEPVwnN6fuQybr/SRXa6hM=
|
||||
go.opentelemetry.io/otel v1.14.0/go.mod h1:o4buv+dJzx8rohcUeRmWUZhqupFvzWis188WlggnNeU=
|
||||
go.opentelemetry.io/otel/sdk v1.14.0 h1:PDCppFRDq8A1jL9v6KMI6dYesaq+DFcDZvjsoGvxGzY=
|
||||
go.opentelemetry.io/otel/sdk v1.14.0/go.mod h1:bwIC5TjrNG6QDCHNWvW4HLHtUQ4I+VQDsnjhvyZCALM=
|
||||
go.opentelemetry.io/otel/trace v1.7.0/go.mod h1:fzLSB9nqR2eXzxPXb2JW9IKE+ScyXA48yyE4TNvoHqU=
|
||||
go.opentelemetry.io/otel/trace v1.14.0 h1:wp2Mmvj41tDsyAJXiWDWpfNsOiIyd38fy85pyKcFq/M=
|
||||
go.opentelemetry.io/otel/trace v1.14.0/go.mod h1:8avnQLK+CG77yNLUae4ea2JDQ6iT+gozhnZjy/rw9G8=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/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-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.1.0 h1:MDRAIl0xIo9Io2xV565hzXHw3zVseKrJKodhohM5CjU=
|
||||
golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
|
||||
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-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.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.9.0 h1:KENHtAZL2y3NLMYZeHY9DW8HW8V+kQyJsY/V9JlKvCs=
|
||||
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-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-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ=
|
||||
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
|
||||
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-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-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
|
||||
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-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-20191220220014-0732a990476f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/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-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
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-20220405052023-b1e9470b6e64/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220429233432-b5fbb4746d32/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
|
||||
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
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.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.8-0.20211105212822-18b340fc7af2/go.mod h1:EFNZuWvGYxIRUEX+K8UmCFwYmZjqcrnq15ZuVldZkZ0=
|
||||
golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68=
|
||||
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
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-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-20201124115921-2c860bdd6e78/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo=
|
||||
golang.org/x/tools v0.7.0 h1:W4OVu8VVOaIO0yzWMNdepAulS7YfoS3Zabrm8DOXXU4=
|
||||
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=
|
||||
@ -168,33 +183,17 @@ google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ
|
||||
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/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-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/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
lukechampine.com/uint128 v1.1.1/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk=
|
||||
modernc.org/cc/v3 v3.36.0/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI=
|
||||
modernc.org/ccgo/v3 v3.0.0-20220428102840-41399a37e894/go.mod h1:eI31LL8EwEBKPpNpA4bU1/i+sKOwOrQy8D87zWUcRZc=
|
||||
modernc.org/ccgo/v3 v3.0.0-20220430103911-bc99d88307be/go.mod h1:bwdAnOoaIt8Ax9YdWGjxWsdkPcZyRPHqrOvJxaKAKGw=
|
||||
modernc.org/ccgo/v3 v3.16.4/go.mod h1:tGtX0gE9Jn7hdZFeU88slbTh1UtCYKusWOoCJuvkWsQ=
|
||||
modernc.org/ccgo/v3 v3.16.6/go.mod h1:tGtX0gE9Jn7hdZFeU88slbTh1UtCYKusWOoCJuvkWsQ=
|
||||
modernc.org/ccorpus v1.11.6/go.mod h1:2gEUTrWqdpH2pXsmTM1ZkjeSrUWDpjMu2T6m29L/ErQ=
|
||||
modernc.org/httpfs v1.0.6/go.mod h1:7dosgurJGp0sPaRanU53W4xZYKh14wfzX420oZADeHM=
|
||||
modernc.org/libc v0.0.0-20220428101251-2d5f3daf273b/go.mod h1:p7Mg4+koNjc8jkqwcoFBJx7tXkpj00G77X7A72jXPXA=
|
||||
modernc.org/libc v1.16.0/go.mod h1:N4LD6DBE9cf+Dzf9buBlzVJndKr/iJHG97vGLHYnb5A=
|
||||
modernc.org/libc v1.16.1/go.mod h1:JjJE0eu4yeK7tab2n4S1w8tlWd9MxXLRzheaRnAKymU=
|
||||
modernc.org/libc v1.16.7/go.mod h1:hYIV5VZczAmGZAnG15Vdngn5HSF5cSkbvfz2B7GRuVU=
|
||||
modernc.org/libc v1.16.8 h1:Ux98PaOMvolgoFX/YwusFOHBnanXdGRmWgI8ciI2z4o=
|
||||
modernc.org/libc v1.16.8/go.mod h1:hYIV5VZczAmGZAnG15Vdngn5HSF5cSkbvfz2B7GRuVU=
|
||||
modernc.org/mathutil v1.2.2/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
|
||||
modernc.org/mathutil v1.4.1 h1:ij3fYGe8zBF4Vu+g0oT7mB06r8sqGWKuJu1yXeR4by8=
|
||||
modernc.org/mathutil v1.4.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
|
||||
modernc.org/memory v1.1.1 h1:bDOL0DIDLQv7bWhP3gMvIrnoFw+Eo6F7a2QK9HPDiFU=
|
||||
modernc.org/memory v1.1.1/go.mod h1:/0wo5ibyrQiaoUoH7f9D8dnglAmILJ5/cxZlRECf+Nw=
|
||||
modernc.org/opt v0.1.1/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0=
|
||||
modernc.org/sqlite v1.17.3 h1:iE+coC5g17LtByDYDWKpR6m2Z9022YrSh3bumwOnIrI=
|
||||
modernc.org/sqlite v1.17.3/go.mod h1:10hPVYar9C0kfXuTWGz8s0XtB8uAGymUy51ZzStYe3k=
|
||||
modernc.org/strutil v1.1.1/go.mod h1:DE+MQQ/hjKBZS2zNInV5hhcipt5rLPWkmpbGeW5mmdw=
|
||||
modernc.org/tcl v1.13.1/go.mod h1:XOLfOwzhkljL4itZkK6T72ckMgvj0BDsnKNdZVUOecw=
|
||||
modernc.org/token v1.0.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
|
||||
modernc.org/z v1.5.1/go.mod h1:eWFB510QWW5Th9YGZT81s+LwvaAs3Q2yr4sP0rmLkv8=
|
||||
modernc.org/libc v1.22.5 h1:91BNch/e5B0uPbJFgqbxXuOnxBQjlS//icfQEGmvyjE=
|
||||
modernc.org/libc v1.22.5/go.mod h1:jj+Z7dTNX8fBScMVNRAYZ/jF91K8fdT2hYMThc3YjBY=
|
||||
modernc.org/mathutil v1.5.0 h1:rV0Ko/6SfM+8G+yKiyI830l3Wuz1zRutdslNoQ0kfiQ=
|
||||
modernc.org/mathutil v1.5.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
|
||||
modernc.org/memory v1.5.0 h1:N+/8c5rE6EqugZwHii4IFsaJ7MUhoWX07J5tC/iI5Ds=
|
||||
modernc.org/memory v1.5.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU=
|
||||
modernc.org/sqlite v1.23.1 h1:nrSBg4aRQQwq59JpvGEQ15tNxoO5pX/kUjcRNwSAGQM=
|
||||
modernc.org/sqlite v1.23.1/go.mod h1:OrDj17Mggn6MhE+iPbBNf7RGKODDE9NFT0f3EwDzJqk=
|
||||
|
||||
20
cmd/gf/go.work
Normal file
20
cmd/gf/go.work
Normal file
@ -0,0 +1,20 @@
|
||||
go 1.18
|
||||
|
||||
use (
|
||||
./
|
||||
)
|
||||
|
||||
// =====================================================================================================
|
||||
// NOTE:
|
||||
// Please update associated commands in ../../.set_version.sh if any of the follows replacements change.
|
||||
// =====================================================================================================
|
||||
|
||||
replace (
|
||||
github.com/gogf/gf/contrib/drivers/clickhouse/v2 => ../../contrib/drivers/clickhouse
|
||||
github.com/gogf/gf/contrib/drivers/mssql/v2 => ../../contrib/drivers/mssql
|
||||
github.com/gogf/gf/contrib/drivers/mysql/v2 => ../../contrib/drivers/mysql
|
||||
github.com/gogf/gf/contrib/drivers/oracle/v2 => ../../contrib/drivers/oracle
|
||||
github.com/gogf/gf/contrib/drivers/pgsql/v2 => ../../contrib/drivers/pgsql
|
||||
github.com/gogf/gf/contrib/drivers/sqlite/v2 => ../../contrib/drivers/sqlite
|
||||
github.com/gogf/gf/v2 => ../../
|
||||
)
|
||||
@ -55,6 +55,7 @@ func (c cGF) Index(ctx context.Context, in cGFInput) (out *cGFOutput, err error)
|
||||
_, err = Version.Index(ctx, cVersionInput{})
|
||||
return
|
||||
}
|
||||
|
||||
answer := "n"
|
||||
// No argument or option, do installation checks.
|
||||
if data, isInstalled := service.Install.IsInstalled(); !isInstalled {
|
||||
@ -71,6 +72,7 @@ func (c cGF) Index(ctx context.Context, in cGFInput) (out *cGFOutput, err error)
|
||||
gcmd.Scan("press `Enter` to exit...")
|
||||
return
|
||||
}
|
||||
|
||||
// Print help content.
|
||||
gcmd.CommandFromCtx(ctx).Print()
|
||||
return
|
||||
|
||||
@ -17,6 +17,7 @@ import (
|
||||
|
||||
"github.com/gogf/gf/v2/encoding/gbase64"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gbuild"
|
||||
"github.com/gogf/gf/v2/os/gcmd"
|
||||
"github.com/gogf/gf/v2/os/genv"
|
||||
"github.com/gogf/gf/v2/os/gfile"
|
||||
@ -43,10 +44,11 @@ type cBuild struct {
|
||||
}
|
||||
|
||||
const (
|
||||
cBuildBrief = `cross-building go project for lots of platforms`
|
||||
cBuildEg = `
|
||||
cBuildDefaultFile = "main.go"
|
||||
cBuildBrief = `cross-building go project for lots of platforms`
|
||||
cBuildEg = `
|
||||
gf build main.go
|
||||
gf build main.go --pack public,template
|
||||
gf build main.go --ps public,template
|
||||
gf build main.go --cgo
|
||||
gf build main.go -m none
|
||||
gf build main.go -n my-app -a all -s all
|
||||
@ -122,14 +124,14 @@ type cBuildInput struct {
|
||||
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 ','"`
|
||||
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 './temp'" d:"./temp"`
|
||||
Path string `short:"p" name:"path" brief:"output binary directory path, default is '.'" d:"."`
|
||||
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"`
|
||||
Cgo bool `short:"c" name:"cgo" brief:"enable or disable cgo feature, it's disabled in default" orphan:"true"`
|
||||
VarMap g.Map `short:"r" name:"varMap" brief:"custom built embedded variable into binary"`
|
||||
PackSrc string `short:"ps" name:"packSrc" brief:"pack one or more folders into one go file before building"`
|
||||
PackDst string `short:"pd" name:"packDst" brief:"temporary go file path for pack, this go file will be automatically removed after built" d:"internal/packed/build_pack_data.go"`
|
||||
ExitWhenError bool `short:"ew" name:"exitWhenError" brief:"exit building when any error occurs, default is false" orphan:"true"`
|
||||
ExitWhenError bool `short:"ew" name:"exitWhenError" brief:"exit building when any error occurs, specially for multiple arch and system buildings. default is false" orphan:"true"`
|
||||
DumpENV bool `short:"de" name:"dumpEnv" brief:"dump current go build environment before building binary" orphan:"true"`
|
||||
}
|
||||
|
||||
@ -143,7 +145,7 @@ func (c cBuild) Index(ctx context.Context, in cBuildInput) (out *cBuildOutput, e
|
||||
|
||||
mlog.SetHeaderPrint(true)
|
||||
|
||||
mlog.Debugf(`build input: %+v`, in)
|
||||
mlog.Debugf(`build command input: %+v`, in)
|
||||
// Necessary check.
|
||||
if gproc.SearchBinary("go") == "" {
|
||||
mlog.Fatalf(`command "go" not found in your environment, please install golang first to proceed this command`)
|
||||
@ -151,14 +153,15 @@ func (c cBuild) Index(ctx context.Context, in cBuildInput) (out *cBuildOutput, e
|
||||
|
||||
var (
|
||||
parser = gcmd.ParserFromCtx(ctx)
|
||||
file = parser.GetArg(2).String()
|
||||
file = in.File
|
||||
)
|
||||
if len(file) < 1 {
|
||||
if file == "" {
|
||||
file = parser.GetArg(2).String()
|
||||
// Check and use the main.go file.
|
||||
if gfile.Exists("main.go") {
|
||||
file = "main.go"
|
||||
if gfile.Exists(cBuildDefaultFile) {
|
||||
file = cBuildDefaultFile
|
||||
} else {
|
||||
mlog.Fatal("build file path cannot be empty")
|
||||
mlog.Fatal("build file path is empty or main.go not found in current working directory")
|
||||
}
|
||||
}
|
||||
if in.Name == "" {
|
||||
@ -238,13 +241,7 @@ func (c cBuild) Index(ctx context.Context, in cBuildInput) (out *cBuildOutput, e
|
||||
} else {
|
||||
genv.MustSet("CGO_ENABLED", "0")
|
||||
}
|
||||
var (
|
||||
cmd = ""
|
||||
ext = ""
|
||||
)
|
||||
for system, item := range platformMap {
|
||||
cmd = ""
|
||||
ext = ""
|
||||
if len(customSystems) > 0 && customSystems[0] != "all" && !gstr.InArray(customSystems, system) {
|
||||
continue
|
||||
}
|
||||
@ -253,44 +250,25 @@ func (c cBuild) Index(ctx context.Context, in cBuildInput) (out *cBuildOutput, e
|
||||
continue
|
||||
}
|
||||
if len(customSystems) == 0 && len(customArches) == 0 {
|
||||
if runtime.GOOS == "windows" {
|
||||
ext = ".exe"
|
||||
}
|
||||
// Single binary building, output the binary to current working folder.
|
||||
output := ""
|
||||
if len(in.Output) > 0 {
|
||||
output = "-o " + in.Output + ext
|
||||
} else {
|
||||
output = "-o " + in.Name + ext
|
||||
}
|
||||
cmd = fmt.Sprintf(`go build %s -ldflags "%s" %s %s`, output, ldFlags, in.Extra, file)
|
||||
} else {
|
||||
// Cross-building, output the compiled binary to specified path.
|
||||
if system == "windows" {
|
||||
ext = ".exe"
|
||||
}
|
||||
genv.MustSet("GOOS", system)
|
||||
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,
|
||||
// For example:
|
||||
// `gf build`
|
||||
// `gf build -o main.exe`
|
||||
c.doBinaryBuild(
|
||||
ctx, file,
|
||||
in.Output, in.Path,
|
||||
runtime.GOOS, runtime.GOARCH, in.Name, ldFlags, in.Extra,
|
||||
in.ExitWhenError,
|
||||
true,
|
||||
)
|
||||
}
|
||||
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))
|
||||
c.doBinaryBuild(
|
||||
ctx, file,
|
||||
in.Output, in.Path,
|
||||
system, arch, in.Name, ldFlags, in.Extra,
|
||||
in.ExitWhenError,
|
||||
false,
|
||||
)
|
||||
}
|
||||
// single binary building.
|
||||
if len(customSystems) == 0 && len(customArches) == 0 {
|
||||
@ -304,6 +282,68 @@ buildDone:
|
||||
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
|
||||
// file as json.
|
||||
func (c cBuild) getBuildInVarStr(ctx context.Context, in cBuildInput) string {
|
||||
@ -311,8 +351,9 @@ func (c cBuild) getBuildInVarStr(ctx context.Context, in cBuildInput) string {
|
||||
if buildInVarMap == nil {
|
||||
buildInVarMap = make(g.Map)
|
||||
}
|
||||
buildInVarMap["builtGit"] = c.getGitCommit(ctx)
|
||||
buildInVarMap["builtTime"] = gtime.Now().String()
|
||||
buildInVarMap[gbuild.BuiltGit] = c.getGitCommit(ctx)
|
||||
buildInVarMap[gbuild.BuiltTime] = gtime.Now().String()
|
||||
buildInVarMap[gbuild.BuiltVersion] = in.Version
|
||||
b, err := json.Marshal(buildInVarMap)
|
||||
if err != nil {
|
||||
mlog.Fatal(err)
|
||||
|
||||
@ -78,10 +78,10 @@ func init() {
|
||||
|
||||
type cDockerInput struct {
|
||||
g.Meta `name:"docker" config:"gfcli.docker"`
|
||||
Main string `name:"MAIN" arg:"true" brief:"{cDockerMainBrief}" d:"main.go"`
|
||||
Main string `name:"MAIN" arg:"true" brief:"{cDockerMainBrief}" d:"main.go"`
|
||||
File string `name:"file" short:"f" brief:"{cDockerFileBrief}" d:"manifest/docker/Dockerfile"`
|
||||
Shell string `name:"shell" short:"s" brief:"{cDockerShellBrief}" d:"manifest/docker/docker.sh"`
|
||||
Build string `name:"build" short:"b" brief:"{cDockerBuildBrief}" d:"-a amd64 -s linux"`
|
||||
Build string `name:"build" short:"b" brief:"{cDockerBuildBrief}"`
|
||||
Tag string `name:"tag" short:"t" brief:"{cDockerTagBrief}"`
|
||||
TagName string `name:"tagName" short:"tn" brief:"{cDockerTagNameBrief}" v:"required-with:TagPrefixes"`
|
||||
TagPrefixes []string `name:"tagPrefixes" short:"tp" brief:"{cDockerTagPrefixesBrief}" v:"required-with:TagName"`
|
||||
@ -97,17 +97,23 @@ func (c cDocker) Index(ctx context.Context, in cDockerInput) (out *cDockerOutput
|
||||
mlog.Fatalf(`command "docker" not found in your environment, please install docker first to proceed this command`)
|
||||
}
|
||||
|
||||
mlog.Debugf(`docker command input: %+v`, in)
|
||||
|
||||
// Binary build.
|
||||
in.Build += " --exit"
|
||||
if in.Main != "" {
|
||||
if err = gproc.ShellRun(ctx, fmt.Sprintf(`gf build %s %s`, in.Main, in.Build)); err != nil {
|
||||
return
|
||||
if in.Main != "" && in.Build != "" {
|
||||
in.Build += " --exitWhenError"
|
||||
if in.Main != "" {
|
||||
if err = gproc.ShellRun(ctx, fmt.Sprintf(`gf build %s %s`, in.Main, in.Build)); err != nil {
|
||||
mlog.Debugf(`build binary failed with error: %+v`, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Shell executing.
|
||||
if in.Shell != "" && gfile.Exists(in.Shell) {
|
||||
if err = c.exeDockerShell(ctx, in.Shell); err != nil {
|
||||
mlog.Debugf(`build docker failed with error: %+v`, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
@ -10,6 +10,7 @@ import (
|
||||
"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"
|
||||
@ -69,6 +70,7 @@ func (c cFix) doFix(in cFixInput) (err error) {
|
||||
|
||||
var items = []cFixItem{
|
||||
{Version: "v2.3", Func: c.doFixV23},
|
||||
{Version: "v2.5", Func: c.doFixV25},
|
||||
}
|
||||
for _, item := range items {
|
||||
if gstr.CompareVersionGo(in.Version, item.Version) < 0 {
|
||||
@ -103,6 +105,28 @@ func (c cFix) doFixV23(version string) error {
|
||||
return gfile.ReplaceDirFunc(replaceFunc, ".", "*.go", true)
|
||||
}
|
||||
|
||||
// doFixV25 fixes code when upgrading to GoFrame v2.5.
|
||||
func (c cFix) doFixV25(version string) (err error) {
|
||||
replaceFunc := func(path, content string) string {
|
||||
content, err = c.doFixV25Content(content)
|
||||
return content
|
||||
}
|
||||
return gfile.ReplaceDirFunc(replaceFunc, ".", "*.go", true)
|
||||
}
|
||||
|
||||
func (c cFix) doFixV25Content(content string) (newContent string, err error) {
|
||||
newContent = content
|
||||
if gstr.Contains(content, `.BindHookHandlerByMap(`) {
|
||||
var pattern = `\.BindHookHandlerByMap\((.+?), map\[string\]ghttp\.HandlerFunc`
|
||||
newContent, err = gregex.ReplaceString(
|
||||
pattern,
|
||||
`.BindHookHandlerByMap($1, map[ghttp.HookName]ghttp.HandlerFunc`,
|
||||
content,
|
||||
)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (c cFix) autoDetectVersion(in cFixInput) (string, error) {
|
||||
var (
|
||||
err error
|
||||
|
||||
@ -19,6 +19,7 @@ type cGen struct {
|
||||
g.Meta `name:"gen" brief:"{cGenBrief}" dc:"{cGenDc}"`
|
||||
cGenDao
|
||||
cGenEnums
|
||||
cGenCtrl
|
||||
cGenPb
|
||||
cGenPbEntity
|
||||
cGenService
|
||||
|
||||
15
cmd/gf/internal/cmd/cmd_gen_ctrl.go
Normal file
15
cmd/gf/internal/cmd/cmd_gen_ctrl.go
Normal file
@ -0,0 +1,15 @@
|
||||
// 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 (
|
||||
"github.com/gogf/gf/cmd/gf/v2/internal/cmd/genctrl"
|
||||
)
|
||||
|
||||
type (
|
||||
cGenCtrl = genctrl.CGenCtrl
|
||||
)
|
||||
@ -25,6 +25,7 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
// Init .
|
||||
Init = cInit{}
|
||||
)
|
||||
|
||||
@ -64,14 +65,13 @@ type cInitInput struct {
|
||||
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"`
|
||||
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{}
|
||||
|
||||
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() {
|
||||
s := gcmd.Scanf(`the folder "%s" is not empty, files might be overwrote, continue? [y/n]: `, in.Name)
|
||||
if strings.EqualFold(s, "n") {
|
||||
@ -105,7 +105,7 @@ func (c cInit) Index(ctx context.Context, in cInitInput) (out *cInitOutput, err
|
||||
err = gfile.ReadLines(gitignoreFile, func(line string) error {
|
||||
// Add only hidden files or directories
|
||||
// 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, ".") {
|
||||
ignoreFiles = append(ignoreFiles, line)
|
||||
}
|
||||
@ -118,6 +118,11 @@ func (c cInit) Index(ctx context.Context, in cInitInput) (out *cInitOutput, err
|
||||
}
|
||||
}
|
||||
|
||||
// Replace module name.
|
||||
if in.Module == "" {
|
||||
in.Module = gfile.Basename(gfile.RealPath(in.Name))
|
||||
}
|
||||
|
||||
// Replace template name to project name.
|
||||
err = gfile.ReplaceDirFunc(func(path, content string) string {
|
||||
for _, ignoreFile := range ignoreFiles {
|
||||
@ -125,7 +130,7 @@ func (c cInit) Index(ctx context.Context, in cInitInput) (out *cInitOutput, err
|
||||
return content
|
||||
}
|
||||
}
|
||||
return gstr.Replace(gfile.GetContents(path), cInitRepoPrefix+templateRepoName, gfile.Basename(gfile.RealPath(in.Name)))
|
||||
return gstr.Replace(gfile.GetContents(path), cInitRepoPrefix+templateRepoName, in.Module)
|
||||
}, in.Name, "*", true)
|
||||
if err != nil {
|
||||
return
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
// Copyright GoFrame gf Author(https://goframe.org). All Rights Reserved.
|
||||
// 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,
|
||||
@ -9,6 +9,7 @@ package cmd
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
@ -33,10 +34,11 @@ type cRun struct {
|
||||
}
|
||||
|
||||
type cRunApp struct {
|
||||
File string // Go run file name.
|
||||
Path string // Directory storing built binary.
|
||||
Options string // Extra "go run" options.
|
||||
Args string // Custom arguments.
|
||||
File string // Go run file name.
|
||||
Path string // Directory storing built binary.
|
||||
Options string // Extra "go run" options.
|
||||
Args string // Custom arguments.
|
||||
WatchPaths []string // Watch paths for live reload.
|
||||
}
|
||||
|
||||
const (
|
||||
@ -46,15 +48,17 @@ const (
|
||||
gf run main.go
|
||||
gf run main.go --args "server -p 8080"
|
||||
gf run main.go -mod=vendor
|
||||
gf run main.go -w "manifest/config/*.yaml"
|
||||
`
|
||||
cRunDc = `
|
||||
The "run" command is used for running go codes with hot-compiled-like feature,
|
||||
which compiles and runs the go codes asynchronously when codes change.
|
||||
`
|
||||
cRunFileBrief = `building file path.`
|
||||
cRunPathBrief = `output directory path for built binary file. it's "manifest/output" in default`
|
||||
cRunExtraBrief = `the same options as "go run"/"go build" except some options as follows defined`
|
||||
cRunArgsBrief = `custom arguments for your process`
|
||||
cRunFileBrief = `building file path.`
|
||||
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`
|
||||
cRunArgsBrief = `custom arguments for your process`
|
||||
cRunWatchPathsBrief = `watch additional paths for live reload, separated by ",". i.e. "manifest/config/*.yaml"`
|
||||
)
|
||||
|
||||
var (
|
||||
@ -63,24 +67,26 @@ var (
|
||||
|
||||
func init() {
|
||||
gtag.Sets(g.MapStrStr{
|
||||
`cRunUsage`: cRunUsage,
|
||||
`cRunBrief`: cRunBrief,
|
||||
`cRunEg`: cRunEg,
|
||||
`cRunDc`: cRunDc,
|
||||
`cRunFileBrief`: cRunFileBrief,
|
||||
`cRunPathBrief`: cRunPathBrief,
|
||||
`cRunExtraBrief`: cRunExtraBrief,
|
||||
`cRunArgsBrief`: cRunArgsBrief,
|
||||
`cRunUsage`: cRunUsage,
|
||||
`cRunBrief`: cRunBrief,
|
||||
`cRunEg`: cRunEg,
|
||||
`cRunDc`: cRunDc,
|
||||
`cRunFileBrief`: cRunFileBrief,
|
||||
`cRunPathBrief`: cRunPathBrief,
|
||||
`cRunExtraBrief`: cRunExtraBrief,
|
||||
`cRunArgsBrief`: cRunArgsBrief,
|
||||
`cRunWatchPathsBrief`: cRunWatchPathsBrief,
|
||||
})
|
||||
}
|
||||
|
||||
type (
|
||||
cRunInput struct {
|
||||
g.Meta `name:"run"`
|
||||
File string `name:"FILE" arg:"true" brief:"{cRunFileBrief}" v:"required"`
|
||||
Path string `name:"path" short:"p" brief:"{cRunPathBrief}" d:"./"`
|
||||
Extra string `name:"extra" short:"e" brief:"{cRunExtraBrief}"`
|
||||
Args string `name:"args" short:"a" brief:"{cRunArgsBrief}"`
|
||||
g.Meta `name:"run"`
|
||||
File string `name:"FILE" arg:"true" brief:"{cRunFileBrief}" v:"required"`
|
||||
Path string `name:"path" short:"p" brief:"{cRunPathBrief}" d:"./"`
|
||||
Extra string `name:"extra" short:"e" brief:"{cRunExtraBrief}"`
|
||||
Args string `name:"args" short:"a" brief:"{cRunArgsBrief}"`
|
||||
WatchPaths []string `name:"watchPaths" short:"w" brief:"{cRunWatchPathsBrief}"`
|
||||
}
|
||||
cRunOutput struct{}
|
||||
)
|
||||
@ -91,31 +97,52 @@ func (c cRun) Index(ctx context.Context, in cRunInput) (out *cRunOutput, err err
|
||||
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{
|
||||
File: in.File,
|
||||
Path: in.Path,
|
||||
Options: in.Extra,
|
||||
Args: in.Args,
|
||||
File: in.File,
|
||||
Path: in.Path,
|
||||
Options: in.Extra,
|
||||
Args: in.Args,
|
||||
WatchPaths: in.WatchPaths,
|
||||
}
|
||||
dirty := gtype.NewBool()
|
||||
_, err = gfsnotify.Add(gfile.RealPath("."), func(event *gfsnotify.Event) {
|
||||
|
||||
callbackFunc := func(event *gfsnotify.Event) {
|
||||
if gfile.ExtName(event.Path) != "go" {
|
||||
return
|
||||
}
|
||||
|
||||
// Variable `dirty` is used for running the changes only one in one second.
|
||||
if !dirty.Cas(false, true) {
|
||||
return
|
||||
}
|
||||
|
||||
// With some delay in case of multiple code changes in very short interval.
|
||||
gtimer.SetTimeout(ctx, 1500*gtime.MS, func(ctx context.Context) {
|
||||
defer dirty.Set(false)
|
||||
mlog.Printf(`go file changes: %s`, event.String())
|
||||
mlog.Printf(`watched file changes: %s`, event.String())
|
||||
app.Run(ctx)
|
||||
})
|
||||
})
|
||||
if err != nil {
|
||||
mlog.Fatal(err)
|
||||
}
|
||||
|
||||
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)
|
||||
select {}
|
||||
}
|
||||
@ -152,7 +179,6 @@ func (app *cRunApp) Run(ctx context.Context) {
|
||||
if process != nil {
|
||||
if err := process.Kill(); err != nil {
|
||||
mlog.Debugf("kill process error: %s", err.Error())
|
||||
//return
|
||||
}
|
||||
}
|
||||
// Run the binary file.
|
||||
@ -171,3 +197,22 @@ func (app *cRunApp) Run(ctx context.Context) {
|
||||
mlog.Printf("build running pid: %d", pid)
|
||||
}
|
||||
}
|
||||
|
||||
func matchWatchPaths(watchPaths []string, eventPath string) bool {
|
||||
for _, path := range watchPaths {
|
||||
absPath, err := filepath.Abs(path)
|
||||
if err != nil {
|
||||
mlog.Printf("match watchPath '%s' error: %s", path, err.Error())
|
||||
continue
|
||||
}
|
||||
matched, err := filepath.Match(absPath, eventPath)
|
||||
if err != nil {
|
||||
mlog.Printf("match watchPath '%s' error: %s", path, err.Error())
|
||||
continue
|
||||
}
|
||||
if matched {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
@ -11,10 +11,11 @@ import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
|
||||
"github.com/gogf/gf/cmd/gf/v2/internal/utility/utils"
|
||||
"github.com/gogf/gf/v2/container/gset"
|
||||
"github.com/gogf/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/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gfile"
|
||||
"github.com/gogf/gf/v2/os/gproc"
|
||||
@ -124,6 +125,8 @@ func (c cUp) doUpgradeVersion(ctx context.Context, in cUpInput) (out *doUpgradeV
|
||||
if gfile.Exists(goModPath) {
|
||||
var packages []Package
|
||||
err = gfile.ReadLines(goModPath, func(line string) error {
|
||||
line = gstr.Trim(line)
|
||||
line = gstr.TrimLeftStr(line, "require ")
|
||||
line = gstr.Trim(line)
|
||||
if gstr.HasPrefix(line, gfPackage) {
|
||||
array := gstr.SplitAndTrim(line, " ")
|
||||
@ -174,6 +177,11 @@ func (c cUp) doUpgradeCLI(ctx context.Context) (err error) {
|
||||
)
|
||||
localSaveFilePath = gfile.SelfPath() + "~"
|
||||
)
|
||||
|
||||
if runtime.GOOS == "windows" {
|
||||
downloadUrl += ".exe"
|
||||
}
|
||||
|
||||
mlog.Printf(`start downloading "%s" to "%s", it may take some time`, downloadUrl, localSaveFilePath)
|
||||
err = utils.HTTPDownloadFileWithPercent(downloadUrl, localSaveFilePath)
|
||||
if err != nil {
|
||||
@ -191,17 +199,14 @@ func (c cUp) doUpgradeCLI(ctx context.Context) (err error) {
|
||||
mlog.Fatalf(`download "%s" to "%s" failed`, downloadUrl, localSaveFilePath)
|
||||
}
|
||||
|
||||
// It replaces self binary with new version cli binary.
|
||||
switch runtime.GOOS {
|
||||
case "windows":
|
||||
if err := gfile.Rename(localSaveFilePath, gfile.SelfPath()); err != nil {
|
||||
mlog.Fatalf(`install failed: %s`, err.Error())
|
||||
}
|
||||
|
||||
default:
|
||||
if err := gfile.PutBytes(gfile.SelfPath(), gfile.GetBytes(localSaveFilePath)); err != nil {
|
||||
mlog.Fatalf(`install failed: %s`, err.Error())
|
||||
}
|
||||
newFile, err := gfile.Open(localSaveFilePath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// selfupdate
|
||||
err = selfupdate.Apply(newFile, selfupdate.Options{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@ -7,14 +7,19 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"runtime"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gogf/gf/v2"
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gbuild"
|
||||
"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"
|
||||
|
||||
@ -25,6 +30,10 @@ var (
|
||||
Version = cVersion{}
|
||||
)
|
||||
|
||||
const (
|
||||
defaultIndent = "{{indent}}"
|
||||
)
|
||||
|
||||
type cVersion struct {
|
||||
g.Meta `name:"version" brief:"show version information of current binary"`
|
||||
}
|
||||
@ -36,40 +45,98 @@ type cVersionInput struct {
|
||||
type cVersionOutput struct{}
|
||||
|
||||
func (c cVersion) Index(ctx context.Context, in cVersionInput) (*cVersionOutput, error) {
|
||||
info := gbuild.Info()
|
||||
if info.Git == "" {
|
||||
info.Git = "none"
|
||||
}
|
||||
mlog.Printf(`GoFrame CLI Tool %s, https://goframe.org`, gf.VERSION)
|
||||
gfVersion, err := c.getGFVersionOfCurrentProject()
|
||||
if err != nil {
|
||||
gfVersion = err.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 {
|
||||
gfVersion = gfVersion + " in current go.mod"
|
||||
}
|
||||
mlog.Printf(`GoFrame Version: %s`, gfVersion)
|
||||
mlog.Printf(`CLI Installed At: %s`, gfile.SelfPath())
|
||||
if info.GoFrame == "" {
|
||||
mlog.Print(`Current is a custom installed version, no installation information.`)
|
||||
return nil, nil
|
||||
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()))
|
||||
}
|
||||
}
|
||||
|
||||
mlog.Print(gstr.Trim(fmt.Sprintf(`
|
||||
CLI Built Detail:
|
||||
Go Version: %s
|
||||
GF Version: %s
|
||||
Git Commit: %s
|
||||
Build Time: %s
|
||||
`, info.Golang, info.GoFrame, info.Git, info.Time)))
|
||||
detailBuffer.appendLine(0, "CLI Detail:")
|
||||
detailBuffer.appendLine(1, fmt.Sprintf("Installed At: %s", gfile.SelfPath()))
|
||||
info := gbuild.Info()
|
||||
if info.GoFrame == "" {
|
||||
detailBuffer.appendLine(1, fmt.Sprintf("Built Go Version: %s", runtime.Version()))
|
||||
detailBuffer.appendLine(1, fmt.Sprintf("Built GF Version: %s", gf.VERSION))
|
||||
} else {
|
||||
if info.Git == "" {
|
||||
info.Git = "none"
|
||||
}
|
||||
detailBuffer.appendLine(1, fmt.Sprintf("Built Go Version: %s", info.Golang))
|
||||
detailBuffer.appendLine(1, fmt.Sprintf("Built GF Version: %s", info.GoFrame))
|
||||
detailBuffer.appendLine(1, fmt.Sprintf("Git Commit: %s", info.Git))
|
||||
detailBuffer.appendLine(1, fmt.Sprintf("Built Time: %s", info.Time))
|
||||
}
|
||||
|
||||
detailBuffer.appendLine(0, "Others Detail:")
|
||||
detailBuffer.appendLine(1, "Docs: https://goframe.org")
|
||||
detailBuffer.appendLine(1, fmt.Sprintf("Now : %s", time.Now().Format(time.RFC3339)))
|
||||
|
||||
mlog.Print(detailBuffer.replaceAllIndent(" "))
|
||||
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.
|
||||
func (c cVersion) getGFVersionOfCurrentProject() (string, error) {
|
||||
goModPath := gfile.Join(gfile.Pwd(), "go.mod")
|
||||
if gfile.Exists(goModPath) {
|
||||
lines := gstr.SplitAndTrim(gfile.GetContents(goModPath), "\n")
|
||||
for _, line := range lines {
|
||||
line = gstr.Trim(line)
|
||||
line = gstr.TrimLeftStr(line, "require ")
|
||||
line = gstr.Trim(line)
|
||||
// Version 1.
|
||||
match, err := gregex.MatchString(`^github\.com/gogf/gf\s+(.+)$`, line)
|
||||
|
||||
38
cmd/gf/internal/cmd/cmd_z_init_test.go
Normal file
38
cmd/gf/internal/cmd/cmd_z_init_test.go
Normal file
@ -0,0 +1,38 @@
|
||||
// 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)
|
||||
}
|
||||
}
|
||||
151
cmd/gf/internal/cmd/cmd_z_unit_build_test.go
Normal file
151
cmd/gf/internal/cmd/cmd_z_unit_build_test.go
Normal file
@ -0,0 +1,151 @@
|
||||
// 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]interface{}{
|
||||
"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)
|
||||
})
|
||||
}
|
||||
24
cmd/gf/internal/cmd/cmd_z_unit_fix_test.go
Normal file
24
cmd/gf/internal/cmd/cmd_z_unit_fix_test.go
Normal file
@ -0,0 +1,24 @@
|
||||
// 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/test/gtest"
|
||||
)
|
||||
|
||||
func Test_Fix_doFixV25Content(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
var (
|
||||
content = gtest.DataContent(`fix`, `fix25_content.go`)
|
||||
f = cFix{}
|
||||
)
|
||||
_, err := f.doFixV25Content(content)
|
||||
t.AssertNil(err)
|
||||
})
|
||||
}
|
||||
86
cmd/gf/internal/cmd/cmd_z_unit_gen_ctrl_test.go
Normal file
86
cmd/gf/internal/cmd/cmd_z_unit_gen_ctrl_test.go
Normal file
@ -0,0 +1,86 @@
|
||||
// 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/cmd/gf/v2/internal/cmd/genctrl"
|
||||
"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"
|
||||
)
|
||||
|
||||
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)
|
||||
if err != nil {
|
||||
panic(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]))
|
||||
}
|
||||
})
|
||||
}
|
||||
470
cmd/gf/internal/cmd/cmd_z_unit_gen_dao_test.go
Normal file
470
cmd/gf/internal/cmd/cmd_z_unit_gen_dao_test.go
Normal file
@ -0,0 +1,470 @@
|
||||
// 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/cmd/gf/v2/internal/cmd/gendao"
|
||||
"github.com/gogf/gf/v2/database/gdb"
|
||||
"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"
|
||||
)
|
||||
|
||||
func Test_Gen_Dao_Default(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 (
|
||||
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,
|
||||
TypeMapping: nil,
|
||||
}
|
||||
)
|
||||
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 {
|
||||
t.Assert(gfile.GetContents(files[i]), gfile.GetContents(expectFiles[i]))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func Test_Gen_Dao_TypeMapping(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,
|
||||
TypeMapping: map[gendao.DBFieldTypeName]gendao.CustomAttributeType{
|
||||
"int": {
|
||||
Type: "int64",
|
||||
Import: "",
|
||||
},
|
||||
"decimal": {
|
||||
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_type_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 {
|
||||
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_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: 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,
|
||||
TypeMapping: 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, "/dao/internal/user_1.go"), true)
|
||||
t.Assert(gstr.InArray(generatedFiles, "/dao/internal/user_2.go"), true)
|
||||
t.Assert(gstr.InArray(generatedFiles, "/dao/user_1.go"), true)
|
||||
t.Assert(gstr.InArray(generatedFiles, "/dao/user_2.go"), true)
|
||||
t.Assert(gstr.InArray(generatedFiles, "/model/do/user_1.go"), true)
|
||||
t.Assert(gstr.InArray(generatedFiles, "/model/do/user_2.go"), true)
|
||||
t.Assert(gstr.InArray(generatedFiles, "/model/entity/user_1.go"), true)
|
||||
t.Assert(gstr.InArray(generatedFiles, "/model/entity/user_2.go"), true)
|
||||
})
|
||||
}
|
||||
|
||||
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: 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,
|
||||
TypeMapping: 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, "/dao/internal/user_1.go"), true)
|
||||
t.Assert(gstr.InArray(generatedFiles, "/dao/internal/user_2.go"), true)
|
||||
t.Assert(gstr.InArray(generatedFiles, "/dao/user_1.go"), true)
|
||||
t.Assert(gstr.InArray(generatedFiles, "/dao/user_2.go"), true)
|
||||
t.Assert(gstr.InArray(generatedFiles, "/model/do/user_1.go"), true)
|
||||
t.Assert(gstr.InArray(generatedFiles, "/model/do/user_2.go"), true)
|
||||
t.Assert(gstr.InArray(generatedFiles, "/model/entity/user_1.go"), true)
|
||||
t.Assert(gstr.InArray(generatedFiles, "/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,
|
||||
TypeMapping: 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))
|
||||
})
|
||||
}
|
||||
70
cmd/gf/internal/cmd/cmd_z_unit_gen_pbentity_test.go
Normal file
70
cmd/gf/internal/cmd/cmd_z_unit_gen_pbentity_test.go
Normal file
@ -0,0 +1,70 @@
|
||||
// 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"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/gogf/gf/v2/os/gcmd"
|
||||
"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"
|
||||
)
|
||||
|
||||
func Test_Gen_Pbentity_NameCase(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())
|
||||
err = gfile.Mkdir(path)
|
||||
t.AssertNil(err)
|
||||
defer gfile.Remove(path)
|
||||
|
||||
root, err := gcmd.NewFromObject(GF)
|
||||
t.AssertNil(err)
|
||||
err = root.AddObject(
|
||||
Gen,
|
||||
)
|
||||
t.AssertNil(err)
|
||||
os.Args = []string{"gf", "gen", "pbentity", "-l", link, "-p", path, "-package=unittest", "-nameCase=SnakeScreaming"}
|
||||
|
||||
err = root.RunWithError(ctx)
|
||||
t.AssertNil(err)
|
||||
|
||||
files := []string{
|
||||
filepath.FromSlash(path + "/table_user.proto"),
|
||||
}
|
||||
|
||||
testPath := gtest.DataPath("genpbentity", "generated_user")
|
||||
expectFiles := []string{
|
||||
filepath.FromSlash(testPath + "/table_user.proto"),
|
||||
}
|
||||
// check files content
|
||||
for i := range files {
|
||||
t.Assert(gfile.GetContents(files[i]), gfile.GetContents(expectFiles[i]))
|
||||
}
|
||||
})
|
||||
}
|
||||
73
cmd/gf/internal/cmd/cmd_z_unit_gen_service_test.go
Normal file
73
cmd/gf/internal/cmd/cmd_z_unit_gen_service_test.go
Normal file
@ -0,0 +1,73 @@
|
||||
// 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/cmd/gf/v2/internal/cmd/genservice"
|
||||
"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"
|
||||
)
|
||||
|
||||
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")
|
||||
apiFolder = gtest.DataPath("genservice", "logic")
|
||||
in = genservice.CGenServiceInput{
|
||||
SrcFolder: apiFolder,
|
||||
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)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// logic file
|
||||
var (
|
||||
genApi = apiFolder + filepath.FromSlash("/logic.go")
|
||||
genApiExpect = apiFolder + filepath.FromSlash("/logic_expect.go")
|
||||
)
|
||||
defer gfile.Remove(genApi)
|
||||
t.Assert(gfile.GetContents(genApi), gfile.GetContents(genApiExpect))
|
||||
|
||||
// files
|
||||
files, err := gfile.ScanDir(dstFolder, "*.go", true)
|
||||
t.AssertNil(err)
|
||||
t.Assert(files, []string{
|
||||
dstFolder + filepath.FromSlash("/article.go"),
|
||||
})
|
||||
|
||||
// contents
|
||||
testPath := gtest.DataPath("genservice", "service")
|
||||
expectFiles := []string{
|
||||
testPath + filepath.FromSlash("/article.go"),
|
||||
}
|
||||
for i := range files {
|
||||
t.Assert(gfile.GetContents(files[i]), gfile.GetContents(expectFiles[i]))
|
||||
}
|
||||
})
|
||||
}
|
||||
236
cmd/gf/internal/cmd/genctrl/genctrl.go
Normal file
236
cmd/gf/internal/cmd/genctrl/genctrl.go
Normal file
@ -0,0 +1,236 @@
|
||||
// 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 (
|
||||
"context"
|
||||
|
||||
"github.com/gogf/gf/v2/container/gset"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gfile"
|
||||
"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/gtag"
|
||||
|
||||
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
|
||||
)
|
||||
|
||||
const (
|
||||
CGenCtrlConfig = `gfcli.gen.ctrl`
|
||||
CGenCtrlUsage = `gf gen ctrl [OPTION]`
|
||||
CGenCtrlBrief = `parse api definitions to generate controller/sdk go files`
|
||||
CGenCtrlEg = `
|
||||
gf gen ctrl
|
||||
`
|
||||
CGenCtrlBriefSrcFolder = `source folder path to be parsed. default: api`
|
||||
CGenCtrlBriefDstFolder = `destination folder path storing automatically generated go files. default: internal/controller`
|
||||
CGenCtrlBriefWatchFile = `used in file watcher, it re-generates go files only if given file is under srcFolder`
|
||||
CGenCtrlBriefSdkPath = `also generate SDK go files for api definitions to specified directory`
|
||||
CGenCtrlBriefSdkStdVersion = `use standard version prefix for generated sdk request path`
|
||||
CGenCtrlBriefSdkNoV1 = `do not add version suffix for interface module name if version is v1`
|
||||
CGenCtrlBriefClear = `auto delete generated and unimplemented controller go files if api definitions are missing`
|
||||
CGenCtrlControllerMerge = `generate all controller files into one go file by name of api definition source go file`
|
||||
)
|
||||
|
||||
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+{`
|
||||
)
|
||||
|
||||
const (
|
||||
genCtrlFileLockSeconds = 10
|
||||
)
|
||||
|
||||
func init() {
|
||||
gtag.Sets(g.MapStrStr{
|
||||
`CGenCtrlConfig`: CGenCtrlConfig,
|
||||
`CGenCtrlUsage`: CGenCtrlUsage,
|
||||
`CGenCtrlBrief`: CGenCtrlBrief,
|
||||
`CGenCtrlEg`: CGenCtrlEg,
|
||||
`CGenCtrlBriefSrcFolder`: CGenCtrlBriefSrcFolder,
|
||||
`CGenCtrlBriefDstFolder`: CGenCtrlBriefDstFolder,
|
||||
`CGenCtrlBriefWatchFile`: CGenCtrlBriefWatchFile,
|
||||
`CGenCtrlBriefSdkPath`: CGenCtrlBriefSdkPath,
|
||||
`CGenCtrlBriefSdkStdVersion`: CGenCtrlBriefSdkStdVersion,
|
||||
`CGenCtrlBriefSdkNoV1`: CGenCtrlBriefSdkNoV1,
|
||||
`CGenCtrlBriefClear`: CGenCtrlBriefClear,
|
||||
`CGenCtrlControllerMerge`: CGenCtrlControllerMerge,
|
||||
})
|
||||
}
|
||||
|
||||
type (
|
||||
CGenCtrl struct{}
|
||||
CGenCtrlInput struct {
|
||||
g.Meta `name:"ctrl" config:"{CGenCtrlConfig}" usage:"{CGenCtrlUsage}" brief:"{CGenCtrlBrief}" eg:"{CGenCtrlEg}"`
|
||||
SrcFolder string `short:"s" name:"srcFolder" brief:"{CGenCtrlBriefSrcFolder}" d:"api"`
|
||||
DstFolder string `short:"d" name:"dstFolder" brief:"{CGenCtrlBriefDstFolder}" d:"internal/controller"`
|
||||
WatchFile string `short:"w" name:"watchFile" brief:"{CGenCtrlBriefWatchFile}"`
|
||||
SdkPath string `short:"k" name:"sdkPath" brief:"{CGenCtrlBriefSdkPath}"`
|
||||
SdkStdVersion bool `short:"v" name:"sdkStdVersion" brief:"{CGenCtrlBriefSdkStdVersion}" orphan:"true"`
|
||||
SdkNoV1 bool `short:"n" name:"sdkNoV1" brief:"{CGenCtrlBriefSdkNoV1}" orphan:"true"`
|
||||
Clear bool `short:"c" name:"clear" brief:"{CGenCtrlBriefClear}" orphan:"true"`
|
||||
Merge bool `short:"m" name:"merge" brief:"{CGenCtrlControllerMerge}" orphan:"true"`
|
||||
}
|
||||
CGenCtrlOutput struct{}
|
||||
)
|
||||
|
||||
func (c CGenCtrl) Ctrl(ctx context.Context, in CGenCtrlInput) (out *CGenCtrlOutput, err error) {
|
||||
if in.WatchFile != "" {
|
||||
err = c.generateByWatchFile(
|
||||
in.WatchFile, in.SdkPath, in.SdkStdVersion, in.SdkNoV1, in.Clear, in.Merge,
|
||||
)
|
||||
mlog.Print(`done!`)
|
||||
return
|
||||
}
|
||||
|
||||
if !gfile.Exists(in.SrcFolder) {
|
||||
mlog.Fatalf(`source folder path "%s" does not exist`, in.SrcFolder)
|
||||
}
|
||||
// retrieve all api modules.
|
||||
apiModuleFolderPaths, err := gfile.ScanDir(in.SrcFolder, "*", false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, apiModuleFolderPath := range apiModuleFolderPaths {
|
||||
if !gfile.IsDir(apiModuleFolderPath) {
|
||||
continue
|
||||
}
|
||||
// generate go files by api module.
|
||||
var (
|
||||
module = gfile.Basename(apiModuleFolderPath)
|
||||
dstModuleFolderPath = gfile.Join(in.DstFolder, module)
|
||||
)
|
||||
err = c.generateByModule(
|
||||
apiModuleFolderPath, dstModuleFolderPath, in.SdkPath,
|
||||
in.SdkStdVersion, in.SdkNoV1, in.Clear, in.Merge,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
mlog.Print(`done!`)
|
||||
return
|
||||
}
|
||||
|
||||
func (c CGenCtrl) generateByWatchFile(watchFile, sdkPath string, sdkStdVersion, sdkNoV1, clear, merge bool) (err error) {
|
||||
// File lock to avoid multiple processes.
|
||||
var (
|
||||
flockFilePath = gfile.Temp("gf.cli.gen.service.lock")
|
||||
flockContent = gfile.GetContents(flockFilePath)
|
||||
)
|
||||
if flockContent != "" {
|
||||
if gtime.Timestamp()-gconv.Int64(flockContent) < genCtrlFileLockSeconds {
|
||||
// If another generating process is running, it just exits.
|
||||
mlog.Debug(`another "gen service" process is running, exit`)
|
||||
return
|
||||
}
|
||||
}
|
||||
defer gfile.Remove(flockFilePath)
|
||||
_ = gfile.PutContents(flockFilePath, gtime.TimestampStr())
|
||||
|
||||
// check this updated file is an api file.
|
||||
// watch file should be in standard goframe project structure.
|
||||
var (
|
||||
apiVersionPath = gfile.Dir(watchFile)
|
||||
apiModuleFolderPath = gfile.Dir(apiVersionPath)
|
||||
shouldBeNameOfAPi = gfile.Basename(gfile.Dir(apiModuleFolderPath))
|
||||
)
|
||||
if shouldBeNameOfAPi != "api" {
|
||||
return nil
|
||||
}
|
||||
// watch file should have api definitions.
|
||||
if gfile.Exists(watchFile) {
|
||||
if !gregex.IsMatchString(PatternApiDefinition, gfile.GetContents(watchFile)) {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
projectRootPath = gfile.Dir(gfile.Dir(apiModuleFolderPath))
|
||||
module = gfile.Basename(apiModuleFolderPath)
|
||||
dstModuleFolderPath = gfile.Join(projectRootPath, "internal", "controller", module)
|
||||
)
|
||||
return c.generateByModule(
|
||||
apiModuleFolderPath, dstModuleFolderPath, sdkPath, sdkStdVersion, sdkNoV1, clear, merge,
|
||||
)
|
||||
}
|
||||
|
||||
// parseApiModule parses certain api and generate associated go files by certain module, not all api modules.
|
||||
func (c CGenCtrl) generateByModule(
|
||||
apiModuleFolderPath, dstModuleFolderPath, sdkPath string,
|
||||
sdkStdVersion, sdkNoV1, clear, merge bool,
|
||||
) (err error) {
|
||||
// parse src and dst folder go files.
|
||||
apiItemsInSrc, err := c.getApiItemsInSrc(apiModuleFolderPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
apiItemsInDst, err := c.getApiItemsInDst(dstModuleFolderPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// generate api interface go files.
|
||||
if err = newApiInterfaceGenerator().Generate(apiModuleFolderPath, apiItemsInSrc); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// generate controller go files.
|
||||
// api filtering for already implemented api controllers.
|
||||
var (
|
||||
alreadyImplementedCtrlSet = gset.NewStrSet()
|
||||
toBeImplementedApiItems = make([]apiItem, 0)
|
||||
)
|
||||
for _, item := range apiItemsInDst {
|
||||
alreadyImplementedCtrlSet.Add(item.String())
|
||||
}
|
||||
for _, item := range apiItemsInSrc {
|
||||
if alreadyImplementedCtrlSet.Contains(item.String()) {
|
||||
continue
|
||||
}
|
||||
toBeImplementedApiItems = append(toBeImplementedApiItems, item)
|
||||
}
|
||||
if len(toBeImplementedApiItems) > 0 {
|
||||
err = newControllerGenerator().Generate(dstModuleFolderPath, toBeImplementedApiItems, merge)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// delete unimplemented controllers if api definitions are missing.
|
||||
if clear {
|
||||
var (
|
||||
apiDefinitionSet = gset.NewStrSet()
|
||||
extraApiItemsInCtrl = make([]apiItem, 0)
|
||||
)
|
||||
for _, item := range apiItemsInSrc {
|
||||
apiDefinitionSet.Add(item.String())
|
||||
}
|
||||
for _, item := range apiItemsInDst {
|
||||
if apiDefinitionSet.Contains(item.String()) {
|
||||
continue
|
||||
}
|
||||
extraApiItemsInCtrl = append(extraApiItemsInCtrl, item)
|
||||
}
|
||||
if len(extraApiItemsInCtrl) > 0 {
|
||||
err = newControllerClearer().Clear(dstModuleFolderPath, extraApiItemsInCtrl)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// generate sdk go files.
|
||||
if sdkPath != "" {
|
||||
if err = newApiSdkGenerator().Generate(apiItemsInSrc, sdkPath, sdkStdVersion, sdkNoV1); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
23
cmd/gf/internal/cmd/genctrl/genctrl_api_item.go
Normal file
23
cmd/gf/internal/cmd/genctrl/genctrl_api_item.go
Normal file
@ -0,0 +1,23 @@
|
||||
// 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 "github.com/gogf/gf/v2/text/gstr"
|
||||
|
||||
type apiItem struct {
|
||||
Import string `eg:"demo.com/api/user/v1"`
|
||||
FileName string `eg:"user"`
|
||||
Module string `eg:"user"`
|
||||
Version string `eg:"v1"`
|
||||
MethodName string `eg:"GetList"`
|
||||
}
|
||||
|
||||
func (a apiItem) String() string {
|
||||
return gstr.Join([]string{
|
||||
a.Import, a.Module, a.Version, a.MethodName,
|
||||
}, ",")
|
||||
}
|
||||
145
cmd/gf/internal/cmd/genctrl/genctrl_calculate.go
Normal file
145
cmd/gf/internal/cmd/genctrl/genctrl_calculate.go
Normal file
@ -0,0 +1,145 @@
|
||||
// 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 (
|
||||
"github.com/gogf/gf/cmd/gf/v2/internal/utility/utils"
|
||||
"github.com/gogf/gf/v2/os/gfile"
|
||||
"github.com/gogf/gf/v2/text/gregex"
|
||||
"github.com/gogf/gf/v2/text/gstr"
|
||||
)
|
||||
|
||||
func (c CGenCtrl) getApiItemsInSrc(apiModuleFolderPath string) (items []apiItem, err error) {
|
||||
var (
|
||||
fileContent string
|
||||
importPath string
|
||||
)
|
||||
// The second level folders: versions.
|
||||
apiVersionFolderPaths, err := gfile.ScanDir(apiModuleFolderPath, "*", false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, apiVersionFolderPath := range apiVersionFolderPaths {
|
||||
if !gfile.IsDir(apiVersionFolderPath) {
|
||||
continue
|
||||
}
|
||||
// The second level folders: versions.
|
||||
apiFileFolderPaths, err := gfile.ScanDir(apiVersionFolderPath, "*.go", false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
importPath = utils.GetImportPath(apiVersionFolderPath)
|
||||
for _, apiFileFolderPath := range apiFileFolderPaths {
|
||||
if gfile.IsDir(apiFileFolderPath) {
|
||||
continue
|
||||
}
|
||||
fileContent = gfile.GetContents(apiFileFolderPath)
|
||||
matches, err := gregex.MatchAllString(PatternApiDefinition, fileContent)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, match := range matches {
|
||||
var (
|
||||
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{
|
||||
Import: gstr.Trim(importPath, `"`),
|
||||
FileName: gfile.Name(apiFileFolderPath),
|
||||
Module: gfile.Basename(apiModuleFolderPath),
|
||||
Version: gfile.Basename(apiVersionFolderPath),
|
||||
MethodName: methodName,
|
||||
}
|
||||
items = append(items, item)
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (c CGenCtrl) getApiItemsInDst(dstFolder string) (items []apiItem, err error) {
|
||||
if !gfile.Exists(dstFolder) {
|
||||
return nil, nil
|
||||
}
|
||||
type importItem struct {
|
||||
Path string
|
||||
Alias string
|
||||
}
|
||||
var fileContent string
|
||||
filePaths, err := gfile.ScanDir(dstFolder, "*.go", true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, filePath := range filePaths {
|
||||
fileContent = gfile.GetContents(filePath)
|
||||
match, err := gregex.MatchString(`import\s+\(([\s\S]+?)\)`, fileContent)
|
||||
if err != nil {
|
||||
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.
|
||||
for _, importLine := range importLines {
|
||||
array = gstr.SplitAndTrim(importLine, " ")
|
||||
if len(array) == 2 {
|
||||
importItems = append(importItems, importItem{
|
||||
Path: gstr.Trim(array[1], `"`),
|
||||
Alias: array[0],
|
||||
})
|
||||
} else {
|
||||
importItems = append(importItems, importItem{
|
||||
Path: gstr.Trim(array[0], `"`),
|
||||
})
|
||||
}
|
||||
}
|
||||
// retrieve all api usages.
|
||||
matches, err := gregex.MatchAllString(PatternCtrlDefinition, fileContent)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, match = range matches {
|
||||
// try to find the import path of the api.
|
||||
var (
|
||||
importPath string
|
||||
version = match[1]
|
||||
methodName = match[2] // not the function name, but the method name in api definition.
|
||||
)
|
||||
for _, item := range importItems {
|
||||
if item.Alias != "" {
|
||||
if item.Alias == version {
|
||||
importPath = item.Path
|
||||
break
|
||||
}
|
||||
continue
|
||||
}
|
||||
if gfile.Basename(item.Path) == version {
|
||||
importPath = item.Path
|
||||
break
|
||||
}
|
||||
}
|
||||
item := apiItem{
|
||||
Import: gstr.Trim(importPath, `"`),
|
||||
Module: module,
|
||||
Version: gfile.Basename(importPath),
|
||||
MethodName: methodName,
|
||||
}
|
||||
items = append(items, item)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
164
cmd/gf/internal/cmd/genctrl/genctrl_generate_ctrl.go
Normal file
164
cmd/gf/internal/cmd/genctrl/genctrl_generate_ctrl.go
Normal file
@ -0,0 +1,164 @@
|
||||
// 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 (
|
||||
"fmt"
|
||||
"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/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gfile"
|
||||
"github.com/gogf/gf/v2/text/gstr"
|
||||
)
|
||||
|
||||
type controllerGenerator struct{}
|
||||
|
||||
func newControllerGenerator() *controllerGenerator {
|
||||
return &controllerGenerator{}
|
||||
}
|
||||
|
||||
func (c *controllerGenerator) Generate(dstModuleFolderPath string, apiModuleApiItems []apiItem, merge bool) (err error) {
|
||||
var (
|
||||
doneApiItemSet = gset.NewStrSet()
|
||||
)
|
||||
for _, item := range apiModuleApiItems {
|
||||
if doneApiItemSet.Contains(item.String()) {
|
||||
continue
|
||||
}
|
||||
// retrieve all api items of the same module.
|
||||
var (
|
||||
subItems = c.getSubItemsByModuleAndVersion(apiModuleApiItems, item.Module, item.Version)
|
||||
importPath = gstr.Replace(gfile.Dir(item.Import), "\\", "/", -1)
|
||||
)
|
||||
if err = c.doGenerateCtrlNewByModuleAndVersion(
|
||||
dstModuleFolderPath, item.Module, item.Version, importPath,
|
||||
); err != nil {
|
||||
return
|
||||
}
|
||||
for _, subItem := range subItems {
|
||||
if err = c.doGenerateCtrlItem(dstModuleFolderPath, subItem, merge); err != nil {
|
||||
return
|
||||
}
|
||||
doneApiItemSet.Add(subItem.String())
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (c *controllerGenerator) getSubItemsByModuleAndVersion(items []apiItem, module, version string) (subItems []apiItem) {
|
||||
for _, item := range items {
|
||||
if item.Module == module && item.Version == version {
|
||||
subItems = append(subItems, item)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (c *controllerGenerator) doGenerateCtrlNewByModuleAndVersion(
|
||||
dstModuleFolderPath, module, version, importPath string,
|
||||
) (err error) {
|
||||
var (
|
||||
moduleFilePath = filepath.FromSlash(gfile.Join(dstModuleFolderPath, module+".go"))
|
||||
moduleFilePathNew = filepath.FromSlash(gfile.Join(dstModuleFolderPath, module+"_new.go"))
|
||||
ctrlName = fmt.Sprintf(`Controller%s`, gstr.UcFirst(version))
|
||||
interfaceName = fmt.Sprintf(`%s.I%s%s`, module, gstr.CaseCamel(module), gstr.UcFirst(version))
|
||||
newFuncName = fmt.Sprintf(`New%s`, gstr.UcFirst(version))
|
||||
newFuncNameDefinition = fmt.Sprintf(`func %s()`, newFuncName)
|
||||
alreadyCreated bool
|
||||
)
|
||||
if !gfile.Exists(moduleFilePath) {
|
||||
content := gstr.ReplaceByMap(consts.TemplateGenCtrlControllerEmpty, g.MapStrStr{
|
||||
"{Module}": module,
|
||||
})
|
||||
if err = gfile.PutContents(moduleFilePath, gstr.TrimLeft(content)); err != nil {
|
||||
return err
|
||||
}
|
||||
mlog.Printf(`generated: %s`, moduleFilePath)
|
||||
}
|
||||
if !gfile.Exists(moduleFilePathNew) {
|
||||
content := gstr.ReplaceByMap(consts.TemplateGenCtrlControllerNewEmpty, g.MapStrStr{
|
||||
"{Module}": module,
|
||||
"{ImportPath}": fmt.Sprintf(`"%s"`, importPath),
|
||||
})
|
||||
if err = gfile.PutContents(moduleFilePathNew, gstr.TrimLeft(content)); err != nil {
|
||||
return err
|
||||
}
|
||||
mlog.Printf(`generated: %s`, moduleFilePathNew)
|
||||
}
|
||||
filePaths, err := gfile.ScanDir(dstModuleFolderPath, "*.go", false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, filePath := range filePaths {
|
||||
if gstr.Contains(gfile.GetContents(filePath), newFuncNameDefinition) {
|
||||
alreadyCreated = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !alreadyCreated {
|
||||
content := gstr.ReplaceByMap(consts.TemplateGenCtrlControllerNewFunc, g.MapStrStr{
|
||||
"{CtrlName}": ctrlName,
|
||||
"{NewFuncName}": newFuncName,
|
||||
"{InterfaceName}": interfaceName,
|
||||
})
|
||||
err = gfile.PutContentsAppend(moduleFilePathNew, content)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (c *controllerGenerator) doGenerateCtrlItem(dstModuleFolderPath string, item apiItem, merge bool) (err error) {
|
||||
var (
|
||||
methodNameSnake = gstr.CaseSnake(item.MethodName)
|
||||
ctrlName = fmt.Sprintf(`Controller%s`, gstr.UcFirst(item.Version))
|
||||
methodFilePath = filepath.FromSlash(gfile.Join(dstModuleFolderPath, fmt.Sprintf(
|
||||
`%s_%s_%s.go`, item.Module, item.Version, methodNameSnake,
|
||||
)))
|
||||
)
|
||||
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) {
|
||||
content = gstr.ReplaceByMap(consts.TemplateGenCtrlControllerMethodFuncMerge, g.MapStrStr{
|
||||
"{Module}": item.Module,
|
||||
"{CtrlName}": ctrlName,
|
||||
"{Version}": item.Version,
|
||||
"{MethodName}": item.MethodName,
|
||||
})
|
||||
|
||||
if gstr.Contains(gfile.GetContents(methodFilePath), fmt.Sprintf(`func (c *%v) %v`, ctrlName, item.MethodName)) {
|
||||
return
|
||||
}
|
||||
if err = gfile.PutContentsAppend(methodFilePath, gstr.TrimLeft(content)); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
content = gstr.ReplaceByMap(consts.TemplateGenCtrlControllerMethodFunc, g.MapStrStr{
|
||||
"{Module}": item.Module,
|
||||
"{ImportPath}": item.Import,
|
||||
"{CtrlName}": ctrlName,
|
||||
"{Version}": item.Version,
|
||||
"{MethodName}": item.MethodName,
|
||||
})
|
||||
if err = gfile.PutContents(methodFilePath, gstr.TrimLeft(content)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
mlog.Printf(`generated: %s`, methodFilePath)
|
||||
return
|
||||
}
|
||||
57
cmd/gf/internal/cmd/genctrl/genctrl_generate_ctrl_clear.go
Normal file
57
cmd/gf/internal/cmd/genctrl/genctrl_generate_ctrl_clear.go
Normal file
@ -0,0 +1,57 @@
|
||||
// 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 (
|
||||
"fmt"
|
||||
|
||||
"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{}
|
||||
|
||||
func newControllerClearer() *controllerClearer {
|
||||
return &controllerClearer{}
|
||||
}
|
||||
|
||||
func (c *controllerClearer) Clear(dstModuleFolderPath string, extraApiItemsInCtrl []apiItem) (err error) {
|
||||
for _, item := range extraApiItemsInCtrl {
|
||||
if err = c.doClear(dstModuleFolderPath, item); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (c *controllerClearer) doClear(dstModuleFolderPath string, item apiItem) (err error) {
|
||||
var (
|
||||
methodNameSnake = gstr.CaseSnake(item.MethodName)
|
||||
methodFilePath = gfile.Join(dstModuleFolderPath, fmt.Sprintf(
|
||||
`%s_%s_%s.go`, item.Module, item.Version, methodNameSnake,
|
||||
))
|
||||
fileContent = gstr.Trim(gfile.GetContents(methodFilePath))
|
||||
)
|
||||
match, err := gregex.MatchString(`.+?Req.+?Res.+?{([\s\S]+?)}`, fileContent)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(match) > 1 {
|
||||
implements := gstr.Trim(match[1])
|
||||
// One line.
|
||||
if !gstr.Contains(implements, "\n") && gstr.Contains(implements, `CodeNotImplemented`) {
|
||||
mlog.Printf(
|
||||
`remove unimplemented and of no api definitions controller file: %s`,
|
||||
methodFilePath,
|
||||
)
|
||||
err = gfile.Remove(methodFilePath)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
117
cmd/gf/internal/cmd/genctrl/genctrl_generate_interface.go
Normal file
117
cmd/gf/internal/cmd/genctrl/genctrl_generate_interface.go
Normal file
@ -0,0 +1,117 @@
|
||||
// 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 (
|
||||
"fmt"
|
||||
"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/gset"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gfile"
|
||||
"github.com/gogf/gf/v2/text/gstr"
|
||||
"github.com/gogf/gf/v2/util/gconv"
|
||||
)
|
||||
|
||||
type apiInterfaceGenerator struct{}
|
||||
|
||||
func newApiInterfaceGenerator() *apiInterfaceGenerator {
|
||||
return &apiInterfaceGenerator{}
|
||||
}
|
||||
|
||||
func (c *apiInterfaceGenerator) Generate(apiModuleFolderPath string, apiModuleApiItems []apiItem) (err error) {
|
||||
if len(apiModuleApiItems) == 0 {
|
||||
return nil
|
||||
}
|
||||
var firstApiItem = apiModuleApiItems[0]
|
||||
if err = c.doGenerate(apiModuleFolderPath, firstApiItem.Module, apiModuleApiItems); err != nil {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (c *apiInterfaceGenerator) doGenerate(apiModuleFolderPath string, module string, items []apiItem) (err error) {
|
||||
var (
|
||||
moduleFilePath = filepath.FromSlash(gfile.Join(apiModuleFolderPath, fmt.Sprintf(`%s.go`, module)))
|
||||
importPathMap = gmap.NewListMap()
|
||||
importPaths []string
|
||||
)
|
||||
// if there's already exist file that with the same but not auto generated go file,
|
||||
// it uses another file name.
|
||||
if !utils.IsFileDoNotEdit(moduleFilePath) {
|
||||
moduleFilePath = filepath.FromSlash(gfile.Join(apiModuleFolderPath, fmt.Sprintf(`%s.if.go`, module)))
|
||||
}
|
||||
// all import paths.
|
||||
importPathMap.Set("\t"+`"context"`+"\n", 1)
|
||||
for _, item := range items {
|
||||
importPathMap.Set(fmt.Sprintf("\t"+`"%s"`, item.Import), 1)
|
||||
}
|
||||
importPaths = gconv.Strings(importPathMap.Keys())
|
||||
// interface definitions.
|
||||
var (
|
||||
doneApiItemSet = gset.NewStrSet()
|
||||
interfaceDefinition string
|
||||
interfaceContent = gstr.TrimLeft(gstr.ReplaceByMap(consts.TemplateGenCtrlApiInterface, g.MapStrStr{
|
||||
"{Module}": module,
|
||||
"{ImportPaths}": gstr.Join(importPaths, "\n"),
|
||||
}))
|
||||
)
|
||||
for _, item := range items {
|
||||
if doneApiItemSet.Contains(item.String()) {
|
||||
continue
|
||||
}
|
||||
// retrieve all api items of the same module.
|
||||
subItems := c.getSubItemsByModuleAndVersion(items, item.Module, item.Version)
|
||||
var (
|
||||
method string
|
||||
methods = make([]string, 0)
|
||||
interfaceName = fmt.Sprintf(`I%s%s`, gstr.CaseCamel(item.Module), gstr.UcFirst(item.Version))
|
||||
)
|
||||
for _, subItem := range subItems {
|
||||
method = fmt.Sprintf(
|
||||
"\t%s(ctx context.Context, req *%s.%sReq) (res *%s.%sRes, err error)",
|
||||
subItem.MethodName, subItem.Version, subItem.MethodName, subItem.Version, subItem.MethodName,
|
||||
)
|
||||
methods = append(methods, method)
|
||||
doneApiItemSet.Add(subItem.String())
|
||||
}
|
||||
interfaceDefinition += fmt.Sprintf("type %s interface {", interfaceName)
|
||||
interfaceDefinition += "\n"
|
||||
interfaceDefinition += gstr.Join(methods, "\n")
|
||||
interfaceDefinition += "\n"
|
||||
interfaceDefinition += fmt.Sprintf("}")
|
||||
interfaceDefinition += "\n\n"
|
||||
}
|
||||
interfaceContent = gstr.TrimLeft(gstr.ReplaceByMap(interfaceContent, g.MapStrStr{
|
||||
"{Interfaces}": gstr.TrimRightStr(interfaceDefinition, "\n", 2),
|
||||
}))
|
||||
err = gfile.PutContents(moduleFilePath, interfaceContent)
|
||||
mlog.Printf(`generated: %s`, moduleFilePath)
|
||||
return
|
||||
}
|
||||
|
||||
func (c *apiInterfaceGenerator) getSubItemsByModule(items []apiItem, module string) (subItems []apiItem) {
|
||||
for _, item := range items {
|
||||
if item.Module == module {
|
||||
subItems = append(subItems, item)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (c *apiInterfaceGenerator) getSubItemsByModuleAndVersion(items []apiItem, module, version string) (subItems []apiItem) {
|
||||
for _, item := range items {
|
||||
if item.Module == module && item.Version == version {
|
||||
subItems = append(subItems, item)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
195
cmd/gf/internal/cmd/genctrl/genctrl_generate_sdk.go
Normal file
195
cmd/gf/internal/cmd/genctrl/genctrl_generate_sdk.go
Normal file
@ -0,0 +1,195 @@
|
||||
// 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 (
|
||||
"fmt"
|
||||
"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/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gfile"
|
||||
"github.com/gogf/gf/v2/text/gregex"
|
||||
"github.com/gogf/gf/v2/text/gstr"
|
||||
)
|
||||
|
||||
type apiSdkGenerator struct{}
|
||||
|
||||
func newApiSdkGenerator() *apiSdkGenerator {
|
||||
return &apiSdkGenerator{}
|
||||
}
|
||||
|
||||
func (c *apiSdkGenerator) Generate(apiModuleApiItems []apiItem, sdkFolderPath string, sdkStdVersion, sdkNoV1 bool) (err error) {
|
||||
if err = c.doGenerateSdkPkgFile(sdkFolderPath); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
var doneApiItemSet = gset.NewStrSet()
|
||||
for _, item := range apiModuleApiItems {
|
||||
if doneApiItemSet.Contains(item.String()) {
|
||||
continue
|
||||
}
|
||||
// retrieve all api items of the same module.
|
||||
subItems := c.getSubItemsByModuleAndVersion(apiModuleApiItems, item.Module, item.Version)
|
||||
if err = c.doGenerateSdkIClient(sdkFolderPath, item.Import, item.Module, item.Version, sdkNoV1); err != nil {
|
||||
return
|
||||
}
|
||||
if err = c.doGenerateSdkImplementer(
|
||||
subItems, sdkFolderPath, item.Import, item.Module, item.Version, sdkStdVersion, sdkNoV1,
|
||||
); err != nil {
|
||||
return
|
||||
}
|
||||
for _, subItem := range subItems {
|
||||
doneApiItemSet.Add(subItem.String())
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (c *apiSdkGenerator) doGenerateSdkPkgFile(sdkFolderPath string) (err error) {
|
||||
var (
|
||||
pkgName = gfile.Basename(sdkFolderPath)
|
||||
pkgFilePath = filepath.FromSlash(gfile.Join(sdkFolderPath, fmt.Sprintf(`%s.go`, pkgName)))
|
||||
fileContent string
|
||||
)
|
||||
if gfile.Exists(pkgFilePath) {
|
||||
return nil
|
||||
}
|
||||
fileContent = gstr.TrimLeft(gstr.ReplaceByMap(consts.TemplateGenCtrlSdkPkgNew, g.MapStrStr{
|
||||
"{PkgName}": pkgName,
|
||||
}))
|
||||
err = gfile.PutContents(pkgFilePath, fileContent)
|
||||
mlog.Printf(`generated: %s`, pkgFilePath)
|
||||
return
|
||||
}
|
||||
|
||||
func (c *apiSdkGenerator) doGenerateSdkIClient(
|
||||
sdkFolderPath, versionImportPath, module, version string, sdkNoV1 bool,
|
||||
) (err error) {
|
||||
var (
|
||||
fileContent string
|
||||
isDirty bool
|
||||
isExist bool
|
||||
pkgName = gfile.Basename(sdkFolderPath)
|
||||
funcName = gstr.CaseCamel(module) + gstr.UcFirst(version)
|
||||
interfaceName = fmt.Sprintf(`I%s`, funcName)
|
||||
moduleImportPath = gstr.Replace(fmt.Sprintf(`"%s"`, gfile.Dir(versionImportPath)), "\\", "/", -1)
|
||||
iClientFilePath = filepath.FromSlash(gfile.Join(sdkFolderPath, fmt.Sprintf(`%s.iclient.go`, pkgName)))
|
||||
interfaceFuncDefinition = fmt.Sprintf(
|
||||
`%s() %s.%s`,
|
||||
gstr.CaseCamel(module)+gstr.UcFirst(version), module, interfaceName,
|
||||
)
|
||||
)
|
||||
if sdkNoV1 && version == "v1" {
|
||||
interfaceFuncDefinition = fmt.Sprintf(
|
||||
`%s() %s.%s`,
|
||||
gstr.CaseCamel(module), module, interfaceName,
|
||||
)
|
||||
}
|
||||
if isExist = gfile.Exists(iClientFilePath); isExist {
|
||||
fileContent = gfile.GetContents(iClientFilePath)
|
||||
} else {
|
||||
fileContent = gstr.TrimLeft(gstr.ReplaceByMap(consts.TemplateGenCtrlSdkIClient, g.MapStrStr{
|
||||
"{PkgName}": pkgName,
|
||||
}))
|
||||
}
|
||||
|
||||
// append the import path to current import paths.
|
||||
if !gstr.Contains(fileContent, moduleImportPath) {
|
||||
isDirty = true
|
||||
fileContent, err = gregex.ReplaceString(
|
||||
`(import \([\s\S]*?)\)`,
|
||||
fmt.Sprintf("$1\t%s\n)", moduleImportPath),
|
||||
fileContent,
|
||||
)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// append the function definition to interface definition.
|
||||
if !gstr.Contains(fileContent, interfaceFuncDefinition) {
|
||||
isDirty = true
|
||||
fileContent, err = gregex.ReplaceString(
|
||||
`(type IClient interface {[\s\S]*?)}`,
|
||||
fmt.Sprintf("$1\t%s\n}", interfaceFuncDefinition),
|
||||
fileContent,
|
||||
)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
if isDirty {
|
||||
err = gfile.PutContents(iClientFilePath, fileContent)
|
||||
if isExist {
|
||||
mlog.Printf(`updated: %s`, iClientFilePath)
|
||||
} else {
|
||||
mlog.Printf(`generated: %s`, iClientFilePath)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (c *apiSdkGenerator) doGenerateSdkImplementer(
|
||||
items []apiItem, sdkFolderPath, versionImportPath, module, version string, sdkStdVersion, sdkNoV1 bool,
|
||||
) (err error) {
|
||||
var (
|
||||
pkgName = gfile.Basename(sdkFolderPath)
|
||||
moduleNameCamel = gstr.CaseCamel(module)
|
||||
moduleNameSnake = gstr.CaseSnake(module)
|
||||
moduleImportPath = gstr.Replace(gfile.Dir(versionImportPath), "\\", "/", -1)
|
||||
versionPrefix = ""
|
||||
implementerName = moduleNameCamel + gstr.UcFirst(version)
|
||||
implementerFilePath = filepath.FromSlash(gfile.Join(sdkFolderPath, fmt.Sprintf(
|
||||
`%s_%s_%s.go`, pkgName, moduleNameSnake, version,
|
||||
)))
|
||||
)
|
||||
if sdkNoV1 && version == "v1" {
|
||||
implementerName = moduleNameCamel
|
||||
}
|
||||
// implementer file template.
|
||||
var importPaths = make([]string, 0)
|
||||
importPaths = append(importPaths, fmt.Sprintf("\t\"%s\"", moduleImportPath))
|
||||
importPaths = append(importPaths, fmt.Sprintf("\t\"%s\"", versionImportPath))
|
||||
implementerFileContent := gstr.TrimLeft(gstr.ReplaceByMap(consts.TemplateGenCtrlSdkImplementer, g.MapStrStr{
|
||||
"{PkgName}": pkgName,
|
||||
"{ImportPaths}": gstr.Join(importPaths, "\n"),
|
||||
"{ImplementerName}": implementerName,
|
||||
}))
|
||||
// implementer new function definition.
|
||||
if sdkStdVersion {
|
||||
versionPrefix = fmt.Sprintf(`/api/%s`, version)
|
||||
}
|
||||
implementerFileContent += gstr.TrimLeft(gstr.ReplaceByMap(consts.TemplateGenCtrlSdkImplementerNew, g.MapStrStr{
|
||||
"{Module}": module,
|
||||
"{VersionPrefix}": versionPrefix,
|
||||
"{ImplementerName}": implementerName,
|
||||
}))
|
||||
// implementer functions definitions.
|
||||
for _, item := range items {
|
||||
implementerFileContent += gstr.TrimLeft(gstr.ReplaceByMap(consts.TemplateGenCtrlSdkImplementerFunc, g.MapStrStr{
|
||||
"{Version}": item.Version,
|
||||
"{MethodName}": item.MethodName,
|
||||
"{ImplementerName}": implementerName,
|
||||
}))
|
||||
implementerFileContent += "\n"
|
||||
}
|
||||
err = gfile.PutContents(implementerFilePath, implementerFileContent)
|
||||
mlog.Printf(`generated: %s`, implementerFilePath)
|
||||
return
|
||||
}
|
||||
|
||||
func (c *apiSdkGenerator) getSubItemsByModuleAndVersion(items []apiItem, module, version string) (subItems []apiItem) {
|
||||
for _, item := range items {
|
||||
if item.Module == module && item.Version == version {
|
||||
subItems = append(subItems, item)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
@ -11,12 +11,15 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/mod/modfile"
|
||||
|
||||
"github.com/gogf/gf/cmd/gf/v2/internal/utility/utils"
|
||||
"github.com/gogf/gf/v2/container/garray"
|
||||
"github.com/gogf/gf/v2/database/gdb"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gfile"
|
||||
"github.com/gogf/gf/v2/os/gproc"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
"github.com/gogf/gf/v2/text/gregex"
|
||||
"github.com/gogf/gf/v2/text/gstr"
|
||||
"github.com/gogf/gf/v2/util/gtag"
|
||||
|
||||
@ -49,28 +52,36 @@ CONFIGURATION SUPPORT
|
||||
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`
|
||||
CGenDaoBriefGroup = `
|
||||
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`
|
||||
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"
|
||||
`
|
||||
@ -105,7 +116,21 @@ generated json tag case for model struct, cases are as follows:
|
||||
)
|
||||
|
||||
var (
|
||||
createdAt = gtime.Now()
|
||||
createdAt = gtime.Now()
|
||||
defaultTypeMapping = map[DBFieldTypeName]CustomAttributeType{
|
||||
"decimal": {
|
||||
Type: "float64",
|
||||
},
|
||||
"money": {
|
||||
Type: "float64",
|
||||
},
|
||||
"numeric": {
|
||||
Type: "float64",
|
||||
},
|
||||
"smallmoney": {
|
||||
Type: "float64",
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
func init() {
|
||||
@ -121,6 +146,7 @@ func init() {
|
||||
`CGenDaoBriefTablesEx`: CGenDaoBriefTablesEx,
|
||||
`CGenDaoBriefPrefix`: CGenDaoBriefPrefix,
|
||||
`CGenDaoBriefRemovePrefix`: CGenDaoBriefRemovePrefix,
|
||||
`CGenDaoBriefRemoveFieldPrefix`: CGenDaoBriefRemoveFieldPrefix,
|
||||
`CGenDaoBriefStdTime`: CGenDaoBriefStdTime,
|
||||
`CGenDaoBriefWithTime`: CGenDaoBriefWithTime,
|
||||
`CGenDaoBriefDaoPath`: CGenDaoBriefDaoPath,
|
||||
@ -135,6 +161,7 @@ func init() {
|
||||
`CGenDaoBriefNoJsonTag`: CGenDaoBriefNoJsonTag,
|
||||
`CGenDaoBriefNoModelComment`: CGenDaoBriefNoModelComment,
|
||||
`CGenDaoBriefClear`: CGenDaoBriefClear,
|
||||
`CGenDaoBriefTypeMapping`: CGenDaoBriefTypeMapping,
|
||||
`CGenDaoBriefGroup`: CGenDaoBriefGroup,
|
||||
`CGenDaoBriefJsonCase`: CGenDaoBriefJsonCase,
|
||||
`CGenDaoBriefTplDaoIndexPath`: CGenDaoBriefTplDaoIndexPath,
|
||||
@ -155,6 +182,7 @@ type (
|
||||
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"`
|
||||
@ -172,6 +200,9 @@ type (
|
||||
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"`
|
||||
genItems *CGenDaoInternalGenItems
|
||||
}
|
||||
CGenDaoOutput struct{}
|
||||
|
||||
@ -180,11 +211,17 @@ type (
|
||||
DB gdb.DB
|
||||
TableNames []string
|
||||
NewTableNames []string
|
||||
ModName string // Module name of current golang project, which is used for import purpose.
|
||||
}
|
||||
|
||||
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) {
|
||||
in.genItems = newCGenDaoInternalGenItems()
|
||||
if g.Cfg().Available(ctx) {
|
||||
v := g.Cfg().MustGet(ctx, CGenDaoConfig)
|
||||
if v.IsSlice() {
|
||||
@ -197,6 +234,7 @@ func (c CGenDao) Dao(ctx context.Context, in CGenDaoInput) (out *CGenDaoOutput,
|
||||
} else {
|
||||
doGenDaoForArray(ctx, -1, in)
|
||||
}
|
||||
doClear(in.genItems)
|
||||
mlog.Print("done!")
|
||||
return
|
||||
}
|
||||
@ -204,9 +242,8 @@ func (c CGenDao) Dao(ctx context.Context, in CGenDaoInput) (out *CGenDaoOutput,
|
||||
// doGenDaoForArray implements the "gen dao" command for configuration array.
|
||||
func doGenDaoForArray(ctx context.Context, index int, in CGenDaoInput) {
|
||||
var (
|
||||
err error
|
||||
db gdb.DB
|
||||
modName string // Go module name, eg: github.com/gogf/gf.
|
||||
err error
|
||||
db gdb.DB
|
||||
)
|
||||
if index >= 0 {
|
||||
err = g.Cfg().MustGet(
|
||||
@ -221,21 +258,6 @@ func doGenDaoForArray(ctx context.Context, index int, in CGenDaoInput) {
|
||||
mlog.Fatalf(`path "%s" does not exist`, in.Path)
|
||||
}
|
||||
removePrefixArray := gstr.SplitAndTrim(in.RemovePrefix, ",")
|
||||
if in.ImportPrefix == "" {
|
||||
mlog.Debug(`import prefix is empty, trying calculating the import package path using go.mod`)
|
||||
if !gfile.Exists("go.mod") {
|
||||
mlog.Fatal("go.mod does not exist in current working directory")
|
||||
}
|
||||
var (
|
||||
goModContent = gfile.GetContents("go.mod")
|
||||
match, _ = gregex.MatchString(`^module\s+(.+)\s*`, goModContent)
|
||||
)
|
||||
if len(match) > 1 {
|
||||
modName = gstr.Trim(match[1])
|
||||
} else {
|
||||
mlog.Fatal("module name does not found in go.mod")
|
||||
}
|
||||
}
|
||||
|
||||
// It uses user passed database configuration.
|
||||
if in.Link != "" {
|
||||
@ -271,6 +293,17 @@ func doGenDaoForArray(ctx context.Context, index int, in CGenDaoInput) {
|
||||
tableNames = array.Slice()
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Generating dao & model go files one by one according to given table name.
|
||||
newTableNames := make([]string, len(tableNames))
|
||||
for i, tableName := range tableNames {
|
||||
@ -281,13 +314,15 @@ func doGenDaoForArray(ctx context.Context, index int, in CGenDaoInput) {
|
||||
newTableName = in.Prefix + newTableName
|
||||
newTableNames[i] = newTableName
|
||||
}
|
||||
|
||||
in.genItems.Scale()
|
||||
|
||||
// Dao: index and internal.
|
||||
generateDao(ctx, CGenDaoInternalInput{
|
||||
CGenDaoInput: in,
|
||||
DB: db,
|
||||
TableNames: tableNames,
|
||||
NewTableNames: newTableNames,
|
||||
ModName: modName,
|
||||
})
|
||||
// Do.
|
||||
generateDo(ctx, CGenDaoInternalInput{
|
||||
@ -295,7 +330,6 @@ func doGenDaoForArray(ctx context.Context, index int, in CGenDaoInput) {
|
||||
DB: db,
|
||||
TableNames: tableNames,
|
||||
NewTableNames: newTableNames,
|
||||
ModName: modName,
|
||||
})
|
||||
// Entity.
|
||||
generateEntity(ctx, CGenDaoInternalInput{
|
||||
@ -303,15 +337,13 @@ func doGenDaoForArray(ctx context.Context, index int, in CGenDaoInput) {
|
||||
DB: db,
|
||||
TableNames: tableNames,
|
||||
NewTableNames: newTableNames,
|
||||
ModName: modName,
|
||||
})
|
||||
|
||||
in.genItems.SetClear(in.Clear)
|
||||
}
|
||||
|
||||
func getImportPartContent(source string, isDo bool) string {
|
||||
var (
|
||||
packageImportsArray = garray.NewStrArray()
|
||||
)
|
||||
|
||||
func getImportPartContent(ctx context.Context, source string, isDo bool, appendImports []string) string {
|
||||
var packageImportsArray = garray.NewStrArray()
|
||||
if isDo {
|
||||
packageImportsArray.Append(`"github.com/gogf/gf/v2/frame/g"`)
|
||||
}
|
||||
@ -328,6 +360,32 @@ func getImportPartContent(source string, isDo bool) string {
|
||||
packageImportsArray.Append(`"github.com/gogf/gf/v2/encoding/gjson"`)
|
||||
}
|
||||
|
||||
// Check and update imports in go.mod
|
||||
if appendImports != nil && len(appendImports) > 0 {
|
||||
goModPath := utils.GetModPath()
|
||||
if goModPath == "" {
|
||||
mlog.Fatal("go.mod not found in current project")
|
||||
}
|
||||
mod, err := modfile.Parse(goModPath, gfile.GetBytes(goModPath), nil)
|
||||
if err != nil {
|
||||
mlog.Fatalf("parse go.mod failed: %+v", err)
|
||||
}
|
||||
for _, appendImport := range appendImports {
|
||||
found := false
|
||||
for _, require := range mod.Require {
|
||||
if gstr.Contains(appendImport, require.Mod.Path) {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
err = gproc.ShellRun(ctx, `go get `+appendImport)
|
||||
mlog.Fatalf(`%+v`, err)
|
||||
}
|
||||
packageImportsArray.Append(fmt.Sprintf(`"%s"`, appendImport))
|
||||
}
|
||||
}
|
||||
|
||||
// Generate and write content to golang file.
|
||||
packageImportsStr := ""
|
||||
if packageImportsArray.Len() > 0 {
|
||||
|
||||
@ -7,22 +7,40 @@
|
||||
package gendao
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"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/utils"
|
||||
)
|
||||
|
||||
func doClear(ctx context.Context, dirPath string, force bool) {
|
||||
files, err := gfile.ScanDirFile(dirPath, "*.go", true)
|
||||
if err != nil {
|
||||
mlog.Fatal(err)
|
||||
func doClear(items *CGenDaoInternalGenItems) {
|
||||
var allGeneratedFilePaths = make([]string, 0)
|
||||
for _, item := range items.Items {
|
||||
allGeneratedFilePaths = append(allGeneratedFilePaths, item.GeneratedFilePaths...)
|
||||
}
|
||||
for _, file := range files {
|
||||
if force || utils.IsFileDoNotEdit(file) {
|
||||
if err = gfile.Remove(file); err != nil {
|
||||
for i, v := range allGeneratedFilePaths {
|
||||
allGeneratedFilePaths[i] = gfile.RealPath(v)
|
||||
}
|
||||
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.Remove(filePath); err != nil {
|
||||
mlog.Print(err)
|
||||
}
|
||||
}
|
||||
|
||||
@ -10,6 +10,7 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/olekukonko/tablewriter"
|
||||
@ -17,7 +18,6 @@ import (
|
||||
"github.com/gogf/gf/v2/database/gdb"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gfile"
|
||||
"github.com/gogf/gf/v2/text/gregex"
|
||||
"github.com/gogf/gf/v2/text/gstr"
|
||||
|
||||
"github.com/gogf/gf/cmd/gf/v2/internal/consts"
|
||||
@ -30,9 +30,7 @@ func generateDao(ctx context.Context, in CGenDaoInternalInput) {
|
||||
dirPathDao = gfile.Join(in.Path, in.DaoPath)
|
||||
dirPathDaoInternal = gfile.Join(dirPathDao, "internal")
|
||||
)
|
||||
if in.Clear {
|
||||
doClear(ctx, dirPathDao, true)
|
||||
}
|
||||
in.genItems.AppendDirPath(dirPathDao)
|
||||
for i := 0; i < len(in.TableNames); i++ {
|
||||
generateDaoSingle(ctx, generateDaoSingleInput{
|
||||
CGenDaoInternalInput: in,
|
||||
@ -60,23 +58,13 @@ func generateDaoSingle(ctx context.Context, in generateDaoSingleInput) {
|
||||
mlog.Fatalf(`fetching tables fields failed for table "%s": %+v`, in.TableName, err)
|
||||
}
|
||||
var (
|
||||
dirRealPath = gfile.RealPath(in.Path)
|
||||
tableNameCamelCase = gstr.CaseCamel(in.NewTableName)
|
||||
tableNameCamelLowerCase = gstr.CaseCamelLower(in.NewTableName)
|
||||
tableNameSnakeCase = gstr.CaseSnake(in.NewTableName)
|
||||
importPrefix = in.ImportPrefix
|
||||
)
|
||||
if importPrefix == "" {
|
||||
if dirRealPath == "" {
|
||||
dirRealPath = in.Path
|
||||
importPrefix = dirRealPath
|
||||
importPrefix = gstr.Trim(dirRealPath, "./")
|
||||
} else {
|
||||
importPrefix = gstr.Replace(dirRealPath, gfile.Pwd(), "")
|
||||
}
|
||||
importPrefix = gstr.Replace(importPrefix, gfile.Separator, "/")
|
||||
importPrefix = gstr.Join(g.SliceStr{in.ModName, importPrefix, in.DaoPath}, "/")
|
||||
importPrefix, _ = gregex.ReplaceString(`\/{2,}`, `/`, gstr.Trim(importPrefix, "/"))
|
||||
importPrefix = utils.GetImportPath(gfile.Join(in.Path, in.DaoPath))
|
||||
} else {
|
||||
importPrefix = gstr.Join(g.SliceStr{importPrefix, in.DaoPath}, "/")
|
||||
}
|
||||
@ -117,7 +105,9 @@ type generateDaoIndexInput struct {
|
||||
}
|
||||
|
||||
func generateDaoIndex(in generateDaoIndexInput) {
|
||||
path := 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) {
|
||||
indexContent := gstr.ReplaceByMap(
|
||||
getTemplateFromPathOrDefault(in.TplDaoIndexPath, consts.TemplateGenDaoIndexContent),
|
||||
@ -147,7 +137,8 @@ type generateDaoInternalInput struct {
|
||||
}
|
||||
|
||||
func generateDaoInternal(in generateDaoInternalInput) {
|
||||
path := gfile.Join(in.DirPathDaoInternal, in.FileName+".go")
|
||||
path := filepath.FromSlash(gfile.Join(in.DirPathDaoInternal, in.FileName+".go"))
|
||||
removeFieldPrefixArray := gstr.SplitAndTrim(in.RemoveFieldPrefix, ",")
|
||||
modelContent := gstr.ReplaceByMap(
|
||||
getTemplateFromPathOrDefault(in.TplDaoInternalPath, consts.TemplateGenDaoInternalContent),
|
||||
g.MapStrStr{
|
||||
@ -156,10 +147,11 @@ func generateDaoInternal(in generateDaoInternalInput) {
|
||||
tplVarGroupName: in.Group,
|
||||
tplVarTableNameCamelCase: in.TableNameCamelCase,
|
||||
tplVarTableNameCamelLowerCase: in.TableNameCamelLowerCase,
|
||||
tplVarColumnDefine: gstr.Trim(generateColumnDefinitionForDao(in.FieldMap)),
|
||||
tplVarColumnNames: gstr.Trim(generateColumnNamesForDao(in.FieldMap)),
|
||||
tplVarColumnDefine: gstr.Trim(generateColumnDefinitionForDao(in.FieldMap, removeFieldPrefixArray)),
|
||||
tplVarColumnNames: gstr.Trim(generateColumnNamesForDao(in.FieldMap, removeFieldPrefixArray)),
|
||||
})
|
||||
modelContent = replaceDefaultVar(in.CGenDaoInternalInput, modelContent)
|
||||
in.genItems.AppendGeneratedFilePath(path)
|
||||
if err := gfile.PutContents(path, strings.TrimSpace(modelContent)); err != nil {
|
||||
mlog.Fatalf("writing content to '%s' failed: %v", path, err)
|
||||
} else {
|
||||
@ -170,16 +162,23 @@ func generateDaoInternal(in generateDaoInternalInput) {
|
||||
|
||||
// generateColumnNamesForDao generates and returns the column names assignment content of column struct
|
||||
// for specified table.
|
||||
func generateColumnNamesForDao(fieldMap map[string]*gdb.TableField) string {
|
||||
func generateColumnNamesForDao(fieldMap map[string]*gdb.TableField, removeFieldPrefixArray []string) string {
|
||||
var (
|
||||
buffer = bytes.NewBuffer(nil)
|
||||
array = make([][]string, len(fieldMap))
|
||||
names = sortFieldKeyForDao(fieldMap)
|
||||
)
|
||||
|
||||
for index, name := range names {
|
||||
field := fieldMap[name]
|
||||
|
||||
newFiledName := field.Name
|
||||
for _, v := range removeFieldPrefixArray {
|
||||
newFiledName = gstr.TrimLeftStr(newFiledName, v, 1)
|
||||
}
|
||||
|
||||
array[index] = []string{
|
||||
" #" + gstr.CaseCamel(field.Name) + ":",
|
||||
" #" + gstr.CaseCamel(newFiledName) + ":",
|
||||
fmt.Sprintf(` #"%s",`, field.Name),
|
||||
}
|
||||
}
|
||||
@ -199,12 +198,13 @@ func generateColumnNamesForDao(fieldMap map[string]*gdb.TableField) string {
|
||||
}
|
||||
|
||||
// generateColumnDefinitionForDao generates and returns the column names definition for specified table.
|
||||
func generateColumnDefinitionForDao(fieldMap map[string]*gdb.TableField) string {
|
||||
func generateColumnDefinitionForDao(fieldMap map[string]*gdb.TableField, removeFieldPrefixArray []string) string {
|
||||
var (
|
||||
buffer = bytes.NewBuffer(nil)
|
||||
array = make([][]string, len(fieldMap))
|
||||
names = sortFieldKeyForDao(fieldMap)
|
||||
)
|
||||
|
||||
for index, name := range names {
|
||||
var (
|
||||
field = fieldMap[name]
|
||||
@ -213,8 +213,12 @@ func generateColumnDefinitionForDao(fieldMap map[string]*gdb.TableField) string
|
||||
"\r", " ",
|
||||
}))
|
||||
)
|
||||
newFiledName := field.Name
|
||||
for _, v := range removeFieldPrefixArray {
|
||||
newFiledName = gstr.TrimLeftStr(newFiledName, v, 1)
|
||||
}
|
||||
array[index] = []string{
|
||||
" #" + gstr.CaseCamel(field.Name),
|
||||
" #" + gstr.CaseCamel(newFiledName),
|
||||
" # " + "string",
|
||||
" #" + fmt.Sprintf(`// %s`, comment),
|
||||
}
|
||||
|
||||
@ -9,6 +9,7 @@ package gendao
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
@ -22,10 +23,8 @@ import (
|
||||
)
|
||||
|
||||
func generateDo(ctx context.Context, in CGenDaoInternalInput) {
|
||||
var dirPathDo = gfile.Join(in.Path, in.DoPath)
|
||||
if in.Clear {
|
||||
doClear(ctx, dirPathDo, false)
|
||||
}
|
||||
var dirPathDo = filepath.FromSlash(gfile.Join(in.Path, in.DoPath))
|
||||
in.genItems.AppendDirPath(dirPathDo)
|
||||
in.NoJsonTag = true
|
||||
in.DescriptionTag = false
|
||||
in.NoModelComment = false
|
||||
@ -36,9 +35,9 @@ func generateDo(ctx context.Context, in CGenDaoInternalInput) {
|
||||
mlog.Fatalf("fetching tables fields failed for table '%s':\n%v", tableName, err)
|
||||
}
|
||||
var (
|
||||
newTableName = in.NewTableNames[i]
|
||||
doFilePath = gfile.Join(dirPathDo, gstr.CaseSnake(newTableName)+".go")
|
||||
structDefinition = generateStructDefinition(ctx, generateStructDefinitionInput{
|
||||
newTableName = in.NewTableNames[i]
|
||||
doFilePath = gfile.Join(dirPathDo, gstr.CaseSnake(newTableName)+".go")
|
||||
structDefinition, _ = generateStructDefinition(ctx, generateStructDefinitionInput{
|
||||
CGenDaoInternalInput: in,
|
||||
TableName: tableName,
|
||||
StructName: gstr.CaseCamel(newTableName),
|
||||
@ -59,11 +58,13 @@ func generateDo(ctx context.Context, in CGenDaoInternalInput) {
|
||||
},
|
||||
)
|
||||
modelContent := generateDoContent(
|
||||
ctx,
|
||||
in,
|
||||
tableName,
|
||||
gstr.CaseCamel(newTableName),
|
||||
structDefinition,
|
||||
)
|
||||
in.genItems.AppendGeneratedFilePath(doFilePath)
|
||||
err = gfile.PutContents(doFilePath, strings.TrimSpace(modelContent))
|
||||
if err != nil {
|
||||
mlog.Fatalf(`writing content to "%s" failed: %v`, doFilePath, err)
|
||||
@ -74,15 +75,18 @@ func generateDo(ctx context.Context, in CGenDaoInternalInput) {
|
||||
}
|
||||
}
|
||||
|
||||
func generateDoContent(in CGenDaoInternalInput, tableName, tableNameCamelCase, structDefine string) string {
|
||||
func generateDoContent(
|
||||
ctx context.Context, in CGenDaoInternalInput, tableName, tableNameCamelCase, structDefine string,
|
||||
) string {
|
||||
doContent := gstr.ReplaceByMap(
|
||||
getTemplateFromPathOrDefault(in.TplDaoDoPath, consts.TemplateGenDaoDoContent),
|
||||
g.MapStrStr{
|
||||
tplVarTableName: tableName,
|
||||
tplVarPackageImports: getImportPartContent(structDefine, true),
|
||||
tplVarPackageImports: getImportPartContent(ctx, structDefine, true, nil),
|
||||
tplVarTableNameCamelCase: tableNameCamelCase,
|
||||
tplVarStructDefine: structDefine,
|
||||
})
|
||||
},
|
||||
)
|
||||
doContent = replaceDefaultVar(in, doContent)
|
||||
return doContent
|
||||
}
|
||||
|
||||
@ -8,6 +8,7 @@ package gendao
|
||||
|
||||
import (
|
||||
"context"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
@ -21,31 +22,34 @@ import (
|
||||
|
||||
func generateEntity(ctx context.Context, in CGenDaoInternalInput) {
|
||||
var dirPathEntity = gfile.Join(in.Path, in.EntityPath)
|
||||
if in.Clear {
|
||||
doClear(ctx, dirPathEntity, false)
|
||||
}
|
||||
in.genItems.AppendDirPath(dirPathEntity)
|
||||
// Model content.
|
||||
for i, tableName := range in.TableNames {
|
||||
fieldMap, err := in.DB.TableFields(ctx, tableName)
|
||||
if err != nil {
|
||||
mlog.Fatalf("fetching tables fields failed for table '%s':\n%v", tableName, err)
|
||||
}
|
||||
|
||||
var (
|
||||
newTableName = in.NewTableNames[i]
|
||||
entityFilePath = gfile.Join(dirPathEntity, gstr.CaseSnake(newTableName)+".go")
|
||||
entityContent = generateEntityContent(
|
||||
newTableName = in.NewTableNames[i]
|
||||
entityFilePath = filepath.FromSlash(gfile.Join(dirPathEntity, gstr.CaseSnake(newTableName)+".go"))
|
||||
structDefinition, appendImports = generateStructDefinition(ctx, generateStructDefinitionInput{
|
||||
CGenDaoInternalInput: in,
|
||||
TableName: tableName,
|
||||
StructName: gstr.CaseCamel(newTableName),
|
||||
FieldMap: fieldMap,
|
||||
IsDo: false,
|
||||
})
|
||||
entityContent = generateEntityContent(
|
||||
ctx,
|
||||
in,
|
||||
newTableName,
|
||||
gstr.CaseCamel(newTableName),
|
||||
generateStructDefinition(ctx, generateStructDefinitionInput{
|
||||
CGenDaoInternalInput: in,
|
||||
TableName: tableName,
|
||||
StructName: gstr.CaseCamel(newTableName),
|
||||
FieldMap: fieldMap,
|
||||
IsDo: false,
|
||||
}),
|
||||
structDefinition,
|
||||
appendImports,
|
||||
)
|
||||
)
|
||||
in.genItems.AppendGeneratedFilePath(entityFilePath)
|
||||
err = gfile.PutContents(entityFilePath, strings.TrimSpace(entityContent))
|
||||
if err != nil {
|
||||
mlog.Fatalf("writing content to '%s' failed: %v", entityFilePath, err)
|
||||
@ -56,15 +60,18 @@ func generateEntity(ctx context.Context, in CGenDaoInternalInput) {
|
||||
}
|
||||
}
|
||||
|
||||
func generateEntityContent(in CGenDaoInternalInput, tableName, tableNameCamelCase, structDefine string) string {
|
||||
func generateEntityContent(
|
||||
ctx context.Context, in CGenDaoInternalInput, tableName, tableNameCamelCase, structDefine string, appendImports []string,
|
||||
) string {
|
||||
entityContent := gstr.ReplaceByMap(
|
||||
getTemplateFromPathOrDefault(in.TplDaoEntityPath, consts.TemplateGenDaoEntityContent),
|
||||
g.MapStrStr{
|
||||
tplVarTableName: tableName,
|
||||
tplVarPackageImports: getImportPartContent(structDefine, false),
|
||||
tplVarPackageImports: getImportPartContent(ctx, structDefine, false, appendImports),
|
||||
tplVarTableNameCamelCase: tableNameCamelCase,
|
||||
tplVarStructDefine: structDefine,
|
||||
})
|
||||
},
|
||||
)
|
||||
entityContent = replaceDefaultVar(in, entityContent)
|
||||
return entityContent
|
||||
}
|
||||
|
||||
53
cmd/gf/internal/cmd/gendao/gendao_gen_item.go
Normal file
53
cmd/gf/internal/cmd/gendao/gendao_gen_item.go
Normal file
@ -0,0 +1,53 @@
|
||||
// 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,6 +10,7 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/olekukonko/tablewriter"
|
||||
|
||||
@ -27,13 +28,18 @@ type generateStructDefinitionInput struct {
|
||||
IsDo bool // Is generating DTO struct.
|
||||
}
|
||||
|
||||
func generateStructDefinition(ctx context.Context, in generateStructDefinitionInput) string {
|
||||
func generateStructDefinition(ctx context.Context, in generateStructDefinitionInput) (string, []string) {
|
||||
var appendImports []string
|
||||
buffer := bytes.NewBuffer(nil)
|
||||
array := make([][]string, len(in.FieldMap))
|
||||
names := sortFieldKeyForDao(in.FieldMap)
|
||||
for index, name := range names {
|
||||
var imports string
|
||||
field := in.FieldMap[name]
|
||||
array[index] = generateStructFieldDefinition(ctx, field, in)
|
||||
array[index], imports = generateStructFieldDefinition(ctx, field, in)
|
||||
if imports != "" {
|
||||
appendImports = append(appendImports, imports)
|
||||
}
|
||||
}
|
||||
tw := tablewriter.NewWriter(buffer)
|
||||
tw.SetBorder(false)
|
||||
@ -54,59 +60,91 @@ func generateStructDefinition(ctx context.Context, in generateStructDefinitionIn
|
||||
}
|
||||
buffer.WriteString(stContent)
|
||||
buffer.WriteString("}")
|
||||
return buffer.String()
|
||||
return buffer.String(), appendImports
|
||||
}
|
||||
|
||||
// generateStructFieldDefinition generates and returns the attribute definition for specified field.
|
||||
func generateStructFieldDefinition(
|
||||
ctx context.Context, field *gdb.TableField, in generateStructDefinitionInput,
|
||||
) []string {
|
||||
) (attrLines []string, appendImport string) {
|
||||
var (
|
||||
err error
|
||||
typeName string
|
||||
jsonTag = getJsonTagFromCase(field.Name, in.JsonCase)
|
||||
err error
|
||||
localTypeName gdb.LocalType
|
||||
localTypeNameStr string
|
||||
jsonTag = gstr.CaseConvert(field.Name, gstr.CaseTypeMatch(in.JsonCase))
|
||||
)
|
||||
typeName, err = in.DB.CheckLocalTypeForField(ctx, field.Type, nil)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
switch typeName {
|
||||
case gdb.LocalTypeDate, gdb.LocalTypeDatetime:
|
||||
if in.StdTime {
|
||||
typeName = "time.Time"
|
||||
|
||||
if in.TypeMapping != nil && len(in.TypeMapping) > 0 {
|
||||
var (
|
||||
tryTypeName string
|
||||
)
|
||||
tryTypeMatch, _ := gregex.MatchString(`(.+?)\((.+)\)`, field.Type)
|
||||
if len(tryTypeMatch) == 3 {
|
||||
tryTypeName = gstr.Trim(tryTypeMatch[1])
|
||||
} else {
|
||||
typeName = "*gtime.Time"
|
||||
tryTypeName = gstr.Split(field.Type, " ")[0]
|
||||
}
|
||||
if tryTypeName != "" {
|
||||
if typeMapping, ok := in.TypeMapping[strings.ToLower(tryTypeName)]; ok {
|
||||
localTypeNameStr = typeMapping.Type
|
||||
appendImport = typeMapping.Import
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
case gdb.LocalTypeInt64Bytes:
|
||||
typeName = "int64"
|
||||
if localTypeNameStr == "" {
|
||||
localTypeName, err = in.DB.CheckLocalTypeForField(ctx, field.Type, nil)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
localTypeNameStr = string(localTypeName)
|
||||
switch localTypeName {
|
||||
case gdb.LocalTypeDate, gdb.LocalTypeDatetime:
|
||||
if in.StdTime {
|
||||
localTypeNameStr = "time.Time"
|
||||
} else {
|
||||
localTypeNameStr = "*gtime.Time"
|
||||
}
|
||||
|
||||
case gdb.LocalTypeUint64Bytes:
|
||||
typeName = "uint64"
|
||||
case gdb.LocalTypeInt64Bytes:
|
||||
localTypeNameStr = "int64"
|
||||
|
||||
// Special type handle.
|
||||
case gdb.LocalTypeJson, gdb.LocalTypeJsonb:
|
||||
if in.GJsonSupport {
|
||||
typeName = "*gjson.Json"
|
||||
} else {
|
||||
typeName = "string"
|
||||
case gdb.LocalTypeUint64Bytes:
|
||||
localTypeNameStr = "uint64"
|
||||
|
||||
// Special type handle.
|
||||
case gdb.LocalTypeJson, gdb.LocalTypeJsonb:
|
||||
if in.GJsonSupport {
|
||||
localTypeNameStr = "*gjson.Json"
|
||||
} else {
|
||||
localTypeNameStr = "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
tagKey = "`"
|
||||
result = []string{
|
||||
" #" + gstr.CaseCamel(field.Name),
|
||||
" #" + typeName,
|
||||
}
|
||||
tagKey = "`"
|
||||
descriptionTag = gstr.Replace(formatComment(field.Comment), `"`, `\"`)
|
||||
)
|
||||
removeFieldPrefixArray := gstr.SplitAndTrim(in.RemoveFieldPrefix, ",")
|
||||
newFiledName := field.Name
|
||||
for _, v := range removeFieldPrefixArray {
|
||||
newFiledName = gstr.TrimLeftStr(newFiledName, v, 1)
|
||||
}
|
||||
attrLines = []string{
|
||||
" #" + gstr.CaseCamel(newFiledName),
|
||||
" #" + localTypeNameStr,
|
||||
}
|
||||
attrLines = append(attrLines, fmt.Sprintf(` #%sjson:"%s"`, tagKey, jsonTag))
|
||||
// orm tag
|
||||
if !in.IsDo {
|
||||
// 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)))
|
||||
|
||||
result = append(result, " #"+fmt.Sprintf(tagKey+`json:"%s"`, jsonTag))
|
||||
result = append(result, " #"+fmt.Sprintf(`description:"%s"`+tagKey, descriptionTag))
|
||||
result = append(result, " #"+fmt.Sprintf(`// %s`, formatComment(field.Comment)))
|
||||
|
||||
for k, v := range result {
|
||||
for k, v := range attrLines {
|
||||
if in.NoJsonTag {
|
||||
v, _ = gregex.ReplaceString(`json:".+"`, ``, v)
|
||||
}
|
||||
@ -116,9 +154,9 @@ func generateStructFieldDefinition(
|
||||
if in.NoModelComment {
|
||||
v, _ = gregex.ReplaceString(`//.+`, ``, v)
|
||||
}
|
||||
result[k] = v
|
||||
attrLines[k] = v
|
||||
}
|
||||
return result
|
||||
return attrLines, appendImport
|
||||
}
|
||||
|
||||
// formatComment formats the comment string to fit the golang code without any lines.
|
||||
@ -131,30 +169,3 @@ func formatComment(comment string) string {
|
||||
comment = gstr.Trim(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
|
||||
}
|
||||
|
||||
@ -21,10 +21,10 @@ import (
|
||||
type (
|
||||
CGenEnums struct{}
|
||||
CGenEnumsInput struct {
|
||||
g.Meta `name:"enums" config:"{CGenEnumsConfig}" brief:"{CGenEnumsBrief}" eg:"{CGenEnumsEg}"`
|
||||
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/boot/boot_enums.go"`
|
||||
Prefix string `name:"prefix" short:"x" dc:"only exports packages that starts with specified prefix"`
|
||||
g.Meta `name:"enums" config:"{CGenEnumsConfig}" brief:"{CGenEnumsBrief}" eg:"{CGenEnumsEg}"`
|
||||
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/boot/boot_enums.go"`
|
||||
Prefixes []string `name:"prefixes" short:"x" dc:"only exports packages that starts with specified prefixes"`
|
||||
}
|
||||
CGenEnumsOutput struct{}
|
||||
)
|
||||
@ -57,7 +57,7 @@ func (c CGenEnums) Enums(ctx context.Context, in CGenEnumsInput) (out *CGenEnums
|
||||
if err != nil {
|
||||
mlog.Fatal(err)
|
||||
}
|
||||
mlog.Printf(`scanning: %s`, realPath)
|
||||
mlog.Printf(`scanning for enums: %s`, realPath)
|
||||
cfg := &packages.Config{
|
||||
Dir: realPath,
|
||||
Mode: pkgLoadMode,
|
||||
@ -67,7 +67,7 @@ func (c CGenEnums) Enums(ctx context.Context, in CGenEnumsInput) (out *CGenEnums
|
||||
if err != nil {
|
||||
mlog.Fatal(err)
|
||||
}
|
||||
p := NewEnumsParser(in.Prefix)
|
||||
p := NewEnumsParser(in.Prefixes)
|
||||
p.ParsePackages(pkgs)
|
||||
var enumsContent = gstr.ReplaceByMap(consts.TemplateGenEnums, g.MapStrStr{
|
||||
"{PackageName}": gfile.Basename(gfile.Dir(in.Path)),
|
||||
@ -77,7 +77,7 @@ func (c CGenEnums) Enums(ctx context.Context, in CGenEnumsInput) (out *CGenEnums
|
||||
if err = gfile.PutContents(in.Path, enumsContent); err != nil {
|
||||
return
|
||||
}
|
||||
mlog.Printf(`generated: %s`, in.Path)
|
||||
mlog.Printf(`generated enums go file: %s`, in.Path)
|
||||
mlog.Print("done!")
|
||||
return
|
||||
}
|
||||
|
||||
@ -19,9 +19,10 @@ import (
|
||||
const pkgLoadMode = 0xffffff
|
||||
|
||||
type EnumsParser struct {
|
||||
enums []EnumItem
|
||||
parsedPkg map[string]struct{}
|
||||
prefix string
|
||||
enums []EnumItem
|
||||
parsedPkg map[string]struct{}
|
||||
prefixes []string
|
||||
standardPackages map[string]struct{}
|
||||
}
|
||||
|
||||
type EnumItem struct {
|
||||
@ -31,23 +32,12 @@ type EnumItem struct {
|
||||
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(prefix string) *EnumsParser {
|
||||
func NewEnumsParser(prefixes []string) *EnumsParser {
|
||||
return &EnumsParser{
|
||||
enums: make([]EnumItem, 0),
|
||||
parsedPkg: make(map[string]struct{}),
|
||||
prefix: prefix,
|
||||
enums: make([]EnumItem, 0),
|
||||
parsedPkg: make(map[string]struct{}),
|
||||
prefixes: prefixes,
|
||||
standardPackages: getStandardPackages(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -59,7 +49,7 @@ func (p *EnumsParser) ParsePackages(pkgs []*packages.Package) {
|
||||
|
||||
func (p *EnumsParser) ParsePackage(pkg *packages.Package) {
|
||||
// Ignore std packages.
|
||||
if _, ok := standardPackages[pkg.ID]; ok {
|
||||
if _, ok := p.standardPackages[pkg.ID]; ok {
|
||||
return
|
||||
}
|
||||
// Ignore pared packages.
|
||||
@ -67,9 +57,16 @@ func (p *EnumsParser) ParsePackage(pkg *packages.Package) {
|
||||
return
|
||||
}
|
||||
p.parsedPkg[pkg.ID] = struct{}{}
|
||||
// Only parse specified prefix.
|
||||
if p.prefix != "" {
|
||||
if !gstr.HasPrefix(pkg.ID, p.prefix) {
|
||||
|
||||
// Only parse specified prefixes.
|
||||
if len(p.prefixes) > 0 {
|
||||
var hasPrefix bool
|
||||
for _, prefix := range p.prefixes {
|
||||
if hasPrefix = gstr.HasPrefix(pkg.ID, prefix); hasPrefix {
|
||||
break
|
||||
}
|
||||
}
|
||||
if !hasPrefix {
|
||||
return
|
||||
}
|
||||
}
|
||||
@ -108,7 +105,6 @@ func (p *EnumsParser) ParsePackage(pkg *packages.Package) {
|
||||
Type: enumType,
|
||||
Kind: enumKind,
|
||||
})
|
||||
|
||||
}
|
||||
for _, im := range pkg.Imports {
|
||||
p.ParsePackage(im)
|
||||
@ -138,3 +134,15 @@ func (p *EnumsParser) Export() string {
|
||||
}
|
||||
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,6 +9,7 @@ package genpb
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/gogf/gf/cmd/gf/v2/internal/utility/utils"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
@ -85,7 +86,7 @@ func (c CGenPb) parseControllers(filePath string) ([]generateCtrl, error) {
|
||||
func(match []string) string {
|
||||
ctrl := generateCtrl{
|
||||
Name: match[1],
|
||||
Package: gfile.Basename(gfile.Dir(gfile.Dir(filePath))),
|
||||
Package: strings.ReplaceAll(gfile.Basename(gfile.Dir(gfile.Dir(filePath))), "-", "_"),
|
||||
Version: gfile.Basename(gfile.Dir(filePath)),
|
||||
Methods: make([]generateCtrlMethod, 0),
|
||||
}
|
||||
|
||||
@ -10,9 +10,11 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/olekukonko/tablewriter"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/olekukonko/tablewriter"
|
||||
|
||||
"github.com/gogf/gf/cmd/gf/v2/internal/consts"
|
||||
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
|
||||
"github.com/gogf/gf/v2/database/gdb"
|
||||
@ -29,16 +31,17 @@ import (
|
||||
type (
|
||||
CGenPbEntity struct{}
|
||||
CGenPbEntityInput struct {
|
||||
g.Meta `name:"pbentity" config:"{CGenPbEntityConfig}" brief:"{CGenPbEntityBrief}" eg:"{CGenPbEntityEg}" ad:"{CGenPbEntityAd}"`
|
||||
Path string `name:"path" short:"p" brief:"{CGenPbEntityBriefPath}" d:"manifest/protobuf/pbentity"`
|
||||
Package string `name:"package" short:"k" brief:"{CGenPbEntityBriefPackage}"`
|
||||
Link string `name:"link" short:"l" brief:"{CGenPbEntityBriefLink}"`
|
||||
Tables string `name:"tables" short:"t" brief:"{CGenPbEntityBriefTables}"`
|
||||
Prefix string `name:"prefix" short:"f" brief:"{CGenPbEntityBriefPrefix}"`
|
||||
RemovePrefix string `name:"removePrefix" short:"r" brief:"{CGenPbEntityBriefRemovePrefix}"`
|
||||
NameCase string `name:"nameCase" short:"n" brief:"{CGenPbEntityBriefNameCase}" d:"Camel"`
|
||||
JsonCase string `name:"jsonCase" short:"j" brief:"{CGenPbEntityBriefJsonCase}" d:"CamelLower"`
|
||||
Option string `name:"option" short:"o" brief:"{CGenPbEntityBriefOption}"`
|
||||
g.Meta `name:"pbentity" config:"{CGenPbEntityConfig}" brief:"{CGenPbEntityBrief}" eg:"{CGenPbEntityEg}" ad:"{CGenPbEntityAd}"`
|
||||
Path string `name:"path" short:"p" brief:"{CGenPbEntityBriefPath}" d:"manifest/protobuf/pbentity"`
|
||||
Package string `name:"package" short:"k" brief:"{CGenPbEntityBriefPackage}"`
|
||||
Link string `name:"link" short:"l" brief:"{CGenPbEntityBriefLink}"`
|
||||
Tables string `name:"tables" short:"t" brief:"{CGenPbEntityBriefTables}"`
|
||||
Prefix string `name:"prefix" short:"f" brief:"{CGenPbEntityBriefPrefix}"`
|
||||
RemovePrefix string `name:"removePrefix" short:"r" brief:"{CGenPbEntityBriefRemovePrefix}"`
|
||||
RemoveFieldPrefix string `name:"removeFieldPrefix" short:"rf" brief:"{CGenPbEntityBriefRemoveFieldPrefix}"`
|
||||
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}"`
|
||||
}
|
||||
CGenPbEntityOutput struct{}
|
||||
|
||||
@ -85,14 +88,15 @@ CONFIGURATION SUPPORT
|
||||
option java_package = "protobuf/demos";
|
||||
option php_namespace = "protobuf/demos";
|
||||
`
|
||||
CGenPbEntityBriefPath = `directory path for generated files storing`
|
||||
CGenPbEntityBriefPackage = `package path for all entity proto files`
|
||||
CGenPbEntityBriefLink = `database configuration, the same as the ORM configuration of GoFrame`
|
||||
CGenPbEntityBriefTables = `generate models only for given tables, multiple table names separated with ','`
|
||||
CGenPbEntityBriefPrefix = `add specified prefix for all entity names and entity proto files`
|
||||
CGenPbEntityBriefRemovePrefix = `remove specified prefix of the table, multiple prefix separated with ','`
|
||||
CGenPbEntityBriefOption = `extra protobuf options`
|
||||
CGenPbEntityBriefGroup = `
|
||||
CGenPbEntityBriefPath = `directory path for generated files storing`
|
||||
CGenPbEntityBriefPackage = `package path for all entity proto files`
|
||||
CGenPbEntityBriefLink = `database configuration, the same as the ORM configuration of GoFrame`
|
||||
CGenPbEntityBriefTables = `generate models only for given tables, multiple table names separated with ','`
|
||||
CGenPbEntityBriefPrefix = `add specified prefix for all entity names and entity proto files`
|
||||
CGenPbEntityBriefRemovePrefix = `remove specified prefix of the table, multiple prefix separated with ','`
|
||||
CGenPbEntityBriefRemoveFieldPrefix = `remove specified prefix of the field, multiple prefix separated with ','`
|
||||
CGenPbEntityBriefOption = `extra protobuf options`
|
||||
CGenPbEntityBriefGroup = `
|
||||
specifying the configuration group name of database for generated ORM instance,
|
||||
it's not necessary and the default value is "default"
|
||||
`
|
||||
@ -118,20 +122,21 @@ set it to "none" to ignore json tag generating.
|
||||
|
||||
func init() {
|
||||
gtag.Sets(g.MapStrStr{
|
||||
`CGenPbEntityConfig`: CGenPbEntityConfig,
|
||||
`CGenPbEntityBrief`: CGenPbEntityBrief,
|
||||
`CGenPbEntityEg`: CGenPbEntityEg,
|
||||
`CGenPbEntityAd`: CGenPbEntityAd,
|
||||
`CGenPbEntityBriefPath`: CGenPbEntityBriefPath,
|
||||
`CGenPbEntityBriefPackage`: CGenPbEntityBriefPackage,
|
||||
`CGenPbEntityBriefLink`: CGenPbEntityBriefLink,
|
||||
`CGenPbEntityBriefTables`: CGenPbEntityBriefTables,
|
||||
`CGenPbEntityBriefPrefix`: CGenPbEntityBriefPrefix,
|
||||
`CGenPbEntityBriefRemovePrefix`: CGenPbEntityBriefRemovePrefix,
|
||||
`CGenPbEntityBriefGroup`: CGenPbEntityBriefGroup,
|
||||
`CGenPbEntityBriefNameCase`: CGenPbEntityBriefNameCase,
|
||||
`CGenPbEntityBriefJsonCase`: CGenPbEntityBriefJsonCase,
|
||||
`CGenPbEntityBriefOption`: CGenPbEntityBriefOption,
|
||||
`CGenPbEntityConfig`: CGenPbEntityConfig,
|
||||
`CGenPbEntityBrief`: CGenPbEntityBrief,
|
||||
`CGenPbEntityEg`: CGenPbEntityEg,
|
||||
`CGenPbEntityAd`: CGenPbEntityAd,
|
||||
`CGenPbEntityBriefPath`: CGenPbEntityBriefPath,
|
||||
`CGenPbEntityBriefPackage`: CGenPbEntityBriefPackage,
|
||||
`CGenPbEntityBriefLink`: CGenPbEntityBriefLink,
|
||||
`CGenPbEntityBriefTables`: CGenPbEntityBriefTables,
|
||||
`CGenPbEntityBriefPrefix`: CGenPbEntityBriefPrefix,
|
||||
`CGenPbEntityBriefRemovePrefix`: CGenPbEntityBriefRemovePrefix,
|
||||
`CGenPbEntityBriefRemoveFieldPrefix`: CGenPbEntityBriefRemoveFieldPrefix,
|
||||
`CGenPbEntityBriefGroup`: CGenPbEntityBriefGroup,
|
||||
`CGenPbEntityBriefNameCase`: CGenPbEntityBriefNameCase,
|
||||
`CGenPbEntityBriefJsonCase`: CGenPbEntityBriefJsonCase,
|
||||
`CGenPbEntityBriefOption`: CGenPbEntityBriefOption,
|
||||
})
|
||||
}
|
||||
|
||||
@ -196,7 +201,7 @@ func doGenPbEntityForArray(ctx context.Context, index int, in CGenPbEntityInput)
|
||||
if len(match) == 3 {
|
||||
gdb.AddConfigNode(tempGroup, gdb.ConfigNode{
|
||||
Type: gstr.Trim(match[1]),
|
||||
Link: gstr.Trim(match[2]),
|
||||
Link: in.Link,
|
||||
})
|
||||
db, _ = gdb.Instance(tempGroup)
|
||||
}
|
||||
@ -245,7 +250,7 @@ func generatePbEntityContentFile(ctx context.Context, in CGenPbEntityInternalInp
|
||||
tableNameSnakeCase = gstr.CaseSnake(newTableName)
|
||||
entityMessageDefine = generateEntityMessageDefinition(tableNameCamelCase, fieldMap, in)
|
||||
fileName = gstr.Trim(tableNameSnakeCase, "-_.")
|
||||
path = gfile.Join(in.Path, fileName+".proto")
|
||||
path = filepath.FromSlash(gfile.Join(in.Path, fileName+".proto"))
|
||||
)
|
||||
if gstr.Contains(entityMessageDefine, "google.protobuf.Timestamp") {
|
||||
imports = `import "google/protobuf/timestamp.proto";`
|
||||
@ -294,17 +299,17 @@ func generateEntityMessageDefinition(entityName string, fieldMap map[string]*gdb
|
||||
// generateMessageFieldForPbEntity generates and returns the message definition for specified field.
|
||||
func generateMessageFieldForPbEntity(index int, field *gdb.TableField, in CGenPbEntityInternalInput) []string {
|
||||
var (
|
||||
typeName string
|
||||
comment string
|
||||
jsonTagStr string
|
||||
err error
|
||||
ctx = gctx.GetInitCtx()
|
||||
localTypeName gdb.LocalType
|
||||
comment string
|
||||
jsonTagStr string
|
||||
err error
|
||||
ctx = gctx.GetInitCtx()
|
||||
)
|
||||
typeName, err = in.DB.CheckLocalTypeForField(ctx, field.Type, nil)
|
||||
localTypeName, err = in.DB.CheckLocalTypeForField(ctx, field.Type, nil)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
var typeMapping = map[string]string{
|
||||
var typeMapping = map[gdb.LocalType]string{
|
||||
gdb.LocalTypeString: "string",
|
||||
gdb.LocalTypeDate: "google.protobuf.Timestamp",
|
||||
gdb.LocalTypeDatetime: "google.protobuf.Timestamp",
|
||||
@ -317,16 +322,16 @@ func generateMessageFieldForPbEntity(index int, field *gdb.TableField, in CGenPb
|
||||
gdb.LocalTypeUint64Slice: "repeated uint64",
|
||||
gdb.LocalTypeInt64Bytes: "repeated int64",
|
||||
gdb.LocalTypeUint64Bytes: "repeated uint64",
|
||||
gdb.LocalTypeFloat32: "float32",
|
||||
gdb.LocalTypeFloat64: "float64",
|
||||
gdb.LocalTypeBytes: "[]byte",
|
||||
gdb.LocalTypeFloat32: "float",
|
||||
gdb.LocalTypeFloat64: "double",
|
||||
gdb.LocalTypeBytes: "bytes",
|
||||
gdb.LocalTypeBool: "bool",
|
||||
gdb.LocalTypeJson: "string",
|
||||
gdb.LocalTypeJsonb: "string",
|
||||
}
|
||||
typeName = typeMapping[typeName]
|
||||
if typeName == "" {
|
||||
typeName = "string"
|
||||
localTypeNameStr := typeMapping[localTypeName]
|
||||
if localTypeNameStr == "" {
|
||||
localTypeNameStr = "string"
|
||||
}
|
||||
|
||||
comment = gstr.ReplaceByArray(field.Comment, g.SliceStr{
|
||||
@ -337,6 +342,7 @@ func generateMessageFieldForPbEntity(index int, field *gdb.TableField, in CGenPb
|
||||
comment = gstr.Replace(comment, `\n`, " ")
|
||||
comment, _ = gregex.ReplaceString(`\s{2,}`, ` `, comment)
|
||||
if jsonTagName := formatCase(field.Name, in.JsonCase); jsonTagName != "" {
|
||||
jsonTagStr = fmt.Sprintf(`[json_name = "%s"]`, jsonTagName)
|
||||
// beautiful indent.
|
||||
if index < 10 {
|
||||
// 3 spaces
|
||||
@ -349,9 +355,16 @@ func generateMessageFieldForPbEntity(index int, field *gdb.TableField, in CGenPb
|
||||
jsonTagStr = " " + jsonTagStr
|
||||
}
|
||||
}
|
||||
|
||||
removeFieldPrefixArray := gstr.SplitAndTrim(in.RemoveFieldPrefix, ",")
|
||||
newFiledName := field.Name
|
||||
for _, v := range removeFieldPrefixArray {
|
||||
newFiledName = gstr.TrimLeftStr(newFiledName, v, 1)
|
||||
}
|
||||
|
||||
return []string{
|
||||
" #" + typeName,
|
||||
" #" + formatCase(field.Name, in.NameCase),
|
||||
" #" + localTypeNameStr,
|
||||
" #" + formatCase(newFiledName, in.NameCase),
|
||||
" #= " + gconv.String(index) + jsonTagStr + ";",
|
||||
" #" + fmt.Sprintf(`// %s`, comment),
|
||||
}
|
||||
@ -366,32 +379,10 @@ func getTplPbEntityContent(tplEntityPath string) string {
|
||||
|
||||
// formatCase call gstr.Case* function to convert the s to specified case.
|
||||
func formatCase(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)
|
||||
|
||||
case "none":
|
||||
if caseStr == "none" {
|
||||
return ""
|
||||
}
|
||||
return str
|
||||
return gstr.CaseConvert(str, gstr.CaseTypeMatch(caseStr))
|
||||
}
|
||||
|
||||
func sortFieldKeyForPbEntity(fieldMap map[string]*gdb.TableField) []string {
|
||||
|
||||
@ -9,12 +9,13 @@ package genservice
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/gogf/gf/v2/container/garray"
|
||||
"github.com/gogf/gf/v2/container/gmap"
|
||||
"github.com/gogf/gf/v2/container/gset"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gfile"
|
||||
"github.com/gogf/gf/v2/os/gproc"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
"github.com/gogf/gf/v2/text/gregex"
|
||||
"github.com/gogf/gf/v2/text/gstr"
|
||||
@ -50,7 +51,7 @@ destination file name storing automatically generated go files, cases are as fol
|
||||
`
|
||||
CGenServiceBriefWatchFile = `used in file watcher, it re-generates all service go files only if given file is under srcFolder`
|
||||
CGenServiceBriefStPattern = `regular expression matching struct name for generating service. default: ^s([A-Z]\\\\w+)$`
|
||||
CGenServiceBriefPackages = `produce go files only for given source packages`
|
||||
CGenServiceBriefPackages = `produce go files only for given source packages(source folders)`
|
||||
CGenServiceBriefImportPrefix = `custom import prefix to calculate import path for generated importing go file of logic`
|
||||
CGenServiceBriefClear = `delete all generated go files that are not used any further`
|
||||
)
|
||||
@ -93,28 +94,28 @@ const (
|
||||
)
|
||||
|
||||
func (c CGenService) Service(ctx context.Context, in CGenServiceInput) (out *CGenServiceOutput, err error) {
|
||||
// File lock to avoid multiple processes.
|
||||
var (
|
||||
flockFilePath = gfile.Temp("gf.cli.gen.service.lock")
|
||||
flockContent = gfile.GetContents(flockFilePath)
|
||||
)
|
||||
if flockContent != "" {
|
||||
if gtime.Timestamp()-gconv.Int64(flockContent) < genServiceFileLockSeconds {
|
||||
// If another "gen service" process is running, it just exits.
|
||||
mlog.Debug(`another "gen service" process is running, exit`)
|
||||
return
|
||||
}
|
||||
}
|
||||
defer gfile.Remove(flockFilePath)
|
||||
_ = gfile.PutContents(flockFilePath, gtime.TimestampStr())
|
||||
|
||||
in.SrcFolder = gstr.TrimRight(in.SrcFolder, `\/`)
|
||||
in.SrcFolder = gstr.Replace(in.SrcFolder, "\\", "/")
|
||||
in.WatchFile = gstr.TrimRight(in.WatchFile, `\/`)
|
||||
in.WatchFile = gstr.Replace(in.WatchFile, "\\", "/")
|
||||
in.SrcFolder = filepath.ToSlash(in.SrcFolder)
|
||||
in.SrcFolder = gstr.TrimRight(in.SrcFolder, `/`)
|
||||
in.WatchFile = filepath.ToSlash(in.WatchFile)
|
||||
in.WatchFile = gstr.TrimRight(in.WatchFile, `/`)
|
||||
|
||||
// Watch file handling.
|
||||
if in.WatchFile != "" {
|
||||
// File lock to avoid multiple processes.
|
||||
var (
|
||||
flockFilePath = gfile.Temp("gf.cli.gen.service.lock")
|
||||
flockContent = gfile.GetContents(flockFilePath)
|
||||
)
|
||||
if flockContent != "" {
|
||||
if gtime.Timestamp()-gconv.Int64(flockContent) < genServiceFileLockSeconds {
|
||||
// If another "gen service" process is running, it just exits.
|
||||
mlog.Debug(`another "gen service" process is running, exit`)
|
||||
return
|
||||
}
|
||||
}
|
||||
defer gfile.Remove(flockFilePath)
|
||||
_ = gfile.PutContents(flockFilePath, gtime.TimestampStr())
|
||||
|
||||
// It works only if given WatchFile is in SrcFolder.
|
||||
var (
|
||||
watchFileDir = gfile.Dir(in.WatchFile)
|
||||
@ -131,13 +132,10 @@ func (c CGenService) Service(ctx context.Context, in CGenServiceInput) (out *CGe
|
||||
mlog.Fatalf(`%+v`, err)
|
||||
}
|
||||
mlog.Debug("Chdir:", newWorkingDir)
|
||||
_ = gfile.Remove(flockFilePath)
|
||||
var command = fmt.Sprintf(
|
||||
`%s gen service -packages=%s`,
|
||||
gfile.SelfName(), gfile.Basename(watchFileDir),
|
||||
)
|
||||
err = gproc.ShellRun(ctx, command)
|
||||
return
|
||||
|
||||
in.WatchFile = ""
|
||||
in.Packages = []string{gfile.Basename(watchFileDir)}
|
||||
return c.Service(ctx, in)
|
||||
}
|
||||
|
||||
if !gfile.Exists(in.SrcFolder) {
|
||||
@ -145,16 +143,7 @@ func (c CGenService) Service(ctx context.Context, in CGenServiceInput) (out *CGe
|
||||
}
|
||||
|
||||
if in.ImportPrefix == "" {
|
||||
if !gfile.Exists("go.mod") {
|
||||
mlog.Fatal("ImportPrefix is empty and go.mod does not exist in current working directory")
|
||||
}
|
||||
var (
|
||||
goModContent = gfile.GetContents("go.mod")
|
||||
match, _ = gregex.MatchString(`^module\s+(.+)\s*`, goModContent)
|
||||
)
|
||||
if len(match) > 1 {
|
||||
in.ImportPrefix = fmt.Sprintf(`%s/%s`, gstr.Trim(match[1]), gstr.Replace(in.SrcFolder, `\`, `/`))
|
||||
}
|
||||
in.ImportPrefix = utils.GetImportPath(in.SrcFolder)
|
||||
}
|
||||
|
||||
var (
|
||||
@ -182,34 +171,118 @@ func (c CGenService) Service(ctx context.Context, in CGenServiceInput) (out *CGe
|
||||
if len(files) == 0 {
|
||||
continue
|
||||
}
|
||||
// Parse single logic package folder.
|
||||
var (
|
||||
// StructName => FunctionDefinitions
|
||||
srcPkgInterfaceMap = make(map[string]*garray.StrArray)
|
||||
srcImportedPackages = garray.NewSortedStrArray().SetUnique(true)
|
||||
srcPackageName = gfile.Basename(srcFolderPath)
|
||||
ok bool
|
||||
dstFilePath = gfile.Join(in.DstFolder,
|
||||
srcPkgInterfaceMap = gmap.NewListMap()
|
||||
srcImportedPackages = garray.NewSortedStrArray().SetUnique(true)
|
||||
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)
|
||||
for _, file := range files {
|
||||
var packageItems []packageItem
|
||||
fileContent = gfile.GetContents(file)
|
||||
fileContent, err := gregex.ReplaceString(`/[/|\*](.+)`, "", fileContent)
|
||||
// Calculate code comments in source Go files.
|
||||
err = c.calculateCodeCommented(in, fileContent, srcCodeCommentedMap)
|
||||
if err != nil {
|
||||
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.
|
||||
err = c.calculateImportedPackages(fileContent, srcImportedPackages)
|
||||
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.
|
||||
err = c.calculateInterfaceFunctions(in, fileContent, srcPkgInterfaceMap, dstPackageName)
|
||||
err = c.calculateInterfaceFunctions(in, fileContent, srcPkgInterfaceMap)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
initImportSrcPackages = append(
|
||||
initImportSrcPackages,
|
||||
fmt.Sprintf(`%s/%s`, in.ImportPrefix, srcPackageName),
|
||||
@ -222,7 +295,7 @@ func (c CGenService) Service(ctx context.Context, in CGenServiceInput) (out *CGe
|
||||
)
|
||||
continue
|
||||
}
|
||||
// Generating service go file for logic.
|
||||
// Generating service go file for single logic package.
|
||||
if ok, err = c.generateServiceFile(generateServiceFilesInput{
|
||||
CGenServiceInput: in,
|
||||
SrcStructFunctions: srcPkgInterfaceMap,
|
||||
@ -230,6 +303,7 @@ func (c CGenService) Service(ctx context.Context, in CGenServiceInput) (out *CGe
|
||||
SrcPackageName: srcPackageName,
|
||||
DstPackageName: dstPackageName,
|
||||
DstFilePath: dstFilePath,
|
||||
SrcCodeCommentedMap: srcCodeCommentedMap,
|
||||
}); err != nil {
|
||||
return
|
||||
}
|
||||
@ -271,6 +345,64 @@ func (c CGenService) Service(ctx context.Context, in CGenServiceInput) (out *CGe
|
||||
utils.GoFmt(in.DstFolder)
|
||||
}
|
||||
|
||||
// auto update main.go.
|
||||
if err = c.checkAndUpdateMain(in.SrcFolder); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
mlog.Print(`done!`)
|
||||
return
|
||||
}
|
||||
|
||||
func (c CGenService) checkAndUpdateMain(srcFolder string) (err error) {
|
||||
var (
|
||||
logicPackageName = gstr.ToLower(gfile.Basename(srcFolder))
|
||||
logicFilePath = gfile.Join(srcFolder, logicPackageName+".go")
|
||||
importPath = utils.GetImportPath(logicFilePath)
|
||||
importStr = fmt.Sprintf(`_ "%s"`, importPath)
|
||||
mainFilePath = gfile.Join(gfile.Dir(gfile.Dir(gfile.Dir(logicFilePath))), "main.go")
|
||||
mainFileContent = gfile.GetContents(mainFilePath)
|
||||
)
|
||||
// No main content found.
|
||||
if mainFileContent == "" {
|
||||
return nil
|
||||
}
|
||||
if gstr.Contains(mainFileContent, importStr) {
|
||||
return nil
|
||||
}
|
||||
match, err := gregex.MatchString(`import \(([\s\S]+?)\)`, mainFileContent)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// No match.
|
||||
if len(match) < 2 {
|
||||
return nil
|
||||
}
|
||||
lines := garray.NewStrArrayFrom(gstr.Split(match[1], "\n"))
|
||||
for i, line := range lines.Slice() {
|
||||
line = gstr.Trim(line)
|
||||
if len(line) == 0 {
|
||||
continue
|
||||
}
|
||||
if line[0] == '_' {
|
||||
continue
|
||||
}
|
||||
// Insert the logic import into imports.
|
||||
if err = lines.InsertBefore(i, fmt.Sprintf("\t%s\n\n", importStr)); err != nil {
|
||||
return err
|
||||
}
|
||||
break
|
||||
}
|
||||
mainFileContent, err = gregex.ReplaceString(
|
||||
`import \(([\s\S]+?)\)`,
|
||||
fmt.Sprintf(`import (%s)`, lines.Join("\n")),
|
||||
mainFileContent,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
mlog.Print(`update main.go`)
|
||||
err = gfile.PutContents(mainFilePath, mainFileContent)
|
||||
utils.GoFmt(mainFilePath)
|
||||
return
|
||||
}
|
||||
|
||||
@ -7,45 +7,54 @@
|
||||
package genservice
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/parser"
|
||||
"go/token"
|
||||
|
||||
"github.com/gogf/gf/v2/container/garray"
|
||||
"github.com/gogf/gf/v2/container/gmap"
|
||||
"github.com/gogf/gf/v2/text/gregex"
|
||||
"github.com/gogf/gf/v2/text/gstr"
|
||||
)
|
||||
|
||||
func (c CGenService) calculateImportedPackages(fileContent string, srcImportedPackages *garray.SortedStrArray) (err error) {
|
||||
type packageItem struct {
|
||||
Alias string
|
||||
Path string
|
||||
RawImport string
|
||||
}
|
||||
|
||||
func (c CGenService) calculateImportedPackages(fileContent string) (packages []packageItem, err error) {
|
||||
f, err := parser.ParseFile(token.NewFileSet(), "", fileContent, parser.ImportsOnly)
|
||||
if err != nil {
|
||||
return err
|
||||
return nil, err
|
||||
}
|
||||
packages = make([]packageItem, 0)
|
||||
for _, s := range f.Imports {
|
||||
if s.Path != nil {
|
||||
if s.Name != nil {
|
||||
// If it has alias, and it is not `_`.
|
||||
if pkgAlias := s.Name.String(); pkgAlias != "_" {
|
||||
srcImportedPackages.Add(pkgAlias + " " + s.Path.Value)
|
||||
packages = append(packages, packageItem{
|
||||
Alias: pkgAlias,
|
||||
Path: s.Path.Value,
|
||||
RawImport: pkgAlias + " " + s.Path.Value,
|
||||
})
|
||||
}
|
||||
} else {
|
||||
// no alias
|
||||
srcImportedPackages.Add(s.Path.Value)
|
||||
packages = append(packages, packageItem{
|
||||
Alias: "",
|
||||
Path: s.Path.Value,
|
||||
RawImport: s.Path.Value,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
return packages, nil
|
||||
}
|
||||
|
||||
func (c CGenService) calculateInterfaceFunctions(
|
||||
in CGenServiceInput, fileContent string, srcPkgInterfaceMap map[string]*garray.StrArray, dstPackageName string,
|
||||
) (err error) {
|
||||
var (
|
||||
ok bool
|
||||
matches [][]string
|
||||
srcPkgInterfaceFuncArray *garray.StrArray
|
||||
)
|
||||
// calculate struct name and its functions according function definitions.
|
||||
matches, err = gregex.MatchAllString(`func \((.+?)\) ([\s\S]+?) {`, fileContent)
|
||||
func (c CGenService) calculateCodeCommented(in CGenServiceInput, fileContent string, srcCodeCommentedMap map[string]string) error {
|
||||
matches, err := gregex.MatchAllString(`((((//.*)|(/\*[\s\S]*?\*/))\s)+)func \((.+?)\) ([\s\S]+?) {`, fileContent)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -53,13 +62,14 @@ func (c CGenService) calculateInterfaceFunctions(
|
||||
var (
|
||||
structName string
|
||||
structMatch []string
|
||||
funcReceiver = gstr.Trim(match[1])
|
||||
funcReceiver = gstr.Trim(match[1+5])
|
||||
receiverArray = gstr.SplitAndTrim(funcReceiver, " ")
|
||||
functionHead = gstr.Trim(gstr.Replace(match[2], "\n", ""))
|
||||
functionHead = gstr.Trim(gstr.Replace(match[2+5], "\n", ""))
|
||||
commentedInfo = ""
|
||||
)
|
||||
if len(receiverArray) > 1 {
|
||||
structName = receiverArray[1]
|
||||
} else {
|
||||
} else if len(receiverArray) == 1 {
|
||||
structName = receiverArray[0]
|
||||
}
|
||||
structName = gstr.Trim(structName, "*")
|
||||
@ -80,9 +90,63 @@ func (c CGenService) calculateInterfaceFunctions(
|
||||
continue
|
||||
}
|
||||
structName = gstr.CaseCamel(structMatch[1])
|
||||
if srcPkgInterfaceFuncArray, ok = srcPkgInterfaceMap[structName]; !ok {
|
||||
srcPkgInterfaceMap[structName] = garray.NewStrArray()
|
||||
srcPkgInterfaceFuncArray = srcPkgInterfaceMap[structName]
|
||||
|
||||
commentedInfo = match[1]
|
||||
if len(commentedInfo) > 0 {
|
||||
srcCodeCommentedMap[fmt.Sprintf("%s-%s", structName, functionHead)] = commentedInfo
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c CGenService) calculateInterfaceFunctions(
|
||||
in CGenServiceInput, fileContent string, srcPkgInterfaceMap *gmap.ListMap,
|
||||
) (err error) {
|
||||
var (
|
||||
matches [][]string
|
||||
srcPkgInterfaceFuncArray *garray.StrArray
|
||||
)
|
||||
// calculate struct name and its functions according function definitions.
|
||||
matches, err = gregex.MatchAllString(`func \((.+?)\) ([\s\S]+?) {`, fileContent)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, match := range matches {
|
||||
var (
|
||||
structName string
|
||||
structMatch []string
|
||||
funcReceiver = gstr.Trim(match[1])
|
||||
receiverArray = gstr.SplitAndTrim(funcReceiver, " ")
|
||||
functionHead = gstr.Trim(gstr.Replace(match[2], "\n", ""))
|
||||
)
|
||||
if len(receiverArray) > 1 {
|
||||
structName = receiverArray[1]
|
||||
} else if len(receiverArray) == 1 {
|
||||
structName = receiverArray[0]
|
||||
}
|
||||
structName = gstr.Trim(structName, "*")
|
||||
|
||||
// Case of:
|
||||
// Xxx(\n ctx context.Context, req *v1.XxxReq,\n) -> Xxx(ctx context.Context, req *v1.XxxReq)
|
||||
functionHead = gstr.Replace(functionHead, `,)`, `)`)
|
||||
functionHead, _ = gregex.ReplaceString(`\(\s+`, `(`, functionHead)
|
||||
functionHead, _ = gregex.ReplaceString(`\s{2,}`, ` `, functionHead)
|
||||
if !gstr.IsLetterUpper(functionHead[0]) {
|
||||
continue
|
||||
}
|
||||
// Match and pick the struct name from receiver.
|
||||
if structMatch, err = gregex.MatchString(in.StPattern, structName); err != nil {
|
||||
return err
|
||||
}
|
||||
if len(structMatch) < 1 {
|
||||
continue
|
||||
}
|
||||
structName = gstr.CaseCamel(structMatch[1])
|
||||
if !srcPkgInterfaceMap.Contains(structName) {
|
||||
srcPkgInterfaceFuncArray = garray.NewStrArray()
|
||||
srcPkgInterfaceMap.Set(structName, srcPkgInterfaceFuncArray)
|
||||
} else {
|
||||
srcPkgInterfaceFuncArray = srcPkgInterfaceMap.Get(structName).(*garray.StrArray)
|
||||
}
|
||||
srcPkgInterfaceFuncArray.Append(functionHead)
|
||||
}
|
||||
@ -103,8 +167,8 @@ func (c CGenService) calculateInterfaceFunctions(
|
||||
continue
|
||||
}
|
||||
structName = gstr.CaseCamel(structMatch[1])
|
||||
if srcPkgInterfaceFuncArray, ok = srcPkgInterfaceMap[structName]; !ok {
|
||||
srcPkgInterfaceMap[structName] = garray.NewStrArray()
|
||||
if !srcPkgInterfaceMap.Contains(structName) {
|
||||
srcPkgInterfaceMap.Set(structName, garray.NewStrArray())
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
||||
@ -10,6 +10,7 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/gogf/gf/v2/container/garray"
|
||||
"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/text/gregex"
|
||||
@ -23,10 +24,11 @@ import (
|
||||
type generateServiceFilesInput struct {
|
||||
CGenServiceInput
|
||||
DstFilePath string // Absolute file path for generated service go file.
|
||||
SrcStructFunctions map[string]*garray.StrArray
|
||||
SrcStructFunctions *gmap.ListMap
|
||||
SrcImportedPackages []string
|
||||
SrcPackageName string
|
||||
DstPackageName string
|
||||
SrcCodeCommentedMap map[string]string
|
||||
}
|
||||
|
||||
func (c CGenService) generateServiceFile(in generateServiceFilesInput) (ok bool, err error) {
|
||||
@ -45,14 +47,23 @@ func (c CGenService) generateServiceFile(in generateServiceFilesInput) (ok bool,
|
||||
// Type definitions.
|
||||
generatedContent += "type("
|
||||
generatedContent += "\n"
|
||||
for structName, funcArray := range in.SrcStructFunctions {
|
||||
in.SrcStructFunctions.Iterator(func(key, value interface{}) bool {
|
||||
structName, funcArray := key.(string), value.(*garray.StrArray)
|
||||
allFuncArray.Append(funcArray.Slice()...)
|
||||
// Add comments to a method.
|
||||
for index, funcName := range funcArray.Slice() {
|
||||
if commentedInfo, exist := in.SrcCodeCommentedMap[fmt.Sprintf("%s-%s", structName, funcName)]; exist {
|
||||
funcName = commentedInfo + funcName
|
||||
_ = funcArray.Set(index, funcName)
|
||||
}
|
||||
}
|
||||
generatedContent += gstr.Trim(gstr.ReplaceByMap(consts.TemplateGenServiceContentInterface, g.MapStrStr{
|
||||
"{InterfaceName}": "I" + structName,
|
||||
"{FuncDefinition}": funcArray.Join("\n\t"),
|
||||
}))
|
||||
generatedContent += "\n"
|
||||
}
|
||||
return true
|
||||
})
|
||||
generatedContent += ")"
|
||||
generatedContent += "\n"
|
||||
|
||||
@ -62,17 +73,19 @@ func (c CGenService) generateServiceFile(in generateServiceFilesInput) (ok bool,
|
||||
generatingInterfaceCheck string
|
||||
)
|
||||
// Variable definitions.
|
||||
for structName := range in.SrcStructFunctions {
|
||||
in.SrcStructFunctions.Iterator(func(key, value interface{}) bool {
|
||||
structName := key.(string)
|
||||
generatingInterfaceCheck = fmt.Sprintf(`[^\w\d]+%s.I%s[^\w\d]`, in.DstPackageName, structName)
|
||||
if gregex.IsMatchString(generatingInterfaceCheck, generatedContent) {
|
||||
continue
|
||||
return true
|
||||
}
|
||||
variableContent += gstr.Trim(gstr.ReplaceByMap(consts.TemplateGenServiceContentVariable, g.MapStrStr{
|
||||
"{StructName}": structName,
|
||||
"{InterfaceName}": "I" + structName,
|
||||
}))
|
||||
variableContent += "\n"
|
||||
}
|
||||
return true
|
||||
})
|
||||
if variableContent != "" {
|
||||
generatedContent += "var("
|
||||
generatedContent += "\n"
|
||||
@ -81,17 +94,19 @@ func (c CGenService) generateServiceFile(in generateServiceFilesInput) (ok bool,
|
||||
generatedContent += "\n"
|
||||
}
|
||||
// Variable register function definitions.
|
||||
for structName := range in.SrcStructFunctions {
|
||||
in.SrcStructFunctions.Iterator(func(key, value interface{}) bool {
|
||||
structName := key.(string)
|
||||
generatingInterfaceCheck = fmt.Sprintf(`[^\w\d]+%s.I%s[^\w\d]`, in.DstPackageName, structName)
|
||||
if gregex.IsMatchString(generatingInterfaceCheck, generatedContent) {
|
||||
continue
|
||||
return true
|
||||
}
|
||||
generatedContent += gstr.Trim(gstr.ReplaceByMap(consts.TemplateGenServiceContentRegister, g.MapStrStr{
|
||||
"{StructName}": structName,
|
||||
"{InterfaceName}": "I" + structName,
|
||||
}))
|
||||
generatedContent += "\n\n"
|
||||
}
|
||||
return true
|
||||
})
|
||||
|
||||
// Replace empty braces that have new line.
|
||||
generatedContent, _ = gregex.ReplaceString(`{[\s\t]+}`, `{}`, generatedContent)
|
||||
@ -120,6 +135,7 @@ func (c CGenService) generateServiceFile(in generateServiceFilesInput) (ok bool,
|
||||
// isToGenerateServiceGoFile checks and returns whether the service content dirty.
|
||||
func (c CGenService) isToGenerateServiceGoFile(dstPackageName, filePath string, funcArray *garray.StrArray) bool {
|
||||
var (
|
||||
err error
|
||||
fileContent = gfile.GetContents(filePath)
|
||||
generatedFuncArray = garray.NewSortedStrArrayFrom(funcArray.Slice())
|
||||
contentFuncArray = garray.NewSortedStrArray()
|
||||
@ -127,6 +143,12 @@ func (c CGenService) isToGenerateServiceGoFile(dstPackageName, filePath string,
|
||||
if fileContent == "" {
|
||||
return true
|
||||
}
|
||||
// remove all comments.
|
||||
fileContent, err = gregex.ReplaceString(`(//.*)|((?s)/\*.*?\*/)`, "", fileContent)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
return false
|
||||
}
|
||||
matches, _ := gregex.MatchAllString(`\s+interface\s+{([\s\S]+?)}`, fileContent)
|
||||
for _, match := range matches {
|
||||
contentFuncArray.Append(gstr.SplitAndTrim(match[1], "\n")...)
|
||||
@ -151,55 +173,37 @@ func (c CGenService) isToGenerateServiceGoFile(dstPackageName, filePath string,
|
||||
return false
|
||||
}
|
||||
|
||||
// generateInitializationFile generates `logic.go`.
|
||||
func (c CGenService) generateInitializationFile(in CGenServiceInput, importSrcPackages []string) (err error) {
|
||||
var (
|
||||
srcPackageName = gstr.ToLower(gfile.Basename(in.SrcFolder))
|
||||
srcFilePath = gfile.Join(in.SrcFolder, srcPackageName+".go")
|
||||
srcImports string
|
||||
logicPackageName = gstr.ToLower(gfile.Basename(in.SrcFolder))
|
||||
logicFilePath = gfile.Join(in.SrcFolder, logicPackageName+".go")
|
||||
logicImports string
|
||||
generatedContent string
|
||||
)
|
||||
if !utils.IsFileDoNotEdit(srcFilePath) {
|
||||
mlog.Debugf(`ignore file as it is manually maintained: %s`, srcFilePath)
|
||||
if !utils.IsFileDoNotEdit(logicFilePath) {
|
||||
mlog.Debugf(`ignore file as it is manually maintained: %s`, logicFilePath)
|
||||
return nil
|
||||
}
|
||||
for _, importSrcPackage := range importSrcPackages {
|
||||
srcImports += fmt.Sprintf(`%s_ "%s"%s`, "\t", importSrcPackage, "\n")
|
||||
logicImports += fmt.Sprintf(`%s_ "%s"%s`, "\t", importSrcPackage, "\n")
|
||||
}
|
||||
generatedContent = gstr.ReplaceByMap(consts.TemplateGenServiceLogicContent, g.MapStrStr{
|
||||
"{PackageName}": srcPackageName,
|
||||
"{Imports}": srcImports,
|
||||
"{PackageName}": logicPackageName,
|
||||
"{Imports}": logicImports,
|
||||
})
|
||||
mlog.Printf(`generating init go file: %s`, srcFilePath)
|
||||
if err = gfile.PutContents(srcFilePath, generatedContent); err != nil {
|
||||
mlog.Printf(`generating init go file: %s`, logicFilePath)
|
||||
if err = gfile.PutContents(logicFilePath, generatedContent); err != nil {
|
||||
return err
|
||||
}
|
||||
utils.GoFmt(srcFilePath)
|
||||
utils.GoFmt(logicFilePath)
|
||||
return nil
|
||||
}
|
||||
|
||||
// getDstFileNameCase call gstr.Case* function to convert the s to specified case.
|
||||
func (c CGenService) getDstFileNameCase(str, caseStr string) string {
|
||||
switch gstr.ToLower(caseStr) {
|
||||
case gstr.ToLower("Lower"):
|
||||
return gstr.ToLower(str)
|
||||
|
||||
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("SnakeFirstUpper"):
|
||||
return gstr.CaseSnakeFirstUpper(str)
|
||||
|
||||
case gstr.ToLower("SnakeScreaming"):
|
||||
return gstr.CaseSnakeScreaming(str)
|
||||
func (c CGenService) getDstFileNameCase(str, caseStr string) (newStr string) {
|
||||
if newStr := gstr.CaseConvert(str, gstr.CaseTypeMatch(caseStr)); newStr != str {
|
||||
return newStr
|
||||
}
|
||||
return gstr.CaseSnake(str)
|
||||
}
|
||||
|
||||
5
cmd/gf/internal/cmd/testdata/build/multiple/multiple.go
vendored
Normal file
5
cmd/gf/internal/cmd/testdata/build/multiple/multiple.go
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
package main
|
||||
|
||||
func main() {
|
||||
|
||||
}
|
||||
5
cmd/gf/internal/cmd/testdata/build/single/main.go
vendored
Normal file
5
cmd/gf/internal/cmd/testdata/build/single/main.go
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
package main
|
||||
|
||||
func main() {
|
||||
|
||||
}
|
||||
12
cmd/gf/internal/cmd/testdata/build/varmap/go.mod
vendored
Normal file
12
cmd/gf/internal/cmd/testdata/build/varmap/go.mod
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
module github.com/gogf/gf/cmd/gf/cmd/gf/testdata/vardump/v2
|
||||
|
||||
go 1.18
|
||||
|
||||
require github.com/gogf/gf/v2 v2.6.1
|
||||
|
||||
require (
|
||||
go.opentelemetry.io/otel v1.14.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.14.0 // indirect
|
||||
)
|
||||
|
||||
replace github.com/gogf/gf/v2 => ../../../../../../../
|
||||
26
cmd/gf/internal/cmd/testdata/build/varmap/go.sum
vendored
Normal file
26
cmd/gf/internal/cmd/testdata/build/varmap/go.sum
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
github.com/BurntSushi/toml v1.2.0 h1:Rt8g24XnyGTyglgET/PRUNlrUeu9F5L+7FilkXfZgs0=
|
||||
github.com/clbanning/mxj/v2 v2.7.0 h1:WA/La7UGCanFe5NpHF0Q3DNtnCsVoxbPKuyBNHWRyME=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs=
|
||||
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
|
||||
github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0=
|
||||
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
|
||||
github.com/grokify/html-strip-tags-go v0.0.1 h1:0fThFwLbW7P/kOiTBs03FsJSV9RM2M/Q/MOnCQxKMo0=
|
||||
github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo=
|
||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||
github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng=
|
||||
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
|
||||
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
|
||||
go.opentelemetry.io/otel v1.14.0 h1:/79Huy8wbf5DnIPhemGB+zEPVwnN6fuQybr/SRXa6hM=
|
||||
go.opentelemetry.io/otel v1.14.0/go.mod h1:o4buv+dJzx8rohcUeRmWUZhqupFvzWis188WlggnNeU=
|
||||
go.opentelemetry.io/otel/sdk v1.14.0 h1:PDCppFRDq8A1jL9v6KMI6dYesaq+DFcDZvjsoGvxGzY=
|
||||
go.opentelemetry.io/otel/trace v1.14.0 h1:wp2Mmvj41tDsyAJXiWDWpfNsOiIyd38fy85pyKcFq/M=
|
||||
go.opentelemetry.io/otel/trace v1.14.0/go.mod h1:8avnQLK+CG77yNLUae4ea2JDQ6iT+gozhnZjy/rw9G8=
|
||||
golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
|
||||
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
|
||||
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
13
cmd/gf/internal/cmd/testdata/build/varmap/main.go
vendored
Normal file
13
cmd/gf/internal/cmd/testdata/build/varmap/main.go
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/gogf/gf/v2/os/gbuild"
|
||||
)
|
||||
|
||||
func main() {
|
||||
for k, v := range gbuild.Data() {
|
||||
fmt.Printf("%s: %v\n", k, v)
|
||||
}
|
||||
}
|
||||
30
cmd/gf/internal/cmd/testdata/fix/fix25_content.go
vendored
Normal file
30
cmd/gf/internal/cmd/testdata/fix/fix25_content.go
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
package testdata
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/net/ghttp"
|
||||
"github.com/gogf/gf/v2/test/gtest"
|
||||
"github.com/gogf/gf/v2/util/guid"
|
||||
)
|
||||
|
||||
func Test_Router_Hook_Multi(t *testing.T) {
|
||||
s := g.Server(guid.S())
|
||||
s.BindHandler("/multi-hook", func(r *ghttp.Request) {
|
||||
r.Response.Write("show")
|
||||
})
|
||||
|
||||
s.BindHookHandlerByMap("/multi-hook", map[string]ghttp.HandlerFunc{
|
||||
ghttp.HookBeforeServe: func(r *ghttp.Request) {
|
||||
r.Response.Write("1")
|
||||
},
|
||||
})
|
||||
s.BindHookHandlerByMap("/multi-hook/{id}", map[string]ghttp.HandlerFunc{
|
||||
ghttp.HookBeforeServe: func(r *ghttp.Request) {
|
||||
r.Response.Write("2")
|
||||
},
|
||||
})
|
||||
}
|
||||
24
cmd/gf/internal/cmd/testdata/genctrl/api/article/article_expect.go
vendored
Normal file
24
cmd/gf/internal/cmd/testdata/genctrl/api/article/article_expect.go
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
// =================================================================================
|
||||
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
// =================================================================================
|
||||
|
||||
package article
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/gogf/gf/cmd/gf/v2/internal/cmd/testdata/genctrl/api/article/v1"
|
||||
"github.com/gogf/gf/cmd/gf/v2/internal/cmd/testdata/genctrl/api/article/v2"
|
||||
)
|
||||
|
||||
type IArticleV1 interface {
|
||||
Create(ctx context.Context, req *v1.CreateReq) (res *v1.CreateRes, err error)
|
||||
Update(ctx context.Context, req *v1.UpdateReq) (res *v1.UpdateRes, err error)
|
||||
GetList(ctx context.Context, req *v1.GetListReq) (res *v1.GetListRes, err error)
|
||||
GetOne(ctx context.Context, req *v1.GetOneReq) (res *v1.GetOneRes, err error)
|
||||
}
|
||||
|
||||
type IArticleV2 interface {
|
||||
Create(ctx context.Context, req *v2.CreateReq) (res *v2.CreateRes, err error)
|
||||
Update(ctx context.Context, req *v2.UpdateReq) (res *v2.UpdateRes, err error)
|
||||
}
|
||||
27
cmd/gf/internal/cmd/testdata/genctrl/api/article/v1/edit.go
vendored
Normal file
27
cmd/gf/internal/cmd/testdata/genctrl/api/article/v1/edit.go
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
// Copyright GoFrame 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 v1
|
||||
|
||||
import "github.com/gogf/gf/v2/frame/g"
|
||||
|
||||
type (
|
||||
CreateReq struct {
|
||||
g.Meta `path:"/article/create" method:"post" tags:"ArticleService"`
|
||||
Title string `v:"required"`
|
||||
}
|
||||
|
||||
CreateRes struct{}
|
||||
)
|
||||
|
||||
type (
|
||||
UpdateReq struct {
|
||||
g.Meta `path:"/article/update" method:"post" tags:"ArticleService"`
|
||||
Title string `v:"required"`
|
||||
}
|
||||
|
||||
UpdateRes struct{}
|
||||
)
|
||||
25
cmd/gf/internal/cmd/testdata/genctrl/api/article/v1/get.go
vendored
Normal file
25
cmd/gf/internal/cmd/testdata/genctrl/api/article/v1/get.go
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
// Copyright GoFrame 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 v1
|
||||
|
||||
import "github.com/gogf/gf/v2/frame/g"
|
||||
|
||||
type GetListReq struct {
|
||||
g.Meta `path:"/article/list" method:"get" tags:"ArticleService"`
|
||||
}
|
||||
|
||||
type GetListRes struct {
|
||||
list []struct{}
|
||||
}
|
||||
|
||||
type GetOneReq struct {
|
||||
g.Meta `path:"/article/one" method:"get" tags:"ArticleService"`
|
||||
}
|
||||
|
||||
type GetOneRes struct {
|
||||
one struct{}
|
||||
}
|
||||
23
cmd/gf/internal/cmd/testdata/genctrl/api/article/v2/edit.go
vendored
Normal file
23
cmd/gf/internal/cmd/testdata/genctrl/api/article/v2/edit.go
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
// Copyright GoFrame 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 v2
|
||||
|
||||
import "github.com/gogf/gf/v2/frame/g"
|
||||
|
||||
type CreateReq struct {
|
||||
g.Meta `path:"/article/create" method:"post" tags:"ArticleService"`
|
||||
Title string `v:"required"`
|
||||
}
|
||||
|
||||
type CreateRes struct{}
|
||||
|
||||
type UpdateReq struct {
|
||||
g.Meta `path:"/article/update" method:"post" tags:"ArticleService"`
|
||||
Title string `v:"required"`
|
||||
}
|
||||
|
||||
type UpdateRes struct{}
|
||||
5
cmd/gf/internal/cmd/testdata/genctrl/controller/article/article.go
vendored
Normal file
5
cmd/gf/internal/cmd/testdata/genctrl/controller/article/article.go
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
// =================================================================================
|
||||
// This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish.
|
||||
// =================================================================================
|
||||
|
||||
package article
|
||||
21
cmd/gf/internal/cmd/testdata/genctrl/controller/article/article_new.go
vendored
Normal file
21
cmd/gf/internal/cmd/testdata/genctrl/controller/article/article_new.go
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
// =================================================================================
|
||||
// This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish.
|
||||
// =================================================================================
|
||||
|
||||
package article
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/cmd/gf/v2/internal/cmd/testdata/genctrl/api/article"
|
||||
)
|
||||
|
||||
type ControllerV1 struct{}
|
||||
|
||||
func NewV1() article.IArticleV1 {
|
||||
return &ControllerV1{}
|
||||
}
|
||||
|
||||
type ControllerV2 struct{}
|
||||
|
||||
func NewV2() article.IArticleV2 {
|
||||
return &ControllerV2{}
|
||||
}
|
||||
14
cmd/gf/internal/cmd/testdata/genctrl/controller/article/article_v1_create.go
vendored
Normal file
14
cmd/gf/internal/cmd/testdata/genctrl/controller/article/article_v1_create.go
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
package article
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/gogf/gf/v2/errors/gcode"
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
|
||||
"github.com/gogf/gf/cmd/gf/v2/internal/cmd/testdata/genctrl/api/article/v1"
|
||||
)
|
||||
|
||||
func (c *ControllerV1) Create(ctx context.Context, req *v1.CreateReq) (res *v1.CreateRes, err error) {
|
||||
return nil, gerror.NewCode(gcode.CodeNotImplemented)
|
||||
}
|
||||
14
cmd/gf/internal/cmd/testdata/genctrl/controller/article/article_v1_get_list.go
vendored
Normal file
14
cmd/gf/internal/cmd/testdata/genctrl/controller/article/article_v1_get_list.go
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
package article
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/gogf/gf/v2/errors/gcode"
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
|
||||
"github.com/gogf/gf/cmd/gf/v2/internal/cmd/testdata/genctrl/api/article/v1"
|
||||
)
|
||||
|
||||
func (c *ControllerV1) GetList(ctx context.Context, req *v1.GetListReq) (res *v1.GetListRes, err error) {
|
||||
return nil, gerror.NewCode(gcode.CodeNotImplemented)
|
||||
}
|
||||
14
cmd/gf/internal/cmd/testdata/genctrl/controller/article/article_v1_get_one.go
vendored
Normal file
14
cmd/gf/internal/cmd/testdata/genctrl/controller/article/article_v1_get_one.go
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
package article
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/gogf/gf/v2/errors/gcode"
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
|
||||
"github.com/gogf/gf/cmd/gf/v2/internal/cmd/testdata/genctrl/api/article/v1"
|
||||
)
|
||||
|
||||
func (c *ControllerV1) GetOne(ctx context.Context, req *v1.GetOneReq) (res *v1.GetOneRes, err error) {
|
||||
return nil, gerror.NewCode(gcode.CodeNotImplemented)
|
||||
}
|
||||
14
cmd/gf/internal/cmd/testdata/genctrl/controller/article/article_v1_update.go
vendored
Normal file
14
cmd/gf/internal/cmd/testdata/genctrl/controller/article/article_v1_update.go
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
package article
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/gogf/gf/v2/errors/gcode"
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
|
||||
"github.com/gogf/gf/cmd/gf/v2/internal/cmd/testdata/genctrl/api/article/v1"
|
||||
)
|
||||
|
||||
func (c *ControllerV1) Update(ctx context.Context, req *v1.UpdateReq) (res *v1.UpdateRes, err error) {
|
||||
return nil, gerror.NewCode(gcode.CodeNotImplemented)
|
||||
}
|
||||
14
cmd/gf/internal/cmd/testdata/genctrl/controller/article/article_v2_create.go
vendored
Normal file
14
cmd/gf/internal/cmd/testdata/genctrl/controller/article/article_v2_create.go
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
package article
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/gogf/gf/v2/errors/gcode"
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
|
||||
"github.com/gogf/gf/cmd/gf/v2/internal/cmd/testdata/genctrl/api/article/v2"
|
||||
)
|
||||
|
||||
func (c *ControllerV2) Create(ctx context.Context, req *v2.CreateReq) (res *v2.CreateRes, err error) {
|
||||
return nil, gerror.NewCode(gcode.CodeNotImplemented)
|
||||
}
|
||||
14
cmd/gf/internal/cmd/testdata/genctrl/controller/article/article_v2_update.go
vendored
Normal file
14
cmd/gf/internal/cmd/testdata/genctrl/controller/article/article_v2_update.go
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
package article
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/gogf/gf/v2/errors/gcode"
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
|
||||
"github.com/gogf/gf/cmd/gf/v2/internal/cmd/testdata/genctrl/api/article/v2"
|
||||
)
|
||||
|
||||
func (c *ControllerV2) Update(ctx context.Context, req *v2.UpdateReq) (res *v2.UpdateRes, err error) {
|
||||
return nil, gerror.NewCode(gcode.CodeNotImplemented)
|
||||
}
|
||||
85
cmd/gf/internal/cmd/testdata/gendao/generated_user/dao/internal/table_user.go
vendored
Normal file
85
cmd/gf/internal/cmd/testdata/gendao/generated_user/dao/internal/table_user.go
vendored
Normal file
@ -0,0 +1,85 @@
|
||||
// ==========================================================================
|
||||
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
// ==========================================================================
|
||||
|
||||
package internal
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/gogf/gf/v2/database/gdb"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
)
|
||||
|
||||
// TableUserDao is the data access object for table table_user.
|
||||
type TableUserDao struct {
|
||||
table string // table is the underlying table name of the DAO.
|
||||
group string // group is the database configuration group name of current DAO.
|
||||
columns TableUserColumns // columns contains all the column names of Table for convenient usage.
|
||||
}
|
||||
|
||||
// TableUserColumns defines and stores column names for table table_user.
|
||||
type TableUserColumns struct {
|
||||
Id string // User ID
|
||||
Passport string // User Passport
|
||||
Password string // User Password
|
||||
Nickname string // User Nickname
|
||||
Score string // Total score amount.
|
||||
CreateAt string // Created Time
|
||||
UpdateAt string // Updated Time
|
||||
}
|
||||
|
||||
// tableUserColumns holds the columns for table table_user.
|
||||
var tableUserColumns = TableUserColumns{
|
||||
Id: "id",
|
||||
Passport: "passport",
|
||||
Password: "password",
|
||||
Nickname: "nickname",
|
||||
Score: "score",
|
||||
CreateAt: "create_at",
|
||||
UpdateAt: "update_at",
|
||||
}
|
||||
|
||||
// NewTableUserDao creates and returns a new DAO object for table data access.
|
||||
func NewTableUserDao() *TableUserDao {
|
||||
return &TableUserDao{
|
||||
group: "test",
|
||||
table: "table_user",
|
||||
columns: tableUserColumns,
|
||||
}
|
||||
}
|
||||
|
||||
// DB retrieves and returns the underlying raw database management object of current DAO.
|
||||
func (dao *TableUserDao) DB() gdb.DB {
|
||||
return g.DB(dao.group)
|
||||
}
|
||||
|
||||
// Table returns the table name of current dao.
|
||||
func (dao *TableUserDao) Table() string {
|
||||
return dao.table
|
||||
}
|
||||
|
||||
// Columns returns all column names of current dao.
|
||||
func (dao *TableUserDao) Columns() TableUserColumns {
|
||||
return dao.columns
|
||||
}
|
||||
|
||||
// Group returns the configuration group name of database of current dao.
|
||||
func (dao *TableUserDao) Group() string {
|
||||
return dao.group
|
||||
}
|
||||
|
||||
// Ctx creates and returns the Model for current DAO, It automatically sets the context for current operation.
|
||||
func (dao *TableUserDao) Ctx(ctx context.Context) *gdb.Model {
|
||||
return dao.DB().Model(dao.table).Safe().Ctx(ctx)
|
||||
}
|
||||
|
||||
// Transaction wraps the transaction logic using function f.
|
||||
// It rollbacks the transaction and returns the error from function f if it returns non-nil error.
|
||||
// It commits the transaction and returns nil if function f returns nil.
|
||||
//
|
||||
// Note that, you should not Commit or Rollback the transaction in function f
|
||||
// as it is automatically handled by this function.
|
||||
func (dao *TableUserDao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) {
|
||||
return dao.Ctx(ctx).Transaction(ctx, f)
|
||||
}
|
||||
27
cmd/gf/internal/cmd/testdata/gendao/generated_user/dao/table_user.go
vendored
Normal file
27
cmd/gf/internal/cmd/testdata/gendao/generated_user/dao/table_user.go
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
// =================================================================================
|
||||
// This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish.
|
||||
// =================================================================================
|
||||
|
||||
package dao
|
||||
|
||||
import (
|
||||
"for-gendao-test/pkg/dao/internal"
|
||||
)
|
||||
|
||||
// internalTableUserDao is internal type for wrapping internal DAO implements.
|
||||
type internalTableUserDao = *internal.TableUserDao
|
||||
|
||||
// tableUserDao is the data access object for table table_user.
|
||||
// You can define custom methods on it to extend its functionality as you wish.
|
||||
type tableUserDao struct {
|
||||
internalTableUserDao
|
||||
}
|
||||
|
||||
var (
|
||||
// TableUser is globally public accessible object for table table_user operations.
|
||||
TableUser = tableUserDao{
|
||||
internal.NewTableUserDao(),
|
||||
}
|
||||
)
|
||||
|
||||
// Fill with you ideas below.
|
||||
22
cmd/gf/internal/cmd/testdata/gendao/generated_user/model/do/table_user.go
vendored
Normal file
22
cmd/gf/internal/cmd/testdata/gendao/generated_user/model/do/table_user.go
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
// =================================================================================
|
||||
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
// =================================================================================
|
||||
|
||||
package do
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
)
|
||||
|
||||
// TableUser is the golang structure of table table_user for DAO operations like Where/Data.
|
||||
type TableUser struct {
|
||||
g.Meta `orm:"table:table_user, do:true"`
|
||||
Id interface{} // User ID
|
||||
Passport interface{} // User Passport
|
||||
Password interface{} // User Password
|
||||
Nickname interface{} // User Nickname
|
||||
Score interface{} // Total score amount.
|
||||
CreateAt *gtime.Time // Created Time
|
||||
UpdateAt *gtime.Time // Updated Time
|
||||
}
|
||||
20
cmd/gf/internal/cmd/testdata/gendao/generated_user/model/entity/table_user.go
vendored
Normal file
20
cmd/gf/internal/cmd/testdata/gendao/generated_user/model/entity/table_user.go
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
// =================================================================================
|
||||
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
// =================================================================================
|
||||
|
||||
package entity
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
)
|
||||
|
||||
// TableUser is the golang structure for table table_user.
|
||||
type TableUser struct {
|
||||
Id uint `json:"ID" orm:"id" ` // User ID
|
||||
Passport string `json:"PASSPORT" orm:"passport" ` // User Passport
|
||||
Password string `json:"PASSWORD" orm:"password" ` // User Password
|
||||
Nickname string `json:"NICKNAME" orm:"nickname" ` // User Nickname
|
||||
Score float64 `json:"SCORE" orm:"score" ` // Total score amount.
|
||||
CreateAt *gtime.Time `json:"CREATE_AT" orm:"create_at" ` // Created Time
|
||||
UpdateAt *gtime.Time `json:"UPDATE_AT" orm:"update_at" ` // Updated Time
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user