Compare commits

...

142 Commits

Author SHA1 Message Date
ec6c537def feat(cmd/gf): project template updates for command gf init (#3928) 2024-11-17 10:57:17 +08:00
bcfcda793c chore(errors/gerror): add examples (#3927) 2024-11-16 18:14:40 +08:00
138dea0f3a feat(cmd/gf): change document source from repo gf to gf-site (#3926) 2024-11-15 14:33:23 +08:00
3d4904eb3d feat(net/ghttp): remove Req/Res suffix limitation for input/output parameters of strict router handler (#3848) 2024-11-14 17:58:39 +08:00
955a76cf35 feat: new version v2.8.0 (#3924) 2024-11-14 13:26:23 +08:00
ffa6081471 fix(util/gconv): fix missing minus in string to int64 conversion (#3920) 2024-11-13 23:25:24 +08:00
6baf4338b0 fix(database/gdb): recognize field type tinyint(1) to golang type bool (#3921) 2024-11-13 23:09:01 +08:00
8c6db247b2 chore: readme updates (#3919) 2024-11-13 20:48:02 +08:00
fff2f8a24c build: downgrade fsnotify from v1.8.0 to v1.7.0 to solve data race error (#3916) 2024-11-13 12:22:23 +08:00
475e8bbae0 chore: README.md updates (#3912) 2024-11-12 21:30:46 +08:00
070efecc6e style(gtest/test): improve code (#3891) 2024-11-12 20:20:13 +08:00
a63af5d5f8 build: upgrade fsnotify from v1.7.0 to v1.8.0 to solve occasional ci failure (#3910) 2024-11-12 10:25:39 +08:00
bd2e8408e8 chore: update README.MD (#3911) 2024-11-12 09:25:37 +08:00
6c6fd7902a feat(database/gdb): remove unnecessary blank character requirement in tag for With feature of gdb.Model (#3875) 2024-11-11 21:59:26 +08:00
1b7b536d6c fix(cmd/gf): protoc file comments contain backticks and double quotes, resulting in syntax errors in the generated file of go (#3890) 2024-11-11 21:37:30 +08:00
9cc1cf1b53 fix(cmd/gf): remove dir after process done if given build file parameter is not a file but a dir name (#3908) 2024-11-11 21:32:58 +08:00
76948d93d6 test(drivers/mysql): use asserts function to replace if statement (#3849) 2024-11-11 20:54:57 +08:00
5ba165a3c0 fix(cmd/gf): go back current working directory after gf gen pb (#3895) 2024-11-11 20:42:25 +08:00
f4db846633 fix(contrib/drivers/pgsql): connection fails when postgres database password is empty (#3900) 2024-11-11 20:27:07 +08:00
e7cc2c3d9c chore: update the contributors in README.MD (#3907) 2024-11-06 22:11:23 +08:00
01cd0103e4 fix(net/gclient): Client Clone with allocated header/cookie (#3902) 2024-11-06 22:09:28 +08:00
d1872f17f7 fix(util/gconv): assigned the same value to struct field and its same name field in embedded struct failed (#3905) 2024-11-06 21:12:01 +08:00
e4c4fb591e feat(database/gdb): add Exist support for checking records existance for certain condition (#3854) 2024-10-24 15:29:03 +08:00
656668f444 feat: new version v2.8.0-beta (#3878) 2024-10-24 14:51:03 +08:00
555bb3fa6b feat(net/goai): enhance openapi doc with responses and examples (#3859) 2024-10-21 21:16:45 +08:00
e179e1d4fe fix(database/gdb): unix socket connection support for mysql (#3872) 2024-10-21 09:22:53 +08:00
7dd38a1700 feat(database/gdb): add Raw support for Fields function of gdb.Model (#3873) 2024-10-21 09:22:31 +08:00
b1d875a31f fix(util/gconv): incorrect fuzzy converting logic (#3874) 2024-10-21 09:16:50 +08:00
c18339b1a9 feat(contrib/drivers/pgsql): add InsertIgnore support (#3855) 2024-10-16 07:32:33 +08:00
5288b70567 fix(util/gconv): one parameter to same tag in multiple struct attributes mapping failed (#3822) 2024-10-14 21:34:39 +08:00
4b5f637651 feat(trace): add trace for Custom trace client and provider (#3847) 2024-10-14 21:30:27 +08:00
e3e5c89ba7 fix(os/gcmd): cannot retrieve all args if no subcommand defined for a root command (#3850) 2024-10-10 09:17:34 +08:00
4d29939f87 fix(net/goai): cannot customize OpenAPIv3 type for request parameters (#3845) 2024-10-09 13:15:46 +08:00
ae3ae8b177 test(cmd/gf): add unit testing case generating dao/do/entity files for sqlite in command gen dao (#3808) 2024-10-08 22:06:07 +08:00
7a6889817f feat(encoding/ghtml): add parameter validation for function SpecialCharsMapOrStruct (#3841) 2024-10-08 20:46:06 +08:00
a72a9ff13e fix(container/gtree): deadlock in Map/MapStrAny functions, comments update (#3840) 2024-10-08 20:45:23 +08:00
91884e7c93 fix(database/gdb): remove support of Array/Value/Count operations for result that has multiple record fields (#3839) 2024-10-08 20:42:06 +08:00
7cbc9e8533 test(os/gcache): fix unit testing occasionally failed due to too short expration duration set (#3842) 2024-10-08 13:06:11 +08:00
2301de6e8c fix(util/gutil): invalid empty parameter value check for function GetOrDefaultAny (#3844) 2024-10-08 13:05:59 +08:00
183395f0a0 fix(cmd/gf): gen service error when there's version number at the end of package import path (#3836) 2024-10-05 12:25:43 +08:00
d4fa2c82bf feat(contrib/rpc/grpcx): use grpc.NewClient instead of grpc.Dial (#3684) 2024-09-30 20:41:14 +08:00
459c8ce84e feat(os/gfsnotify): add recursive watching for created subfolders and sub-files under folders that already watched (#3830) 2024-09-30 11:24:27 +08:00
38622f966f refactor(contrib/trace/jaeger): remove trace jaeger, please use the OpenTelemetry SDKs(otlphttp&otlpgrpc) (#3825) 2024-09-29 20:31:16 +08:00
499f755d3a build(deps): bump google.golang.org/grpc from 1.51.0 to 1.56.3 in /contrib/config/polaris (#3831) 2024-09-29 17:06:02 +08:00
3f1439ac4c build(deps): bump google.golang.org/grpc from 1.51.0 to 1.56.3 in /contrib/registry/polaris (#3828) 2024-09-29 15:48:28 +08:00
0ca2ed5979 chore(contrib/config/polaris): upgrade dependent polaris library version to v1.5.8 and go version to v1.21 (#3827) 2024-09-29 11:08:07 +08:00
ee5284a1b2 chore(contrib/registry/polaris): upgrade dependent polaris library version to v1.5.8 and go version v1.21 (#3826) 2024-09-29 10:59:48 +08:00
8e7f1180c4 fix(contrib/drivers/mssql): fix mssql paging sql generate statement error (#3782) 2024-09-29 10:18:34 +08:00
3abb9477c4 ci: fix mssql docker service starting failed (#3824) 2024-09-28 21:46:23 +08:00
ab3fbddfc7 build(go.mod): upgrade minimum required go version from 1.18 to 1.20 (#3688) 2024-09-28 20:58:04 +08:00
55b92151f4 refactor(net/ghttp): enhance ghttp.StartPProfServer (#3555) 2024-09-28 18:10:53 +08:00
9589384b36 refactor(encoding/gjson): change data parameter from type any to []byte (#3542) 2024-09-28 18:10:00 +08:00
cf742233e8 refactor(net/gudp): improve implements (#3491) 2024-09-28 18:08:46 +08:00
1c97b7a982 fix(os/gcache): memory leak for LRU when adding operations more faster than deleting (#3823) 2024-09-28 18:07:11 +08:00
ea09457d84 fix(os/gcmd): argument index calculating error in multilevel command (#3807) 2024-09-28 18:02:34 +08:00
66ee52c96a fix(database/gdb): invalid order by statement generated when multiple order inputs (#3803) 2024-09-28 12:06:22 +08:00
f45f64897a fix(cmd/gf): creating logic.go empty folder when there is no correct logic service (#3815) 2024-09-28 11:28:06 +08:00
8708dc7940 test(drivers/mysql): loose unit testing for transaction (#3819) 2024-09-28 11:19:14 +08:00
79451e4624 fix(net/ghttp&gclient,contrib/rpc/grpcx): remove request and response contents in opentelemetry tracing attributes (#3810) 2024-09-26 09:50:07 +08:00
a716c6bfab feat: new version v2.7.4 (#3809) 2024-09-25 19:53:23 +08:00
5aa321dbde fix(util/gconv): unstable converting when there is an external attribute with the same name as the internal structure (#3799) 2024-09-25 19:22:15 +08:00
3f2b1cb329 feat(database/gdb): add year field type support for ORM operations (#3805) 2024-09-25 16:33:52 +08:00
ab2c3b02ac fix(cmd/gf): table and field names converted to its lower case before CamelCase converting in command gen dao (#3801) 2024-09-25 10:59:00 +08:00
76783fd72b fix(net/gclient): panic when containing @file: parameter value in json post request (#3775) 2024-09-25 10:37:32 +08:00
fsl
a1ce97ec9b feat(contrib/registry/etcd/): add DialTimeout and AutoSyncInterval option (#3698) 2024-09-24 17:01:10 +08:00
c13004e230 fix(database/gdb): support OrderRandom feature in different databases (#3794) 2024-09-24 11:58:34 +08:00
9af8393758 fix(net/goai): change default value of RequestBody.Required from true to false, add required tag support for RequestBody (#3796) 2024-09-24 11:51:53 +08:00
e15b543a5b fix(util/gvalid): retrive empty slice parameter in custom validation rule function failed (#3795) 2024-09-23 19:59:48 +08:00
8a1c97f518 fix(util/gconv): cached field indexes append issue caused incorrect field converting (#3790) 2024-09-23 19:05:32 +08:00
d8e3e9d713 fix(utils/utils_str): recognize '+' as a valid numeric sign (#3778) 2024-09-23 16:45:55 +08:00
777c2e7117 ci: fix mssql docker service failed in ci (#3792) 2024-09-23 11:50:48 +08:00
c4327f62e7 fix(net/ghttp): server shutdown not graceful using admin api /debug/admin/shutdown (#3777) 2024-09-19 14:10:16 +08:00
fd33dcb97b ci: add go version 1.23 support (#3733) 2024-09-19 10:38:20 +08:00
d8b06d056e fix(os/gcache): a little memory leak for removed timestamp key (#3779) 2024-09-14 11:05:47 +08:00
e186eab1a5 fix(debug/gdebug): incorrect package name handling in function CallerPackage (#3771) 2024-09-13 16:51:39 +08:00
6a99931798 fix(database/gdb): #3755 error parsing database link without port number (#3772) 2024-09-13 16:50:59 +08:00
4ee5bf5c45 fix(database/gdb): #3754 FieldsEx feature conflicts with soft time feature in soft time fields updating (#3773) 2024-09-13 16:50:38 +08:00
e4669387b5 fix(encoding/gxml): XML special character encoding error (#3740) 2024-09-13 10:37:15 +08:00
0e471eab38 fix(util/gconv): #3764 fix bool converting issue (#3765) 2024-09-12 21:59:38 +08:00
3d63ebfe81 fix(net/ghttp): skip common response body in common response handler for streaming content types (#3762) 2024-09-12 17:50:43 +08:00
9b318bb57f perf(database/gdb): performance improvement for struct scanning when with feature disabled (#3677) 2024-09-12 15:38:18 +08:00
6b3fb607cf fix(net/goai): fix openapi miss required tag of BizRequest when set CommonRequest (#3724) 2024-09-10 18:00:21 +08:00
bb9a3b83eb feat(database/gdb): add time field type for value converting for/from field (#3712) 2024-09-10 17:51:22 +08:00
baea1c7a7a feat: version v2.7.3 (#3763) 2024-09-09 16:39:02 +08:00
1b4ebc0812 perf(util/gconv): add cache logic to enhance performance (#3673) 2024-09-09 16:17:01 +08:00
803cb5a0bc fix(contrib/drivers/pgsql): fix insert error when data struct field has nil in PgSQL (#3679) 2024-09-09 16:16:20 +08:00
448df14860 fix(util/gconv): #3731 map type name mismatch in switch case statement (#3732) 2024-09-09 14:54:40 +08:00
467a5c1093 fix(contrib/drivers/pgsql): #3671 fix invalid pgsql insert json type (#3742) 2024-09-09 14:32:14 +08:00
26d2a98fb1 refactor(nacos-registry): use official nacos sdk instead of the third-party nacos sdk (#3745) 2024-09-09 14:27:21 +08:00
6e5ce98d23 fix(database/gdb): fix #3649 when constructing query param, gdb.Row value not directly write to Buffer (#3718) 2024-08-14 21:16:17 +08:00
a6c361dcf7 fix(os/gtime): fix gtime.Value() when time only, add time only example (#3714) 2024-08-14 21:00:39 +08:00
dc8bb809a8 fix(contrib/registry/file/v2): fix the panic caused by channel closing after resolver closed (#3691) 2024-08-14 20:44:05 +08:00
9143b26182 fix(contrib/nosql/redis): missing err nil check in function ScriptExists (#3713) 2024-07-29 20:32:59 +08:00
fsl
cd2d51ea30 build: bump google.golang.org/protobuf to v1.33.0 (#3697) 2024-07-24 19:27:28 +08:00
fsl
144ad5f263 ci: add Scorecard workflow (#3702) 2024-07-24 19:24:14 +08:00
4fdafa4517 feat(cmd/gf): project templates update for command gf init (#3704) 2024-07-24 19:15:54 +08:00
ba322ba0ac fix(cmd/gf): fix command gf up with -u option upgrading packages indirectly required would fail with higher version of go required (#3687) 2024-07-17 20:21:26 +08:00
559ae0e77e chore(.github/template): update document for github pull requests (#3666) 2024-07-02 20:56:20 +08:00
3e54839aa8 refractor(container/gtree): refactor code with gods package for rbtree (#3655) 2024-07-02 20:36:43 +08:00
2565bb3d07 refractor(container/gtree): improve function order of btree (#3656) 2024-07-02 20:35:53 +08:00
54423b6d84 refractor(container/gtree): refactor code with gods package for avltree (#3647) 2024-07-01 20:37:11 +08:00
c3cfc01cf6 refactor(container/gring): mark deprecated, package container/gring will not be maintained in future (#3665) 2024-06-27 21:12:51 +08:00
31a6ae2a19 fix(cmd/gf): remove dm driver for command gen dao as it causes building failed for some platforms (#3667) 2024-06-27 21:12:06 +08:00
b11caba5b0 version v2.7.2 (#3663) 2024-06-26 10:08:04 +08:00
8824b8b0fe os/gcron: add graceful shutdown support (#3625) 2024-06-25 21:13:51 +08:00
f8272bc5f4 database/gdb: remove duplicated SQL records in tracing events (#3659) 2024-06-25 21:11:36 +08:00
e8a2629b19 net/goai: fix: #3660, support multiple file upload parameters for OpenAPIv3 (#3662) 2024-06-25 21:01:58 +08:00
dba6c08548 net/ghttp: fix Content-Type for jsonp response from application/json to application/javascript (#3651) 2024-06-24 21:37:49 +08:00
7d464d4de2 net/ghttp: fix args issue for forkRestartProcess in graceful restarting of ghttp.Server (#3661) 2024-06-24 20:53:37 +08:00
4abb32e11b contrib/drivers/pgsql: support slice type to insert into array for pgsql (#3645) 2024-06-18 19:36:07 +08:00
74d0945fa1 gerror: fix #3633 Is performs the same as errors.Is from go stdlib (#3640) 2024-06-13 21:55:32 +08:00
ffbe9a7197 container/gtree: refactor code with gods package (#3595) 2024-06-13 21:26:53 +08:00
fba878f47a net/ghttp: update error message for duplicated routes registering (#3603) 2024-06-13 21:16:11 +08:00
88f188d0f9 cmd/gf: use automatic generating package names for go files of dao/do/entity instead of constant package names (#3639) 2024-06-13 21:13:05 +08:00
2ccbb02c71 fix: #3613 ignore automatic handling for creating/updating time if it has been specified (#3615) 2024-06-12 21:41:44 +08:00
01408f1a87 cmd/gf: delete binary file when gf run end process (#3628) 2024-06-12 21:32:24 +08:00
dea0ffcfb3 cmd/gf: add command gf doc (#3634) 2024-06-12 21:29:56 +08:00
d5825ab51c drivers/pgsql:pgsql returning id should use quotation marks,when primary key is capital (#3638) 2024-06-12 21:22:39 +08:00
753965b9a9 example: password encrypt-decrypt for database using custom implement driver (#3610) 2024-06-04 22:04:36 +08:00
ee211dbdac cmd/gf: improve gf gen ctrl using ast (#3616) 2024-06-04 21:13:23 +08:00
4d916ae73e os/gres: fix #3611 add custom prefix / support for resource packing (#3621) 2024-06-04 20:38:59 +08:00
59a775aad4 util/gvalid: add 171 number support for virtual phone number validation (#3622) 2024-06-04 20:36:28 +08:00
e3a00d7f56 cmd/gf: fix missing configuration file support for cli command pack/run/tpl/up (#3629) 2024-06-04 19:59:05 +08:00
bd8d046b83 cmd/gf: add DaMeng database driver support (#3606) 2024-05-30 21:20:46 +08:00
57583a98bc .github/workflows: remove code coverage report for folder example (#3608) 2024-05-30 21:05:35 +08:00
f8175e7113 drivers/mssql: change driver from github.com/denisenkom/go-mssqldb to github.com/microsoft/go-mssqldb (#3612) 2024-05-30 20:58:51 +08:00
6b84a37794 .github/workflows: fix warning info from node16 on timezone setting (#3614) 2024-05-30 20:55:06 +08:00
457f7abcf5 contrib/drivers: add README.zh_CN.MD (#3604) 2024-05-27 21:02:02 +08:00
9e9e42b45c cmd/gf: test gen ctrl comments (#3575) 2024-05-27 20:42:26 +08:00
8f4d5f7d74 cmd/gf: refactor gf gen service with AST (#3488) 2024-05-27 20:41:05 +08:00
b675d01418 database/gdb: add unscoped tag support for orm struct (#3464) 2024-05-22 21:52:21 +08:00
17385eeaef database/gdb: fix confusing error message in Insert/Update operations when table not exist or the table contains no fields (#3553) 2024-05-22 21:26:53 +08:00
23df83cb0b database/gdb: fix deadlock when orm operations perform in cache function from gcache (#3585) 2024-05-22 21:14:43 +08:00
2e471662f4 os/gcfg: fix file searching issue always returning the configuration file of pwd (#3592) 2024-05-22 21:14:16 +08:00
1e8f4287af contrib/registry/zookeeper: fix invalid searching prefix (#3598) 2024-05-22 21:12:21 +08:00
21c83670d6 os/gtime: fixed gtime ci fail (#3596) 2024-05-22 20:45:39 +08:00
1b23bf495a container/gmap&gset: fix deadlock when removing values during iterating (#3572) 2024-05-21 22:07:28 +08:00
15b60462a2 driver/pgsql: optimize regex for version matching (#3583) 2024-05-21 21:51:43 +08:00
1455440efa os/gcfg: fix gcfg adaptfile dogetfilepath (#3587) 2024-05-20 20:23:38 +08:00
737da954a0 util/gconv: remove unnecessary logic for function doScanList (#3588) 2024-05-20 19:42:51 +08:00
a9a0785252 util/gconv: refactor code unit testing (#3591) 2024-05-20 19:40:30 +08:00
d5561aa323 cmd/gf: add gf init app/mono-app -a (#3550) 2024-05-15 20:25:43 +08:00
484 changed files with 16523 additions and 13788 deletions

View File

@ -1,22 +1,44 @@
**Please ensure you adhere to every item in this list.**
+ The PR title is formatted as follows: `os/gtime: fixed time zone issues`
+ The package name goes before the colon
+ The PR title is formatted as follows: `<type>[optional scope]: <description>` For example, `fix(os/gtime): fix time zone issue`
+ `<type>` is mandatory and can be one of `fix`, `feat`, `build`, `ci`, `docs`, `style`, `refactor`, `perf`, `test`, `chore`
+ fix: Used when a bug has been fixed.
+ feat: Used when a new feature has been added.
+ build: Used for modifications to the project build system, such as changes to dependencies, external interfaces, or upgrading Node version.
+ ci: Used for modifications to continuous integration processes, such as changes to Travis, Jenkins workflow configurations.
+ docs: Used for modifications to documentation, such as changes to README files, API documentation, etc.
+ style: Used for changes to code style, such as adjustments to indentation, spaces, blank lines, etc.
+ refactor: Used for code refactoring, such as changes to code structure, variable names, function names, without altering functionality.
+ perf: Used for performance optimization, such as improving code performance, reducing memory usage, etc.
+ test: Used for modifications to test cases, such as adding, deleting, or modifying test cases for code.
+ chore: Used for modifications to non-business-related code, such as changes to build processes or tool configurations.
+ After `<type>`, specify the affected package name or scope in parentheses, for example, `(os/gtime)`.
+ The part after the colon uses the verb tense + phrase that completes the blank in
+ Lowercase verb after the colon
+ No trailing period
+ Keep the title as short as possible. ideally under 76 characters or shorter
+ Title not Markdown
+ [Reference Documentation](https://www.conventionalcommits.org/en/v1.0.0/)
+ If there is a corresponding issue, add either `Fixes #1234` or `Updates #1234`
(the latter if this is not a complete fix) to this comment
+ Delete these instructions once you have read and applied them
**提交前请遵守每个事项,感谢!**
+ PR 标题格式如下:`os/gtime: fixed time zone issues`
+ 冒号前是包名
+ PR 标题格式如下:`<类型>[可选 范围]: <描述>` 例如 `fix(os/gtime): fix time zone issue`
+ `<类型>`是必须的,可以是 `fix`、`feat`、`build`、`ci`、`docs`、`style`、`refactor`、`perf`、`test`、`chore` 中的一个
+ fix: 用于修复了一个 bug
+ feat: 用于新增了一个功能
+ build: 用于修改项目构建系统,例如修改依赖库、外部接口或者升级 Node 版本等
+ ci: 用于修改持续集成流程,例如修改 Travis、Jenkins 等工作流配置
+ docs: 用于修改文档,例如修改 README 文件、API 文档等
+ style: 用于修改代码的样式,例如调整缩进、空格、空行等
+ refactor: 用于重构代码,例如修改代码结构、变量名、函数名等但不修改功能逻辑
+ perf: 用于优化性能,例如提升代码的性能、减少内存占用等
+ test: 用于修改测试用例,例如添加、删除、修改代码的测试用例等
+ chore: 用于对非业务性代码进行修改,例如修改构建流程或者工具配置等
+ `<类型>`后在括号中填写受影响的包名或范围,例如 `(os/gtime)`
+ 冒号后使用动词时态 + 短语
+ 冒号后的动词小写
+ 不要有结尾句号
+ 标题尽量保持简短,最好在 76 个字符或更短
+ 标题不要使用 Markdown
+ [参考文档](https://www.conventionalcommits.org/zh-hans/v1.0.0/)
+ 如果有对应的 issue请在此评论中添加 `Fixes #1234`,如果不是完全修复则添加 `Updates #1234`
+ 应用这些规则后删除所有的说明

View File

@ -7,24 +7,25 @@ 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
if [[ $file =~ "/testdata/" ]]; then
echo "ignore testdata path $file"
continue 1
fi
# package kuhecm needs golang >= v1.19
# package kuhecm was moved to sub ci procedure.
if [ "kubecm" = $(basename $dirpath) ]; then
continue 1
if ! go version|grep -qE "go1.19|go1.[2-9][0-9]"; then
echo "ignore kubecm as go version: $(go version)"
continue 1
fi
fi
# package consul needs golang >= v1.19
if [ "consul" = $(basename $dirpath) ]; then
continue 1
if ! go version|grep -qE "go1.19|go1.[2-9][0-9]"; then
if ! go version|grep -qE "go1.[2-9][0-9]"; then
echo "ignore consul as go version: $(go version)"
continue 1
fi
@ -32,7 +33,7 @@ for file in `find . -name go.mod`; do
# package etcd needs golang >= v1.19
if [ "etcd" = $(basename $dirpath) ]; then
if ! go version|grep -qE "go1.19|go1.[2-9][0-9]"; then
if ! go version|grep -qE "go1.[2-9][0-9]"; then
echo "ignore etcd as go version: $(go version)"
continue 1
fi
@ -40,7 +41,7 @@ for file in `find . -name go.mod`; do
# package polaris needs golang >= v1.19
if [ "polaris" = $(basename $dirpath) ]; then
if ! go version|grep -qE "go1.19|go1.[2-9][0-9]"; then
if ! go version|grep -qE "go1.[2-9][0-9]"; then
echo "ignore polaris as go version: $(go version)"
continue 1
fi
@ -52,6 +53,12 @@ for file in `find . -name go.mod`; do
echo "ignore example as go version: $(go version)"
continue 1
fi
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
# package otlpgrpc needs golang >= v1.20

View File

@ -32,7 +32,7 @@ env:
jobs:
code-test:
runs-on: ubuntu-latest
runs-on: ubuntu-20.04
# Service containers to run with `code-test`
services:
@ -58,6 +58,11 @@ jobs:
- 6379:6379
# MySQL backend server.
# docker run -d --name mysql \
# -p 3306:3306 \
# -e MYSQL_DATABASE=test \
# -e MYSQL_ROOT_PASSWORD=12345678 \
# loads/mysql:5.7
mysql:
image: loads/mysql:5.7
env:
@ -185,13 +190,14 @@ jobs:
strategy:
matrix:
go-version: [ "1.18", "1.19", "1.20", "1.21", "1.22" ]
go-version: [ "1.20", "1.21", "1.22", "1.23" ]
goarch: [ "386", "amd64" ]
steps:
# TODO: szenius/set-timezone update to node16
# sudo ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
- name: Setup Timezone
uses: szenius/set-timezone@v1.1
uses: szenius/set-timezone@v2.0
with:
timezoneLinux: "Asia/Shanghai"
@ -214,7 +220,19 @@ jobs:
uses: actions/setup-go@v5
with:
go-version: ${{ matrix.go-version }}
cache-dependency-path: '**/go.sum'
cache-dependency-path: '**/go.sum'
- name: Install Protoc
uses: arduino/setup-protoc@v2
with:
version: "23.x"
repo-token: ${{ secrets.GITHUB_TOKEN }}
- name: Install the protocol compiler plugins for Go
run: |
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest
export PATH="$PATH:$(go env GOPATH)/bin"
- name: Before Script
run: bash .github/workflows/before_script.sh

View File

@ -9,7 +9,7 @@ for file in `find . -name go.mod`; do
# package kuhecm needs golang >= v1.19
if [ "kubecm" = $(basename $dirpath) ]; then
if ! go version|grep -qE "go1.19|go1.[2-9][0-9]"; then
if ! go version|grep -qE "go1.[2-9][0-9]"; then
echo "ignore kubecm as go version: $(go version)"
continue 1
fi

View File

@ -37,12 +37,12 @@ jobs:
strategy:
matrix:
go-version: [ "1.18", "1.19", "1.20", "1.22" ]
go-version: [ "1.20", "1.21", "1.22", "1.23" ]
goarch: [ "386", "amd64" ]
steps:
- name: Setup Timezone
uses: szenius/set-timezone@v1.1
uses: szenius/set-timezone@v2.0
with:
timezoneLinux: "Asia/Shanghai"

View File

@ -12,17 +12,17 @@ jobs:
name: Deploy to GitHub Pages
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
with:
ref: doc-build
- uses: actions/setup-node@v3
- uses: actions/setup-node@v4
with:
node-version: 18
cache: npm
- name: Set Up Golang Environment
uses: actions/setup-go@v4
uses: actions/setup-go@v5
with:
go-version: 1.20.4
go-version: 1.22.5
cache: false
- name: download goframe docs
run: ./download.sh
@ -31,7 +31,7 @@ jobs:
- name: Build website
run: npm run build
- name: Deploy to GitHub Pages
uses: peaceiris/actions-gh-pages@v3
uses: peaceiris/actions-gh-pages@v4
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./build

View File

@ -14,7 +14,7 @@ jobs:
- name: Checkout source code
uses: actions/checkout@v4
- name: Mirror GitHub to Gitee
uses: Yikun/hub-mirror-action@v1.3
uses: Yikun/hub-mirror-action@v1.4
with:
src: github/gogf
dst: gitee/johng

View File

@ -36,7 +36,7 @@ jobs:
golangci:
strategy:
matrix:
go-version: [ '1.18','1.19','1.20','1.21.4','1.22' ]
go-version: [ '1.20','1.21.4','1.22', '1.23' ]
name: golangci-lint
runs-on: ubuntu-latest
steps:
@ -47,8 +47,8 @@ jobs:
with:
go-version: ${{ matrix.go-version }}
- name: golangci-lint
uses: golangci/golangci-lint-action@v4
uses: golangci/golangci-lint-action@v6
with:
# Required: the version of golangci-lint is required and must be specified without patch version: we always use the latest patch version.
version: v1.56.2
version: v1.60.1
args: --timeout 3m0s

View File

@ -21,7 +21,7 @@ jobs:
- name: Set Up Golang Environment
uses: actions/setup-go@v5
with:
go-version: 1.20.8
go-version: 1.22.5
- name: Build CLI Binary
run: |

53
.github/workflows/sonarcloud.yaml vendored Normal file
View File

@ -0,0 +1,53 @@
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-all
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@0864cf19026789058feabb7e87baa5f140aac736 # v2.3.1
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

1
.gitignore vendored
View File

@ -14,6 +14,7 @@ bin/
cmd/gf/main
cmd/gf/gf
temp/
example/log
go.work
go.work.sum
!cmd/gf/go.work

View File

@ -38,7 +38,7 @@ linters:
# Custom enable linters we want to use.
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.
- 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
- goconst # Finds repeated strings that could be replaced by a constant
- gocritic # Provides diagnostics that check for bugs, performance and style issues.
@ -125,7 +125,7 @@ linters-settings:
# Checks the number of lines in a function.
# If lower than 0, disable the check.
# Default: 60
lines: 330
lines: 340
# Checks the number of statements in a function.
# If lower than 0, disable the check.
# Default: 40
@ -172,10 +172,6 @@ linters-settings:
# https://golangci-lint.run/usage/linters/#gosimple
gosimple:
# Select the Go version to target.
# Default: 1.13
# Deprecated: use the global `run.go` instead.
go: "1.15"
# Sxxxx checks in https://staticcheck.io/docs/configuration/options/#checks
# Default: ["*"]
checks: [
@ -186,7 +182,7 @@ linters-settings:
govet:
# Report about shadowed variables.
# Default: false
check-shadowing: true
# check-shadowing: true
# Settings per analyzer.
settings:
# Analyzer name, run `go tool vet help` to see all analyzers.
@ -259,10 +255,6 @@ linters-settings:
# https://golangci-lint.run/usage/linters/#staticcheck
staticcheck:
# Select the Go version to target.
# Default: "1.13"
# Deprecated: use the global `run.go` instead.
go: "1.20"
# SAxxxx checks in https://staticcheck.io/docs/configuration/options/#checks
# Default: ["*"]
checks: [ "all","-SA1019","-SA4015","-SA1029","-SA1016","-SA9003","-SA4006","-SA6003" ]

View File

@ -1,7 +1,7 @@
# GoFrame
<div align=center>
<img src="https://goframe.org/statics/image/logo2.png?v=1" width="300"/>
<img src="https://goframe.org/img/logo_full.png" width="300"/>
[![Go Reference](https://pkg.go.dev/badge/github.com/gogf/gf/v2.svg)](https://pkg.go.dev/github.com/gogf/gf/v2)
[![GoFrame CI](https://github.com/gogf/gf/actions/workflows/ci-main.yml/badge.svg)](https://github.com/gogf/gf/actions/workflows/ci-main.yml)
@ -37,6 +37,12 @@
- OpenAPIV3 documentation generating, automatically
- much, much more...ready to explore?
# Documentation
- GoFrame Official Site: [https://goframe.org](https://goframe.org)
- GoDoc API: [https://pkg.go.dev/github.com/gogf/gf/v2](https://pkg.go.dev/github.com/gogf/gf/v2)
# Installation
Enter your repo. directory and execute following command:
@ -56,44 +62,25 @@ go install github.com/gogf/gf/cmd/gf/v2@latest
# Limitation
```
golang version >= 1.18
golang version >= 1.20
```
# Documentation
# Contributors
- Chinese Official Site(中文官网): [https://goframe.org](https://goframe.org/display/gf)
- Chinese Pages Document(中文镜像文档): [https://pages.goframe.org](https://pages.goframe.org)
- Chinese Offline Document(中文离线文档): [https://github.com/gogf/goframe.org-pdf](https://github.com/gogf/goframe.org-pdf)
- GoDoc API: [https://pkg.go.dev/github.com/gogf/gf/v2](https://pkg.go.dev/github.com/gogf/gf/v2)
💖 Thanks all the contributors making GoFrame awesome! [[Contributors](https://github.com/gogf/gf/graphs/contributors)] 💖
<a href="https://github.com/gogf/gf/graphs/contributors">
<img src="https://goframe.org/img/contributors.svg" />
</a>
# License
`GoFrame` is licensed under the [MIT License](LICENSE), 100% free and open-source, forever.
# Part Of Users
- [Tencent](https://www.tencent.com/)
- [ZTE](https://www.zte.com.cn/china/)
- [Ant Financial Services](https://www.antfin.com/)
- [VIVO](https://www.vivo.com/)
- [MedLinker](https://www.medlinker.com/)
- [KuCoin](https://www.kucoin.io/)
- [LeYouJia](https://www.leyoujia.com/)
- [IGG](https://igg.com)
- [37](https://www.37.com)
- [XiMaLaYa](https://www.ximalaya.com)
- [ZYBang](https://www.zybang.com/)
> We list part of the users here, if your company or products are using `GoFrame`, please let us know [here](https://goframe.org/pages/viewpage.action?pageId=1114415).
# Contributors
This project exists thanks to all the people who contribute. [[Contributors](https://github.com/gogf/gf/graphs/contributors)].
<a href="https://github.com/gogf/gf/graphs/contributors"><img src="https://contributors-img.web.app/image?repo=gogf/gf" /></a>
# Donators
If you love `GoFrame`, why not [buy developer a cup of coffee](https://goframe.org/pages/viewpage.action?pageId=1115633)?
If you love `GoFrame`, why not [buy developer a cup of coffee](https://goframe.org/supportus/donate)?
# Sponsors
@ -101,5 +88,5 @@ We appreciate any kind of sponsorship for `GoFrame` development. If you've got s
# Thanks
<a href="https://www.jetbrains.com/?from=GoFrame"><img src="https://goframe.org/download/thumbnails/1114119/jetbrains.png" height="120" alt="JetBrains"/></a>
<a href="https://www.atlassian.com/?from=GoFrame"><img src="https://goframe.org/download/attachments/1114119/atlassian.jpg" height="120" alt="Atlassian"/></a>
<a href="https://www.jetbrains.com/?from=GoFrame"><img src="https://goframe.org/img/jetbrains.png" height="120" alt="JetBrains"/></a>
<a href="https://www.atlassian.com/?from=GoFrame"><img src="https://goframe.org/img/atlassian.jpg" height="120" alt="Atlassian"/></a>

View File

@ -1,5 +1,6 @@
.DEFAULT_GOAL := pack
pack: pack.template-single pack.template-mono
pack: pack.template-single pack.template-mono pack.template-mono-app
pack.template-single:
@rm -fr temp
@ -15,4 +16,21 @@ pack.template-mono:
@cd temp && git clone https://github.com/gogf/template-mono
@rm -fr temp/template-mono/.git
@cd temp && gf pack template-mono ../internal/packed/template-mono.go -n=packed -y
@rm -fr temp
# Note:
# command `sed` only works on MacOS.
# use `grep -irl 'template-single' temp| xargs sed -i'' -e 's/template-single/template-mono-app/g'` on other platforms.
pack.template-mono-app:
@rm -fr temp
@mkdir temp || exit 0
@cd temp && git clone https://github.com/gogf/template-single
@cd temp && mv template-single template-mono-app
@rm -fr temp/template-mono-app/.git
@rm -fr temp/template-mono-app/.gitattributes
@rm -fr temp/template-mono-app/.gitignore
@rm -fr temp/template-mono-app/go.mod
@rm -fr temp/template-mono-app/go.sum
@grep -irl 'template-single' temp| xargs sed -i '' -e 's/template-single/template-mono-app/g'
@cd temp && gf pack template-mono-app ../internal/packed/template-mono-app.go -n=packed -y
@rm -fr temp

View File

@ -73,7 +73,7 @@ func (c *Command) Run(ctx context.Context) {
func GetCommand(ctx context.Context) (*Command, error) {
root, err := gcmd.NewFromObject(cmd.GF)
if err != nil {
panic(err)
return nil, err
}
err = root.AddObject(
cmd.Up,
@ -88,6 +88,7 @@ func GetCommand(ctx context.Context) (*Command, error) {
cmd.Docker,
cmd.Install,
cmd.Version,
cmd.Doc,
)
if err != nil {
return nil, err

View File

@ -3,56 +3,58 @@ module github.com/gogf/gf/cmd/gf/v2
go 1.18
require (
github.com/gogf/gf/contrib/drivers/clickhouse/v2 v2.7.1
github.com/gogf/gf/contrib/drivers/mssql/v2 v2.7.1
github.com/gogf/gf/contrib/drivers/mysql/v2 v2.7.1
github.com/gogf/gf/contrib/drivers/oracle/v2 v2.7.1
github.com/gogf/gf/contrib/drivers/pgsql/v2 v2.7.1
github.com/gogf/gf/contrib/drivers/sqlite/v2 v2.7.1
github.com/gogf/gf/v2 v2.7.1
github.com/gogf/gf/contrib/drivers/clickhouse/v2 v2.8.0
github.com/gogf/gf/contrib/drivers/mssql/v2 v2.8.0
github.com/gogf/gf/contrib/drivers/mysql/v2 v2.8.0
github.com/gogf/gf/contrib/drivers/oracle/v2 v2.8.0
github.com/gogf/gf/contrib/drivers/pgsql/v2 v2.8.0
github.com/gogf/gf/contrib/drivers/sqlite/v2 v2.8.0
github.com/gogf/gf/v2 v2.8.0
github.com/gogf/selfupdate v0.0.0-20231215043001-5c48c528462f
github.com/olekukonko/tablewriter v0.0.5
golang.org/x/mod v0.17.0
golang.org/x/tools v0.18.0
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d
)
require (
aead.dev/minisign v0.2.0 // indirect
github.com/BurntSushi/toml v1.3.2 // indirect
github.com/BurntSushi/toml v1.4.0 // indirect
github.com/ClickHouse/clickhouse-go/v2 v2.0.15 // indirect
github.com/clbanning/mxj/v2 v2.7.0 // indirect
github.com/denisenkom/go-mssqldb v0.12.3 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/fatih/color v1.16.0 // indirect
github.com/emirpasic/gods v1.18.1 // indirect
github.com/fatih/color v1.17.0 // indirect
github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/glebarez/go-sqlite v1.21.2 // indirect
github.com/go-logr/logr v1.2.4 // indirect
github.com/go-logr/logr v1.4.2 // 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-20190719163853-cb61b32ac6fe // indirect
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 // indirect
github.com/golang-sql/sqlexp v0.1.0 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/gorilla/websocket v1.5.1 // indirect
github.com/google/uuid v1.6.0 // indirect
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.7 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-runewidth v0.0.15 // indirect
github.com/microsoft/go-mssqldb v1.7.1 // 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.4 // 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.14.0 // indirect
go.opentelemetry.io/otel/sdk v1.14.0 // indirect
go.opentelemetry.io/otel/trace v1.14.0 // indirect
golang.org/x/crypto v0.23.0 // indirect
golang.org/x/net v0.25.0 // 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.25.0 // indirect
golang.org/x/net v0.27.0 // indirect
golang.org/x/sync v0.7.0 // indirect
golang.org/x/sys v0.20.0 // indirect
golang.org/x/text v0.15.0 // indirect
golang.org/x/sys v0.22.0 // indirect
golang.org/x/text v0.16.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
modernc.org/libc v1.22.5 // indirect
modernc.org/mathutil v1.5.0 // indirect

View File

@ -1,10 +1,13 @@
aead.dev/minisign v0.2.0 h1:kAWrq/hBRu4AARY6AlciO83xhNnW9UaC8YipS2uhLPk=
aead.dev/minisign v0.2.0/go.mod h1:zdq6LdSd9TbuSxchxwhpA9zEb9YXcVGoE8JakuiGaIQ=
github.com/Azure/azure-sdk-for-go/sdk/azcore v0.19.0/go.mod h1:h6H6c8enJmmocHUbLiiGY6sx7f9i+X3m1CHdd5c6Rdw=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v0.11.0/go.mod h1:HcM1YX14R7CJcghJGOYCgdezslRSVzqwLf/q+4Y2r/0=
github.com/Azure/azure-sdk-for-go/sdk/internal v0.7.0/go.mod h1:yqy467j36fJxcRV2TzfVZ1pCb5vxm4BtZPUdYWe/Xo8=
github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8=
github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.9.1 h1:lGlwhPtrX6EVml1hO0ivjkUxsSyl4dsiw9qcA1k/3IQ=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.5.1 h1:sO0/P7g68FrryJzljemN+6GTssUXdANk6aJ7T1ZxnsQ=
github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.1 h1:6oNBlSdi1QqM1PNW7FPA6xOGA5UNsXnkaYZz9vdPGhA=
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/internal v1.0.0 h1:D3occbWoio4EBLkbkevetNMAVX197GkzbUMtqjGWn80=
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/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=
@ -15,22 +18,20 @@ github.com/clbanning/mxj/v2 v2.7.0/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn
github.com/cloudflare/golz4 v0.0.0-20150217214814-ef862a3cdc58/go.mod h1:EOBUe0h4xcZ5GoxqC5SDxFQ8gwyZPKQoEzownBlhI80=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/denisenkom/go-mssqldb v0.12.3 h1:pBSGx9Tq67pBOTLmxNuirNTeB8Vjmf886Kx+8Y+8shw=
github.com/denisenkom/go-mssqldb v0.12.3/go.mod h1:k0mtMFOnU+AihqFxPMiF05rtiDrorD1Vrm1KEz5hxDo=
github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ=
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
github.com/fatih/color v1.17.0 h1:GlRw1BRJxkpqUCBKzKOw098ed57fEsKeNjpTe3cSjK4=
github.com/fatih/color v1.17.0/go.mod h1:YZ7TlrGPkiz6ku9fK3TLD/pl3CpsiFyu8N92HLgmosI=
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
github.com/glebarez/go-sqlite v1.21.2 h1:3a6LFC4sKahUunAmynQKLZceZCOzUthkRkEAl9gAXWo=
github.com/glebarez/go-sqlite v1.21.2/go.mod h1:sfxdZyhQjTM2Wry3gVYWaW072Ri1WMdWJi0k6+3382k=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
github.com/go-logr/logr v1.4.2/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=
@ -41,26 +42,29 @@ github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9
github.com/gogf/selfupdate v0.0.0-20231215043001-5c48c528462f h1:7xfXR/BhG3JDqO1s45n65Oyx9t4E/UqDOXep6jXdLCM=
github.com/gogf/selfupdate v0.0.0-20231215043001-5c48c528462f/go.mod h1:HnYoio6S7VaFJdryKcD/r9HgX+4QzYfr00XiXUo/xz0=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY=
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
github.com/golang-jwt/jwt/v5 v5.2.0 h1:d/ix8ftRUorsN+5eMIlF4T6J8CAt9rch3My2winC1Jw=
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 h1:au07oEsX2xN0ktxqI+Sida1w446QrXBRJ0nee3SNZlA=
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A=
github.com/golang-sql/sqlexp v0.1.0/go.mod h1:J4ad9Vo8ZCWQ2GMrC4UCQy1JpCbwU9m3EOqtpKwwwHI=
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.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/handlers v1.4.2/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ=
github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY=
github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY=
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/grokify/html-strip-tags-go v0.1.0/go.mod h1:ZdzgfHEzAfz9X6Xe5eBLVblWIxXfYSQ40S/VKrAOGpc=
github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks=
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/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
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=
@ -75,8 +79,9 @@ github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m
github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
github.com/microsoft/go-mssqldb v1.7.1 h1:KU/g8aWeM3Hx7IMOFpiwYiUkU+9zeISb4+tx3ScVfsM=
github.com/microsoft/go-mssqldb v1.7.1/go.mod h1:kOvZKUdrhhFQmxLZqbwUV0rHkNkZpthMITIb2Ko1IoA=
github.com/mkevac/debugcharts v0.0.0-20191222103121-ae1c48aa8615/go.mod h1:Ad7oeElCZqA1Ufj0U9/liOF4BtVepxRcTvr2ey7zTvM=
github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3PzxT8aQXRPkAt8xlV/e7d7w8GM5g0fa5F0D8=
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
github.com/paulmach/orb v0.7.1 h1:Zha++Z5OX/l168sqHK3k4z18LDvr+YAO/VjK0ReQ9rU=
@ -85,15 +90,15 @@ github.com/paulmach/protoscan v0.2.1/go.mod h1:SpcSwydNLrxUGSDvXvO0P7g7AuhJ7lcKf
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
github.com/pierrec/lz4/v4 v4.1.14 h1:+fL8AQEZtz/ijeNnpduH0bROTu0O3NZAlPjQxGn8LwE=
github.com/pierrec/lz4/v4 v4.1.14/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4/go.mod h1:4OwLy04Bl9Ef3GJJCoec+30X3LQs/0/m4HFRt/2LUSA=
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ=
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=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis=
github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/shirou/gopsutil v2.19.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4/go.mod h1:qsXQc7+bwAM3Q1u/4XEfrquwF8Lw7D7y5cD8CuHnfIc=
@ -104,31 +109,30 @@ github.com/sijms/go-ora/v2 v2.7.10/go.mod h1:EHxlY6x7y9HAsdfumurRfTd+v8NrEOTR3Xl
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
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/otel v1.7.0/go.mod h1:5BdUoMIz5WEs0vt0CUEMtSSaTSHBBVwrhnz7+nrD5xk=
go.opentelemetry.io/otel v1.14.0 h1:/79Huy8wbf5DnIPhemGB+zEPVwnN6fuQybr/SRXa6hM=
go.opentelemetry.io/otel v1.14.0/go.mod h1:o4buv+dJzx8rohcUeRmWUZhqupFvzWis188WlggnNeU=
go.opentelemetry.io/otel/sdk v1.14.0 h1:PDCppFRDq8A1jL9v6KMI6dYesaq+DFcDZvjsoGvxGzY=
go.opentelemetry.io/otel/sdk v1.14.0/go.mod h1:bwIC5TjrNG6QDCHNWvW4HLHtUQ4I+VQDsnjhvyZCALM=
go.opentelemetry.io/otel 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/trace v1.7.0/go.mod h1:fzLSB9nqR2eXzxPXb2JW9IKE+ScyXA48yyE4TNvoHqU=
go.opentelemetry.io/otel/trace v1.14.0 h1:wp2Mmvj41tDsyAJXiWDWpfNsOiIyd38fy85pyKcFq/M=
go.opentelemetry.io/otel/trace v1.14.0/go.mod h1:8avnQLK+CG77yNLUae4ea2JDQ6iT+gozhnZjy/rw9G8=
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/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-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI=
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30=
golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M=
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=
@ -137,10 +141,8 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys=
golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE=
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=
@ -152,29 +154,24 @@ golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191220220014-0732a990476f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210228012217-479acdf4ea46/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220429233432-b5fbb4746d32/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=
golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk=
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
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.18.0 h1:k8NLag8AGHnn+PHbl7g43CtqZAwG60vZkLqgyZgIHgQ=
golang.org/x/tools v0.18.0/go.mod h1:GL7B4CwcLLeo59yx/9UWWuNOW1n3VZ4f5axWfML7Lcg=
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/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=
@ -184,10 +181,7 @@ google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
modernc.org/libc v1.22.5 h1:91BNch/e5B0uPbJFgqbxXuOnxBQjlS//icfQEGmvyjE=

View File

@ -16,5 +16,6 @@ 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/dm/v2 => ../../contrib/drivers/dm
github.com/gogf/gf/v2 => ../../
)

View File

@ -59,7 +59,7 @@ func (c cGF) Index(ctx context.Context, in cGFInput) (out *cGFOutput, err error)
answer := "n"
// No argument or option, do installation checks.
if data, isInstalled := service.Install.IsInstalled(); !isInstalled {
mlog.Print("hi, it seams it's the first time you installing gf cli.")
mlog.Print("hi, it seems it's the first time you installing gf cli.")
answer = gcmd.Scanf("do you want to install gf(%s) binary to your system? [y/n]: ", gf.VERSION)
} else if !data.IsSelf {
mlog.Print("hi, you have installed gf cli.")

View File

@ -217,7 +217,7 @@ func (c cBuild) Index(ctx context.Context, in cBuildInput) (out *cBuildOutput, e
if !gfile.Exists(in.PackDst) {
// Remove the go file that is automatically packed resource.
defer func() {
_ = gfile.Remove(in.PackDst)
_ = gfile.RemoveFile(in.PackDst)
mlog.Printf(`remove the automatically generated resource go file: %s`, in.PackDst)
}()
}

View File

@ -0,0 +1,183 @@
// Copyright GoFrame gf Author(https://goframe.org). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://github.com/gogf/gf.
package cmd
import (
"context"
"fmt"
"io"
"net/http"
"os"
"path"
"path/filepath"
"time"
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
"github.com/gogf/gf/v2/encoding/gcompress"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gfile"
)
const (
GitName = "gf-site"
BranchName = "gh-pages"
SiteFileName = GitName + "-" + BranchName
// DocURL is the download address of the document
DocURL = "https://github.com/gogf/" + GitName + "/archive/refs/heads/" + BranchName + ".zip"
)
var (
Doc = cDoc{}
)
type cDoc struct {
g.Meta `name:"doc" brief:"download https://pages.goframe.org/ to run locally"`
}
type cDocInput struct {
g.Meta `name:"doc" config:"gfcli.doc"`
Path string `short:"p" name:"path" brief:"download docs directory path, default is \"%temp%/goframe\""`
Port int `short:"o" name:"port" brief:"http server port, default is 8080" d:"8080"`
Update bool `short:"u" name:"update" brief:"clean docs directory and update docs"`
Clean bool `short:"c" name:"clean" brief:"clean docs directory"`
Proxy string `short:"x" name:"proxy" brief:"proxy for download, such as https://hub.gitmirror.com/;https://ghproxy.com/;https://ghproxy.net/;https://ghps.cc/"`
}
type cDocOutput struct{}
func (c cDoc) Index(ctx context.Context, in cDocInput) (out *cDocOutput, err error) {
docs := NewDocSetting(ctx, in)
mlog.Print("Directory where the document is downloaded:", docs.TempDir)
if in.Clean {
mlog.Print("Cleaning document directory")
err = docs.Clean()
if err != nil {
mlog.Print("Failed to clean document directory:", err)
return
}
return
}
if in.Update {
mlog.Print("Cleaning old document directory")
err = docs.Clean()
if err != nil {
mlog.Print("Failed to clean old document directory:", err)
return
}
}
err = docs.DownloadDoc()
if err != nil {
mlog.Print("Failed to download document:", err)
return
}
http.Handle("/", http.FileServer(http.Dir(docs.DocDir)))
mlog.Printf("Access address http://127.0.0.1:%d in %s", in.Port, docs.DocDir)
err = http.ListenAndServe(fmt.Sprintf(":%d", in.Port), nil)
if err != nil {
return nil, err
}
return
}
// DocSetting doc setting
type DocSetting struct {
TempDir string
DocURL string
DocDir string
DocZipFile string
}
// NewDocSetting new DocSetting
func NewDocSetting(ctx context.Context, in cDocInput) *DocSetting {
fileName := SiteFileName + ".zip"
tempDir := in.Path
if tempDir == "" {
tempDir = gfile.Temp("goframe/docs")
} else {
tempDir = gfile.Abs(path.Join(tempDir, "docs"))
}
return &DocSetting{
TempDir: filepath.FromSlash(tempDir),
DocDir: filepath.FromSlash(path.Join(tempDir, SiteFileName)),
DocURL: in.Proxy + DocURL,
DocZipFile: filepath.FromSlash(path.Join(tempDir, fileName)),
}
}
// Clean cleans the temporary directory
func (d *DocSetting) Clean() error {
if _, err := os.Stat(d.TempDir); err == nil {
err = gfile.RemoveAll(d.TempDir)
if err != nil {
mlog.Print("Failed to delete temporary directory:", err)
return err
}
}
return nil
}
// DownloadDoc download the document
func (d *DocSetting) DownloadDoc() error {
if _, err := os.Stat(d.TempDir); err != nil {
err = gfile.Mkdir(d.TempDir)
if err != nil {
mlog.Print("Failed to create temporary directory:", err)
return nil
}
}
// Check if the file exists
if _, err := os.Stat(d.DocDir); err == nil {
mlog.Print("Document already exists, no need to download and unzip")
return nil
}
if _, err := os.Stat(d.DocZipFile); err == nil {
mlog.Print("File already exists, no need to download")
} else {
mlog.Printf("File does not exist, start downloading: %s", d.DocURL)
startTime := time.Now()
// Download the file
resp, err := http.Get(d.DocURL)
if err != nil {
mlog.Print("Failed to download file:", err)
return err
}
defer resp.Body.Close()
// Create the file
out, err := os.Create(d.DocZipFile)
if err != nil {
mlog.Print("Failed to create file:", err)
return err
}
defer out.Close()
// Write the response body to the file
_, err = io.Copy(out, resp.Body)
if err != nil {
mlog.Print("Failed to write file:", err)
return err
}
mlog.Printf("Download successful, time-consuming: %v", time.Since(startTime))
}
mlog.Print("Start unzipping the file...")
// Unzip the file
err := gcompress.UnZipFile(d.DocZipFile, d.TempDir)
if err != nil {
mlog.Print("Failed to unzip the file, please run again:", err)
_ = gfile.RemoveFile(d.DocZipFile)
return err
}
mlog.Print("Download and unzip successful")
return nil
}

View File

@ -8,6 +8,7 @@ package cmd
import (
_ "github.com/gogf/gf/contrib/drivers/clickhouse/v2"
// _ "github.com/gogf/gf/contrib/drivers/dm/v2" // precompilation does not support certain target platforms.
_ "github.com/gogf/gf/contrib/drivers/mssql/v2"
_ "github.com/gogf/gf/contrib/drivers/mysql/v2"
_ "github.com/gogf/gf/contrib/drivers/oracle/v2"

View File

@ -12,6 +12,9 @@ import (
"os"
"strings"
"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"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gcmd"
"github.com/gogf/gf/v2/os/gfile"
@ -19,9 +22,6 @@ import (
"github.com/gogf/gf/v2/os/gres"
"github.com/gogf/gf/v2/text/gstr"
"github.com/gogf/gf/v2/util/gtag"
"github.com/gogf/gf/cmd/gf/v2/internal/utility/allyes"
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
)
var (
@ -34,13 +34,15 @@ type cInit struct {
}
const (
cInitRepoPrefix = `github.com/gogf/`
cInitMonoRepo = `template-mono`
cInitSingleRepo = `template-single`
cInitBrief = `create and initialize an empty GoFrame project`
cInitEg = `
cInitRepoPrefix = `github.com/gogf/`
cInitMonoRepo = `template-mono`
cInitMonoRepoApp = `template-mono-app`
cInitSingleRepo = `template-single`
cInitBrief = `create and initialize an empty GoFrame project`
cInitEg = `
gf init my-project
gf init my-mono-repo -m
gf init my-mono-repo -a
`
cInitNameBrief = `
name for the project. It will create a folder with NAME in current directory.
@ -61,11 +63,12 @@ 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"`
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" 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"`
}
type cInitOutput struct{}
@ -86,11 +89,15 @@ func (c cInit) Index(ctx context.Context, in cInitInput) (out *cInitOutput, err
templateRepoName string
gitignoreFile = in.Name + "/" + cInitGitignore
)
if in.Mono {
templateRepoName = cInitMonoRepo
} else if in.MonoApp {
templateRepoName = cInitMonoRepoApp
} else {
templateRepoName = cInitSingleRepo
}
err = gres.Export(templateRepoName, in.Name, gres.ExportOption{
RemovePrefix: templateRepoName,
})
@ -101,7 +108,8 @@ func (c cInit) Index(ctx context.Context, in cInitInput) (out *cInitOutput, err
// build ignoreFiles from the .gitignore file
ignoreFiles := make([]string, 0, 10)
ignoreFiles = append(ignoreFiles, cInitGitDir)
if overwrote {
// in.MonoApp is a mono-repo-app, it should ignore the .gitignore file
if overwrote && !in.MonoApp {
err = gfile.ReadLines(gitignoreFile, func(line string) error {
// Add only hidden files or directories
// If other directories are added, it may cause the entire directory to be ignored
@ -118,10 +126,14 @@ func (c cInit) Index(ctx context.Context, in cInitInput) (out *cInitOutput, err
}
}
// Replace module name.
// Get template name and module name.
if in.Module == "" {
in.Module = gfile.Basename(gfile.RealPath(in.Name))
}
if in.MonoApp {
pwd := gfile.Pwd() + string(os.PathSeparator) + in.Name
in.Module = utils.GetImportPath(pwd)
}
// Replace template name to project name.
err = gfile.ReplaceDirFunc(func(path, content string) string {

View File

@ -63,7 +63,7 @@ func init() {
}
type cPackInput struct {
g.Meta `name:"pack"`
g.Meta `name:"pack" config:"gfcli.pack"`
Src string `name:"SRC" arg:"true" v:"required" brief:"{cPackSrcBrief}"`
Dst string `name:"DST" arg:"true" v:"required" brief:"{cPackDstBrief}"`
Name string `name:"name" short:"n" brief:"{cPackNameBrief}"`

View File

@ -9,6 +9,7 @@ package cmd
import (
"context"
"fmt"
"os"
"path/filepath"
"runtime"
"strings"
@ -55,7 +56,7 @@ The "run" command is used for running go codes with hot-compiled-like feature,
which compiles and runs the go codes asynchronously when codes change.
`
cRunFileBrief = `building file path.`
cRunPathBrief = `output directory path for built binary file. it's "manifest/output" in default`
cRunPathBrief = `output directory path for built binary file. it's "./" in default`
cRunExtraBrief = `the same options as "go run"/"go build" except some options as follows defined`
cRunArgsBrief = `custom arguments for your process`
cRunWatchPathsBrief = `watch additional paths for live reload, separated by ",". i.e. "manifest/config/*.yaml"`
@ -81,7 +82,7 @@ func init() {
type (
cRunInput struct {
g.Meta `name:"run"`
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}"`
@ -92,6 +93,12 @@ type (
)
func (c cRun) Index(ctx context.Context, in cRunInput) (out *cRunOutput, err error) {
if !gfile.Exists(in.File) {
mlog.Fatalf(`given file "%s" not found`, in.File)
}
if !gfile.IsFile(in.File) {
mlog.Fatalf(`given "%s" is not a file`, in.File)
}
// Necessary check.
if gproc.SearchBinary("go") == "" {
mlog.Fatalf(`command "go" not found in your environment, please install golang first to proceed this command`)
@ -104,13 +111,14 @@ func (c cRun) Index(ctx context.Context, in cRunInput) (out *cRunOutput, err err
app := &cRunApp{
File: in.File,
Path: in.Path,
Path: filepath.FromSlash(in.Path),
Options: in.Extra,
Args: in.Args,
WatchPaths: in.WatchPaths,
}
dirty := gtype.NewBool()
var outputPath = app.genOutputPath()
callbackFunc := func(event *gfsnotify.Event) {
if gfile.ExtName(event.Path) != "go" {
return
@ -125,7 +133,7 @@ func (c cRun) Index(ctx context.Context, in cRunInput) (out *cRunOutput, err err
gtimer.SetTimeout(ctx, 1500*gtime.MS, func(ctx context.Context) {
defer dirty.Set(false)
mlog.Printf(`watched file changes: %s`, event.String())
app.Run(ctx)
app.Run(ctx, outputPath)
})
}
@ -143,24 +151,21 @@ func (c cRun) Index(ctx context.Context, in cRunInput) (out *cRunOutput, err err
}
}
go app.Run(ctx)
go app.Run(ctx, outputPath)
gproc.AddSigHandlerShutdown(func(sig os.Signal) {
app.End(ctx, sig, outputPath)
os.Exit(0)
})
gproc.Listen()
select {}
}
func (app *cRunApp) Run(ctx context.Context) {
func (app *cRunApp) Run(ctx context.Context, outputPath string) {
// Rebuild and run the codes.
renamePath := ""
mlog.Printf("build: %s", app.File)
outputPath := gfile.Join(app.Path, gfile.Name(app.File))
if runtime.GOOS == "windows" {
outputPath += ".exe"
if gfile.Exists(outputPath) {
renamePath = outputPath + "~"
if err := gfile.Rename(outputPath, renamePath); err != nil {
mlog.Print(err)
}
}
}
// In case of `pipe: too many open files` error.
// Build the app.
buildCommand := fmt.Sprintf(
@ -198,6 +203,36 @@ func (app *cRunApp) Run(ctx context.Context) {
}
}
func (app *cRunApp) End(ctx context.Context, sig os.Signal, outputPath string) {
// Delete the binary file.
// firstly, kill the process.
if process != nil {
if err := process.Kill(); err != nil {
mlog.Debugf("kill process error: %s", err.Error())
}
}
if err := gfile.RemoveFile(outputPath); err != nil {
mlog.Printf("delete binary file error: %s", err.Error())
} else {
mlog.Printf("deleted binary file: %s", outputPath)
}
}
func (app *cRunApp) genOutputPath() (outputPath string) {
var renamePath string
outputPath = gfile.Join(app.Path, gfile.Name(app.File))
if runtime.GOOS == "windows" {
outputPath += ".exe"
if gfile.Exists(outputPath) {
renamePath = outputPath + "~"
if err := gfile.Rename(outputPath, renamePath); err != nil {
mlog.Print(err)
}
}
}
return filepath.FromSlash(outputPath)
}
func matchWatchPaths(watchPaths []string, eventPath string) bool {
for _, path := range watchPaths {
absPath, err := filepath.Abs(path)

View File

@ -47,7 +47,7 @@ gf tpl parse -p ./template -v values.json -o ./template.parsed
type (
cTplParseInput struct {
g.Meta `name:"parse" brief:"{cTplParseBrief}" eg:"{cTplParseEg}"`
g.Meta `name:"parse" config:"gfcli.tpl.parse" brief:"{cTplParseBrief}" eg:"{cTplParseEg}"`
Path string `name:"path" short:"p" brief:"template file or folder path" v:"required"`
Pattern string `name:"pattern" short:"n" brief:"template file pattern when path is a folder, default is:*" d:"*"`
Recursive bool `name:"recursive" short:"c" brief:"recursively parsing files if path is folder, default is:true" d:"true"`

View File

@ -48,7 +48,7 @@ func init() {
}
type cUpInput struct {
g.Meta `name:"up" config:"gfcli.up"`
g.Meta `name:"up" config:"gfcli.up"`
All bool `name:"all" short:"a" brief:"upgrade both version and cli, auto fix codes" orphan:"true"`
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"`
@ -142,8 +142,9 @@ func (c cUp) doUpgradeVersion(ctx context.Context, in cUpInput) (out *doUpgradeV
}
for _, pkg := range packages {
mlog.Printf(`upgrading "%s" from "%s" to "latest"`, pkg.Name, pkg.Version)
// go get -u
command := fmt.Sprintf(`cd %s && go get -u %s@latest`, dirPath, pkg.Name)
mlog.Printf(`running command: go get %s@latest`, pkg.Name)
// go get @latest
command := fmt.Sprintf(`cd %s && go get %s@latest`, dirPath, pkg.Name)
if err = gproc.ShellRun(ctx, command); err != nil {
return
}
@ -191,7 +192,7 @@ func (c cUp) doUpgradeCLI(ctx context.Context) (err error) {
defer func() {
mlog.Printf(`new version cli binary is successfully installed to "%s"`, gfile.SelfPath())
mlog.Printf(`remove temporary buffer file "%s"`, localSaveFilePath)
_ = gfile.Remove(localSaveFilePath)
_ = gfile.RemoveFile(localSaveFilePath)
}()
// It fails if file not exist or its size is less than 1MB.

View File

@ -83,56 +83,12 @@ func Test_Gen_Ctrl_Default(t *testing.T) {
})
}
// https://github.com/gogf/gf/issues/3460
func Test_Gen_Ctrl_UseMerge_Issue3460(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
var (
ctrlPath = gfile.Temp(guid.S())
//ctrlPath = gtest.DataPath("issue", "3460", "controller")
apiFolder = gtest.DataPath("issue", "3460", "api")
in = genctrl.CGenCtrlInput{
SrcFolder: apiFolder,
DstFolder: ctrlPath,
WatchFile: "",
SdkPath: "",
SdkStdVersion: false,
SdkNoV1: false,
Clear: false,
Merge: true,
}
)
err := gfile.Mkdir(ctrlPath)
t.AssertNil(err)
defer gfile.Remove(ctrlPath)
_, err = genctrl.CGenCtrl{}.Ctrl(ctx, in)
t.AssertNil(err)
files, err := gfile.ScanDir(ctrlPath, "*.go", true)
t.AssertNil(err)
t.Assert(files, []string{
filepath.Join(ctrlPath, "/hello/hello.go"),
filepath.Join(ctrlPath, "/hello/hello_new.go"),
filepath.Join(ctrlPath, "/hello/hello_v1_req.go"),
filepath.Join(ctrlPath, "/hello/hello_v2_req.go"),
})
expectCtrlPath := gtest.DataPath("issue", "3460", "controller")
expectFiles := []string{
filepath.Join(expectCtrlPath, "/hello/hello.go"),
filepath.Join(expectCtrlPath, "/hello/hello_new.go"),
filepath.Join(expectCtrlPath, "/hello/hello_v1_req.go"),
filepath.Join(expectCtrlPath, "/hello/hello_v2_req.go"),
}
// Line Feed maybe \r\n or \n
for i, expectFile := range expectFiles {
val := gfile.GetContents(files[i])
expect := gfile.GetContents(expectFile)
t.Assert(val, expect)
}
})
func expectFilesContent(t *gtest.T, paths []string, expectPaths []string) {
for i, expectFile := range expectPaths {
val := gfile.GetContents(paths[i])
expect := gfile.GetContents(expectFile)
t.Assert(val, expect)
}
}
// gf gen ctrl -m
@ -300,10 +256,54 @@ type DictTypeAddRes struct {
}
func expectFilesContent(t *gtest.T, paths []string, expectPaths []string) {
for i, expectFile := range expectPaths {
val := gfile.GetContents(paths[i])
expect := gfile.GetContents(expectFile)
t.Assert(val, expect)
}
// https://github.com/gogf/gf/issues/3460
func Test_Gen_Ctrl_UseMerge_Issue3460(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
var (
ctrlPath = gfile.Temp(guid.S())
//ctrlPath = gtest.DataPath("issue", "3460", "controller")
apiFolder = gtest.DataPath("issue", "3460", "api")
in = genctrl.CGenCtrlInput{
SrcFolder: apiFolder,
DstFolder: ctrlPath,
WatchFile: "",
SdkPath: "",
SdkStdVersion: false,
SdkNoV1: false,
Clear: false,
Merge: true,
}
)
err := gfile.Mkdir(ctrlPath)
t.AssertNil(err)
defer gfile.Remove(ctrlPath)
_, err = genctrl.CGenCtrl{}.Ctrl(ctx, in)
t.AssertNil(err)
files, err := gfile.ScanDir(ctrlPath, "*.go", true)
t.AssertNil(err)
t.Assert(files, []string{
filepath.Join(ctrlPath, "/hello/hello.go"),
filepath.Join(ctrlPath, "/hello/hello_new.go"),
filepath.Join(ctrlPath, "/hello/hello_v1_req.go"),
filepath.Join(ctrlPath, "/hello/hello_v2_req.go"),
})
expectCtrlPath := gtest.DataPath("issue", "3460", "controller")
expectFiles := []string{
filepath.Join(expectCtrlPath, "/hello/hello.go"),
filepath.Join(expectCtrlPath, "/hello/hello_new.go"),
filepath.Join(expectCtrlPath, "/hello/hello_v1_req.go"),
filepath.Join(expectCtrlPath, "/hello/hello_v2_req.go"),
}
// Line Feed maybe \r\n or \n
for i, expectFile := range expectFiles {
val := gfile.GetContents(files[i])
expect := gfile.GetContents(expectFile)
t.Assert(val, expect)
}
})
}

View File

@ -691,3 +691,151 @@ func Test_Gen_Dao_Issue3459(t *testing.T) {
}
})
}
// https://github.com/gogf/gf/issues/3749
func Test_Gen_Dao_Issue3749(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
var (
err error
db = testDB
table = "table_user"
sqlContent = fmt.Sprintf(
gtest.DataContent(`issue`, `3749`, `user.tpl.sql`),
table,
)
)
dropTableWithDb(db, table)
array := gstr.SplitAndTrim(sqlContent, ";")
for _, v := range array {
if _, err = db.Exec(ctx, v); err != nil {
t.AssertNil(err)
}
}
defer dropTableWithDb(db, table)
var (
path = gfile.Temp(guid.S())
group = "test"
in = gendao.CGenDaoInput{
Path: path,
Link: link,
Group: group,
}
)
err = gutil.FillStructWithDefault(&in)
t.AssertNil(err)
err = gfile.Mkdir(path)
t.AssertNil(err)
// for go mod import path auto retrieve.
err = gfile.Copy(
gtest.DataPath("gendao", "go.mod.txt"),
gfile.Join(path, "go.mod"),
)
t.AssertNil(err)
_, err = gendao.CGenDao{}.Dao(ctx, in)
t.AssertNil(err)
defer gfile.Remove(path)
// files
files, err := gfile.ScanDir(path, "*.go", true)
t.AssertNil(err)
t.Assert(files, []string{
filepath.FromSlash(path + "/dao/internal/table_user.go"),
filepath.FromSlash(path + "/dao/table_user.go"),
filepath.FromSlash(path + "/model/do/table_user.go"),
filepath.FromSlash(path + "/model/entity/table_user.go"),
})
// content
testPath := gtest.DataPath(`issue`, `3749`)
expectFiles := []string{
filepath.FromSlash(testPath + "/dao/internal/table_user.go"),
filepath.FromSlash(testPath + "/dao/table_user.go"),
filepath.FromSlash(testPath + "/model/do/table_user.go"),
filepath.FromSlash(testPath + "/model/entity/table_user.go"),
}
for i, _ := range files {
t.Assert(gfile.GetContents(files[i]), gfile.GetContents(expectFiles[i]))
}
})
}
func Test_Gen_Dao_Sqlite3(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
var (
err error
table = "table_user"
path = gfile.Temp(guid.S())
linkSqlite3 = fmt.Sprintf("sqlite::@file(%s/db.sqlite3)", path)
sqlContent = fmt.Sprintf(
gtest.DataContent(`gendao`, `sqlite3`, `user.sqlite3.sql`),
table,
)
)
err = gfile.Mkdir(path)
t.AssertNil(err)
defer gfile.Remove(path)
dbSqlite3, err := gdb.New(gdb.ConfigNode{
Link: linkSqlite3,
})
t.AssertNil(err)
array := gstr.SplitAndTrim(sqlContent, ";")
for _, v := range array {
if v == "" {
continue
}
if _, err = dbSqlite3.Exec(ctx, v); err != nil {
t.AssertNil(err)
}
}
var (
group = "test"
in = gendao.CGenDaoInput{
Path: path,
Link: linkSqlite3,
Group: group,
Tables: table,
}
)
err = gutil.FillStructWithDefault(&in)
t.AssertNil(err)
// for go mod import path auto retrieve.
err = gfile.Copy(
gtest.DataPath("gendao", "go.mod.txt"),
gfile.Join(path, "go.mod"),
)
t.AssertNil(err)
_, err = gendao.CGenDao{}.Dao(ctx, in)
t.AssertNil(err)
defer gfile.Remove(path)
// files
files, err := gfile.ScanDir(path, "*.go", true)
t.AssertNil(err)
t.Assert(files, []string{
filepath.FromSlash(path + "/dao/internal/table_user.go"),
filepath.FromSlash(path + "/dao/table_user.go"),
filepath.FromSlash(path + "/model/do/table_user.go"),
filepath.FromSlash(path + "/model/entity/table_user.go"),
})
// content
testPath := gtest.DataPath("gendao", "generated_user_sqlite3")
expectFiles := []string{
filepath.FromSlash(testPath + "/dao/internal/table_user.go"),
filepath.FromSlash(testPath + "/dao/table_user.go"),
filepath.FromSlash(testPath + "/model/do/table_user.go"),
filepath.FromSlash(testPath + "/model/entity/table_user.go"),
}
for i, _ := range files {
t.Assert(gfile.GetContents(files[i]), gfile.GetContents(expectFiles[i]))
}
})
}

View File

@ -0,0 +1,50 @@
// Copyright GoFrame gf Author(https://goframe.org). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://github.com/gogf/gf.
package cmd
import (
"path/filepath"
"testing"
"github.com/gogf/gf/cmd/gf/v2/internal/cmd/genpb"
"github.com/gogf/gf/v2/os/gfile"
"github.com/gogf/gf/v2/test/gtest"
"github.com/gogf/gf/v2/text/gstr"
"github.com/gogf/gf/v2/util/guid"
)
func TestGenPbIssue3882(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
var (
outputPath = gfile.Temp(guid.S())
outputApiPath = filepath.Join(outputPath, "api")
outputCtrlPath = filepath.Join(outputPath, "controller")
protobufFolder = gtest.DataPath("issue", "3882")
in = genpb.CGenPbInput{
Path: protobufFolder,
OutputApi: outputApiPath,
OutputCtrl: outputCtrlPath,
}
err error
)
err = gfile.Mkdir(outputApiPath)
t.AssertNil(err)
err = gfile.Mkdir(outputCtrlPath)
t.AssertNil(err)
defer gfile.Remove(outputPath)
_, err = genpb.CGenPb{}.Pb(ctx, in)
t.AssertNil(err)
var (
genContent = gfile.GetContents(filepath.Join(outputApiPath, "issue3882.pb.go"))
exceptText = `dc:"Some comment on field with 'one' 'two' 'three' in the comment."`
)
t.Assert(gstr.Contains(genContent, exceptText), true)
})
}

View File

@ -22,9 +22,9 @@ func Test_Gen_Service_Default(t *testing.T) {
var (
path = gfile.Temp(guid.S())
dstFolder = path + filepath.FromSlash("/service")
apiFolder = gtest.DataPath("genservice", "logic")
srvFolder = gtest.DataPath("genservice", "logic")
in = genservice.CGenServiceInput{
SrcFolder: apiFolder,
SrcFolder: srvFolder,
DstFolder: dstFolder,
DstFileNameCase: "Snake",
WatchFile: "",
@ -46,26 +46,110 @@ func Test_Gen_Service_Default(t *testing.T) {
// logic file
var (
genApi = apiFolder + filepath.FromSlash("/logic.go")
genApiExpect = apiFolder + filepath.FromSlash("/logic_expect.go")
genSrv = srvFolder + filepath.FromSlash("/logic.go")
genSrvExpect = srvFolder + filepath.FromSlash("/logic_expect.go")
)
defer gfile.Remove(genApi)
t.Assert(gfile.GetContents(genApi), gfile.GetContents(genApiExpect))
defer gfile.Remove(genSrv)
t.Assert(gfile.GetContents(genSrv), gfile.GetContents(genSrvExpect))
// files
files, err := gfile.ScanDir(dstFolder, "*.go", true)
t.AssertNil(err)
t.Assert(files, []string{
dstFolder + filepath.FromSlash("/article.go"),
dstFolder + filepath.FromSlash("/delivery.go"),
dstFolder + filepath.FromSlash("/user.go"),
})
// contents
testPath := gtest.DataPath("genservice", "service")
expectFiles := []string{
testPath + filepath.FromSlash("/article.go"),
testPath + filepath.FromSlash("/delivery.go"),
testPath + filepath.FromSlash("/user.go"),
}
for i := range files {
t.Assert(gfile.GetContents(files[i]), gfile.GetContents(expectFiles[i]))
}
})
}
// https://github.com/gogf/gf/issues/3328
func Test_Issue3328(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
var (
path = gfile.Temp(guid.S())
dstFolder = path + filepath.FromSlash("/service")
srvFolder = gtest.DataPath("issue", "3328", "logic")
logicGoPath = srvFolder + filepath.FromSlash("/logic.go")
in = genservice.CGenServiceInput{
SrcFolder: srvFolder,
DstFolder: dstFolder,
DstFileNameCase: "Snake",
WatchFile: "",
StPattern: "",
Packages: nil,
ImportPrefix: "",
Clear: false,
}
)
gfile.Remove(logicGoPath)
defer gfile.Remove(logicGoPath)
err := gutil.FillStructWithDefault(&in)
t.AssertNil(err)
err = gfile.Mkdir(path)
t.AssertNil(err)
defer gfile.Remove(path)
_, err = genservice.CGenService{}.Service(ctx, in)
t.AssertNil(err)
files, err := gfile.ScanDir(srvFolder, "*", true)
for _, file := range files {
if file == logicGoPath {
if gfile.IsDir(logicGoPath) {
t.Fatalf("%s should not is folder", logicGoPath)
}
}
}
})
}
// https://github.com/gogf/gf/issues/3835
func Test_Issue3835(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
var (
path = gfile.Temp(guid.S())
dstFolder = path + filepath.FromSlash("/service")
srvFolder = gtest.DataPath("issue", "3835", "logic")
in = genservice.CGenServiceInput{
SrcFolder: srvFolder,
DstFolder: dstFolder,
DstFileNameCase: "Snake",
WatchFile: "",
StPattern: "",
Packages: nil,
ImportPrefix: "",
Clear: false,
}
)
err := gutil.FillStructWithDefault(&in)
t.AssertNil(err)
err = gfile.Mkdir(path)
t.AssertNil(err)
defer gfile.Remove(path)
_, err = genservice.CGenService{}.Service(ctx, in)
t.AssertNil(err)
// contents
var (
genFile = dstFolder + filepath.FromSlash("/issue_3835.go")
expectFile = gtest.DataPath("issue", "3835", "service", "issue_3835.go")
)
t.Assert(gfile.GetContents(genFile), gfile.GetContents(expectFile))
})
}

View File

@ -128,7 +128,7 @@ func (c CGenCtrl) generateByWatchFile(watchFile, sdkPath string, sdkStdVersion,
return
}
}
defer gfile.Remove(flockFilePath)
defer gfile.RemoveFile(flockFilePath)
_ = gfile.PutContents(flockFilePath, gtime.TimestampStr())
// check this updated file is an api file.

View File

@ -0,0 +1,78 @@
// Copyright GoFrame gf Author(https://goframe.org). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://github.com/gogf/gf.
package genctrl
import (
"bytes"
"go/ast"
"go/parser"
"go/printer"
"go/token"
"github.com/gogf/gf/v2/os/gfile"
"github.com/gogf/gf/v2/text/gstr"
)
// getStructsNameInSrc retrieves all struct names
// that end in "Req" and have "g.Meta" in their body.
func (c CGenCtrl) getStructsNameInSrc(filePath string) (structsName []string, err error) {
var (
fileContent = gfile.GetContents(filePath)
fileSet = token.NewFileSet()
)
node, err := parser.ParseFile(fileSet, "", fileContent, parser.ParseComments)
if err != nil {
return
}
ast.Inspect(node, func(n ast.Node) bool {
if typeSpec, ok := n.(*ast.TypeSpec); ok {
methodName := typeSpec.Name.Name
if !gstr.HasSuffix(methodName, "Req") {
// ignore struct name that do not end in "Req"
return true
}
if structType, ok := typeSpec.Type.(*ast.StructType); ok {
var buf bytes.Buffer
if err := printer.Fprint(&buf, fileSet, structType); err != nil {
return false
}
// ignore struct name that match a request, but has no g.Meta in its body.
if !gstr.Contains(buf.String(), `g.Meta`) {
return true
}
structsName = append(structsName, methodName)
}
}
return true
})
return
}
// getImportsInDst retrieves all import paths in the file.
func (c CGenCtrl) getImportsInDst(filePath string) (imports []string, err error) {
var (
fileContent = gfile.GetContents(filePath)
fileSet = token.NewFileSet()
)
node, err := parser.ParseFile(fileSet, "", fileContent, parser.ParseComments)
if err != nil {
return
}
ast.Inspect(node, func(n ast.Node) bool {
if imp, ok := n.(*ast.ImportSpec); ok {
imports = append(imports, imp.Path.Value)
}
return true
})
return
}

View File

@ -0,0 +1,43 @@
// Copyright GoFrame gf Author(https://goframe.org). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://github.com/gogf/gf.
package genctrl
import (
"bytes"
"go/ast"
"go/parser"
"go/printer"
"go/token"
"github.com/gogf/gf/v2/os/gfile"
)
// getFuncInDst retrieves all function declarations and bodies in the file.
func (c *controllerClearer) getFuncInDst(filePath string) (funcs []string, err error) {
var (
fileContent = gfile.GetContents(filePath)
fileSet = token.NewFileSet()
)
node, err := parser.ParseFile(fileSet, "", fileContent, parser.ParseComments)
if err != nil {
return
}
ast.Inspect(node, func(n ast.Node) bool {
if fun, ok := n.(*ast.FuncDecl); ok {
var buf bytes.Buffer
if err := printer.Fprint(&buf, fileSet, fun); err != nil {
return false
}
funcs = append(funcs, buf.String())
}
return true
})
return
}

View File

@ -7,12 +7,6 @@
package genctrl
import (
"bytes"
"go/ast"
"go/parser"
"go/printer"
"go/token"
"github.com/gogf/gf/cmd/gf/v2/internal/utility/utils"
"github.com/gogf/gf/v2/os/gfile"
"github.com/gogf/gf/v2/text/gregex"
@ -139,63 +133,3 @@ func (c CGenCtrl) getApiItemsInDst(dstFolder string) (items []apiItem, err error
}
return
}
// getStructsNameInSrc retrieves all struct names
// that end in "Req" and have "g.Meta" in their body.
func (c CGenCtrl) getStructsNameInSrc(filePath string) (structsName []string, err error) {
var (
fileContent = gfile.GetContents(filePath)
fileSet = token.NewFileSet()
)
node, err := parser.ParseFile(fileSet, "", fileContent, parser.ParseComments)
if err != nil {
return
}
ast.Inspect(node, func(n ast.Node) bool {
if typeSpec, ok := n.(*ast.TypeSpec); ok {
methodName := typeSpec.Name.Name
if !gstr.HasSuffix(methodName, "Req") {
// ignore struct name that do not end in "Req"
return true
}
if structType, ok := typeSpec.Type.(*ast.StructType); ok {
var buf bytes.Buffer
if err := printer.Fprint(&buf, fileSet, structType); err != nil {
return false
}
// ignore struct name that match a request, but has no g.Meta in its body.
if !gstr.Contains(buf.String(), `g.Meta`) {
return true
}
structsName = append(structsName, methodName)
}
}
return true
})
return
}
// getImportsInDst retrieves all import paths in the file.
func (c CGenCtrl) getImportsInDst(filePath string) (imports []string, err error) {
var (
fileContent = gfile.GetContents(filePath)
fileSet = token.NewFileSet()
)
node, err := parser.ParseFile(fileSet, "", fileContent, parser.ParseComments)
if err != nil {
return
}
ast.Inspect(node, func(n ast.Node) bool {
if imp, ok := n.(*ast.ImportSpec); ok {
imports = append(imports, imp.Path.Value)
}
return true
})
return
}

View File

@ -89,7 +89,7 @@ func (c *controllerGenerator) doGenerateCtrlNewByModuleAndVersion(
if err = gfile.PutContents(moduleFilePath, gstr.TrimLeft(content)); err != nil {
return err
}
mlog.Printf(`generated: %s`, moduleFilePath)
mlog.Printf(`generated: %s`, gfile.RealPath(moduleFilePath))
}
if !gfile.Exists(moduleFilePathNew) {
content := gstr.ReplaceByMap(consts.TemplateGenCtrlControllerNewEmpty, g.MapStrStr{
@ -99,7 +99,7 @@ func (c *controllerGenerator) doGenerateCtrlNewByModuleAndVersion(
if err = gfile.PutContents(moduleFilePathNew, gstr.TrimLeft(content)); err != nil {
return err
}
mlog.Printf(`generated: %s`, moduleFilePathNew)
mlog.Printf(`generated: %s`, gfile.RealPath(moduleFilePathNew))
}
filePaths, err := gfile.ScanDir(dstModuleFolderPath, "*.go", false)
if err != nil {
@ -161,7 +161,7 @@ func (c *controllerGenerator) doGenerateCtrlItem(dstModuleFolderPath string, ite
return err
}
}
mlog.Printf(`generated: %s`, methodFilePath)
mlog.Printf(`generated: %s`, gfile.RealPath(methodFilePath))
return
}
@ -221,7 +221,7 @@ func (c *controllerGenerator) doGenerateCtrlMergeItem(dstModuleFolderPath string
if err = gfile.PutContentsAppend(ctrlFilePath, ctrlFileItem.controllers.String()); err != nil {
return err
}
mlog.Printf(`generated: %s`, ctrlFilePath)
mlog.Printf(`generated: %s`, gfile.RealPath(ctrlFilePath))
}
return
}

View File

@ -11,7 +11,6 @@ import (
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
"github.com/gogf/gf/v2/os/gfile"
"github.com/gogf/gf/v2/text/gregex"
"github.com/gogf/gf/v2/text/gstr"
)
@ -36,22 +35,21 @@ func (c *controllerClearer) doClear(dstModuleFolderPath string, item apiItem) (e
methodFilePath = gfile.Join(dstModuleFolderPath, fmt.Sprintf(
`%s_%s_%s.go`, item.Module, item.Version, methodNameSnake,
))
fileContent = gstr.Trim(gfile.GetContents(methodFilePath))
)
// retrieve it without using AST, because it's simple.
match, err := gregex.MatchString(`.+?Req.+?Res.+?{([\s\S]+?)}`, fileContent)
funcs, err := c.getFuncInDst(methodFilePath)
if err != nil {
return err
}
if len(match) > 1 {
implements := gstr.Trim(match[1])
if len(funcs) > 1 {
// One line.
if !gstr.Contains(implements, "\n") && gstr.Contains(implements, `CodeNotImplemented`) {
if !gstr.Contains(funcs[0], "\n") && gstr.Contains(funcs[0], `CodeNotImplemented`) {
mlog.Printf(
`remove unimplemented and of no api definitions controller file: %s`,
methodFilePath,
)
err = gfile.Remove(methodFilePath)
err = gfile.RemoveFile(methodFilePath)
}
}
return

View File

@ -94,7 +94,7 @@ func (c *apiInterfaceGenerator) doGenerate(apiModuleFolderPath string, module st
"{Interfaces}": gstr.TrimRightStr(interfaceDefinition, "\n", 2),
}))
err = gfile.PutContents(moduleFilePath, interfaceContent)
mlog.Printf(`generated: %s`, moduleFilePath)
mlog.Printf(`generated: %s`, gfile.RealPath(moduleFilePath))
return
}

View File

@ -65,7 +65,7 @@ func (c *apiSdkGenerator) doGenerateSdkPkgFile(sdkFolderPath string) (err error)
"{PkgName}": pkgName,
}))
err = gfile.PutContents(pkgFilePath, fileContent)
mlog.Printf(`generated: %s`, pkgFilePath)
mlog.Printf(`generated: %s`, gfile.RealPath(pkgFilePath))
return
}
@ -130,9 +130,9 @@ func (c *apiSdkGenerator) doGenerateSdkIClient(
if isDirty {
err = gfile.PutContents(iClientFilePath, fileContent)
if isExist {
mlog.Printf(`updated: %s`, iClientFilePath)
mlog.Printf(`updated: %s`, gfile.RealPath(iClientFilePath))
} else {
mlog.Printf(`generated: %s`, iClientFilePath)
mlog.Printf(`generated: %s`, gfile.RealPath(iClientFilePath))
}
}
return
@ -183,7 +183,7 @@ func (c *apiSdkGenerator) doGenerateSdkImplementer(
implementerFileContent += "\n"
}
err = gfile.PutContents(implementerFilePath, implementerFileContent)
mlog.Printf(`generated: %s`, implementerFilePath)
mlog.Printf(`generated: %s`, gfile.RealPath(implementerFilePath))
return
}

View File

@ -118,6 +118,7 @@ generated json tag case for model struct, cases are as follows:
tplVarGroupName = `{TplGroupName}`
tplVarDatetimeStr = `{TplDatetimeStr}`
tplVarCreatedAtDatetimeStr = `{TplCreatedAtDatetimeStr}`
tplVarPackageName = `{TplPackageName}`
)
var (
@ -207,9 +208,11 @@ type (
NoModelComment bool `name:"noModelComment" short:"m" brief:"{CGenDaoBriefNoModelComment}" orphan:"true"`
Clear bool `name:"clear" short:"a" brief:"{CGenDaoBriefClear}" orphan:"true"`
TypeMapping map[DBFieldTypeName]CustomAttributeType `name:"typeMapping" short:"y" brief:"{CGenDaoBriefTypeMapping}" orphan:"true"`
FieldMapping map[DBTableFieldName]CustomAttributeType `name:"fieldMapping" short:"fm" brief:"{CGenDaoBriefFieldMapping}" orphan:"true"`
genItems *CGenDaoInternalGenItems
TypeMapping map[DBFieldTypeName]CustomAttributeType `name:"typeMapping" short:"y" brief:"{CGenDaoBriefTypeMapping}" orphan:"true"`
FieldMapping map[DBTableFieldName]CustomAttributeType `name:"fieldMapping" short:"fm" brief:"{CGenDaoBriefFieldMapping}" orphan:"true"`
// internal usage purpose.
genItems *CGenDaoInternalGenItems
}
CGenDaoOutput struct{}

View File

@ -40,7 +40,7 @@ func doClearItem(item CGenDaoInternalGenItem, allGeneratedFilePaths []string) {
}
for _, filePath := range generatedFilePaths {
if !gstr.InArray(allGeneratedFilePaths, filePath) {
if err := gfile.Remove(filePath); err != nil {
if err := gfile.RemoveFile(filePath); err != nil {
mlog.Print(err)
}
}

View File

@ -58,8 +58,8 @@ func generateDaoSingle(ctx context.Context, in generateDaoSingleInput) {
mlog.Fatalf(`fetching tables fields failed for table "%s": %+v`, in.TableName, err)
}
var (
tableNameCamelCase = gstr.CaseCamel(in.NewTableName)
tableNameCamelLowerCase = gstr.CaseCamelLower(in.NewTableName)
tableNameCamelCase = formatFieldName(in.NewTableName, FieldNameCaseCamel)
tableNameCamelLowerCase = formatFieldName(in.NewTableName, FieldNameCaseCamelLower)
tableNameSnakeCase = gstr.CaseSnake(in.NewTableName)
importPrefix = in.ImportPrefix
)
@ -116,13 +116,14 @@ func generateDaoIndex(in generateDaoIndexInput) {
tplVarTableName: in.TableName,
tplVarTableNameCamelCase: in.TableNameCamelCase,
tplVarTableNameCamelLowerCase: in.TableNameCamelLowerCase,
tplVarPackageName: filepath.Base(in.DaoPath),
})
indexContent = replaceDefaultVar(in.CGenDaoInternalInput, indexContent)
if err := gfile.PutContents(path, strings.TrimSpace(indexContent)); err != nil {
mlog.Fatalf("writing content to '%s' failed: %v", path, err)
} else {
utils.GoFmt(path)
mlog.Print("generated:", path)
mlog.Print("generated:", gfile.RealPath(path))
}
}
}
@ -156,7 +157,7 @@ func generateDaoInternal(in generateDaoInternalInput) {
mlog.Fatalf("writing content to '%s' failed: %v", path, err)
} else {
utils.GoFmt(path)
mlog.Print("generated:", path)
mlog.Print("generated:", gfile.RealPath(path))
}
}
@ -178,7 +179,7 @@ func generateColumnNamesForDao(fieldMap map[string]*gdb.TableField, removeFieldP
}
array[index] = []string{
" #" + gstr.CaseCamel(newFiledName) + ":",
" #" + formatFieldName(newFiledName, FieldNameCaseCamel) + ":",
fmt.Sprintf(` #"%s",`, field.Name),
}
}
@ -218,7 +219,7 @@ func generateColumnDefinitionForDao(fieldMap map[string]*gdb.TableField, removeF
newFiledName = gstr.TrimLeftStr(newFiledName, v, 1)
}
array[index] = []string{
" #" + gstr.CaseCamel(newFiledName),
" #" + formatFieldName(newFiledName, FieldNameCaseCamel),
" # " + "string",
" #" + fmt.Sprintf(`// %s`, comment),
}

View File

@ -40,7 +40,7 @@ func generateDo(ctx context.Context, in CGenDaoInternalInput) {
structDefinition, _ = generateStructDefinition(ctx, generateStructDefinitionInput{
CGenDaoInternalInput: in,
TableName: tableName,
StructName: gstr.CaseCamel(newTableName),
StructName: formatFieldName(newTableName, FieldNameCaseCamel),
FieldMap: fieldMap,
IsDo: true,
})
@ -61,7 +61,7 @@ func generateDo(ctx context.Context, in CGenDaoInternalInput) {
ctx,
in,
tableName,
gstr.CaseCamel(newTableName),
formatFieldName(newTableName, FieldNameCaseCamel),
structDefinition,
)
in.genItems.AppendGeneratedFilePath(doFilePath)
@ -70,7 +70,7 @@ func generateDo(ctx context.Context, in CGenDaoInternalInput) {
mlog.Fatalf(`writing content to "%s" failed: %v`, doFilePath, err)
} else {
utils.GoFmt(doFilePath)
mlog.Print("generated:", doFilePath)
mlog.Print("generated:", gfile.RealPath(doFilePath))
}
}
}
@ -85,6 +85,7 @@ func generateDoContent(
tplVarPackageImports: getImportPartContent(ctx, structDefine, true, nil),
tplVarTableNameCamelCase: tableNameCamelCase,
tplVarStructDefine: structDefine,
tplVarPackageName: filepath.Base(in.DoPath),
},
)
doContent = replaceDefaultVar(in, doContent)

View File

@ -36,7 +36,7 @@ func generateEntity(ctx context.Context, in CGenDaoInternalInput) {
structDefinition, appendImports = generateStructDefinition(ctx, generateStructDefinitionInput{
CGenDaoInternalInput: in,
TableName: tableName,
StructName: gstr.CaseCamel(newTableName),
StructName: formatFieldName(newTableName, FieldNameCaseCamel),
FieldMap: fieldMap,
IsDo: false,
})
@ -44,7 +44,7 @@ func generateEntity(ctx context.Context, in CGenDaoInternalInput) {
ctx,
in,
newTableName,
gstr.CaseCamel(newTableName),
formatFieldName(newTableName, FieldNameCaseCamel),
structDefinition,
appendImports,
)
@ -55,7 +55,7 @@ func generateEntity(ctx context.Context, in CGenDaoInternalInput) {
mlog.Fatalf("writing content to '%s' failed: %v", entityFilePath, err)
} else {
utils.GoFmt(entityFilePath)
mlog.Print("generated:", entityFilePath)
mlog.Print("generated:", gfile.RealPath(entityFilePath))
}
}
}
@ -70,6 +70,7 @@ func generateEntityContent(
tplVarPackageImports: getImportPartContent(ctx, structDefine, false, appendImports),
tplVarTableNameCamelCase: tableNameCamelCase,
tplVarStructDefine: structDefine,
tplVarPackageName: filepath.Base(in.EntityPath),
},
)
entityContent = replaceDefaultVar(in, entityContent)

View File

@ -99,7 +99,7 @@ func generateStructFieldDefinition(
}
localTypeNameStr = string(localTypeName)
switch localTypeName {
case gdb.LocalTypeDate, gdb.LocalTypeDatetime:
case gdb.LocalTypeDate, gdb.LocalTypeTime, gdb.LocalTypeDatetime:
if in.StdTime {
localTypeNameStr = "time.Time"
} else {
@ -140,7 +140,7 @@ func generateStructFieldDefinition(
}
attrLines = []string{
" #" + gstr.CaseCamel(newFiledName),
" #" + formatFieldName(newFiledName, FieldNameCaseCamel),
" #" + localTypeNameStr,
}
attrLines = append(attrLines, fmt.Sprintf(` #%sjson:"%s"`, tagKey, jsonTag))
@ -167,6 +167,43 @@ func generateStructFieldDefinition(
return attrLines, appendImport
}
type FieldNameCase string
const (
FieldNameCaseCamel FieldNameCase = "CaseCamel"
FieldNameCaseCamelLower FieldNameCase = "CaseCamelLower"
)
// formatFieldName formats and returns a new field name that is used for golang codes generating.
func formatFieldName(fieldName string, nameCase FieldNameCase) string {
// For normal databases like mysql, pgsql, sqlite,
// field/table names of that are in normal case.
var newFieldName = fieldName
if isAllUpper(fieldName) {
// For special databases like dm, oracle,
// field/table names of that are in upper case.
newFieldName = strings.ToLower(fieldName)
}
switch nameCase {
case FieldNameCaseCamel:
return gstr.CaseCamel(newFieldName)
case FieldNameCaseCamelLower:
return gstr.CaseCamelLower(newFieldName)
default:
return ""
}
}
// isAllUpper checks and returns whether given `fieldName` all letters are upper case.
func isAllUpper(fieldName string) bool {
for _, b := range fieldName {
if b >= 'a' && b <= 'z' {
return false
}
}
return true
}
// formatComment formats the comment string to fit the golang code without any lines.
func formatComment(comment string) string {
comment = gstr.ReplaceByArray(comment, g.SliceStr{

View File

@ -94,6 +94,9 @@ func (c CGenPb) Pb(ctx context.Context, in CGenPbInput) (out *CGenPbOutput, err
mlog.Fatalf(`no proto files found in folder "%s"`, in.Path)
}
var originPwd = gfile.Pwd()
defer gfile.Chdir(originPwd)
if err = gfile.Chdir(protoPath); err != nil {
mlog.Fatal(err)
}

View File

@ -12,6 +12,7 @@ import (
"github.com/gogf/gf/cmd/gf/v2/internal/utility/utils"
"github.com/gogf/gf/v2/container/gmap"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gfile"
"github.com/gogf/gf/v2/text/gregex"
"github.com/gogf/gf/v2/text/gstr"
@ -90,8 +91,12 @@ func (c CGenPb) tagCommentIntoListMap(comment string, lineTagMap *gmap.ListMap)
lineTagMap.Set(tagName, lineTagMap.GetVar(tagName).String()+tagContent)
} else {
var (
tagName = "dc"
tagContent = comment
tagName = "dc"
// Convert backticks and double quotes to single quotes.
tagContent = gstr.ReplaceByMap(comment, g.MapStrStr{
"`": `'`,
`"`: `'`,
})
)
lineTagMap.Set(tagName, lineTagMap.GetVar(tagName).String()+tagContent)
}

View File

@ -254,7 +254,7 @@ func generatePbEntityContentFile(ctx context.Context, in CGenPbEntityInternalInp
if err := gfile.PutContents(path, strings.TrimSpace(entityContent)); err != nil {
mlog.Fatalf("writing content to '%s' failed: %v", path, err)
} else {
mlog.Print("generated:", path)
mlog.Print("generated:", gfile.RealPath(path))
}
}

View File

@ -10,7 +10,11 @@ import (
"context"
"fmt"
"path/filepath"
"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"
@ -21,9 +25,6 @@ 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 (
@ -113,7 +114,7 @@ func (c CGenService) Service(ctx context.Context, in CGenServiceInput) (out *CGe
return
}
}
defer gfile.Remove(flockFilePath)
defer gfile.RemoveFile(flockFilePath)
_ = gfile.PutContents(flockFilePath, gtime.TimestampStr())
// It works only if given WatchFile is in SrcFolder.
@ -147,19 +148,22 @@ func (c CGenService) Service(ctx context.Context, in CGenServiceInput) (out *CGe
}
var (
isDirty bool // Temp boolean.
isDirty atomic.Value // Temp boolean.
files []string // Temp file array.
fileContent string // Temp file content for handling go file.
initImportSrcPackages []string // Used for generating logic.go.
inputPackages = in.Packages // Custom packages.
dstPackageName = gstr.ToLower(gfile.Basename(in.DstFolder)) // Package name for generated go files.
generatedDstFilePathSet = gset.NewStrSet() // All generated file path set.
)
isDirty.Store(false)
// The first level folders.
srcFolderPaths, err := gfile.ScanDir(in.SrcFolder, "*", false)
if err != nil {
return nil, err
}
// it will use goroutine to generate service files for each package.
var wg = sync.WaitGroup{}
for _, srcFolderPath := range srcFolderPaths {
if !gfile.IsDir(srcFolderPath) {
continue
@ -173,111 +177,30 @@ func (c CGenService) Service(ctx context.Context, in CGenServiceInput) (out *CGe
}
// Parse single logic package folder.
var (
// StructName => FunctionDefinitions
srcPkgInterfaceMap = gmap.NewListMap()
srcImportedPackages = garray.NewSortedStrArray().SetUnique(true)
importAliasToPathMap = gmap.NewStrStrMap() // for conflict imports check. alias => import path(with `"`)
importPathToAliasMap = gmap.NewStrStrMap() // for conflict imports check. import path(with `"`) => alias
srcPackageName = gfile.Basename(srcFolderPath)
ok bool
dstFilePath = gfile.Join(in.DstFolder,
srcPackageName = gfile.Basename(srcFolderPath)
srcImportedPackages = garray.NewSortedStrArray().SetUnique(true)
srcStructFunctions = gmap.NewListMap()
dstFilePath = gfile.Join(in.DstFolder,
c.getDstFileNameCase(srcPackageName, in.DstFileNameCase)+".go",
)
srcCodeCommentedMap = make(map[string]string)
)
generatedDstFilePathSet.Add(dstFilePath)
// if it were to use goroutine,
// it would cause the order of the generated functions in the file to be disordered.
for _, file := range files {
var packageItems []packageItem
fileContent = gfile.GetContents(file)
// Calculate code comments in source Go files.
err = c.calculateCodeCommented(in, fileContent, srcCodeCommentedMap)
if err != nil {
return nil, err
}
// remove all comments.
fileContent, err = gregex.ReplaceString(`(//.*)|((?s)/\*.*?\*/)`, "", fileContent)
pkgItems, funcItems, err := c.parseItemsInSrc(file)
if err != nil {
return nil, err
}
// Calculate imported packages of source go files.
packageItems, err = c.calculateImportedPackages(fileContent)
// Calculate imported packages for service generating.
err = c.calculateImportedItems(in, pkgItems, funcItems, srcImportedPackages)
if err != nil {
return nil, err
}
// try finding the conflicts imports between files.
for _, item := range packageItems {
var alias = item.Alias
if alias == "" {
alias = gfile.Basename(gstr.Trim(item.Path, `"`))
}
// ignore unused import paths, which do not exist in function definitions.
if !gregex.IsMatchString(fmt.Sprintf(`func .+?([^\w])%s(\.\w+).+?{`, alias), fileContent) {
mlog.Debugf(`ignore unused package: %s`, item.RawImport)
continue
}
// find the exist alias with the same import path.
var existAlias = importPathToAliasMap.Get(item.Path)
if existAlias != "" {
fileContent, err = gregex.ReplaceStringFuncMatch(
fmt.Sprintf(`([^\w])%s(\.\w+)`, alias), fileContent,
func(match []string) string {
return match[1] + existAlias + match[2]
},
)
if err != nil {
return nil, err
}
continue
}
// resolve alias conflicts.
var importPath = importAliasToPathMap.Get(alias)
if importPath == "" {
importAliasToPathMap.Set(alias, item.Path)
importPathToAliasMap.Set(item.Path, alias)
srcImportedPackages.Add(item.RawImport)
continue
}
if importPath != item.Path {
// update the conflicted alias for import path with suffix.
// eg:
// v1 -> v10
// v11 -> v110
for aliasIndex := 0; ; aliasIndex++ {
item.Alias = fmt.Sprintf(`%s%d`, alias, aliasIndex)
var existPathForAlias = importAliasToPathMap.Get(item.Alias)
if existPathForAlias != "" {
if existPathForAlias == item.Path {
break
}
continue
}
break
}
importPathToAliasMap.Set(item.Path, item.Alias)
importAliasToPathMap.Set(item.Alias, item.Path)
// reformat the import path with alias.
item.RawImport = fmt.Sprintf(`%s %s`, item.Alias, item.Path)
// update the file content with new alias import.
fileContent, err = gregex.ReplaceStringFuncMatch(
fmt.Sprintf(`([^\w])%s(\.\w+)`, alias), fileContent,
func(match []string) string {
return match[1] + item.Alias + match[2]
},
)
if err != nil {
return nil, err
}
srcImportedPackages.Add(item.RawImport)
}
}
// Calculate functions and interfaces for service generating.
err = c.calculateInterfaceFunctions(in, fileContent, srcPkgInterfaceMap)
err = c.calculateFuncItems(in, funcItems, srcStructFunctions)
if err != nil {
return nil, err
}
@ -295,22 +218,28 @@ func (c CGenService) Service(ctx context.Context, in CGenServiceInput) (out *CGe
)
continue
}
// Generating service go file for single logic package.
if ok, err = c.generateServiceFile(generateServiceFilesInput{
wg.Add(1)
go func(generateServiceFilesInput generateServiceFilesInput) {
defer wg.Done()
ok, err := c.generateServiceFile(generateServiceFilesInput)
if err != nil {
mlog.Printf(`error generating service file "%s": %v`, generateServiceFilesInput.DstFilePath, err)
}
if !isDirty.Load().(bool) && ok {
isDirty.Store(true)
}
}(generateServiceFilesInput{
CGenServiceInput: in,
SrcStructFunctions: srcPkgInterfaceMap,
SrcImportedPackages: srcImportedPackages.Slice(),
SrcPackageName: srcPackageName,
SrcImportedPackages: srcImportedPackages.Slice(),
SrcStructFunctions: srcStructFunctions,
DstPackageName: dstPackageName,
DstFilePath: dstFilePath,
SrcCodeCommentedMap: srcCodeCommentedMap,
}); err != nil {
return
}
if ok {
isDirty = true
}
})
}
wg.Wait()
if in.Clear {
files, err = gfile.ScanDirFile(in.DstFolder, "*.go", false)
@ -320,16 +249,18 @@ func (c CGenService) Service(ctx context.Context, in CGenServiceInput) (out *CGe
var relativeFilePath string
for _, file := range files {
relativeFilePath = gstr.SubStrFromR(file, in.DstFolder)
if !generatedDstFilePathSet.Contains(relativeFilePath) && utils.IsFileDoNotEdit(relativeFilePath) {
if !generatedDstFilePathSet.Contains(relativeFilePath) &&
utils.IsFileDoNotEdit(relativeFilePath) {
mlog.Printf(`remove no longer used service file: %s`, relativeFilePath)
if err = gfile.Remove(file); err != nil {
if err = gfile.RemoveFile(file); err != nil {
return nil, err
}
}
}
}
if isDirty {
if isDirty.Load().(bool) {
// Generate initialization go file.
if len(initImportSrcPackages) > 0 {
if err = c.generateInitializationFile(in, initImportSrcPackages); err != nil {
@ -358,7 +289,7 @@ func (c CGenService) checkAndUpdateMain(srcFolder string) (err error) {
var (
logicPackageName = gstr.ToLower(gfile.Basename(srcFolder))
logicFilePath = gfile.Join(srcFolder, logicPackageName+".go")
importPath = utils.GetImportPath(logicFilePath)
importPath = utils.GetImportPath(srcFolder)
importStr = fmt.Sprintf(`_ "%s"`, importPath)
mainFilePath = gfile.Join(gfile.Dir(gfile.Dir(gfile.Dir(logicFilePath))), "main.go")
mainFileContent = gfile.GetContents(mainFilePath)

View File

@ -0,0 +1,221 @@
// Copyright GoFrame gf Author(https://goframe.org). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://github.com/gogf/gf.
package genservice
import (
"go/ast"
"go/parser"
"go/token"
"github.com/gogf/gf/v2/os/gfile"
"github.com/gogf/gf/v2/text/gstr"
)
type pkgItem struct {
Alias string `eg:"gdbas"`
Path string `eg:"github.com/gogf/gf/v2/database/gdb"`
RawImport string `eg:"gdbas github.com/gogf/gf/v2/database/gdb"`
}
type funcItem struct {
Receiver string `eg:"sUser"`
MethodName string `eg:"GetList"`
Params []map[string]string `eg:"ctx: context.Context, cond: *SearchInput"`
Results []map[string]string `eg:"list: []*User, err: error"`
Comment string `eg:"Get user list"`
}
// parseItemsInSrc parses the pkgItem and funcItem from the specified file.
// It can't skip the private methods.
// It can't skip the imported packages of import alias equal to `_`.
func (c CGenService) parseItemsInSrc(filePath string) (pkgItems []pkgItem, funcItems []funcItem, err error) {
var (
fileContent = gfile.GetContents(filePath)
fileSet = token.NewFileSet()
)
node, err := parser.ParseFile(fileSet, "", fileContent, parser.ParseComments)
if err != nil {
return
}
ast.Inspect(node, func(n ast.Node) bool {
switch x := n.(type) {
case *ast.ImportSpec:
// parse the imported packages.
pkgItems = append(pkgItems, c.parseImportPackages(x))
case *ast.FuncDecl:
// parse the function items.
if x.Recv == nil {
return true
}
var funcName = x.Name.Name
funcItems = append(funcItems, funcItem{
Receiver: c.parseFuncReceiverTypeName(x),
MethodName: funcName,
Params: c.parseFuncParams(x),
Results: c.parseFuncResults(x),
Comment: c.parseFuncComment(x),
})
}
return true
})
return
}
// parseImportPackages retrieves the imported packages from the specified ast.ImportSpec.
func (c CGenService) parseImportPackages(node *ast.ImportSpec) (packages pkgItem) {
if node.Path == nil {
return
}
var (
alias string
path = node.Path.Value
rawImport string
)
if node.Name != nil {
alias = node.Name.Name
rawImport = node.Name.Name + " " + path
} else {
rawImport = path
}
// if the alias is empty, it will further retrieve the real alias.
if alias == "" {
alias = c.getRealAlias(path)
}
return pkgItem{
Alias: alias,
Path: path,
RawImport: rawImport,
}
}
// getRealAlias retrieves the real alias of the package.
// If package is "github.com/gogf/gf", the alias is "gf".
// If package is "github.com/gogf/gf/v2", the alias is "gf" instead of "v2".
func (c CGenService) getRealAlias(importPath string) (pkgName string) {
importPath = gstr.Trim(importPath, `"`)
parts := gstr.Split(importPath, "/")
if len(parts) == 0 {
return
}
pkgName = parts[len(parts)-1]
if !gstr.HasPrefix(pkgName, "v") {
return pkgName
}
if len(parts) < 2 {
return pkgName
}
if gstr.IsNumeric(gstr.SubStr(pkgName, 1)) {
pkgName = parts[len(parts)-2]
}
return pkgName
}
// parseFuncReceiverTypeName retrieves the receiver type of the function.
// For example:
//
// func(s *sArticle) -> *sArticle
// func(s sArticle) -> sArticle
func (c CGenService) parseFuncReceiverTypeName(node *ast.FuncDecl) (receiverType string) {
if node.Recv == nil {
return ""
}
receiverType, err := c.astExprToString(node.Recv.List[0].Type)
if err != nil {
return ""
}
return
}
// parseFuncParams retrieves the input parameters of the function.
// It returns the name and type of the input parameters.
// For example:
//
// []map[string]string{paramName:ctx paramType:context.Context, paramName:info paramType:struct{}}
func (c CGenService) parseFuncParams(node *ast.FuncDecl) (params []map[string]string) {
if node.Type.Params == nil {
return
}
for _, param := range node.Type.Params.List {
if param.Names == nil {
// No name for the return value.
resultType, err := c.astExprToString(param.Type)
if err != nil {
continue
}
params = append(params, map[string]string{
"paramName": "",
"paramType": resultType,
})
continue
}
for _, name := range param.Names {
paramType, err := c.astExprToString(param.Type)
if err != nil {
continue
}
params = append(params, map[string]string{
"paramName": name.Name,
"paramType": paramType,
})
}
}
return
}
// parseFuncResults retrieves the output parameters of the function.
// It returns the name and type of the output parameters.
// For example:
//
// []map[string]string{resultName:list resultType:[]*User, resultName:err resultType:error}
// []map[string]string{resultName: "", resultType: error}
func (c CGenService) parseFuncResults(node *ast.FuncDecl) (results []map[string]string) {
if node.Type.Results == nil {
return
}
for _, result := range node.Type.Results.List {
if result.Names == nil {
// No name for the return value.
resultType, err := c.astExprToString(result.Type)
if err != nil {
continue
}
results = append(results, map[string]string{
"resultName": "",
"resultType": resultType,
})
continue
}
for _, name := range result.Names {
resultType, err := c.astExprToString(result.Type)
if err != nil {
continue
}
results = append(results, map[string]string{
"resultName": name.Name,
"resultType": resultType,
})
}
}
return
}
// parseFuncComment retrieves the comment of the function.
func (c CGenService) parseFuncComment(node *ast.FuncDecl) string {
return c.astCommentToString(node.Doc)
}

View File

@ -0,0 +1,48 @@
// Copyright GoFrame gf Author(https://goframe.org). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://github.com/gogf/gf.
package genservice
import (
"bytes"
"go/ast"
"go/format"
"go/token"
"strings"
)
// exprToString converts ast.Expr to string.
// For example:
//
// ast.Expr -> "context.Context"
// ast.Expr -> "*v1.XxxReq"
// ast.Expr -> "error"
// ast.Expr -> "int"
func (c CGenService) astExprToString(expr ast.Expr) (string, error) {
var (
buf bytes.Buffer
err error
)
err = format.Node(&buf, token.NewFileSet(), expr)
if err != nil {
return "", err
}
return buf.String(), nil
}
// astCommentToString returns the raw (original) text of the comment.
// It includes the comment markers (//, /*, and */).
// It adds a newline at the end of the comment.
func (c CGenService) astCommentToString(node *ast.CommentGroup) string {
if node == nil {
return ""
}
var b strings.Builder
for _, c := range node.List {
b.WriteString(c.Text + "\n")
}
return b.String()
}

View File

@ -8,168 +8,145 @@ package genservice
import (
"fmt"
"go/parser"
"go/token"
"strings"
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
"github.com/gogf/gf/v2/container/garray"
"github.com/gogf/gf/v2/container/gmap"
"github.com/gogf/gf/v2/os/gfile"
"github.com/gogf/gf/v2/text/gregex"
"github.com/gogf/gf/v2/text/gstr"
)
type packageItem struct {
Alias string
Path string
RawImport string
}
func (c CGenService) calculateImportedPackages(fileContent string) (packages []packageItem, err error) {
f, err := parser.ParseFile(token.NewFileSet(), "", fileContent, parser.ImportsOnly)
if err != nil {
return nil, err
}
packages = make([]packageItem, 0)
for _, s := range f.Imports {
if s.Path != nil {
if s.Name != nil {
// If it has alias, and it is not `_`.
if pkgAlias := s.Name.String(); pkgAlias != "_" {
packages = append(packages, packageItem{
Alias: pkgAlias,
Path: s.Path.Value,
RawImport: pkgAlias + " " + s.Path.Value,
})
}
} else {
// no alias
packages = append(packages, packageItem{
Alias: "",
Path: s.Path.Value,
RawImport: s.Path.Value,
})
}
}
}
return packages, nil
}
func (c CGenService) calculateCodeCommented(in CGenServiceInput, fileContent string, srcCodeCommentedMap map[string]string) error {
matches, err := gregex.MatchAllString(`((((//.*)|(/\*[\s\S]*?\*/))\s)+)func \((.+?)\) ([\s\S]+?) {`, fileContent)
if err != nil {
return err
}
for _, match := range matches {
var (
structName string
structMatch []string
funcReceiver = gstr.Trim(match[1+5])
receiverArray = gstr.SplitAndTrim(funcReceiver, " ")
functionHead = gstr.Trim(gstr.Replace(match[2+5], "\n", ""))
commentedInfo = ""
)
if len(receiverArray) > 1 {
structName = receiverArray[1]
} else if len(receiverArray) == 1 {
structName = receiverArray[0]
}
structName = gstr.Trim(structName, "*")
// Case of:
// Xxx(\n ctx context.Context, req *v1.XxxReq,\n) -> Xxx(ctx context.Context, req *v1.XxxReq)
functionHead = gstr.Replace(functionHead, `,)`, `)`)
functionHead, _ = gregex.ReplaceString(`\(\s+`, `(`, functionHead)
functionHead, _ = gregex.ReplaceString(`\s{2,}`, ` `, functionHead)
if !gstr.IsLetterUpper(functionHead[0]) {
continue
}
// Match and pick the struct name from receiver.
if structMatch, err = gregex.MatchString(in.StPattern, structName); err != nil {
return err
}
if len(structMatch) < 1 {
continue
}
structName = gstr.CaseCamel(structMatch[1])
commentedInfo = match[1]
if len(commentedInfo) > 0 {
srcCodeCommentedMap[fmt.Sprintf("%s-%s", structName, functionHead)] = commentedInfo
}
}
return nil
}
func (c CGenService) calculateInterfaceFunctions(
in CGenServiceInput, fileContent string, srcPkgInterfaceMap *gmap.ListMap,
func (c CGenService) calculateImportedItems(
in CGenServiceInput,
pkgItems []pkgItem, funcItems []funcItem,
srcImportedPackages *garray.SortedStrArray,
) (err error) {
var (
matches [][]string
srcPkgInterfaceFuncArray *garray.StrArray
)
// calculate struct name and its functions according function definitions.
matches, err = gregex.MatchAllString(`func \((.+?)\) ([\s\S]+?) {`, fileContent)
if err != nil {
return err
}
for _, match := range matches {
var (
structName string
structMatch []string
funcReceiver = gstr.Trim(match[1])
receiverArray = gstr.SplitAndTrim(funcReceiver, " ")
functionHead = gstr.Trim(gstr.Replace(match[2], "\n", ""))
)
if len(receiverArray) > 1 {
structName = receiverArray[1]
} else if len(receiverArray) == 1 {
structName = receiverArray[0]
}
structName = gstr.Trim(structName, "*")
// allFuncParamType saves all the param and result types of the functions.
var allFuncParamType strings.Builder
// Case of:
// Xxx(\n ctx context.Context, req *v1.XxxReq,\n) -> Xxx(ctx context.Context, req *v1.XxxReq)
functionHead = gstr.Replace(functionHead, `,)`, `)`)
functionHead, _ = gregex.ReplaceString(`\(\s+`, `(`, functionHead)
functionHead, _ = gregex.ReplaceString(`\s{2,}`, ` `, functionHead)
if !gstr.IsLetterUpper(functionHead[0]) {
continue
for _, item := range funcItems {
for _, param := range item.Params {
allFuncParamType.WriteString(param["paramType"] + ",")
}
// Match and pick the struct name from receiver.
if structMatch, err = gregex.MatchString(in.StPattern, structName); err != nil {
return err
for _, result := range item.Results {
allFuncParamType.WriteString(result["resultType"] + ",")
}
if len(structMatch) < 1 {
continue
}
structName = gstr.CaseCamel(structMatch[1])
if !srcPkgInterfaceMap.Contains(structName) {
srcPkgInterfaceFuncArray = garray.NewStrArray()
srcPkgInterfaceMap.Set(structName, srcPkgInterfaceFuncArray)
} else {
srcPkgInterfaceFuncArray = srcPkgInterfaceMap.Get(structName).(*garray.StrArray)
}
srcPkgInterfaceFuncArray.Append(functionHead)
}
// calculate struct name according type definitions.
matches, err = gregex.MatchAllString(`type (.+) struct\s*{`, fileContent)
if err != nil {
return err
}
for _, match := range matches {
var (
structName string
structMatch []string
)
if structMatch, err = gregex.MatchString(in.StPattern, match[1]); err != nil {
return err
}
if len(structMatch) < 1 {
for _, item := range pkgItems {
alias := item.Alias
// If the alias is _, it means that the package is not generated.
if alias == "_" {
mlog.Debugf(`ignore anonymous package: %s`, item.RawImport)
continue
}
structName = gstr.CaseCamel(structMatch[1])
if !srcPkgInterfaceMap.Contains(structName) {
srcPkgInterfaceMap.Set(structName, garray.NewStrArray())
// If the alias is empty, it will use the package name as the alias.
if alias == "" {
alias = gfile.Basename(gstr.Trim(item.Path, `"`))
}
if !gstr.Contains(allFuncParamType.String(), alias) {
mlog.Debugf(`ignore unused package: %s`, item.RawImport)
continue
}
srcImportedPackages.Add(item.RawImport)
}
return nil
}
func (c CGenService) calculateFuncItems(
in CGenServiceInput,
funcItems []funcItem,
srcPkgInterfaceMap *gmap.ListMap,
) (err error) {
var srcPkgInterfaceFunc []map[string]string
for _, item := range funcItems {
var (
// eg: "sArticle"
receiverName string
receiverMatch []string
// eg: "GetList(ctx context.Context, req *v1.ArticleListReq) (list []*v1.Article, err error)"
funcHead string
)
// handle the receiver name.
if item.Receiver == "" {
continue
}
receiverName = item.Receiver
receiverName = gstr.Trim(receiverName, "*")
// Match and pick the struct name from receiver.
if receiverMatch, err = gregex.MatchString(in.StPattern, receiverName); err != nil {
return err
}
if len(receiverMatch) < 1 {
continue
}
receiverName = gstr.CaseCamel(receiverMatch[1])
// check if the func name is public.
if !gstr.IsLetterUpper(item.MethodName[0]) {
continue
}
if !srcPkgInterfaceMap.Contains(receiverName) {
srcPkgInterfaceFunc = make([]map[string]string, 0)
srcPkgInterfaceMap.Set(receiverName, srcPkgInterfaceFunc)
} else {
srcPkgInterfaceFunc = srcPkgInterfaceMap.Get(receiverName).([]map[string]string)
}
// make the func head.
paramsStr := c.tidyParam(item.Params)
resultsStr := c.tidyResult(item.Results)
funcHead = fmt.Sprintf("%s(%s) (%s)", item.MethodName, paramsStr, resultsStr)
srcPkgInterfaceFunc = append(srcPkgInterfaceFunc, map[string]string{
"funcHead": funcHead,
"funcComment": item.Comment,
})
srcPkgInterfaceMap.Set(receiverName, srcPkgInterfaceFunc)
}
return nil
}
// tidyParam tidies the input parameters.
// For example:
//
// []map[string]string{paramName:ctx paramType:context.Context, paramName:info paramType:struct{}}
// -> ctx context.Context, info struct{}
func (c CGenService) tidyParam(paramSlice []map[string]string) (paramStr string) {
for i, param := range paramSlice {
if i > 0 {
paramStr += ", "
}
paramStr += fmt.Sprintf("%s %s", param["paramName"], param["paramType"])
}
return
}
// tidyResult tidies the output parameters.
// For example:
//
// []map[string]string{resultName:list resultType:[]*User, resultName:err resultType:error}
// -> list []*User, err error
//
// []map[string]string{resultName: "", resultType: error}
// -> error
func (c CGenService) tidyResult(resultSlice []map[string]string) (resultStr string) {
for i, result := range resultSlice {
if i > 0 {
resultStr += ", "
}
if result["resultName"] != "" {
resultStr += fmt.Sprintf("%s %s", result["resultName"], result["resultType"])
} else {
resultStr += result["resultType"]
}
}
return
}

View File

@ -7,112 +7,34 @@
package genservice
import (
"bytes"
"fmt"
"github.com/gogf/gf/v2/container/garray"
"github.com/gogf/gf/v2/container/gmap"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gfile"
"github.com/gogf/gf/v2/text/gregex"
"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"
"github.com/gogf/gf/cmd/gf/v2/internal/utility/utils"
"github.com/gogf/gf/v2/container/gmap"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gfile"
"github.com/gogf/gf/v2/text/gstr"
)
type generateServiceFilesInput struct {
CGenServiceInput
DstFilePath string // Absolute file path for generated service go file.
SrcStructFunctions *gmap.ListMap
SrcImportedPackages []string
SrcPackageName string
SrcImportedPackages []string
SrcStructFunctions *gmap.ListMap
DstPackageName string
SrcCodeCommentedMap map[string]string
DstFilePath string // Absolute file path for generated service go file.
}
func (c CGenService) generateServiceFile(in generateServiceFilesInput) (ok bool, err error) {
var (
generatedContent string
allFuncArray = garray.NewStrArray() // Used for check whether interface dirty, going to change file content.
importedPackagesContent = fmt.Sprintf(
"import (\n%s\n)", gstr.Join(in.SrcImportedPackages, "\n"),
)
)
generatedContent += gstr.ReplaceByMap(consts.TemplateGenServiceContentHead, g.MapStrStr{
"{Imports}": importedPackagesContent,
"{PackageName}": in.DstPackageName,
})
var generatedContent bytes.Buffer
// Type definitions.
generatedContent += "type("
generatedContent += "\n"
in.SrcStructFunctions.Iterator(func(key, value interface{}) bool {
structName, funcArray := key.(string), value.(*garray.StrArray)
allFuncArray.Append(funcArray.Slice()...)
// Add comments to a method.
for index, funcName := range funcArray.Slice() {
if commentedInfo, exist := in.SrcCodeCommentedMap[fmt.Sprintf("%s-%s", structName, funcName)]; exist {
funcName = commentedInfo + funcName
_ = funcArray.Set(index, funcName)
}
}
generatedContent += gstr.Trim(gstr.ReplaceByMap(consts.TemplateGenServiceContentInterface, g.MapStrStr{
"{InterfaceName}": "I" + structName,
"{FuncDefinition}": funcArray.Join("\n\t"),
}))
generatedContent += "\n"
return true
})
generatedContent += ")"
generatedContent += "\n"
// Generating variable and register definitions.
var (
variableContent string
generatingInterfaceCheck string
)
// Variable definitions.
in.SrcStructFunctions.Iterator(func(key, value interface{}) bool {
structName := key.(string)
generatingInterfaceCheck = fmt.Sprintf(`[^\w\d]+%s.I%s[^\w\d]`, in.DstPackageName, structName)
if gregex.IsMatchString(generatingInterfaceCheck, generatedContent) {
return true
}
variableContent += gstr.Trim(gstr.ReplaceByMap(consts.TemplateGenServiceContentVariable, g.MapStrStr{
"{StructName}": structName,
"{InterfaceName}": "I" + structName,
}))
variableContent += "\n"
return true
})
if variableContent != "" {
generatedContent += "var("
generatedContent += "\n"
generatedContent += variableContent
generatedContent += ")"
generatedContent += "\n"
}
// Variable register function definitions.
in.SrcStructFunctions.Iterator(func(key, value interface{}) bool {
structName := key.(string)
generatingInterfaceCheck = fmt.Sprintf(`[^\w\d]+%s.I%s[^\w\d]`, in.DstPackageName, structName)
if gregex.IsMatchString(generatingInterfaceCheck, generatedContent) {
return true
}
generatedContent += gstr.Trim(gstr.ReplaceByMap(consts.TemplateGenServiceContentRegister, g.MapStrStr{
"{StructName}": structName,
"{InterfaceName}": "I" + structName,
}))
generatedContent += "\n\n"
return true
})
// Replace empty braces that have new line.
generatedContent, _ = gregex.ReplaceString(`{[\s\t]+}`, `{}`, generatedContent)
// Remove package name calls of `dstPackageName` in produced codes.
generatedContent, _ = gregex.ReplaceString(fmt.Sprintf(`\*{0,1}%s\.`, in.DstPackageName), ``, generatedContent)
c.generatePackageImports(&generatedContent, in.DstPackageName, in.SrcImportedPackages)
c.generateType(&generatedContent, in.SrcStructFunctions, in.DstPackageName)
c.generateVar(&generatedContent, in.SrcStructFunctions)
c.generateFunc(&generatedContent, in.SrcStructFunctions)
// Write file content to disk.
if gfile.Exists(in.DstFilePath) {
@ -120,59 +42,14 @@ func (c CGenService) generateServiceFile(in generateServiceFilesInput) (ok bool,
mlog.Printf(`ignore file as it is manually maintained: %s`, in.DstFilePath)
return false, nil
}
if !c.isToGenerateServiceGoFile(in.DstPackageName, in.DstFilePath, allFuncArray) {
mlog.Printf(`not dirty, ignore generating service go file: %s`, in.DstFilePath)
return false, nil
}
}
mlog.Printf(`generating service go file: %s`, in.DstFilePath)
if err = gfile.PutContents(in.DstFilePath, generatedContent); err != nil {
if err = gfile.PutBytes(in.DstFilePath, generatedContent.Bytes()); err != nil {
return true, err
}
return true, nil
}
// isToGenerateServiceGoFile checks and returns whether the service content dirty.
func (c CGenService) isToGenerateServiceGoFile(dstPackageName, filePath string, funcArray *garray.StrArray) bool {
var (
err error
fileContent = gfile.GetContents(filePath)
generatedFuncArray = garray.NewSortedStrArrayFrom(funcArray.Slice())
contentFuncArray = garray.NewSortedStrArray()
)
if fileContent == "" {
return true
}
// remove all comments.
fileContent, err = gregex.ReplaceString(`(//.*)|((?s)/\*.*?\*/)`, "", fileContent)
if err != nil {
panic(err)
return false
}
matches, _ := gregex.MatchAllString(`\s+interface\s+{([\s\S]+?)}`, fileContent)
for _, match := range matches {
contentFuncArray.Append(gstr.SplitAndTrim(match[1], "\n")...)
}
if generatedFuncArray.Len() != contentFuncArray.Len() {
mlog.Debugf(
`dirty, generatedFuncArray.Len()[%d] != contentFuncArray.Len()[%d]`,
generatedFuncArray.Len(), contentFuncArray.Len(),
)
return true
}
var funcDefinition string
for i := 0; i < generatedFuncArray.Len(); i++ {
funcDefinition, _ = gregex.ReplaceString(
fmt.Sprintf(`\*{0,1}%s\.`, dstPackageName), ``, generatedFuncArray.At(i),
)
if funcDefinition != contentFuncArray.At(i) {
mlog.Debugf(`dirty, %s != %s`, funcDefinition, contentFuncArray.At(i))
return true
}
}
return false
}
// generateInitializationFile generates `logic.go`.
func (c CGenService) generateInitializationFile(in CGenServiceInput, importSrcPackages []string) (err error) {
var (

View File

@ -0,0 +1,104 @@
// Copyright GoFrame gf Author(https://goframe.org). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://github.com/gogf/gf.
package genservice
import (
"bytes"
"fmt"
"github.com/gogf/gf/cmd/gf/v2/internal/consts"
"github.com/gogf/gf/v2/container/gmap"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/text/gregex"
"github.com/gogf/gf/v2/text/gstr"
)
func (c CGenService) generatePackageImports(generatedContent *bytes.Buffer, packageName string, imports []string) {
generatedContent.WriteString(gstr.ReplaceByMap(consts.TemplateGenServiceContentHead, g.MapStrStr{
"{PackageName}": packageName,
"{Imports}": fmt.Sprintf(
"import (\n%s\n)", gstr.Join(imports, "\n"),
),
}))
}
// generateType type definitions.
// See: const.TemplateGenServiceContentInterface
func (c CGenService) generateType(generatedContent *bytes.Buffer, srcStructFunctions *gmap.ListMap, dstPackageName string) {
generatedContent.WriteString("type(")
generatedContent.WriteString("\n")
srcStructFunctions.Iterator(func(key, value interface{}) bool {
var (
funcContents = make([]string, 0)
funcContent string
)
structName, funcSlice := key.(string), value.([]map[string]string)
// Generating interface content.
for _, funcInfo := range funcSlice {
// Remove package name calls of `dstPackageName` in produced codes.
funcHead, _ := gregex.ReplaceString(
fmt.Sprintf(`\*{0,1}%s\.`, dstPackageName),
``, funcInfo["funcHead"],
)
funcContent = funcInfo["funcComment"] + funcHead
funcContents = append(funcContents, funcContent)
}
// funcContents to string.
generatedContent.WriteString(
gstr.Trim(gstr.ReplaceByMap(consts.TemplateGenServiceContentInterface, g.MapStrStr{
"{InterfaceName}": "I" + structName,
"{FuncDefinition}": gstr.Join(funcContents, "\n\t"),
})),
)
generatedContent.WriteString("\n")
return true
})
generatedContent.WriteString(")")
generatedContent.WriteString("\n")
}
// generateVar variable definitions.
// See: const.TemplateGenServiceContentVariable
func (c CGenService) generateVar(generatedContent *bytes.Buffer, srcStructFunctions *gmap.ListMap) {
// Generating variable and register definitions.
var variableContent string
srcStructFunctions.Iterator(func(key, value interface{}) bool {
structName := key.(string)
variableContent += gstr.Trim(gstr.ReplaceByMap(consts.TemplateGenServiceContentVariable, g.MapStrStr{
"{StructName}": structName,
"{InterfaceName}": "I" + structName,
}))
variableContent += "\n"
return true
})
if variableContent != "" {
generatedContent.WriteString("var(")
generatedContent.WriteString("\n")
generatedContent.WriteString(variableContent)
generatedContent.WriteString(")")
generatedContent.WriteString("\n")
}
}
// generateFunc function definitions.
// See: const.TemplateGenServiceContentRegister
func (c CGenService) generateFunc(generatedContent *bytes.Buffer, srcStructFunctions *gmap.ListMap) {
// Variable register function definitions.
srcStructFunctions.Iterator(func(key, value interface{}) bool {
structName := key.(string)
generatedContent.WriteString(gstr.Trim(gstr.ReplaceByMap(consts.TemplateGenServiceContentRegister, g.MapStrStr{
"{StructName}": structName,
"{InterfaceName}": "I" + structName,
})))
generatedContent.WriteString("\n\n")
return true
})
}

View File

@ -2,11 +2,11 @@ module github.com/gogf/gf/cmd/gf/cmd/gf/testdata/vardump/v2
go 1.18
require github.com/gogf/gf/v2 v2.6.1
require github.com/gogf/gf/v2 v2.8.0
require (
go.opentelemetry.io/otel v1.14.0 // indirect
go.opentelemetry.io/otel/trace v1.14.0 // indirect
go.opentelemetry.io/otel v1.24.0 // indirect
go.opentelemetry.io/otel/trace v1.24.0 // indirect
)
replace github.com/gogf/gf/v2 => ../../../../../../../

View File

@ -1,26 +1,29 @@
github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8=
github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0=
github.com/clbanning/mxj/v2 v2.7.0 h1:WA/La7UGCanFe5NpHF0Q3DNtnCsVoxbPKuyBNHWRyME=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
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.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0=
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
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/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
go.opentelemetry.io/otel v1.14.0 h1:/79Huy8wbf5DnIPhemGB+zEPVwnN6fuQybr/SRXa6hM=
go.opentelemetry.io/otel v1.14.0/go.mod h1:o4buv+dJzx8rohcUeRmWUZhqupFvzWis188WlggnNeU=
go.opentelemetry.io/otel/sdk v1.14.0 h1:PDCppFRDq8A1jL9v6KMI6dYesaq+DFcDZvjsoGvxGzY=
go.opentelemetry.io/otel/trace v1.14.0 h1:wp2Mmvj41tDsyAJXiWDWpfNsOiIyd38fy85pyKcFq/M=
go.opentelemetry.io/otel/trace v1.14.0/go.mod h1:8avnQLK+CG77yNLUae4ea2JDQ6iT+gozhnZjy/rw9G8=
golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w=
golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
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=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=

View File

@ -21,3 +21,11 @@ type UpdateReq struct {
}
type UpdateRes struct{}
//type GetListReq struct {
// g.Meta `path:"/article/list" method:"get" tags:"ArticleService"`
//}
//
//type GetListRes struct {
// list []struct{}
//}

View File

@ -0,0 +1,83 @@
// ==========================================================================
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
// ==========================================================================
package internal
import (
"context"
"github.com/gogf/gf/v2/database/gdb"
"github.com/gogf/gf/v2/frame/g"
)
// TableUserDao is the data access object for table table_user.
type TableUserDao struct {
table string // table is the underlying table name of the DAO.
group string // group is the database configuration group name of current DAO.
columns TableUserColumns // columns contains all the column names of Table for convenient usage.
}
// TableUserColumns defines and stores column names for table table_user.
type TableUserColumns struct {
Id string //
Passport string //
Password string //
Nickname string //
CreatedAt string //
UpdatedAt string //
}
// tableUserColumns holds the columns for table table_user.
var tableUserColumns = TableUserColumns{
Id: "id",
Passport: "passport",
Password: "password",
Nickname: "nickname",
CreatedAt: "created_at",
UpdatedAt: "updated_at",
}
// NewTableUserDao creates and returns a new DAO object for table data access.
func NewTableUserDao() *TableUserDao {
return &TableUserDao{
group: "test",
table: "table_user",
columns: tableUserColumns,
}
}
// DB retrieves and returns the underlying raw database management object of current DAO.
func (dao *TableUserDao) DB() gdb.DB {
return g.DB(dao.group)
}
// Table returns the table name of current dao.
func (dao *TableUserDao) Table() string {
return dao.table
}
// Columns returns all column names of current dao.
func (dao *TableUserDao) Columns() TableUserColumns {
return dao.columns
}
// Group returns the configuration group name of database of current dao.
func (dao *TableUserDao) Group() string {
return dao.group
}
// Ctx creates and returns the Model for current DAO, It automatically sets the context for current operation.
func (dao *TableUserDao) Ctx(ctx context.Context) *gdb.Model {
return dao.DB().Model(dao.table).Safe().Ctx(ctx)
}
// Transaction wraps the transaction logic using function f.
// It rollbacks the transaction and returns the error from function f if it returns non-nil error.
// It commits the transaction and returns nil if function f returns nil.
//
// Note that, you should not Commit or Rollback the transaction in function f
// as it is automatically handled by this function.
func (dao *TableUserDao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) {
return dao.Ctx(ctx).Transaction(ctx, f)
}

View File

@ -0,0 +1,27 @@
// =================================================================================
// This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish.
// =================================================================================
package dao
import (
"for-gendao-test/pkg/dao/internal"
)
// internalTableUserDao is internal type for wrapping internal DAO implements.
type internalTableUserDao = *internal.TableUserDao
// tableUserDao is the data access object for table table_user.
// You can define custom methods on it to extend its functionality as you wish.
type tableUserDao struct {
internalTableUserDao
}
var (
// TableUser is globally public accessible object for table table_user operations.
TableUser = tableUserDao{
internal.NewTableUserDao(),
}
)
// Fill with you ideas below.

View File

@ -0,0 +1,21 @@
// =================================================================================
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
// =================================================================================
package do
import (
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gtime"
)
// TableUser is the golang structure of table table_user for DAO operations like Where/Data.
type TableUser struct {
g.Meta `orm:"table:table_user, do:true"`
Id interface{} //
Passport interface{} //
Password interface{} //
Nickname interface{} //
CreatedAt *gtime.Time //
UpdatedAt *gtime.Time //
}

View File

@ -0,0 +1,19 @@
// =================================================================================
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
// =================================================================================
package entity
import (
"github.com/gogf/gf/v2/os/gtime"
)
// TableUser is the golang structure for table table_user.
type TableUser struct {
Id int `json:"id" orm:"id" ` //
Passport string `json:"passport" orm:"passport" ` //
Password string `json:"password" orm:"password" ` //
Nickname string `json:"nickname" orm:"nickname" ` //
CreatedAt *gtime.Time `json:"createdAt" orm:"created_at" ` //
UpdatedAt *gtime.Time `json:"updatedAt" orm:"updated_at" ` //
}

View File

@ -0,0 +1,8 @@
create table `%s`(
id INTEGER PRIMARY KEY AUTOINCREMENT UNIQUE,
passport VARCHAR(45) NOT NULL DEFAULT passport,
password VARCHAR(128) NOT NULL DEFAULT password,
nickname VARCHAR(45),
created_at TIMESTAMP,
updated_at TIMESTAMP
)

View File

@ -8,8 +8,11 @@ package article
import (
"context"
"go/ast"
t "time"
"github.com/gogf/gf/cmd/gf/v2/internal/cmd/testdata/genservice/service"
gdbalias "github.com/gogf/gf/v2/database/gdb"
)
type sArticle struct {
@ -30,5 +33,15 @@ func (s *sArticle) Get(ctx context.Context, id uint) (info struct{}, err error)
* @author oldme
*/
func (s *sArticle) Create(ctx context.Context, info struct{}) (id uint, err error) {
// Use time package to test alias import.
t.Now()
return id, err
}
func (s *sArticle) A1o2(ctx context.Context, str string, a, b *ast.GoStmt) error {
return nil
}
func (s *sArticle) B_2(ctx context.Context, db gdbalias.Raw) (err error) {
return nil
}

View File

@ -0,0 +1,75 @@
// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://github.com/gogf/gf.
package article
// import (
// "context"
//
// "github.com/gogf/gf/cmd/gf/v2/internal/cmd/testdata/genservice/service"
// )
import (
"context"
// This is a random comment
gdbas "github.com/gogf/gf/v2/database/gdb"
/**
*
*/
_ "github.com/gogf/gf/v2/os/gfile"
)
// T1 random comment
func (s sArticle) T1(ctx context.Context, id, id2 uint) (gdb gdbas.Model, err error) {
g := gdbas.Model{}
return g, err
}
// I'm a random comment
// t2 random comment
func (s *sArticle) t2(ctx context.Context) (err error) {
/**
* random comment
* i (1). func (s *sArticle) t2(ctx context.Context) (err error) { /** 1883
*
*/
_ = func(ctx2 context.Context) {}
return nil
}
// T3
/**
* random comment @*4213hHY1&%##%><<Y
* @param b
* @return c, d
* @return err
* @author oldme
*/
func (s *sArticle) T3(ctx context.Context, b *gdbas.Model) (c, d *gdbas.Model, err error) {
/* import (
* "context"
*
* "github.com/gogf/gf/cmd/gf/v2/internal/cmd/testdata/genservice/service"
*/
return nil, nil, nil
}
/**
* random comment
*/
// func (s *sArticle) T4(i interface{}) interface{}
// # $ % ^ & * ( ) _ + - = { } | [ ] \ : " ; ' < > ? , . /
func (s *sArticle) T4(i interface{}) interface{} {
return nil
}
/**
* func (s *sArticle) T4(i interface{}) interface{} {
* return nil
* }
*/

View File

@ -0,0 +1,38 @@
// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://github.com/gogf/gf.
package delivery
import (
"context"
"github.com/gogf/gf/cmd/gf/v2/internal/cmd/testdata/genservice/service"
)
type sDeliveryApp struct{}
func NewDeliveryApp() *sDeliveryApp {
return &sDeliveryApp{}
}
func (s *sDeliveryApp) Create(ctx context.Context) (i service.IDeliveryCluster, err error) {
return
}
func (s *sDeliveryApp) GetList(ctx context.Context, i service.IDeliveryCluster) (err error) {
service.Article().Get(ctx, 1)
return
}
func (s *sDeliveryApp) GetOne(ctx context.Context) (err error) {
return
}
func (s *sDeliveryApp) Delete(ctx context.Context) (err error) {
return
}
func (s *sDeliveryApp) AA(ctx context.Context) (err error) { return }

View File

@ -0,0 +1,32 @@
// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://github.com/gogf/gf.
package delivery
import (
"context"
gdbas "github.com/gogf/gf/v2/database/gdb"
)
type sDeliveryCluster struct{}
func NewDeliveryCluster() *sDeliveryCluster {
return &sDeliveryCluster{}
}
// Create 自动创建Cluster及Project.
func (s *sDeliveryCluster) Create(ctx context.Context) (err error, gdb gdbas.Model) {
return
}
func (s *sDeliveryCluster) Delete(ctx context.Context) (err error) {
return
}
func (s *sDeliveryCluster) GetList(ctx context.Context) (err error) {
return
}

View File

@ -6,4 +6,6 @@ package logic
import (
_ "github.com/gogf/gf/cmd/gf/v2/internal/cmd/testdata/genservice/logic/article"
_ "github.com/gogf/gf/cmd/gf/v2/internal/cmd/testdata/genservice/logic/delivery"
_ "github.com/gogf/gf/cmd/gf/v2/internal/cmd/testdata/genservice/logic/user"
)

View File

@ -0,0 +1,49 @@
// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://github.com/gogf/gf.
package user
import (
"context"
"github.com/gogf/gf/cmd/gf/v2/internal/cmd/testdata/genservice/service"
)
func init() {
service.RegisterUser(New())
}
type sUser struct {
}
func New() *sUser {
return &sUser{}
}
// Create creates a new user.
func (s *sUser) Create(ctx context.Context, name string) (id int, err error) {
return 0, nil
}
// GetOne retrieves user by id.
func (s *sUser) GetOne(ctx context.Context, id int) (name string, err error) {
return "", nil
}
// GetList retrieves user list.
func (s *sUser) GetList(ctx context.Context) (names []string, err error) {
return nil, nil
}
// Update updates user by id.
func (s *sUser) Update(ctx context.Context, id int) (name string, err error) {
return "", nil
}
// Delete deletes user by id.
func (s *sUser) Delete(ctx context.Context, id int) (err error) {
return nil
}

View File

@ -7,6 +7,10 @@ package service
import (
"context"
"go/ast"
gdbalias "github.com/gogf/gf/v2/database/gdb"
gdbas "github.com/gogf/gf/v2/database/gdb"
)
type (
@ -19,6 +23,22 @@ type (
* @author oldme
*/
Create(ctx context.Context, info struct{}) (id uint, err error)
A1o2(ctx context.Context, str string, a *ast.GoStmt, b *ast.GoStmt) error
B_2(ctx context.Context, db gdbalias.Raw) (err error)
// T1 random comment
T1(ctx context.Context, id uint, id2 uint) (gdb gdbas.Model, err error)
// T3
/**
* random comment @*4213hHY1&%##%><<Y
* @param b
* @return c, d
* @return err
* @author oldme
*/
T3(ctx context.Context, b *gdbas.Model) (c *gdbas.Model, d *gdbas.Model, err error)
// func (s *sArticle) T4(i interface{}) interface{}
// # $ % ^ & * ( ) _ + - = { } | [ ] \ : " ; ' < > ? , . /
T4(i interface{}) interface{}
}
)

View File

@ -0,0 +1,55 @@
// ================================================================================
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
// You can delete these comments if you wish manually maintain this interface file.
// ================================================================================
package service
import (
"context"
gdbas "github.com/gogf/gf/v2/database/gdb"
)
type (
IDeliveryApp interface {
Create(ctx context.Context) (i IDeliveryCluster, err error)
GetList(ctx context.Context, i IDeliveryCluster) (err error)
GetOne(ctx context.Context) (err error)
Delete(ctx context.Context) (err error)
AA(ctx context.Context) (err error)
}
IDeliveryCluster interface {
// Create 自动创建Cluster及Project.
Create(ctx context.Context) (err error, gdb gdbas.Model)
Delete(ctx context.Context) (err error)
GetList(ctx context.Context) (err error)
}
)
var (
localDeliveryApp IDeliveryApp
localDeliveryCluster IDeliveryCluster
)
func DeliveryApp() IDeliveryApp {
if localDeliveryApp == nil {
panic("implement not found for interface IDeliveryApp, forgot register?")
}
return localDeliveryApp
}
func RegisterDeliveryApp(i IDeliveryApp) {
localDeliveryApp = i
}
func DeliveryCluster() IDeliveryCluster {
if localDeliveryCluster == nil {
panic("implement not found for interface IDeliveryCluster, forgot register?")
}
return localDeliveryCluster
}
func RegisterDeliveryCluster(i IDeliveryCluster) {
localDeliveryCluster = i
}

View File

@ -0,0 +1,40 @@
// ================================================================================
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
// You can delete these comments if you wish manually maintain this interface file.
// ================================================================================
package service
import (
"context"
)
type (
IUser interface {
// Create creates a new user.
Create(ctx context.Context, name string) (id int, err error)
// GetOne retrieves user by id.
GetOne(ctx context.Context, id int) (name string, err error)
// GetList retrieves user list.
GetList(ctx context.Context) (names []string, err error)
// Update updates user by id.
Update(ctx context.Context, id int) (name string, err error)
// Delete deletes user by id.
Delete(ctx context.Context, id int) (err error)
}
)
var (
localUser IUser
)
func User() IUser {
if localUser == nil {
panic("implement not found for interface IUser, forgot register?")
}
return localUser
}
func RegisterUser(i IUser) {
localUser = i
}

View File

View File

@ -0,0 +1,85 @@
// ==========================================================================
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
// ==========================================================================
package internal
import (
"context"
"github.com/gogf/gf/v2/database/gdb"
"github.com/gogf/gf/v2/frame/g"
)
// TableUserDao is the data access object for table table_user.
type TableUserDao struct {
table string // table is the underlying table name of the DAO.
group string // group is the database configuration group name of current DAO.
columns TableUserColumns // columns contains all the column names of Table for convenient usage.
}
// TableUserColumns defines and stores column names for table table_user.
type TableUserColumns struct {
Id string // User ID
ParentId string //
Passport string // User Passport
PassWord string // User Password
Nickname2 string // User Nickname
CreateAt string // Created Time
UpdateAt string // Updated Time
}
// tableUserColumns holds the columns for table table_user.
var tableUserColumns = TableUserColumns{
Id: "Id",
ParentId: "parentId",
Passport: "PASSPORT",
PassWord: "PASS_WORD",
Nickname2: "NICKNAME2",
CreateAt: "create_at",
UpdateAt: "update_at",
}
// NewTableUserDao creates and returns a new DAO object for table data access.
func NewTableUserDao() *TableUserDao {
return &TableUserDao{
group: "test",
table: "table_user",
columns: tableUserColumns,
}
}
// DB retrieves and returns the underlying raw database management object of current DAO.
func (dao *TableUserDao) DB() gdb.DB {
return g.DB(dao.group)
}
// Table returns the table name of current dao.
func (dao *TableUserDao) Table() string {
return dao.table
}
// Columns returns all column names of current dao.
func (dao *TableUserDao) Columns() TableUserColumns {
return dao.columns
}
// Group returns the configuration group name of database of current dao.
func (dao *TableUserDao) Group() string {
return dao.group
}
// Ctx creates and returns the Model for current DAO, It automatically sets the context for current operation.
func (dao *TableUserDao) Ctx(ctx context.Context) *gdb.Model {
return dao.DB().Model(dao.table).Safe().Ctx(ctx)
}
// Transaction wraps the transaction logic using function f.
// It rollbacks the transaction and returns the error from function f if it returns non-nil error.
// It commits the transaction and returns nil if function f returns nil.
//
// Note that, you should not Commit or Rollback the transaction in function f
// as it is automatically handled by this function.
func (dao *TableUserDao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) {
return dao.Ctx(ctx).Transaction(ctx, f)
}

View File

@ -0,0 +1,27 @@
// =================================================================================
// This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish.
// =================================================================================
package dao
import (
"for-gendao-test/pkg/dao/internal"
)
// internalTableUserDao is internal type for wrapping internal DAO implements.
type internalTableUserDao = *internal.TableUserDao
// tableUserDao is the data access object for table table_user.
// You can define custom methods on it to extend its functionality as you wish.
type tableUserDao struct {
internalTableUserDao
}
var (
// TableUser is globally public accessible object for table table_user operations.
TableUser = tableUserDao{
internal.NewTableUserDao(),
}
)
// Fill with you ideas below.

View File

@ -0,0 +1,22 @@
// =================================================================================
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
// =================================================================================
package do
import (
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gtime"
)
// TableUser is the golang structure of table table_user for DAO operations like Where/Data.
type TableUser struct {
g.Meta `orm:"table:table_user, do:true"`
Id interface{} // User ID
ParentId interface{} //
Passport interface{} // User Passport
PassWord interface{} // User Password
Nickname2 interface{} // User Nickname
CreateAt *gtime.Time // Created Time
UpdateAt *gtime.Time // Updated Time
}

View File

@ -0,0 +1,20 @@
// =================================================================================
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
// =================================================================================
package entity
import (
"github.com/gogf/gf/v2/os/gtime"
)
// TableUser is the golang structure for table table_user.
type TableUser struct {
Id uint `json:"id" orm:"Id" ` // User ID
ParentId string `json:"parentId" orm:"parentId" ` //
Passport string `json:"pASSPORT" orm:"PASSPORT" ` // User Passport
PassWord string `json:"pASSWORD" orm:"PASS_WORD" ` // User Password
Nickname2 string `json:"nICKNAME2" orm:"NICKNAME2" ` // User Nickname
CreateAt *gtime.Time `json:"createAt" orm:"create_at" ` // Created Time
UpdateAt *gtime.Time `json:"updateAt" orm:"update_at" ` // Updated Time
}

View File

@ -0,0 +1,10 @@
CREATE TABLE `%s` (
`Id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'User ID',
`parentId` varchar(45) NOT NULL COMMENT '',
`PASSPORT` varchar(45) NOT NULL COMMENT 'User Passport',
`PASS_WORD` varchar(45) NOT NULL COMMENT 'User Password',
`NICKNAME2` varchar(45) NOT NULL COMMENT 'User Nickname',
`create_at` datetime DEFAULT NULL COMMENT 'Created Time',
`update_at` datetime DEFAULT NULL COMMENT 'Updated Time',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

View File

@ -0,0 +1,23 @@
package issue3835
import (
"context"
"github.com/gogf/gf/cmd/gf/v2/internal/cmd/testdata/issue/3835/service"
"github.com/gogf/gf/contrib/drivers/mysql/v2"
)
func init() {
service.RegisterItest(New())
}
type sItest struct {
}
func New() *sItest {
return &sItest{}
}
func (s *sItest) F(ctx context.Context) (d mysql.Driver, err error) {
return mysql.Driver{}, nil
}

View File

@ -0,0 +1,9 @@
// ==========================================================================
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
// ==========================================================================
package logic
import (
_ "github.com/gogf/gf/cmd/gf/v2/internal/cmd/testdata/issue/3835/logic/issue3835"
)

View File

@ -0,0 +1,33 @@
// ================================================================================
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
// You can delete these comments if you wish manually maintain this interface file.
// ================================================================================
package service
import (
"context"
"github.com/gogf/gf/contrib/drivers/mysql/v2"
)
type (
IItest interface {
F(ctx context.Context) (d mysql.Driver, err error)
}
)
var (
localItest IItest
)
func Itest() IItest {
if localItest == nil {
panic("implement not found for interface IItest, forgot register?")
}
return localItest
}
func RegisterItest(i IItest) {
localItest = i
}

View File

@ -0,0 +1,10 @@
syntax = "proto3";
package test;
option go_package = "github.com/gogf/gf/cmd/gf/test";
message SomeMessage {
// Some comment on field with "one" `two` 'three' in the comment.
string field = 1;
}

View File

@ -11,7 +11,7 @@ const TemplateGenDaoIndexContent = `
// This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish.
// =================================================================================
package dao
package {TplPackageName}
import (
"{TplImportPrefix}/internal"

View File

@ -11,7 +11,7 @@ const TemplateGenDaoDoContent = `
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. {TplCreatedAtDatetimeStr}
// =================================================================================
package do
package {TplPackageName}
{TplPackageImports}

View File

@ -11,7 +11,7 @@ const TemplateGenDaoEntityContent = `
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. {TplCreatedAtDatetimeStr}
// =================================================================================
package entity
package {TplPackageName}
{TplPackageImports}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -75,28 +75,24 @@ func ReplaceGeneratedContentGFV2(folderPath string) (err error) {
}, folderPath, "*.go", true)
}
// GetImportPath calculates and returns the golang import path for given `filePath`.
// GetImportPath calculates and returns the golang import path for given `dirPath`.
// Note that it needs a `go.mod` in current working directory or parent directories to detect the path.
func GetImportPath(filePath string) string {
func GetImportPath(dirPath string) string {
// If `filePath` does not exist, create it firstly to find the import path.
var realPath = gfile.RealPath(filePath)
var realPath = gfile.RealPath(dirPath)
if realPath == "" {
_ = gfile.Mkdir(filePath)
realPath = gfile.RealPath(filePath)
_ = gfile.Mkdir(dirPath)
realPath = gfile.RealPath(dirPath)
}
var (
newDir = gfile.Dir(realPath)
oldDir string
suffix string
suffix = gfile.Basename(dirPath)
goModName = "go.mod"
goModPath string
importPath string
)
if gfile.IsDir(filePath) {
suffix = gfile.Basename(filePath)
}
for {
goModPath = gfile.Join(newDir, goModName)
if gfile.Exists(goModPath) {

View File

@ -5,7 +5,8 @@
// You can obtain one at https://github.com/gogf/gf.
//
// Package glist provides most commonly used doubly linked list container which also supports concurrent-safe/unsafe switch feature.
// Package glist provides most commonly used doubly linked list container which also supports
// concurrent-safe/unsafe switch feature.
package glist
import (

View File

@ -291,7 +291,7 @@ func TestRemove(t *testing.T) {
})
}
func TestIssue4103(t *testing.T) {
func Test_Issue4103(t *testing.T) {
l1 := New()
l1.PushBack(1)
l1.PushBack(2)
@ -312,7 +312,7 @@ func TestIssue4103(t *testing.T) {
}
}
func TestIssue6349(t *testing.T) {
func Test_Issue6349(t *testing.T) {
l := New()
l.PushBack(1)
l.PushBack(2)

View File

@ -45,9 +45,7 @@ func NewAnyAnyMapFrom(data map[interface{}]interface{}, safe ...bool) *AnyAnyMap
// Iterator iterates the hash map readonly with custom callback function `f`.
// If `f` returns true, then it continues iterating; or false to stop.
func (m *AnyAnyMap) Iterator(f func(k interface{}, v interface{}) bool) {
m.mu.RLock()
defer m.mu.RUnlock()
for k, v := range m.data {
for k, v := range m.Map() {
if !f(k, v) {
break
}

View File

@ -46,9 +46,7 @@ func NewIntAnyMapFrom(data map[int]interface{}, safe ...bool) *IntAnyMap {
// Iterator iterates the hash map readonly with custom callback function `f`.
// If `f` returns true, then it continues iterating; or false to stop.
func (m *IntAnyMap) Iterator(f func(k int, v interface{}) bool) {
m.mu.RLock()
defer m.mu.RUnlock()
for k, v := range m.data {
for k, v := range m.Map() {
if !f(k, v) {
break
}

View File

@ -42,9 +42,7 @@ func NewIntIntMapFrom(data map[int]int, safe ...bool) *IntIntMap {
// Iterator iterates the hash map readonly with custom callback function `f`.
// If `f` returns true, then it continues iterating; or false to stop.
func (m *IntIntMap) Iterator(f func(k int, v int) bool) {
m.mu.RLock()
defer m.mu.RUnlock()
for k, v := range m.data {
for k, v := range m.Map() {
if !f(k, v) {
break
}

View File

@ -42,9 +42,7 @@ func NewIntStrMapFrom(data map[int]string, safe ...bool) *IntStrMap {
// Iterator iterates the hash map readonly with custom callback function `f`.
// If `f` returns true, then it continues iterating; or false to stop.
func (m *IntStrMap) Iterator(f func(k int, v string) bool) {
m.mu.RLock()
defer m.mu.RUnlock()
for k, v := range m.data {
for k, v := range m.Map() {
if !f(k, v) {
break
}

View File

@ -47,9 +47,7 @@ func NewStrAnyMapFrom(data map[string]interface{}, safe ...bool) *StrAnyMap {
// Iterator iterates the hash map readonly with custom callback function `f`.
// If `f` returns true, then it continues iterating; or false to stop.
func (m *StrAnyMap) Iterator(f func(k string, v interface{}) bool) {
m.mu.RLock()
defer m.mu.RUnlock()
for k, v := range m.data {
for k, v := range m.Map() {
if !f(k, v) {
break
}

View File

@ -43,9 +43,7 @@ func NewStrIntMapFrom(data map[string]int, safe ...bool) *StrIntMap {
// Iterator iterates the hash map readonly with custom callback function `f`.
// If `f` returns true, then it continues iterating; or false to stop.
func (m *StrIntMap) Iterator(f func(k string, v int) bool) {
m.mu.RLock()
defer m.mu.RUnlock()
for k, v := range m.data {
for k, v := range m.Map() {
if !f(k, v) {
break
}

View File

@ -43,9 +43,7 @@ func NewStrStrMapFrom(data map[string]string, safe ...bool) *StrStrMap {
// Iterator iterates the hash map readonly with custom callback function `f`.
// If `f` returns true, then it continues iterating; or false to stop.
func (m *StrStrMap) Iterator(f func(k string, v string) bool) {
m.mu.RLock()
defer m.mu.RUnlock()
for k, v := range m.data {
for k, v := range m.Map() {
if !f(k, v) {
break
}

View File

@ -110,6 +110,22 @@ func Test_AnyAnyMap_Batch(t *testing.T) {
})
}
func Test_AnyAnyMap_Iterator_Deadlock(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
m := gmap.NewAnyAnyMapFrom(map[interface{}]interface{}{1: 1, 2: "2", "3": "3", "4": 4}, true)
m.Iterator(func(k interface{}, _ interface{}) bool {
if gconv.Int(k)%2 == 0 {
m.Remove(k)
}
return true
})
t.Assert(m.Map(), map[interface{}]interface{}{
1: 1,
"3": "3",
})
})
}
func Test_AnyAnyMap_Iterator(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
expect := map[interface{}]interface{}{1: 1, 2: "2"}

View File

@ -118,6 +118,22 @@ func Test_IntAnyMap_Batch(t *testing.T) {
})
}
func Test_IntAnyMap_Iterator_Deadlock(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
m := gmap.NewIntAnyMapFrom(map[int]interface{}{1: 1, 2: 2, 3: "3", 4: 4}, true)
m.Iterator(func(k int, _ interface{}) bool {
if k%2 == 0 {
m.Remove(k)
}
return true
})
t.Assert(m.Map(), map[int]interface{}{
1: 1,
3: "3",
})
})
}
func Test_IntAnyMap_Iterator(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
expect := map[int]interface{}{1: 1, 2: "2"}

View File

@ -127,6 +127,22 @@ func Test_IntIntMap_Batch(t *testing.T) {
})
}
func Test_IntIntMap_Iterator_Deadlock(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
m := gmap.NewIntIntMapFrom(map[int]int{1: 1, 2: 2, 3: 3, 4: 4}, true)
m.Iterator(func(k int, _ int) bool {
if k%2 == 0 {
m.Remove(k)
}
return true
})
t.Assert(m.Map(), map[int]int{
1: 1,
3: 3,
})
})
}
func Test_IntIntMap_Iterator(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
expect := map[int]int{1: 1, 2: 2}

Some files were not shown because too many files have changed in this diff Show More