mirror of
https://gitee.com/johng/gf
synced 2026-06-07 18:26:02 +08:00
Compare commits
154 Commits
revert-409
...
v2.9.7
| Author | SHA1 | Date | |
|---|---|---|---|
| dd62b18877 | |||
| cb4681ce3e | |||
| 7daf916032 | |||
| c82da1e57c | |||
| 90564f9fb0 | |||
| 4d6c7e3d3a | |||
| 18e77de02f | |||
| bf6238e178 | |||
| 887a776441 | |||
| 7274a7399a | |||
| b59824e9dc | |||
| 5cbe421aaa | |||
| 852c3dda62 | |||
| d8b857f930 | |||
| d353bf0fbc | |||
| baf30a0e99 | |||
| 6e0ba551f9 | |||
| 1650aab340 | |||
| bb9133ab9d | |||
| 48845c3473 | |||
| ea956189bf | |||
| 3912d97811 | |||
| 50fb349bc9 | |||
| 777d7aabb5 | |||
| 5a67aac85d | |||
| 132a5ab9a3 | |||
| 8575f01273 | |||
| ac75026716 | |||
| 485a9637cc | |||
| b57b49ecca | |||
| cdead46c79 | |||
| a4883e6e3d | |||
| fe8ba5e35f | |||
| 54b7c249fd | |||
| 99d69857fa | |||
| 1b26013a66 | |||
| 6c2155bd26 | |||
| 9018a3d4ac | |||
| 362d4202c4 | |||
| a85b221d32 | |||
| cb8594eb80 | |||
| ac88e640d1 | |||
| 2d307c5dd1 | |||
| 54453c8e8f | |||
| 072b962b81 | |||
| a80f58b7f6 | |||
| 1e3aa5f080 | |||
| fde47e8981 | |||
| c02148cd6b | |||
| 1d4e684949 | |||
| 8ff0de88b8 | |||
| ac3efe5a00 | |||
| 2744fe2212 | |||
| 1682cc98bb | |||
| 2742c98c06 | |||
| 4226a23a39 | |||
| b8e414e125 | |||
| 08c34b5ed7 | |||
| 416f314390 | |||
| 98f0c36a1d | |||
| 2b7b4c8581 | |||
| b8844f3d40 | |||
| 3e2176d799 | |||
| 2f9225057f | |||
| 7b373446dc | |||
| 0f6d47c7a8 | |||
| f24729206b | |||
| 7e9715ab1d | |||
| f565a347c4 | |||
| f172e61585 | |||
| 22d873f6bd | |||
| b60b04e27a | |||
| d2bc5d812b | |||
| 0648fd688e | |||
| d0cfcce85b | |||
| 2518d490c3 | |||
| edc96a8c16 | |||
| 22427a08ad | |||
| 41a5484620 | |||
| 325ee45a55 | |||
| 627aa5d27f | |||
| 47db44843e | |||
| a39498f74f | |||
| 80b866e11c | |||
| 2a77d3203e | |||
| 3c451bef82 | |||
| 5073f25691 | |||
| 40e97f1325 | |||
| 502d158bc0 | |||
| f08897a114 | |||
| b6181e4bde | |||
| f8cdeae2d7 | |||
| bea060af4c | |||
| 94cc233325 | |||
| 71743e6903 | |||
| f9ec3b19f7 | |||
| ee24da4e72 | |||
| 26f20787ba | |||
| 1371b3bad5 | |||
| 1da73451b9 | |||
| 94b623e126 | |||
| 4262aa254d | |||
| 8cff64915b | |||
| bec98e8de0 | |||
| a6dbf4b7eb | |||
| 0c2f60468b | |||
| 656ae070da | |||
| 2d5fcd73cb | |||
| 82043856f4 | |||
| 7ffdff37e4 | |||
| 24083b865d | |||
| 8cb64c9f88 | |||
| 5fa656d1cc | |||
| 09ec90746a | |||
| c0d1e44526 | |||
| b323862b4c | |||
| 3d9cdb8997 | |||
| 7180d895ea | |||
| afb1595fbe | |||
| 6637add9ca | |||
| bc862cf97b | |||
| 9033ca087b | |||
| b985fd978c | |||
| 88c4471500 | |||
| b73e2047db | |||
| 1534abdb05 | |||
| fee38b4531 | |||
| 69e3362d0d | |||
| 9a61a6970f | |||
| abf77fac50 | |||
| 07696fc779 | |||
| bc1e1019c5 | |||
| bb696bb281 | |||
| 029f324c5c | |||
| f8331bad6e | |||
| bcda48bf82 | |||
| a8a055f122 | |||
| dfe088f5cd | |||
| f4074cd815 | |||
| 4a65e7a629 | |||
| ac653d3dee | |||
| 2d3ab4f9fb | |||
| bda42d18ee | |||
| 63cb3285f8 | |||
| 2fa03556ef | |||
| 01593ad8b6 | |||
| 42d8845d35 | |||
| 1ef1c442d3 | |||
| 7d3b055d3e | |||
| a3b3c656d9 | |||
| 0eb229a887 | |||
| 20b1987828 | |||
| f9c7eae23b | |||
| 1f8845291a |
20
.github/PULL_REQUEST_TEMPLATE.MD
vendored
20
.github/PULL_REQUEST_TEMPLATE.MD
vendored
@ -1,16 +1,16 @@
|
||||
**Please ensure you adhere to every item in this list.**
|
||||
+ The PR title is formatted as follows: `<type>[optional scope]: <description>` For example, `fix(os/gtime): fix time zone issue`
|
||||
+ `<type>` is mandatory and can be one of `fix`, `feat`, `build`, `ci`, `docs`, `style`, `refactor`, `perf`, `test`, `chore`
|
||||
+ fix: Used when a bug has been fixed.
|
||||
+ feat: Used when a new feature has been added.
|
||||
+ build: Used for modifications to the project build system, such as changes to dependencies, external interfaces, or upgrading Node version.
|
||||
+ ci: Used for modifications to continuous integration processes, such as changes to Travis, Jenkins workflow configurations.
|
||||
+ docs: Used for modifications to documentation, such as changes to README files, API documentation, etc.
|
||||
+ style: Used for changes to code style, such as adjustments to indentation, spaces, blank lines, etc.
|
||||
+ refactor: Used for code refactoring, such as changes to code structure, variable names, function names, without altering functionality.
|
||||
+ perf: Used for performance optimization, such as improving code performance, reducing memory usage, etc.
|
||||
+ test: Used for modifications to test cases, such as adding, deleting, or modifying test cases for code.
|
||||
+ chore: Used for modifications to non-business-related code, such as changes to build processes or tool configurations.
|
||||
+ `fix`: Used when a bug has been fixed.
|
||||
+ `feat`: Used when a new feature has been added.
|
||||
+ `build`: Used for modifications to the project build system, such as changes to dependencies, external interfaces, or upgrading Node version.
|
||||
+ `ci`: Used for modifications to continuous integration processes, such as changes to Travis, Jenkins workflow configurations.
|
||||
+ `docs`: Used for modifications to documentation, such as changes to README files, API documentation, etc.
|
||||
+ `style`: Used for changes to code style, such as adjustments to indentation, spaces, blank lines, etc.
|
||||
+ `refactor`: Used for code refactoring, such as changes to code structure, variable names, function names, without altering functionality.
|
||||
+ `perf`: Used for performance optimization, such as improving code performance, reducing memory usage, etc.
|
||||
+ `test`: Used for modifications to test cases, such as adding, deleting, or modifying test cases for code.
|
||||
+ `chore`: Used for modifications to non-business-related code, such as changes to build processes or tool configurations.
|
||||
+ After `<type>`, specify the affected package name or scope in parentheses, for example, `(os/gtime)`.
|
||||
+ The part after the colon uses the verb tense + phrase that completes the blank in
|
||||
+ Lowercase verb after the colon
|
||||
|
||||
60
.github/workflows/ci-main.sh
vendored
60
.github/workflows/ci-main.sh
vendored
@ -1,60 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
coverage=$1
|
||||
|
||||
# find all path that contains go.mod.
|
||||
for file in `find . -name go.mod`; do
|
||||
dirpath=$(dirname $file)
|
||||
echo $dirpath
|
||||
|
||||
# ignore mssql tests as its docker service failed
|
||||
# TODO remove this ignoring codes after the mssql docker service OK
|
||||
if [ "mssql" = $(basename $dirpath) ]; then
|
||||
continue 1
|
||||
fi
|
||||
|
||||
# package kuhecm was moved to sub ci procedure.
|
||||
if [ "kubecm" = $(basename $dirpath) ]; then
|
||||
continue 1
|
||||
fi
|
||||
|
||||
# Check if it's a contrib directory or example directory
|
||||
if [[ $dirpath =~ "/contrib/" ]] || [ "example" = $(basename $dirpath) ]; then
|
||||
# Check if go version meets the requirement
|
||||
if ! go version | grep -qE "go${LATEST_GO_VERSION}"; then
|
||||
echo "ignore path $dirpath as go version is not ${LATEST_GO_VERSION}: $(go version)"
|
||||
continue 1
|
||||
fi
|
||||
# If it's example directory, only build without tests
|
||||
if [ "example" = $(basename $dirpath) ]; then
|
||||
echo "the example directory only needs to be built, not unit tests and coverage tests."
|
||||
cd $dirpath
|
||||
go mod tidy
|
||||
go build ./...
|
||||
cd -
|
||||
continue 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ $file =~ "/testdata/" ]]; then
|
||||
echo "ignore testdata path $file"
|
||||
continue 1
|
||||
fi
|
||||
|
||||
cd $dirpath
|
||||
go mod tidy
|
||||
go build ./...
|
||||
|
||||
# test with 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
|
||||
76
.github/workflows/ci-main.yml
vendored
76
.github/workflows/ci-main.yml
vendored
@ -20,6 +20,13 @@ on:
|
||||
- feature/**
|
||||
- enhance/**
|
||||
- fix/**
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
debug:
|
||||
type: boolean
|
||||
description: 'Enable tmate Debug'
|
||||
required: false
|
||||
default: false
|
||||
|
||||
# This allows a subsequently queued workflow run to interrupt previous runs
|
||||
concurrency:
|
||||
@ -29,7 +36,7 @@ concurrency:
|
||||
env:
|
||||
TZ: "Asia/Shanghai"
|
||||
# for unit testing cases of some components that only execute on the latest go version.
|
||||
LATEST_GO_VERSION: "1.23"
|
||||
LATEST_GO_VERSION: "1.25"
|
||||
|
||||
jobs:
|
||||
code-test:
|
||||
@ -38,19 +45,18 @@ jobs:
|
||||
# 🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥
|
||||
# When adding new go version to the list, make sure:
|
||||
# 1. Update the `LATEST_GO_VERSION` env variable.
|
||||
# 2. Update the `Report Coverage` action.
|
||||
# 🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥
|
||||
go-version: [ "1.20", "1.21", "1.22", "1.23" ]
|
||||
go-version: [ "1.23", "1.24", "1.25" ]
|
||||
goarch: [ "386", "amd64" ]
|
||||
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
# Service containers to run with `code-test`
|
||||
services:
|
||||
# Etcd service.
|
||||
# docker run -d --name etcd -p 2379:2379 -e ALLOW_NONE_AUTHENTICATION=yes bitnami/etcd:3.4.24
|
||||
# docker run -p 2379:2379 -e ALLOW_NONE_AUTHENTICATION=yes bitnamilegacy/etcd:3.4.24
|
||||
etcd:
|
||||
image: bitnami/etcd:3.4.24
|
||||
image: bitnamilegacy/etcd:3.4.24
|
||||
env:
|
||||
ALLOW_NONE_AUTHENTICATION: yes
|
||||
ports:
|
||||
@ -69,7 +75,7 @@ jobs:
|
||||
- 6379:6379
|
||||
|
||||
# MySQL backend server.
|
||||
# docker run -d --name mysql \
|
||||
# docker run \
|
||||
# -p 3306:3306 \
|
||||
# -e MYSQL_DATABASE=test \
|
||||
# -e MYSQL_ROOT_PASSWORD=12345678 \
|
||||
@ -83,7 +89,7 @@ jobs:
|
||||
- 3306:3306
|
||||
|
||||
# MariaDb backend server.
|
||||
# docker run -d --name mariadb \
|
||||
# docker run \
|
||||
# -p 3307:3306 \
|
||||
# -e MYSQL_DATABASE=test \
|
||||
# -e MYSQL_ROOT_PASSWORD=12345678 \
|
||||
@ -97,7 +103,7 @@ jobs:
|
||||
- 3307:3306
|
||||
|
||||
# PostgreSQL backend server.
|
||||
# docker run -d --name postgres \
|
||||
# docker run \
|
||||
# -p 5432:5432 \
|
||||
# -e POSTGRES_PASSWORD=12345678 \
|
||||
# -e POSTGRES_USER=postgres \
|
||||
@ -144,7 +150,7 @@ jobs:
|
||||
--health-retries 10
|
||||
|
||||
# ClickHouse backend server.
|
||||
# docker run -d --name clickhouse \
|
||||
# docker run \
|
||||
# -p 9000:9000 -p 8123:8123 -p 9001:9001 \
|
||||
# clickhouse/clickhouse-server:24.11.1.2557-alpine
|
||||
clickhouse-server:
|
||||
@ -155,15 +161,11 @@ jobs:
|
||||
- 9001:9001
|
||||
|
||||
# Polaris backend server.
|
||||
# docker run -d --name polaris \
|
||||
# docker run \
|
||||
# -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
|
||||
# polarismesh/polaris-standalone:v1.17.2
|
||||
polaris:
|
||||
image: loads/polaris-standalone:v1.17.2
|
||||
image: polarismesh/polaris-standalone:v1.17.2
|
||||
ports:
|
||||
- 8090:8090
|
||||
- 8091:8091
|
||||
@ -196,6 +198,17 @@ jobs:
|
||||
ports:
|
||||
- 5236:5236
|
||||
|
||||
# openGauss server
|
||||
# docker run --privileged=true -e GS_PASSWORD=UTpass@1234 -p 9950:5432 opengauss/opengauss:7.0.0-RC1.B023
|
||||
gaussdb:
|
||||
image: opengauss/opengauss:7.0.0-RC1.B023
|
||||
env:
|
||||
GS_PASSWORD: UTpass@1234
|
||||
TZ: Asia/Shanghai
|
||||
ports:
|
||||
- 9950:5432
|
||||
|
||||
|
||||
zookeeper:
|
||||
image: zookeeper:3.8
|
||||
ports:
|
||||
@ -210,7 +223,20 @@ jobs:
|
||||
timezoneLinux: "Asia/Shanghai"
|
||||
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Setup tmate Session
|
||||
uses: mxschmitt/action-tmate@v3
|
||||
if: ${{ github.event_name == 'workflow_dispatch' && inputs.debug }}
|
||||
with:
|
||||
detached: true
|
||||
limit-access-to-actor: false
|
||||
|
||||
- name: Free Disk Space
|
||||
run: |
|
||||
df -h /
|
||||
sudo rm -rf /usr/share/dotnet /usr/local/lib/android /opt/hostedtoolcache/CodeQL /opt/hostedtoolcache/Python || true
|
||||
df -h /
|
||||
|
||||
- name: Start Apollo Containers
|
||||
run: docker compose -f ".github/workflows/apollo/docker-compose.yml" up -d --build
|
||||
@ -231,9 +257,9 @@ jobs:
|
||||
cache-dependency-path: '**/go.sum'
|
||||
|
||||
- name: Install Protoc
|
||||
uses: arduino/setup-protoc@v2
|
||||
uses: arduino/setup-protoc@v3
|
||||
with:
|
||||
version: "29.x"
|
||||
version: "31.x"
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Install the protocol compiler plugins for Go
|
||||
@ -243,15 +269,15 @@ jobs:
|
||||
export PATH="$PATH:$(go env GOPATH)/bin"
|
||||
|
||||
- name: Before Script
|
||||
run: bash .github/workflows/before_script.sh
|
||||
run: bash .github/workflows/scripts/before_script.sh
|
||||
|
||||
- name: Build & Test
|
||||
if: ${{ (github.event_name == 'push' && github.ref != 'refs/heads/master') || github.event_name == 'pull_request' }}
|
||||
run: bash .github/workflows/ci-main.sh
|
||||
run: bash .github/workflows/scripts/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
|
||||
run: bash .github/workflows/scripts/ci-main.sh coverage
|
||||
|
||||
- name: Stop Redis Cluster Containers
|
||||
run: docker compose -f ".github/workflows/redis/docker-compose.yml" down
|
||||
@ -267,8 +293,8 @@ jobs:
|
||||
|
||||
- name: Report Coverage
|
||||
uses: codecov/codecov-action@v4
|
||||
# Only report coverage on the latest go version and amd64 arch
|
||||
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' && matrix.go-version == '1.23' && matrix.goarch == 'amd64' }}
|
||||
# Only report coverage on the latest go version
|
||||
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' && matrix.go-version == env.LATEST_GO_VERSION }}
|
||||
with:
|
||||
flags: go-${{ matrix.go-version }}-${{ matrix.goarch }}
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
|
||||
27
.github/workflows/ci-sub.sh
vendored
27
.github/workflows/ci-sub.sh
vendored
@ -1,27 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
coverage=$1
|
||||
|
||||
# find all path that contains go.mod.
|
||||
for file in `find . -name go.mod`; do
|
||||
dirpath=$(dirname $file)
|
||||
echo $dirpath
|
||||
|
||||
# package kuhecm needs golang >= v1.19
|
||||
if [ "kubecm" = $(basename $dirpath) ]; then
|
||||
if ! go version|grep -qE "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
|
||||
10
.github/workflows/ci-sub.yml
vendored
10
.github/workflows/ci-sub.yml
vendored
@ -30,7 +30,7 @@ concurrency:
|
||||
env:
|
||||
TZ: "Asia/Shanghai"
|
||||
# for unit testing cases of some components that only execute on the latest go version.
|
||||
LATEST_GO_VERSION: "1.23"
|
||||
LATEST_GO_VERSION: "1.25"
|
||||
|
||||
jobs:
|
||||
code-test:
|
||||
@ -40,7 +40,7 @@ jobs:
|
||||
# When adding new go version to the list, make sure:
|
||||
# 1. Update the `LATEST_GO_VERSION` env variable.
|
||||
# 🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥🔥
|
||||
go-version: [ "1.20", "1.21", "1.22", "1.23" ]
|
||||
go-version: [ "1.23", "1.24", "1.25" ]
|
||||
goarch: [ "386", "amd64" ]
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
@ -52,7 +52,7 @@ jobs:
|
||||
timezoneLinux: "Asia/Shanghai"
|
||||
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Start Minikube
|
||||
uses: medyagh/setup-minikube@master
|
||||
@ -64,9 +64,9 @@ jobs:
|
||||
cache-dependency-path: '**/go.sum'
|
||||
|
||||
- name: Before Script
|
||||
run: bash .github/workflows/before_script.sh
|
||||
run: bash .github/workflows/scripts/before_script.sh
|
||||
|
||||
- name: Build & Test
|
||||
run: bash .github/workflows/ci-sub.sh
|
||||
run: bash .github/workflows/scripts/ci-sub.sh
|
||||
|
||||
|
||||
|
||||
100
.github/workflows/codeql.yml
vendored
Normal file
100
.github/workflows/codeql.yml
vendored
Normal file
@ -0,0 +1,100 @@
|
||||
# For most projects, this workflow file will not need changing; you simply need
|
||||
# to commit it to your repository.
|
||||
#
|
||||
# You may wish to alter this file to override the set of languages analyzed,
|
||||
# or to provide custom queries or build logic.
|
||||
#
|
||||
# ******** NOTE ********
|
||||
# We have attempted to detect the languages in your repository. Please check
|
||||
# the `language` matrix defined below to confirm you have the correct set of
|
||||
# supported CodeQL languages.
|
||||
#
|
||||
name: "CodeQL Advanced"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "master", "develop" ]
|
||||
pull_request:
|
||||
branches: [ "master", "develop" ]
|
||||
schedule:
|
||||
- cron: '0 21 * * *'
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
name: Analyze (${{ matrix.language }})
|
||||
# Runner size impacts CodeQL analysis time. To learn more, please see:
|
||||
# - https://gh.io/recommended-hardware-resources-for-running-codeql
|
||||
# - https://gh.io/supported-runners-and-hardware-resources
|
||||
# - https://gh.io/using-larger-runners (GitHub.com only)
|
||||
# Consider using larger runners or machines with greater resources for possible analysis time improvements.
|
||||
runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }}
|
||||
permissions:
|
||||
# required for all workflows
|
||||
security-events: write
|
||||
|
||||
# required to fetch internal or private CodeQL packs
|
||||
packages: read
|
||||
|
||||
# only required for workflows in private repositories
|
||||
actions: read
|
||||
contents: read
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- language: actions
|
||||
build-mode: none
|
||||
- language: go
|
||||
build-mode: autobuild
|
||||
# CodeQL supports the following values keywords for 'language': 'actions', 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'rust', 'swift'
|
||||
# Use `c-cpp` to analyze code written in C, C++ or both
|
||||
# Use 'java-kotlin' to analyze code written in Java, Kotlin or both
|
||||
# Use 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both
|
||||
# To learn more about changing the languages that are analyzed or customizing the build mode for your analysis,
|
||||
# see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning.
|
||||
# If you are analyzing a compiled language, you can modify the 'build-mode' for that language to customize how
|
||||
# your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
# Add any setup steps before running the `github/codeql-action/init` action.
|
||||
# This includes steps like installing compilers or runtimes (`actions/setup-node`
|
||||
# or others). This is typically only required for manual builds.
|
||||
# - name: Setup runtime (example)
|
||||
# uses: actions/setup-example@v1
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v3
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
build-mode: ${{ matrix.build-mode }}
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
# By default, queries listed here will override any specified in a config file.
|
||||
# Prefix the list here with "+" to use these queries and those in the config file.
|
||||
|
||||
# For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
|
||||
# queries: security-extended,security-and-quality
|
||||
|
||||
# If the analyze step fails for one of the languages you are analyzing with
|
||||
# "We were unable to automatically build your code", modify the matrix above
|
||||
# to set the build mode to "manual" for that language. Then modify this step
|
||||
# to build your code.
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
|
||||
- if: matrix.build-mode == 'manual'
|
||||
shell: bash
|
||||
run: |
|
||||
echo 'If you are using a "manual" build mode for one or more of the' \
|
||||
'languages you are analyzing, replace this with the commands to build' \
|
||||
'your code, for example:'
|
||||
echo ' make bootstrap'
|
||||
echo ' make release'
|
||||
exit 1
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v3
|
||||
with:
|
||||
category: "/language:${{matrix.language}}"
|
||||
38
.github/workflows/doc-build.yml
vendored
38
.github/workflows/doc-build.yml
vendored
@ -1,38 +0,0 @@
|
||||
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@v4
|
||||
with:
|
||||
ref: doc-build
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18
|
||||
cache: npm
|
||||
- name: Set Up Golang Environment
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: 1.23.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@v4
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
publish_dir: ./build
|
||||
cname: pages.goframe.org
|
||||
2
.github/workflows/format-code-on-push.yml
vendored
2
.github/workflows/format-code-on-push.yml
vendored
@ -12,7 +12,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
- name: Setup Golang ${{ matrix.go-version }}
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
|
||||
2
.github/workflows/gitee-sync.yml
vendored
2
.github/workflows/gitee-sync.yml
vendored
@ -12,7 +12,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout source code
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
- name: Mirror GitHub to Gitee
|
||||
uses: Yikun/hub-mirror-action@v1.4
|
||||
with:
|
||||
|
||||
14
.github/workflows/golangci-lint.yml
vendored
14
.github/workflows/golangci-lint.yml
vendored
@ -4,7 +4,7 @@
|
||||
# If a copy of the MIT was not distributed with this file,
|
||||
# You can obtain one at https://github.com/gogf/gf.
|
||||
|
||||
name: GolangCI Lint
|
||||
name: golangci-lint
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
@ -29,22 +29,24 @@ jobs:
|
||||
golang-ci:
|
||||
strategy:
|
||||
matrix:
|
||||
go-version: [ 'stable' ]
|
||||
go-version: [ "stable" ]
|
||||
|
||||
name: golang-ci-lint
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Setup Golang ${{ matrix.go-version }}
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: ${{ matrix.go-version }}
|
||||
- name: golang-ci-lint
|
||||
uses: golangci/golangci-lint-action@v6
|
||||
uses: golangci/golangci-lint-action@v8
|
||||
with:
|
||||
# Required: specify the golangci-lint version without the patch version to always use the latest patch.
|
||||
version: v1.62.2
|
||||
only-new-issues: true
|
||||
skip-cache: true
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
args: --timeout 3m0s --config=.golangci.yml -v
|
||||
args: --config=.golangci.yml -v
|
||||
|
||||
2
.github/workflows/issue-check-inactive.yml
vendored
2
.github/workflows/issue-check-inactive.yml
vendored
@ -23,6 +23,6 @@ jobs:
|
||||
with:
|
||||
actions: 'check-inactive'
|
||||
inactive-label: 'inactive'
|
||||
inactive-day: 7
|
||||
inactive-day: 30
|
||||
issue-state: open
|
||||
exclude-labels: 'bug,planned,$exclude-empty'
|
||||
2
.github/workflows/nacos/docker-compose.yml
vendored
2
.github/workflows/nacos/docker-compose.yml
vendored
@ -17,7 +17,7 @@ services:
|
||||
retries: 10
|
||||
|
||||
initializer:
|
||||
image: loads/curl:latest
|
||||
image: alpine/curl:latest
|
||||
depends_on:
|
||||
nacos:
|
||||
condition: service_healthy
|
||||
|
||||
11
.github/workflows/release.yml
vendored
11
.github/workflows/release.yml
vendored
@ -16,12 +16,13 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout Github Code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Set Up Golang Environment
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: 1.23.4
|
||||
go-version: 1.25
|
||||
cache: false
|
||||
|
||||
- name: Build CLI Binary
|
||||
run: |
|
||||
@ -34,7 +35,7 @@ jobs:
|
||||
- name: Build CLI Binary For All Platform
|
||||
run: |
|
||||
cd cmd/gf
|
||||
gf build main.go -n gf -a all -s all -p temp
|
||||
gf build main.go -n gf -a all -s linux,windows,darwin,freebsd,netbsd,openbsd -p temp
|
||||
|
||||
- name: Move Files Before Release
|
||||
run: |
|
||||
@ -52,7 +53,7 @@ jobs:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
tag_name: ${{ github.ref }}
|
||||
name: GoFrame Release ${{ github.ref }}
|
||||
name: GoFrame Release ${{ github.ref_name }}
|
||||
draft: false
|
||||
prerelease: false
|
||||
|
||||
|
||||
80
.github/workflows/scorecard.yml
vendored
Normal file
80
.github/workflows/scorecard.yml
vendored
Normal file
@ -0,0 +1,80 @@
|
||||
# This workflow uses actions that are not certified by GitHub. They are provided
|
||||
# by a third-party and are governed by separate terms of service, privacy
|
||||
# policy, and support documentation.
|
||||
|
||||
name: Scorecard supply-chain security
|
||||
on:
|
||||
# For Branch-Protection check. Only the default branch is supported. See
|
||||
# https://github.com/ossf/scorecard/blob/main/docs/checks.md#branch-protection
|
||||
branch_protection_rule:
|
||||
# To guarantee Maintained check is occasionally updated. See
|
||||
# https://github.com/ossf/scorecard/blob/main/docs/checks.md#maintained
|
||||
schedule:
|
||||
- cron: '0 21 * * *'
|
||||
push:
|
||||
branches: [ "master" ]
|
||||
pull_request:
|
||||
branches: [ "master" ]
|
||||
|
||||
# Declare default permissions as read only.
|
||||
permissions: read-all
|
||||
|
||||
jobs:
|
||||
analysis:
|
||||
name: Scorecard analysis
|
||||
runs-on: ubuntu-latest
|
||||
# `publish_results: true` only works when run from the default branch. conditional can be removed if disabled.
|
||||
if: github.event.repository.default_branch == github.ref_name || github.event_name == 'pull_request'
|
||||
permissions:
|
||||
# Needed to upload the results to code-scanning dashboard.
|
||||
security-events: write
|
||||
# Needed to publish results and get a badge (see publish_results below).
|
||||
id-token: write
|
||||
# Uncomment the permissions below if installing in a private repository.
|
||||
# contents: read
|
||||
# actions: read
|
||||
|
||||
steps:
|
||||
- name: "Checkout code"
|
||||
uses: actions/checkout@v4.2.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: "Run analysis"
|
||||
uses: ossf/scorecard-action@v2.4.1
|
||||
with:
|
||||
results_file: results.sarif
|
||||
results_format: sarif
|
||||
# (Optional) "write" PAT token. Uncomment the `repo_token` line below if:
|
||||
# - you want to enable the Branch-Protection check on a *public* repository, or
|
||||
# - you are installing Scorecard on a *private* repository
|
||||
# To create the PAT, follow the steps in https://github.com/ossf/scorecard-action?tab=readme-ov-file#authentication-with-fine-grained-pat-optional.
|
||||
# repo_token: ${{ secrets.SCORECARD_TOKEN }}
|
||||
|
||||
# Public repositories:
|
||||
# - Publish results to OpenSSF REST API for easy access by consumers
|
||||
# - Allows the repository to include the Scorecard badge.
|
||||
# - See https://github.com/ossf/scorecard-action#publishing-results.
|
||||
# For private repositories:
|
||||
# - `publish_results` will always be set to `false`, regardless
|
||||
# of the value entered here.
|
||||
publish_results: true
|
||||
|
||||
# (Optional) Uncomment file_mode if you have a .gitattributes with files marked export-ignore
|
||||
# file_mode: git
|
||||
|
||||
# Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF
|
||||
# format to the repository Actions tab.
|
||||
- name: "Upload artifact"
|
||||
uses: actions/upload-artifact@v4.6.1
|
||||
with:
|
||||
name: SARIF file
|
||||
path: results.sarif
|
||||
retention-days: 5
|
||||
|
||||
# Upload the results to GitHub's code scanning dashboard (optional).
|
||||
# Commenting out will disable upload of results to your repo's Code Scanning dashboard
|
||||
- name: "Upload to code-scanning"
|
||||
uses: github/codeql-action/upload-sarif@v3
|
||||
with:
|
||||
sarif_file: results.sarif
|
||||
0
.github/workflows/before_script.sh → .github/workflows/scripts/before_script.sh
vendored
Normal file → Executable file
0
.github/workflows/before_script.sh → .github/workflows/scripts/before_script.sh
vendored
Normal file → Executable file
250
.github/workflows/scripts/ci-main-clean.sh
vendored
Executable file
250
.github/workflows/scripts/ci-main-clean.sh
vendored
Executable file
@ -0,0 +1,250 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
dirpath=$1
|
||||
|
||||
# Extract the base directory name for pattern matching
|
||||
if [ -n "$dirpath" ]; then
|
||||
dirname=$(basename "$dirpath")
|
||||
echo "Cleaning Docker resources for path: $dirpath (pattern: $dirname)"
|
||||
df -h /
|
||||
|
||||
# Process containers and images based on the directory
|
||||
case "$dirname" in
|
||||
# "mysql")
|
||||
# echo "Cleaning mysql resources..."
|
||||
# containers=$(docker ps -aq --filter "name=$dirname" 2>/dev/null)
|
||||
# if [ -n "$containers" ]; then
|
||||
# echo "Stopping and removing mysql containers..."
|
||||
# docker stop $containers 2>/dev/null || true
|
||||
# docker rm -f $containers 2>/dev/null || true
|
||||
# fi
|
||||
# docker rmi -f $(docker images -q mysql 2>/dev/null) 2>/dev/null || true
|
||||
# ;;
|
||||
"mssql")
|
||||
echo "Cleaning mssql resources..."
|
||||
containers=$(docker ps -aq --filter "name=$dirname" 2>/dev/null)
|
||||
if [ -n "$containers" ]; then
|
||||
echo "Stopping and removing mssql containers..."
|
||||
docker stop $containers 2>/dev/null || true
|
||||
docker rm -f $containers 2>/dev/null || true
|
||||
fi
|
||||
docker rmi -f $(docker images -q mcr.microsoft.com/mssql/server 2>/dev/null) 2>/dev/null || true
|
||||
;;
|
||||
"pgsql")
|
||||
echo "Cleaning postgres resources..."
|
||||
containers=$(docker ps -aq --filter "name=$dirname" 2>/dev/null)
|
||||
if [ -n "$containers" ]; then
|
||||
echo "Stopping and removing postgres containers..."
|
||||
docker stop $containers 2>/dev/null || true
|
||||
docker rm -f $containers 2>/dev/null || true
|
||||
fi
|
||||
docker rmi -f $(docker images -q postgres 2>/dev/null) 2>/dev/null || true
|
||||
;;
|
||||
"oracle")
|
||||
echo "Cleaning oracle resources..."
|
||||
containers=$(docker ps -aq --filter "name=$dirname" 2>/dev/null)
|
||||
if [ -n "$containers" ]; then
|
||||
echo "Stopping and removing oracle containers..."
|
||||
docker stop $containers 2>/dev/null || true
|
||||
docker rm -f $containers 2>/dev/null || true
|
||||
fi
|
||||
docker rmi -f $(docker images -q loads/oracle-xe-11g-r2 2>/dev/null) 2>/dev/null || true
|
||||
;;
|
||||
"dm")
|
||||
echo "Cleaning dm resources..."
|
||||
containers=$(docker ps -aq --filter "name=$dirname" 2>/dev/null)
|
||||
if [ -n "$containers" ]; then
|
||||
echo "Stopping and removing dm containers..."
|
||||
docker stop $containers 2>/dev/null || true
|
||||
docker rm -f $containers 2>/dev/null || true
|
||||
fi
|
||||
docker rmi -f $(docker images -q loads/dm 2>/dev/null) 2>/dev/null || true
|
||||
;;
|
||||
"clickhouse")
|
||||
echo "Cleaning clickhouse resources..."
|
||||
containers=$(docker ps -aq --filter "name=$dirname" 2>/dev/null)
|
||||
if [ -n "$containers" ]; then
|
||||
echo "Stopping and removing clickhouse containers..."
|
||||
docker stop $containers 2>/dev/null || true
|
||||
docker rm -f $containers 2>/dev/null || true
|
||||
fi
|
||||
docker rmi -f $(docker images -q clickhouse/clickhouse-server 2>/dev/null) 2>/dev/null || true
|
||||
;;
|
||||
# "redis")
|
||||
# echo "Cleaning redis resources..."
|
||||
# containers=$(docker ps -aq --filter "name=$dirname" 2>/dev/null)
|
||||
# if [ -n "$containers" ]; then
|
||||
# echo "Stopping and removing redis containers..."
|
||||
# docker stop $containers 2>/dev/null || true
|
||||
# docker rm -f $containers 2>/dev/null || true
|
||||
# fi
|
||||
# docker rmi -f $(docker images -q redis loads/redis loads/redis-sentinel 2>/dev/null) 2>/dev/null || true
|
||||
# ;;
|
||||
"etcd")
|
||||
echo "Cleaning etcd resources..."
|
||||
containers=$(docker ps -aq --filter "name=$dirname" 2>/dev/null)
|
||||
if [ -n "$containers" ]; then
|
||||
echo "Stopping and removing etcd containers..."
|
||||
docker stop $containers 2>/dev/null || true
|
||||
docker rm -f $containers 2>/dev/null || true
|
||||
fi
|
||||
docker rmi -f $(docker images -q bitnamilegacy/etcd 2>/dev/null) 2>/dev/null || true
|
||||
;;
|
||||
# "consul")
|
||||
# echo "Cleaning consul resources..."
|
||||
# containers=$(docker ps -aq --filter "name=$dirname" 2>/dev/null)
|
||||
# if [ -n "$containers" ]; then
|
||||
# echo "Stopping and removing consul containers..."
|
||||
# docker stop $containers 2>/dev/null || true
|
||||
# docker rm -f $containers 2>/dev/null || true
|
||||
# fi
|
||||
# docker rmi -f $(docker images -q consul 2>/dev/null) 2>/dev/null || true
|
||||
# ;;
|
||||
# "nacos")
|
||||
# echo "Cleaning nacos resources..."
|
||||
# containers=$(docker ps -aq --filter "name=$dirname" 2>/dev/null)
|
||||
# if [ -n "$containers" ]; then
|
||||
# echo "Stopping and removing nacos containers..."
|
||||
# docker stop $containers 2>/dev/null || true
|
||||
# docker rm -f $containers 2>/dev/null || true
|
||||
# fi
|
||||
# docker rmi -f $(docker images -q nacos/nacos-server 2>/dev/null) 2>/dev/null || true
|
||||
# ;;
|
||||
# "polaris")
|
||||
# echo "Cleaning polaris resources..."
|
||||
# containers=$(docker ps -aq --filter "name=$dirname" 2>/dev/null)
|
||||
# if [ -n "$containers" ]; then
|
||||
# echo "Stopping and removing polaris containers..."
|
||||
# docker stop $containers 2>/dev/null || true
|
||||
# docker rm -f $containers 2>/dev/null || true
|
||||
# fi
|
||||
# docker rmi -f $(docker images -q polarismesh/polaris-standalone 2>/dev/null) 2>/dev/null || true
|
||||
# ;;
|
||||
"zookeeper")
|
||||
echo "Cleaning zookeeper resources..."
|
||||
containers=$(docker ps -aq --filter "name=$dirname" 2>/dev/null)
|
||||
if [ -n "$containers" ]; then
|
||||
echo "Stopping and removing zookeeper containers..."
|
||||
docker stop $containers 2>/dev/null || true
|
||||
docker rm -f $containers 2>/dev/null || true
|
||||
fi
|
||||
docker rmi -f $(docker images -q zookeeper 2>/dev/null) 2>/dev/null || true
|
||||
;;
|
||||
# "apollo")
|
||||
# echo "Cleaning apollo resources..."
|
||||
# containers=$(docker ps -aq --filter "name=$dirname" 2>/dev/null)
|
||||
# if [ -n "$containers" ]; then
|
||||
# echo "Stopping and removing apollo containers..."
|
||||
# docker stop $containers 2>/dev/null || true
|
||||
# docker rm -f $containers 2>/dev/null || true
|
||||
# fi
|
||||
# docker rmi -f $(docker images -q loads/apollo-quick-start 2>/dev/null) 2>/dev/null || true
|
||||
# ;;
|
||||
*)
|
||||
# No matching pattern, skip cleanup
|
||||
echo "No specific Docker cleanup rule for '$dirname', skipping cleanup"
|
||||
;;
|
||||
esac
|
||||
|
||||
# Remove dangling images and volumes to free up space
|
||||
echo "Removing dangling images and unused volumes..."
|
||||
docker image prune -f 2>/dev/null || true
|
||||
docker volume prune -f 2>/dev/null || true
|
||||
|
||||
echo "Docker cleanup completed for $dirname"
|
||||
docker system df
|
||||
df -h /
|
||||
fi
|
||||
|
||||
# df -h /
|
||||
# Filesystem Size Used Avail Use% Mounted on
|
||||
# /dev/root 72G 67G 5.4G 93% /
|
||||
# tmpfs 7.9G 84K 7.9G 1% /dev/shm
|
||||
# tmpfs 3.2G 2.6M 3.2G 1% /run
|
||||
# tmpfs 5.0M 0 5.0M 0% /run/lock
|
||||
# /dev/sdb16 881M 62M 758M 8% /boot
|
||||
# /dev/sdb15 105M 6.2M 99M 6% /boot/efi
|
||||
# /dev/sda1 74G 4.1G 66G 6% /mnt
|
||||
# tmpfs 1.6G 12K 1.6G 1% /run/user/1001
|
||||
|
||||
# runner@runnervmg1sw1:~/work/gf/gf$ docker system df
|
||||
# TYPE TOTAL ACTIVE SIZE RECLAIMABLE
|
||||
# Images 18 11 8.326GB 1.644GB (19%)
|
||||
# Containers 11 11 2.692GB 0B (0%)
|
||||
# Local Volumes 11 8 665.7MB 211.9MB (31%)
|
||||
# Build Cache 0 0 0B 0B
|
||||
|
||||
# runner@runnervmg1sw1:~/work/gf/gf$ docker images
|
||||
# REPOSITORY TAG IMAGE ID CREATED SIZE
|
||||
# alpine/curl latest 99fd43792a61 2 days ago 13.5MB
|
||||
# postgres 17-alpine b6bf692a8125 9 days ago 278MB
|
||||
# zookeeper 3.8 2f26c02b94ca 10 days ago 306MB
|
||||
# mariadb 11.4 063fb6684f96 10 days ago 332MB
|
||||
# mcr.microsoft.com/mssql/server 2022-latest a2fbff321505 4 weeks ago 1.61GB
|
||||
# clickhouse/clickhouse-server 24.11.1.2557-alpine 2eee9fd3ae74 12 months ago 539MB
|
||||
# redis 7.0 7705dd2858c1 18 months ago 109MB
|
||||
# consul 1.15 686495461132 20 months ago 155MB
|
||||
# mysql 5.7 5107333e08a8 23 months ago 501MB
|
||||
# polarismesh/polaris-standalone v1.17.2 b7a8cf0a8438 2 years ago 545MB
|
||||
# bitnamilegacy/etcd 3.4.24 74ae5e205ac5 2 years ago 134MB
|
||||
# nacos/nacos-server v2.1.2 a978644d9246 2 years ago 1.06GB
|
||||
# loads/redis 7.0-sentinel 6f12d40540ba 3 years ago 114MB
|
||||
# loads/dm v8.1.2.128_ent_x86_64_ctm_pack4 ccb727ce9dce 3 years ago 432MB
|
||||
# loads/redis-sentinel 7.0 6818c626f5ca 3 years ago 104MB
|
||||
# loads/apollo-quick-start latest 8490de672148 3 years ago 190MB
|
||||
# alpine 3.8 c8bccc0af957 5 years ago 4.41MB
|
||||
# loads/oracle-xe-11g-r2 11.2.0 0d19fd2e072e 6 years ago 2.1GB
|
||||
|
||||
# runner@runnervmg1sw1:~/work/gf/gf$ docker ps -s
|
||||
# CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES SIZE
|
||||
# 8214f83420c6 zookeeper:3.8 "/docker-entrypoint.…" 6 minutes ago Up 6 minutes 2888/tcp, 3888/tcp, 0.0.0.0:2181->2181/tcp, [::]:2181->2181/tcp, 8080/tcp d66bac92ae9646f688f70ed4b5176f14_zookeeper38_3a22ef 33kB (virtual 306MB)
|
||||
# 8938d73842e8 loads/dm:v8.1.2.128_ent_x86_64_ctm_pack4 "/bin/bash /opt/star…" 6 minutes ago Up 6 minutes 0.0.0.0:5236->5236/tcp, [::]:5236->5236/tcp ca280fbdb86f40c2acf86d7d526c6285_loadsdmv812128_ent_x86_64_ctm_pack4_770a59 844MB (virtual 1.28GB)
|
||||
# 0d3a653fe1f2 loads/oracle-xe-11g-r2:11.2.0 "/bin/sh -c '/usr/sb…" 6 minutes ago Up 6 minutes 22/tcp, 8080/tcp, 0.0.0.0:1521->1521/tcp, [::]:1521->1521/tcp 2048856d428c4967b1c35193eb8c9192_loadsoraclexe11gr21120_295d54 1.3GB (virtual 3.4GB)
|
||||
# ca3936189166 polarismesh/polaris-standalone:v1.17.2 "/bin/bash run.sh" 6 minutes ago Up 6 minutes 0.0.0.0:8090-8091->8090-8091/tcp, [::]:8090-8091->8090-8091/tcp, 8080/tcp, 8100-8101/tcp, 0.0.0.0:8093->8093/tcp, [::]:8093->8093/tcp, 8761/tcp, 15010/tcp, 0.0.0.0:9090-9091->9090-9091/tcp, [::]:9090-9091->9090-9091/tcp cbd43dceef754e2d8aab507e33167be7_polarismeshpolarisstandalonev1172_ca40b6 299MB (virtual 844MB)
|
||||
# 26169dad485e clickhouse/clickhouse-server:24.11.1.2557-alpine "/entrypoint.sh" 6 minutes ago Up 6 minutes 0.0.0.0:8123->8123/tcp, [::]:8123->8123/tcp, 0.0.0.0:9000-9001->9000-9001/tcp, [::]:9000-9001->9000-9001/tcp, 9009/tcp f1c7766fbe36401792a6f735d7acf123_clickhouseclickhouseserver241112557alpine_cfc034 338kB (virtual 539MB)
|
||||
# 04689a1d581f mcr.microsoft.com/mssql/server:2022-latest "/opt/mssql/bin/laun…" 6 minutes ago Up 6 minutes (healthy) 0.0.0.0:1433->1433/tcp, [::]:1433->1433/tcp 41d685349a7640b28230db8d0f60efe7_mcrmicrosoftcommssqlserver2022latest_fe29fb 108MB (virtual 1.72GB)
|
||||
# d5fbc5f811af postgres:17-alpine "docker-entrypoint.s…" 6 minutes ago Up 6 minutes (healthy) 0.0.0.0:5432->5432/tcp, [::]:5432->5432/tcp 2783be71b5ce417ab9a31428e7b4d8f2_postgres17alpine_c60840 63B (virtual 278MB)
|
||||
# da96a7ad7a01 mariadb:11.4 "docker-entrypoint.s…" 7 minutes ago Up 7 minutes 0.0.0.0:3307->3306/tcp, [::]:3307->3306/tcp 45eed646fa6c4a698893ee11cda95a4c_mariadb114_3a9cd6 2B (virtual 332MB)
|
||||
# 27ba1904ba3a mysql:5.7 "docker-entrypoint.s…" 7 minutes ago Up 7 minutes 0.0.0.0:3306->3306/tcp, [::]:3306->3306/tcp, 33060/tcp ea6d7a4c207d427a95b5ae0db91fdf56_mysql57_c21053 4B (virtual 501MB)
|
||||
# 518e785d1bb6 redis:7.0 "docker-entrypoint.s…" 7 minutes ago Up 7 minutes (healthy) 0.0.0.0:6379->6379/tcp, [::]:6379->6379/tcp af6044fc849e441bbc6c48f7a5ec5fec_redis70_b11994 0B (virtual 109MB)
|
||||
# 7495ec2cd8e3 bitnamilegacy/etcd:3.4.24 "/opt/bitnami/script…" 7 minutes ago Up 7 minutes 0.0.0.0:2379->2379/tcp, [::]:2379->2379/tcp, 2380/tcp 49f2a2a6bf3a4fae842cc950bbc3658a_bitnamilegacyetcd3424_1265e1 145MB (virtual 279MB)
|
||||
|
||||
# runner@runnervmg1sw1:~/work/gf/gf$ du -ah --max-depth=1 /usr | sort -n
|
||||
# 4.0K /usr/games
|
||||
# 4.0K /usr/lib64
|
||||
# 6.6G /usr/lib
|
||||
# 9.3G /usr/share
|
||||
# 15M /usr/lib32
|
||||
# 24G /usr/local
|
||||
# 41G /usr
|
||||
# 95M /usr/sbin
|
||||
# 156M /usr/include
|
||||
# 158M /usr/src
|
||||
# 402M /usr/libexec
|
||||
# 841M /usr/bin
|
||||
|
||||
# runner@runnervmg1sw1:~/work/gf/gf$ du -ah --max-depth=1 /opt | sort -n
|
||||
# 4.0K /opt/pipx_bin
|
||||
# 5.8G /opt/hostedtoolcache
|
||||
# 8.5G /opt
|
||||
# 12K /opt/containerd
|
||||
# 14M /opt/hca
|
||||
# 16K /opt/post-generation
|
||||
# 217M /opt/runner-cache
|
||||
# 243M /opt/actionarchivecache
|
||||
# 374M /opt/google
|
||||
# 515M /opt/pipx
|
||||
# 655M /opt/az
|
||||
# 783M /opt/microsoft
|
||||
|
||||
# runner@runnervmg1sw1:~/work/gf/gf$ du -ah --max-depth=1 /opt/hostedtoolcache/ | sort -n
|
||||
# 1.1G /opt/hostedtoolcache/go
|
||||
# 1.6G /opt/hostedtoolcache/CodeQL
|
||||
# 1.9G /opt/hostedtoolcache/Python
|
||||
# 5.8G /opt/hostedtoolcache/
|
||||
# 9.9M /opt/hostedtoolcache/protoc
|
||||
# 24K /opt/hostedtoolcache/Java_Temurin-Hotspot_jdk
|
||||
# 217M /opt/hostedtoolcache/Ruby
|
||||
# 520M /opt/hostedtoolcache/PyPy
|
||||
# 574M /opt/hostedtoolcache/node
|
||||
|
||||
59
.github/workflows/scripts/ci-main.sh
vendored
Executable file
59
.github/workflows/scripts/ci-main.sh
vendored
Executable file
@ -0,0 +1,59 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
coverage=$1
|
||||
|
||||
# find all path that contains go.mod.
|
||||
for file in `find . -name go.mod`; do
|
||||
dirpath=$(dirname $file)
|
||||
echo $dirpath
|
||||
|
||||
# package kubecm was moved to sub ci procedure.
|
||||
if [ "kubecm" = $(basename $dirpath) ]; then
|
||||
continue 1
|
||||
fi
|
||||
|
||||
# examples directory was moved to sub ci procedure.
|
||||
if [[ $dirpath =~ "/examples/" ]]; then
|
||||
continue 1
|
||||
fi
|
||||
|
||||
if [[ $file =~ "/testdata/" ]]; then
|
||||
echo "ignore testdata path $file"
|
||||
continue 1
|
||||
fi
|
||||
|
||||
# Check if it's a contrib directory
|
||||
if [[ $dirpath =~ "/contrib/" ]]; then
|
||||
# Check if go version meets the requirement
|
||||
if ! go version | grep -qE "go${LATEST_GO_VERSION}"; then
|
||||
echo "ignore path $dirpath as go version is not ${LATEST_GO_VERSION}: $(go version)"
|
||||
# clean docker containers and images to free disk space
|
||||
# bash .github/workflows/scripts/ci-main-clean.sh "$dirpath"
|
||||
continue 1
|
||||
fi
|
||||
fi
|
||||
|
||||
# if [[ $dirpath = "." ]]; then
|
||||
# # No space left on device error sometimes occurs in CI pipelines, so clean the cache before tests.
|
||||
# go clean -cache
|
||||
# fi
|
||||
|
||||
cd $dirpath
|
||||
go mod tidy
|
||||
go build ./...
|
||||
|
||||
# test with coverage
|
||||
if [ "${coverage}" = "coverage" ]; then
|
||||
go test ./... -count=1 -race -coverprofile=coverage.out -covermode=atomic -coverpkg=./...,github.com/gogf/gf/... || exit 1
|
||||
|
||||
if grep -q "/gogf/gf/.*/v2" go.mod; then
|
||||
sed -i "s/gogf\/gf\(\/.*\)\/v2/gogf\/gf\/v2\1/g" coverage.out
|
||||
fi
|
||||
else
|
||||
go test ./... -count=1 -race || exit 1
|
||||
fi
|
||||
|
||||
cd -
|
||||
# clean docker containers and images to free disk space
|
||||
# bash .github/workflows/scripts/ci-main-clean.sh "$dirpath"
|
||||
done
|
||||
86
.github/workflows/scripts/ci-sub.sh
vendored
Executable file
86
.github/workflows/scripts/ci-sub.sh
vendored
Executable file
@ -0,0 +1,86 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
coverage=$1
|
||||
|
||||
# update code of submodules
|
||||
git clone https://github.com/gogf/examples
|
||||
|
||||
# update go.mod in examples directory to replace github.com/gogf/gf packages with local directory
|
||||
bash .github/workflows/scripts/replace_examples_gomod.sh
|
||||
|
||||
# Function to compare version numbers
|
||||
version_compare() {
|
||||
local ver1=$1
|
||||
local ver2=$2
|
||||
|
||||
# Remove 'go' prefix and 'v' if present
|
||||
ver1=$(echo "$ver1" | sed 's/^go//; s/^v//')
|
||||
ver2=$(echo "$ver2" | sed 's/^go//; s/^v//')
|
||||
|
||||
# Split versions into major.minor format
|
||||
local major1=$(echo "$ver1" | cut -d. -f1)
|
||||
local minor1=$(echo "$ver1" | cut -d. -f2)
|
||||
local major2=$(echo "$ver2" | cut -d. -f1)
|
||||
local minor2=$(echo "$ver2" | cut -d. -f2)
|
||||
|
||||
# Compare versions: return 0 if ver1 <= ver2, 1 otherwise
|
||||
if [ "$major1" -lt "$major2" ]; then
|
||||
return 0
|
||||
elif [ "$major1" -eq "$major2" ] && [ "$minor1" -le "$minor2" ]; then
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Get current Go version
|
||||
current_go_version=$(go version | grep -oE 'go[0-9]+\.[0-9]+')
|
||||
|
||||
# find all path that contains go.mod.
|
||||
for file in `find . -name go.mod`; do
|
||||
dirpath=$(dirname $file)
|
||||
echo "Processing: $dirpath"
|
||||
|
||||
# Only process examples and kubecm directories
|
||||
|
||||
# Process examples directory (only build, no tests)
|
||||
if [[ $dirpath =~ "/examples/" ]]; then
|
||||
echo " the examples directory only needs to be built, not unit tests."
|
||||
cd $dirpath
|
||||
go mod tidy
|
||||
go build ./...
|
||||
cd -
|
||||
continue 1
|
||||
fi
|
||||
|
||||
# Process kubecm directory
|
||||
if [ "kubecm" != $(basename $dirpath) ]; then
|
||||
echo " Skipping: not kubecm directory"
|
||||
continue
|
||||
fi
|
||||
|
||||
cd $dirpath
|
||||
|
||||
# Read Go version requirement from go.mod
|
||||
if [ -f "go.mod" ]; then
|
||||
go_mod_version=$(grep '^go ' go.mod | awk '{print $2}' | head -1)
|
||||
|
||||
if [ -n "$go_mod_version" ]; then
|
||||
echo " go.mod requires: go$go_mod_version"
|
||||
echo " current version: $current_go_version"
|
||||
|
||||
# Check if go.mod version requirement is satisfied by current Go version
|
||||
if version_compare "$go_mod_version" "$current_go_version"; then
|
||||
echo " ✓ Version requirement satisfied, proceeding with build and test"
|
||||
|
||||
go mod tidy
|
||||
go build ./...
|
||||
go test ./... -race || exit 1
|
||||
else
|
||||
echo " ✗ Current Go version ($current_go_version) does not meet requirement (go$go_mod_version), skipping"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
cd -
|
||||
done
|
||||
81
.github/workflows/scripts/replace_examples_gomod.sh
vendored
Executable file
81
.github/workflows/scripts/replace_examples_gomod.sh
vendored
Executable file
@ -0,0 +1,81 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Get the absolute path to the repository root
|
||||
repo_root=$(pwd)
|
||||
workdir=$repo_root/examples
|
||||
|
||||
echo "Prepare to process go.mod files in the ${workdir} directory"
|
||||
|
||||
# Check if examples directory exists
|
||||
if [ ! -d "${workdir}" ]; then
|
||||
echo "Error: examples directory not found at ${workdir}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if find command is available
|
||||
if ! command -v find &> /dev/null; then
|
||||
echo "Error: find command not found!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
for file in `find ${workdir} -name go.mod`; do
|
||||
goModPath=$(dirname $file)
|
||||
echo ""
|
||||
echo "Processing dir: $goModPath"
|
||||
|
||||
# Calculate relative path to root
|
||||
# First get the relative path from go.mod to repo root
|
||||
relativePath=""
|
||||
current="$goModPath"
|
||||
while [ "$current" != "$repo_root" ]; do
|
||||
relativePath="../$relativePath"
|
||||
current=$(dirname "$current")
|
||||
done
|
||||
relativePath=${relativePath%/} # Remove trailing slash
|
||||
echo "Relative path to root: $relativePath"
|
||||
|
||||
# Get all github.com/gogf/gf dependencies
|
||||
# Use awk to get package names without version numbers
|
||||
dependencies=$(awk '/^[[:space:]]*github\.com\/gogf\/gf\// {print $1}' "$file" | sort -u)
|
||||
|
||||
if [ -n "$dependencies" ]; then
|
||||
echo "Found GoFrame dependencies:"
|
||||
echo "$dependencies"
|
||||
echo "Adding replace directives..."
|
||||
|
||||
# Create temporary file
|
||||
temp_file="${file}.tmp"
|
||||
# Remove existing replace directives and copy to temp file
|
||||
sed '/^replace.*github\.com\/gogf\/gf.*/d' "$file" > "$temp_file"
|
||||
|
||||
# Add new replace block
|
||||
echo "" >> "$temp_file"
|
||||
echo "replace (" >> "$temp_file"
|
||||
|
||||
while IFS= read -r dep; do
|
||||
# Skip empty lines
|
||||
[ -z "$dep" ] && continue
|
||||
|
||||
# Calculate the relative path for the replacement
|
||||
if [[ "$dep" == "github.com/gogf/gf/v2" ]]; then
|
||||
replacement="$relativePath"
|
||||
else
|
||||
# Extract the path after v2 and remove trailing version
|
||||
subpath=$(echo "$dep" | sed -E 's/github\.com\/gogf\/gf\/(contrib\/[^/]+\/[^/]+)\/v2.*/\1/')
|
||||
replacement="$relativePath/$subpath"
|
||||
fi
|
||||
|
||||
echo " $dep => $replacement/" >> "$temp_file"
|
||||
done <<< "$dependencies"
|
||||
|
||||
echo ")" >> "$temp_file"
|
||||
|
||||
# Replace original file with temporary file
|
||||
mv "$temp_file" "$file"
|
||||
echo "Replace directives added to $file"
|
||||
else
|
||||
echo "No GoFrame dependencies found in $file"
|
||||
fi
|
||||
done
|
||||
|
||||
echo "\nAll go.mod files have been processed successfully."
|
||||
50
.github/workflows/scripts/update_version.sh
vendored
Executable file
50
.github/workflows/scripts/update_version.sh
vendored
Executable file
@ -0,0 +1,50 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Check if the number of parameters is 2
|
||||
if [ $# -ne 2 ]; then
|
||||
echo "Invalid parameters, please execute in format: version.sh [directory] [version]"
|
||||
echo "Example: version.sh ./contrib v1.0.0"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if the first parameter is a directory and exists
|
||||
if [ ! -d "$1" ]; then
|
||||
echo "Error: Directory does not exist"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if the second parameter starts with 'v'
|
||||
if [[ "$2" != v* ]]; then
|
||||
echo "Error: Version number does not start with 'v'"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
workdir=$1
|
||||
newVersion=$2
|
||||
echo "Preparing to replace version numbers in all go.mod files under ${workdir} directory to ${newVersion}"
|
||||
|
||||
|
||||
# Check if file exists
|
||||
if [ -f "go.work" ]; then
|
||||
# File exists, rename it
|
||||
mv go.work go.work.${newVersion}
|
||||
echo "Backup go.work file to avoid affecting the upgrade"
|
||||
fi
|
||||
|
||||
for file in `find ${workdir} -name go.mod`; do
|
||||
goModPath=$(dirname $file)
|
||||
echo ""
|
||||
echo "processing dir: $goModPath"
|
||||
cd $goModPath
|
||||
go mod tidy
|
||||
go list -f "{{if and (not .Indirect) (not .Main)}}{{.Path}}@${newVersion}{{end}}" -m all | grep "^github.com/gogf/gf"
|
||||
go list -f "{{if and (not .Indirect) (not .Main)}}{{.Path}}@${newVersion}{{end}}" -m all | grep "^github.com/gogf/gf" | xargs -L1 go get -v
|
||||
go mod tidy
|
||||
cd -
|
||||
done
|
||||
|
||||
if [ -f "go.work.${newVersion}" ]; then
|
||||
# File exists, rename it back
|
||||
mv go.work.${newVersion} go.work
|
||||
echo "Restore go.work file"
|
||||
fi
|
||||
53
.github/workflows/sonarcloud.yaml
vendored
53
.github/workflows/sonarcloud.yaml
vendored
@ -1,53 +0,0 @@
|
||||
name: Sonarcloud Scan
|
||||
|
||||
on:
|
||||
schedule:
|
||||
# Weekly on Saturdays.
|
||||
- cron: '30 1 * * 6'
|
||||
push:
|
||||
branches: [ master ]
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
# Declare default permissions as read only.
|
||||
permissions: read
|
||||
|
||||
jobs:
|
||||
analysis:
|
||||
name: Scorecards analysis
|
||||
runs-on: ubuntu-22.04
|
||||
permissions:
|
||||
# Needed to upload the results to code-scanning dashboard.
|
||||
security-events: write
|
||||
# Used to receive a badge. (Upcoming feature)
|
||||
id-token: write
|
||||
# Needs for private repositories.
|
||||
contents: read
|
||||
actions: read
|
||||
|
||||
steps:
|
||||
- name: "Checkout code"
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: "Run analysis"
|
||||
uses: ossf/scorecard-action@v2.4.0 # v2.4.0
|
||||
with:
|
||||
results_file: results.sarif
|
||||
results_format: sarif
|
||||
publish_results: true
|
||||
|
||||
- name: "Upload artifact"
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: SARIF file
|
||||
path: results.sarif
|
||||
retention-days: 5
|
||||
|
||||
- name: "Upload to code-scanning"
|
||||
uses: github/codeql-action/upload-sarif@3ebbd71c74ef574dbc558c82f70e52732c8b44fe # v2.2.1
|
||||
with:
|
||||
sarif_file: results.sarif
|
||||
38
.github/workflows/tag.yml
vendored
38
.github/workflows/tag.yml
vendored
@ -4,36 +4,56 @@ on:
|
||||
push:
|
||||
# Sequence of patterns matched against refs/tags
|
||||
tags:
|
||||
- 'v*' # Push events to matching v*, i.e. v1.0, v20.15.10
|
||||
- 'v*' # Push events to matching v*, i.e. v1.0, v20.15.10
|
||||
|
||||
env:
|
||||
TZ: Asia/Shanghai
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Auto Creating Tags
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout Github Code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
uses: actions/checkout@v5
|
||||
- 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
|
||||
tag=$(dirname $file)/${{ github.ref_name }}
|
||||
git tag $tag
|
||||
git push origin $tag
|
||||
done
|
||||
|
||||
- name: update dependencies
|
||||
run: |
|
||||
go env -w GOPRIVATE=github.com/gogf/gf
|
||||
.github/workflows/scripts/update_version.sh ./cmd/gf ${{ github.ref_name }}
|
||||
- name: Create Pull Request
|
||||
uses: peter-evans/create-pull-request@v4
|
||||
with:
|
||||
commit-message: 'update gf cli to ${{ github.ref_name }}'
|
||||
title: 'fix: update gf cli to ${{ github.ref_name }}'
|
||||
base: master
|
||||
branch: fix/${{ github.ref_name }}
|
||||
delete-branch: true
|
||||
- name: Commit & Push changes
|
||||
uses: actions-js/push@master
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
branch: fix/${{ github.ref_name }}
|
||||
author_name: TagRobot
|
||||
author_email: tagrobot@goframe.org
|
||||
message: 'fix: update gf cli to ${{ github.ref_name }}'
|
||||
- name: Auto Creating Tags For cli tool
|
||||
run: |
|
||||
git config --global user.email "tagrobot@goframe.org"
|
||||
git config --global user.name "TagRobot"
|
||||
# auto create tag for cli tool
|
||||
for file in `find cmd -name go.mod`; do
|
||||
tag=$(dirname $file)/$GITHUB_REF_NAME
|
||||
for file in `find cmd -name go.mod -not -path "*/testdata/*"`; do
|
||||
tag=$(dirname $file)/${{ github.ref_name }}
|
||||
git tag $tag
|
||||
git push origin $tag
|
||||
done
|
||||
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@ -7,7 +7,6 @@
|
||||
.settings/
|
||||
.vscode/
|
||||
vendor/
|
||||
pkg/
|
||||
bin/
|
||||
**/.DS_Store
|
||||
.test/
|
||||
@ -24,3 +23,5 @@ go.work.sum
|
||||
node_modules
|
||||
.docusaurus
|
||||
output
|
||||
.example/
|
||||
.golangci.bck.yml
|
||||
0
.gitmodules
vendored
Normal file
0
.gitmodules
vendored
Normal file
535
.golangci.yml
535
.golangci.yml
@ -1,325 +1,220 @@
|
||||
## This file contains all available configuration options
|
||||
## with their default values.
|
||||
|
||||
# See https://github.com/golangci/golangci-lint#config-file
|
||||
# See https://golangci-lint.run/usage/configuration/
|
||||
|
||||
# Options for analysis running.
|
||||
version: "2"
|
||||
run:
|
||||
# Timeout for analysis, e.g. 30s, 5m.
|
||||
# Default: 1m
|
||||
timeout: 5m
|
||||
# Exit code when at least one issue was found.
|
||||
# Default: 1
|
||||
issues-exit-code: 2
|
||||
# Include test files or not.
|
||||
# Default: true
|
||||
tests: false
|
||||
# List of build tags, all linters use it.
|
||||
# Default: []
|
||||
build-tags: []
|
||||
# If set, we pass it to "go list -mod={option}". From "go help modules":
|
||||
# If invoked with -mod=readonly, the go command is disallowed from the implicit
|
||||
# automatic updating of go.mod described above. Instead, it fails when any changes
|
||||
# to go.mod are needed. This setting is most useful to check that go.mod does
|
||||
# not need updates, such as in a continuous integration and testing system.
|
||||
# If invoked with -mod=vendor, the go command assumes that the vendor
|
||||
# directory holds the correct copies of dependencies and ignores
|
||||
# the dependency descriptions in go.mod.
|
||||
#
|
||||
# Allowed values: readonly|vendor|mod
|
||||
# Default: ""
|
||||
modules-download-mode: readonly
|
||||
# Allow multiple parallel golangci-lint instances running.
|
||||
# If false, golangci-lint acquires file lock on start.
|
||||
# Default: false
|
||||
allow-parallel-runners: true
|
||||
# Allow multiple golangci-lint instances running, but serialize them around a lock.
|
||||
# If false, golangci-lint exits with an error if it fails to acquire file lock on start.
|
||||
# Default: false
|
||||
allow-serial-runners: true
|
||||
# Define the Go version limit.
|
||||
# Mainly related to generics support since go1.18.
|
||||
# Default: use Go version from the go.mod file, fallback on the env var `GOVERSION`, fallback on 1.17
|
||||
go: '1.20'
|
||||
# Number of operating system threads (`GOMAXPROCS`) that can execute golangci-lint simultaneously.
|
||||
# If it is explicitly set to 0 (i.e. not the default) then golangci-lint will automatically set the value to match Linux container CPU quota.
|
||||
# Default: the number of logical CPUs in the machine
|
||||
concurrency: 4
|
||||
|
||||
|
||||
# Main linters configurations.
|
||||
# See https://golangci-lint.run/usage/linters
|
||||
go: "1.25"
|
||||
modules-download-mode: readonly
|
||||
issues-exit-code: 2
|
||||
tests: false
|
||||
allow-parallel-runners: true
|
||||
allow-serial-runners: true
|
||||
linters:
|
||||
# Disable all default enabled linters.
|
||||
disable-all: true
|
||||
# Custom enable linters we want to use.
|
||||
default: none
|
||||
enable:
|
||||
- errcheck # Errcheck is a program for checking for unchecked errors in go programs.
|
||||
- errchkjson # Checks types passed to the JSON encoding functions. Reports unsupported types and optionally reports occasions, where the check for the returned error can be omitted.
|
||||
- funlen # Tool for detection of long functions
|
||||
- gofmt # Gofmt checks whether code was gofmt-ed. By default this tool runs with -s option to check for code simplification
|
||||
- goimports # Check import statements are formatted according to the 'goimport' command. Reformat imports in autofix mode.
|
||||
- gci # Gci controls Go package import order and makes it always deterministic.
|
||||
- goconst # Finds repeated strings that could be replaced by a constant
|
||||
- gocritic # Provides diagnostics that check for bugs, performance and style issues.
|
||||
- gosimple # Linter for Go source code that specializes in simplifying code
|
||||
- govet # Vet examines Go source code and reports suspicious constructs, such as Printf calls whose arguments do not align with the format string
|
||||
- misspell # Finds commonly misspelled English words in comments
|
||||
- nolintlint # Reports ill-formed or insufficient nolint directives
|
||||
- revive # Fast, configurable, extensible, flexible, and beautiful linter for Go. Drop-in replacement of golint.
|
||||
- staticcheck # It's a set of rules from staticcheck. It's not the same thing as the staticcheck binary.
|
||||
- typecheck # Like the front-end of a Go compiler, parses and type-checks Go code
|
||||
- usestdlibvars # A linter that detect the possibility to use variables/constants from the Go standard library.
|
||||
- whitespace # Tool for detection of leading and trailing whitespace
|
||||
|
||||
|
||||
issues:
|
||||
exclude-rules:
|
||||
# helpers in tests often (rightfully) pass a *testing.T as their first argument
|
||||
- path: _test\.go
|
||||
text: "context.Context should be the first parameter of a function"
|
||||
linters:
|
||||
- revive
|
||||
# Yes, they are, but it's okay in a test
|
||||
- path: _test\.go
|
||||
text: "exported func.*returns unexported type.*which can be annoying to use"
|
||||
linters:
|
||||
- revive
|
||||
# https://github.com/go-critic/go-critic/issues/926
|
||||
- linters:
|
||||
- gocritic
|
||||
text: "unnecessaryDefer:"
|
||||
|
||||
|
||||
# https://golangci-lint.run/usage/linters
|
||||
linters-settings:
|
||||
# https://golangci-lint.run/usage/linters/#misspell
|
||||
misspell:
|
||||
locale: US
|
||||
ignore-words:
|
||||
- cancelled
|
||||
# https://golangci-lint.run/usage/linters/#gofmt
|
||||
gofmt:
|
||||
# Simplify code: gofmt with `-s` option.
|
||||
# Default: true
|
||||
simplify: true
|
||||
# Apply the rewrite rules to the source before reformatting.
|
||||
# https://pkg.go.dev/cmd/gofmt
|
||||
# Default: []
|
||||
rewrite-rules: [ ]
|
||||
# - pattern: 'interface{}'
|
||||
# replacement: 'any'
|
||||
# - pattern: 'a[b:len(a)]'
|
||||
# replacement: 'a[b:]'
|
||||
goimports:
|
||||
# A comma-separated list of prefixes, which, if set, checks import paths
|
||||
# with the given prefixes are grouped after 3rd-party packages.
|
||||
# Default: ""
|
||||
local-prefixes: github.com/gogf/gf/v2
|
||||
gci:
|
||||
# Section configuration to compare against.
|
||||
# Section names are case-insensitive and may contain parameters in ().
|
||||
# The default order of sections is `standard > default > custom > blank > dot > alias > localmodule`,
|
||||
# If `custom-order` is `true`, it follows the order of `sections` option.
|
||||
# Default: ["standard", "default"]
|
||||
sections:
|
||||
- standard # Standard section: captures all standard packages.
|
||||
- blank # Blank section: contains all blank imports. This section is not present unless explicitly enabled.
|
||||
- default # Default section: contains all imports that could not be matched to another section type.
|
||||
- dot # Dot section: contains all dot imports. This section is not present unless explicitly enabled.
|
||||
# - alias # Alias section: contains all alias imports. This section is not present unless explicitly enabled.
|
||||
# - localmodule # Local module section: contains all local packages. This section is not present unless explicitly enabled.
|
||||
- prefix(github.com/gogf/gf) # Custom section: groups all imports with the specified Prefix.
|
||||
- prefix(github.com/gogf/gf/cmd) # Custom section: groups all imports with the specified Prefix.
|
||||
- prefix(github.com/gogf/gfcontrib) # Custom section: groups all imports with the specified Prefix.
|
||||
- prefix(github.com/gogf/gf/example) # Custom section: groups all imports with the specified Prefix.
|
||||
# Skip generated files.
|
||||
# Default: true
|
||||
skip-generated: true
|
||||
# Enable custom order of sections.
|
||||
# If `true`, make the section order the same as the order of `sections`.
|
||||
# Default: false
|
||||
custom-order: true
|
||||
# Drops lexical ordering for custom sections.
|
||||
# Default: false
|
||||
no-lex-order: false
|
||||
# https://golangci-lint.run/usage/linters/#revive
|
||||
# https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md
|
||||
revive:
|
||||
ignore-generated-header: true
|
||||
severity: error
|
||||
- errcheck
|
||||
- errchkjson
|
||||
- funlen
|
||||
- goconst
|
||||
- gocritic
|
||||
- govet
|
||||
- misspell
|
||||
- nolintlint
|
||||
- revive
|
||||
- staticcheck
|
||||
- usestdlibvars
|
||||
- whitespace
|
||||
settings:
|
||||
funlen:
|
||||
lines: 340
|
||||
statements: -1
|
||||
goconst:
|
||||
match-constant: false
|
||||
min-len: 4
|
||||
min-occurrences: 30
|
||||
numbers: true
|
||||
min: 5
|
||||
max: 20
|
||||
ignore-calls: false
|
||||
gocritic:
|
||||
disabled-checks:
|
||||
- ifElseChain
|
||||
- assignOp
|
||||
- appendAssign
|
||||
- singleCaseSwitch
|
||||
- regexpMust
|
||||
- typeSwitchVar
|
||||
- elseif
|
||||
govet:
|
||||
disable:
|
||||
- asmdecl
|
||||
- assign
|
||||
- atomic
|
||||
- atomicalign
|
||||
- bools
|
||||
- buildtag
|
||||
- cgocall
|
||||
- composites
|
||||
- copylocks
|
||||
- deepequalerrors
|
||||
- errorsas
|
||||
- fieldalignment
|
||||
- findcall
|
||||
- framepointer
|
||||
- httpresponse
|
||||
- ifaceassert
|
||||
- loopclosure
|
||||
- lostcancel
|
||||
- nilfunc
|
||||
- nilness
|
||||
- reflectvaluecompare
|
||||
- shift
|
||||
- shadow
|
||||
- sigchanyzer
|
||||
- sortslice
|
||||
- stdmethods
|
||||
- stringintconv
|
||||
- structtag
|
||||
- testinggoroutine
|
||||
- tests
|
||||
- unmarshal
|
||||
- unreachable
|
||||
- unsafeptr
|
||||
- unusedwrite
|
||||
enable-all: true
|
||||
settings:
|
||||
printf:
|
||||
funcs:
|
||||
- (github.com/golangci/golangci-lint/pkg/logutils.Log).Infof
|
||||
- (github.com/golangci/golangci-lint/pkg/logutils.Log).Warnf
|
||||
- (github.com/golangci/golangci-lint/pkg/logutils.Log).Errorf
|
||||
- (github.com/golangci/golangci-lint/pkg/logutils.Log).Fatalf
|
||||
unusedresult:
|
||||
funcs:
|
||||
- pkg.MyFunc
|
||||
- context.WithCancel
|
||||
stringmethods:
|
||||
- MyMethod
|
||||
misspell:
|
||||
locale: US
|
||||
ignore-rules:
|
||||
- cancelled
|
||||
revive:
|
||||
severity: error
|
||||
rules:
|
||||
- name: atomic
|
||||
- name: line-length-limit
|
||||
arguments:
|
||||
- 380
|
||||
severity: error
|
||||
- name: unhandled-error
|
||||
severity: warning
|
||||
disabled: true
|
||||
- name: var-naming
|
||||
arguments:
|
||||
- - ID
|
||||
- URL
|
||||
- IP
|
||||
- HTTP
|
||||
- JSON
|
||||
- API
|
||||
- UID
|
||||
- Id
|
||||
- Api
|
||||
- Uid
|
||||
- Http
|
||||
- Json
|
||||
- Ip
|
||||
- Url
|
||||
- - VM
|
||||
severity: warning
|
||||
disabled: true
|
||||
- name: string-format
|
||||
arguments:
|
||||
- - core.WriteError[1].Message
|
||||
- /^([^A-Z]|$)/
|
||||
- must not start with a capital letter
|
||||
- - fmt.Errorf[0]
|
||||
- /(^|[^\.!?])$/
|
||||
- must not end in punctuation
|
||||
- - panic
|
||||
- /^[^\n]*$/
|
||||
- must not contain line breaks
|
||||
severity: warning
|
||||
disabled: false
|
||||
- name: function-result-limit
|
||||
arguments:
|
||||
- 4
|
||||
severity: warning
|
||||
disabled: false
|
||||
staticcheck:
|
||||
checks: [ "all","-S1000","-S1009","-S1016","-S1023","-S1025","-S1029","-S1034","-S1040","-SA1016","-SA1019","-SA1029","-SA4006","-SA4015","-SA6003","-SA9003","-ST1003","-QF1001","-QF1002","-QF1003","-QF1006","-QF1007","-QF1008","-QF1011","-QF1012","-ST1011" ]
|
||||
initialisms: [ "ACL", "API", "ASCII", "CPU", "CSS", "DNS", "EOF", "GUID", "HTML", "HTTP", "HTTPS", "ID", "IP", "JSON", "QPS", "RAM", "RPC", "SLA", "SMTP", "SQL", "SSH", "TCP", "TLS", "TTL", "UDP", "UI", "GID", "UID", "UUID", "URI", "URL", "UTF8", "VM", "XML", "XMPP", "XSRF", "XSS", "SIP", "RTP", "AMQP", "DB", "TS" ]
|
||||
dot-import-whitelist: [ "fmt" ]
|
||||
http-status-code-whitelist: [ "200", "400", "404", "500" ]
|
||||
exclusions:
|
||||
generated: lax
|
||||
presets:
|
||||
- comments
|
||||
- common-false-positives
|
||||
- legacy
|
||||
- std-error-handling
|
||||
rules:
|
||||
- name: atomic
|
||||
- name: line-length-limit
|
||||
severity: error
|
||||
arguments: [ 380 ]
|
||||
- name: unhandled-error
|
||||
severity: warning
|
||||
disabled: true
|
||||
arguments: []
|
||||
- name: var-naming
|
||||
severity: warning
|
||||
disabled: true
|
||||
arguments:
|
||||
# AllowList
|
||||
- [ "ID","URL","IP","HTTP","JSON","API","UID","Id","Api","Uid","Http","Json","Ip","Url" ]
|
||||
# DenyList
|
||||
- [ "VM" ]
|
||||
- name: string-format
|
||||
severity: warning
|
||||
disabled: false
|
||||
arguments:
|
||||
- - 'core.WriteError[1].Message'
|
||||
- '/^([^A-Z]|$)/'
|
||||
- must not start with a capital letter
|
||||
- - 'fmt.Errorf[0]'
|
||||
- '/(^|[^\.!?])$/'
|
||||
- must not end in punctuation
|
||||
- - panic
|
||||
- '/^[^\n]*$/'
|
||||
- must not contain line breaks
|
||||
- name: function-result-limit
|
||||
severity: warning
|
||||
disabled: false
|
||||
arguments: [ 4 ]
|
||||
|
||||
# https://golangci-lint.run/usage/linters/#funlen
|
||||
funlen:
|
||||
# Checks the number of lines in a function.
|
||||
# If lower than 0, disable the check.
|
||||
# Default: 60
|
||||
lines: 340
|
||||
# Checks the number of statements in a function.
|
||||
# If lower than 0, disable the check.
|
||||
# Default: 40
|
||||
statements: -1
|
||||
|
||||
# https://golangci-lint.run/usage/linters/#goconst
|
||||
goconst:
|
||||
# Minimal length of string constant.
|
||||
# Default: 3
|
||||
min-len: 4
|
||||
# Minimum occurrences of constant string count to trigger issue.
|
||||
# Default: 3
|
||||
# For subsequent optimization, the value is reduced.
|
||||
min-occurrences: 30
|
||||
# Ignore test files.
|
||||
# Default: false
|
||||
ignore-tests: true
|
||||
# Look for existing constants matching the values.
|
||||
# Default: true
|
||||
match-constant: false
|
||||
# Search also for duplicated numbers.
|
||||
# Default: false
|
||||
numbers: true
|
||||
# Minimum value, only works with goconst.numbers
|
||||
# Default: 3
|
||||
min: 5
|
||||
# Maximum value, only works with goconst.numbers
|
||||
# Default: 3
|
||||
max: 20
|
||||
# Ignore when constant is not used as function argument.
|
||||
# Default: true
|
||||
ignore-calls: false
|
||||
|
||||
# https://golangci-lint.run/usage/linters/#gocritic
|
||||
gocritic:
|
||||
disabled-checks:
|
||||
- ifElseChain
|
||||
- assignOp
|
||||
- appendAssign
|
||||
- singleCaseSwitch
|
||||
- regexpMust
|
||||
- typeSwitchVar
|
||||
- elseif
|
||||
|
||||
# https://golangci-lint.run/usage/linters/#gosimple
|
||||
gosimple:
|
||||
# Sxxxx checks in https://staticcheck.io/docs/configuration/options/#checks
|
||||
# Default: ["*"]
|
||||
checks: [
|
||||
"all", "-S1000", "-S1001", "-S1002", "-S1008", "-S1009", "-S1016", "-S1023", "-S1025", "-S1029", "-S1034", "-S1040"
|
||||
]
|
||||
|
||||
# https://golangci-lint.run/usage/linters/#govet
|
||||
govet:
|
||||
# Report about shadowed variables.
|
||||
# Default: false
|
||||
# check-shadowing: true
|
||||
# Settings per analyzer.
|
||||
settings:
|
||||
# Analyzer name, run `go tool vet help` to see all analyzers.
|
||||
printf:
|
||||
# Comma-separated list of print function names to check (in addition to default, see `go tool vet help printf`).
|
||||
# Default: []
|
||||
funcs:
|
||||
- (github.com/golangci/golangci-lint/pkg/logutils.Log).Infof
|
||||
- (github.com/golangci/golangci-lint/pkg/logutils.Log).Warnf
|
||||
- (github.com/golangci/golangci-lint/pkg/logutils.Log).Errorf
|
||||
- (github.com/golangci/golangci-lint/pkg/logutils.Log).Fatalf
|
||||
# shadow:
|
||||
# Whether to be strict about shadowing; can be noisy.
|
||||
# Default: false
|
||||
# strict: false
|
||||
unusedresult:
|
||||
# Comma-separated list of functions whose results must be used
|
||||
# (in addition to defaults context.WithCancel,context.WithDeadline,context.WithTimeout,context.WithValue,
|
||||
# errors.New,fmt.Errorf,fmt.Sprint,fmt.Sprintf,sort.Reverse)
|
||||
# Default []
|
||||
funcs:
|
||||
- pkg.MyFunc
|
||||
- context.WithCancel
|
||||
# Comma-separated list of names of methods of type func() string whose results must be used
|
||||
# (in addition to default Error,String)
|
||||
# Default []
|
||||
stringmethods:
|
||||
- MyMethod
|
||||
# Enable all analyzers.
|
||||
# Default: false
|
||||
enable-all: true
|
||||
# Disable analyzers by name.
|
||||
# Run `go tool vet help` to see all analyzers.
|
||||
# Default: []
|
||||
disable:
|
||||
- asmdecl
|
||||
- assign
|
||||
- atomic
|
||||
- atomicalign
|
||||
- bools
|
||||
- buildtag
|
||||
- cgocall
|
||||
- composites
|
||||
- copylocks
|
||||
- deepequalerrors
|
||||
- errorsas
|
||||
- fieldalignment
|
||||
- findcall
|
||||
- framepointer
|
||||
- httpresponse
|
||||
- ifaceassert
|
||||
- loopclosure
|
||||
- lostcancel
|
||||
- nilfunc
|
||||
- nilness
|
||||
- reflectvaluecompare
|
||||
- shift
|
||||
- shadow
|
||||
- sigchanyzer
|
||||
- sortslice
|
||||
- stdmethods
|
||||
- stringintconv
|
||||
- structtag
|
||||
- testinggoroutine
|
||||
- tests
|
||||
- unmarshal
|
||||
- unreachable
|
||||
- unsafeptr
|
||||
- unusedwrite
|
||||
|
||||
# https://golangci-lint.run/usage/linters/#staticcheck
|
||||
staticcheck:
|
||||
# SAxxxx checks in https://staticcheck.io/docs/configuration/options/#checks
|
||||
# Default: ["*"]
|
||||
checks: [ "all","-SA1019","-SA4015","-SA1029","-SA1016","-SA9003","-SA4006","-SA6003" ]
|
||||
|
||||
- linters:
|
||||
- revive
|
||||
path: _test\.go
|
||||
text: context.Context should be the first parameter of a function
|
||||
- linters:
|
||||
- revive
|
||||
path: _test\.go
|
||||
text: exported func.*returns unexported type.*which can be annoying to use
|
||||
- linters:
|
||||
- gocritic
|
||||
text: 'unnecessaryDefer:'
|
||||
- linters:
|
||||
- goconst
|
||||
path: (.+)_test\.go
|
||||
paths:
|
||||
- third_party$
|
||||
- builtin$
|
||||
- examples$
|
||||
formatters:
|
||||
enable:
|
||||
- gci
|
||||
- gofmt
|
||||
- goimports
|
||||
settings:
|
||||
gci:
|
||||
sections:
|
||||
- standard
|
||||
- blank
|
||||
- default
|
||||
- dot
|
||||
- prefix(github.com/gogf/gf/v2)
|
||||
- prefix(github.com/gogf/gf/cmd)
|
||||
- prefix(github.com/gogf/gfcontrib)
|
||||
- prefix(github.com/gogf/gf/example)
|
||||
custom-order: true
|
||||
no-lex-order: false
|
||||
gofmt:
|
||||
simplify: true
|
||||
rewrite-rules:
|
||||
- pattern: 'interface{}'
|
||||
replacement: 'any'
|
||||
- pattern: 'reflect.Ptr'
|
||||
replacement: 'reflect.Pointer'
|
||||
- pattern: 'ioutil.ReadAll'
|
||||
replacement: 'io.ReadAll'
|
||||
- pattern: 'ioutil.WriteFile'
|
||||
replacement: 'os.WriteFile'
|
||||
- pattern: 'ioutil.ReadFile'
|
||||
replacement: 'os.ReadFile'
|
||||
- pattern: 'ioutil.NopCloser'
|
||||
replacement: 'io.NopCloser'
|
||||
goimports:
|
||||
local-prefixes:
|
||||
- github.com/gogf/gf/v2
|
||||
exclusions:
|
||||
generated: lax
|
||||
paths:
|
||||
- third_party$
|
||||
- builtin$
|
||||
- examples$
|
||||
|
||||
35
.make_tidy.sh
Executable file
35
.make_tidy.sh
Executable file
@ -0,0 +1,35 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
workdir=.
|
||||
echo "Prepare to tidy all go.mod files in the ${workdir} directory"
|
||||
|
||||
# check find command support or not
|
||||
output=$(find "${workdir}" -name go.mod 2>&1)
|
||||
if [[ $? -ne 0 ]]; then
|
||||
echo "Error: please use bash or zsh to run!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
for file in `find ${workdir} -name go.mod`; do
|
||||
goModPath=$(dirname $file)
|
||||
echo ""
|
||||
echo "processing dir: $goModPath"
|
||||
|
||||
if [[ $goModPath =~ "/testdata/" ]]; then
|
||||
echo "ignore testdata path $goModPath"
|
||||
continue 1
|
||||
fi
|
||||
|
||||
if [[ $goModPath =~ "/examples/" ]]; then
|
||||
echo "ignore examples path $goModPath"
|
||||
continue 1
|
||||
fi
|
||||
|
||||
cd $goModPath
|
||||
# Remove indirect dependencies
|
||||
sed -i '/\/\/ indirect/d' go.mod
|
||||
go mod tidy
|
||||
# Remove toolchain line if exists
|
||||
sed -i '' '/^toolchain/d' go.mod
|
||||
cd - > /dev/null
|
||||
done
|
||||
@ -1,4 +1,19 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Function to detect OS and set sed parameters
|
||||
setup_sed() {
|
||||
if [[ "$OSTYPE" == "darwin"* ]]; then
|
||||
# macOS
|
||||
SED_INPLACE="sed -i ''"
|
||||
else
|
||||
# Linux/Windows Git Bash
|
||||
SED_INPLACE="sed -i"
|
||||
fi
|
||||
}
|
||||
|
||||
# Initialize sed command
|
||||
setup_sed
|
||||
|
||||
if [ $# -ne 2 ]; then
|
||||
echo "Parameter exception, please execute in the format of $0 [directory] [version number]"
|
||||
echo "PS:$0 ./ v2.4.0"
|
||||
@ -17,7 +32,7 @@ fi
|
||||
|
||||
workdir=.
|
||||
newVersion=$2
|
||||
echo "Prepare to replace the GF library version numbers in all go.mod files in the ${workdir} directory with ${newVersion}"
|
||||
echo "Prepare to replace the GoFrame 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)
|
||||
@ -28,10 +43,10 @@ fi
|
||||
|
||||
if [[ true ]]; then
|
||||
# Use sed to replace the version number in version.go
|
||||
sed -i '' 's/VERSION = ".*"/VERSION = "'${newVersion}'"/' version.go
|
||||
$SED_INPLACE 's/VERSION = ".*"/VERSION = "'${newVersion}'"/' version.go
|
||||
|
||||
# Use sed to replace the version number in README.MD
|
||||
sed -i '' 's/version=[^"]*/version='${newVersion}'/' README.MD
|
||||
$SED_INPLACE 's/version=[^"]*/version='${newVersion}'/' README.MD
|
||||
fi
|
||||
|
||||
if [ -f "go.work" ]; then
|
||||
@ -49,6 +64,11 @@ for file in `find ${workdir} -name go.mod`; do
|
||||
continue 1
|
||||
fi
|
||||
|
||||
if [[ $goModPath =~ "/examples/" ]]; then
|
||||
echo "ignore examples path $goModPath"
|
||||
continue 1
|
||||
fi
|
||||
|
||||
cd $goModPath
|
||||
if [ $goModPath = "./cmd/gf" ]; then
|
||||
mv go.work go.work.version.bak
|
||||
@ -59,15 +79,22 @@ for file in `find ${workdir} -name go.mod`; do
|
||||
go mod edit -replace github.com/gogf/gf/contrib/drivers/oracle/v2=../../contrib/drivers/oracle
|
||||
go mod edit -replace github.com/gogf/gf/contrib/drivers/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
|
||||
# Remove indirect dependencies
|
||||
sed -i '/\/\/ indirect/d' go.mod
|
||||
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
|
||||
# Remove toolchain line if exists
|
||||
$SED_INPLACE '/^toolchain/d' go.mod
|
||||
|
||||
# Upgrading only GoFrame related libraries, sometimes even if a version number is specified,
|
||||
# it may not be possible to successfully upgrade. Please confirm before submitting the code
|
||||
go list -f "{{if and (not .Indirect) (not .Main)}}{{.Path}}@${newVersion}{{end}}" -m all | grep "^github.com/gogf/gf"
|
||||
go list -f "{{if and (not .Indirect) (not .Main)}}{{.Path}}@${newVersion}{{end}}" -m all | grep "^github.com/gogf/gf" | xargs -L1 go get -v
|
||||
# Remove indirect dependencies
|
||||
sed -i '/\/\/ indirect/d' go.mod
|
||||
go mod tidy
|
||||
# Remove toolchain line if exists
|
||||
$SED_INPLACE '/^toolchain/d' go.mod
|
||||
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
|
||||
17
CONTRIBUTING.md
Normal file
17
CONTRIBUTING.md
Normal file
@ -0,0 +1,17 @@
|
||||
# Contributing
|
||||
|
||||
Thanks for taking the time to join our community and start contributing!
|
||||
|
||||
## With issues
|
||||
|
||||
- Use the search tool before opening a new issue.
|
||||
- Please provide source code and commit sha if you found a bug.
|
||||
- Review existing issues and provide feedback or react to them.
|
||||
|
||||
## With pull requests
|
||||
|
||||
- Open your pull request against `master`
|
||||
- Your pull request should have no more than two commits, if not you should squash them.
|
||||
- It should pass all tests in the available continuous integrations systems such as GitHub CI.
|
||||
- You should add/modify tests to cover your proposed code changes.
|
||||
- If your pull request contains a new feature, please document it on the README.
|
||||
72
Makefile
72
Makefile
@ -3,26 +3,76 @@ SHELL := /bin/bash
|
||||
# execute "go mod tidy" on all folders that have go.mod file
|
||||
.PHONY: tidy
|
||||
tidy:
|
||||
$(eval files=$(shell find . -name go.mod))
|
||||
@set -e; \
|
||||
for file in ${files}; do \
|
||||
goModPath=$$(dirname $$file); \
|
||||
if ! echo $$goModPath | grep -q "testdata"; then \
|
||||
cd $$goModPath; \
|
||||
go mod tidy; \
|
||||
cd -; \
|
||||
fi \
|
||||
done
|
||||
./.make_tidy.sh
|
||||
|
||||
# execute "golangci-lint" to check code style
|
||||
# go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@latest
|
||||
.PHONY: lint
|
||||
lint:
|
||||
golangci-lint run -c .golangci.yml
|
||||
|
||||
# make branch to=v2.4.0
|
||||
.PHONY: branch
|
||||
branch:
|
||||
@set -e; \
|
||||
newVersion=$(to); \
|
||||
if [ -z "$$newVersion" ]; then \
|
||||
echo "Error: 'to' variable is required. Usage: make branch to=vX.Y.Z"; \
|
||||
exit 1; \
|
||||
fi; \
|
||||
branchName=fix/$$newVersion; \
|
||||
echo "Switching to master branch..."; \
|
||||
git checkout master; \
|
||||
echo "Pulling latest changes from master..."; \
|
||||
git pull origin master; \
|
||||
echo "Creating and switching to branch $$branchName from master..."; \
|
||||
git checkout -b $$branchName; \
|
||||
echo "Branch $$branchName created successfully!"
|
||||
|
||||
# make version to=v2.4.0
|
||||
.PHONY: version
|
||||
version:
|
||||
@set -e; \
|
||||
newVersion=$(to); \
|
||||
./.set_version.sh ./ $$newVersion; \
|
||||
./.make_version.sh ./ $$newVersion; \
|
||||
echo "make version to=$(to) done"
|
||||
|
||||
# make tag to=v2.4.0
|
||||
.PHONY: tag
|
||||
tag:
|
||||
@set -e; \
|
||||
newVersion=$(to); \
|
||||
echo "Switching to master branch..."; \
|
||||
git checkout master; \
|
||||
echo "Pulling latest changes from master..."; \
|
||||
git pull origin master; \
|
||||
echo "Creating annotated tag $$newVersion..."; \
|
||||
git tag -a $$newVersion -m "Release $$newVersion"; \
|
||||
echo "Pushing tag $$newVersion..."; \
|
||||
git push origin $$newVersion; \
|
||||
echo "Tag $$newVersion created and pushed successfully!"
|
||||
|
||||
# update submodules
|
||||
.PHONY: subup
|
||||
subup:
|
||||
@set -e; \
|
||||
echo "Updating submodules..."; \
|
||||
git submodule init;\
|
||||
git submodule update;
|
||||
|
||||
# update and commit submodules
|
||||
.PHONY: subsync
|
||||
subsync: subup
|
||||
@set -e; \
|
||||
echo "";\
|
||||
cd examples; \
|
||||
echo "Checking for changes..."; \
|
||||
if git diff-index --quiet HEAD --; then \
|
||||
echo "No changes to commit"; \
|
||||
else \
|
||||
echo "Found changes, committing..."; \
|
||||
git add -A; \
|
||||
git commit -m "examples update"; \
|
||||
git push origin; \
|
||||
fi; \
|
||||
cd ..;
|
||||
|
||||
27
README.MD
27
README.MD
@ -1,9 +1,12 @@
|
||||
English | [简体中文](README.zh_CN.MD)
|
||||
|
||||
<div align=center>
|
||||
<img src="https://goframe.org/img/logo_full.png" width="300" alt="goframe gf logo"/>
|
||||
|
||||
[](https://pkg.go.dev/github.com/gogf/gf/v2)
|
||||
[](https://github.com/gogf/gf/actions/workflows/ci-main.yml)
|
||||
[](https://scorecard.dev/viewer/?uri=github.com/gogf/gf)
|
||||
[](https://bestpractices.coreinfrastructure.org/projects/9233)
|
||||
[](https://goreportcard.com/report/github.com/gogf/gf/v2)
|
||||
[](https://codecov.io/gh/gogf/gf)
|
||||
[](https://github.com/gogf/gf)
|
||||
@ -21,24 +24,30 @@
|
||||
|
||||
A powerful framework for faster, easier, and more efficient project development.
|
||||
|
||||
## Installation
|
||||
|
||||
# Documentation
|
||||
```bash
|
||||
go get -u github.com/gogf/gf/v2
|
||||
```
|
||||
|
||||
- GoFrame Official Site: [https://goframe.org](https://goframe.org)
|
||||
- GoFrame Official Site(en): [https://goframe.org/en](https://goframe.org/en)
|
||||
- GoFrame Mirror Site(中文): [https://goframe.org.cn](https://goframe.org.cn)
|
||||
- GoFrame Mirror Site(github pages): [https://pages.goframe.org](https://pages.goframe.org)
|
||||
## Documentation
|
||||
|
||||
- Official Site: [https://goframe.org](https://goframe.org)
|
||||
- Official Site(en): [https://goframe.org/en](https://goframe.org/en)
|
||||
- 国内镜像: [https://goframe.org.cn](https://goframe.org.cn)
|
||||
- Mirror Site: [Github Pages](https://pages.goframe.org)
|
||||
- Mirror Site: [Offline Docs](https://github.com/gogf/goframe.org-pdf?tab=readme-ov-file#%E6%9C%80%E6%96%B0%E7%89%88%E6%9C%AC)
|
||||
- GoDoc API: [https://pkg.go.dev/github.com/gogf/gf/v2](https://pkg.go.dev/github.com/gogf/gf/v2)
|
||||
- Doc Source: [https://github.com/gogf/gf-site](https://github.com/gogf/gf-site)
|
||||
|
||||
|
||||
# Contributors
|
||||
## Contributors
|
||||
|
||||
💖 [Thanks to all the contributors who made GoFrame possible](https://github.com/gogf/gf/graphs/contributors) 💖
|
||||
|
||||
<a href="https://github.com/gogf/gf/graphs/contributors">
|
||||
<img src="https://goframe.org/img/contributors.svg?version=v2.8.3" alt="goframe contributors"/>
|
||||
<img src="https://goframe.org/img/contributors.svg?version=v2.9.7" alt="goframe contributors"/>
|
||||
</a>
|
||||
|
||||
# License
|
||||
## License
|
||||
|
||||
`GoFrame` is licensed under the [MIT License](LICENSE), 100% free and open-source, forever.
|
||||
|
||||
53
README.zh_CN.MD
Normal file
53
README.zh_CN.MD
Normal file
@ -0,0 +1,53 @@
|
||||
[English](README.MD) | 简体中文
|
||||
|
||||
<div align=center>
|
||||
<img src="https://goframe.org/img/logo_full.png" width="300" alt="goframe gf logo"/>
|
||||
|
||||
[](https://pkg.go.dev/github.com/gogf/gf/v2)
|
||||
[](https://github.com/gogf/gf/actions/workflows/ci-main.yml)
|
||||
[](https://scorecard.dev/viewer/?uri=github.com/gogf/gf)
|
||||
[](https://bestpractices.coreinfrastructure.org/projects/9233)
|
||||
[](https://goreportcard.com/report/github.com/gogf/gf/v2)
|
||||
[](https://codecov.io/gh/gogf/gf)
|
||||
[](https://github.com/gogf/gf)
|
||||
[](https://github.com/gogf/gf)
|
||||
|
||||
[](https://github.com/gogf/gf/releases)
|
||||
[](https://github.com/gogf/gf/pulls)
|
||||
[](https://github.com/gogf/gf/pulls?q=is%3Apr+is%3Aclosed)
|
||||
[](https://github.com/gogf/gf/issues)
|
||||
[](https://github.com/gogf/gf/issues?q=is%3Aissue+is%3Aclosed)
|
||||

|
||||

|
||||
|
||||
</div>
|
||||
|
||||
一个强大的框架,为了更快、更轻松、更高效的项目开发。
|
||||
|
||||
## 安装
|
||||
|
||||
```bash
|
||||
go get -u github.com/gogf/gf/v2
|
||||
```
|
||||
|
||||
## 文档
|
||||
|
||||
- 官方网站: [https://goframe.org](https://goframe.org)
|
||||
- 官方网站(en): [https://goframe.org/en](https://goframe.org/en)
|
||||
- 国内镜像: [https://goframe.org.cn](https://goframe.org.cn)
|
||||
- 镜像网站: [Github Pages](https://pages.goframe.org)
|
||||
- 镜像网站: [离线文档](https://github.com/gogf/goframe.org-pdf?tab=readme-ov-file#%E6%9C%80%E6%96%B0%E7%89%88%E6%9C%AC)
|
||||
- Go包文档: [https://pkg.go.dev/github.com/gogf/gf/v2](https://pkg.go.dev/github.com/gogf/gf/v2)
|
||||
- 文档源码: [https://github.com/gogf/gf-site](https://github.com/gogf/gf-site)
|
||||
|
||||
## 贡献者
|
||||
|
||||
💖 [感谢所有使 GoFrame 成为可能的贡献者](https://github.com/gogf/gf/graphs/contributors) 💖
|
||||
|
||||
<a href="https://github.com/gogf/gf/graphs/contributors">
|
||||
<img src="https://goframe.org/img/contributors.svg?version=v2.9.5" alt="goframe contributors"/>
|
||||
</a>
|
||||
|
||||
## 许可证
|
||||
|
||||
`GoFrame` 采用 [MIT License](LICENSE) 许可,100% 免费和开源,永久保持。
|
||||
@ -1,3 +1,5 @@
|
||||
English | [简体中文](README.zh_CN.MD)
|
||||
|
||||
# gf
|
||||
|
||||
`gf` is a powerful CLI tool for building [GoFrame](https://goframe.org) application with convenience.
|
||||
@ -21,18 +23,18 @@ You can also install `gf` tool using pre-built binaries: <https://github.com/gog
|
||||
|
||||
3. Database support
|
||||
|
||||
| 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. |
|
||||
| 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 | yes | - |
|
||||
| dm | no | manually add package import to the [source codes](./internal/cmd/cmd_gen_dao.go) and do the building. |
|
||||
|
||||
## 2) Manually Install
|
||||
|
||||
@ -43,30 +45,31 @@ go install github.com/gogf/gf/cmd/gf/v2@v2.5.5 # certain version(should be >= v2
|
||||
|
||||
## 2. Commands
|
||||
|
||||
```html
|
||||
$ gf
|
||||
```shell
|
||||
$ gf -h
|
||||
USAGE
|
||||
gf COMMAND [OPTION]
|
||||
|
||||
COMMAND
|
||||
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
|
||||
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
|
||||
doc download https://pages.goframe.org/ to run locally
|
||||
|
||||
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.
|
||||
|
||||
82
cmd/gf/README.zh_CN.MD
Normal file
82
cmd/gf/README.zh_CN.MD
Normal file
@ -0,0 +1,82 @@
|
||||
[English](README.MD) | 简体中文
|
||||
|
||||
# gf
|
||||
|
||||
`gf` 是一个强大的 CLI 工具,用于便捷地构建 [GoFrame](https://goframe.org) 应用程序。
|
||||
|
||||
## 1. 安装
|
||||
|
||||
## 1) 预编译二进制文件
|
||||
|
||||
您也可以使用预构建的二进制文件安装 `gf` 工具:<https://github.com/gogf/gf/releases>
|
||||
|
||||
1. `Mac` & `Linux`
|
||||
|
||||
```shell
|
||||
wget -O gf https://github.com/gogf/gf/releases/latest/download/gf_$(go env GOOS)_$(go env GOARCH) && chmod +x gf && ./gf install -y && rm ./gf
|
||||
```
|
||||
|
||||
> 如果您使用 `zsh`,您可能需要通过命令 `alias gf=gf` 重命名别名以解决 `gf` 和 `git fetch` 之间的冲突。
|
||||
|
||||
2. `Windows`
|
||||
手动下载,在命令行中执行,然后按照说明操作。
|
||||
|
||||
3. 数据库支持
|
||||
|
||||
| 数据库 | 内置支持 | 说明 |
|
||||
| :--------: | :-------------: | :-------------------------------------------------------------------------------------------------------------------------------------------------------------: |
|
||||
| mysql | 是 | - |
|
||||
| mariadb | 是 | - |
|
||||
| tidb | 是 | - |
|
||||
| mssql | 是 | - |
|
||||
| oracle | 是 | - |
|
||||
| pgsql | 是 | - |
|
||||
| sqlite | 是 | - |
|
||||
| sqlitecgo | 否 | 要在 32 位架构系统上支持 sqlite 数据库,请手动向[源代码](./internal/cmd/cmd_gen_dao.go)添加包导入并进行构建。 |
|
||||
| clickhouse | 是 | - |
|
||||
| dm | 否 | 手动向[源代码](./internal/cmd/cmd_gen_dao.go)添加包导入并进行构建。 |
|
||||
|
||||
## 2) 手动安装
|
||||
|
||||
```shell
|
||||
go install github.com/gogf/gf/cmd/gf/v2@latest # 最新版本
|
||||
go install github.com/gogf/gf/cmd/gf/v2@v2.5.5 # 特定版本(应该 >= v2.5.5)
|
||||
```
|
||||
|
||||
## 2. 命令
|
||||
|
||||
```shell
|
||||
$ gf -h
|
||||
用法
|
||||
gf 命令 [选项]
|
||||
|
||||
命令
|
||||
up 升级项目中的 GoFrame 版本/工具到最新版本
|
||||
env 显示当前 Golang 环境变量
|
||||
fix 升级到新 GoFrame 版本后自动修复代码
|
||||
run 运行 go 代码,具有热编译功能
|
||||
gen 自动生成 dao/do/entity/pb/pbentity 的 go 文件
|
||||
tpl 模板解析和构建命令
|
||||
init 创建并初始化一个空的 GoFrame 项目
|
||||
pack 将任何文件/目录打包到资源文件或 go 文件
|
||||
build 为多个平台交叉编译 go 项目
|
||||
docker 为当前 GoFrame 项目构建 docker 镜像
|
||||
install 将 gf 二进制文件安装到系统(可能需要 root/admin 权限)
|
||||
version 显示当前二进制文件的版本信息
|
||||
doc 下载 https://pages.goframe.org/ 本地运行
|
||||
|
||||
选项
|
||||
-y, --yes 对所有命令都使用 yes,不再提示
|
||||
-v, --version 显示当前二进制文件的版本信息
|
||||
-d, --debug 显示内部详细的调试信息
|
||||
-h, --help 显示此命令的更多信息
|
||||
|
||||
附加信息
|
||||
使用 "gf 命令 -h" 获取有关命令的详细信息。
|
||||
```
|
||||
|
||||
## 3. 常见问题
|
||||
|
||||
### 1). 命令 `gf run` 返回 `pipe: too many open files`
|
||||
|
||||
请使用 `ulimit -n 65535` 扩大系统配置以增加当前终端 shell 会话的最大打开文件数,然后再运行 `gf run`。
|
||||
@ -1,33 +1,33 @@
|
||||
module github.com/gogf/gf/cmd/gf/v2
|
||||
|
||||
go 1.20
|
||||
go 1.23.0
|
||||
|
||||
require (
|
||||
github.com/gogf/gf/contrib/drivers/clickhouse/v2 v2.8.3
|
||||
github.com/gogf/gf/contrib/drivers/mssql/v2 v2.8.3
|
||||
github.com/gogf/gf/contrib/drivers/mysql/v2 v2.8.3
|
||||
github.com/gogf/gf/contrib/drivers/oracle/v2 v2.8.3
|
||||
github.com/gogf/gf/contrib/drivers/pgsql/v2 v2.8.3
|
||||
github.com/gogf/gf/contrib/drivers/sqlite/v2 v2.8.3
|
||||
github.com/gogf/gf/v2 v2.8.3
|
||||
github.com/gogf/gf/contrib/drivers/clickhouse/v2 v2.9.7
|
||||
github.com/gogf/gf/contrib/drivers/mssql/v2 v2.9.7
|
||||
github.com/gogf/gf/contrib/drivers/mysql/v2 v2.9.7
|
||||
github.com/gogf/gf/contrib/drivers/oracle/v2 v2.9.7
|
||||
github.com/gogf/gf/contrib/drivers/pgsql/v2 v2.9.7
|
||||
github.com/gogf/gf/contrib/drivers/sqlite/v2 v2.9.7
|
||||
github.com/gogf/gf/v2 v2.9.7
|
||||
github.com/gogf/selfupdate v0.0.0-20231215043001-5c48c528462f
|
||||
github.com/olekukonko/tablewriter v0.0.5
|
||||
github.com/olekukonko/tablewriter v1.1.0
|
||||
github.com/schollz/progressbar/v3 v3.15.0
|
||||
golang.org/x/mod v0.17.0
|
||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d
|
||||
golang.org/x/mod v0.25.0
|
||||
golang.org/x/tools v0.26.0
|
||||
)
|
||||
|
||||
require (
|
||||
aead.dev/minisign v0.2.0 // indirect
|
||||
github.com/BurntSushi/toml v1.4.0 // indirect
|
||||
github.com/BurntSushi/toml v1.5.0 // indirect
|
||||
github.com/ClickHouse/clickhouse-go/v2 v2.0.15 // indirect
|
||||
github.com/clbanning/mxj/v2 v2.7.0 // indirect
|
||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||
github.com/emirpasic/gods v1.18.1 // indirect
|
||||
github.com/emirpasic/gods/v2 v2.0.0-alpha // indirect
|
||||
github.com/fatih/color v1.18.0 // indirect
|
||||
github.com/fsnotify/fsnotify v1.7.0 // indirect
|
||||
github.com/fsnotify/fsnotify v1.9.0 // indirect
|
||||
github.com/glebarez/go-sqlite v1.21.2 // indirect
|
||||
github.com/go-logr/logr v1.4.2 // indirect
|
||||
github.com/go-logr/logr v1.4.3 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/go-sql-driver/mysql v1.7.1 // indirect
|
||||
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 // indirect
|
||||
@ -36,28 +36,31 @@ require (
|
||||
github.com/gorilla/websocket v1.5.3 // indirect
|
||||
github.com/grokify/html-strip-tags-go v0.1.0 // indirect
|
||||
github.com/lib/pq v1.10.9 // indirect
|
||||
github.com/magiconair/properties v1.8.9 // indirect
|
||||
github.com/magiconair/properties v1.8.10 // 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.16 // indirect
|
||||
github.com/microsoft/go-mssqldb v1.7.1 // indirect
|
||||
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db // indirect
|
||||
github.com/olekukonko/errors v1.1.0 // indirect
|
||||
github.com/olekukonko/ll v0.0.9 // indirect
|
||||
github.com/paulmach/orb v0.7.1 // indirect
|
||||
github.com/pierrec/lz4/v4 v4.1.14 // indirect
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
||||
github.com/rivo/uniseg v0.4.7 // indirect
|
||||
github.com/shopspring/decimal v1.3.1 // indirect
|
||||
github.com/sijms/go-ora/v2 v2.7.10 // indirect
|
||||
go.opentelemetry.io/otel v1.24.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.24.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk v1.24.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.24.0 // indirect
|
||||
golang.org/x/crypto v0.31.0 // indirect
|
||||
golang.org/x/net v0.33.0 // indirect
|
||||
golang.org/x/sync v0.10.0 // indirect
|
||||
golang.org/x/sys v0.28.0 // indirect
|
||||
golang.org/x/term v0.27.0 // indirect
|
||||
golang.org/x/text v0.21.0 // indirect
|
||||
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
|
||||
go.opentelemetry.io/otel v1.38.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.38.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk v1.38.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.38.0 // indirect
|
||||
golang.org/x/crypto v0.38.0 // indirect
|
||||
golang.org/x/net v0.40.0 // indirect
|
||||
golang.org/x/sync v0.14.0 // indirect
|
||||
golang.org/x/sys v0.35.0 // indirect
|
||||
golang.org/x/term v0.32.0 // indirect
|
||||
golang.org/x/text v0.25.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
modernc.org/libc v1.22.5 // indirect
|
||||
modernc.org/mathutil v1.5.0 // indirect
|
||||
|
||||
122
cmd/gf/go.sum
122
cmd/gf/go.sum
@ -1,13 +1,19 @@
|
||||
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 v1.9.1 h1:lGlwhPtrX6EVml1hO0ivjkUxsSyl4dsiw9qcA1k/3IQ=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.1/go.mod h1:RKUqNu35KJYcVG/fqTRqmuXJZYNhYkBrnC/hX7yGbTA=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.5.1 h1:sO0/P7g68FrryJzljemN+6GTssUXdANk6aJ7T1ZxnsQ=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.5.1/go.mod h1:h8hyGFDsU5HMivxiS2iYFZsgDbU9OnnJ163x5UGVKYo=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.1 h1:6oNBlSdi1QqM1PNW7FPA6xOGA5UNsXnkaYZz9vdPGhA=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.1/go.mod h1:s4kgfzA0covAXNicZHDMN58jExvcng2mC/DepXiF1EI=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys v1.0.1 h1:MyVTgWR8qd/Jw1Le0NZebGBUCLbtak3bJ3z1OlqZBpw=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/azkeys v1.0.1/go.mod h1:GpPjLhVR9dnUoJMyHWSPy71xY9/lcmpzIPZXmF0FCVY=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.0.0 h1:D3occbWoio4EBLkbkevetNMAVX197GkzbUMtqjGWn80=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/security/keyvault/internal v1.0.0/go.mod h1:bTSOgj05NGRuHHhQwAdPnYr9TOdNmKlZTgGLL6nyAdI=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.1 h1:DzHpqpoJVaCgOUdVHxE8QB52S6NiVdDQvGlny1qvPqA=
|
||||
github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0=
|
||||
github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.1/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI=
|
||||
github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg=
|
||||
github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
|
||||
github.com/ClickHouse/clickhouse-go v1.5.4/go.mod h1:EaI/sW7Azgz9UATzd5ZdZHRUhHgv5+JMS9NSr2smCJI=
|
||||
github.com/ClickHouse/clickhouse-go/v2 v2.0.15 h1:lLAZliqrZEygkxosLaW1qHyeTb4Ho7fVCZ0WKCpLocU=
|
||||
github.com/ClickHouse/clickhouse-go/v2 v2.0.15/go.mod h1:Z21o82zD8FFqefOQDg93c0XITlxGbTsWQuRm588Azkk=
|
||||
@ -21,18 +27,18 @@ 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/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/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
|
||||
github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
|
||||
github.com/emirpasic/gods/v2 v2.0.0-alpha h1:dwFlh8pBg1VMOXWGipNMRt8v96dKAIvBehtCt6OtunU=
|
||||
github.com/emirpasic/gods/v2 v2.0.0-alpha/go.mod h1:W0y4M2dtBB9U5z3YlghmpuUhiaZT2h6yoeE+C1sCp6A=
|
||||
github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=
|
||||
github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU=
|
||||
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/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
|
||||
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
|
||||
github.com/glebarez/go-sqlite v1.21.2 h1:3a6LFC4sKahUunAmynQKLZceZCOzUthkRkEAl9gAXWo=
|
||||
github.com/glebarez/go-sqlite v1.21.2/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/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
|
||||
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
|
||||
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
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=
|
||||
@ -40,24 +46,11 @@ github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiU
|
||||
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
||||
github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI=
|
||||
github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
|
||||
github.com/gogf/gf/contrib/drivers/clickhouse/v2 v2.8.3 h1:b/AQMTxiHKPHsidEdk471AC5pkfoK88a5cPmKnzE53U=
|
||||
github.com/gogf/gf/contrib/drivers/clickhouse/v2 v2.8.3/go.mod h1:qYrF+x5urXLhce3pMcUAyccIsw3Oec0htynoDE4Boi4=
|
||||
github.com/gogf/gf/contrib/drivers/mssql/v2 v2.8.3 h1:F7Gt1y6YsYOIvgrUlRK07H29BL77dEgLPXilTqqVC80=
|
||||
github.com/gogf/gf/contrib/drivers/mssql/v2 v2.8.3/go.mod h1:K5prIMZwHANSZrqZbfm6PoEIMfLtd0PwR7u+hZD9HFs=
|
||||
github.com/gogf/gf/contrib/drivers/mysql/v2 v2.8.3 h1:RtoBg5HWACFrgIrFkpzH94kxSd5EWefNAq5k6olNY6c=
|
||||
github.com/gogf/gf/contrib/drivers/mysql/v2 v2.8.3/go.mod h1:elZjckHRCejwml5Kdx2zfhOUDiAV3r5i4BgXcKAeH00=
|
||||
github.com/gogf/gf/contrib/drivers/oracle/v2 v2.8.3 h1:10/RCoWmvQ6PSm+leoS6CsKijH4dB38HOXLgP5+aScQ=
|
||||
github.com/gogf/gf/contrib/drivers/oracle/v2 v2.8.3/go.mod h1:XSaHf3/vTlzj/zioUbzKmaffPuoKvPV639fT91caheM=
|
||||
github.com/gogf/gf/contrib/drivers/pgsql/v2 v2.8.3 h1:DvpoiVac1cwGVDTqC6wzFbDb+gXNzcceRgZUIcuTmaI=
|
||||
github.com/gogf/gf/contrib/drivers/pgsql/v2 v2.8.3/go.mod h1:zugvYVb6c/X9rJ8Gb6b5WkMe+bFz2BsxQ5OLf4RSZos=
|
||||
github.com/gogf/gf/contrib/drivers/sqlite/v2 v2.8.3 h1:3pdibfm4UOiTGGh6UD8jfMyGZBGH9ikrrIMU8i/XANA=
|
||||
github.com/gogf/gf/contrib/drivers/sqlite/v2 v2.8.3/go.mod h1:G5rfcFkBhtmZT4+CU7A3fJH3sNmP4WRIaJ+4JFeVE08=
|
||||
github.com/gogf/gf/v2 v2.8.3 h1:h9Px3lqJnnH6It0AqHRz4/1hx0JmvaSf1IvUir5x1rA=
|
||||
github.com/gogf/gf/v2 v2.8.3/go.mod h1:n++xPYGUUMadw6IygLEgGZqc6y6DRLrJKg5kqCrPLWY=
|
||||
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-jwt/jwt/v5 v5.2.0 h1:d/ix8ftRUorsN+5eMIlF4T6J8CAt9rch3My2winC1Jw=
|
||||
github.com/golang-jwt/jwt/v5 v5.2.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
|
||||
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 h1:au07oEsX2xN0ktxqI+Sida1w446QrXBRJ0nee3SNZlA=
|
||||
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
|
||||
github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A=
|
||||
@ -65,8 +58,10 @@ github.com/golang-sql/sqlexp v0.1.0/go.mod h1:J4ad9Vo8ZCWQ2GMrC4UCQy1JpCbwU9m3EO
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||
github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ=
|
||||
github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo=
|
||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
@ -80,18 +75,22 @@ github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhB
|
||||
github.com/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213/go.mod h1:vNUNkEQ1e29fT/6vq2aBdFsgNPmy8qMdSay1npru+Sw=
|
||||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
|
||||
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
|
||||
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
|
||||
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/magiconair/properties v1.8.9 h1:nWcCbLq1N2v/cpNsy5WvQ37Fb+YElfq20WJ/a8RkpQM=
|
||||
github.com/magiconair/properties v1.8.9/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
|
||||
github.com/magiconair/properties v1.8.10 h1:s31yESBquKXCV9a/ScB3ESkOjUYYv+X0rg8SYxI99mE=
|
||||
github.com/magiconair/properties v1.8.10/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
|
||||
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.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
|
||||
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
||||
@ -100,8 +99,12 @@ github.com/microsoft/go-mssqldb v1.7.1/go.mod h1:kOvZKUdrhhFQmxLZqbwUV0rHkNkZpth
|
||||
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db h1:62I3jR2EmQ4l5rM/4FEfDWcRD+abF5XlKShorW5LRoQ=
|
||||
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db/go.mod h1:l0dey0ia/Uv7NcFFVbCLtqEBQbrT4OCwCSKTEv6enCw=
|
||||
github.com/mkevac/debugcharts v0.0.0-20191222103121-ae1c48aa8615/go.mod h1:Ad7oeElCZqA1Ufj0U9/liOF4BtVepxRcTvr2ey7zTvM=
|
||||
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
|
||||
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
|
||||
github.com/olekukonko/errors v1.1.0 h1:RNuGIh15QdDenh+hNvKrJkmxxjV4hcS50Db478Ou5sM=
|
||||
github.com/olekukonko/errors v1.1.0/go.mod h1:ppzxA5jBKcO1vIpCXQ9ZqgDh8iwODz6OXIGKU8r5m4Y=
|
||||
github.com/olekukonko/ll v0.0.9 h1:Y+1YqDfVkqMWuEQMclsF9HUR5+a82+dxJuL1HHSRpxI=
|
||||
github.com/olekukonko/ll v0.0.9/go.mod h1:En+sEW0JNETl26+K8eZ6/W4UQ7CYSrrgg/EdIYT2H8g=
|
||||
github.com/olekukonko/tablewriter v1.1.0 h1:N0LHrshF4T39KvI96fn6GT8HEjXRXYNDrDjKFDB7RIY=
|
||||
github.com/olekukonko/tablewriter v1.1.0/go.mod h1:5c+EBPeSqvXnLLgkm9isDdzR3wjfBkHR9Nhfp3NWrzo=
|
||||
github.com/paulmach/orb v0.7.1 h1:Zha++Z5OX/l168sqHK3k4z18LDvr+YAO/VjK0ReQ9rU=
|
||||
github.com/paulmach/orb v0.7.1/go.mod h1:FWRlTgl88VI1RBx/MkrwWDRhQ96ctqMCh8boXhmqB/A=
|
||||
github.com/paulmach/protoscan v0.2.1/go.mod h1:SpcSwydNLrxUGSDvXvO0P7g7AuhJ7lcKfDlhJCDw2gY=
|
||||
@ -109,6 +112,7 @@ github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi
|
||||
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-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ=
|
||||
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||
@ -117,6 +121,8 @@ github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qq
|
||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
|
||||
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
|
||||
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
|
||||
github.com/schollz/progressbar/v3 v3.15.0 h1:cNZmcNiVyea6oofBTg80ZhVXxf3wG/JoAhqCCwopkQo=
|
||||
github.com/schollz/progressbar/v3 v3.15.0/go.mod h1:ncBdc++eweU0dQoeZJ3loXoAc+bjaallHRIm8pVVeQM=
|
||||
github.com/shirou/gopsutil v2.19.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
|
||||
@ -131,43 +137,50 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
|
||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||
github.com/tklauser/go-sysconf v0.3.10/go.mod h1:C8XykCvCb+Gn0oNCWPIlcb0RuglQTYaQ2hGm7jmxEFk=
|
||||
github.com/tklauser/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/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
|
||||
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
|
||||
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
|
||||
go.opentelemetry.io/otel v1.7.0/go.mod h1:5BdUoMIz5WEs0vt0CUEMtSSaTSHBBVwrhnz7+nrD5xk=
|
||||
go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo=
|
||||
go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo=
|
||||
go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI=
|
||||
go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco=
|
||||
go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucgoDw=
|
||||
go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg=
|
||||
go.opentelemetry.io/otel v1.38.0 h1:RkfdswUDRimDg0m2Az18RKOsnI8UDzppJAtj01/Ymk8=
|
||||
go.opentelemetry.io/otel v1.38.0/go.mod h1:zcmtmQ1+YmQM9wrNsTGV/q/uyusom3P8RxwExxkZhjM=
|
||||
go.opentelemetry.io/otel/metric v1.38.0 h1:Kl6lzIYGAh5M159u9NgiRkmoMKjvbsKtYRwgfrA6WpA=
|
||||
go.opentelemetry.io/otel/metric v1.38.0/go.mod h1:kB5n/QoRM8YwmUahxvI3bO34eVtQf2i4utNVLr9gEmI=
|
||||
go.opentelemetry.io/otel/sdk v1.38.0 h1:l48sr5YbNf2hpCUj/FoGhW9yDkl+Ma+LrVl8qaM5b+E=
|
||||
go.opentelemetry.io/otel/sdk v1.38.0/go.mod h1:ghmNdGlVemJI3+ZB5iDEuk4bWA3GkTpW+DOoZMYBVVg=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.38.0 h1:aSH66iL0aZqo//xXzQLYozmWrXxyFkBJ6qT5wthqPoM=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.38.0/go.mod h1:dg9PBnW9XdQ1Hd6ZnRz689CbtrUp0wMMs9iPcgT9EZA=
|
||||
go.opentelemetry.io/otel/trace v1.7.0/go.mod h1:fzLSB9nqR2eXzxPXb2JW9IKE+ScyXA48yyE4TNvoHqU=
|
||||
go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI=
|
||||
go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU=
|
||||
go.opentelemetry.io/otel/trace v1.38.0 h1:Fxk5bKrDZJUH+AMyyIXGcFAPah0oRcT+LuNtJrmcNLE=
|
||||
go.opentelemetry.io/otel/trace v1.38.0/go.mod h1:j1P9ivuFsTceSWe1oY+EeW3sc+Pp42sO++GHkg4wwhs=
|
||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||
golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
|
||||
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
|
||||
golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8=
|
||||
golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw=
|
||||
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.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA=
|
||||
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/mod v0.25.0 h1:n7a+ZbQKQA/Ysbyb0/6IbB1H/X41mKgbhfv7AfG/44w=
|
||||
golang.org/x/mod v0.25.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
|
||||
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.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I=
|
||||
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
|
||||
golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY=
|
||||
golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds=
|
||||
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.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
|
||||
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ=
|
||||
golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@ -180,30 +193,31 @@ golang.org/x/sys v0.0.0-20220429233432-b5fbb4746d32/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
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.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
|
||||
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
|
||||
golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8=
|
||||
golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q=
|
||||
golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
|
||||
golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg=
|
||||
golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
|
||||
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
|
||||
golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4=
|
||||
golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA=
|
||||
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-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg=
|
||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
|
||||
golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ=
|
||||
golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
|
||||
@ -1,8 +1,6 @@
|
||||
go 1.20
|
||||
go 1.23.0
|
||||
|
||||
use (
|
||||
./
|
||||
)
|
||||
use ./
|
||||
|
||||
// =====================================================================================================
|
||||
// NOTE:
|
||||
@ -16,5 +14,9 @@ replace (
|
||||
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/contrib/drivers/mariadb/v2 => ../../contrib/drivers/mariadb
|
||||
github.com/gogf/gf/contrib/drivers/tidb/v2 => ../../contrib/drivers/tidb
|
||||
github.com/gogf/gf/contrib/drivers/oceanbase/v2 => ../../contrib/drivers/oceanbase
|
||||
github.com/gogf/gf/contrib/drivers/gaussdb/v2 => ../../contrib/drivers/gaussdb
|
||||
github.com/gogf/gf/v2 => ../../
|
||||
)
|
||||
|
||||
@ -30,12 +30,10 @@ import (
|
||||
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
|
||||
)
|
||||
|
||||
var (
|
||||
Build = cBuild{
|
||||
nodeNameInConfigFile: "gfcli.build",
|
||||
packedGoFileName: "internal/packed/build_pack_data.go",
|
||||
}
|
||||
)
|
||||
var Build = cBuild{
|
||||
nodeNameInConfigFile: "gfcli.build",
|
||||
packedGoFileName: "internal/packed/build_pack_data.go",
|
||||
}
|
||||
|
||||
type cBuild struct {
|
||||
g.Meta `name:"build" brief:"{cBuildBrief}" dc:"{cBuildDc}" eg:"{cBuildEg}" ad:"{cBuildAd}"`
|
||||
@ -65,45 +63,67 @@ It provides much more features for building binary:
|
||||
`
|
||||
cBuildAd = `
|
||||
PLATFORMS
|
||||
aix ppc64
|
||||
android 386,amd64,arm,arm64
|
||||
darwin amd64,arm64
|
||||
dragonfly amd64
|
||||
freebsd 386,amd64,arm
|
||||
linux 386,amd64,arm,arm64,ppc64,ppc64le,mips,mipsle,mips64,mips64le
|
||||
illumos amd64
|
||||
ios arm64
|
||||
js wasm
|
||||
linux 386,amd64,arm,arm64,loong64,mips,mipsle,mips64,mips64le,ppc64,ppc64le,riscv64,s390x
|
||||
netbsd 386,amd64,arm
|
||||
openbsd 386,amd64,arm
|
||||
windows 386,amd64
|
||||
openbsd 386,amd64,arm,arm64
|
||||
plan9 386,amd64,arm
|
||||
solaris amd64
|
||||
wasip1 wasm
|
||||
windows 386,amd64,arm,arm64
|
||||
`
|
||||
// https://golang.google.cn/doc/install/source
|
||||
cBuildPlatforms = `
|
||||
aix ppc64
|
||||
android 386
|
||||
android amd64
|
||||
android arm
|
||||
android arm64
|
||||
darwin amd64
|
||||
darwin arm64
|
||||
ios amd64
|
||||
ios arm64
|
||||
dragonfly amd64
|
||||
freebsd 386
|
||||
freebsd amd64
|
||||
freebsd arm
|
||||
illumos amd64
|
||||
ios arm64
|
||||
js wasm
|
||||
linux 386
|
||||
linux amd64
|
||||
linux arm
|
||||
linux arm64
|
||||
linux ppc64
|
||||
linux ppc64le
|
||||
linux loong64
|
||||
linux mips
|
||||
linux mipsle
|
||||
linux mips64
|
||||
linux mips64le
|
||||
linux ppc64
|
||||
linux ppc64le
|
||||
linux riscv64
|
||||
linux s390x
|
||||
netbsd 386
|
||||
netbsd amd64
|
||||
netbsd arm
|
||||
openbsd 386
|
||||
openbsd amd64
|
||||
openbsd arm
|
||||
windows 386
|
||||
windows amd64
|
||||
android arm
|
||||
dragonfly amd64
|
||||
openbsd arm64
|
||||
plan9 386
|
||||
plan9 amd64
|
||||
plan9 arm
|
||||
solaris amd64
|
||||
wasip1 wasm
|
||||
windows 386
|
||||
windows amd64
|
||||
windows arm
|
||||
windows arm64
|
||||
`
|
||||
)
|
||||
|
||||
|
||||
@ -11,6 +11,8 @@ import (
|
||||
"context"
|
||||
|
||||
"github.com/olekukonko/tablewriter"
|
||||
"github.com/olekukonko/tablewriter/renderer"
|
||||
"github.com/olekukonko/tablewriter/tw"
|
||||
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gproc"
|
||||
@ -61,10 +63,23 @@ func (c cEnv) Index(ctx context.Context, in cEnvInput) (out *cEnvOutput, err err
|
||||
}
|
||||
array = append(array, []string{gstr.Trim(match[1]), gstr.Trim(match[2])})
|
||||
}
|
||||
tw := tablewriter.NewWriter(buffer)
|
||||
tw.SetColumnAlignment([]int{tablewriter.ALIGN_LEFT, tablewriter.ALIGN_LEFT})
|
||||
tw.AppendBulk(array)
|
||||
tw.Render()
|
||||
table := tablewriter.NewTable(buffer,
|
||||
tablewriter.WithRenderer(renderer.NewBlueprint(tw.Rendition{
|
||||
Settings: tw.Settings{
|
||||
Separators: tw.Separators{BetweenRows: tw.Off, BetweenColumns: tw.On},
|
||||
},
|
||||
Symbols: tw.NewSymbols(tw.StyleASCII),
|
||||
})),
|
||||
tablewriter.WithConfig(tablewriter.Config{
|
||||
Row: tw.CellConfig{
|
||||
Formatting: tw.CellFormatting{AutoWrap: tw.WrapNone},
|
||||
Alignment: tw.CellAlignment{PerColumn: []tw.Align{tw.AlignLeft, tw.AlignLeft}},
|
||||
ColMaxWidths: tw.CellWidth{Global: 84},
|
||||
},
|
||||
}),
|
||||
)
|
||||
table.Bulk(array)
|
||||
table.Render()
|
||||
mlog.Print(buffer.String())
|
||||
return
|
||||
}
|
||||
|
||||
@ -7,9 +7,11 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
@ -20,6 +22,7 @@ import (
|
||||
"github.com/gogf/gf/v2/text/gstr"
|
||||
"github.com/gogf/gf/v2/util/gtag"
|
||||
|
||||
"github.com/gogf/gf/cmd/gf/v2/internal/cmd/geninit"
|
||||
"github.com/gogf/gf/cmd/gf/v2/internal/utility/allyes"
|
||||
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
|
||||
"github.com/gogf/gf/cmd/gf/v2/internal/utility/utils"
|
||||
@ -44,6 +47,12 @@ const (
|
||||
gf init my-project
|
||||
gf init my-mono-repo -m
|
||||
gf init my-mono-repo -a
|
||||
gf init my-project -u
|
||||
gf init my-project -g "github.com/myorg/myproject"
|
||||
gf init -r github.com/gogf/template-single my-project
|
||||
gf init -r github.com/gogf/template-single my-project -s
|
||||
gf init -r github.com/gogf/examples/httpserver/jwt my-jwt
|
||||
gf init -i
|
||||
`
|
||||
cInitNameBrief = `
|
||||
name for the project. It will create a folder with NAME in current directory.
|
||||
@ -55,6 +64,16 @@ The NAME will also be the module name for the project.
|
||||
cInitGitignore = ".gitignore"
|
||||
)
|
||||
|
||||
// defaultTemplates is the list of predefined templates for interactive selection
|
||||
var defaultTemplates = []struct {
|
||||
Name string
|
||||
Repo string
|
||||
Desc string
|
||||
}{
|
||||
{"template-single", "github.com/gogf/template-single", "Single project template"},
|
||||
{"template-mono", "github.com/gogf/template-mono", "Mono-repo project template"},
|
||||
}
|
||||
|
||||
func init() {
|
||||
gtag.Sets(g.MapStrStr{
|
||||
`cInitBrief`: cInitBrief,
|
||||
@ -64,17 +83,86 @@ func init() {
|
||||
}
|
||||
|
||||
type cInitInput struct {
|
||||
g.Meta `name:"init"`
|
||||
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"`
|
||||
MonoApp bool `name:"monoApp" short:"a" brief:"initialize a mono-repo-app instead a single-repo" orphan:"true"`
|
||||
Update bool `name:"update" short:"u" brief:"update to the latest goframe version" orphan:"true"`
|
||||
Module string `name:"module" short:"g" brief:"custom go module"`
|
||||
g.Meta `name:"init"`
|
||||
Name string `name:"NAME" arg:"true" brief:"{cInitNameBrief}"`
|
||||
Mono bool `name:"mono" short:"m" brief:"initialize a mono-repo instead a single-repo" orphan:"true"`
|
||||
MonoApp bool `name:"monoApp" short:"a" brief:"initialize a mono-repo-app instead a single-repo" orphan:"true"`
|
||||
Update bool `name:"update" short:"u" brief:"update to the latest goframe version" orphan:"true"`
|
||||
Module string `name:"module" short:"g" brief:"custom go module"`
|
||||
Repo string `name:"repo" short:"r" brief:"remote repository URL for template download"`
|
||||
SelectVer bool `name:"select" short:"s" brief:"enable interactive version selection for remote template" orphan:"true"`
|
||||
Interactive bool `name:"interactive" short:"i" brief:"enable interactive mode to select template" orphan:"true"`
|
||||
}
|
||||
|
||||
type cInitOutput struct{}
|
||||
|
||||
func (c cInit) Index(ctx context.Context, in cInitInput) (out *cInitOutput, err error) {
|
||||
// Check if using remote template mode
|
||||
if in.Repo != "" || in.Interactive {
|
||||
return c.initFromRemote(ctx, in)
|
||||
}
|
||||
|
||||
// If no name provided and no remote mode, enter interactive mode
|
||||
if in.Name == "" {
|
||||
return c.initInteractive(ctx, in)
|
||||
}
|
||||
|
||||
// Default: use built-in template
|
||||
return c.initFromBuiltin(ctx, in)
|
||||
}
|
||||
|
||||
// initFromRemote initializes project from remote repository
|
||||
func (c cInit) initFromRemote(ctx context.Context, in cInitInput) (out *cInitOutput, err error) {
|
||||
repo := in.Repo
|
||||
name := in.Name
|
||||
|
||||
// If interactive mode and no repo specified, let user select
|
||||
if in.Interactive && repo == "" {
|
||||
var modPath string
|
||||
var upgradeDeps bool
|
||||
repo, name, modPath, upgradeDeps, err = interactiveSelectTemplate()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if modPath != "" {
|
||||
in.Module = modPath
|
||||
}
|
||||
if upgradeDeps {
|
||||
in.Update = true
|
||||
}
|
||||
}
|
||||
|
||||
if repo == "" {
|
||||
return nil, fmt.Errorf("repository URL is required for remote template mode")
|
||||
}
|
||||
|
||||
// Default name to repo basename if empty
|
||||
if name == "" {
|
||||
name = gfile.Basename(repo)
|
||||
mlog.Printf("Using repository basename as project name: %s", name)
|
||||
}
|
||||
|
||||
mlog.Print("initializing from remote template...")
|
||||
|
||||
opts := &geninit.ProcessOptions{
|
||||
SelectVersion: in.SelectVer,
|
||||
ModulePath: in.Module,
|
||||
UpgradeDeps: in.Update,
|
||||
}
|
||||
|
||||
if err = geninit.Process(ctx, repo, name, opts); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
mlog.Print("initialization done!")
|
||||
if name != "" && name != "." {
|
||||
mlog.Printf(`you can now run "cd %s && gf run main.go" to start your journey, enjoy!`, name)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// initFromBuiltin initializes project from built-in template
|
||||
func (c cInit) initFromBuiltin(ctx context.Context, in cInitInput) (out *cInitOutput, err error) {
|
||||
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)
|
||||
@ -180,3 +268,170 @@ func (c cInit) Index(ctx context.Context, in cInitInput) (out *cInitOutput, err
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// initInteractive enters interactive mode when no arguments provided
|
||||
func (c cInit) initInteractive(ctx context.Context, in cInitInput) (out *cInitOutput, err error) {
|
||||
reader := bufio.NewReader(os.Stdin)
|
||||
|
||||
// Ask user which mode to use
|
||||
fmt.Println("\nPlease select initialization mode:")
|
||||
fmt.Println(strings.Repeat("-", 50))
|
||||
fmt.Println(" [1] Built-in template (default)")
|
||||
fmt.Println(" [2] Remote template")
|
||||
fmt.Println(strings.Repeat("-", 50))
|
||||
|
||||
fmt.Print("Select mode [1-2] (default: 1): ")
|
||||
input, err := reader.ReadString('\n')
|
||||
if err != nil {
|
||||
mlog.Fatalf("failed to read input: %v", err)
|
||||
return
|
||||
}
|
||||
input = strings.TrimSpace(input)
|
||||
|
||||
if input == "2" {
|
||||
in.Interactive = true
|
||||
return c.initFromRemote(ctx, in)
|
||||
}
|
||||
|
||||
// Built-in template mode
|
||||
fmt.Println("\nPlease select project type:")
|
||||
fmt.Println(strings.Repeat("-", 50))
|
||||
fmt.Println(" [1] Single project (default)")
|
||||
fmt.Println(" [2] Mono-repo project")
|
||||
fmt.Println(" [3] Mono-repo app")
|
||||
fmt.Println(strings.Repeat("-", 50))
|
||||
|
||||
fmt.Print("Select type [1-3] (default: 1): ")
|
||||
input, err = reader.ReadString('\n')
|
||||
if err != nil {
|
||||
mlog.Fatalf("failed to read input: %v", err)
|
||||
return
|
||||
}
|
||||
input = strings.TrimSpace(input)
|
||||
|
||||
switch input {
|
||||
case "2":
|
||||
in.Mono = true
|
||||
case "3":
|
||||
in.MonoApp = true
|
||||
}
|
||||
|
||||
// Get project name
|
||||
for {
|
||||
fmt.Print("Enter project name: ")
|
||||
input, err = reader.ReadString('\n')
|
||||
if err != nil {
|
||||
mlog.Fatalf("failed to read input: %v", err)
|
||||
return
|
||||
}
|
||||
in.Name = strings.TrimSpace(input)
|
||||
if in.Name != "" {
|
||||
break
|
||||
}
|
||||
fmt.Println("Project name cannot be empty")
|
||||
}
|
||||
|
||||
// Get module path (optional)
|
||||
fmt.Printf("Enter Go module path (leave empty to use \"%s\"): ", in.Name)
|
||||
input, err = reader.ReadString('\n')
|
||||
if err != nil {
|
||||
mlog.Fatalf("failed to read input: %v", err)
|
||||
return
|
||||
}
|
||||
in.Module = strings.TrimSpace(input)
|
||||
|
||||
// Ask about update
|
||||
fmt.Print("Update to latest GoFrame version? [y/N]: ")
|
||||
input, err = reader.ReadString('\n')
|
||||
if err != nil {
|
||||
mlog.Fatalf("failed to read input: %v", err)
|
||||
return
|
||||
}
|
||||
input = strings.TrimSpace(strings.ToLower(input))
|
||||
in.Update = input == "y" || input == "yes"
|
||||
|
||||
fmt.Println()
|
||||
return c.initFromBuiltin(ctx, in)
|
||||
}
|
||||
|
||||
// interactiveSelectTemplate prompts user to select a template interactively
|
||||
func interactiveSelectTemplate() (repo, name, modPath string, upgradeDeps bool, err error) {
|
||||
reader := bufio.NewReader(os.Stdin)
|
||||
|
||||
// 1. Select template
|
||||
fmt.Println("\nPlease select a project template:")
|
||||
fmt.Println(strings.Repeat("-", 50))
|
||||
for i, t := range defaultTemplates {
|
||||
fmt.Printf(" [%d] %s - %s\n", i+1, t.Name, t.Desc)
|
||||
}
|
||||
fmt.Printf(" [%d] Custom repository URL\n", len(defaultTemplates)+1)
|
||||
fmt.Println(strings.Repeat("-", 50))
|
||||
|
||||
for {
|
||||
fmt.Printf("Select template [1-%d]: ", len(defaultTemplates)+1)
|
||||
input, err := reader.ReadString('\n')
|
||||
if err != nil {
|
||||
return "", "", "", false, fmt.Errorf("failed to read template selection: %w", err)
|
||||
}
|
||||
input = strings.TrimSpace(input)
|
||||
|
||||
idx, e := strconv.Atoi(input)
|
||||
if e != nil || idx < 1 || idx > len(defaultTemplates)+1 {
|
||||
fmt.Printf("Invalid selection, please enter a number between 1-%d\n", len(defaultTemplates)+1)
|
||||
continue
|
||||
}
|
||||
|
||||
if idx <= len(defaultTemplates) {
|
||||
repo = defaultTemplates[idx-1].Repo
|
||||
fmt.Printf("Selected: %s\n\n", repo)
|
||||
} else {
|
||||
// Custom URL
|
||||
fmt.Print("Enter repository URL: ")
|
||||
input, err = reader.ReadString('\n')
|
||||
if err != nil {
|
||||
return "", "", "", false, fmt.Errorf("failed to read repository URL: %w", err)
|
||||
}
|
||||
repo = strings.TrimSpace(input)
|
||||
if repo == "" {
|
||||
fmt.Println("Repository URL cannot be empty")
|
||||
continue
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
// 2. Enter project name
|
||||
for {
|
||||
fmt.Print("Enter project name: ")
|
||||
input, err := reader.ReadString('\n')
|
||||
if err != nil {
|
||||
return "", "", "", false, fmt.Errorf("failed to read project name: %w", err)
|
||||
}
|
||||
name = strings.TrimSpace(input)
|
||||
if name == "" {
|
||||
fmt.Println("Project name cannot be empty")
|
||||
continue
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
// 3. Enter module path (optional)
|
||||
fmt.Printf("Enter Go module path (leave empty to use \"%s\"): ", name)
|
||||
input, err := reader.ReadString('\n')
|
||||
if err != nil {
|
||||
return "", "", "", false, fmt.Errorf("failed to read module path: %w", err)
|
||||
}
|
||||
modPath = strings.TrimSpace(input)
|
||||
|
||||
// 4. Ask about upgrade
|
||||
fmt.Print("Upgrade dependencies to latest (go get -u)? [y/N]: ")
|
||||
input, err = reader.ReadString('\n')
|
||||
if err != nil {
|
||||
return "", "", "", false, fmt.Errorf("failed to read upgrade confirmation: %w", err)
|
||||
}
|
||||
input = strings.TrimSpace(strings.ToLower(input))
|
||||
upgradeDeps = input == "y" || input == "yes"
|
||||
|
||||
fmt.Println()
|
||||
return repo, name, modPath, upgradeDeps, nil
|
||||
}
|
||||
|
||||
@ -13,6 +13,7 @@ import (
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gogf/gf/v2/container/gtype"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
@ -26,20 +27,24 @@ import (
|
||||
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
|
||||
)
|
||||
|
||||
var (
|
||||
Run = cRun{}
|
||||
)
|
||||
var Run = cRun{}
|
||||
|
||||
type cRun struct {
|
||||
g.Meta `name:"run" usage:"{cRunUsage}" brief:"{cRunBrief}" eg:"{cRunEg}" dc:"{cRunDc}"`
|
||||
}
|
||||
|
||||
type watchPath struct {
|
||||
Path string
|
||||
Recursive bool
|
||||
}
|
||||
|
||||
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.
|
||||
WatchPaths []string // Watch paths for live reload.
|
||||
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.
|
||||
IgnorePatterns []string // Custom ignore patterns.
|
||||
}
|
||||
|
||||
const (
|
||||
@ -49,45 +54,47 @@ 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"
|
||||
gf run main.go -w internal,api
|
||||
gf run main.go -i ".git,node_modules"
|
||||
`
|
||||
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 "./" 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"`
|
||||
cRunFileBrief = `building file path.`
|
||||
cRunPathBrief = `output directory path for built binary file. it's "./" in default`
|
||||
cRunExtraBrief = `the same options as "go run"/"go build" except some options as follows defined`
|
||||
cRunArgsBrief = `custom arguments for your process`
|
||||
cRunWatchPathsBrief = `watch additional paths for live reload, separated by ",". i.e. "internal,api"`
|
||||
cRunIgnorePatternBrief = `custom ignore patterns for watch, separated by ",". i.e. ".git,node_modules". default patterns: node_modules, vendor, .*, _*. Glob syntax: "*" matches any chars, "?" matches single char, "[abc]" matches char class. Note: patterns match directory names only, not paths`
|
||||
)
|
||||
|
||||
var (
|
||||
process *gproc.Process
|
||||
)
|
||||
var process *gproc.Process
|
||||
|
||||
func init() {
|
||||
gtag.Sets(g.MapStrStr{
|
||||
`cRunUsage`: cRunUsage,
|
||||
`cRunBrief`: cRunBrief,
|
||||
`cRunEg`: cRunEg,
|
||||
`cRunDc`: cRunDc,
|
||||
`cRunFileBrief`: cRunFileBrief,
|
||||
`cRunPathBrief`: cRunPathBrief,
|
||||
`cRunExtraBrief`: cRunExtraBrief,
|
||||
`cRunArgsBrief`: cRunArgsBrief,
|
||||
`cRunWatchPathsBrief`: cRunWatchPathsBrief,
|
||||
`cRunUsage`: cRunUsage,
|
||||
`cRunBrief`: cRunBrief,
|
||||
`cRunEg`: cRunEg,
|
||||
`cRunDc`: cRunDc,
|
||||
`cRunFileBrief`: cRunFileBrief,
|
||||
`cRunPathBrief`: cRunPathBrief,
|
||||
`cRunExtraBrief`: cRunExtraBrief,
|
||||
`cRunArgsBrief`: cRunArgsBrief,
|
||||
`cRunWatchPathsBrief`: cRunWatchPathsBrief,
|
||||
`cRunIgnorePatternBrief`: cRunIgnorePatternBrief,
|
||||
})
|
||||
}
|
||||
|
||||
type (
|
||||
cRunInput struct {
|
||||
g.Meta `name:"run" config:"gfcli.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}"`
|
||||
g.Meta `name:"run" config:"gfcli.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}"`
|
||||
IgnorePatterns []string `name:"ignorePatterns" short:"i" brief:"{cRunIgnorePatternBrief}"`
|
||||
}
|
||||
cRunOutput struct{}
|
||||
)
|
||||
@ -104,22 +111,35 @@ 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], ",")
|
||||
// Parse comma-separated values in WatchPaths
|
||||
if len(in.WatchPaths) > 0 {
|
||||
in.WatchPaths = parseCommaSeparatedArgs(in.WatchPaths)
|
||||
mlog.Printf("watchPaths: %v", in.WatchPaths)
|
||||
}
|
||||
|
||||
// Parse comma-separated values in IgnorePatterns
|
||||
if len(in.IgnorePatterns) > 0 {
|
||||
in.IgnorePatterns = parseCommaSeparatedArgs(in.IgnorePatterns)
|
||||
mlog.Printf("ignorePatterns: %v", in.IgnorePatterns)
|
||||
}
|
||||
|
||||
app := &cRunApp{
|
||||
File: in.File,
|
||||
Path: filepath.FromSlash(in.Path),
|
||||
Options: in.Extra,
|
||||
Args: in.Args,
|
||||
WatchPaths: in.WatchPaths,
|
||||
File: in.File,
|
||||
Path: filepath.FromSlash(in.Path),
|
||||
Options: in.Extra,
|
||||
Args: in.Args,
|
||||
WatchPaths: in.WatchPaths,
|
||||
IgnorePatterns: in.IgnorePatterns,
|
||||
}
|
||||
dirty := gtype.NewBool()
|
||||
|
||||
var outputPath = app.genOutputPath()
|
||||
outputPath := app.genOutputPath()
|
||||
callbackFunc := func(event *gfsnotify.Event) {
|
||||
if !event.IsWrite() && !event.IsCreate() && !event.IsRemove() && !event.IsRename() {
|
||||
return
|
||||
}
|
||||
|
||||
// Check if the file extension is 'go'.
|
||||
if gfile.ExtName(event.Path) != "go" {
|
||||
return
|
||||
}
|
||||
@ -137,15 +157,11 @@ func (c cRun) Index(ctx context.Context, in cRunInput) (out *cRunOutput, err 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)
|
||||
// Get directories to watch (recursive or non-recursive monitoring).
|
||||
watchPaths := app.getWatchPaths()
|
||||
for _, wp := range watchPaths {
|
||||
option := gfsnotify.WatchOption{NoRecursive: !wp.Recursive}
|
||||
_, err = gfsnotify.Add(wp.Path, callbackFunc, option)
|
||||
if err != nil {
|
||||
mlog.Fatal(err)
|
||||
}
|
||||
@ -207,8 +223,37 @@ func (app *cRunApp) End(ctx context.Context, sig os.Signal, outputPath string) {
|
||||
// Delete the binary file.
|
||||
// firstly, kill the process.
|
||||
if process != nil {
|
||||
if err := process.Kill(); err != nil {
|
||||
mlog.Debugf("kill process error: %s", err.Error())
|
||||
if sig != nil && runtime.GOOS != "windows" {
|
||||
if err := process.Signal(sig); err != nil {
|
||||
mlog.Debugf("send signal to process error: %s", err.Error())
|
||||
if err := process.Kill(); err != nil {
|
||||
mlog.Debugf("kill process error: %s", err.Error())
|
||||
}
|
||||
} else {
|
||||
waitCtx, cancel := context.WithTimeout(ctx, 30*time.Second)
|
||||
defer cancel()
|
||||
done := make(chan error, 1)
|
||||
go func() {
|
||||
select {
|
||||
case <-waitCtx.Done():
|
||||
done <- waitCtx.Err()
|
||||
case done <- process.Wait():
|
||||
}
|
||||
}()
|
||||
err := <-done
|
||||
if err != nil {
|
||||
mlog.Debugf("process wait error: %s", err.Error())
|
||||
if err := process.Kill(); err != nil {
|
||||
mlog.Debugf("kill process error: %s", err.Error())
|
||||
}
|
||||
} else {
|
||||
mlog.Debug("process exited gracefully")
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if err := process.Kill(); err != nil {
|
||||
mlog.Debugf("kill process error: %s", err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
if err := gfile.RemoveFile(outputPath); err != nil {
|
||||
@ -219,35 +264,181 @@ func (app *cRunApp) End(ctx context.Context, sig os.Signal, outputPath string) {
|
||||
}
|
||||
|
||||
func (app *cRunApp) genOutputPath() (outputPath string) {
|
||||
var renamePath string
|
||||
outputPath = gfile.Join(app.Path, gfile.Name(app.File))
|
||||
if runtime.GOOS == "windows" {
|
||||
outputPath += ".exe"
|
||||
if gfile.Exists(outputPath) {
|
||||
renamePath = outputPath + "~"
|
||||
renamePath := outputPath + "~"
|
||||
if err := gfile.Rename(outputPath, renamePath); err != nil {
|
||||
mlog.Print(err)
|
||||
}
|
||||
// Clean up the renamed old binary file
|
||||
defer func() {
|
||||
if gfile.Exists(renamePath) {
|
||||
_ = gfile.Remove(renamePath)
|
||||
}
|
||||
}()
|
||||
}
|
||||
}
|
||||
return filepath.FromSlash(outputPath)
|
||||
}
|
||||
|
||||
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())
|
||||
// getWatchPaths uses DFS to find the minimal set of directories to watch.
|
||||
// Rule: if a directory and all its descendants have no ignored subdirectories, watch it;
|
||||
// otherwise, recurse into valid children and watch the current directory non-recursively.
|
||||
func (app *cRunApp) getWatchPaths() []watchPath {
|
||||
roots := []string{"."}
|
||||
if len(app.WatchPaths) > 0 {
|
||||
roots = app.WatchPaths
|
||||
}
|
||||
|
||||
// Use custom ignore patterns if provided, otherwise use default.
|
||||
ignorePatterns := defaultIgnorePatterns
|
||||
if len(app.IgnorePatterns) > 0 {
|
||||
ignorePatterns = app.IgnorePatterns
|
||||
}
|
||||
|
||||
var watchPaths []watchPath
|
||||
|
||||
for _, root := range roots {
|
||||
absRoot := gfile.RealPath(root)
|
||||
if absRoot == "" {
|
||||
mlog.Printf("watch path '%s' not found, skipping", root)
|
||||
continue
|
||||
}
|
||||
matched, err := filepath.Match(absPath, eventPath)
|
||||
if err != nil {
|
||||
mlog.Printf("match watchPath '%s' error: %s", path, err.Error())
|
||||
if isIgnoredDirName(absRoot, ignorePatterns) {
|
||||
continue
|
||||
}
|
||||
if matched {
|
||||
app.collectWatchPaths(absRoot, ignorePatterns, &watchPaths)
|
||||
}
|
||||
|
||||
if len(watchPaths) == 0 {
|
||||
mlog.Printf("no directories to watch, using current directory")
|
||||
if absCur := gfile.RealPath("."); absCur != "" {
|
||||
return []watchPath{{Path: absCur, Recursive: true}}
|
||||
}
|
||||
return []watchPath{{Path: ".", Recursive: true}}
|
||||
}
|
||||
|
||||
mlog.Printf("watching %d paths", len(watchPaths))
|
||||
for _, wp := range watchPaths {
|
||||
recursiveStr := "recursive"
|
||||
if !wp.Recursive {
|
||||
recursiveStr = "non-recursive"
|
||||
}
|
||||
mlog.Debugf(" - %s (%s)", wp.Path, recursiveStr)
|
||||
}
|
||||
return watchPaths
|
||||
}
|
||||
|
||||
// collectWatchPaths performs a DFS traversal to collect the minimal set of directories to watch.
|
||||
// Returns true if the directory or any of its descendants contains ignored directories.
|
||||
// Rule: if a directory has no ignored descendants at any depth, watch it recursively;
|
||||
// otherwise, watch it non-recursively and recurse into valid children.
|
||||
func (app *cRunApp) collectWatchPaths(dir string, ignorePatterns []string, watchPaths *[]watchPath) bool {
|
||||
entries, err := gfile.ScanDir(dir, "*", false)
|
||||
if err != nil {
|
||||
mlog.Printf("scan directory '%s' error: %s", dir, err.Error())
|
||||
// If we can't scan the directory, add it to watch list as fallback
|
||||
*watchPaths = append(*watchPaths, watchPath{Path: dir, Recursive: true})
|
||||
return false
|
||||
}
|
||||
|
||||
// First pass: identify valid subdirectories and check for directly ignored children
|
||||
var validSubDirs []string
|
||||
hasIgnoredChild := false
|
||||
for _, entry := range entries {
|
||||
if !gfile.IsDir(entry) {
|
||||
continue
|
||||
}
|
||||
if isIgnoredDirName(entry, ignorePatterns) {
|
||||
hasIgnoredChild = true
|
||||
} else {
|
||||
validSubDirs = append(validSubDirs, entry)
|
||||
}
|
||||
}
|
||||
|
||||
// If already has ignored child, we know this dir needs non-recursive watch
|
||||
if hasIgnoredChild {
|
||||
*watchPaths = append(*watchPaths, watchPath{Path: dir, Recursive: false})
|
||||
for _, subDir := range validSubDirs {
|
||||
app.collectWatchPaths(subDir, ignorePatterns, watchPaths)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// No ignored children, but need to check descendants recursively
|
||||
// Collect results from all subdirectories first
|
||||
subResults := make([]bool, len(validSubDirs))
|
||||
subWatchPaths := make([][]watchPath, len(validSubDirs))
|
||||
hasIgnoredDescendant := false
|
||||
|
||||
for i, subDir := range validSubDirs {
|
||||
var subPaths []watchPath
|
||||
subResults[i] = app.collectWatchPaths(subDir, ignorePatterns, &subPaths)
|
||||
subWatchPaths[i] = subPaths
|
||||
if subResults[i] {
|
||||
hasIgnoredDescendant = true
|
||||
}
|
||||
}
|
||||
|
||||
if !hasIgnoredDescendant {
|
||||
// No ignored descendants at any depth, watch this directory recursively
|
||||
*watchPaths = append(*watchPaths, watchPath{Path: dir, Recursive: true})
|
||||
return false
|
||||
}
|
||||
|
||||
// Has ignored descendants, watch current directory non-recursively
|
||||
// and add all collected subdirectory watch paths
|
||||
*watchPaths = append(*watchPaths, watchPath{Path: dir, Recursive: false})
|
||||
for _, subPaths := range subWatchPaths {
|
||||
*watchPaths = append(*watchPaths, subPaths...)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// defaultIgnorePatterns contains glob patterns for directory names that should be ignored when watching.
|
||||
// These directories typically contain third-party code or non-source files.
|
||||
// Supported glob syntax (filepath.Match):
|
||||
// - "*" matches any sequence of non-separator characters
|
||||
// - "?" matches any single non-separator character
|
||||
// - "[abc]" matches any character in the bracket
|
||||
// - "[a-z]" matches any character in the range
|
||||
// - "[^abc]" or "[!abc]" matches any character not in the bracket
|
||||
//
|
||||
// Note: patterns match directory base names only, not full paths (no "/" or path separators allowed).
|
||||
var defaultIgnorePatterns = []string{
|
||||
"node_modules",
|
||||
"vendor",
|
||||
".*", // All hidden directories (covers .git, .svn, .hg, .idea, .vscode, etc.)
|
||||
"_*", // Directories starting with underscore
|
||||
}
|
||||
|
||||
// isIgnoredDirName checks if a directory name matches any ignored pattern.
|
||||
// It accepts either a full path or just the directory name, but only matches against the base name.
|
||||
// Note: patterns should not contain "/" as they only match directory names, not paths.
|
||||
func isIgnoredDirName(name string, ignorePatterns []string) bool {
|
||||
baseName := gfile.Basename(name)
|
||||
for _, pattern := range ignorePatterns {
|
||||
if matched, _ := filepath.Match(pattern, baseName); matched {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// parseCommaSeparatedArgs parses command line arguments that may contain comma-separated values.
|
||||
// It handles both single argument with commas (e.g., "a,b,c") and multiple arguments.
|
||||
func parseCommaSeparatedArgs(args []string) []string {
|
||||
var result []string
|
||||
for _, arg := range args {
|
||||
parts := strings.Split(arg, ",")
|
||||
for _, part := range parts {
|
||||
trimmed := strings.TrimSpace(part)
|
||||
if trimmed != "" {
|
||||
result = append(result, trimmed)
|
||||
}
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
@ -15,6 +15,7 @@ import (
|
||||
|
||||
"github.com/gogf/gf/v2/container/gset"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/genv"
|
||||
"github.com/gogf/gf/v2/os/gfile"
|
||||
"github.com/gogf/gf/v2/os/gproc"
|
||||
"github.com/gogf/gf/v2/text/gstr"
|
||||
@ -39,7 +40,11 @@ gf up
|
||||
gf up -a
|
||||
gf up -c
|
||||
gf up -cf
|
||||
gf up -a -m=install
|
||||
gf up -a -m=install -p=github.com/gogf/gf/cmd/gf/v2@latest
|
||||
`
|
||||
cliMethodHttpDownload = "http"
|
||||
cliMethodGoInstall = "install"
|
||||
)
|
||||
|
||||
func init() {
|
||||
@ -49,10 +54,14 @@ func init() {
|
||||
}
|
||||
|
||||
type cUpInput struct {
|
||||
g.Meta `name:"up" config:"gfcli.up"`
|
||||
All bool `name:"all" short:"a" brief:"upgrade both version and cli, auto fix codes" orphan:"true"`
|
||||
Cli bool `name:"cli" short:"c" brief:"also upgrade CLI tool" orphan:"true"`
|
||||
Fix bool `name:"fix" short:"f" brief:"auto fix codes(it only make sense if cli is to be upgraded)" orphan:"true"`
|
||||
g.Meta `name:"up" config:"gfcli.up"`
|
||||
All bool `name:"all" short:"a" brief:"upgrade both version and cli, auto fix codes" orphan:"true"`
|
||||
Cli bool `name:"cli" short:"c" brief:"also upgrade CLI tool" orphan:"true"`
|
||||
Fix bool `name:"fix" short:"f" brief:"auto fix codes(it only make sense if cli is to be upgraded)" orphan:"true"`
|
||||
CliDownloadingMethod string `name:"cli-download-method" short:"m" brief:"cli upgrade method: http=download binary via HTTP GET, install=upgrade via go install" d:"http"`
|
||||
// CliModulePath specifies the module path for CLI installation via go install.
|
||||
// This is used when CliDownloadingMethod is set to "install".
|
||||
CliModulePath string `name:"cli-module-path" short:"p" brief:"custom cli module path for upgrade CLI tool with go install method" d:"github.com/gogf/gf/cmd/gf/v2@latest"`
|
||||
}
|
||||
|
||||
type cUpOutput struct{}
|
||||
@ -76,7 +85,7 @@ func (c cUp) Index(ctx context.Context, in cUpInput) (out *cUpOutput, err error)
|
||||
}
|
||||
|
||||
if in.Cli {
|
||||
if err = c.doUpgradeCLI(ctx); err != nil {
|
||||
if err = c.doUpgradeCLI(ctx, in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
@ -170,8 +179,22 @@ func (c cUp) doUpgradeVersion(ctx context.Context, in cUpInput) (out *doUpgradeV
|
||||
}
|
||||
|
||||
// doUpgradeCLI downloads the new version binary with process.
|
||||
func (c cUp) doUpgradeCLI(ctx context.Context) (err error) {
|
||||
func (c cUp) doUpgradeCLI(ctx context.Context, in cUpInput) (err error) {
|
||||
mlog.Print(`start upgrading cli...`)
|
||||
fmt.Println(` cli upgrade method:`, in.CliDownloadingMethod)
|
||||
switch in.CliDownloadingMethod {
|
||||
case cliMethodHttpDownload:
|
||||
return c.doUpgradeCLIWithHttpDownload(ctx)
|
||||
case cliMethodGoInstall:
|
||||
return c.doUpgradeCLIWithGoInstall(ctx, in)
|
||||
default:
|
||||
mlog.Fatalf(`invalid cli upgrade method: "%s", please use "http" or "install"`, in.CliDownloadingMethod)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (c cUp) doUpgradeCLIWithHttpDownload(ctx context.Context) (err error) {
|
||||
mlog.Print(`start upgrading cli with http get download...`)
|
||||
var (
|
||||
downloadUrl = fmt.Sprintf(
|
||||
`https://github.com/gogf/gf/releases/latest/download/gf_%s_%s`,
|
||||
@ -213,6 +236,41 @@ func (c cUp) doUpgradeCLI(ctx context.Context) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (c cUp) doUpgradeCLIWithGoInstall(ctx context.Context, in cUpInput) (err error) {
|
||||
mlog.Print(`upgrading cli with go install...`)
|
||||
if !genv.Contains("GOPATH") {
|
||||
mlog.Fatal(`"GOPATH" environment variable does not exist, please check your go installation`)
|
||||
}
|
||||
|
||||
command := fmt.Sprintf(`go install %s`, in.CliModulePath)
|
||||
mlog.Printf(`running command: %s`, command)
|
||||
err = gproc.ShellRun(ctx, command)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cliFilePath := gfile.Join(genv.Get("GOPATH").String(), "bin/gf")
|
||||
if runtime.GOOS == "windows" {
|
||||
cliFilePath += ".exe"
|
||||
}
|
||||
|
||||
// It fails if file not exist or its size is less than 1MB.
|
||||
if !gfile.Exists(cliFilePath) || gfile.Size(cliFilePath) < 1024*1024 {
|
||||
mlog.Fatalf(`go install %s failed, "%s" does not exist or its size is less than 1MB`, in.CliModulePath, cliFilePath)
|
||||
}
|
||||
|
||||
newFile, err := gfile.Open(cliFilePath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// selfupdate
|
||||
err = selfupdate.Apply(newFile, selfupdate.Options{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (c cUp) doAutoFixing(ctx context.Context, dirPath string, version string) (err error) {
|
||||
mlog.Printf(`auto fixing directory path "%s" from version "%s" ...`, dirPath, version)
|
||||
command := fmt.Sprintf(`gf fix -p %s`, dirPath)
|
||||
|
||||
@ -104,7 +104,7 @@ func Test_Build_Single_VarMap(t *testing.T) {
|
||||
|
||||
t.Assert(gfile.Exists(binaryPath), false)
|
||||
_, err = f.Index(ctx, cBuildInput{
|
||||
VarMap: map[string]interface{}{
|
||||
VarMap: map[string]any{
|
||||
"a": "1",
|
||||
"b": "2",
|
||||
},
|
||||
|
||||
@ -66,6 +66,7 @@ func Test_Gen_Dao_Issue2572(t *testing.T) {
|
||||
NoJsonTag: false,
|
||||
NoModelComment: false,
|
||||
Clear: false,
|
||||
GenTable: false,
|
||||
TypeMapping: nil,
|
||||
FieldMapping: nil,
|
||||
}
|
||||
@ -155,6 +156,7 @@ func Test_Gen_Dao_Issue2616(t *testing.T) {
|
||||
NoJsonTag: false,
|
||||
NoModelComment: false,
|
||||
Clear: false,
|
||||
GenTable: false,
|
||||
TypeMapping: nil,
|
||||
FieldMapping: nil,
|
||||
}
|
||||
@ -266,6 +268,7 @@ func Test_Gen_Dao_Issue2746(t *testing.T) {
|
||||
NoJsonTag: false,
|
||||
NoModelComment: false,
|
||||
Clear: false,
|
||||
GenTable: false,
|
||||
TypeMapping: nil,
|
||||
FieldMapping: nil,
|
||||
}
|
||||
@ -338,6 +341,7 @@ func Test_Gen_Dao_Issue3459(t *testing.T) {
|
||||
NoJsonTag: false,
|
||||
NoModelComment: false,
|
||||
Clear: false,
|
||||
GenTable: false,
|
||||
TypeMapping: nil,
|
||||
}
|
||||
)
|
||||
@ -378,7 +382,7 @@ func Test_Gen_Dao_Issue3459(t *testing.T) {
|
||||
filepath.FromSlash(testPath + "/model/do/table_user.go"),
|
||||
filepath.FromSlash(testPath + "/model/entity/table_user.go"),
|
||||
}
|
||||
for i, _ := range files {
|
||||
for i := range files {
|
||||
//_ = gfile.PutContents(expectFiles[i], gfile.GetContents(files[i]))
|
||||
t.Assert(gfile.GetContents(files[i]), gfile.GetContents(expectFiles[i]))
|
||||
}
|
||||
@ -450,7 +454,7 @@ func Test_Gen_Dao_Issue3749(t *testing.T) {
|
||||
filepath.FromSlash(testPath + "/model/do/table_user.go"),
|
||||
filepath.FromSlash(testPath + "/model/entity/table_user.go"),
|
||||
}
|
||||
for i, _ := range files {
|
||||
for i := range files {
|
||||
//_ = gfile.PutContents(expectFiles[i], gfile.GetContents(files[i]))
|
||||
t.Assert(gfile.GetContents(files[i]), gfile.GetContents(expectFiles[i]))
|
||||
}
|
||||
|
||||
@ -26,25 +26,34 @@ func Test_Gen_Dao_Sharding(t *testing.T) {
|
||||
tableSingle = "single_table"
|
||||
table1 = "users_0001"
|
||||
table2 = "users_0002"
|
||||
table3 = "users_0003"
|
||||
table3 = "orders_0001"
|
||||
table4 = "orders_0002"
|
||||
sqlFilePath = gtest.DataPath(`gendao`, `sharding`, `sharding.sql`)
|
||||
)
|
||||
dropTableWithDb(db, tableSingle)
|
||||
dropTableWithDb(db, table1)
|
||||
dropTableWithDb(db, table2)
|
||||
dropTableWithDb(db, table3)
|
||||
dropTableWithDb(db, table4)
|
||||
t.AssertNil(execSqlFile(db, sqlFilePath))
|
||||
defer dropTableWithDb(db, tableSingle)
|
||||
defer dropTableWithDb(db, table1)
|
||||
defer dropTableWithDb(db, table2)
|
||||
defer dropTableWithDb(db, table3)
|
||||
defer dropTableWithDb(db, table4)
|
||||
|
||||
var (
|
||||
path = gfile.Temp(guid.S())
|
||||
//path = "/Users/john/Temp/gen_dao_sharding"
|
||||
// path = "/Users/john/Temp/gen_dao_sharding"
|
||||
group = "test"
|
||||
in = gendao.CGenDaoInput{
|
||||
Path: path,
|
||||
Link: link,
|
||||
Group: group,
|
||||
Path: path,
|
||||
Link: link,
|
||||
Group: group,
|
||||
Prefix: "",
|
||||
ShardingPattern: []string{
|
||||
`users_?`,
|
||||
`orders_?`,
|
||||
},
|
||||
}
|
||||
)
|
||||
@ -65,13 +74,16 @@ func Test_Gen_Dao_Sharding(t *testing.T) {
|
||||
|
||||
generatedFiles, err := gfile.ScanDir(path, "*.go", true)
|
||||
t.AssertNil(err)
|
||||
t.Assert(len(generatedFiles), 8)
|
||||
t.Assert(len(generatedFiles), 12)
|
||||
var (
|
||||
daoSingleTableContent = gfile.GetContents(gfile.Join(path, "dao", "single_table.go"))
|
||||
daoUsersContent = gfile.GetContents(gfile.Join(path, "dao", "users.go"))
|
||||
daoOrdersContent = gfile.GetContents(gfile.Join(path, "dao", "orders.go"))
|
||||
)
|
||||
t.Assert(gstr.Contains(daoSingleTableContent, "SingleTable = singleTableDao{internal.NewSingleTableDao()}"), true)
|
||||
t.Assert(gstr.Contains(daoUsersContent, "Users = usersDao{internal.NewUsersDao(userShardingHandler)}"), true)
|
||||
t.Assert(gstr.Contains(daoUsersContent, "Users = usersDao{internal.NewUsersDao(usersShardingHandler)}"), true)
|
||||
t.Assert(gstr.Contains(daoUsersContent, "m.Sharding(gdb.ShardingConfig{"), true)
|
||||
t.Assert(gstr.Contains(daoOrdersContent, "Orders = ordersDao{internal.NewOrdersDao(ordersShardingHandler)}"), true)
|
||||
t.Assert(gstr.Contains(daoOrdersContent, "m.Sharding(gdb.ShardingConfig{"), true)
|
||||
})
|
||||
}
|
||||
|
||||
@ -69,6 +69,7 @@ func Test_Gen_Dao_Default(t *testing.T) {
|
||||
NoJsonTag: false,
|
||||
NoModelComment: false,
|
||||
Clear: false,
|
||||
GenTable: false,
|
||||
TypeMapping: nil,
|
||||
FieldMapping: nil,
|
||||
}
|
||||
@ -107,7 +108,7 @@ func Test_Gen_Dao_Default(t *testing.T) {
|
||||
filepath.FromSlash(testPath + "/model/do/table_user.go"),
|
||||
filepath.FromSlash(testPath + "/model/entity/table_user.go"),
|
||||
}
|
||||
for i, _ := range files {
|
||||
for i := range files {
|
||||
t.Assert(gfile.GetContents(files[i]), gfile.GetContents(expectFiles[i]))
|
||||
}
|
||||
})
|
||||
@ -161,6 +162,7 @@ func Test_Gen_Dao_TypeMapping(t *testing.T) {
|
||||
NoJsonTag: false,
|
||||
NoModelComment: false,
|
||||
Clear: false,
|
||||
GenTable: false,
|
||||
TypeMapping: map[gendao.DBFieldTypeName]gendao.CustomAttributeType{
|
||||
"int": {
|
||||
Type: "int64",
|
||||
@ -208,7 +210,7 @@ func Test_Gen_Dao_TypeMapping(t *testing.T) {
|
||||
filepath.FromSlash(testPath + "/model/do/table_user.go"),
|
||||
filepath.FromSlash(testPath + "/model/entity/table_user.go"),
|
||||
}
|
||||
for i, _ := range files {
|
||||
for i := range files {
|
||||
//_ = gfile.PutContents(expectFiles[i], gfile.GetContents(files[i]))
|
||||
t.Assert(gfile.GetContents(files[i]), gfile.GetContents(expectFiles[i]))
|
||||
}
|
||||
@ -263,6 +265,7 @@ func Test_Gen_Dao_FieldMapping(t *testing.T) {
|
||||
NoJsonTag: false,
|
||||
NoModelComment: false,
|
||||
Clear: false,
|
||||
GenTable: false,
|
||||
TypeMapping: map[gendao.DBFieldTypeName]gendao.CustomAttributeType{
|
||||
"int": {
|
||||
Type: "int64",
|
||||
@ -311,7 +314,7 @@ func Test_Gen_Dao_FieldMapping(t *testing.T) {
|
||||
filepath.FromSlash(testPath + "/model/do/table_user.go"),
|
||||
filepath.FromSlash(testPath + "/model/entity/table_user.go"),
|
||||
}
|
||||
for i, _ := range files {
|
||||
for i := range files {
|
||||
//_ = gfile.PutContents(expectFiles[i], gfile.GetContents(files[i]))
|
||||
t.Assert(gfile.GetContents(files[i]), gfile.GetContents(expectFiles[i]))
|
||||
}
|
||||
@ -403,7 +406,7 @@ func Test_Gen_Dao_Sqlite3(t *testing.T) {
|
||||
filepath.FromSlash(testPath + "/model/do/table_user.go"),
|
||||
filepath.FromSlash(testPath + "/model/entity/table_user.go"),
|
||||
}
|
||||
for i, _ := range files {
|
||||
for i := range files {
|
||||
//_ = gfile.PutContents(expectFiles[i], gfile.GetContents(files[i]))
|
||||
t.Assert(gfile.GetContents(files[i]), gfile.GetContents(expectFiles[i]))
|
||||
}
|
||||
|
||||
@ -55,7 +55,7 @@ func TestGenPbIssue3882(t *testing.T) {
|
||||
func TestGenPbIssue3953(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
var (
|
||||
outputPath = gfile.Temp(guid.S())
|
||||
outputPath = gfile.Temp("f" + guid.S())
|
||||
outputApiPath = filepath.Join(outputPath, "api")
|
||||
outputCtrlPath = filepath.Join(outputPath, "controller")
|
||||
|
||||
|
||||
@ -367,3 +367,145 @@ func Test_Issue_3955(t *testing.T) {
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func Test_Issue_4330_TypeMapping_Ineffective(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
var (
|
||||
err error
|
||||
db = testDB
|
||||
table = "table_user"
|
||||
sqlContent = fmt.Sprintf(
|
||||
gtest.DataContent(`issue`, `3685`, `user.tpl.sql`),
|
||||
table,
|
||||
)
|
||||
)
|
||||
dropTableWithDb(db, table)
|
||||
array := gstr.SplitAndTrim(sqlContent, ";")
|
||||
for _, v := range array {
|
||||
if _, err = db.Exec(ctx, v); err != nil {
|
||||
t.AssertNil(err)
|
||||
}
|
||||
}
|
||||
defer dropTableWithDb(db, table)
|
||||
|
||||
var (
|
||||
path = gfile.Temp(guid.S())
|
||||
in = genpbentity.CGenPbEntityInput{
|
||||
Path: path,
|
||||
Package: "",
|
||||
Link: link,
|
||||
Tables: "",
|
||||
Prefix: "",
|
||||
RemovePrefix: "",
|
||||
RemoveFieldPrefix: "",
|
||||
NameCase: "",
|
||||
JsonCase: "",
|
||||
Option: "",
|
||||
TypeMapping: map[genpbentity.DBFieldTypeName]genpbentity.CustomAttributeType{
|
||||
"json": {
|
||||
Type: "google.protobuf.Value",
|
||||
Import: "google/protobuf/struct.proto",
|
||||
},
|
||||
"decimal": {
|
||||
Type: "double",
|
||||
},
|
||||
},
|
||||
FieldMapping: nil,
|
||||
}
|
||||
)
|
||||
err = gutil.FillStructWithDefault(&in)
|
||||
t.AssertNil(err)
|
||||
|
||||
err = gfile.Mkdir(path)
|
||||
t.AssertNil(err)
|
||||
defer gfile.Remove(path)
|
||||
|
||||
_, err = genpbentity.CGenPbEntity{}.PbEntity(ctx, in)
|
||||
t.AssertNil(err)
|
||||
|
||||
// files
|
||||
files, err := gfile.ScanDir(path, "*.proto", false)
|
||||
t.AssertNil(err)
|
||||
t.Assert(files, []string{
|
||||
path + filepath.FromSlash("/table_user.proto"),
|
||||
})
|
||||
|
||||
// contents
|
||||
testPath := gtest.DataPath("issue", "4330")
|
||||
expectFiles := []string{
|
||||
testPath + filepath.FromSlash("/issue4330_double.proto"),
|
||||
}
|
||||
for i := range files {
|
||||
t.Assert(gfile.GetContents(files[i]), gfile.GetContents(expectFiles[i]))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func Test_Gen_Pbentity_Sharding(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
var (
|
||||
err error
|
||||
db = testDB
|
||||
tableSingle = "single_table"
|
||||
table1 = "users_0001"
|
||||
table2 = "users_0002"
|
||||
table3 = "orders_0001"
|
||||
table4 = "orders_0002"
|
||||
sqlFilePath = gtest.DataPath(`gendao`, `sharding`, `sharding.sql`)
|
||||
)
|
||||
dropTableWithDb(db, tableSingle)
|
||||
dropTableWithDb(db, table1)
|
||||
dropTableWithDb(db, table2)
|
||||
dropTableWithDb(db, table3)
|
||||
dropTableWithDb(db, table4)
|
||||
t.AssertNil(execSqlFile(db, sqlFilePath))
|
||||
defer dropTableWithDb(db, tableSingle)
|
||||
defer dropTableWithDb(db, table1)
|
||||
defer dropTableWithDb(db, table2)
|
||||
defer dropTableWithDb(db, table3)
|
||||
defer dropTableWithDb(db, table4)
|
||||
|
||||
var (
|
||||
path = gfile.Temp(guid.S())
|
||||
in = genpbentity.CGenPbEntityInput{
|
||||
Path: path,
|
||||
Package: "unittest",
|
||||
Link: link,
|
||||
Tables: "",
|
||||
RemovePrefix: "",
|
||||
RemoveFieldPrefix: "",
|
||||
NameCase: "",
|
||||
JsonCase: "",
|
||||
Option: "",
|
||||
TypeMapping: nil,
|
||||
FieldMapping: nil,
|
||||
ShardingPattern: []string{
|
||||
`users_?`,
|
||||
`orders_?`,
|
||||
},
|
||||
}
|
||||
)
|
||||
err = gutil.FillStructWithDefault(&in)
|
||||
t.AssertNil(err)
|
||||
|
||||
err = gfile.Mkdir(path)
|
||||
t.AssertNil(err)
|
||||
defer gfile.Remove(path)
|
||||
|
||||
_, err = genpbentity.CGenPbEntity{}.PbEntity(ctx, in)
|
||||
t.AssertNil(err)
|
||||
|
||||
// files
|
||||
t.AssertNil(err)
|
||||
generatedFiles, err := gfile.ScanDir(path, "*.proto", true)
|
||||
t.Assert(len(generatedFiles), 3)
|
||||
var (
|
||||
msgSingleTableContent = gfile.GetContents(gfile.Join(path, "single_table.proto"))
|
||||
msgUsersContent = gfile.GetContents(gfile.Join(path, "users.proto"))
|
||||
msgOrdersContent = gfile.GetContents(gfile.Join(path, "orders.proto"))
|
||||
)
|
||||
t.Assert(gstr.Contains(msgSingleTableContent, "message SingleTable {"), true)
|
||||
t.Assert(gstr.Contains(msgUsersContent, "message Users {"), true)
|
||||
t.Assert(gstr.Contains(msgOrdersContent, "message Orders {"), true)
|
||||
})
|
||||
}
|
||||
|
||||
336
cmd/gf/internal/cmd/cmd_z_unit_run_test.go
Normal file
336
cmd/gf/internal/cmd/cmd_z_unit_run_test.go
Normal file
@ -0,0 +1,336 @@
|
||||
// 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 (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/gogf/gf/v2/os/gfile"
|
||||
"github.com/gogf/gf/v2/test/gtest"
|
||||
)
|
||||
|
||||
func Test_cRunApp_getWatchPaths_Basic(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
app := &cRunApp{
|
||||
WatchPaths: []string{"."},
|
||||
}
|
||||
watchPaths := app.getWatchPaths()
|
||||
|
||||
t.AssertGT(len(watchPaths), 0)
|
||||
for _, v := range watchPaths {
|
||||
t.Log(v)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func Test_cRunApp_getWatchPaths_EmptyWatchPaths(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
app := &cRunApp{
|
||||
WatchPaths: []string{},
|
||||
}
|
||||
watchPaths := app.getWatchPaths()
|
||||
|
||||
// Should default to current directory "."
|
||||
t.AssertGT(len(watchPaths), 0)
|
||||
})
|
||||
}
|
||||
|
||||
func Test_cRunApp_getWatchPaths_CustomIgnorePattern(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
app := &cRunApp{
|
||||
WatchPaths: []string{"testdata"},
|
||||
IgnorePatterns: []string{"2572"},
|
||||
}
|
||||
watchPaths := app.getWatchPaths()
|
||||
|
||||
// Ensure the "2572" directory is not watched directly.
|
||||
for _, wp := range watchPaths {
|
||||
t.Log("watch path:", wp)
|
||||
t.Assert(strings.HasSuffix(wp.Path, "2572"), false)
|
||||
}
|
||||
t.AssertGT(len(watchPaths), 0)
|
||||
})
|
||||
}
|
||||
|
||||
func Test_cRunApp_getWatchPaths_WithIgnoredDirectories(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
// Create a temporary directory structure for testing
|
||||
tempDir := gfile.Temp("gf_run_test")
|
||||
defer gfile.Remove(tempDir)
|
||||
|
||||
// Create directory structure:
|
||||
// tempDir/
|
||||
// ├── src/
|
||||
// │ ├── api/
|
||||
// │ └── internal/
|
||||
// ├── vendor/ <-- ignored
|
||||
// └── node_modules/ <-- ignored
|
||||
gfile.Mkdir(filepath.Join(tempDir, "src", "api"))
|
||||
gfile.Mkdir(filepath.Join(tempDir, "src", "internal"))
|
||||
gfile.Mkdir(filepath.Join(tempDir, "vendor"))
|
||||
gfile.Mkdir(filepath.Join(tempDir, "node_modules"))
|
||||
|
||||
app := &cRunApp{
|
||||
WatchPaths: []string{tempDir},
|
||||
}
|
||||
watchPaths := app.getWatchPaths()
|
||||
|
||||
// Should watch tempDir non-recursively (to catch top-level files) and src recursively
|
||||
t.Assert(len(watchPaths), 2)
|
||||
// First path is tempDir (non-recursive)
|
||||
t.Assert(watchPaths[0].Path, tempDir)
|
||||
t.Assert(watchPaths[0].Recursive, false)
|
||||
// Second path is src (recursive, since it has no ignored descendants)
|
||||
t.Assert(watchPaths[1].Path, filepath.Join(tempDir, "src"))
|
||||
t.Assert(watchPaths[1].Recursive, true)
|
||||
})
|
||||
}
|
||||
|
||||
func Test_cRunApp_getWatchPaths_NoIgnoredDirectories(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
// Create a temporary directory structure without ignored directories
|
||||
tempDir := gfile.Temp("gf_run_test_no_ignore")
|
||||
defer gfile.Remove(tempDir)
|
||||
|
||||
// Create directory structure without ignored patterns:
|
||||
// tempDir/
|
||||
// ├── src/
|
||||
// │ ├── api/
|
||||
// │ └── internal/
|
||||
gfile.Mkdir(filepath.Join(tempDir, "src", "api"))
|
||||
gfile.Mkdir(filepath.Join(tempDir, "src", "internal"))
|
||||
|
||||
app := &cRunApp{
|
||||
WatchPaths: []string{tempDir},
|
||||
}
|
||||
watchPaths := app.getWatchPaths()
|
||||
|
||||
// Should watch the root directory recursively since no ignored directories exist
|
||||
t.Assert(len(watchPaths), 1)
|
||||
t.Assert(watchPaths[0].Path, tempDir)
|
||||
t.Assert(watchPaths[0].Recursive, true)
|
||||
})
|
||||
}
|
||||
|
||||
func Test_cRunApp_getWatchPaths_CustomIgnorePatterns(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
// Create a temporary directory structure
|
||||
tempDir := gfile.Temp("gf_run_test_custom_ignore")
|
||||
defer gfile.Remove(tempDir)
|
||||
|
||||
// Create directory structure:
|
||||
// tempDir/
|
||||
// ├── src/
|
||||
// │ ├── api/
|
||||
// │ └── internal/
|
||||
// ├── build/ <-- ignored
|
||||
// └── dist/ <-- ignored
|
||||
gfile.Mkdir(filepath.Join(tempDir, "src", "api"))
|
||||
gfile.Mkdir(filepath.Join(tempDir, "src", "internal"))
|
||||
gfile.Mkdir(filepath.Join(tempDir, "build"))
|
||||
gfile.Mkdir(filepath.Join(tempDir, "dist"))
|
||||
|
||||
app := &cRunApp{
|
||||
WatchPaths: []string{tempDir},
|
||||
IgnorePatterns: []string{"build", "dist"},
|
||||
}
|
||||
watchPaths := app.getWatchPaths()
|
||||
|
||||
// Should watch tempDir non-recursively and src recursively
|
||||
t.Assert(len(watchPaths), 2)
|
||||
t.Assert(watchPaths[0].Path, tempDir)
|
||||
t.Assert(watchPaths[0].Recursive, false)
|
||||
t.Assert(watchPaths[1].Path, filepath.Join(tempDir, "src"))
|
||||
t.Assert(watchPaths[1].Recursive, true)
|
||||
})
|
||||
}
|
||||
|
||||
func Test_cRunApp_getWatchPaths_DeepNestedStructure(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
// Create a deep nested directory structure
|
||||
tempDir := gfile.Temp("gf_run_test_deep")
|
||||
defer gfile.Remove(tempDir)
|
||||
|
||||
// Create deep directory structure:
|
||||
// tempDir/
|
||||
// ├── a/
|
||||
// │ ├── b/
|
||||
// │ │ └── c/
|
||||
// │ └── vendor/ <-- ignored
|
||||
// └── d/
|
||||
gfile.Mkdir(filepath.Join(tempDir, "a", "b", "c"))
|
||||
gfile.Mkdir(filepath.Join(tempDir, "a", "vendor"))
|
||||
gfile.Mkdir(filepath.Join(tempDir, "d"))
|
||||
|
||||
app := &cRunApp{
|
||||
WatchPaths: []string{tempDir},
|
||||
}
|
||||
watchPaths := app.getWatchPaths()
|
||||
|
||||
// Should watch individual valid directories due to ignored vendor directory
|
||||
t.AssertGT(len(watchPaths), 0)
|
||||
|
||||
// Verify that vendor directory is not in watch list
|
||||
for _, wp := range watchPaths {
|
||||
t.Assert(strings.Contains(wp.Path, "vendor"), false)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func Test_cRunApp_getWatchPaths_MultipleRoots(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
// Create multiple temporary directories
|
||||
tempDir1 := gfile.Temp("gf_run_test_multi1")
|
||||
tempDir2 := gfile.Temp("gf_run_test_multi2")
|
||||
defer gfile.Remove(tempDir1)
|
||||
defer gfile.Remove(tempDir2)
|
||||
|
||||
gfile.Mkdir(filepath.Join(tempDir1, "src"))
|
||||
gfile.Mkdir(filepath.Join(tempDir2, "api"))
|
||||
|
||||
app := &cRunApp{
|
||||
WatchPaths: []string{tempDir1, tempDir2},
|
||||
}
|
||||
watchPaths := app.getWatchPaths()
|
||||
|
||||
// Should watch both root directories recursively
|
||||
t.Assert(len(watchPaths), 2)
|
||||
|
||||
// Both directories should be in the watch list
|
||||
foundDir1, foundDir2 := false, false
|
||||
for _, wp := range watchPaths {
|
||||
if wp.Path == tempDir1 {
|
||||
foundDir1 = true
|
||||
t.Assert(wp.Recursive, true)
|
||||
}
|
||||
if wp.Path == tempDir2 {
|
||||
foundDir2 = true
|
||||
t.Assert(wp.Recursive, true)
|
||||
}
|
||||
}
|
||||
t.Assert(foundDir1, true)
|
||||
t.Assert(foundDir2, true)
|
||||
})
|
||||
}
|
||||
|
||||
func Test_cRunApp_getWatchPaths_NonExistentDirectory(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
app := &cRunApp{
|
||||
WatchPaths: []string{"/non/existent/path"},
|
||||
}
|
||||
watchPaths := app.getWatchPaths()
|
||||
|
||||
// Should fall back to current directory when no valid paths found
|
||||
t.AssertGT(len(watchPaths), 0)
|
||||
|
||||
// Should contain current directory
|
||||
currentDir, _ := os.Getwd()
|
||||
foundCurrentDir := false
|
||||
for _, wp := range watchPaths {
|
||||
if wp.Path == currentDir {
|
||||
foundCurrentDir = true
|
||||
break
|
||||
}
|
||||
}
|
||||
t.Assert(foundCurrentDir, true)
|
||||
})
|
||||
}
|
||||
|
||||
func Test_isIgnoredDirName(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
// Test default ignore patterns
|
||||
t.Assert(isIgnoredDirName("node_modules", defaultIgnorePatterns), true)
|
||||
t.Assert(isIgnoredDirName("vendor", defaultIgnorePatterns), true)
|
||||
t.Assert(isIgnoredDirName(".git", defaultIgnorePatterns), true)
|
||||
t.Assert(isIgnoredDirName("_private", defaultIgnorePatterns), true)
|
||||
t.Assert(isIgnoredDirName("src", defaultIgnorePatterns), false)
|
||||
t.Assert(isIgnoredDirName("api", defaultIgnorePatterns), false)
|
||||
|
||||
// Test custom ignore patterns
|
||||
customPatterns := []string{"build", "dist", "*.tmp"}
|
||||
t.Assert(isIgnoredDirName("build", customPatterns), true)
|
||||
t.Assert(isIgnoredDirName("dist", customPatterns), true)
|
||||
t.Assert(isIgnoredDirName("test.tmp", customPatterns), true)
|
||||
t.Assert(isIgnoredDirName("src", customPatterns), false)
|
||||
})
|
||||
}
|
||||
|
||||
func Test_cRunApp_getWatchPaths_DeeplyNestedIgnore(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
// Create a temporary directory structure with deeply nested ignored directory
|
||||
tempDir := gfile.Temp("gf_run_test_deeply_nested")
|
||||
defer gfile.Remove(tempDir)
|
||||
|
||||
// Create directory structure:
|
||||
// tempDir/
|
||||
// ├── a/
|
||||
// │ ├── b/
|
||||
// │ │ ├── c/
|
||||
// │ │ │ └── vendor/ <-- deeply nested ignored (4 levels)
|
||||
// │ │ └── d/
|
||||
// │ └── e/
|
||||
// └── f/
|
||||
gfile.Mkdir(filepath.Join(tempDir, "a", "b", "c", "vendor"))
|
||||
gfile.Mkdir(filepath.Join(tempDir, "a", "b", "d"))
|
||||
gfile.Mkdir(filepath.Join(tempDir, "a", "e"))
|
||||
gfile.Mkdir(filepath.Join(tempDir, "f"))
|
||||
|
||||
app := &cRunApp{
|
||||
WatchPaths: []string{tempDir},
|
||||
}
|
||||
watchPaths := app.getWatchPaths()
|
||||
|
||||
// Expected watch paths:
|
||||
// 1. tempDir (non-recursive) - has ignored descendant
|
||||
// 2. a (non-recursive) - has ignored descendant in b/c/vendor
|
||||
// 3. b (non-recursive) - has ignored descendant in c/vendor
|
||||
// 4. c (non-recursive) - has ignored child vendor
|
||||
// 5. d (recursive) - no ignored descendants
|
||||
// 6. e (recursive) - no ignored descendants
|
||||
// 7. f (recursive) - no ignored descendants
|
||||
|
||||
t.AssertGT(len(watchPaths), 0)
|
||||
|
||||
// Verify vendor is not in watch paths
|
||||
for _, wp := range watchPaths {
|
||||
t.Assert(strings.Contains(wp.Path, "vendor"), false)
|
||||
}
|
||||
|
||||
// Find specific paths and verify their recursive flags
|
||||
foundF := false
|
||||
for _, wp := range watchPaths {
|
||||
if wp.Path == filepath.Join(tempDir, "f") {
|
||||
foundF = true
|
||||
t.Assert(wp.Recursive, true) // f should be recursive (no ignored descendants)
|
||||
}
|
||||
}
|
||||
t.Assert(foundF, true)
|
||||
})
|
||||
}
|
||||
|
||||
func Test_cRunApp_getWatchPaths_EmptyDirectory(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
// Create an empty temporary directory
|
||||
tempDir := gfile.Temp("gf_run_test_empty")
|
||||
defer gfile.Remove(tempDir)
|
||||
|
||||
gfile.Mkdir(tempDir)
|
||||
|
||||
app := &cRunApp{
|
||||
WatchPaths: []string{tempDir},
|
||||
}
|
||||
watchPaths := app.getWatchPaths()
|
||||
|
||||
// Empty directory should be watched recursively (no ignored descendants)
|
||||
t.Assert(len(watchPaths), 1)
|
||||
t.Assert(watchPaths[0].Path, tempDir)
|
||||
t.Assert(watchPaths[0].Recursive, true)
|
||||
})
|
||||
}
|
||||
@ -9,13 +9,14 @@ package genctrl
|
||||
import (
|
||||
"context"
|
||||
|
||||
"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/os/gtime"
|
||||
"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 (
|
||||
|
||||
@ -6,7 +6,11 @@
|
||||
|
||||
package genctrl
|
||||
|
||||
import "github.com/gogf/gf/v2/text/gstr"
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/gogf/gf/v2/text/gstr"
|
||||
)
|
||||
|
||||
type apiItem struct {
|
||||
Import string `eg:"demo.com/api/user/v1"`
|
||||
@ -14,6 +18,7 @@ type apiItem struct {
|
||||
Module string `eg:"user"`
|
||||
Version string `eg:"v1"`
|
||||
MethodName string `eg:"GetList"`
|
||||
Comment string `eg:"GetList get list"`
|
||||
}
|
||||
|
||||
func (a apiItem) String() string {
|
||||
@ -21,3 +26,12 @@ func (a apiItem) String() string {
|
||||
a.Import, a.Module, a.Version, a.MethodName,
|
||||
}, ",")
|
||||
}
|
||||
|
||||
// GetComment returns the comment of apiItem.
|
||||
func (a apiItem) GetComment() string {
|
||||
if a.Comment == "" {
|
||||
return ""
|
||||
}
|
||||
// format for handling comments
|
||||
return fmt.Sprintf("\n// %s %s", a.MethodName, a.Comment)
|
||||
}
|
||||
|
||||
@ -17,9 +17,14 @@ import (
|
||||
"github.com/gogf/gf/v2/text/gstr"
|
||||
)
|
||||
|
||||
// getStructsNameInSrc retrieves all struct names
|
||||
type structInfo struct {
|
||||
structName string
|
||||
comment string
|
||||
}
|
||||
|
||||
// getStructsNameInSrc retrieves all struct names and comment
|
||||
// that end in "Req" and have "g.Meta" in their body.
|
||||
func (c CGenCtrl) getStructsNameInSrc(filePath string) (structsName []string, err error) {
|
||||
func (c CGenCtrl) getStructsNameInSrc(filePath string) (structInfos []*structInfo, err error) {
|
||||
var (
|
||||
fileContent = gfile.GetContents(filePath)
|
||||
fileSet = token.NewFileSet()
|
||||
@ -32,8 +37,8 @@ func (c CGenCtrl) getStructsNameInSrc(filePath string) (structsName []string, er
|
||||
|
||||
ast.Inspect(node, func(n ast.Node) bool {
|
||||
if typeSpec, ok := n.(*ast.TypeSpec); ok {
|
||||
methodName := typeSpec.Name.Name
|
||||
if !gstr.HasSuffix(methodName, "Req") {
|
||||
structName := typeSpec.Name.Name
|
||||
if !gstr.HasSuffix(structName, "Req") {
|
||||
// ignore struct name that do not end in "Req"
|
||||
return true
|
||||
}
|
||||
@ -46,7 +51,19 @@ func (c CGenCtrl) getStructsNameInSrc(filePath string) (structsName []string, er
|
||||
if !gstr.Contains(buf.String(), `g.Meta`) {
|
||||
return true
|
||||
}
|
||||
structsName = append(structsName, methodName)
|
||||
|
||||
comment := typeSpec.Doc.Text()
|
||||
// remove the struct name from the comment
|
||||
if gstr.HasPrefix(comment, structName) {
|
||||
comment = gstr.TrimLeftStr(comment, structName, 1)
|
||||
}
|
||||
// remove the comment \n or space
|
||||
comment = gstr.Trim(comment)
|
||||
|
||||
structInfos = append(structInfos, &structInfo{
|
||||
structName: structName,
|
||||
comment: comment,
|
||||
})
|
||||
}
|
||||
}
|
||||
return true
|
||||
|
||||
@ -39,15 +39,16 @@ func (c CGenCtrl) getApiItemsInSrc(apiModuleFolderPath string) (items []apiItem,
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, methodName := range structsInfo {
|
||||
for _, s := range structsInfo {
|
||||
// remove end "Req"
|
||||
methodName = gstr.TrimRightStr(methodName, "Req", 1)
|
||||
methodName := gstr.TrimRightStr(s.structName, "Req", 1)
|
||||
item := apiItem{
|
||||
Import: gstr.Trim(importPath, `"`),
|
||||
FileName: gfile.Name(apiFileFolderPath),
|
||||
Module: gfile.Basename(apiModuleFolderPath),
|
||||
Version: gfile.Basename(apiVersionFolderPath),
|
||||
MethodName: methodName,
|
||||
Comment: s.comment,
|
||||
}
|
||||
items = append(items, item)
|
||||
}
|
||||
|
||||
@ -138,10 +138,11 @@ func (c *controllerGenerator) doGenerateCtrlItem(dstModuleFolderPath string, ite
|
||||
|
||||
if gfile.Exists(methodFilePath) {
|
||||
content = gstr.ReplaceByMap(consts.TemplateGenCtrlControllerMethodFuncMerge, g.MapStrStr{
|
||||
"{Module}": item.Module,
|
||||
"{CtrlName}": ctrlName,
|
||||
"{Version}": item.Version,
|
||||
"{MethodName}": item.MethodName,
|
||||
"{Module}": item.Module,
|
||||
"{CtrlName}": ctrlName,
|
||||
"{Version}": item.Version,
|
||||
"{MethodName}": item.MethodName,
|
||||
"{MethodComment}": item.GetComment(),
|
||||
})
|
||||
|
||||
if gstr.Contains(gfile.GetContents(methodFilePath), fmt.Sprintf(`func (c *%v) %v(`, ctrlName, item.MethodName)) {
|
||||
@ -152,11 +153,12 @@ func (c *controllerGenerator) doGenerateCtrlItem(dstModuleFolderPath string, ite
|
||||
}
|
||||
} else {
|
||||
content = gstr.ReplaceByMap(consts.TemplateGenCtrlControllerMethodFunc, g.MapStrStr{
|
||||
"{Module}": item.Module,
|
||||
"{ImportPath}": item.Import,
|
||||
"{CtrlName}": ctrlName,
|
||||
"{Version}": item.Version,
|
||||
"{MethodName}": item.MethodName,
|
||||
"{Module}": item.Module,
|
||||
"{ImportPath}": item.Import,
|
||||
"{CtrlName}": ctrlName,
|
||||
"{Version}": item.Version,
|
||||
"{MethodName}": item.MethodName,
|
||||
"{MethodComment}": item.GetComment(),
|
||||
})
|
||||
if err = gfile.PutContents(methodFilePath, gstr.TrimLeft(content)); err != nil {
|
||||
return err
|
||||
@ -192,10 +194,11 @@ func (c *controllerGenerator) doGenerateCtrlMergeItem(dstModuleFolderPath string
|
||||
}
|
||||
|
||||
ctrl := gstr.TrimLeft(gstr.ReplaceByMap(consts.TemplateGenCtrlControllerMethodFuncMerge, g.MapStrStr{
|
||||
"{Module}": api.Module,
|
||||
"{CtrlName}": fmt.Sprintf(`Controller%s`, gstr.UcFirst(api.Version)),
|
||||
"{Version}": api.Version,
|
||||
"{MethodName}": api.MethodName,
|
||||
"{Module}": api.Module,
|
||||
"{CtrlName}": fmt.Sprintf(`Controller%s`, gstr.UcFirst(api.Version)),
|
||||
"{Version}": api.Version,
|
||||
"{MethodName}": api.MethodName,
|
||||
"{MethodComment}": api.GetComment(),
|
||||
}))
|
||||
ctrlFileItem.controllers.WriteString(ctrl)
|
||||
doneApiSet.Add(api.String())
|
||||
|
||||
@ -180,6 +180,7 @@ func (c *apiSdkGenerator) doGenerateSdkImplementer(
|
||||
"{Version}": item.Version,
|
||||
"{MethodName}": item.MethodName,
|
||||
"{ImplementerName}": implementerName,
|
||||
"{MethodComment}": item.GetComment(),
|
||||
}))
|
||||
implementerFileContent += "\n"
|
||||
}
|
||||
|
||||
BIN
cmd/gf/internal/cmd/gendao.zip
Normal file
BIN
cmd/gf/internal/cmd/gendao.zip
Normal file
Binary file not shown.
@ -11,6 +11,9 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/olekukonko/tablewriter"
|
||||
"github.com/olekukonko/tablewriter/renderer"
|
||||
"github.com/olekukonko/tablewriter/tw"
|
||||
"golang.org/x/mod/modfile"
|
||||
|
||||
"github.com/gogf/gf/v2/container/garray"
|
||||
@ -36,7 +39,7 @@ type (
|
||||
Link string `name:"link" short:"l" brief:"{CGenDaoBriefLink}"`
|
||||
Tables string `name:"tables" short:"t" brief:"{CGenDaoBriefTables}"`
|
||||
TablesEx string `name:"tablesEx" short:"x" brief:"{CGenDaoBriefTablesEx}"`
|
||||
ShardingPattern []string `name:"ShardingPattern" short:"sp" brief:"{CGenDaoBriefShardingPattern}"`
|
||||
ShardingPattern []string `name:"shardingPattern" short:"sp" brief:"{CGenDaoBriefShardingPattern}"`
|
||||
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}"`
|
||||
@ -44,8 +47,10 @@ type (
|
||||
JsonCase string `name:"jsonCase" short:"j" brief:"{CGenDaoBriefJsonCase}" d:"CamelLower"`
|
||||
ImportPrefix string `name:"importPrefix" short:"i" brief:"{CGenDaoBriefImportPrefix}"`
|
||||
DaoPath string `name:"daoPath" short:"d" brief:"{CGenDaoBriefDaoPath}" d:"dao"`
|
||||
TablePath string `name:"tablePath" short:"tp" brief:"{CGenDaoBriefTablePath}" d:"table"`
|
||||
DoPath string `name:"doPath" short:"o" brief:"{CGenDaoBriefDoPath}" d:"model/do"`
|
||||
EntityPath string `name:"entityPath" short:"e" brief:"{CGenDaoBriefEntityPath}" d:"model/entity"`
|
||||
TplDaoTablePath string `name:"tplDaoTablePath" short:"t0" brief:"{CGenDaoBriefTplDaoTablePath}"`
|
||||
TplDaoIndexPath string `name:"tplDaoIndexPath" short:"t1" brief:"{CGenDaoBriefTplDaoIndexPath}"`
|
||||
TplDaoInternalPath string `name:"tplDaoInternalPath" short:"t2" brief:"{CGenDaoBriefTplDaoInternalPath}"`
|
||||
TplDaoDoPath string `name:"tplDaoDoPath" short:"t3" brief:"{CGenDaoBriefTplDaoDoPathPath}"`
|
||||
@ -58,6 +63,7 @@ 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"`
|
||||
GenTable bool `name:"genTable" short:"gt" brief:"{CGenDaoBriefGenTable}" orphan:"true"`
|
||||
|
||||
TypeMapping map[DBFieldTypeName]CustomAttributeType `name:"typeMapping" short:"y" brief:"{CGenDaoBriefTypeMapping}" orphan:"true"`
|
||||
FieldMapping map[DBTableFieldName]CustomAttributeType `name:"fieldMapping" short:"fm" brief:"{CGenDaoBriefFieldMapping}" orphan:"true"`
|
||||
@ -98,7 +104,25 @@ var (
|
||||
"smallmoney": {
|
||||
Type: "float64",
|
||||
},
|
||||
"uuid": {
|
||||
Type: "uuid.UUID",
|
||||
Import: "github.com/google/uuid",
|
||||
},
|
||||
}
|
||||
|
||||
// tablewriter Options
|
||||
twRenderer = tablewriter.WithRenderer(renderer.NewBlueprint(tw.Rendition{
|
||||
Borders: tw.Border{Top: tw.Off, Bottom: tw.Off, Left: tw.Off, Right: tw.Off},
|
||||
Settings: tw.Settings{
|
||||
Separators: tw.Separators{BetweenRows: tw.Off, BetweenColumns: tw.Off},
|
||||
},
|
||||
Symbols: tw.NewSymbols(tw.StyleASCII),
|
||||
}))
|
||||
twConfig = tablewriter.WithConfig(tablewriter.Config{
|
||||
Row: tw.CellConfig{
|
||||
Formatting: tw.CellFormatting{AutoWrap: tw.WrapNone},
|
||||
},
|
||||
})
|
||||
)
|
||||
|
||||
func (c CGenDao) Dao(ctx context.Context, in CGenDaoInput) (out *CGenDaoOutput, err error) {
|
||||
@ -173,8 +197,29 @@ func doGenDaoForArray(ctx context.Context, index int, in CGenDaoInput) {
|
||||
// Table excluding.
|
||||
if in.TablesEx != "" {
|
||||
array := garray.NewStrArrayFrom(tableNames)
|
||||
for _, v := range gstr.SplitAndTrim(in.TablesEx, ",") {
|
||||
array.RemoveValue(v)
|
||||
for _, p := range gstr.SplitAndTrim(in.TablesEx, ",") {
|
||||
if gstr.Contains(p, "*") || gstr.Contains(p, "?") {
|
||||
p = gstr.ReplaceByMap(p, map[string]string{
|
||||
"\r": "",
|
||||
"\n": "",
|
||||
})
|
||||
p = gstr.ReplaceByMap(p, map[string]string{
|
||||
"*": "\r",
|
||||
"?": "\n",
|
||||
})
|
||||
p = gregex.Quote(p)
|
||||
p = gstr.ReplaceByMap(p, map[string]string{
|
||||
"\r": ".*",
|
||||
"\n": ".",
|
||||
})
|
||||
for _, v := range array.Clone().Slice() {
|
||||
if gregex.IsMatchString(p, v) {
|
||||
array.RemoveValue(v)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
array.RemoveValue(p)
|
||||
}
|
||||
}
|
||||
tableNames = array.Slice()
|
||||
}
|
||||
@ -219,14 +264,18 @@ func doGenDaoForArray(ctx context.Context, index int, in CGenDaoInput) {
|
||||
tableNames[i] = ""
|
||||
continue
|
||||
}
|
||||
shardingNewTableSet.Add(newTableName)
|
||||
// Add prefix to sharding table name, if not, the isSharding check would not match.
|
||||
shardingNewTableSet.Add(in.Prefix + newTableName)
|
||||
}
|
||||
}
|
||||
newTableName = in.Prefix + newTableName
|
||||
newTableNames[i] = newTableName
|
||||
if tableNames[i] != "" {
|
||||
// If shardingNewTableSet contains newTableName (tableName is empty), it should not be added to tableNames, make it empty and filter later.
|
||||
newTableNames[i] = newTableName
|
||||
}
|
||||
}
|
||||
tableNames = garray.NewStrArrayFrom(tableNames).FilterEmpty().Slice()
|
||||
|
||||
newTableNames = garray.NewStrArrayFrom(newTableNames).FilterEmpty().Slice() // Filter empty table names. make sure that newTableNames and tableNames have the same length.
|
||||
in.genItems.Scale()
|
||||
|
||||
// Dao: index and internal.
|
||||
@ -237,6 +286,14 @@ func doGenDaoForArray(ctx context.Context, index int, in CGenDaoInput) {
|
||||
NewTableNames: newTableNames,
|
||||
ShardingTableSet: shardingNewTableSet,
|
||||
})
|
||||
// Table: table fields.
|
||||
generateTable(ctx, CGenDaoInternalInput{
|
||||
CGenDaoInput: in,
|
||||
DB: db,
|
||||
TableNames: tableNames,
|
||||
NewTableNames: newTableNames,
|
||||
ShardingTableSet: shardingNewTableSet,
|
||||
})
|
||||
// Do.
|
||||
generateDo(ctx, CGenDaoInternalInput{
|
||||
CGenDaoInput: in,
|
||||
|
||||
@ -127,6 +127,7 @@ func generateDaoIndex(in generateDaoIndexInput) {
|
||||
tplView.ClearAssigns()
|
||||
tplView.Assigns(gview.Params{
|
||||
tplVarTableSharding: in.IsSharding,
|
||||
tplVarTableShardingPrefix: in.NewTableName + "_",
|
||||
tplVarImportPrefix: in.ImportPrefix,
|
||||
tplVarTableName: in.TableName,
|
||||
tplVarTableNameCamelCase: in.TableNameCamelCase,
|
||||
@ -210,13 +211,9 @@ func generateColumnNamesForDao(fieldMap map[string]*gdb.TableField, removeFieldP
|
||||
fmt.Sprintf(` #"%s",`, field.Name),
|
||||
}
|
||||
}
|
||||
tw := tablewriter.NewWriter(buffer)
|
||||
tw.SetBorder(false)
|
||||
tw.SetRowLine(false)
|
||||
tw.SetAutoWrapText(false)
|
||||
tw.SetColumnSeparator("")
|
||||
tw.AppendBulk(array)
|
||||
tw.Render()
|
||||
table := tablewriter.NewTable(buffer, twRenderer, twConfig)
|
||||
table.Bulk(array)
|
||||
table.Render()
|
||||
namesContent := buffer.String()
|
||||
// Let's do this hack of table writer for indent!
|
||||
namesContent = gstr.Replace(namesContent, " #", "")
|
||||
@ -251,13 +248,9 @@ func generateColumnDefinitionForDao(fieldMap map[string]*gdb.TableField, removeF
|
||||
" #" + fmt.Sprintf(`// %s`, comment),
|
||||
}
|
||||
}
|
||||
tw := tablewriter.NewWriter(buffer)
|
||||
tw.SetBorder(false)
|
||||
tw.SetRowLine(false)
|
||||
tw.SetAutoWrapText(false)
|
||||
tw.SetColumnSeparator("")
|
||||
tw.AppendBulk(array)
|
||||
tw.Render()
|
||||
table := tablewriter.NewTable(buffer, twRenderer, twConfig)
|
||||
table.Bulk(array)
|
||||
table.Render()
|
||||
defineContent := buffer.String()
|
||||
// Let's do this hack of table writer for indent!
|
||||
defineContent = gstr.Replace(defineContent, " #", "")
|
||||
|
||||
@ -45,14 +45,14 @@ func generateDo(ctx context.Context, in CGenDaoInternalInput) {
|
||||
IsDo: true,
|
||||
})
|
||||
)
|
||||
// replace all types to interface{}.
|
||||
// replace all types to any.
|
||||
structDefinition, _ = gregex.ReplaceStringFuncMatch(
|
||||
"([A-Z]\\w*?)\\s+([\\w\\*\\.]+?)\\s+(//)",
|
||||
structDefinition,
|
||||
func(match []string) string {
|
||||
// If the type is already a pointer/slice/map, it does nothing.
|
||||
if !gstr.HasPrefix(match[2], "*") && !gstr.HasPrefix(match[2], "[]") && !gstr.HasPrefix(match[2], "map") {
|
||||
return fmt.Sprintf(`%s interface{} %s`, match[1], match[3])
|
||||
return fmt.Sprintf(`%s any %s`, match[1], match[3])
|
||||
}
|
||||
return match[0]
|
||||
},
|
||||
|
||||
@ -41,28 +41,55 @@ func generateStructDefinition(ctx context.Context, in generateStructDefinitionIn
|
||||
appendImports = append(appendImports, imports)
|
||||
}
|
||||
}
|
||||
tw := tablewriter.NewWriter(buffer)
|
||||
tw.SetBorder(false)
|
||||
tw.SetRowLine(false)
|
||||
tw.SetAutoWrapText(false)
|
||||
tw.SetColumnSeparator("")
|
||||
tw.AppendBulk(array)
|
||||
tw.Render()
|
||||
table := tablewriter.NewTable(buffer, twRenderer, twConfig)
|
||||
table.Bulk(array)
|
||||
table.Render()
|
||||
stContent := buffer.String()
|
||||
// Let's do this hack of table writer for indent!
|
||||
stContent = gstr.Replace(stContent, " #", "")
|
||||
stContent = gstr.Replace(stContent, "` ", "`")
|
||||
stContent = gstr.Replace(stContent, "``", "")
|
||||
buffer.Reset()
|
||||
buffer.WriteString(fmt.Sprintf("type %s struct {\n", in.StructName))
|
||||
fmt.Fprintf(buffer, "type %s struct {\n", in.StructName)
|
||||
if in.IsDo {
|
||||
buffer.WriteString(fmt.Sprintf("g.Meta `orm:\"table:%s, do:true\"`\n", in.TableName))
|
||||
fmt.Fprintf(buffer, "g.Meta `orm:\"table:%s, do:true\"`\n", in.TableName)
|
||||
}
|
||||
buffer.WriteString(stContent)
|
||||
buffer.WriteString("}")
|
||||
return buffer.String(), appendImports
|
||||
}
|
||||
|
||||
func getTypeMappingInfo(
|
||||
ctx context.Context, fieldType string, inTypeMapping map[DBFieldTypeName]CustomAttributeType,
|
||||
) (typeNameStr, importStr string) {
|
||||
if typeMapping, ok := inTypeMapping[strings.ToLower(fieldType)]; ok {
|
||||
typeNameStr = typeMapping.Type
|
||||
importStr = typeMapping.Import
|
||||
return
|
||||
}
|
||||
tryTypeMatch, _ := gregex.MatchString(`(.+?)\(([^\(\)]+)\)([\s\)]*)`, fieldType)
|
||||
var (
|
||||
tryTypeName string
|
||||
moreTry bool
|
||||
)
|
||||
if len(tryTypeMatch) == 4 {
|
||||
tryTypeMatch3, _ := gregex.ReplaceString(`\s+`, "", tryTypeMatch[3])
|
||||
tryTypeName = gstr.Trim(tryTypeMatch[1]) + tryTypeMatch3
|
||||
moreTry = tryTypeMatch3 != ""
|
||||
} else {
|
||||
tryTypeName = gstr.Split(fieldType, " ")[0]
|
||||
}
|
||||
if tryTypeName != "" {
|
||||
if typeMapping, ok := inTypeMapping[strings.ToLower(tryTypeName)]; ok {
|
||||
typeNameStr = typeMapping.Type
|
||||
importStr = typeMapping.Import
|
||||
} else if moreTry {
|
||||
typeNameStr, importStr = getTypeMappingInfo(ctx, tryTypeName, inTypeMapping)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// generateStructFieldDefinition generates and returns the attribute definition for specified field.
|
||||
func generateStructFieldDefinition(
|
||||
ctx context.Context, field *gdb.TableField, in generateStructDefinitionInput,
|
||||
@ -71,25 +98,10 @@ func generateStructFieldDefinition(
|
||||
err error
|
||||
localTypeName gdb.LocalType
|
||||
localTypeNameStr string
|
||||
jsonTag = gstr.CaseConvert(field.Name, gstr.CaseTypeMatch(in.JsonCase))
|
||||
)
|
||||
|
||||
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 {
|
||||
tryTypeName = gstr.Split(field.Type, " ")[0]
|
||||
}
|
||||
if tryTypeName != "" {
|
||||
if typeMapping, ok := in.TypeMapping[strings.ToLower(tryTypeName)]; ok {
|
||||
localTypeNameStr = typeMapping.Type
|
||||
appendImport = typeMapping.Import
|
||||
}
|
||||
}
|
||||
localTypeNameStr, appendImport = getTypeMappingInfo(ctx, field.Type, in.TypeMapping)
|
||||
}
|
||||
|
||||
if localTypeNameStr == "" {
|
||||
@ -143,6 +155,8 @@ func generateStructFieldDefinition(
|
||||
" #" + formatFieldName(newFiledName, FieldNameCaseCamel),
|
||||
" #" + localTypeNameStr,
|
||||
}
|
||||
|
||||
jsonTag := gstr.CaseConvert(newFiledName, gstr.CaseTypeMatch(in.JsonCase))
|
||||
attrLines = append(attrLines, fmt.Sprintf(` #%sjson:"%s"`, tagKey, jsonTag))
|
||||
// orm tag
|
||||
if !in.IsDo {
|
||||
|
||||
147
cmd/gf/internal/cmd/gendao/gendao_table.go
Normal file
147
cmd/gf/internal/cmd/gendao/gendao_table.go
Normal file
@ -0,0 +1,147 @@
|
||||
// Copyright GoFrame gf Author(https://goframe.org). All Rights Reserved.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the MIT License.
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
// You can obtain one at https://github.com/gogf/gf.
|
||||
|
||||
package gendao
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/gogf/gf/v2/database/gdb"
|
||||
"github.com/gogf/gf/v2/os/gfile"
|
||||
"github.com/gogf/gf/v2/os/gview"
|
||||
"github.com/gogf/gf/v2/text/gstr"
|
||||
"github.com/gogf/gf/v2/util/gconv"
|
||||
|
||||
"github.com/gogf/gf/cmd/gf/v2/internal/consts"
|
||||
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
|
||||
"github.com/gogf/gf/cmd/gf/v2/internal/utility/utils"
|
||||
)
|
||||
|
||||
// generateTable generates dao files for given tables.
|
||||
func generateTable(ctx context.Context, in CGenDaoInternalInput) {
|
||||
dirPathTable := gfile.Join(in.Path, in.TablePath)
|
||||
if !in.GenTable {
|
||||
if gfile.Exists(dirPathTable) {
|
||||
in.genItems.AppendDirPath(dirPathTable)
|
||||
}
|
||||
return
|
||||
}
|
||||
in.genItems.AppendDirPath(dirPathTable)
|
||||
for i := 0; i < len(in.TableNames); i++ {
|
||||
var (
|
||||
realTableName = in.TableNames[i]
|
||||
newTableName = in.NewTableNames[i]
|
||||
)
|
||||
generateTableSingle(ctx, generateTableSingleInput{
|
||||
CGenDaoInternalInput: in,
|
||||
TableName: realTableName,
|
||||
NewTableName: newTableName,
|
||||
DirPathTable: dirPathTable,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// generateTableSingleInput is the input parameter for generateTableSingle.
|
||||
type generateTableSingleInput struct {
|
||||
CGenDaoInternalInput
|
||||
// TableName specifies the table name of the table.
|
||||
TableName string
|
||||
// NewTableName specifies the prefix-stripped or custom edited name of the table.
|
||||
NewTableName string
|
||||
DirPathTable string
|
||||
}
|
||||
|
||||
// generateTableSingle generates dao files for a single table.
|
||||
func generateTableSingle(ctx context.Context, in generateTableSingleInput) {
|
||||
// Generating table data preparing.
|
||||
fieldMap, err := in.DB.TableFields(ctx, in.TableName)
|
||||
if err != nil {
|
||||
mlog.Fatalf(`fetching tables fields failed for table "%s": %+v`, in.TableName, err)
|
||||
}
|
||||
|
||||
tableNameSnakeCase := gstr.CaseSnake(in.NewTableName)
|
||||
fileName := gstr.Trim(tableNameSnakeCase, "-_.")
|
||||
if len(fileName) > 5 && fileName[len(fileName)-5:] == "_test" {
|
||||
// Add suffix to avoid the table name which contains "_test",
|
||||
// which would make the go file a testing file.
|
||||
fileName += "_table"
|
||||
}
|
||||
path := filepath.FromSlash(gfile.Join(in.DirPathTable, fileName+".go"))
|
||||
in.genItems.AppendGeneratedFilePath(path)
|
||||
if in.OverwriteDao || !gfile.Exists(path) {
|
||||
var (
|
||||
ctx = context.Background()
|
||||
tplContent = getTemplateFromPathOrDefault(
|
||||
in.TplDaoTablePath, consts.TemplateGenTableContent,
|
||||
)
|
||||
)
|
||||
tplView.ClearAssigns()
|
||||
tplView.Assigns(gview.Params{
|
||||
tplVarGroupName: in.Group,
|
||||
tplVarTableName: in.TableName,
|
||||
tplVarTableNameCamelCase: formatFieldName(in.NewTableName, FieldNameCaseCamel),
|
||||
tplVarPackageName: filepath.Base(in.TablePath),
|
||||
tplVarTableFields: generateTableFields(fieldMap),
|
||||
})
|
||||
indexContent, err := tplView.ParseContent(ctx, tplContent)
|
||||
if err != nil {
|
||||
mlog.Fatalf("parsing template content failed: %v", err)
|
||||
}
|
||||
if err = gfile.PutContents(path, strings.TrimSpace(indexContent)); err != nil {
|
||||
mlog.Fatalf("writing content to '%s' failed: %v", path, err)
|
||||
} else {
|
||||
utils.GoFmt(path)
|
||||
mlog.Print("generated:", gfile.RealPath(path))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// generateTableFields generates and returns the field definition content for specified table.
|
||||
func generateTableFields(fields map[string]*gdb.TableField) string {
|
||||
var buf bytes.Buffer
|
||||
fieldNames := make([]string, 0, len(fields))
|
||||
for fieldName := range fields {
|
||||
fieldNames = append(fieldNames, fieldName)
|
||||
}
|
||||
sort.Slice(fieldNames, func(i, j int) bool {
|
||||
return fields[fieldNames[i]].Index < fields[fieldNames[j]].Index // asc
|
||||
})
|
||||
for index, fieldName := range fieldNames {
|
||||
field := fields[fieldName]
|
||||
buf.WriteString(" " + strconv.Quote(field.Name) + ": {\n")
|
||||
buf.WriteString(" Index: " + gconv.String(field.Index) + ",\n")
|
||||
buf.WriteString(" Name: " + strconv.Quote(field.Name) + ",\n")
|
||||
buf.WriteString(" Type: " + strconv.Quote(field.Type) + ",\n")
|
||||
buf.WriteString(" Null: " + gconv.String(field.Null) + ",\n")
|
||||
buf.WriteString(" Key: " + strconv.Quote(field.Key) + ",\n")
|
||||
buf.WriteString(" Default: " + generateDefaultValue(field.Default) + ",\n")
|
||||
buf.WriteString(" Extra: " + strconv.Quote(field.Extra) + ",\n")
|
||||
buf.WriteString(" Comment: " + strconv.Quote(field.Comment) + ",\n")
|
||||
buf.WriteString(" },")
|
||||
if index != len(fieldNames)-1 {
|
||||
buf.WriteString("\n")
|
||||
}
|
||||
}
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
// generateDefaultValue generates and returns the default value definition for specified field.
|
||||
func generateDefaultValue(value interface{}) string {
|
||||
if value == nil {
|
||||
return "nil"
|
||||
}
|
||||
switch v := value.(type) {
|
||||
case string:
|
||||
return strconv.Quote(v)
|
||||
default:
|
||||
return gconv.String(v)
|
||||
}
|
||||
}
|
||||
@ -60,6 +60,7 @@ CONFIGURATION SUPPORT
|
||||
CGenDaoBriefGJsonSupport = `use gJsonSupport to use *gjson.Json instead of string for generated json fields of tables`
|
||||
CGenDaoBriefImportPrefix = `custom import prefix for generated go files`
|
||||
CGenDaoBriefDaoPath = `directory path for storing generated dao files under path`
|
||||
CGenDaoBriefTablePath = `directory path for storing generated table files under path`
|
||||
CGenDaoBriefDoPath = `directory path for storing generated do files under path`
|
||||
CGenDaoBriefEntityPath = `directory path for storing generated entity files under path`
|
||||
CGenDaoBriefOverwriteDao = `overwrite all dao files both inside/outside internal folder`
|
||||
@ -69,6 +70,7 @@ CONFIGURATION SUPPORT
|
||||
CGenDaoBriefNoJsonTag = `no json tag will be added for each field`
|
||||
CGenDaoBriefNoModelComment = `no model comment will be added for each field`
|
||||
CGenDaoBriefClear = `delete all generated go files that do not exist in database`
|
||||
CGenDaoBriefGenTable = `generate table files`
|
||||
CGenDaoBriefTypeMapping = `custom local type mapping for generated struct attributes relevant to fields of table`
|
||||
CGenDaoBriefFieldMapping = `custom local type mapping for generated struct attributes relevant to specific fields of table`
|
||||
CGenDaoBriefShardingPattern = `sharding pattern for table name, e.g. "users_?" will be replace tables "users_001,users_002,..." to "users" dao`
|
||||
@ -97,6 +99,8 @@ generated json tag case for model struct, cases are as follows:
|
||||
tplVarTableNameCamelCase = `TplTableNameCamelCase`
|
||||
tplVarTableNameCamelLowerCase = `TplTableNameCamelLowerCase`
|
||||
tplVarTableSharding = `TplTableSharding`
|
||||
tplVarTableShardingPrefix = `TplTableShardingPrefix`
|
||||
tplVarTableFields = `TplTableFields`
|
||||
tplVarPackageImports = `TplPackageImports`
|
||||
tplVarImportPrefix = `TplImportPrefix`
|
||||
tplVarStructDefine = `TplStructDefine`
|
||||
@ -125,6 +129,7 @@ func init() {
|
||||
`CGenDaoBriefStdTime`: CGenDaoBriefStdTime,
|
||||
`CGenDaoBriefWithTime`: CGenDaoBriefWithTime,
|
||||
`CGenDaoBriefDaoPath`: CGenDaoBriefDaoPath,
|
||||
`CGenDaoBriefTablePath`: CGenDaoBriefTablePath,
|
||||
`CGenDaoBriefDoPath`: CGenDaoBriefDoPath,
|
||||
`CGenDaoBriefEntityPath`: CGenDaoBriefEntityPath,
|
||||
`CGenDaoBriefGJsonSupport`: CGenDaoBriefGJsonSupport,
|
||||
@ -136,6 +141,7 @@ func init() {
|
||||
`CGenDaoBriefNoJsonTag`: CGenDaoBriefNoJsonTag,
|
||||
`CGenDaoBriefNoModelComment`: CGenDaoBriefNoModelComment,
|
||||
`CGenDaoBriefClear`: CGenDaoBriefClear,
|
||||
`CGenDaoBriefGenTable`: CGenDaoBriefGenTable,
|
||||
`CGenDaoBriefTypeMapping`: CGenDaoBriefTypeMapping,
|
||||
`CGenDaoBriefFieldMapping`: CGenDaoBriefFieldMapping,
|
||||
`CGenDaoBriefShardingPattern`: CGenDaoBriefShardingPattern,
|
||||
|
||||
@ -113,12 +113,12 @@ func (p *EnumsParser) ParsePackage(pkg *packages.Package) {
|
||||
}
|
||||
|
||||
func (p *EnumsParser) Export() string {
|
||||
var typeEnumMap = make(map[string][]interface{})
|
||||
var typeEnumMap = make(map[string][]any)
|
||||
for _, enum := range p.enums {
|
||||
if typeEnumMap[enum.Type] == nil {
|
||||
typeEnumMap[enum.Type] = make([]interface{}, 0)
|
||||
typeEnumMap[enum.Type] = make([]any, 0)
|
||||
}
|
||||
var value interface{}
|
||||
var value any
|
||||
switch enum.Kind {
|
||||
case constant.Int:
|
||||
value = gconv.Int64(enum.Value)
|
||||
|
||||
236
cmd/gf/internal/cmd/geninit/geninit.go
Normal file
236
cmd/gf/internal/cmd/geninit/geninit.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 geninit
|
||||
|
||||
import (
|
||||
"context"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/gogf/gf/v2/os/gfile"
|
||||
"github.com/gogf/gf/v2/text/gstr"
|
||||
|
||||
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
|
||||
)
|
||||
|
||||
// ProcessOptions contains options for the Process function
|
||||
type ProcessOptions struct {
|
||||
SelectVersion bool // Enable interactive version selection
|
||||
ModulePath string // Custom go.mod module path (e.g., github.com/xxx/xxx)
|
||||
UpgradeDeps bool // Upgrade dependencies to latest (go get -u ./...)
|
||||
}
|
||||
|
||||
// Process handles the template generation flow from remote repository
|
||||
func Process(ctx context.Context, repo, name string, opts *ProcessOptions) error {
|
||||
if opts == nil {
|
||||
opts = &ProcessOptions{}
|
||||
}
|
||||
|
||||
// 0. Check Go environment first
|
||||
mlog.Print("Checking Go environment...")
|
||||
goEnv, err := CheckGoEnv(ctx)
|
||||
if err != nil {
|
||||
mlog.Printf("Go environment check failed: %v", err)
|
||||
return err
|
||||
}
|
||||
mlog.Printf("Go environment OK (version: %s)", goEnv.GOVERSION)
|
||||
|
||||
// Check if this is a git subdirectory URL
|
||||
if IsSubdirRepo(repo) {
|
||||
return processGitSubdir(ctx, repo, name, opts)
|
||||
}
|
||||
|
||||
// Try Go module download first, fallback to git subdirectory if it fails
|
||||
// This handles edge cases where the heuristic may be incorrect
|
||||
err = processGoModule(ctx, repo, name, opts)
|
||||
if err != nil {
|
||||
mlog.Printf("Go module download failed, trying git subdirectory mode: %v", err)
|
||||
mlog.Print("Note: If this is a git subdirectory, you can force git mode by using a full git URL")
|
||||
|
||||
// If Go module download fails, try git subdirectory as fallback
|
||||
// This handles cases where the heuristic incorrectly classified a git subdir as Go module
|
||||
if IsSubdirRepo(repo) {
|
||||
mlog.Print("Falling back to git subdirectory download...")
|
||||
return processGitSubdir(ctx, repo, name, opts)
|
||||
}
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// processGoModule handles standard Go module download via go get
|
||||
func processGoModule(ctx context.Context, repo, name string, opts *ProcessOptions) error {
|
||||
// Extract module path (without version)
|
||||
modulePath := repo
|
||||
specifiedVersion := ""
|
||||
if gstr.Contains(repo, "@") {
|
||||
parts := gstr.Split(repo, "@")
|
||||
modulePath = parts[0]
|
||||
specifiedVersion = parts[1]
|
||||
}
|
||||
|
||||
// Default name to repo basename if empty
|
||||
if name == "" {
|
||||
name = filepath.Base(modulePath)
|
||||
}
|
||||
|
||||
// Determine the target module path for go.mod
|
||||
targetModulePath := name
|
||||
if opts.ModulePath != "" {
|
||||
targetModulePath = opts.ModulePath
|
||||
}
|
||||
|
||||
// 1. Determine version to use
|
||||
var targetVersion string
|
||||
if specifiedVersion != "" {
|
||||
// User specified version
|
||||
targetVersion = specifiedVersion
|
||||
mlog.Printf("Using specified version: %s", targetVersion)
|
||||
} else if opts.SelectVersion {
|
||||
// Interactive version selection
|
||||
mlog.Print("Fetching available versions...")
|
||||
versionInfo, err := GetModuleVersions(ctx, modulePath)
|
||||
if err != nil {
|
||||
mlog.Printf("Failed to get versions: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
targetVersion, err = SelectVersion(ctx, versionInfo.Versions, modulePath)
|
||||
if err != nil {
|
||||
mlog.Printf("Version selection failed: %v", err)
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
// Default: use latest version
|
||||
mlog.Print("Fetching latest version...")
|
||||
latest, err := GetLatestVersion(ctx, modulePath)
|
||||
if err != nil {
|
||||
mlog.Printf("Failed to get latest version, will try @latest tag: %v", err)
|
||||
targetVersion = "latest"
|
||||
} else {
|
||||
targetVersion = latest
|
||||
mlog.Printf("Latest version: %s", targetVersion)
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Download Template with determined version
|
||||
repoWithVersion := modulePath + "@" + targetVersion
|
||||
srcDir, err := downloadTemplate(ctx, repoWithVersion)
|
||||
if err != nil {
|
||||
mlog.Printf("Download failed: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
mlog.Debugf("Template located at: %s", srcDir)
|
||||
|
||||
// 3. Generate Project
|
||||
if err := generateProject(ctx, srcDir, name, modulePath, targetModulePath); err != nil {
|
||||
mlog.Printf("Generation failed: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
// 4. Handle dependencies
|
||||
var projectDir string
|
||||
if name == "." {
|
||||
projectDir = gfile.Pwd()
|
||||
} else {
|
||||
projectDir = filepath.Join(gfile.Pwd(), name)
|
||||
}
|
||||
if opts.UpgradeDeps {
|
||||
// Upgrade all dependencies to latest
|
||||
if err := upgradeDependencies(ctx, projectDir); err != nil {
|
||||
mlog.Printf("Failed to upgrade dependencies: %v", err)
|
||||
}
|
||||
} else {
|
||||
// Default: just tidy dependencies
|
||||
if err := tidyDependencies(ctx, projectDir); err != nil {
|
||||
mlog.Printf("Failed to tidy dependencies: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// processGitSubdir handles git subdirectory download via sparse checkout
|
||||
func processGitSubdir(ctx context.Context, repo, name string, opts *ProcessOptions) error {
|
||||
mlog.Print("Detected subdirectory URL, using git sparse checkout...")
|
||||
|
||||
// Check if git is available
|
||||
gitVersion, err := CheckGitEnv(ctx)
|
||||
if err != nil {
|
||||
mlog.Printf("Git is required for subdirectory templates: %v", err)
|
||||
return err
|
||||
}
|
||||
mlog.Printf("Git available (%s)", gitVersion)
|
||||
|
||||
// Download via git sparse checkout
|
||||
srcDir, gitInfo, err := downloadGitSubdir(ctx, repo)
|
||||
if err != nil {
|
||||
mlog.Printf("Git download failed: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
// Clean up temp directory after generation
|
||||
// The temp dir is parent of parent of srcDir (tempDir/repo/subpath)
|
||||
tempDir := filepath.Dir(filepath.Dir(srcDir))
|
||||
if tempDir != "" && gfile.Exists(tempDir) && gstr.Contains(tempDir, "gf-init-git") {
|
||||
defer func() {
|
||||
if err := gfile.Remove(tempDir); err != nil {
|
||||
mlog.Debugf("Failed to remove temp directory %s: %v", tempDir, err)
|
||||
} else {
|
||||
mlog.Debugf("Cleaned up temp directory: %s", tempDir)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
// Default name to subpath basename if empty
|
||||
if name == "" {
|
||||
name = filepath.Base(gitInfo.SubPath)
|
||||
}
|
||||
|
||||
// Get original module name from go.mod (might be "main" or something else)
|
||||
oldModule := GetModuleNameFromGoMod(srcDir)
|
||||
if oldModule == "" {
|
||||
// Fallback: construct from git info
|
||||
oldModule = gitInfo.Host + "/" + gitInfo.Owner + "/" + gitInfo.Repo + "/" + gitInfo.SubPath
|
||||
}
|
||||
|
||||
// Determine the target module path for go.mod
|
||||
targetModulePath := name
|
||||
if opts.ModulePath != "" {
|
||||
targetModulePath = opts.ModulePath
|
||||
}
|
||||
|
||||
mlog.Debugf("Template located at: %s", srcDir)
|
||||
mlog.Debugf("Original module: %s", oldModule)
|
||||
|
||||
// Generate Project
|
||||
if err := generateProject(ctx, srcDir, name, oldModule, targetModulePath); err != nil {
|
||||
mlog.Printf("Generation failed: %v", err)
|
||||
return err
|
||||
}
|
||||
|
||||
// Handle dependencies
|
||||
var projectDir string
|
||||
if name == "." {
|
||||
projectDir = gfile.Pwd()
|
||||
} else {
|
||||
projectDir = filepath.Join(gfile.Pwd(), name)
|
||||
}
|
||||
if opts.UpgradeDeps {
|
||||
// Upgrade all dependencies to latest
|
||||
if err := upgradeDependencies(ctx, projectDir); err != nil {
|
||||
mlog.Printf("Failed to upgrade dependencies: %v", err)
|
||||
}
|
||||
} else {
|
||||
// Default: just tidy dependencies
|
||||
if err := tidyDependencies(ctx, projectDir); err != nil {
|
||||
mlog.Printf("Failed to tidy dependencies: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
126
cmd/gf/internal/cmd/geninit/geninit_ast.go
Normal file
126
cmd/gf/internal/cmd/geninit/geninit_ast.go
Normal file
@ -0,0 +1,126 @@
|
||||
// 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 geninit
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"go/ast"
|
||||
"go/parser"
|
||||
"go/printer"
|
||||
"go/token"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/gogf/gf/v2/os/gfile"
|
||||
|
||||
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
|
||||
)
|
||||
|
||||
// ASTReplacer handles import path replacement using Go AST
|
||||
type ASTReplacer struct {
|
||||
oldModule string
|
||||
newModule string
|
||||
fset *token.FileSet
|
||||
}
|
||||
|
||||
// NewASTReplacer creates a new AST-based import replacer
|
||||
func NewASTReplacer(oldModule, newModule string) *ASTReplacer {
|
||||
return &ASTReplacer{
|
||||
oldModule: oldModule,
|
||||
newModule: newModule,
|
||||
fset: token.NewFileSet(),
|
||||
}
|
||||
}
|
||||
|
||||
// ReplaceInFile replaces import paths in a single Go file
|
||||
func (r *ASTReplacer) ReplaceInFile(ctx context.Context, filePath string) error {
|
||||
// Read file content
|
||||
content := gfile.GetContents(filePath)
|
||||
if content == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Parse the file
|
||||
file, err := parser.ParseFile(r.fset, filePath, content, parser.ParseComments)
|
||||
if err != nil {
|
||||
mlog.Debugf("Failed to parse %s: %v", filePath, err)
|
||||
return nil // Skip files that can't be parsed
|
||||
}
|
||||
|
||||
// Track if any changes were made
|
||||
changed := false
|
||||
|
||||
// Traverse and modify imports
|
||||
ast.Inspect(file, func(n ast.Node) bool {
|
||||
switch x := n.(type) {
|
||||
case *ast.ImportSpec:
|
||||
if x.Path != nil {
|
||||
importPath := strings.Trim(x.Path.Value, `"`)
|
||||
if strings.HasPrefix(importPath, r.oldModule) {
|
||||
// Replace only the leading module prefix for clarity and correctness.
|
||||
newPath := r.newModule + strings.TrimPrefix(importPath, r.oldModule)
|
||||
x.Path.Value = `"` + newPath + `"`
|
||||
changed = true
|
||||
mlog.Debugf("Replaced import: %s -> %s in %s", importPath, newPath, filePath)
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
})
|
||||
|
||||
if !changed {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Write back to file
|
||||
var buf bytes.Buffer
|
||||
// Use default printer configuration to match gofmt output
|
||||
cfg := &printer.Config{}
|
||||
if err := cfg.Fprint(&buf, r.fset, file); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return gfile.PutContents(filePath, buf.String())
|
||||
}
|
||||
|
||||
// ReplaceInDir replaces import paths in all Go files in a directory (recursively)
|
||||
func (r *ASTReplacer) ReplaceInDir(ctx context.Context, dir string) error {
|
||||
mlog.Printf("Replacing imports: %s -> %s", r.oldModule, r.newModule)
|
||||
|
||||
// Find all .go files
|
||||
files, err := findGoFiles(dir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, file := range files {
|
||||
if err := r.ReplaceInFile(ctx, file); err != nil {
|
||||
mlog.Printf("Failed to process %s: %v", file, err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// findGoFiles recursively finds all .go files in a directory
|
||||
func findGoFiles(dir string) ([]string, error) {
|
||||
var files []string
|
||||
|
||||
err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !info.IsDir() && strings.HasSuffix(path, ".go") {
|
||||
files = append(files, path)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
return files, err
|
||||
}
|
||||
111
cmd/gf/internal/cmd/geninit/geninit_downloader.go
Normal file
111
cmd/gf/internal/cmd/geninit/geninit_downloader.go
Normal file
@ -0,0 +1,111 @@
|
||||
// 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 geninit
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
|
||||
"github.com/gogf/gf/v2/os/gfile"
|
||||
"github.com/gogf/gf/v2/text/gstr"
|
||||
|
||||
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
|
||||
)
|
||||
|
||||
// downloadTemplate fetches the remote repository using go get
|
||||
func downloadTemplate(ctx context.Context, repo string) (string, error) {
|
||||
// 1. Create a temporary directory workspace
|
||||
tempDir := gfile.Temp("gf-init-cli")
|
||||
if tempDir == "" {
|
||||
return "", fmt.Errorf("failed to create temporary directory")
|
||||
}
|
||||
if err := gfile.Mkdir(tempDir); err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer func() {
|
||||
if err := gfile.Remove(tempDir); err != nil {
|
||||
mlog.Debugf("Failed to remove temp directory %s: %v", tempDir, err)
|
||||
}
|
||||
}() // Clean up the temp workspace
|
||||
|
||||
mlog.Debugf("Using temp workspace: %s", tempDir)
|
||||
|
||||
// 2. Initialize a temp go module to perform go get
|
||||
// We run commands inside the temp directory
|
||||
if err := runCmd(ctx, tempDir, "go", "mod", "init", "temp"); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// 3. Run go get <repo>
|
||||
// Try different version strategies: original -> @latest -> @master
|
||||
moduleName := repo
|
||||
if gstr.Contains(repo, "@") {
|
||||
moduleName = gstr.Split(repo, "@")[0]
|
||||
}
|
||||
|
||||
var downloadErrs []string
|
||||
versionsToTry := []string{repo}
|
||||
if !gstr.Contains(repo, "@") {
|
||||
versionsToTry = append(versionsToTry, repo+"@latest", repo+"@master")
|
||||
}
|
||||
|
||||
var successRepo string
|
||||
for _, tryRepo := range versionsToTry {
|
||||
mlog.Printf("Downloading template %s...", tryRepo)
|
||||
if err := runCmd(ctx, tempDir, "go", "get", tryRepo); err == nil {
|
||||
successRepo = tryRepo
|
||||
break
|
||||
} else {
|
||||
downloadErrs = append(downloadErrs, fmt.Sprintf("%s: %v", tryRepo, err))
|
||||
mlog.Debugf("Failed to download %s, trying next...", tryRepo)
|
||||
}
|
||||
}
|
||||
|
||||
if successRepo == "" {
|
||||
errMsg := "all download attempts failed"
|
||||
if len(downloadErrs) > 0 {
|
||||
errMsg = strings.Join(downloadErrs, "; ")
|
||||
}
|
||||
return "", fmt.Errorf("failed to download repo %s: %s", repo, errMsg)
|
||||
}
|
||||
|
||||
// 4. Find the local path using go list -m -json <repo>
|
||||
listCmd := exec.CommandContext(ctx, "go", "list", "-m", "-json", moduleName)
|
||||
listCmd.Dir = tempDir
|
||||
output, err := listCmd.Output()
|
||||
if err != nil {
|
||||
if exitErr, ok := err.(*exec.ExitError); ok {
|
||||
return "", fmt.Errorf("go list failed: %s", string(exitErr.Stderr))
|
||||
}
|
||||
return "", fmt.Errorf("failed to locate module path: %w", err)
|
||||
}
|
||||
|
||||
var modInfo struct {
|
||||
Dir string `json:"Dir"`
|
||||
}
|
||||
if err := json.Unmarshal(output, &modInfo); err != nil {
|
||||
return "", fmt.Errorf("failed to parse go list output: %w", err)
|
||||
}
|
||||
|
||||
if modInfo.Dir == "" {
|
||||
return "", fmt.Errorf("module directory not found for %s", repo)
|
||||
}
|
||||
|
||||
return modInfo.Dir, nil
|
||||
}
|
||||
|
||||
func runCmd(ctx context.Context, dir string, name string, args ...string) error {
|
||||
cmd := exec.CommandContext(ctx, name, args...)
|
||||
cmd.Dir = dir
|
||||
cmd.Stdout = os.Stdout
|
||||
cmd.Stderr = os.Stderr
|
||||
return cmd.Run()
|
||||
}
|
||||
90
cmd/gf/internal/cmd/geninit/geninit_env.go
Normal file
90
cmd/gf/internal/cmd/geninit/geninit_env.go
Normal file
@ -0,0 +1,90 @@
|
||||
// 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 geninit
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"strings"
|
||||
|
||||
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
|
||||
)
|
||||
|
||||
// GoEnv represents Go environment variables
|
||||
type GoEnv struct {
|
||||
GOVERSION string `json:"GOVERSION"`
|
||||
GOROOT string `json:"GOROOT"`
|
||||
GOPATH string `json:"GOPATH"`
|
||||
GOMODCACHE string `json:"GOMODCACHE"`
|
||||
GOPROXY string `json:"GOPROXY"`
|
||||
GO111MODULE string `json:"GO111MODULE"`
|
||||
}
|
||||
|
||||
// CheckGoEnv verifies Go is installed and properly configured
|
||||
func CheckGoEnv(ctx context.Context) (*GoEnv, error) {
|
||||
// 1. Check if go binary exists
|
||||
goPath, err := exec.LookPath("go")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("go is not installed or not in PATH: %w", err)
|
||||
}
|
||||
mlog.Debugf("Found go binary at: %s", goPath)
|
||||
|
||||
// 2. Get go env as JSON
|
||||
cmd := exec.CommandContext(ctx, "go", "env", "-json")
|
||||
output, err := cmd.Output()
|
||||
if err != nil {
|
||||
if exitErr, ok := err.(*exec.ExitError); ok {
|
||||
return nil, fmt.Errorf("go env failed: %s", string(exitErr.Stderr))
|
||||
}
|
||||
return nil, fmt.Errorf("failed to run go env: %w", err)
|
||||
}
|
||||
|
||||
// 3. Parse JSON output
|
||||
var env GoEnv
|
||||
if err := json.Unmarshal(output, &env); err != nil {
|
||||
return nil, fmt.Errorf("failed to parse go env output: %w", err)
|
||||
}
|
||||
|
||||
// 4. Validate critical environment variables
|
||||
if env.GOROOT == "" {
|
||||
return nil, fmt.Errorf("GOROOT is not set")
|
||||
}
|
||||
if env.GOMODCACHE == "" && env.GOPATH == "" {
|
||||
return nil, fmt.Errorf("neither GOMODCACHE nor GOPATH is set")
|
||||
}
|
||||
|
||||
mlog.Debugf("Go Version: %s", env.GOVERSION)
|
||||
mlog.Debugf("GOROOT: %s", env.GOROOT)
|
||||
mlog.Debugf("GOMODCACHE: %s", env.GOMODCACHE)
|
||||
mlog.Debugf("GOPROXY: %s", env.GOPROXY)
|
||||
|
||||
return &env, nil
|
||||
}
|
||||
|
||||
// CheckGitEnv verifies Git is installed and returns its version
|
||||
func CheckGitEnv(ctx context.Context) (string, error) {
|
||||
// 1. Check if git binary exists
|
||||
gitPath, err := exec.LookPath("git")
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("git is not installed or not in PATH: %w", err)
|
||||
}
|
||||
mlog.Debugf("Found git binary at: %s", gitPath)
|
||||
|
||||
// 2. Get git version
|
||||
cmd := exec.CommandContext(ctx, "git", "--version")
|
||||
output, err := cmd.Output()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to get git version: %w", err)
|
||||
}
|
||||
|
||||
version := strings.TrimSpace(string(output))
|
||||
mlog.Debugf("Git version: %s", version)
|
||||
|
||||
return version, nil
|
||||
}
|
||||
110
cmd/gf/internal/cmd/geninit/geninit_generator.go
Normal file
110
cmd/gf/internal/cmd/geninit/geninit_generator.go
Normal file
@ -0,0 +1,110 @@
|
||||
// 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 geninit
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/gogf/gf/v2/os/gfile"
|
||||
"github.com/gogf/gf/v2/text/gstr"
|
||||
|
||||
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
|
||||
)
|
||||
|
||||
// generateProject copies the template to the destination and performs cleanup
|
||||
// oldModule: original module path from template
|
||||
// newModule: target module path for go.mod (can be different from project name)
|
||||
func generateProject(ctx context.Context, srcPath, name, oldModule, newModule string) error {
|
||||
pwd := gfile.Pwd()
|
||||
|
||||
dstPath := filepath.Join(pwd, name)
|
||||
if name == "." {
|
||||
dstPath = pwd
|
||||
}
|
||||
|
||||
if gfile.Exists(dstPath) && !gfile.IsEmpty(dstPath) {
|
||||
return fmt.Errorf("target directory %s is not empty", dstPath)
|
||||
}
|
||||
|
||||
mlog.Printf("Generating project in %s...", dstPath)
|
||||
|
||||
// 1. Copy files
|
||||
if err := gfile.Copy(srcPath, dstPath); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 2. Clean up .git directory
|
||||
gitDir := filepath.Join(dstPath, ".git")
|
||||
if gfile.Exists(gitDir) {
|
||||
if err := gfile.Remove(gitDir); err != nil {
|
||||
mlog.Debugf("Failed to remove .git directory: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Clean up go.work and go.work.sum (workspace files should not be in generated project)
|
||||
for _, workFile := range []string{"go.work", "go.work.sum"} {
|
||||
workPath := filepath.Join(dstPath, workFile)
|
||||
if gfile.Exists(workPath) {
|
||||
if err := gfile.Remove(workPath); err != nil {
|
||||
mlog.Printf("Failed to remove %s: %v", workFile, err)
|
||||
} else {
|
||||
mlog.Debugf("Removed %s", workFile)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 4. Update go.mod module name
|
||||
goModPath := filepath.Join(dstPath, "go.mod")
|
||||
if gfile.Exists(goModPath) {
|
||||
content := gfile.GetContents(goModPath)
|
||||
lines := gstr.Split(content, "\n")
|
||||
if len(lines) > 0 && gstr.HasPrefix(lines[0], "module ") {
|
||||
lines[0] = "module " + newModule
|
||||
newContent := gstr.Join(lines, "\n")
|
||||
if err := gfile.PutContents(goModPath, newContent); err != nil {
|
||||
mlog.Printf("Failed to update go.mod: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 5. Use AST to replace import paths in all Go files
|
||||
if oldModule != "" && oldModule != newModule {
|
||||
replacer := NewASTReplacer(oldModule, newModule)
|
||||
if err := replacer.ReplaceInDir(ctx, dstPath); err != nil {
|
||||
return fmt.Errorf("failed to replace imports: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
mlog.Print("Project generated successfully!")
|
||||
return nil
|
||||
}
|
||||
|
||||
// tidyDependencies runs go mod tidy in the project directory
|
||||
func tidyDependencies(ctx context.Context, projectDir string) error {
|
||||
mlog.Print("Tidying dependencies (go mod tidy)...")
|
||||
if err := runCmd(ctx, projectDir, "go", "mod", "tidy"); err != nil {
|
||||
return fmt.Errorf("go mod tidy failed: %w", err)
|
||||
}
|
||||
mlog.Print("Dependencies tidied successfully!")
|
||||
return nil
|
||||
}
|
||||
|
||||
// upgradeDependencies runs go get -u ./... to upgrade all dependencies to latest
|
||||
func upgradeDependencies(ctx context.Context, projectDir string) error {
|
||||
mlog.Print("Upgrading dependencies to latest (go get -u ./...)...")
|
||||
if err := runCmd(ctx, projectDir, "go", "get", "-u", "./..."); err != nil {
|
||||
return fmt.Errorf("go get -u failed: %w", err)
|
||||
}
|
||||
// Run tidy again after upgrade
|
||||
if err := runCmd(ctx, projectDir, "go", "mod", "tidy"); err != nil {
|
||||
return fmt.Errorf("go mod tidy after upgrade failed: %w", err)
|
||||
}
|
||||
mlog.Print("Dependencies upgraded successfully!")
|
||||
return nil
|
||||
}
|
||||
241
cmd/gf/internal/cmd/geninit/geninit_git_downloader.go
Normal file
241
cmd/gf/internal/cmd/geninit/geninit_git_downloader.go
Normal file
@ -0,0 +1,241 @@
|
||||
// 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 geninit
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/gogf/gf/v2/os/gfile"
|
||||
"github.com/gogf/gf/v2/text/gstr"
|
||||
|
||||
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
|
||||
)
|
||||
|
||||
// GitRepoInfo holds parsed git repository information
|
||||
type GitRepoInfo struct {
|
||||
Host string // e.g., github.com
|
||||
Owner string // e.g., gogf
|
||||
Repo string // e.g., examples
|
||||
Branch string // e.g., main (default: main)
|
||||
SubPath string // e.g., httpserver/jwt
|
||||
CloneURL string // e.g., https://github.com/gogf/examples.git
|
||||
}
|
||||
|
||||
// ParseGitURL parses a git URL and extracts repository info
|
||||
// Supports formats:
|
||||
// - github.com/owner/repo
|
||||
// - github.com/owner/repo/subdir/path
|
||||
// - github.com/owner/repo/tree/branch/subdir/path (from GitHub web URL)
|
||||
func ParseGitURL(url string) (*GitRepoInfo, error) {
|
||||
// Remove protocol prefix if present
|
||||
url = strings.TrimPrefix(url, "https://")
|
||||
url = strings.TrimPrefix(url, "http://")
|
||||
url = strings.TrimSuffix(url, ".git")
|
||||
|
||||
// Remove version suffix like @v1.0.0
|
||||
if idx := strings.Index(url, "@"); idx != -1 {
|
||||
url = url[:idx]
|
||||
}
|
||||
|
||||
parts := strings.Split(url, "/")
|
||||
if len(parts) < 3 {
|
||||
return nil, fmt.Errorf("invalid git URL: %s", url)
|
||||
}
|
||||
|
||||
info := &GitRepoInfo{
|
||||
Host: parts[0],
|
||||
Owner: parts[1],
|
||||
Repo: parts[2],
|
||||
Branch: "main", // default branch
|
||||
}
|
||||
|
||||
// Check for /tree/branch/ pattern (GitHub web URL)
|
||||
if len(parts) > 4 && parts[3] == "tree" {
|
||||
info.Branch = parts[4]
|
||||
if len(parts) > 5 {
|
||||
info.SubPath = strings.Join(parts[5:], "/")
|
||||
}
|
||||
} else if len(parts) > 3 {
|
||||
// Direct subpath: github.com/owner/repo/subdir/path
|
||||
info.SubPath = strings.Join(parts[3:], "/")
|
||||
}
|
||||
|
||||
info.CloneURL = fmt.Sprintf("https://%s/%s/%s.git", info.Host, info.Owner, info.Repo)
|
||||
|
||||
return info, nil
|
||||
}
|
||||
|
||||
// IsSubdirRepo checks if the URL points to a subdirectory of a repository
|
||||
// Returns false for Go module paths (which may have /vN suffix or nested module paths)
|
||||
// Note: This uses heuristics that may have false positives/negatives in edge cases
|
||||
func IsSubdirRepo(url string) bool {
|
||||
info, err := ParseGitURL(url)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
if info.SubPath == "" {
|
||||
return false
|
||||
}
|
||||
|
||||
// Check if this looks like a Go module path rather than a git subdirectory
|
||||
// Go modules can have nested paths like github.com/owner/repo/cmd/tool/v2
|
||||
// We should try to resolve it as a Go module first
|
||||
|
||||
// If the URL can be resolved as a Go module, it's not a subdir repo
|
||||
// We use a heuristic: check if the full path looks like a valid Go module
|
||||
// by checking if it ends with /vN (major version) or contains common module patterns
|
||||
|
||||
// Remove version suffix for checking
|
||||
cleanURL := url
|
||||
if before, _, ok := strings.Cut(url, "@"); ok {
|
||||
cleanURL = before
|
||||
}
|
||||
|
||||
// Check if the path ends with /vN (Go module major version)
|
||||
parts := strings.Split(cleanURL, "/")
|
||||
if len(parts) > 0 {
|
||||
lastPart := parts[len(parts)-1]
|
||||
if len(lastPart) >= 2 && lastPart[0] == 'v' {
|
||||
// Check if it's v2, v3, etc.
|
||||
if _, err := fmt.Sscanf(lastPart, "v%d", new(int)); err == nil {
|
||||
// This looks like a Go module with major version suffix
|
||||
// It could be either a versioned module or a subdir ending in vN
|
||||
// We'll treat it as a Go module and let go get handle it
|
||||
mlog.Debugf("URL %s detected as Go module (ends with /vN)", url)
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// For GitHub URLs, check if the subpath could be a nested Go module
|
||||
// Common patterns: cmd/*, internal/*, pkg/*, contrib/*
|
||||
subPathParts := strings.Split(info.SubPath, "/")
|
||||
if len(subPathParts) > 0 {
|
||||
firstPart := subPathParts[0]
|
||||
// These are common Go module nesting patterns
|
||||
if firstPart == "cmd" || firstPart == "contrib" || firstPart == "tools" {
|
||||
// This might be a nested Go module, not a simple subdirectory
|
||||
// Let go get try first
|
||||
mlog.Debugf("URL %s detected as Go module (starts with common pattern)", url)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
mlog.Debugf("URL %s detected as git subdirectory", url)
|
||||
return true
|
||||
}
|
||||
|
||||
// downloadGitSubdir downloads a subdirectory from a git repository using sparse checkout
|
||||
func downloadGitSubdir(ctx context.Context, repoURL string) (string, *GitRepoInfo, error) {
|
||||
info, err := ParseGitURL(repoURL)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
|
||||
if info.SubPath == "" {
|
||||
return "", nil, fmt.Errorf("not a subdirectory URL: %s", repoURL)
|
||||
}
|
||||
|
||||
// Create temp directory for clone
|
||||
tempDir := gfile.Temp("gf-init-git")
|
||||
if tempDir == "" {
|
||||
return "", nil, fmt.Errorf("failed to create temporary directory")
|
||||
}
|
||||
if err := gfile.Mkdir(tempDir); err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
|
||||
cloneDir := filepath.Join(tempDir, info.Repo)
|
||||
mlog.Debugf("Using git temp workspace: %s", tempDir)
|
||||
mlog.Printf("Cloning %s (sparse checkout: %s)...", info.CloneURL, info.SubPath)
|
||||
|
||||
// 1. Clone with no checkout, filter, and sparse
|
||||
if err := runCmd(ctx, tempDir, "git", "clone", "--filter=blob:none", "--no-checkout", "--sparse", info.CloneURL); err != nil {
|
||||
// Fallback: try without filter for older git versions
|
||||
mlog.Debugf("Sparse clone failed, trying full clone...")
|
||||
if err := gfile.Remove(cloneDir); err != nil {
|
||||
mlog.Debugf("Failed to remove clone directory: %v", err)
|
||||
}
|
||||
if err := runCmd(ctx, tempDir, "git", "clone", "--no-checkout", info.CloneURL); err != nil {
|
||||
if err := gfile.Remove(tempDir); err != nil {
|
||||
mlog.Debugf("Failed to remove temp directory: %v", err)
|
||||
}
|
||||
return "", nil, fmt.Errorf("git clone failed: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Set sparse-checkout to the subpath
|
||||
if err := runCmd(ctx, cloneDir, "git", "sparse-checkout", "set", info.SubPath); err != nil {
|
||||
// Fallback for older git: use sparse-checkout init + set
|
||||
mlog.Debugf("sparse-checkout set failed, trying legacy method...")
|
||||
if err := runCmd(ctx, cloneDir, "git", "sparse-checkout", "init", "--cone"); err != nil {
|
||||
if err := gfile.Remove(tempDir); err != nil {
|
||||
mlog.Debugf("Failed to remove temp directory: %v", err)
|
||||
}
|
||||
return "", nil, fmt.Errorf("git sparse-checkout init (legacy) failed: %w", err)
|
||||
}
|
||||
if err := runCmd(ctx, cloneDir, "git", "sparse-checkout", "set", info.SubPath); err != nil {
|
||||
if err := gfile.Remove(tempDir); err != nil {
|
||||
mlog.Debugf("Failed to remove temp directory: %v", err)
|
||||
}
|
||||
return "", nil, fmt.Errorf("git sparse-checkout set (legacy) failed: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Checkout the branch
|
||||
if err := runCmd(ctx, cloneDir, "git", "checkout", info.Branch); err != nil {
|
||||
// Try master if main fails
|
||||
if info.Branch == "main" {
|
||||
mlog.Debugf("Branch 'main' not found, trying 'master'...")
|
||||
info.Branch = "master"
|
||||
if err := runCmd(ctx, cloneDir, "git", "checkout", "master"); err != nil {
|
||||
if err := gfile.Remove(tempDir); err != nil {
|
||||
mlog.Debugf("Failed to remove temp directory: %v", err)
|
||||
}
|
||||
return "", nil, fmt.Errorf("git checkout failed: %w", err)
|
||||
}
|
||||
} else {
|
||||
if err := gfile.Remove(tempDir); err != nil {
|
||||
mlog.Debugf("Failed to remove temp directory: %v", err)
|
||||
}
|
||||
return "", nil, fmt.Errorf("git checkout failed: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Return the path to the subdirectory
|
||||
subDirPath := filepath.Join(cloneDir, info.SubPath)
|
||||
if !gfile.Exists(subDirPath) {
|
||||
if err := gfile.Remove(tempDir); err != nil {
|
||||
mlog.Debugf("Failed to remove temp directory: %v", err)
|
||||
}
|
||||
return "", nil, fmt.Errorf("subdirectory not found: %s", info.SubPath)
|
||||
}
|
||||
|
||||
mlog.Debugf("Subdirectory located at: %s", subDirPath)
|
||||
return subDirPath, info, nil
|
||||
}
|
||||
|
||||
// GetModuleNameFromGoMod reads module name from go.mod file
|
||||
func GetModuleNameFromGoMod(dir string) string {
|
||||
goModPath := filepath.Join(dir, "go.mod")
|
||||
if !gfile.Exists(goModPath) {
|
||||
return ""
|
||||
}
|
||||
|
||||
content := gfile.GetContents(goModPath)
|
||||
lines := gstr.Split(content, "\n")
|
||||
for _, line := range lines {
|
||||
line = strings.TrimSpace(line)
|
||||
if after, ok := strings.CutPrefix(line, "module "); ok {
|
||||
return strings.TrimSpace(after)
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
99
cmd/gf/internal/cmd/geninit/geninit_selector.go
Normal file
99
cmd/gf/internal/cmd/geninit/geninit_selector.go
Normal file
@ -0,0 +1,99 @@
|
||||
// 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 geninit
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
|
||||
)
|
||||
|
||||
// SelectVersion prompts user to select a version interactively
|
||||
func SelectVersion(ctx context.Context, versions []string, modulePath string) (string, error) {
|
||||
if len(versions) == 0 {
|
||||
return "", fmt.Errorf("no versions available for selection")
|
||||
}
|
||||
|
||||
if len(versions) == 1 {
|
||||
mlog.Printf("Only one version available: %s", versions[0])
|
||||
return versions[0], nil
|
||||
}
|
||||
|
||||
// Display available versions
|
||||
fmt.Printf("\nAvailable versions for %s:\n", modulePath)
|
||||
fmt.Println(strings.Repeat("-", 40))
|
||||
|
||||
// Show versions with index (newest first)
|
||||
maxDisplay := 20 // Limit display to avoid overwhelming output
|
||||
displayCount := len(versions)
|
||||
if displayCount > maxDisplay {
|
||||
displayCount = maxDisplay
|
||||
}
|
||||
|
||||
for i := 0; i < displayCount; i++ {
|
||||
marker := ""
|
||||
if i == 0 {
|
||||
marker = " (latest)"
|
||||
}
|
||||
fmt.Printf(" [%2d] %s%s\n", i+1, versions[i], marker)
|
||||
}
|
||||
|
||||
if len(versions) > maxDisplay {
|
||||
fmt.Printf(" ... and %d more versions\n", len(versions)-maxDisplay)
|
||||
}
|
||||
|
||||
fmt.Println(strings.Repeat("-", 40))
|
||||
|
||||
// Prompt for selection
|
||||
reader := bufio.NewReader(os.Stdin)
|
||||
for {
|
||||
fmt.Printf("Select version [1-%d] or enter version string (default: 1 for latest): ", displayCount)
|
||||
|
||||
input, err := reader.ReadString('\n')
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to read input: %w", err)
|
||||
}
|
||||
|
||||
input = strings.TrimSpace(input)
|
||||
|
||||
// Default to latest
|
||||
if input == "" {
|
||||
fmt.Printf("Selected: %s (latest)\n", versions[0])
|
||||
return versions[0], nil
|
||||
}
|
||||
|
||||
// Try parsing as number first
|
||||
idx, err := strconv.Atoi(input)
|
||||
if err == nil {
|
||||
// Valid number - check if in range
|
||||
if idx >= 1 && idx <= len(versions) {
|
||||
// Allow selection from all versions, not just displayed ones
|
||||
selected := versions[idx-1]
|
||||
fmt.Printf("Selected: %s\n", selected)
|
||||
return selected, nil
|
||||
} else if idx < 1 || idx > displayCount {
|
||||
fmt.Printf("Invalid selection. Please enter a number between 1 and %d, or type a version string.\n", displayCount)
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
// Try matching the input as a version string (e.g., "v1.2.3")
|
||||
for _, v := range versions {
|
||||
if v == input || strings.Contains(v, input) {
|
||||
fmt.Printf("Selected: %s\n", v)
|
||||
return v, nil
|
||||
}
|
||||
}
|
||||
fmt.Printf("Version '%s' not found. Please select by number or type a valid version string.\n", input)
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
138
cmd/gf/internal/cmd/geninit/geninit_version.go
Normal file
138
cmd/gf/internal/cmd/geninit/geninit_version.go
Normal file
@ -0,0 +1,138 @@
|
||||
// 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 geninit
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/mod/semver"
|
||||
|
||||
"github.com/gogf/gf/v2/os/gfile"
|
||||
|
||||
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
|
||||
)
|
||||
|
||||
// VersionInfo contains module version information
|
||||
type VersionInfo struct {
|
||||
Module string `json:"module"`
|
||||
Versions []string `json:"versions"`
|
||||
Latest string `json:"latest"`
|
||||
}
|
||||
|
||||
// GetModuleVersions fetches available versions for a Go module
|
||||
func GetModuleVersions(ctx context.Context, modulePath string) (*VersionInfo, error) {
|
||||
// Create a temporary directory for go list
|
||||
tempDir := gfile.Temp("gf-init-version")
|
||||
if tempDir == "" {
|
||||
return nil, fmt.Errorf("failed to create temporary directory for go list")
|
||||
}
|
||||
if err := gfile.Mkdir(tempDir); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer func() {
|
||||
if err := gfile.Remove(tempDir); err != nil {
|
||||
mlog.Debugf("Failed to remove temp directory: %v", err)
|
||||
}
|
||||
}()
|
||||
|
||||
// Initialize a temp go module
|
||||
if err := runCmd(ctx, tempDir, "go", "mod", "init", "temp"); err != nil {
|
||||
return nil, fmt.Errorf("failed to init temp module: %w", err)
|
||||
}
|
||||
|
||||
// Get versions using go list -m -versions
|
||||
cmd := exec.CommandContext(ctx, "go", "list", "-m", "-versions", modulePath)
|
||||
cmd.Dir = tempDir
|
||||
output, err := cmd.Output()
|
||||
if err != nil {
|
||||
// Try with @latest to see if module exists
|
||||
mlog.Debugf("go list -versions failed, trying @latest: %v", err)
|
||||
return getLatestOnly(ctx, tempDir, modulePath)
|
||||
}
|
||||
|
||||
// Parse output: "module/path v1.0.0 v1.1.0 v2.0.0"
|
||||
parts := strings.Fields(strings.TrimSpace(string(output)))
|
||||
if len(parts) < 1 {
|
||||
return nil, fmt.Errorf("no version information found for %s", modulePath)
|
||||
}
|
||||
|
||||
info := &VersionInfo{
|
||||
Module: parts[0],
|
||||
Versions: []string{},
|
||||
}
|
||||
|
||||
if len(parts) > 1 {
|
||||
info.Versions = parts[1:]
|
||||
// Sort versions in descending order (newest first)
|
||||
sort.Slice(info.Versions, func(i, j int) bool {
|
||||
return semver.Compare(info.Versions[i], info.Versions[j]) > 0
|
||||
})
|
||||
info.Latest = info.Versions[0]
|
||||
}
|
||||
|
||||
// If no tagged versions, try to get latest
|
||||
if len(info.Versions) == 0 {
|
||||
latestInfo, err := getLatestOnly(ctx, tempDir, modulePath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
info.Latest = latestInfo.Latest
|
||||
if latestInfo.Latest != "" {
|
||||
info.Versions = []string{latestInfo.Latest}
|
||||
}
|
||||
}
|
||||
|
||||
return info, nil
|
||||
}
|
||||
|
||||
// getLatestOnly gets only the latest version when go list -versions fails
|
||||
func getLatestOnly(ctx context.Context, tempDir, modulePath string) (*VersionInfo, error) {
|
||||
// Try go list -m modulePath@latest
|
||||
cmd := exec.CommandContext(ctx, "go", "list", "-m", "-json", modulePath+"@latest")
|
||||
cmd.Dir = tempDir
|
||||
output, err := cmd.Output()
|
||||
if err != nil {
|
||||
// Try without @latest
|
||||
cmd = exec.CommandContext(ctx, "go", "list", "-m", "-json", modulePath)
|
||||
cmd.Dir = tempDir
|
||||
output, err = cmd.Output()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get module info for %s: %w", modulePath, err)
|
||||
}
|
||||
}
|
||||
|
||||
var modInfo struct {
|
||||
Path string `json:"Path"`
|
||||
Version string `json:"Version"`
|
||||
}
|
||||
if err := json.Unmarshal(output, &modInfo); err != nil {
|
||||
return nil, fmt.Errorf("failed to parse module info: %w", err)
|
||||
}
|
||||
|
||||
return &VersionInfo{
|
||||
Module: modInfo.Path,
|
||||
Versions: []string{modInfo.Version},
|
||||
Latest: modInfo.Version,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GetLatestVersion returns the latest version of a module
|
||||
func GetLatestVersion(ctx context.Context, modulePath string) (string, error) {
|
||||
info, err := GetModuleVersions(ctx, modulePath)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if info.Latest == "" {
|
||||
return "", fmt.Errorf("no version found for %s", modulePath)
|
||||
}
|
||||
return info.Latest, nil
|
||||
}
|
||||
@ -109,7 +109,7 @@ func (c CGenPb) tagCommentIntoListMap(comment string, lineTagMap *gmap.ListMap)
|
||||
|
||||
func (c CGenPb) listMapToStructTag(lineTagMap *gmap.ListMap) string {
|
||||
var tag string
|
||||
lineTagMap.Iterator(func(key, value interface{}) bool {
|
||||
lineTagMap.Iterator(func(key, value any) bool {
|
||||
if tag != "" {
|
||||
tag += " "
|
||||
}
|
||||
|
||||
@ -15,6 +15,8 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/olekukonko/tablewriter"
|
||||
"github.com/olekukonko/tablewriter/renderer"
|
||||
"github.com/olekukonko/tablewriter/tw"
|
||||
|
||||
"github.com/gogf/gf/v2/container/garray"
|
||||
"github.com/gogf/gf/v2/container/gset"
|
||||
@ -37,17 +39,19 @@ 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}"`
|
||||
RemoveFieldPrefix string `name:"removeFieldPrefix" short:"rf" brief:"{CGenPbEntityBriefRemoveFieldPrefix}"`
|
||||
TablesEx string `name:"tablesEx" short:"x" brief:"{CGenDaoBriefTablesEx}"`
|
||||
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}"`
|
||||
Path string `name:"path" short:"p" brief:"{CGenPbEntityBriefPath}" d:"manifest/protobuf/pbentity"`
|
||||
Package string `name:"package" short:"k" brief:"{CGenPbEntityBriefPackage}"`
|
||||
GoPackage string `name:"goPackage" short:"g" brief:"{CGenPbEntityBriefGoPackage}"`
|
||||
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}"`
|
||||
TablesEx string `name:"tablesEx" short:"x" brief:"{CGenDaoBriefTablesEx}"`
|
||||
NameCase string `name:"nameCase" short:"n" brief:"{CGenPbEntityBriefNameCase}" d:"Camel"`
|
||||
JsonCase string `name:"jsonCase" short:"j" brief:"{CGenPbEntityBriefJsonCase}" d:"none"`
|
||||
Option string `name:"option" short:"o" brief:"{CGenPbEntityBriefOption}"`
|
||||
ShardingPattern []string `name:"shardingPattern" short:"sp" brief:"{CGenDaoBriefShardingPattern}"`
|
||||
|
||||
TypeMapping map[DBFieldTypeName]CustomAttributeType `name:"typeMapping" short:"y" brief:"{CGenPbEntityBriefTypeMapping}" orphan:"true"`
|
||||
FieldMapping map[DBTableFieldName]CustomAttributeType `name:"fieldMapping" short:"fm" brief:"{CGenPbEntityBriefFieldMapping}" orphan:"true"`
|
||||
@ -113,6 +117,7 @@ CONFIGURATION SUPPORT
|
||||
`
|
||||
CGenPbEntityBriefPath = `directory path for generated files storing`
|
||||
CGenPbEntityBriefPackage = `package path for all entity proto files`
|
||||
CGenPbEntityBriefGoPackage = `go package path for all entity proto files`
|
||||
CGenPbEntityBriefLink = `database configuration, the same as the ORM configuration of GoFrame`
|
||||
CGenPbEntityBriefTables = `generate models only for given tables, multiple table names separated with ','`
|
||||
CGenPbEntityBriefPrefix = `add specified prefix for all entity names and entity proto files`
|
||||
@ -120,6 +125,7 @@ CONFIGURATION SUPPORT
|
||||
CGenPbEntityBriefTablesEx = `generate all models exclude the specified tables, multiple prefix separated with ','`
|
||||
CGenPbEntityBriefRemoveFieldPrefix = `remove specified prefix of the field, multiple prefix separated with ','`
|
||||
CGenPbEntityBriefOption = `extra protobuf options`
|
||||
CGenPbEntityBriefShardingPattern = `sharding pattern for table name, e.g. "users_?" will replace tables "users_001,users_002,..." to "users" pbentity`
|
||||
CGenPbEntityBriefGroup = `
|
||||
specifying the configuration group name of database for generated ORM instance,
|
||||
it's not necessary and the default value is "default"
|
||||
@ -239,6 +245,7 @@ func init() {
|
||||
`CGenPbEntityAd`: CGenPbEntityAd,
|
||||
`CGenPbEntityBriefPath`: CGenPbEntityBriefPath,
|
||||
`CGenPbEntityBriefPackage`: CGenPbEntityBriefPackage,
|
||||
`CGenPbEntityBriefGoPackage`: CGenPbEntityBriefGoPackage,
|
||||
`CGenPbEntityBriefLink`: CGenPbEntityBriefLink,
|
||||
`CGenPbEntityBriefTables`: CGenPbEntityBriefTables,
|
||||
`CGenPbEntityBriefPrefix`: CGenPbEntityBriefPrefix,
|
||||
@ -249,6 +256,7 @@ func init() {
|
||||
`CGenPbEntityBriefNameCase`: CGenPbEntityBriefNameCase,
|
||||
`CGenPbEntityBriefJsonCase`: CGenPbEntityBriefJsonCase,
|
||||
`CGenPbEntityBriefOption`: CGenPbEntityBriefOption,
|
||||
`CGenPbEntityBriefShardingPattern`: CGenPbEntityBriefShardingPattern,
|
||||
`CGenPbEntityBriefTypeMapping`: CGenPbEntityBriefTypeMapping,
|
||||
`CGenPbEntityBriefFieldMapping`: CGenPbEntityBriefFieldMapping,
|
||||
})
|
||||
@ -318,6 +326,7 @@ func doGenPbEntityForArray(ctx context.Context, index int, in CGenPbEntityInput)
|
||||
}
|
||||
|
||||
tableNames := ([]string)(nil)
|
||||
shardingNewTableSet := gset.NewStrSet()
|
||||
if in.Tables != "" {
|
||||
tableNames = gstr.SplitAndTrim(in.Tables, ",")
|
||||
} else {
|
||||
@ -345,6 +354,31 @@ func doGenPbEntityForArray(ctx context.Context, index int, in CGenPbEntityInput)
|
||||
for _, v := range removePrefixArray {
|
||||
newTableName = gstr.TrimLeftStr(newTableName, v, 1)
|
||||
}
|
||||
var shardingTableName string
|
||||
if len(in.ShardingPattern) > 0 {
|
||||
for _, pattern := range in.ShardingPattern {
|
||||
var (
|
||||
match []string
|
||||
regPattern = gstr.Replace(pattern, "?", `(.+)`)
|
||||
)
|
||||
match, err = gregex.MatchString(regPattern, newTableName)
|
||||
if err != nil {
|
||||
mlog.Fatalf(`invalid sharding pattern "%s": %+v`, pattern, err)
|
||||
}
|
||||
if len(match) < 2 {
|
||||
continue
|
||||
}
|
||||
shardingTableName = gstr.Replace(pattern, "?", "")
|
||||
shardingTableName = gstr.Trim(shardingTableName, `_.-`)
|
||||
}
|
||||
}
|
||||
if shardingTableName != "" {
|
||||
if shardingNewTableSet.Contains(shardingTableName) {
|
||||
continue
|
||||
}
|
||||
shardingNewTableSet.Add(shardingTableName)
|
||||
newTableName = shardingTableName
|
||||
}
|
||||
generatePbEntityContentFile(ctx, CGenPbEntityInternalInput{
|
||||
CGenPbEntityInput: in,
|
||||
DB: db,
|
||||
@ -379,10 +413,13 @@ func generatePbEntityContentFile(ctx context.Context, in CGenPbEntityInternalInp
|
||||
}
|
||||
}
|
||||
}
|
||||
if in.GoPackage == "" {
|
||||
in.GoPackage = in.Package
|
||||
}
|
||||
entityContent := gstr.ReplaceByMap(getTplPbEntityContent(""), g.MapStrStr{
|
||||
"{Imports}": packageImportsArray.Join("\n"),
|
||||
"{PackageName}": gfile.Basename(in.Package),
|
||||
"{GoPackage}": in.Package,
|
||||
"{GoPackage}": in.GoPackage,
|
||||
"{OptionContent}": in.Option,
|
||||
"{EntityMessage}": entityMessageDefine,
|
||||
})
|
||||
@ -408,13 +445,22 @@ func generateEntityMessageDefinition(entityName string, fieldMap map[string]*gdb
|
||||
appendImports = append(appendImports, imports)
|
||||
}
|
||||
}
|
||||
tw := tablewriter.NewWriter(buffer)
|
||||
tw.SetBorder(false)
|
||||
tw.SetRowLine(false)
|
||||
tw.SetAutoWrapText(false)
|
||||
tw.SetColumnSeparator("")
|
||||
tw.AppendBulk(array)
|
||||
tw.Render()
|
||||
table := tablewriter.NewTable(buffer,
|
||||
tablewriter.WithRenderer(renderer.NewBlueprint(tw.Rendition{
|
||||
Borders: tw.Border{Top: tw.Off, Bottom: tw.Off, Left: tw.On, Right: tw.Off},
|
||||
Settings: tw.Settings{
|
||||
Separators: tw.Separators{BetweenRows: tw.Off, BetweenColumns: tw.Off},
|
||||
},
|
||||
Symbols: tw.NewSymbolCustom("Proto").WithColumn(" "),
|
||||
})),
|
||||
tablewriter.WithConfig(tablewriter.Config{
|
||||
Row: tw.CellConfig{
|
||||
Formatting: tw.CellFormatting{AutoWrap: tw.WrapNone},
|
||||
},
|
||||
}),
|
||||
)
|
||||
table.Bulk(array)
|
||||
table.Render()
|
||||
stContent := buffer.String()
|
||||
// Let's do this hack of table writer for indent!
|
||||
stContent = regexp.MustCompile(`\s+\n`).ReplaceAllString(gstr.Replace(stContent, " #", ""), "\n")
|
||||
@ -435,14 +481,23 @@ func generateMessageFieldForPbEntity(index int, field *gdb.TableField, in CGenPb
|
||||
err error
|
||||
ctx = gctx.GetInitCtx()
|
||||
)
|
||||
|
||||
if in.TypeMapping != nil && len(in.TypeMapping) > 0 {
|
||||
// match typeMapping after local type transform.
|
||||
// eg: double => string, varchar => string etc.
|
||||
localTypeName, err = in.DB.CheckLocalTypeForField(ctx, field.Type, nil)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if localTypeName != "" {
|
||||
if typeMapping, ok := in.TypeMapping[strings.ToLower(string(localTypeName))]; ok {
|
||||
if typeMappingLocal, localOk := in.TypeMapping[strings.ToLower(string(localTypeName))]; localOk {
|
||||
localTypeNameStr = typeMappingLocal.Type
|
||||
appendImport = typeMappingLocal.Import
|
||||
}
|
||||
}
|
||||
// Try match unknown / string localTypeName with db type.
|
||||
if localTypeName == "" || localTypeName == gdb.LocalTypeString {
|
||||
formattedFieldType, _ := in.DB.GetFormattedDBTypeNameForField(field.Type)
|
||||
if typeMapping, ok := in.TypeMapping[strings.ToLower(formattedFieldType)]; ok {
|
||||
localTypeNameStr = typeMapping.Type
|
||||
appendImport = typeMapping.Import
|
||||
}
|
||||
|
||||
@ -13,8 +13,6 @@ import (
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
|
||||
"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/garray"
|
||||
"github.com/gogf/gf/v2/container/gmap"
|
||||
"github.com/gogf/gf/v2/container/gset"
|
||||
@ -25,6 +23,9 @@ import (
|
||||
"github.com/gogf/gf/v2/text/gstr"
|
||||
"github.com/gogf/gf/v2/util/gconv"
|
||||
"github.com/gogf/gf/v2/util/gtag"
|
||||
|
||||
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
|
||||
"github.com/gogf/gf/cmd/gf/v2/internal/utility/utils"
|
||||
)
|
||||
|
||||
const (
|
||||
|
||||
@ -33,7 +33,7 @@ func (c CGenService) generateType(generatedContent *bytes.Buffer, srcStructFunct
|
||||
generatedContent.WriteString("type(")
|
||||
generatedContent.WriteString("\n")
|
||||
|
||||
srcStructFunctions.Iterator(func(key, value interface{}) bool {
|
||||
srcStructFunctions.Iterator(func(key, value any) bool {
|
||||
var (
|
||||
funcContents = make([]string, 0)
|
||||
funcContent string
|
||||
@ -71,7 +71,7 @@ func (c CGenService) generateVar(generatedContent *bytes.Buffer, srcStructFuncti
|
||||
// Generating variable and register definitions.
|
||||
var variableContent string
|
||||
|
||||
srcStructFunctions.Iterator(func(key, value interface{}) bool {
|
||||
srcStructFunctions.Iterator(func(key, value any) bool {
|
||||
structName := key.(string)
|
||||
variableContent += gstr.Trim(gstr.ReplaceByMap(consts.TemplateGenServiceContentVariable, g.MapStrStr{
|
||||
"{StructName}": structName,
|
||||
@ -93,7 +93,7 @@ func (c CGenService) generateVar(generatedContent *bytes.Buffer, srcStructFuncti
|
||||
// See: const.TemplateGenServiceContentRegister
|
||||
func (c CGenService) generateFunc(generatedContent *bytes.Buffer, srcStructFunctions *gmap.ListMap) {
|
||||
// Variable register function definitions.
|
||||
srcStructFunctions.Iterator(func(key, value interface{}) bool {
|
||||
srcStructFunctions.Iterator(func(key, value any) bool {
|
||||
structName := key.(string)
|
||||
generatedContent.WriteString(gstr.Trim(gstr.ReplaceByMap(consts.TemplateGenServiceContentRegister, g.MapStrStr{
|
||||
"{StructName}": structName,
|
||||
|
||||
11
cmd/gf/internal/cmd/testdata/build/varmap/go.mod
vendored
11
cmd/gf/internal/cmd/testdata/build/varmap/go.mod
vendored
@ -1,12 +1,15 @@
|
||||
module github.com/gogf/gf/cmd/gf/cmd/gf/testdata/vardump/v2
|
||||
|
||||
go 1.18
|
||||
go 1.23.0
|
||||
|
||||
require github.com/gogf/gf/v2 v2.8.2
|
||||
toolchain go1.24.6
|
||||
|
||||
require github.com/gogf/gf/v2 v2.9.6
|
||||
|
||||
require (
|
||||
go.opentelemetry.io/otel v1.24.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.24.0 // indirect
|
||||
go.opentelemetry.io/otel v1.38.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.38.0 // indirect
|
||||
golang.org/x/text v0.28.0 // indirect
|
||||
)
|
||||
|
||||
replace github.com/gogf/gf/v2 => ../../../../../../../
|
||||
|
||||
73
cmd/gf/internal/cmd/testdata/build/varmap/go.sum
vendored
73
cmd/gf/internal/cmd/testdata/build/varmap/go.sum
vendored
@ -1,29 +1,62 @@
|
||||
github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0=
|
||||
github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg=
|
||||
github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
|
||||
github.com/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/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
|
||||
github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4=
|
||||
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
|
||||
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/emirpasic/gods/v2 v2.0.0-alpha h1:dwFlh8pBg1VMOXWGipNMRt8v96dKAIvBehtCt6OtunU=
|
||||
github.com/emirpasic/gods/v2 v2.0.0-alpha/go.mod h1:W0y4M2dtBB9U5z3YlghmpuUhiaZT2h6yoeE+C1sCp6A=
|
||||
github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=
|
||||
github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU=
|
||||
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
|
||||
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
|
||||
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
|
||||
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
|
||||
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/grokify/html-strip-tags-go v0.1.0 h1:03UrQLjAny8xci+R+qjCce/MYnpNXCtgzltlQbOBae4=
|
||||
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
|
||||
github.com/grokify/html-strip-tags-go v0.1.0/go.mod h1:ZdzgfHEzAfz9X6Xe5eBLVblWIxXfYSQ40S/VKrAOGpc=
|
||||
github.com/magiconair/properties v1.8.10 h1:s31yESBquKXCV9a/ScB3ESkOjUYYv+X0rg8SYxI99mE=
|
||||
github.com/magiconair/properties v1.8.10/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
|
||||
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.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
|
||||
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
|
||||
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/olekukonko/errors v1.1.0 h1:RNuGIh15QdDenh+hNvKrJkmxxjV4hcS50Db478Ou5sM=
|
||||
github.com/olekukonko/errors v1.1.0/go.mod h1:ppzxA5jBKcO1vIpCXQ9ZqgDh8iwODz6OXIGKU8r5m4Y=
|
||||
github.com/olekukonko/ll v0.0.9 h1:Y+1YqDfVkqMWuEQMclsF9HUR5+a82+dxJuL1HHSRpxI=
|
||||
github.com/olekukonko/ll v0.0.9/go.mod h1:En+sEW0JNETl26+K8eZ6/W4UQ7CYSrrgg/EdIYT2H8g=
|
||||
github.com/olekukonko/tablewriter v1.1.0 h1:N0LHrshF4T39KvI96fn6GT8HEjXRXYNDrDjKFDB7RIY=
|
||||
github.com/olekukonko/tablewriter v1.1.0/go.mod h1:5c+EBPeSqvXnLLgkm9isDdzR3wjfBkHR9Nhfp3NWrzo=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
|
||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||
go.opentelemetry.io/otel v1.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo=
|
||||
go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo=
|
||||
go.opentelemetry.io/otel/metric v1.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI=
|
||||
go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucgoDw=
|
||||
go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI=
|
||||
go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU=
|
||||
golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys=
|
||||
golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=
|
||||
golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
|
||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
|
||||
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
|
||||
go.opentelemetry.io/otel v1.38.0 h1:RkfdswUDRimDg0m2Az18RKOsnI8UDzppJAtj01/Ymk8=
|
||||
go.opentelemetry.io/otel v1.38.0/go.mod h1:zcmtmQ1+YmQM9wrNsTGV/q/uyusom3P8RxwExxkZhjM=
|
||||
go.opentelemetry.io/otel/metric v1.38.0 h1:Kl6lzIYGAh5M159u9NgiRkmoMKjvbsKtYRwgfrA6WpA=
|
||||
go.opentelemetry.io/otel/metric v1.38.0/go.mod h1:kB5n/QoRM8YwmUahxvI3bO34eVtQf2i4utNVLr9gEmI=
|
||||
go.opentelemetry.io/otel/sdk v1.38.0 h1:l48sr5YbNf2hpCUj/FoGhW9yDkl+Ma+LrVl8qaM5b+E=
|
||||
go.opentelemetry.io/otel/sdk v1.38.0/go.mod h1:ghmNdGlVemJI3+ZB5iDEuk4bWA3GkTpW+DOoZMYBVVg=
|
||||
go.opentelemetry.io/otel/trace v1.38.0 h1:Fxk5bKrDZJUH+AMyyIXGcFAPah0oRcT+LuNtJrmcNLE=
|
||||
go.opentelemetry.io/otel/trace v1.38.0/go.mod h1:j1P9ivuFsTceSWe1oY+EeW3sc+Pp42sO++GHkg4wwhs=
|
||||
golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY=
|
||||
golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds=
|
||||
golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
|
||||
golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng=
|
||||
golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
||||
@ -1,13 +1,10 @@
|
||||
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"
|
||||
)
|
||||
|
||||
|
||||
@ -9,6 +9,7 @@ package v1
|
||||
import "github.com/gogf/gf/v2/frame/g"
|
||||
|
||||
type (
|
||||
// CreateReq add title.
|
||||
CreateReq struct {
|
||||
g.Meta `path:"/article/create" method:"post" tags:"ArticleService"`
|
||||
Title string `v:"required"`
|
||||
|
||||
@ -9,6 +9,7 @@ import (
|
||||
"github.com/gogf/gf/cmd/gf/v2/internal/cmd/testdata/genctrl/api/article/v1"
|
||||
)
|
||||
|
||||
// Create add title.
|
||||
func (c *ControllerV1) Create(ctx context.Context, req *v1.CreateReq) (res *v1.CreateRes, err error) {
|
||||
return nil, gerror.NewCode(gcode.CodeNotImplemented)
|
||||
}
|
||||
|
||||
@ -12,11 +12,11 @@ import (
|
||||
// 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.
|
||||
Id any // User ID
|
||||
Passport any // User Passport
|
||||
Password any // User Password
|
||||
Nickname any // User Nickname
|
||||
Score any // Total score amount.
|
||||
CreateAt *gtime.Time // Created Time
|
||||
UpdateAt *gtime.Time // Updated Time
|
||||
}
|
||||
|
||||
@ -12,11 +12,11 @@ import (
|
||||
// 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.
|
||||
Id any // User ID
|
||||
Passport any // User Passport
|
||||
Password any // User Password
|
||||
Nickname any // User Nickname
|
||||
Score any // Total score amount.
|
||||
CreateAt *gtime.Time // Created Time
|
||||
UpdateAt *gtime.Time // Updated Time
|
||||
}
|
||||
|
||||
@ -12,10 +12,10 @@ import (
|
||||
// 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{} //
|
||||
Passport interface{} //
|
||||
Password interface{} //
|
||||
Nickname interface{} //
|
||||
Id any //
|
||||
Passport any //
|
||||
Password any //
|
||||
Nickname any //
|
||||
CreatedAt *gtime.Time //
|
||||
UpdatedAt *gtime.Time //
|
||||
}
|
||||
|
||||
@ -12,11 +12,11 @@ import (
|
||||
// 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.
|
||||
Id any // User ID
|
||||
Passport any // User Passport
|
||||
Password any // User Password
|
||||
Nickname any // User Nickname
|
||||
Score any // Total score amount.
|
||||
CreateAt *gtime.Time // Created Time
|
||||
UpdateAt *gtime.Time // Updated Time
|
||||
}
|
||||
|
||||
@ -1,44 +1,54 @@
|
||||
CREATE TABLE `single_table` (
|
||||
`id` int unsigned NOT NULL AUTO_INCREMENT COMMENT 'User ID',
|
||||
`passport` varchar(45) NOT NULL COMMENT 'User Passport',
|
||||
`password` varchar(45) NOT NULL COMMENT 'User Password',
|
||||
`nickname` varchar(45) NOT NULL COMMENT 'User Nickname',
|
||||
`score` decimal(10,2) unsigned DEFAULT NULL COMMENT 'Total score amount.',
|
||||
CREATE TABLE `single_table`
|
||||
(
|
||||
`id` int unsigned NOT NULL AUTO_INCREMENT COMMENT 'User ID',
|
||||
`passport` varchar(45) NOT NULL COMMENT 'User Passport',
|
||||
`password` varchar(45) NOT NULL COMMENT 'User Password',
|
||||
`nickname` varchar(45) NOT NULL COMMENT 'User Nickname',
|
||||
`score` decimal(10, 2) unsigned DEFAULT NULL COMMENT 'Total score amount.',
|
||||
`create_at` datetime DEFAULT NULL COMMENT 'Created Time',
|
||||
`update_at` datetime DEFAULT NULL COMMENT 'Updated Time',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
|
||||
CREATE TABLE `users_0001` (
|
||||
`id` int unsigned NOT NULL AUTO_INCREMENT COMMENT 'User ID',
|
||||
`passport` varchar(45) NOT NULL COMMENT 'User Passport',
|
||||
`password` varchar(45) NOT NULL COMMENT 'User Password',
|
||||
`nickname` varchar(45) NOT NULL COMMENT 'User Nickname',
|
||||
`score` decimal(10,2) unsigned DEFAULT NULL COMMENT 'Total score amount.',
|
||||
CREATE TABLE `users_0001`
|
||||
(
|
||||
`id` int unsigned NOT NULL AUTO_INCREMENT COMMENT 'User ID',
|
||||
`passport` varchar(45) NOT NULL COMMENT 'User Passport',
|
||||
`password` varchar(45) NOT NULL COMMENT 'User Password',
|
||||
`nickname` varchar(45) NOT NULL COMMENT 'User Nickname',
|
||||
`score` decimal(10, 2) unsigned DEFAULT NULL COMMENT 'Total score amount.',
|
||||
`create_at` datetime DEFAULT NULL COMMENT 'Created Time',
|
||||
`update_at` datetime DEFAULT NULL COMMENT 'Updated Time',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
CREATE TABLE `users_0002` (
|
||||
`id` int unsigned NOT NULL AUTO_INCREMENT COMMENT 'User ID',
|
||||
`passport` varchar(45) NOT NULL COMMENT 'User Passport',
|
||||
`password` varchar(45) NOT NULL COMMENT 'User Password',
|
||||
`nickname` varchar(45) NOT NULL COMMENT 'User Nickname',
|
||||
`score` decimal(10,2) unsigned DEFAULT NULL COMMENT 'Total score amount.',
|
||||
CREATE TABLE `users_0002`
|
||||
(
|
||||
`id` int unsigned NOT NULL AUTO_INCREMENT COMMENT 'User ID',
|
||||
`passport` varchar(45) NOT NULL COMMENT 'User Passport',
|
||||
`password` varchar(45) NOT NULL COMMENT 'User Password',
|
||||
`nickname` varchar(45) NOT NULL COMMENT 'User Nickname',
|
||||
`score` decimal(10, 2) unsigned DEFAULT NULL COMMENT 'Total score amount.',
|
||||
`create_at` datetime DEFAULT NULL COMMENT 'Created Time',
|
||||
`update_at` datetime DEFAULT NULL COMMENT 'Updated Time',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
|
||||
CREATE TABLE `users_0003` (
|
||||
`id` int unsigned NOT NULL AUTO_INCREMENT COMMENT 'User ID',
|
||||
`passport` varchar(45) NOT NULL COMMENT 'User Passport',
|
||||
`password` varchar(45) NOT NULL COMMENT 'User Password',
|
||||
`nickname` varchar(45) NOT NULL COMMENT 'User Nickname',
|
||||
`score` decimal(10,2) unsigned DEFAULT NULL COMMENT 'Total score amount.',
|
||||
CREATE TABLE `orders_0001`
|
||||
(
|
||||
`id` int unsigned NOT NULL AUTO_INCREMENT COMMENT 'ORDER ID',
|
||||
`amount` decimal(10, 2) unsigned DEFAULT NULL COMMENT 'Total amount.',
|
||||
`create_at` datetime DEFAULT NULL COMMENT 'Created Time',
|
||||
`update_at` datetime DEFAULT NULL COMMENT 'Updated Time',
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
CREATE TABLE `orders_0002`
|
||||
(
|
||||
`id` int unsigned NOT NULL AUTO_INCREMENT COMMENT 'ORDER ID',
|
||||
`amount` decimal(10, 2) unsigned DEFAULT NULL COMMENT 'Total amount.',
|
||||
`create_at` datetime DEFAULT NULL COMMENT 'Created Time',
|
||||
`update_at` datetime DEFAULT NULL COMMENT 'Updated Time',
|
||||
PRIMARY KEY (`id`)
|
||||
|
||||
@ -63,14 +63,14 @@ func (s *sArticle) T3(ctx context.Context, b *gdbas.Model) (c, d *gdbas.Model, e
|
||||
* random comment
|
||||
*/
|
||||
|
||||
// func (s *sArticle) T4(i interface{}) interface{}
|
||||
// func (s *sArticle) T4(i any) any
|
||||
// # $ % ^ & * ( ) _ + - = { } | [ ] \ : " ; ' < > ? , . /
|
||||
func (s *sArticle) T4(i interface{}) interface{} {
|
||||
func (s *sArticle) T4(i any) any {
|
||||
return nil
|
||||
}
|
||||
|
||||
/**
|
||||
* func (s *sArticle) T4(i interface{}) interface{} {
|
||||
* func (s *sArticle) T4(i any) any {
|
||||
* return nil
|
||||
* }
|
||||
*/
|
||||
|
||||
@ -36,9 +36,9 @@ type (
|
||||
* @author oldme
|
||||
*/
|
||||
T3(ctx context.Context, b *gdbas.Model) (c *gdbas.Model, d *gdbas.Model, err error)
|
||||
// func (s *sArticle) T4(i interface{}) interface{}
|
||||
// func (s *sArticle) T4(i any) any
|
||||
// # $ % ^ & * ( ) _ + - = { } | [ ] \ : " ; ' < > ? , . /
|
||||
T4(i interface{}) interface{}
|
||||
T4(i any) any
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@ -12,11 +12,11 @@ import (
|
||||
// User1 is the golang structure of table user1 for DAO operations like Where/Data.
|
||||
type User1 struct {
|
||||
g.Meta `orm:"table:user1, do:true"`
|
||||
Id interface{} // User ID
|
||||
Passport interface{} // User Passport
|
||||
Password interface{} // User Password
|
||||
Nickname interface{} // User Nickname
|
||||
Score interface{} // Total score amount.
|
||||
Id any // User ID
|
||||
Passport any // User Passport
|
||||
Password any // User Password
|
||||
Nickname any // User Nickname
|
||||
Score any // Total score amount.
|
||||
CreateAt *gtime.Time // Created Time
|
||||
UpdateAt *gtime.Time // Updated Time
|
||||
}
|
||||
|
||||
@ -12,11 +12,11 @@ import (
|
||||
// User2 is the golang structure of table user2 for DAO operations like Where/Data.
|
||||
type User2 struct {
|
||||
g.Meta `orm:"table:user2, do:true"`
|
||||
Id interface{} // User ID
|
||||
Passport interface{} // User Passport
|
||||
Password interface{} // User Password
|
||||
Nickname interface{} // User Nickname
|
||||
Score interface{} // Total score amount.
|
||||
Id any // User ID
|
||||
Passport any // User Passport
|
||||
Password any // User Password
|
||||
Nickname any // User Nickname
|
||||
Score any // Total score amount.
|
||||
CreateAt *gtime.Time // Created Time
|
||||
UpdateAt *gtime.Time // Updated Time
|
||||
}
|
||||
|
||||
@ -12,11 +12,11 @@ import (
|
||||
// User1 is the golang structure of table user1 for DAO operations like Where/Data.
|
||||
type User1 struct {
|
||||
g.Meta `orm:"table:user1, do:true"`
|
||||
Id interface{} // User ID
|
||||
Passport interface{} // User Passport
|
||||
Password interface{} // User Password
|
||||
Nickname interface{} // User Nickname
|
||||
Score interface{} // Total score amount.
|
||||
Id any // User ID
|
||||
Passport any // User Passport
|
||||
Password any // User Password
|
||||
Nickname any // User Nickname
|
||||
Score any // Total score amount.
|
||||
CreateAt *gtime.Time // Created Time
|
||||
UpdateAt *gtime.Time // Updated Time
|
||||
}
|
||||
|
||||
@ -12,11 +12,11 @@ import (
|
||||
// User2 is the golang structure of table user2 for DAO operations like Where/Data.
|
||||
type User2 struct {
|
||||
g.Meta `orm:"table:user2, do:true"`
|
||||
Id interface{} // User ID
|
||||
Passport interface{} // User Passport
|
||||
Password interface{} // User Password
|
||||
Nickname interface{} // User Nickname
|
||||
Score interface{} // Total score amount.
|
||||
Id any // User ID
|
||||
Passport any // User Passport
|
||||
Password any // User Password
|
||||
Nickname any // User Nickname
|
||||
Score any // Total score amount.
|
||||
CreateAt *gtime.Time // Created Time
|
||||
UpdateAt *gtime.Time // Updated Time
|
||||
}
|
||||
|
||||
@ -12,11 +12,11 @@ import (
|
||||
// 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
|
||||
ParentId interface{} //
|
||||
Passport interface{} // User Passport
|
||||
PassWord interface{} // User Password
|
||||
Nickname2 interface{} // User Nickname
|
||||
Id any // User ID
|
||||
ParentId any //
|
||||
Passport any // User Passport
|
||||
PassWord any // User Password
|
||||
Nickname2 any // User Nickname
|
||||
CreateAt *gtime.Time // Created Time
|
||||
UpdateAt *gtime.Time // Updated Time
|
||||
}
|
||||
|
||||
23
cmd/gf/internal/cmd/testdata/issue/4330/issue4330_double.proto
vendored
Normal file
23
cmd/gf/internal/cmd/testdata/issue/4330/issue4330_double.proto
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
// ==========================================================================
|
||||
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
// ==========================================================================
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package pbentity;
|
||||
|
||||
option go_package = "github.com/gogf/gf/cmd/gf/v2/internal/cmd/api/pbentity";
|
||||
|
||||
import "google/protobuf/struct.proto";
|
||||
import "google/protobuf/timestamp.proto";
|
||||
|
||||
message TableUser {
|
||||
uint32 Id = 1; // User ID
|
||||
string Passport = 2; // User Passport
|
||||
string Password = 3; // User Password
|
||||
string Nickname = 4; // User Nickname
|
||||
double Score = 5; // Total score amount.
|
||||
google.protobuf.Value Data = 6; // User Data
|
||||
google.protobuf.Timestamp CreateAt = 7; // Created Time
|
||||
google.protobuf.Timestamp UpdateAt = 8; // Updated Time
|
||||
}
|
||||
23
cmd/gf/internal/cmd/testdata/issue/4330/issue4330_string.proto
vendored
Normal file
23
cmd/gf/internal/cmd/testdata/issue/4330/issue4330_string.proto
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
// ==========================================================================
|
||||
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
// ==========================================================================
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package pbentity;
|
||||
|
||||
option go_package = "github.com/gogf/gf/cmd/gf/v2/internal/cmd/api/pbentity";
|
||||
|
||||
import "google/protobuf/struct.proto";
|
||||
import "google/protobuf/timestamp.proto";
|
||||
|
||||
message TableUser {
|
||||
uint32 Id = 1; // User ID
|
||||
string Passport = 2; // User Passport
|
||||
string Password = 3; // User Password
|
||||
string Nickname = 4; // User Nickname
|
||||
string Score = 5; // Total score amount.
|
||||
google.protobuf.Value Data = 6; // User Data
|
||||
google.protobuf.Timestamp CreateAt = 7; // Created Time
|
||||
google.protobuf.Timestamp UpdateAt = 8; // Updated Time
|
||||
}
|
||||
@ -45,7 +45,7 @@ import (
|
||||
|
||||
"{ImportPath}"
|
||||
)
|
||||
|
||||
{MethodComment}
|
||||
func (c *{CtrlName}) {MethodName}(ctx context.Context, req *{Version}.{MethodName}Req) (res *{Version}.{MethodName}Res, err error) {
|
||||
return nil, gerror.NewCode(gcode.CodeNotImplemented)
|
||||
}
|
||||
@ -66,7 +66,7 @@ import (
|
||||
`
|
||||
|
||||
const TemplateGenCtrlControllerMethodFuncMerge = `
|
||||
|
||||
{MethodComment}
|
||||
func (c *{CtrlName}) {MethodName}(ctx context.Context, req *{Version}.{MethodName}Req) (res *{Version}.{MethodName}Res, err error) {
|
||||
return nil, gerror.NewCode(gcode.CodeNotImplemented)
|
||||
}
|
||||
|
||||
@ -81,7 +81,7 @@ func (i *implementer) {ImplementerName}() {Module}.I{ImplementerName} {
|
||||
|
||||
`
|
||||
|
||||
const TemplateGenCtrlSdkImplementerFunc = `
|
||||
const TemplateGenCtrlSdkImplementerFunc = `{MethodComment}
|
||||
func (i *implementer{ImplementerName}) {MethodName}(ctx context.Context, req *{Version}.{MethodName}Req) (res *{Version}.{MethodName}Res, err error) {
|
||||
err = i.Request(ctx, req, &res)
|
||||
return
|
||||
|
||||
@ -27,7 +27,7 @@ var (
|
||||
// {{.TplTableNameCamelCase}} is a globally accessible object for table {{.TplTableName}} operations.
|
||||
{{.TplTableNameCamelCase}} = {{.TplTableNameCamelLowerCase}}Dao{
|
||||
{{- if .TplTableSharding -}}
|
||||
internal.New{{.TplTableNameCamelCase}}Dao(userShardingHandler),
|
||||
internal.New{{.TplTableNameCamelCase}}Dao({{.TplTableNameCamelLowerCase}}ShardingHandler),
|
||||
{{- else -}}
|
||||
internal.New{{.TplTableNameCamelCase}}Dao(),
|
||||
{{- end -}}
|
||||
@ -35,13 +35,13 @@ var (
|
||||
)
|
||||
|
||||
{{if .TplTableSharding -}}
|
||||
// userShardingHandler is the handler for sharding operations.
|
||||
// {{.TplTableNameCamelLowerCase}}ShardingHandler is the handler for sharding operations.
|
||||
// You can fill this sharding handler with your custom implementation.
|
||||
func userShardingHandler(m *gdb.Model) *gdb.Model {
|
||||
func {{.TplTableNameCamelLowerCase}}ShardingHandler(m *gdb.Model) *gdb.Model {
|
||||
m = m.Sharding(gdb.ShardingConfig{
|
||||
Table: gdb.ShardingTableConfig{
|
||||
Enable: true,
|
||||
Prefix: "",
|
||||
Prefix: "{{.TplTableShardingPrefix}}",
|
||||
// Replace Rule field with your custom sharding rule.
|
||||
// Or you can use "&gdb.DefaultShardingRule{}" for default sharding rule.
|
||||
Rule: nil,
|
||||
|
||||
35
cmd/gf/internal/consts/consts_gen_dao_template_table.go
Normal file
35
cmd/gf/internal/consts/consts_gen_dao_template_table.go
Normal file
@ -0,0 +1,35 @@
|
||||
// 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 consts
|
||||
|
||||
const TemplateGenTableContent = `
|
||||
// =================================================================================
|
||||
// This file is auto-generated by the GoFrame CLI tool. You may modify it as needed.
|
||||
// =================================================================================
|
||||
|
||||
package {{.TplPackageName}}
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/gogf/gf/v2/database/gdb"
|
||||
)
|
||||
|
||||
// {{.TplTableNameCamelCase}} defines the fields of table "{{.TplTableName}}" with their properties.
|
||||
// This map is used internally by GoFrame ORM to understand table structure.
|
||||
var {{.TplTableNameCamelCase}} = map[string]*gdb.TableField{
|
||||
{{.TplTableFields}}
|
||||
}
|
||||
|
||||
// Set{{.TplTableNameCamelCase}}TableFields registers the table fields definition to the database instance.
|
||||
// db: database instance that implements gdb.DB interface.
|
||||
// schema: optional schema/namespace name, especially for databases that support schemas.
|
||||
func Set{{.TplTableNameCamelCase}}TableFields(ctx context.Context, db gdb.DB, schema ...string) error {
|
||||
return db.GetCore().SetTableFields(ctx, "{{.TplTableName}}", {{.TplTableNameCamelCase}}, schema...)
|
||||
}
|
||||
|
||||
`
|
||||
@ -162,8 +162,14 @@ func (s serviceInstall) getGoPathBin() string {
|
||||
func (s serviceInstall) getAvailablePaths() []serviceInstallAvailablePath {
|
||||
var (
|
||||
folderPaths []serviceInstallAvailablePath
|
||||
binaryFileName = "gf" + gfile.Ext(gfile.SelfPath())
|
||||
binaryFileName = "gf"
|
||||
)
|
||||
|
||||
// Windows binary file name suffix.
|
||||
if runtime.GOOS == "windows" {
|
||||
binaryFileName += ".exe"
|
||||
}
|
||||
|
||||
// $GOPATH/bin
|
||||
if goPathBin := s.getGoPathBin(); goPathBin != "" {
|
||||
folderPaths = s.checkAndAppendToAvailablePath(
|
||||
|
||||
@ -51,26 +51,26 @@ func SetHeaderPrint(enabled bool) {
|
||||
}
|
||||
}
|
||||
|
||||
func Print(v ...interface{}) {
|
||||
func Print(v ...any) {
|
||||
logger.Print(ctx, v...)
|
||||
}
|
||||
|
||||
func Printf(format string, v ...interface{}) {
|
||||
func Printf(format string, v ...any) {
|
||||
logger.Printf(ctx, format, v...)
|
||||
}
|
||||
|
||||
func Fatal(v ...interface{}) {
|
||||
func Fatal(v ...any) {
|
||||
logger.Fatal(ctx, v...)
|
||||
}
|
||||
|
||||
func Fatalf(format string, v ...interface{}) {
|
||||
func Fatalf(format string, v ...any) {
|
||||
logger.Fatalf(ctx, format, v...)
|
||||
}
|
||||
|
||||
func Debug(v ...interface{}) {
|
||||
func Debug(v ...any) {
|
||||
logger.Debug(ctx, v...)
|
||||
}
|
||||
|
||||
func Debugf(format string, v ...interface{}) {
|
||||
func Debugf(format string, v ...any) {
|
||||
logger.Debugf(ctx, format, v...)
|
||||
}
|
||||
|
||||
@ -12,12 +12,13 @@ import (
|
||||
|
||||
"golang.org/x/tools/imports"
|
||||
|
||||
"github.com/gogf/gf/cmd/gf/v2/internal/consts"
|
||||
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
|
||||
"github.com/gogf/gf/v2/os/gfile"
|
||||
"github.com/gogf/gf/v2/os/gproc"
|
||||
"github.com/gogf/gf/v2/text/gregex"
|
||||
"github.com/gogf/gf/v2/text/gstr"
|
||||
|
||||
"github.com/gogf/gf/cmd/gf/v2/internal/consts"
|
||||
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
|
||||
)
|
||||
|
||||
// GoFmt formats the source file and adds or removes import statements as necessary.
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user