Compare commits

...

293 Commits

Author SHA1 Message Date
cf37731d5f version: v2.7.1 (#3573) 2024-05-14 21:20:22 +08:00
0765741d99 os/gtime: fix #3558 time zone issues (#3561) 2024-05-10 17:44:45 +08:00
74338c498e ci: fix code coverage not sync to CodeCov (#3570) 2024-05-10 17:44:01 +08:00
ff28d88572 cmd/gf: fix gen enums failed in go version v1.22.1 (#3565) 2024-05-07 20:40:35 +08:00
94c7185826 util/gvalid: fix slice enums verification failed (#3566) 2024-05-07 20:36:55 +08:00
8e075fba53 contrib/sdk/httpclient: add custom response handler support, fixe #3539 (#3540) 2024-04-29 20:37:25 +08:00
3b1d1d33b8 other: update some issue templates (#3544) 2024-04-29 19:37:57 +08:00
ac6604730a cmd/gf: fix pbentity generate fail in mono-repo (#3547) 2024-04-29 19:27:15 +08:00
3cdd9ef36e cmd/gf: fix command gf gen dao for fieldMapping feature (#3549) 2024-04-29 19:22:02 +08:00
9aa426a105 database/gdb/gdb_model_soft_time: fix soft-time support fieldType:LocalTypeUint64 in Insert/Update perations (#3551) 2024-04-29 19:00:51 +08:00
5b7cae78bc feat: add custom field type mapping support for command gf gen dao (#3498) 2024-04-25 19:19:09 +08:00
cc98e5759c fix: #3200 empty content in glog handler after structure logging feature supported (#3475) 2024-04-25 19:13:50 +08:00
12ff9af431 test/gtest: add support for string type in AssertIN and AssertNI (#3537) 2024-04-24 21:04:54 +08:00
aa6d83fe1c other: enhance Issues and Pull Requests template (#3533) 2024-04-24 19:20:34 +08:00
f48ca959f7 chore: fix function names in comment (#3536) 2024-04-24 19:14:42 +08:00
59a959a361 fix: #3459 gf gen dao should ignore link configuration from file as it is passed from arguments (#3531) 2024-04-23 21:43:45 +08:00
ce57b26769 cmd/gf: fix unit testing cases for compatibility with windows (#3532) 2024-04-23 21:39:11 +08:00
adc94fd97a fix: uint testing case for signal feature of package gproc occasionally failed (#3529) 2024-04-23 21:30:33 +08:00
1013df1627 enhance: improve performance of struct converting for package gconv (#3412) 2024-04-23 21:30:06 +08:00
646ed5ea14 enhance: upgrade version of dependencies (#3526) 2024-04-22 19:59:59 +08:00
a39e6a2c62 enhance: gf gen ctrl with -merge option (#3490) 2024-04-18 20:12:02 +08:00
fa4f31f3dd chore: fix function names in comments for package otelmetric (#3493) 2024-04-18 20:04:23 +08:00
adb813fbad enhance: upgrade version of dependencies (#3494) 2024-04-18 20:02:27 +08:00
ebe567dab2 fix: missing file closding when printing downloading percent of gf cli file for command gf up (#3483) 2024-04-16 19:49:09 +08:00
bbcf49db98 fix: #3238 first column might be overwritten in interal context data in multiple goroutines querying (#3476) 2024-04-16 19:31:06 +08:00
75763735c4 enhance: improve command gf gen ctrl using AST for parsing DstFolder (#3478) 2024-04-15 20:16:44 +08:00
285e5a0580 fix: file name example/pack/packed/paked.go → example/pack/packed/packed.go (#3479) 2024-04-15 20:11:01 +08:00
2ee0c2bdac fix: sqlitecgo to support 32-bit architecture (#3480) 2024-04-15 10:03:49 +08:00
ae58dc846a fix: missing arguments on Windows platform for package gproc (#3482) 2024-04-15 09:59:35 +08:00
91f449dff8 feat: add new rule required-if-all for package gvalid (#3455) 2024-04-11 19:45:09 +08:00
2523889765 enhance: improve gf gen ctrl using AST (#3470) 2024-04-11 19:15:31 +08:00
4c6b146627 feat: add Scan method for incremental key retrieval in gredis (#3451) 2024-04-11 15:37:22 +08:00
6e2d238f56 emhace: unit testing cases update for package cmd/gf and contrib/drivers (#3453) 2024-04-10 20:55:09 +08:00
d7a0482146 fix: #3465 If the value of a string is null, the value of string is nil after the string is converted to []string (#3468) 2024-04-10 20:18:03 +08:00
b040654574 enhance: add ORM tag to the entity result of command gen dao to make entity assignment more faster (#3454) 2024-04-07 19:19:07 +08:00
505fc25a64 fix: fsnotify watcher panics when closing (#3399) 2024-04-07 14:12:03 +08:00
83ba887df7 fix: #3449 accept slice parameter as json.RawMessage for http request (#3452) 2024-04-07 14:09:52 +08:00
911f1cb1de enhance: use map iter to iterate the map instead of map keys and values (#3457) 2024-04-07 10:00:04 +08:00
1b7aea0ced feat: add metrics option and prometheus handler wraps (#3445) 2024-04-07 09:57:13 +08:00
x
db5eed17b1 fix: invalid cache key using pointer address of variable for soft time fields (#3448) 2024-04-02 20:10:16 +08:00
1ffb510a77 feat: add custom go module configuration support when initialize go project using command gf init (#3425) 2024-04-02 14:05:22 +08:00
f039393b2b fix: map converting in loop logic of validation for package gvalid (#3423) 2024-04-01 19:23:12 +08:00
00ba053ce6 enhance: use in-memory cache for soft field name and type (#3420) 2024-04-01 19:22:23 +08:00
dcf1f19ff7 enhance: Save operation support for mssql (#3365) 2024-04-01 19:18:54 +08:00
06826750ed enhance: improve Save feature for drivers oracle and dm (#3426) 2024-04-01 19:08:26 +08:00
e0a2645f4a fix: #3390 name&shor tag mapping failed to command input object for package gcmd (#3429) 2024-04-01 19:07:08 +08:00
509fdf45c6 feat: add auth support in address configuration for etcd registry (#3439) 2024-03-29 19:19:45 +08:00
1e7d897b66 fix: lost trace content in occasion when shutting down trace (#3418) 2024-03-29 10:08:58 +08:00
6df0a9ca66 fix: the cron job with precise second time pattern might be executed twice in the same time (#3437) 2024-03-28 22:09:11 +08:00
1c12f3a30d fix: http superfluous response.WriteHeader call in some scenario (#3428) 2024-03-28 22:08:54 +08:00
3a9e0e34ca fix: #3432 Add Access-Control-Expose-Headers: Content-Disposition header in ServeFileDownload (#3433) 2024-03-28 20:07:56 +08:00
8669512f42 feat: add metric feature support in goframe (#3138) 2024-03-24 21:18:30 +08:00
313d9d138f fix: unit testing cases of contrib/drivers occasionally failed by using now time assertion (#3410) 2024-03-21 21:57:33 +08:00
040118b7c6 fix: #3370 fixed process parameter parsing failed on Windows for package gproc (#3386) 2024-03-20 19:58:42 +08:00
b3f48212f1 fix: #3362 IsEmpty panics when some interface implement panics with nil receiver (#3367) 2024-03-20 19:52:12 +08:00
cade0775e8 enhance: Save operation support for contrib/drivers/dm (#3404) 2024-03-20 19:18:25 +08:00
164aad48c3 fix: unit test of dm failed occasionally (#3382) 2024-03-19 19:40:52 +08:00
04756d05a7 fix: fix lost log directory path for grapc log (#3387) 2024-03-18 19:14:31 +08:00
409041b965 enhance: support save for Oracle (#3364) 2024-03-13 20:11:45 +08:00
11f7187367 fix: unit test of dm failed occasionally (#3369) 2024-03-13 19:29:41 +08:00
4feda4c395 enhance: do not ignore error from gdb.FormatMultiLineSqlToSingle func (#3368) 2024-03-13 19:22:17 +08:00
a8713da97f enhance: cut tracing content as unicode for safety (#3342) 2024-03-13 19:21:16 +08:00
199737cd0f fix: for typo in comments for package contrib/drivers and gdb (#3366) 2024-03-12 20:40:20 +08:00
3a8f246569 fix: unit test error in PgSQL and SQLite; Unified t.Assert(err, nil) to t.AssertNil(err) (#3356) 2024-03-12 20:05:03 +08:00
607f079b23 fix: cache value assertion panic if the cache adapter is not in-memory for soft time feature of package gdb; improve converting performance for gconv.Scan (#3351) 2024-03-07 11:36:42 +08:00
cab6b89446 enhance: update contrib/drivers/README.MD (#3355) 2024-03-07 11:34:49 +08:00
6ed3038312 feat: version v2.6.4 (#3352) 2024-03-07 10:12:58 +08:00
9b48da459e enhance: add sentinel auth config for redis (#3348) 2024-03-06 19:27:52 +08:00
fbd266fad0 enhance: add Save operation support for SQLite #2764 (#3315) 2024-03-06 19:22:58 +08:00
240dadff92 fix: WherePri function wrong in pgsql #3330 (#3339) 2024-03-06 19:19:07 +08:00
290f4a3e65 fix: recognize json_valid constraint as json field type for database mariadb #2746 (#3309) 2024-03-06 19:07:31 +08:00
97fcd9d726 enhance: improve FormatUpsert implements for pgsql (#3349) 2024-03-06 19:05:13 +08:00
df15d70466 enhance: change tracing span name from request uri to router uri for http request (#3338) 2024-03-05 21:11:27 +08:00
680ae8616b fix: generated dao go files forcely cleared by command gf gen dao if clear set true (#3337) 2024-03-05 20:49:19 +08:00
4feb8219fa feat: upgrade set-go version and add go 1.22 version (#3316) 2024-03-04 20:18:31 +08:00
509cc47d3f enhance: add Save operation support for pgsql #3053 (#3324) 2024-03-04 20:17:43 +08:00
849b104c31 enhance: gproc.signal enhance #3325 (#3326) 2024-03-04 20:10:05 +08:00
ce3ef13e6a fix: otel tracing content contains invalid UTF-8 (#3340) 2024-02-29 20:22:42 +08:00
rio
c8a73f8c25 nacos-sdk-go upgrade to v2 (#3334) 2024-02-28 21:52:32 +08:00
b71ee13ccd fix error code comment on i18n defaultLanguage value (#3335) 2024-02-28 21:51:43 +08:00
a347cdc30e fix github pages ci (#3331) 2024-02-28 19:20:37 +08:00
39a88ef650 fix typo (#3332) 2024-02-27 21:09:43 +08:00
8b156e25c4 enhance mysql_z_unit_model_test (#3329) 2024-02-27 21:07:31 +08:00
eb0c4b3824 fix #3226 (#3322) 2024-02-27 20:37:49 +08:00
56ef0c0735 fix issue command gf run -w takes no effect (#3321) 2024-02-27 20:33:57 +08:00
a1a9465e52 add ExampleCache_Clear (#3310) 2024-02-27 19:42:58 +08:00
d64a31fd1a new version v2.6.3 (#3308) 2024-02-07 17:11:36 +08:00
6cdf044320 fix issue #2616 (#3307) 2024-02-07 16:47:41 +08:00
5307f0742e add # for cron pattern that can ignore seconds, which makes the cron pattern running in minimum minute like linux crontab pattern (#3306) 2024-02-07 15:38:24 +08:00
51326f3d02 fix #3245 (#3298) 2024-02-06 11:47:25 +08:00
e1fa99013a use iota to unify the enums definition (#3305) 2024-02-06 11:44:29 +08:00
72014689e4 fix issue #2643 (#3304) 2024-02-06 10:21:44 +08:00
2acdf4bb47 add field type detection for soft time field like created_at/updated_at/deleted_at to support unix timestamp or bool deleting table field (#3293) 2024-02-06 10:21:23 +08:00
85c5b7f19e fix issue #2594 (#3303) 2024-02-05 20:40:03 +08:00
42ec1a0076 fix issue #2572 (#3301) 2024-02-05 19:20:05 +08:00
553cc45e54 fix empty pwd path read from gfile.Pwd() which could cause internal error logging for gview.New (#3302) 2024-02-05 16:49:44 +08:00
7415ec32c8 fix issue #2503 (#3299) 2024-02-05 10:30:03 +08:00
14568562e3 fix issue #2552 (#3300) 2024-02-05 10:29:43 +08:00
cc79d23334 fix issue #2457 (#3297) 2024-02-02 10:57:24 +08:00
ef2b47d180 fix issue #3292 (#3294) 2024-02-01 16:02:36 +08:00
adc056f547 feat: support running commands via non-command line arguments (#3290) 2024-01-30 20:14:13 +08:00
8266a16b4e fix issue #3286 (#3289) 2024-01-30 20:03:58 +08:00
c4a51f4c2f bugfix:fix gconv map deep option not effective (#3287) 2024-01-29 19:52:04 +08:00
4ddc9c3909 add offline document link in readme.md (#3284) 2024-01-25 20:47:21 +08:00
0a2f8abb40 Update annotation for redis.toml (#3282) 2024-01-24 20:37:41 +08:00
81de5d3f25 fix workflow script for cli building and release (#3279) 2024-01-24 20:36:50 +08:00
e6d61e6e14 fix error in gerror.HasCode (#3277) 2024-01-24 20:36:32 +08:00
4fb739615b version v2.6.2 (#3276) 2024-01-22 21:53:10 +08:00
ba39323d30 improve converter feature for package gconv (#3211) 2024-01-22 21:52:54 +08:00
383937fe69 add example for ctx keys feature of package glog (#3273) 2024-01-22 21:07:40 +08:00
Bob
f919f90bf5 rename gitee issue template (#3274)
rename gitee ISSUE_TEMPLATE.MD to ISSUE_TEMPLATE
2024-01-22 21:07:04 +08:00
b4f6f06ab5 no printing internal middleware for ghttp.Server (#3271) 2024-01-22 21:05:40 +08:00
73fbca40ca add internal error logging and update comments for gclient.RequestVar (#3270) 2024-01-18 10:21:38 +08:00
e8d3fcac6b feat: upgrade gitee sync Hub Mirror Action (#3272) 2024-01-18 10:21:14 +08:00
f87182d5b8 fix workflow for gitee sync (#3269) 2024-01-17 20:27:41 +08:00
951f8921cd fix #3237 (#3267) 2024-01-17 15:35:48 +08:00
d26b7c5437 fix some wrong comment (#3265) 2024-01-16 14:08:07 +08:00
9407fda197 add example for exporting prometheus metrics using ghttp.Server (#3266) 2024-01-16 14:07:49 +08:00
905913f7be Fix gf gen service bug. Fix the issue of significant differences in the generated code every … (#3260) 2024-01-15 20:35:14 +08:00
4b8eaac73f fix issue #3232 (#3247) 2024-01-15 20:33:30 +08:00
ca242ff401 fix #3251 (#3254) 2024-01-11 22:15:22 +08:00
42e3c5f39a fix #3253 (#3255) 2024-01-11 22:14:22 +08:00
4f4d2c2f8e add MiddlewareNeverDoneCtx for package ghttp (#3250) 2024-01-06 13:03:49 +08:00
Gin
5a01798481 fix: memory leak when gcache.NewAdapterMemory with lru (#3241) 2024-01-03 20:03:19 +08:00
8af1eb693e Update README.MD (#3243) 2024-01-03 19:49:06 +08:00
335ccb32af Update Github issue template (#3234) 2024-01-02 20:42:14 +08:00
e1f2666499 add example for serve file (#3193) 2024-01-02 20:19:40 +08:00
22fcfdf755 add configuration support for logger of grpcx.Server (#3223) 2024-01-02 20:19:05 +08:00
1e21b61a19 fix typo flie -> file (#3228) 2024-01-02 20:17:54 +08:00
6abd8bd864 comments update for package gstr (#3233) 2024-01-02 20:16:51 +08:00
cy
4876ae0e2b fix:gz files are compressed repeatedly every time tick (#3236) 2024-01-02 20:10:57 +08:00
63bdf41d40 fix #3191 (#3194) 2023-12-28 20:18:29 +08:00
984cca8b82 feat: update dependent redoc js for swagger ui (#3217) 2023-12-28 20:13:21 +08:00
9f7ce42c74 enhance #3221 (#3224) 2023-12-28 20:07:07 +08:00
16a43bcb6c Add comment for Format method so that you can know Layout method. (#3230) 2023-12-26 16:19:59 +08:00
85d95e3e27 version v2.6.1 (#3222) 2023-12-21 21:12:51 +08:00
4cce8557e6 fix: #2924 (#3177) 2023-12-21 10:16:14 +08:00
d60d7674d7 fix issues for package contrib/drivers/dm (#3157) 2023-12-20 20:33:58 +08:00
7f9467d1f8 fix: #2938 (#3178) 2023-12-20 20:25:23 +08:00
d08e3ef838 fix: #2689 change sessionId in cookie (#3203) 2023-12-20 20:21:15 +08:00
645c5ff5b5 fix issue #3218 #3204 (#3220) 2023-12-19 21:58:12 +08:00
7975e391f0 Version/v2.6.0 (#3213) 2023-12-18 20:59:09 +08:00
565790036e improve gen dao to support removeFieldPrefix (#3208) 2023-12-18 20:26:43 +08:00
44819b135e fix issue #3204 (#3212) 2023-12-18 20:19:18 +08:00
bb19877430 fix: #3197 (#3206) 2023-12-18 19:11:39 +08:00
fc02e06423 doc: update readme img (#3207) 2023-12-15 15:56:08 +08:00
dd8a5dcf32 fix: #3179 (#3195) 2023-12-14 21:51:28 +08:00
33584506ab fix issue: request body was closed while retrying in callRequest method (#3199) 2023-12-14 14:18:31 +08:00
ee2cf92479 Version/v2.6.0 beta (#3183) 2023-12-04 19:34:48 +08:00
0b6dd6fb13 improve initialization performance and logging content for cmd gf (#3174) 2023-11-30 18:59:49 +08:00
993467bb3c test: add date-format test for RFC3339 (#3181) 2023-11-29 19:12:21 +08:00
c7c9f0011a fix: #2967 (#3175) 2023-11-29 19:05:21 +08:00
9aa872e705 improve map converting feature using MapOption for package gconv (#3170) 2023-11-23 18:59:04 +08:00
ea5d52cb2f fix issue #3147 (#3161) 2023-11-22 21:05:39 +08:00
b1754f8254 script updates for version upgrading (#3169) 2023-11-22 20:49:07 +08:00
83f08b3135 fix issue in Join stements with prefix specified for package gdb (#3151) 2023-11-20 20:47:26 +08:00
d3d1f94e40 Upgrade nacos sdk to latest version (#3166) 2023-11-20 20:47:00 +08:00
fc8572e8dd version v2.5.7 (#3162) 2023-11-20 10:01:54 +08:00
85acd3d31d Fix the bug that ScanAndCount and AllAndCount report errors in sqlserver (#3155) 2023-11-16 20:15:48 +08:00
9694a68211 Optimize the information display of gf -v (#3145) 2023-11-16 20:10:45 +08:00
0be8b29e42 improve gen service code (#3140) 2023-11-14 20:53:41 +08:00
5580ac9475 fix issue in cross-building failed in windows (#3152) 2023-11-14 20:10:49 +08:00
84ed66018e fix issue: Windows Platform did not handle process signal (#3154) 2023-11-14 20:00:26 +08:00
4d7f9552fe fix: gdb unsupport aliyun hologres link (#3150) 2023-11-13 22:05:53 +08:00
d4b14fd717 add gen service unit testing (#3142) 2023-11-09 20:04:05 +08:00
0bd15bdab5 fix: "gf gen dao" utils.GetModPath Return empty string in windows (#3141) 2023-11-09 20:02:47 +08:00
0b407c5e6d fix "gf gen pb" api and ctrl not working well. (#3076) 2023-11-08 21:26:51 +08:00
5f5b82188c example: log rotate (#3137) 2023-11-08 21:23:39 +08:00
a17849bc39 improve struct converting in parameter name case sensitive scenario for package gconv (#3122) 2023-11-08 21:17:55 +08:00
f3e3a5af5a feat: improve code for shutdown of otel (#3136) 2023-11-08 21:16:23 +08:00
dc71c0d28f enhance #3129 (#3134) 2023-11-06 19:27:26 +08:00
eb99f5ebfe rename function name PKCS5UnPadding to PKCS7UnPadding (#3124) 2023-11-06 19:20:07 +08:00
007fe0ea1a enhance #3063 (#3115) 2023-11-06 09:59:45 +08:00
50b04c658c improve implements and fix issues for package contrib/drivers/dm (#3128) 2023-11-06 09:52:36 +08:00
cbea89e6f7 fix duplicated route dump for package ghttp (#3116) 2023-11-02 09:48:39 +08:00
e2e12fadb0 add function CaseConvert for package gstr (#3098) 2023-11-01 19:52:07 +08:00
47eaa513c0 add unit testing cases for command gen ctrl (#3090) 2023-11-01 19:23:03 +08:00
3bbc0fdd21 add Output configuration support for command gf build in cross-buildling binary scenario (#3120) 2023-11-01 19:18:44 +08:00
9393072745 improve TemplateGenCtrlController is comments and formats (#3065) 2023-10-31 20:21:18 +08:00
e42aa64d75 improve impelements for logging file rotation in windows (#3080) 2023-10-31 20:19:01 +08:00
b6935a7285 fix(goai): example value needs to be converted just like default value (#3085) 2023-10-31 20:18:39 +08:00
b0367e4a62 fix: gRPC-Go HTTP/2 Rapid Reset vulnerability (#3095) 2023-10-31 20:17:39 +08:00
0b71bc43a8 fix issue #3099 (#3107) 2023-10-31 20:02:20 +08:00
Gin
afeca8cf9d fix: nacos mod (#3103) 2023-10-31 10:04:51 +08:00
sam
33c396fb74 fix cmd gen pbentity for generating go orm files for database postgres (#3105) 2023-10-31 10:04:07 +08:00
4903ef7887 fix issue #3100 (#3106) 2023-10-30 20:27:48 +08:00
ab5ab4c675 Add the Protocol attribute to the Redis configuration (#3109) 2023-10-30 20:11:23 +08:00
3ea61d084e fix issue #3086 (#3089) 2023-10-26 10:04:21 +08:00
2433b2ce99 ignore cmd/gf/go.work.sum from version controll (#3087) 2023-10-25 21:17:21 +08:00
927758a2a9 fix separator issue in windows os for command gf gen (#3088) 2023-10-25 21:16:05 +08:00
cb0d018fa4 feat: upgrade version and improve consul action (#3078) 2023-10-24 20:36:01 +08:00
49f69f6ade Update README.MD (#3082) 2023-10-24 20:33:10 +08:00
bcb479aabb fix issue #3077 (#3081) 2023-10-24 10:02:04 +08:00
db59f4232f add README and example cases for nacos registry (#3075) 2023-10-23 20:04:39 +08:00
aa625d24bc add example for http rate llimit (#3072) 2023-10-23 20:02:37 +08:00
36cfbaaa22 README.MD updates for cli installation (#3071) 2023-10-23 20:00:10 +08:00
f8462b5218 split ci workflow into two workflows for short (#3069) 2023-10-23 19:28:26 +08:00
b2bd12a371 version v2.5.5 (#3068) 2023-10-20 10:21:04 +08:00
acf2307eb9 fix issue #2963 (#3062) 2023-10-19 19:58:19 +08:00
93964ee231 delete repeat code in ut for package ghttp (#3058) 2023-10-18 20:04:07 +08:00
943939ba2b improve cache duration from second to millisecond for redis adapter of package gcache (#3052) 2023-10-18 20:02:23 +08:00
f1b5a223bf add go workspace for cmd/gf, to enable go install for cmd/gf (#3040) 2023-10-18 20:01:16 +08:00
bb9cd37fab add SetNoUrlEncode/NoUrlEncode functions for gclient.Client (#3041) 2023-10-17 21:19:59 +08:00
972f8c3aff improve comments for package gconv (#3057) 2023-10-17 21:09:46 +08:00
34e522306d resolve response is gzip in internalMiddlewareServerTracing (#3055) 2023-10-17 20:35:56 +08:00
7c92c2f7e8 improve comments and variable names for gcfg.AdapterFile of package gcfg (#3046) 2023-10-17 20:12:07 +08:00
5204bdb60d add option merge controlling generating controller files into one single file for command gf gen ctrl (#3045) 2023-10-17 20:11:23 +08:00
6ab8d065d1 fix:incorrect parameter passing causes captured errors to be lost (#3048) 2023-10-16 21:20:21 +08:00
d4e686226b improve version checks for ci script (#3047) 2023-10-16 21:18:23 +08:00
19d7714503 fix security issue for golang.org/x packages (#3042) 2023-10-16 20:45:43 +08:00
f464f30e6f improve comment of router feature for ghttp.Server (#3014) 2023-10-16 20:41:10 +08:00
XG
0e7d7d1eee feat: add -w/--watchPaths for subcommand gf run (#3009) 2023-10-12 21:07:51 +08:00
6af66a0201 add service registry implements using nacos (#2995) 2023-10-12 21:06:37 +08:00
81f3ad043d ci: Update action script to remove inactive labels (#3013) 2023-10-11 21:39:20 +08:00
ca7450f595 enable go cache for ci, coverage of ut testing is only available after merge of pr (#3011) 2023-10-11 21:38:43 +08:00
65192a7f92 fix issue gconv struct slice/map of json.RawMessage (#3006) (#3008) 2023-10-11 21:35:27 +08:00
8c309ac9fe fix issue #2907 (#3005) 2023-10-11 21:34:17 +08:00
7f1ce2aff3 fix issue #2904 (#3004) 2023-10-11 21:33:51 +08:00
10b67fc7b0 fix issues #2980 (#2994) 2023-10-11 21:28:53 +08:00
3cd005911d fix issue reading resource from manage in function New of package gres (#2961) 2023-10-10 20:02:52 +08:00
d10d96800f temporaryly close the testing of package kubecm to avoid disk unavailable issue (#3007) 2023-10-10 14:09:58 +08:00
35e5f1f204 feat: Migrate the service call tracing to use otlphttp or otlpgrpc for reporting (#3001) 2023-10-09 20:09:20 +08:00
1efdb72990 add direct service address support for grpc client (#2991) 2023-10-09 20:03:45 +08:00
8d925d4741 fix issue #2890 (#3002) 2023-10-09 20:00:08 +08:00
d6362cad16 add List2/List3/ListAndTrim2/ListAndTrim3 functions for package gstr (#2986) 2023-10-09 19:58:14 +08:00
00e83fed3f add function Partition for Model of package gdb (#2989) 2023-10-08 09:49:21 +08:00
02f1cc7b40 allowing use printToStdout, printToFile and printToWriter at the same time for Logger of package glog (#2990) 2023-10-07 20:46:24 +08:00
32a60c2e96 Add consul config adapter usage example. (#2988) 2023-10-07 20:19:47 +08:00
30040332a7 improve address configuration for grpc server (#2982) 2023-09-27 14:40:32 +08:00
569cbb09bf fix: improve specification version (#2987) 2023-09-26 22:03:18 +08:00
130191f4ed add in:header tag cache for http request to enhance performance (#2923) 2023-09-25 21:34:58 +08:00
e6732039c6 add consul config adapter (#2964) 2023-09-25 21:02:55 +08:00
df92c483d0 fix isue #2976, to be compatible with bad response type definition for strict route function (#2977) 2023-09-25 20:40:32 +08:00
7c9eefef3d feat: Preserve original file permissions & Default copy permissions c… (#2969) 2023-09-19 20:20:13 +08:00
42de1c1dbe improve example cases for package gi18n (#2970) 2023-09-19 20:18:43 +08:00
395df940d7 fix(gutil): panic when field is []byte(BINARY in mysql) (#2957) 2023-09-18 20:16:59 +08:00
ef1e18df19 fix: gutil.IsMap judgment logic error (#2953) 2023-09-13 19:30:02 +08:00
e684eae878 Make GTime support multiple formats (#2933) 2023-09-13 19:29:25 +08:00
5219c5c37e add ut cases for command gen dao (#2958) 2023-09-12 22:00:35 +08:00
5059abd88e upgrade dependence github.com/apolloconfig/agollo/v4 version from v4.1.1 to v4.3.1 for package contrib/config/apollo (#2949) 2023-09-12 21:20:53 +08:00
e2ed058e3b feat: upgrade action/checkout to v4 (#2948) 2023-09-12 21:20:10 +08:00
ccc959a2d3 feat: jaeger package will be removed in v2.6.0. (#2946) 2023-09-12 21:17:47 +08:00
a5a7d23792 improve g.Go (#2956) 2023-09-12 20:00:01 +08:00
5bc9acdab3 version v2.5.3 (#2945) 2023-09-11 10:19:51 +08:00
ab1970e7d6 add new function g.Go (#2943) 2023-09-11 10:18:44 +08:00
1582714325 improve signal listening for package grpcx/ghttp/gproc (#2942) 2023-09-11 10:15:08 +08:00
7391a4d45a improve trace span generating for package gctx and http tracing content for package ghttp (#2937) 2023-09-11 10:14:00 +08:00
7e16d9b63e fix codes due to static codes analysis (#2935) 2023-09-07 20:22:20 +08:00
d49dccb147 test: add unit tests regarding issue 2901 (#2930) 2023-09-05 19:30:54 +08:00
6cddfdb313 improve join feature for package gdb (#2929) 2023-09-05 19:29:28 +08:00
912316d765 add cluster mode and tls configuration support for package gredis (#2936) 2023-09-05 19:23:17 +08:00
b9e2b05f04 change interface ConvertDataForRecord to ConvertValueForField for package gdb (#2916) 2023-09-04 21:23:54 +08:00
887803e495 add structure logging handler for package glog (#2919) 2023-09-04 21:23:46 +08:00
eb11061bd2 fix: gjson encode to string expect inconformity(issue 2520) (#2928) 2023-09-04 21:19:22 +08:00
000c7a92ed ORM add function: LeftJoinOnFields,RightJoinOnFields,InnerJoinOnFields (#2921) 2023-09-04 20:33:53 +08:00
097b26f318 fix: multiple interfaces cause the original type to be inaccessible (#2915) 2023-09-04 20:11:14 +08:00
3da5e5e865 fix: gutil.IsSlice judgment logic error (#2910) 2023-09-04 20:09:55 +08:00
e60262fec9 docs: fix code comment err in Model Join case (#2884) 2023-09-04 20:05:52 +08:00
74bf1b4bc3 fix(cmd): Fix gf build examples (#2917) 2023-08-31 15:32:49 +08:00
3f69e0db36 improve error stack configuration for package gerror, add framework error stack filter for package glog (#2918) 2023-08-31 15:31:55 +08:00
7d4c59ac5a fix: OpenAPI cannot correctly identify the file type under the canoni… (#2898) 2023-08-28 21:52:22 +08:00
3841f05e02 add AdapterContent implements for gcfg.Adapter (#2892) 2023-08-28 21:49:30 +08:00
bcd409ab1c fix typo "Upadte" -> "Update" (#2906) 2023-08-28 21:48:56 +08:00
4dd43aa018 improve packed project template for command init (#2885) 2023-08-23 19:28:09 +08:00
aed695313a rewrite gmutex with sync.RWMutex (#2883) 2023-08-23 19:27:57 +08:00
cf299273c4 version v2.5.2 (#2878) 2023-08-18 09:57:25 +08:00
53323f3cf9 improve support for generic router registering (#2877) 2023-08-17 21:16:19 +08:00
24ee5341ec Fix empty map or struct convert to another map will return error. (#2863) 2023-08-17 20:59:16 +08:00
ed4d1554ab improve converter feature for package gconv (#2869) 2023-08-17 20:33:12 +08:00
ac3481ed43 it returns error when Scan to a none empty slice with empty Result for package gdb (#2858) 2023-08-17 20:29:06 +08:00
3df5969348 fix generic check with slice for ghttp (#2850) 2023-08-16 21:42:36 +08:00
ea6a773d60 fix: marked gcode.CodeInternalPanic for panic (#2860) 2023-08-14 09:53:13 +08:00
35a326e169 fix(ghttp): fix access log info format (#2853) 2023-08-10 22:12:10 +08:00
4020eb9b4c fix issue in SliceMap/Maps for package gconv when nil value in map of slice item (#2857) 2023-08-10 21:59:21 +08:00
243fe73c57 improve comment replacement regex pattern for command gen service (#2846) 2023-08-08 20:39:38 +08:00
932f8c48ef Add gconv custom converter feature. (#2828) 2023-08-07 21:15:22 +08:00
7c1be3eb63 improve data converting for DB.DoInsert/DoUpdate (#2830) 2023-08-07 21:03:56 +08:00
5de2cfbfa1 improve command gen ctrl for api parsing and interface file generating (#2836) 2023-08-07 21:02:16 +08:00
b593c00d97 fix gf gen service remove all comments. (#2845) 2023-08-07 20:42:10 +08:00
7798e96190 add more ut case for package goai (#2843) 2023-08-07 20:39:01 +08:00
55ac18d90a Update README for minimum go version requirement (#2833) 2023-08-03 21:14:48 +08:00
a409db5540 Bump golang.org/x/net from 0.0.0-20211112202133-69e39bad7dc2 to 0.7.0 in /contrib/drivers/sqlitecgo (#2834) 2023-08-03 21:13:23 +08:00
dd5d56674e Bump golang.org/x/text from 0.3.8-0.20211105212822-18b340fc7af2 to 0.3.8 in /contrib/drivers/sqlitecgo (#2835) 2023-08-03 21:12:45 +08:00
79617570ca Feat:upgrade redis v9 (#2825) 2023-08-03 20:01:36 +08:00
a4e7cc4700 fix: psgql tx unsupport LastInsertId (#2815) 2023-08-03 19:59:22 +08:00
2fbe4125dd feat: Using sqlite CGO is for building a 32-bit Windows operating system (#2743) 2023-08-03 19:58:16 +08:00
47915816b5 fix: disable map tag summary and description from the OpenAPI Operation to PathItem (#2823) 2023-08-02 20:45:58 +08:00
0f53660453 fix issue #2570 (#2819) 2023-08-02 20:41:28 +08:00
f3437dc00f add generic support for http routes registering #2227 #2457 (#2807) 2023-08-02 20:35:58 +08:00
574d63b4fd fix issue #2803 (#2805) 2023-08-01 22:06:10 +08:00
53e5a04073 change minimum golang version from v1.15 to v1.18 (#2820) 2023-08-01 21:15:28 +08:00
XG
c51785125e refactor: add default client instance for contrib/sdk/httpclient (#2814) 2023-08-01 20:45:20 +08:00
XG
5230f8304e fix issue #2816 (#2817) 2023-08-01 20:11:52 +08:00
847 changed files with 41942 additions and 12492 deletions

View File

@ -1,38 +0,0 @@
<!-- Please answer these questions before submitting your issue. Thanks! -->
<!-- 为高效处理您的疑问如果觉得是BUG类问题请您务必提供可复现该问题的最小可运行代码否则issue可能会被延期处理 -->
<!-- 为高效处理您的疑问如果觉得是BUG类问题请您务必提供可复现该问题的最小可运行代码否则issue可能会被延期处理 -->
<!-- 为高效处理您的疑问如果觉得是BUG类问题请您务必提供可复现该问题的最小可运行代码否则issue可能会被延期处理 -->
<!-- 重要的事情说三遍! -->
### 1. What version of `Go` and system type/arch are you using?
<!--
Please paste the output of command `go version` from your terminal.
What expect to see is like: `go 1.12, linux/amd64`
-->
### 2. What version of `GoFrame` are you using?
<!-- You can find the GF version from your `go.mod`, or from the `version.go` in `GF` -->
### 3. Can this issue be re-produced with the latest release?
### 4. What did you do?
<!--
If possible, provide a copy of shortest codes for reproducing the error.
A complete runnable program is best.
-->
### 5. What did you expect to see?
### 6. What did you see instead?

71
.github/ISSUE_TEMPLATE/00-bug.yml vendored Normal file
View File

@ -0,0 +1,71 @@
# https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/configuring-issue-templates-for-your-repository#creating-issue-forms
# https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-githubs-form-schema
name: Bugs
description: GoFrame command, module, or anything else
title: "os/gtime: issue title"
labels:
- bug
body:
- type: markdown
attributes:
value: |
Thanks for helping us improve! 🙏 Please answer these questions and provide as much information as possible about your problem.
The issue title uses the format of the package name goes before the colon. Thanks!
标题使用包名在冒号前的格式!谢谢!
- type: input
id: go-version
attributes:
label: Go version
description: |
What version of Go are you using (`go version`)?
placeholder: ex. go version go1.20.7 darwin/arm64
validations:
required: true
- type: input
id: gf-version
attributes:
label: GoFrame version
description: |
What version of GoFrame are you using (`gf version`)?
placeholder: ex. 2.7.0
validations:
required: true
- type: dropdown
id: is-reproducible
attributes:
label: Can this bug be reproduced with the latest release?
options:
- Option Yes
- Option No
validations:
required: true
- type: textarea
id: what-did-you-do
attributes:
label: "What did you do?"
description: "If possible, provide a recipe for reproducing the error. A complete runnable program is good. A link on [go.dev/play](https://go.dev/play) is best."
validations:
required: true
- type: textarea
id: actual-behavior
attributes:
label: "What did you see happen?"
description: Command invocations and their associated output, functions with their arguments and return results, full stacktraces for panics (upload a file if it is very long), etc. Prefer copying text output over using screenshots.
validations:
required: true
- type: textarea
id: expected-behavior
attributes:
label: "What did you expect to see?"
description: Why is the current output incorrect, and any additional context we may need to understand the issue.
validations:
required: true

32
.github/ISSUE_TEMPLATE/01-enhance.yml vendored Normal file
View File

@ -0,0 +1,32 @@
# https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/configuring-issue-templates-for-your-repository#creating-issue-forms
# https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-githubs-form-schema
name: Enhancements
description: Enhance an idea for this project
title: "os/gtime: issue title"
labels:
- enhancement
body:
- type: markdown
attributes:
value: |
Thanks for helping us improve! 🙏 Please answer these questions and provide as much information as possible about your problem.
The issue title uses the format of the package name goes before the colon. Thanks!
标题使用包名在冒号前的格式!谢谢!
- type: textarea
id: description
attributes:
label: "Description"
description: "Please describe your idea in detail."
validations:
required: true
- type: textarea
id: additional
attributes:
label: "Additional"
validations:
required: false

48
.github/ISSUE_TEMPLATE/02-feature.yml vendored Normal file
View File

@ -0,0 +1,48 @@
# https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/configuring-issue-templates-for-your-repository#creating-issue-forms
# https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-githubs-form-schema
name: Features
description: Suggest an idea for this project
title: "os/gtime: issue title"
labels:
- feature
body:
- type: markdown
attributes:
value: |
Thanks for helping us improve! 🙏 Please answer these questions and provide as much information as possible about your problem.
The issue title uses the format of the package name goes before the colon. Thanks!
标题使用包名在冒号前的格式!谢谢!
- type: dropdown
id: is-problem
attributes:
label: Is your feature request related to a problem?
options:
- Option Yes
- Option No
validations:
required: true
- type: textarea
id: description-solution
attributes:
label: "Describe the solution you'd like"
validations:
required: true
- type: textarea
id: description-considered
attributes:
label: "Describe alternatives you've considered"
validations:
required: true
- type: textarea
id: additional
attributes:
label: "Additional"
validations:
required: false

25
.github/ISSUE_TEMPLATE/03-question.yml vendored Normal file
View File

@ -0,0 +1,25 @@
# https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/configuring-issue-templates-for-your-repository#creating-issue-forms
# https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-githubs-form-schema
name: Questions
description: I want to ask a question
title: "os/gtime: issue title"
labels:
- question
body:
- type: markdown
attributes:
value: |
Please read the document carefully. 请先仔细阅读文档
The issue title uses the format of the package name goes before the colon. Thanks!
标题使用包名在冒号前的格式!谢谢!
- type: textarea
id: ask
attributes:
label: "What do you want to ask?"
description: "Please describe the details of your questions. 请详细描述你的问题。"
validations:
required: true

22
.github/PULL_REQUEST_TEMPLATE.MD vendored Normal file
View File

@ -0,0 +1,22 @@
**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 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
+ 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`
+ 冒号前是包名
+ 冒号后使用动词时态 + 短语
+ 冒号后的动词小写
+ 不要有结尾句号
+ 标题尽量保持简短,最好在 76 个字符或更短
+ 标题不要使用 Markdown
+ 如果有对应的 issue请在此评论中添加 `Fixes #1234`,如果不是完全修复则添加 `Updates #1234`
+ 应用这些规则后删除所有的说明

View File

@ -1,65 +0,0 @@
#!/usr/bin/env bash
for file in `find . -name go.mod`; do
dirpath=$(dirname $file)
echo $dirpath
# package oracle needs golang >= v1.17
if [ "oracle" = $(basename $dirpath) ]; then
if ! go version|grep -q "1.17"; then
echo "ignore oracle as go version: $(go version)"
continue 1
fi
fi
# package kuhecm needs golang >= v1.18
if [ "kubecm" = $(basename $dirpath) ]; then
if ! go version|grep -q "1.18"; then
echo "ignore kubecm as go version: $(go version)"
continue 1
fi
fi
# package example needs golang >= v1.19
if [ "example" = $(basename $dirpath) ]; then
if ! go version|grep -q "1.19"; then
echo "ignore example as go version: $(go version)"
continue 1
fi
fi
# package cmd/gf needs golang >= v1.18
if [ "gf" = $(basename $dirpath) ]; then
if ! go version|grep -q "1.18"; then
echo "ignore cmd/gf as go version: $(go version)"
continue 1
fi
fi
# package otlpgrpc needs golang >= v1.20
if [ "otlpgrpc" = $(basename $dirpath) ]; then
if ! go version|grep -q "1.20"; then
echo "ignore otlpgrpc as go version: $(go version)"
continue 1
fi
fi
# package otlphttp needs golang >= v1.20
if [ "otlphttp" = $(basename $dirpath) ]; then
if ! go version|grep -q "1.20"; then
echo "ignore otlphttp as go version: $(go version)"
continue 1
fi
fi
cd $dirpath
go mod tidy
go build ./...
go test ./... -race -coverprofile=coverage.out -covermode=atomic -coverpkg=./...,github.com/gogf/gf/... || exit 1
if grep -q "/gogf/gf/.*/v2" go.mod; then
sed -i "s/gogf\/gf\(\/.*\)\/v2/gogf\/gf\/v2\1/g" coverage.out
fi
cd -
done

96
.github/workflows/ci-main.sh vendored Normal file
View File

@ -0,0 +1,96 @@
#!/usr/bin/env bash
coverage=$1
# find all path that contains go.mod.
for file in `find . -name go.mod`; do
dirpath=$(dirname $file)
echo $dirpath
if [[ $file =~ "/testdata/" ]]; then
echo "ignore testdata path $file"
continue 1
fi
# package kuhecm needs golang >= v1.19
if [ "kubecm" = $(basename $dirpath) ]; then
continue 1
if ! go version|grep -qE "go1.19|go1.[2-9][0-9]"; then
echo "ignore kubecm as go version: $(go version)"
continue 1
fi
fi
# package consul needs golang >= v1.19
if [ "consul" = $(basename $dirpath) ]; then
continue 1
if ! go version|grep -qE "go1.19|go1.[2-9][0-9]"; then
echo "ignore consul as go version: $(go version)"
continue 1
fi
fi
# package etcd needs golang >= v1.19
if [ "etcd" = $(basename $dirpath) ]; then
if ! go version|grep -qE "go1.19|go1.[2-9][0-9]"; then
echo "ignore etcd as go version: $(go version)"
continue 1
fi
fi
# package polaris needs golang >= v1.19
if [ "polaris" = $(basename $dirpath) ]; then
if ! go version|grep -qE "go1.19|go1.[2-9][0-9]"; then
echo "ignore polaris as go version: $(go version)"
continue 1
fi
fi
# package example needs golang >= v1.20
if [ "example" = $(basename $dirpath) ]; then
if ! go version|grep -qE "go1.[2-9][0-9]"; then
echo "ignore example as go version: $(go version)"
continue 1
fi
fi
# package otlpgrpc needs golang >= v1.20
if [ "otlpgrpc" = $(basename $dirpath) ]; then
if ! go version|grep -qE "go1.[2-9][0-9]"; then
echo "ignore otlpgrpc as go version: $(go version)"
continue 1
fi
fi
# package otlphttp needs golang >= v1.20
if [ "otlphttp" = $(basename $dirpath) ]; then
if ! go version|grep -qE "go1.[2-9][0-9]"; then
echo "ignore otlphttp as go version: $(go version)"
continue 1
fi
fi
# package otelmetric needs golang >= v1.20
if [ "otelmetric" = $(basename $dirpath) ]; then
if ! go version|grep -qE "go1.[2-9][0-9]"; then
echo "ignore otelmetric as go version: $(go version)"
continue 1
fi
fi
cd $dirpath
go mod tidy
go build ./...
# check coverage
if [ "${coverage}" = "coverage" ]; then
go test ./... -race -coverprofile=coverage.out -covermode=atomic -coverpkg=./...,github.com/gogf/gf/... || exit 1
if grep -q "/gogf/gf/.*/v2" go.mod; then
sed -i "s/gogf\/gf\(\/.*\)\/v2/gogf\/gf\/v2\1/g" coverage.out
fi
else
go test ./... -race || exit 1
fi
cd -
done

View File

@ -1,3 +1,4 @@
# The main codes build and unit testing running workflow.
name: GoFrame Main CI
@ -65,10 +66,23 @@ jobs:
ports:
- 3306:3306
# MariaDb backend server.
mariadb:
image: loads/mariadb:10.4
env:
MARIADB_DATABASE: test
MARIADB_ROOT_PASSWORD: 12345678
ports:
- 3307:3306
# PostgreSQL backend server.
# docker run -d --name postgres -p 5432:5432 \
# -e POSTGRES_PASSWORD=12345678 -e POSTGRES_USER=postgres -e POSTGRES_DB=test \
# -v postgres:/Users/john/Temp/postgresql/data loads/postgres:13
# docker run -d --name postgres \
# -p 5432:5432 \
# -e POSTGRES_PASSWORD=12345678 \
# -e POSTGRES_USER=postgres \
# -e POSTGRES_DB=test \
# -v postgres:/Users/john/Temp/postgresql/data \
# loads/postgres:13
postgres:
image: loads/postgres:13
env:
@ -86,7 +100,8 @@ jobs:
--health-retries 5
# MSSQL backend server.
# docker run -d --name mssql -p 1433:1433 \
# docker run \
# -p 1433:1433 \
# -e ACCEPT_EULA=Y \
# -e SA_PASSWORD=LoremIpsum86 \
# -e MSSQL_DB=test \
@ -111,7 +126,9 @@ jobs:
--health-retries 10
# ClickHouse backend server.
# docker run -d --name clickhouse -p 9000:9000 -p 8123:8123 -p 9001:9001 loads/clickhouse-server:22.1.3.7
# docker run -d --name clickhouse \
# -p 9000:9000 -p 8123:8123 -p 9001:9001 \
# loads/clickhouse-server:22.1.3.7
clickhouse-server:
image: loads/clickhouse-server:22.1.3.7
ports:
@ -120,10 +137,15 @@ jobs:
- 9001:9001
# Polaris backend server.
# docker run -d --name polaris -p 8090:8090 -p 8091:8091 -p 8093:8093 -p 9090:9090 -p 9091:9091 loads/polaris-server-standalone:1.11.2
# docker run -d --name polaris -p 8090:8090 -p 8091:8091 -p 8093:8093 -p 9090:9090 -p 9091:9091 loads/polaris-standalone:v1.16.3
# docker run -d --name polaris \
# -p 8090:8090 -p 8091:8091 -p 8093:8093 -p 9090:9090 -p 9091:9091 \
# loads/polaris-server-standalone:1.11.2
#
# docker run -d --name polaris \
# -p 8090:8090 -p 8091:8091 -p 8093:8093 -p 9090:9090 -p 9091:9091 \
# loads/polaris-standalone:v1.16.3
polaris:
image: loads/polaris-standalone:v1.16.4
image: loads/polaris-standalone:v1.17.2
ports:
- 8090:8090
- 8091:8091
@ -131,7 +153,14 @@ jobs:
- 9090:9090
- 9091:9091
# Oracle 11g server
# Oracle 11g server.
# docker run \
# -e ORACLE_ALLOW_REMOTE=true \
# -e ORACLE_SID=XE \
# -e ORACLE_DB_USER_NAME=system \
# -e ORACLE_DB_PASSWORD=oracle \
# -p 1521:1521 \
# loads/oracle-xe-11g-r2:11.2.0
oracle-server:
image: loads/oracle-xe-11g-r2:11.2.0
env:
@ -143,7 +172,7 @@ jobs:
- 1521:1521
# dm8 server
# docker run -d --name dm -p 5236:5236 loads/dm:v8.1.2.128_ent_x86_64_ctm_pack4
# docker run -p 5236:5236 loads/dm:v8.1.2.128_ent_x86_64_ctm_pack4
dm-server:
image: loads/dm:v8.1.2.128_ent_x86_64_ctm_pack4
ports:
@ -156,7 +185,7 @@ jobs:
strategy:
matrix:
go-version: [ "1.15", "1.16", "1.17", "1.18", "1.19", "1.20" ]
go-version: [ "1.18", "1.19", "1.20", "1.21", "1.22" ]
goarch: [ "386", "amd64" ]
steps:
@ -167,44 +196,52 @@ jobs:
timezoneLinux: "Asia/Shanghai"
- name: Checkout Repository
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Start Apollo Containers
run: docker-compose -f ".github/workflows/apollo/docker-compose.yml" up -d --build
run: docker compose -f ".github/workflows/apollo/docker-compose.yml" up -d --build
- name: Start Nacos Containers
run: docker-compose -f ".github/workflows/nacos/docker-compose.yml" up -d --build
run: docker compose -f ".github/workflows/nacos/docker-compose.yml" up -d --build
- name: Start Redis Cluster Containers
run: docker-compose -f ".github/workflows/redis/docker-compose.yml" up -d --build
run: docker compose -f ".github/workflows/redis/docker-compose.yml" up -d --build
- name: Start Minikube
uses: medyagh/setup-minikube@master
- name: Start Consul Containers
run: docker compose -f ".github/workflows/consul/docker-compose.yml" up -d --build
- name: Setup Golang ${{ matrix.go-version }}
uses: actions/setup-go@v3
uses: actions/setup-go@v5
with:
go-version: ${{ matrix.go-version }}
cache: true
cache-dependency-path: '**/go.sum'
cache-dependency-path: '**/go.sum'
- name: Before Script
run: bash .github/workflows/before_script.sh
- name: Build & Test
run: bash .github/workflows/build_and_test.sh
if: ${{ (github.event_name == 'push' && github.ref != 'refs/heads/master') || github.event_name == 'pull_request' }}
run: bash .github/workflows/ci-main.sh
- name: Build & Test & Coverage
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }}
run: bash .github/workflows/ci-main.sh coverage
- name: Stop Redis Cluster Containers
run: docker-compose -f ".github/workflows/redis/docker-compose.yml" down
run: docker compose -f ".github/workflows/redis/docker-compose.yml" down
- name: Stop Apollo Containers
run: docker-compose -f ".github/workflows/apollo/docker-compose.yml" down
run: docker compose -f ".github/workflows/apollo/docker-compose.yml" down
- name: Stop Nacos Containers
run: docker-compose -f ".github/workflows/nacos/docker-compose.yml" down
run: docker compose -f ".github/workflows/nacos/docker-compose.yml" down
- name: Stop Consul Containers
run: docker compose -f ".github/workflows/consul/docker-compose.yml" down
- name: Report Coverage
uses: codecov/codecov-action@v3
uses: codecov/codecov-action@v4
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }}
with:
flags: go-${{ matrix.go-version }}-${{ matrix.goarch }}
token: ${{ secrets.CODECOV_TOKEN }}

27
.github/workflows/ci-sub.sh vendored Normal file
View File

@ -0,0 +1,27 @@
#!/usr/bin/env bash
coverage=$1
# find all path that contains go.mod.
for file in `find . -name go.mod`; do
dirpath=$(dirname $file)
echo $dirpath
# package kuhecm needs golang >= v1.19
if [ "kubecm" = $(basename $dirpath) ]; then
if ! go version|grep -qE "go1.19|go1.[2-9][0-9]"; then
echo "ignore kubecm as go version: $(go version)"
continue 1
fi
else
continue 1
fi
cd $dirpath
go mod tidy
go build ./...
go test ./... -race || exit 1
cd -
done

67
.github/workflows/ci-sub.yml vendored Normal file
View File

@ -0,0 +1,67 @@
# The sub codes build and unit testing running workflow.
# It maintains the ci of unimportant packages.
name: GoFrame Sub CI
on:
push:
branches:
- master
- develop
- personal/**
- feature/**
- enhance/**
- fix/**
pull_request:
branches:
- master
- develop
- personal/**
- feature/**
- enhance/**
- fix/**
# This allows a subsequently queued workflow run to interrupt previous runs
concurrency:
group: '${{ github.workflow }} @ ${{ github.event.pull_request.head.label || github.head_ref || github.ref }}'
cancel-in-progress: true
env:
TZ: "Asia/Shanghai"
jobs:
code-test:
runs-on: ubuntu-latest
strategy:
matrix:
go-version: [ "1.18", "1.19", "1.20", "1.22" ]
goarch: [ "386", "amd64" ]
steps:
- name: Setup Timezone
uses: szenius/set-timezone@v1.1
with:
timezoneLinux: "Asia/Shanghai"
- name: Checkout Repository
uses: actions/checkout@v4
- name: Start Minikube
uses: medyagh/setup-minikube@master
- name: Setup Golang ${{ matrix.go-version }}
uses: actions/setup-go@v5
with:
go-version: ${{ matrix.go-version }}
cache-dependency-path: '**/go.sum'
- name: Before Script
run: bash .github/workflows/before_script.sh
- name: Build & Test
run: bash .github/workflows/ci-sub.sh

7
.github/workflows/consul/client.json vendored Normal file
View File

@ -0,0 +1,7 @@
{
"node_name": "consul-client",
"data_dir": "/consul/data",
"retry_join":[
"consul-server"
]
}

View File

@ -0,0 +1,31 @@
version: '3.7'
services:
consul-server:
image: loads/consul:1.15
container_name: consul-server
restart: always
volumes:
- ./server.json:/consul/config/server.json:ro
networks:
- consul
ports:
- "8500:8500"
- "8600:8600/tcp"
- "8600:8600/udp"
command: "agent"
consul-client:
image: loads/consul:1.15
container_name: consul-client
restart: always
volumes:
- ./client.json:/consul/config/client.json:ro
networks:
- consul
command: "agent"
networks:
consul:
driver: bridge

12
.github/workflows/consul/server.json vendored Normal file
View File

@ -0,0 +1,12 @@
{
"node_name": "consul-server",
"server": true,
"bootstrap" : true,
"ui_config": {
"enabled" : true
},
"data_dir": "/consul/data",
"addresses": {
"http" : "0.0.0.0"
}
}

38
.github/workflows/doc-build.yml vendored Normal file
View File

@ -0,0 +1,38 @@
name: Deploy to GitHub Pages
on:
push:
branches:
- 'doc-build'
schedule:
- cron: '0 15 * * *'
jobs:
deploy:
name: Deploy to GitHub Pages
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
ref: doc-build
- uses: actions/setup-node@v3
with:
node-version: 18
cache: npm
- name: Set Up Golang Environment
uses: actions/setup-go@v4
with:
go-version: 1.20.4
cache: false
- name: download goframe docs
run: ./download.sh
- name: Install dependencies
run: npm ci
- name: Build website
run: npm run build
- name: Deploy to GitHub Pages
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./build
cname: pages.goframe.org

View File

@ -1,7 +1,7 @@
on:
push:
branches:
- main
- master
tags:
- "*"
@ -12,9 +12,9 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout source code
uses: actions/checkout@v3
- name: Mirror Github to Gitee
uses: Yikun/hub-mirror-action@v1.2
uses: actions/checkout@v4
- name: Mirror GitHub to Gitee
uses: Yikun/hub-mirror-action@v1.3
with:
src: github/gogf
dst: gitee/johng

View File

@ -36,19 +36,19 @@ jobs:
golangci:
strategy:
matrix:
go-version: [ '1.15','1.16','1.17','1.18','1.19','1.20' ]
go-version: [ '1.18','1.19','1.20','1.21.4','1.22' ]
name: golangci-lint
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Setup Golang ${{ matrix.go-version }}
uses: actions/setup-go@v4
uses: actions/setup-go@v5
with:
go-version: ${{ matrix.go-version }}
- name: golangci-lint
uses: golangci/golangci-lint-action@v3
uses: golangci/golangci-lint-action@v4
with:
# Required: the version of golangci-lint is required and must be specified without patch version: we always use the latest patch version.
version: v1.52.2
version: v1.56.2
args: --timeout 3m0s

View File

@ -14,8 +14,8 @@ permissions:
jobs:
issue-check-inactive:
permissions:
issues: write # for actions-cool/issues-helper to update issues
# pull-requests: write # for actions-cool/issues-helper to update PRs
issues: write # for actions-cool/issues-helper to update issues
# pull-requests: write # for actions-cool/issues-helper to update PRs
runs-on: ubuntu-latest
steps:
- name: check-inactive

View File

@ -1,4 +1,4 @@
# 规则描述:每天凌晨4点(GMT+8)执行一次将最近30天没有活跃且非BUGISSUE关闭
# 规则描述:每天凌晨 4 点 (GMT+8) 执行一次,将最近 30 天没有活跃且非 BUGISSUE 关闭
name: Issue Close Inactive
on:

View File

@ -1,4 +1,4 @@
## 规则描述当issue被标记为help wanted 时,增加评论
## 规则描述:当 issue 被标记为 help wanted 时,增加评论
name: Issue Labeled

View File

@ -1,4 +1,4 @@
# 规则描述在issue没有活跃且尚未被关闭期间若issue作者更新或评论该ISSUE则移除其inactive标签
# 规则描述:在 issue 没有活跃且尚未被关闭期间,若 issue 作者更新或评论该 ISSUE则移除其 inactive 标签
name: Issue Remove Inactive
on:
@ -17,13 +17,13 @@ jobs:
issue-remove-inactive:
permissions:
issues: write # for actions-cool/issues-helper to update issues
# pull-requests: write # for actions-cool/issues-helper to update PRs
# pull-requests: write # for actions-cool/issues-helper to update PRs
runs-on: ubuntu-latest
steps:
- name: remove inactive
if: github.event.issue.state == 'open' && github.actor == github.event.issue.user.login
if: github.event.issue.state == 'open'
uses: actions-cool/issues-helper@v3
with:
actions: 'remove-labels'
issue-number: ${{ github.event.issue.number }}
labels: 'inactive'
labels: 'inactive'

View File

@ -1,4 +1,4 @@
# 规则描述将需要提供更多细节且暂未关闭的issue在issue作者评论后移除 need more details 标签
# 规则描述:将需要提供更多细节且暂未关闭的 issue issue 作者评论后,移除 need more details 标签
name: Issue Remove Need More Details
on:
@ -16,8 +16,8 @@ permissions:
jobs:
issue-remove-need-more-details:
permissions:
issues: write # for actions-cool/issues-helper to update issues
# pull-requests: write # for actions-cool/issues-helper to update PRs
issues: write # for actions-cool/issues-helper to update issues
# pull-requests: write # for actions-cool/issues-helper to update PRs
runs-on: ubuntu-latest
steps:
- name: remove need more details

View File

@ -15,22 +15,6 @@ services:
interval: 5s
timeout: 3s
retries: 10
depends_on:
mysql:
condition: service_healthy
mysql:
build:
context: .
dockerfile: ./image/mysql/Dockerfile
container_name: mysql
env_file:
- ./env/mysql.env
healthcheck:
test: [ "CMD", "mysqladmin" ,"ping", "-h", "localhost" ]
interval: 5s
timeout: 3s
retries: 10
initializer:
image: loads/curl:latest

View File

@ -1,4 +0,0 @@
MYSQL_ROOT_PASSWORD=root
MYSQL_DATABASE=nacos_devtest
MYSQL_USER=nacos
MYSQL_PASSWORD=nacos

View File

@ -1,9 +1,2 @@
PREFER_HOST_MODE=hostname
MODE=standalone
SPRING_DATASOURCE_PLATFORM=mysql
MYSQL_SERVICE_HOST=mysql
MYSQL_SERVICE_DB_NAME=nacos_devtest
MYSQL_SERVICE_PORT=3306
MYSQL_SERVICE_USER=nacos
MYSQL_SERVICE_PASSWORD=nacos
MYSQL_SERVICE_DB_PARAM=characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useSSL=false&allowPublicKeyRetrieval=true

View File

@ -1,5 +0,0 @@
FROM loads/mysql:5.7
ADD https://raw.githubusercontent.com/alibaba/nacos/develop/distribution/conf/mysql-schema.sql /docker-entrypoint-initdb.d/nacos-mysql.sql
RUN chown -R mysql:mysql /docker-entrypoint-initdb.d/nacos-mysql.sql
EXPOSE 3306
CMD ["mysqld", "--character-set-server=utf8mb4", "--collation-server=utf8mb4_unicode_ci"]

View File

@ -1,4 +1,4 @@
name: GoFrame CLI Build Release
name: GoFrame Release
on:
push:
@ -16,12 +16,12 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout Github Code
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Set Up Golang Environment
uses: actions/setup-go@v4
uses: actions/setup-go@v5
with:
go-version: 1.20.4
go-version: 1.20.8
- name: Build CLI Binary
run: |
@ -34,7 +34,7 @@ jobs:
- name: Build CLI Binary For All Platform
run: |
cd cmd/gf
gf build main.go -n gf -a all -s all
gf build main.go -n gf -a all -s all -p temp
- name: Move Files Before Release
run: |

View File

@ -17,14 +17,23 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout Github Code
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Auto Creating Tags For Contrib Packages
run: |
git config --global user.email "tagrobot@goframe.org"
git config --global user.name "TagRobot"
# auto create tags for contrib packages.
for file in `find contrib -name go.mod`; do
tag=$(dirname $file)/$GITHUB_REF_NAME
git tag $tag
git push origin $tag
done
# auto create tag for cli tool
for file in `find cmd -name go.mod`; do
tag=$(dirname $file)/$GITHUB_REF_NAME
git tag $tag
git push origin $tag
done

8
.gitignore vendored
View File

@ -13,6 +13,12 @@ bin/
.test/
cmd/gf/main
cmd/gf/gf
temp/
go.work
go.work.sum
temp/
!cmd/gf/go.work
# Ignore for docs
node_modules
.docusaurus
output

View File

@ -262,7 +262,7 @@ linters-settings:
# Select the Go version to target.
# Default: "1.13"
# Deprecated: use the global `run.go` instead.
go: "1.15"
go: "1.20"
# SAxxxx checks in https://staticcheck.io/docs/configuration/options/#checks
# Default: ["*"]
checks: [ "all","-SA1019","-SA4015","-SA1029","-SA1016","-SA9003","-SA4006","-SA6003" ]

View File

@ -1,5 +1,4 @@
#!/usr/bin/env bash
if [ $# -ne 2 ]; then
echo "Parameter exception, please execute in the format of $0 [directory] [version number]"
echo "PS$0 ./ v2.4.0"
@ -16,10 +15,17 @@ if [[ "$2" != v* ]]; then
exit 1
fi
workdir=$1
workdir=.
newVersion=$2
echo "Prepare to replace the GF library version numbers in all go.mod files in the ${workdir} directory with ${newVersion}"
# check find command support or not
output=$(find "${workdir}" -name go.mod 2>&1)
if [[ $? -ne 0 ]]; then
echo "Error: please use bash or zsh to run!"
exit 1
fi
if [[ true ]]; then
echo "package gf" > version.go
echo "" >> version.go
@ -39,11 +45,34 @@ for file in `find ${workdir} -name go.mod`; do
echo ""
echo "processing dir: $goModPath"
cd $goModPath
if [ $goModPath = "./cmd/gf" ]; then
mv go.work go.work.version.bak
go mod edit -replace github.com/gogf/gf/v2=../../
go mod edit -replace github.com/gogf/gf/contrib/drivers/clickhouse/v2=../../contrib/drivers/clickhouse
go mod edit -replace github.com/gogf/gf/contrib/drivers/mssql/v2=../../contrib/drivers/mssql
go mod edit -replace github.com/gogf/gf/contrib/drivers/mysql/v2=../../contrib/drivers/mysql
go mod edit -replace github.com/gogf/gf/contrib/drivers/oracle/v2=../../contrib/drivers/oracle
go mod edit -replace github.com/gogf/gf/contrib/drivers/pgsql/v2=../../contrib/drivers/pgsql
go mod edit -replace github.com/gogf/gf/contrib/drivers/sqlite/v2=../../contrib/drivers/sqlite
# else
# cd -
# continue 1
fi
go mod tidy
# Upgrading only GF related libraries, sometimes even if a version number is specified, it may not be possible to successfully upgrade. Please confirm before submitting the code
go list -f "{{if and (not .Indirect) (not .Main)}}{{.Path}}@${newVersion}{{end}}" -m all | grep "^github.com/gogf/gf"
go list -f "{{if and (not .Indirect) (not .Main)}}{{.Path}}@${newVersion}{{end}}" -m all | grep "^github.com/gogf/gf" | xargs -L1 go get -v
go mod tidy
if [ $goModPath = "./cmd/gf" ]; then
go mod edit -dropreplace github.com/gogf/gf/v2
go mod edit -dropreplace github.com/gogf/gf/contrib/drivers/clickhouse/v2
go mod edit -dropreplace github.com/gogf/gf/contrib/drivers/mssql/v2
go mod edit -dropreplace github.com/gogf/gf/contrib/drivers/mysql/v2
go mod edit -dropreplace github.com/gogf/gf/contrib/drivers/oracle/v2
go mod edit -dropreplace github.com/gogf/gf/contrib/drivers/pgsql/v2
go mod edit -dropreplace github.com/gogf/gf/contrib/drivers/sqlite/v2
mv go.work.version.bak go.work
fi
cd -
done

View File

@ -4,11 +4,20 @@
<img src="https://goframe.org/statics/image/logo2.png?v=1" 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/gf.yml/badge.svg)](https://github.com/gogf/gf/actions/workflows/gf.yml)
[![GoFrame CI](https://github.com/gogf/gf/actions/workflows/ci-main.yml/badge.svg)](https://github.com/gogf/gf/actions/workflows/ci-main.yml)
[![Go Report Card](https://goreportcard.com/badge/github.com/gogf/gf/v2)](https://goreportcard.com/report/github.com/gogf/gf/v2)
[![Code Coverage](https://codecov.io/gh/gogf/gf/branch/master/graph/badge.svg)](https://codecov.io/gh/gogf/gf)
[![Production Ready](https://img.shields.io/badge/production-ready-blue.svg)](https://github.com/gogf/gf)
[![Production Ready](https://img.shields.io/badge/production-ready-blue.svg?style=flat)](https://github.com/gogf/gf)
[![License](https://img.shields.io/github/license/gogf/gf.svg?style=flat)](https://github.com/gogf/gf)
[![Release](https://img.shields.io/github/v/release/gogf/gf?style=flat)](https://github.com/gogf/gf/releases)
[![GitHub pull requests](https://img.shields.io/github/issues-pr/gogf/gf?style=flat)](https://github.com/gogf/gf/pulls)
[![GitHub closed pull requests](https://img.shields.io/github/issues-pr-closed/gogf/gf?style=flat)](https://github.com/gogf/gf/pulls?q=is%3Apr+is%3Aclosed)
[![GitHub issues](https://img.shields.io/github/issues/gogf/gf?style=flat)](https://github.com/gogf/gf/issues)
[![GitHub closed issues](https://img.shields.io/github/issues-closed/gogf/gf?style=flat)](https://github.com/gogf/gf/issues?q=is%3Aissue+is%3Aclosed)
![Stars](https://img.shields.io/github/stars/gogf/gf?style=flat)
![Forks](https://img.shields.io/github/forks/gogf/gf?style=flat)
</div>
`GoFrame` is a modular, powerful, high-performance and enterprise-class application development framework of Golang.
@ -41,24 +50,20 @@ go get -u -v github.com/gogf/gf/v2
## cli tool
```bash
go install github.com/gogf/gf/cmd/gf/v2
go install github.com/gogf/gf/cmd/gf/v2@latest
```
# Limitation
```
golang version >= 1.15
golang version >= 1.18
```
# Architecture
<div align=center>
<img src="https://goframe.org/download/attachments/1114119/arch.png"/>
</div>
# Documentation
- Chinese Official Site(中文官网): [https://goframe.org](https://goframe.org/display/gf)
- Chinese Pages Document(中文镜像文档): [https://pages.goframe.org](https://pages.goframe.org)
- Chinese Offline Document(中文离线文档): [https://github.com/gogf/goframe.org-pdf](https://github.com/gogf/goframe.org-pdf)
- GoDoc API: [https://pkg.go.dev/github.com/gogf/gf/v2](https://pkg.go.dev/github.com/gogf/gf/v2)
# License

View File

@ -21,22 +21,24 @@ You can also install `gf` tool using pre-built binaries: <https://github.com/gog
3. Database support
| DB | support | remarks |
| :------: | :------: | :------: |
| mysql | yes | - |
| mariadb | yes | - |
| tidb | yes | - |
| mssql | yes | - |
| oracle | yes | - |
| pgsql | yes | - |
| sqlite | yes | - |
| clickhouse | no | manually make some changes to the [source codes](./internal/cmd/cmd_gen_dao.go) and do the building. |
| dm | no | manually make some changes to the [source codes](./internal/cmd/cmd_gen_dao.go) and do the building. |
| DB | builtin support | remarks |
|:----------:|:---------------:|:----------------------------------------------------------------------------------------------------------------------------------------------------------------:|
| mysql | yes | - |
| mariadb | yes | - |
| tidb | yes | - |
| mssql | yes | - |
| oracle | yes | - |
| pgsql | yes | - |
| sqlite | yes | - |
| sqlitecgo | no | to support sqlite database on 32bit architecture systems, manually add package import to the [source codes](./internal/cmd/cmd_gen_dao.go) and do the building. |
| clickhouse | no | manually add package import to the [source codes](./internal/cmd/cmd_gen_dao.go) and do the building. |
| dm | no | manually add package import to the [source codes](./internal/cmd/cmd_gen_dao.go) and do the building. |
## 2) Manually Install
```shell
git clone https://github.com/gogf/gf && cd gf/cmd/gf && go install
go install github.com/gogf/gf/cmd/gf/v2@latest # latest version
go install github.com/gogf/gf/cmd/gf/v2@v2.5.5 # certain version(should be >= v2.5.5)
```
## 2. Commands
@ -47,22 +49,24 @@ USAGE
gf COMMAND [OPTION]
COMMAND
env show current Golang environment variables
run running go codes with hot-compiled-like feature
gen automatically generate go files for dao/do/entity/pb/pbentity
tpl template parsing and building commands
init create and initialize an empty GoFrame project
pack packing any file/directory to a resource file, or a go file
build cross-building go project for lots of platforms
docker build docker image for current GoFrame project
install install gf binary to system (might need root/admin permission)
version show version information of current binary
up upgrade GoFrame version/tool to latest one in current project
env show current Golang environment variables
fix auto fixing codes after upgrading to new GoFrame version
run running go codes with hot-compiled-like feature
gen automatically generate go files for dao/do/entity/pb/pbentity
tpl template parsing and building commands
init create and initialize an empty GoFrame project
pack packing any file/directory to a resource file, or a go file
build cross-building go project for lots of platforms
docker build docker image for current GoFrame project
install install gf binary to system (might need root/admin permission)
version show version information of current binary
OPTION
-y, --yes all yes for all command without prompt ask
-v, --version show version information of current binary
-d, --debug show internal detailed debugging information
-h, --help more information about this command
-y, --yes all yes for all command without prompt ask
-v, --version show version information of current binary
-d, --debug show internal detailed debugging information
-h, --help more information about this command
ADDITIONAL
Use "gf COMMAND -h" for details about a command.

View File

@ -7,18 +7,21 @@
package gfcmd
import (
_ "github.com/gogf/gf/cmd/gf/v2/internal/packed"
"context"
"runtime"
"github.com/gogf/gf/cmd/gf/v2/internal/cmd"
"github.com/gogf/gf/cmd/gf/v2/internal/utility/allyes"
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
"github.com/gogf/gf/v2/errors/gcode"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gcfg"
"github.com/gogf/gf/v2/os/gcmd"
"github.com/gogf/gf/v2/os/gfile"
"github.com/gogf/gf/v2/text/gstr"
"github.com/gogf/gf/cmd/gf/v2/internal/cmd"
_ "github.com/gogf/gf/cmd/gf/v2/internal/packed"
"github.com/gogf/gf/cmd/gf/v2/internal/utility/allyes"
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
)
const (
@ -38,7 +41,7 @@ func (c *Command) Run(ctx context.Context) {
if err, ok := exception.(error); ok {
mlog.Print(err.Error())
} else {
panic(exception)
panic(gerror.NewCodef(gcode.CodeInternalPanic, "%+v", exception))
}
}
}()
@ -97,6 +100,9 @@ func GetCommand(ctx context.Context) (*Command, error) {
// zsh alias "git fetch" conflicts checks.
func handleZshAlias() {
if runtime.GOOS == "windows" {
return
}
if home, err := gfile.Home(); err == nil {
zshPath := gfile.Join(home, ".zshrc")
if gfile.Exists(zshPath) {

View File

@ -3,65 +3,59 @@ module github.com/gogf/gf/cmd/gf/v2
go 1.18
require (
github.com/gogf/gf/contrib/drivers/clickhouse/v2 v2.5.1
github.com/gogf/gf/contrib/drivers/mssql/v2 v2.5.1
github.com/gogf/gf/contrib/drivers/mysql/v2 v2.5.1
github.com/gogf/gf/contrib/drivers/oracle/v2 v2.5.1
github.com/gogf/gf/contrib/drivers/pgsql/v2 v2.5.1
github.com/gogf/gf/contrib/drivers/sqlite/v2 v2.5.1
github.com/gogf/gf/v2 v2.5.1
github.com/minio/selfupdate v0.6.0
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/selfupdate v0.0.0-20231215043001-5c48c528462f
github.com/olekukonko/tablewriter v0.0.5
golang.org/x/mod v0.9.0
golang.org/x/tools v0.7.0
golang.org/x/mod v0.17.0
golang.org/x/tools v0.18.0
)
require (
aead.dev/minisign v0.2.0 // indirect
github.com/BurntSushi/toml v1.1.0 // indirect
github.com/BurntSushi/toml v1.3.2 // indirect
github.com/ClickHouse/clickhouse-go/v2 v2.0.15 // indirect
github.com/clbanning/mxj/v2 v2.5.5 // indirect
github.com/denisenkom/go-mssqldb v0.11.0 // indirect
github.com/fatih/color v1.13.0 // indirect
github.com/fsnotify/fsnotify v1.5.4 // indirect
github.com/glebarez/go-sqlite v1.17.3 // indirect
github.com/go-logr/logr v1.2.3 // indirect
github.com/clbanning/mxj/v2 v2.7.0 // indirect
github.com/denisenkom/go-mssqldb v0.12.3 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/fatih/color v1.16.0 // indirect
github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/glebarez/go-sqlite v1.21.2 // indirect
github.com/go-logr/logr v1.2.4 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-sql-driver/mysql v1.6.0 // indirect
github.com/go-sql-driver/mysql v1.7.1 // indirect
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe // indirect
github.com/golang-sql/sqlexp v0.1.0 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/gorilla/websocket v1.5.0 // indirect
github.com/grokify/html-strip-tags-go v0.0.1 // indirect
github.com/lib/pq v1.10.4 // indirect
github.com/magiconair/properties v1.8.6 // indirect
github.com/mattn/go-colorable v0.1.9 // indirect
github.com/mattn/go-isatty v0.0.14 // indirect
github.com/mattn/go-runewidth v0.0.9 // indirect
github.com/gorilla/websocket v1.5.1 // 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/paulmach/orb v0.7.1 // indirect
github.com/pierrec/lz4/v4 v4.1.14 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
github.com/rivo/uniseg v0.4.4 // indirect
github.com/shopspring/decimal v1.3.1 // indirect
github.com/sijms/go-ora/v2 v2.4.20 // indirect
go.opentelemetry.io/otel v1.7.0 // indirect
go.opentelemetry.io/otel/sdk v1.7.0 // indirect
go.opentelemetry.io/otel/trace v1.7.0 // indirect
golang.org/x/crypto v0.1.0 // indirect
golang.org/x/net v0.8.0 // indirect
golang.org/x/sys v0.6.0 // indirect
golang.org/x/text v0.8.0 // indirect
github.com/sijms/go-ora/v2 v2.7.10 // indirect
go.opentelemetry.io/otel v1.14.0 // indirect
go.opentelemetry.io/otel/sdk v1.14.0 // indirect
go.opentelemetry.io/otel/trace v1.14.0 // indirect
golang.org/x/crypto v0.23.0 // indirect
golang.org/x/net v0.25.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
gopkg.in/yaml.v3 v3.0.1 // indirect
modernc.org/libc v1.16.8 // indirect
modernc.org/mathutil v1.4.1 // indirect
modernc.org/memory v1.1.1 // indirect
modernc.org/sqlite v1.17.3 // indirect
)
replace (
github.com/gogf/gf/contrib/drivers/clickhouse/v2 => ../../contrib/drivers/clickhouse/
github.com/gogf/gf/contrib/drivers/mssql/v2 => ../../contrib/drivers/mssql/
github.com/gogf/gf/contrib/drivers/mysql/v2 => ../../contrib/drivers/mysql/
github.com/gogf/gf/contrib/drivers/oracle/v2 => ../../contrib/drivers/oracle/
github.com/gogf/gf/contrib/drivers/pgsql/v2 => ../../contrib/drivers/pgsql/
github.com/gogf/gf/contrib/drivers/sqlite/v2 => ../../contrib/drivers/sqlite/
github.com/gogf/gf/v2 => ../../
modernc.org/libc v1.22.5 // indirect
modernc.org/mathutil v1.5.0 // indirect
modernc.org/memory v1.5.0 // indirect
modernc.org/sqlite v1.23.1 // indirect
)

View File

@ -1,73 +1,82 @@
aead.dev/minisign v0.2.0 h1:kAWrq/hBRu4AARY6AlciO83xhNnW9UaC8YipS2uhLPk=
aead.dev/minisign v0.2.0/go.mod h1:zdq6LdSd9TbuSxchxwhpA9zEb9YXcVGoE8JakuiGaIQ=
github.com/BurntSushi/toml v1.1.0 h1:ksErzDEI1khOiGPgpwuI7x2ebx/uXQNw7xJpn9Eq1+I=
github.com/BurntSushi/toml v1.1.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
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/ClickHouse/clickhouse-go v1.5.4/go.mod h1:EaI/sW7Azgz9UATzd5ZdZHRUhHgv5+JMS9NSr2smCJI=
github.com/ClickHouse/clickhouse-go/v2 v2.0.15 h1:lLAZliqrZEygkxosLaW1qHyeTb4Ho7fVCZ0WKCpLocU=
github.com/ClickHouse/clickhouse-go/v2 v2.0.15/go.mod h1:Z21o82zD8FFqefOQDg93c0XITlxGbTsWQuRm588Azkk=
github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
github.com/bkaradzic/go-lz4 v1.0.0/go.mod h1:0YdlkowM3VswSROI7qDxhRvJ3sLhlFrRRwjwegp5jy4=
github.com/clbanning/mxj/v2 v2.5.5 h1:oT81vUeEiQQ/DcHbzSytRngP6Ky9O+L+0Bw0zSJag9E=
github.com/clbanning/mxj/v2 v2.5.5/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn/Qo+ve2s=
github.com/clbanning/mxj/v2 v2.7.0 h1:WA/La7UGCanFe5NpHF0Q3DNtnCsVoxbPKuyBNHWRyME=
github.com/clbanning/mxj/v2 v2.7.0/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn/Qo+ve2s=
github.com/cloudflare/golz4 v0.0.0-20150217214814-ef862a3cdc58/go.mod h1:EOBUe0h4xcZ5GoxqC5SDxFQ8gwyZPKQoEzownBlhI80=
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/denisenkom/go-mssqldb v0.11.0 h1:9rHa233rhdOyrz2GcP9NM+gi2psgJZ4GWDpL/7ND8HI=
github.com/denisenkom/go-mssqldb v0.11.0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w=
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI=
github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU=
github.com/glebarez/go-sqlite v1.17.3 h1:Rji9ROVSTTfjuWD6j5B+8DtkNvPILoUC3xRhkQzGxvk=
github.com/glebarez/go-sqlite v1.17.3/go.mod h1:Hg+PQuhUy98XCxWEJEaWob8x7lhJzhNYF1nZbUiRGIY=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/denisenkom/go-mssqldb v0.12.3 h1:pBSGx9Tq67pBOTLmxNuirNTeB8Vjmf886Kx+8Y+8shw=
github.com/denisenkom/go-mssqldb v0.12.3/go.mod h1:k0mtMFOnU+AihqFxPMiF05rtiDrorD1Vrm1KEz5hxDo=
github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ=
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
github.com/glebarez/go-sqlite v1.21.2 h1:3a6LFC4sKahUunAmynQKLZceZCOzUthkRkEAl9gAXWo=
github.com/glebarez/go-sqlite v1.21.2/go.mod h1:sfxdZyhQjTM2Wry3gVYWaW072Ri1WMdWJi0k6+3382k=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0=
github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM=
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE=
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI=
github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
github.com/gogf/selfupdate v0.0.0-20231215043001-5c48c528462f h1:7xfXR/BhG3JDqO1s45n65Oyx9t4E/UqDOXep6jXdLCM=
github.com/gogf/selfupdate v0.0.0-20231215043001-5c48c528462f/go.mod h1:HnYoio6S7VaFJdryKcD/r9HgX+4QzYfr00XiXUo/xz0=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY=
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A=
github.com/golang-sql/sqlexp v0.1.0/go.mod h1:J4ad9Vo8ZCWQ2GMrC4UCQy1JpCbwU9m3EOqtpKwwwHI=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o=
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/handlers v1.4.2/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ=
github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/grokify/html-strip-tags-go v0.0.1 h1:0fThFwLbW7P/kOiTBs03FsJSV9RM2M/Q/MOnCQxKMo0=
github.com/grokify/html-strip-tags-go v0.0.1/go.mod h1:2Su6romC5/1VXOQMaWL2yb618ARB8iVo6/DR99A6d78=
github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY=
github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY=
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/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.10.4 h1:SO9z7FRPzA03QhHKJrH5BXA6HU1rS4V2nIVrrNC1iYk=
github.com/lib/pq v1.10.4/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo=
github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
github.com/mattn/go-colorable v0.1.9 h1:sqDoxXbdeALODt0DAeJCVp38ps9ZogZEAXjus69YV3U=
github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
github.com/mattn/go-sqlite3 v1.14.12/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/minio/selfupdate v0.6.0 h1:i76PgT0K5xO9+hjzKcacQtO7+MjJ4JKA8Ak8XQ9DDwU=
github.com/minio/selfupdate v0.6.0/go.mod h1:bO02GTIPCMQFTEvE5h4DjYB58bCoZ35XLeBf0buTDdM=
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=
@ -76,99 +85,96 @@ github.com/paulmach/protoscan v0.2.1/go.mod h1:SpcSwydNLrxUGSDvXvO0P7g7AuhJ7lcKf
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
github.com/pierrec/lz4/v4 v4.1.14 h1:+fL8AQEZtz/ijeNnpduH0bROTu0O3NZAlPjQxGn8LwE=
github.com/pierrec/lz4/v4 v4.1.14/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4/go.mod h1:4OwLy04Bl9Ef3GJJCoec+30X3LQs/0/m4HFRt/2LUSA=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6OkFY5QxjkYwrChwuRruF69c169dPK26NUlk=
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis=
github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/shirou/gopsutil v2.19.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4/go.mod h1:qsXQc7+bwAM3Q1u/4XEfrquwF8Lw7D7y5cD8CuHnfIc=
github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8=
github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
github.com/sijms/go-ora/v2 v2.4.20 h1:9e3z7VLBQXRAHGiIda1GEFtRhfxata0LghyMZqvLKew=
github.com/sijms/go-ora/v2 v2.4.20/go.mod h1:EHxlY6x7y9HAsdfumurRfTd+v8NrEOTR3Xl4FWlH6xk=
github.com/sijms/go-ora/v2 v2.7.10 h1:GSLdj0PYYgSndhsnm7b6p32OqgnwnUZSkFb3j+htfhI=
github.com/sijms/go-ora/v2 v2.7.10/go.mod h1:EHxlY6x7y9HAsdfumurRfTd+v8NrEOTR3Xl4FWlH6xk=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.2 h1:4jaiDzPyXQvSd7D0EjG45355tLlV3VOECpq10pLC+8s=
github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
github.com/tklauser/go-sysconf v0.3.10/go.mod h1:C8XykCvCb+Gn0oNCWPIlcb0RuglQTYaQ2hGm7jmxEFk=
github.com/tklauser/numcpus v0.4.0/go.mod h1:1+UI3pD8NW14VMwdgJNJ1ESk2UnwhAnz5hMwiKKqXCQ=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
go.opentelemetry.io/otel v1.7.0 h1:Z2lA3Tdch0iDcrhJXDIlC94XE+bxok1F9B+4Lz/lGsM=
go.opentelemetry.io/otel v1.7.0/go.mod h1:5BdUoMIz5WEs0vt0CUEMtSSaTSHBBVwrhnz7+nrD5xk=
go.opentelemetry.io/otel/sdk v1.7.0 h1:4OmStpcKVOfvDOgCt7UriAPtKolwIhxpnSNI/yK+1B0=
go.opentelemetry.io/otel/sdk v1.7.0/go.mod h1:uTEOTwaqIVuTGiJN7ii13Ibp75wJmYUDe374q6cZwUU=
go.opentelemetry.io/otel/trace v1.7.0 h1:O37Iogk1lEkMRXewVtZ1BBTVn5JEp8GrJvP92bJqC6o=
go.opentelemetry.io/otel v1.14.0 h1:/79Huy8wbf5DnIPhemGB+zEPVwnN6fuQybr/SRXa6hM=
go.opentelemetry.io/otel v1.14.0/go.mod h1:o4buv+dJzx8rohcUeRmWUZhqupFvzWis188WlggnNeU=
go.opentelemetry.io/otel/sdk v1.14.0 h1:PDCppFRDq8A1jL9v6KMI6dYesaq+DFcDZvjsoGvxGzY=
go.opentelemetry.io/otel/sdk v1.14.0/go.mod h1:bwIC5TjrNG6QDCHNWvW4HLHtUQ4I+VQDsnjhvyZCALM=
go.opentelemetry.io/otel/trace v1.7.0/go.mod h1:fzLSB9nqR2eXzxPXb2JW9IKE+ScyXA48yyE4TNvoHqU=
go.opentelemetry.io/otel/trace v1.14.0 h1:wp2Mmvj41tDsyAJXiWDWpfNsOiIyd38fy85pyKcFq/M=
go.opentelemetry.io/otel/trace v1.14.0/go.mod h1:8avnQLK+CG77yNLUae4ea2JDQ6iT+gozhnZjy/rw9G8=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.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-20211209193657-4570a0811e8b/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.1.0 h1:MDRAIl0xIo9Io2xV565hzXHw3zVseKrJKodhohM5CjU=
golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw=
golang.org/x/crypto v0.0.0-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/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.9.0 h1:KENHtAZL2y3NLMYZeHY9DW8HW8V+kQyJsY/V9JlKvCs=
golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA=
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ=
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191220220014-0732a990476f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210228012217-479acdf4ea46/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220405052023-b1e9470b6e64/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220429233432-b5fbb4746d32/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
golang.org/x/sys v0.20.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.3.8-0.20211105212822-18b340fc7af2/go.mod h1:EFNZuWvGYxIRUEX+K8UmCFwYmZjqcrnq15ZuVldZkZ0=
golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68=
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk=
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo=
golang.org/x/tools v0.7.0 h1:W4OVu8VVOaIO0yzWMNdepAulS7YfoS3Zabrm8DOXXU4=
golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s=
golang.org/x/tools v0.18.0 h1:k8NLag8AGHnn+PHbl7g43CtqZAwG60vZkLqgyZgIHgQ=
golang.org/x/tools v0.18.0/go.mod h1:GL7B4CwcLLeo59yx/9UWWuNOW1n3VZ4f5axWfML7Lcg=
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=
@ -178,32 +184,17 @@ google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQ
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
lukechampine.com/uint128 v1.1.1/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk=
modernc.org/cc/v3 v3.36.0/go.mod h1:NFUHyPn4ekoC/JHeZFfZurN6ixxawE1BnVonP/oahEI=
modernc.org/ccgo/v3 v3.0.0-20220428102840-41399a37e894/go.mod h1:eI31LL8EwEBKPpNpA4bU1/i+sKOwOrQy8D87zWUcRZc=
modernc.org/ccgo/v3 v3.0.0-20220430103911-bc99d88307be/go.mod h1:bwdAnOoaIt8Ax9YdWGjxWsdkPcZyRPHqrOvJxaKAKGw=
modernc.org/ccgo/v3 v3.16.4/go.mod h1:tGtX0gE9Jn7hdZFeU88slbTh1UtCYKusWOoCJuvkWsQ=
modernc.org/ccgo/v3 v3.16.6/go.mod h1:tGtX0gE9Jn7hdZFeU88slbTh1UtCYKusWOoCJuvkWsQ=
modernc.org/ccorpus v1.11.6/go.mod h1:2gEUTrWqdpH2pXsmTM1ZkjeSrUWDpjMu2T6m29L/ErQ=
modernc.org/httpfs v1.0.6/go.mod h1:7dosgurJGp0sPaRanU53W4xZYKh14wfzX420oZADeHM=
modernc.org/libc v0.0.0-20220428101251-2d5f3daf273b/go.mod h1:p7Mg4+koNjc8jkqwcoFBJx7tXkpj00G77X7A72jXPXA=
modernc.org/libc v1.16.0/go.mod h1:N4LD6DBE9cf+Dzf9buBlzVJndKr/iJHG97vGLHYnb5A=
modernc.org/libc v1.16.1/go.mod h1:JjJE0eu4yeK7tab2n4S1w8tlWd9MxXLRzheaRnAKymU=
modernc.org/libc v1.16.7/go.mod h1:hYIV5VZczAmGZAnG15Vdngn5HSF5cSkbvfz2B7GRuVU=
modernc.org/libc v1.16.8 h1:Ux98PaOMvolgoFX/YwusFOHBnanXdGRmWgI8ciI2z4o=
modernc.org/libc v1.16.8/go.mod h1:hYIV5VZczAmGZAnG15Vdngn5HSF5cSkbvfz2B7GRuVU=
modernc.org/mathutil v1.2.2/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
modernc.org/mathutil v1.4.1 h1:ij3fYGe8zBF4Vu+g0oT7mB06r8sqGWKuJu1yXeR4by8=
modernc.org/mathutil v1.4.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
modernc.org/memory v1.1.1 h1:bDOL0DIDLQv7bWhP3gMvIrnoFw+Eo6F7a2QK9HPDiFU=
modernc.org/memory v1.1.1/go.mod h1:/0wo5ibyrQiaoUoH7f9D8dnglAmILJ5/cxZlRECf+Nw=
modernc.org/opt v0.1.1/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0=
modernc.org/sqlite v1.17.3 h1:iE+coC5g17LtByDYDWKpR6m2Z9022YrSh3bumwOnIrI=
modernc.org/sqlite v1.17.3/go.mod h1:10hPVYar9C0kfXuTWGz8s0XtB8uAGymUy51ZzStYe3k=
modernc.org/strutil v1.1.1/go.mod h1:DE+MQQ/hjKBZS2zNInV5hhcipt5rLPWkmpbGeW5mmdw=
modernc.org/tcl v1.13.1/go.mod h1:XOLfOwzhkljL4itZkK6T72ckMgvj0BDsnKNdZVUOecw=
modernc.org/token v1.0.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
modernc.org/z v1.5.1/go.mod h1:eWFB510QWW5Th9YGZT81s+LwvaAs3Q2yr4sP0rmLkv8=
modernc.org/libc v1.22.5 h1:91BNch/e5B0uPbJFgqbxXuOnxBQjlS//icfQEGmvyjE=
modernc.org/libc v1.22.5/go.mod h1:jj+Z7dTNX8fBScMVNRAYZ/jF91K8fdT2hYMThc3YjBY=
modernc.org/mathutil v1.5.0 h1:rV0Ko/6SfM+8G+yKiyI830l3Wuz1zRutdslNoQ0kfiQ=
modernc.org/mathutil v1.5.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
modernc.org/memory v1.5.0 h1:N+/8c5rE6EqugZwHii4IFsaJ7MUhoWX07J5tC/iI5Ds=
modernc.org/memory v1.5.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU=
modernc.org/sqlite v1.23.1 h1:nrSBg4aRQQwq59JpvGEQ15tNxoO5pX/kUjcRNwSAGQM=
modernc.org/sqlite v1.23.1/go.mod h1:OrDj17Mggn6MhE+iPbBNf7RGKODDE9NFT0f3EwDzJqk=

20
cmd/gf/go.work Normal file
View File

@ -0,0 +1,20 @@
go 1.18
use (
./
)
// =====================================================================================================
// NOTE:
// Please update associated commands in ../../.set_version.sh if any of the follows replacements change.
// =====================================================================================================
replace (
github.com/gogf/gf/contrib/drivers/clickhouse/v2 => ../../contrib/drivers/clickhouse
github.com/gogf/gf/contrib/drivers/mssql/v2 => ../../contrib/drivers/mssql
github.com/gogf/gf/contrib/drivers/mysql/v2 => ../../contrib/drivers/mysql
github.com/gogf/gf/contrib/drivers/oracle/v2 => ../../contrib/drivers/oracle
github.com/gogf/gf/contrib/drivers/pgsql/v2 => ../../contrib/drivers/pgsql
github.com/gogf/gf/contrib/drivers/sqlite/v2 => ../../contrib/drivers/sqlite
github.com/gogf/gf/v2 => ../../
)

View File

@ -55,6 +55,7 @@ func (c cGF) Index(ctx context.Context, in cGFInput) (out *cGFOutput, err error)
_, err = Version.Index(ctx, cVersionInput{})
return
}
answer := "n"
// No argument or option, do installation checks.
if data, isInstalled := service.Install.IsInstalled(); !isInstalled {
@ -71,6 +72,7 @@ func (c cGF) Index(ctx context.Context, in cGFInput) (out *cGFOutput, err error)
gcmd.Scan("press `Enter` to exit...")
return
}
// Print help content.
gcmd.CommandFromCtx(ctx).Print()
return

View File

@ -44,10 +44,11 @@ type cBuild struct {
}
const (
cBuildBrief = `cross-building go project for lots of platforms`
cBuildEg = `
cBuildDefaultFile = "main.go"
cBuildBrief = `cross-building go project for lots of platforms`
cBuildEg = `
gf build main.go
gf build main.go --pack public,template
gf build main.go --ps public,template
gf build main.go --cgo
gf build main.go -m none
gf build main.go -n my-app -a all -s all
@ -123,7 +124,7 @@ type cBuildInput struct {
Arch string `short:"a" name:"arch" brief:"output binary architecture, multiple arch separated with ','"`
System string `short:"s" name:"system" brief:"output binary system, multiple os separated with ','"`
Output string `short:"o" name:"output" brief:"output binary path, used when building single binary file"`
Path string `short:"p" name:"path" brief:"output binary directory path, default is './temp'" d:"./temp"`
Path string `short:"p" name:"path" brief:"output binary directory path, default is '.'" d:"."`
Extra string `short:"e" name:"extra" brief:"extra custom \"go build\" options"`
Mod string `short:"m" name:"mod" brief:"like \"-mod\" option of \"go build\", use \"-m none\" to disable go module"`
Cgo bool `short:"c" name:"cgo" brief:"enable or disable cgo feature, it's disabled in default" orphan:"true"`
@ -152,14 +153,15 @@ func (c cBuild) Index(ctx context.Context, in cBuildInput) (out *cBuildOutput, e
var (
parser = gcmd.ParserFromCtx(ctx)
file = parser.GetArg(2).String()
file = in.File
)
if len(file) < 1 {
if file == "" {
file = parser.GetArg(2).String()
// Check and use the main.go file.
if gfile.Exists("main.go") {
file = "main.go"
if gfile.Exists(cBuildDefaultFile) {
file = cBuildDefaultFile
} else {
mlog.Fatal("build file path cannot be empty")
mlog.Fatal("build file path is empty or main.go not found in current working directory")
}
}
if in.Name == "" {
@ -239,13 +241,7 @@ func (c cBuild) Index(ctx context.Context, in cBuildInput) (out *cBuildOutput, e
} else {
genv.MustSet("CGO_ENABLED", "0")
}
var (
cmd = ""
ext = ""
)
for system, item := range platformMap {
cmd = ""
ext = ""
if len(customSystems) > 0 && customSystems[0] != "all" && !gstr.InArray(customSystems, system) {
continue
}
@ -254,44 +250,25 @@ func (c cBuild) Index(ctx context.Context, in cBuildInput) (out *cBuildOutput, e
continue
}
if len(customSystems) == 0 && len(customArches) == 0 {
if runtime.GOOS == "windows" {
ext = ".exe"
}
// Single binary building, output the binary to current working folder.
output := ""
if len(in.Output) > 0 {
output = "-o " + in.Output + ext
} else {
output = "-o " + in.Name + ext
}
cmd = fmt.Sprintf(`go build %s -ldflags "%s" %s %s`, output, ldFlags, in.Extra, file)
} else {
// Cross-building, output the compiled binary to specified path.
if system == "windows" {
ext = ".exe"
}
genv.MustSet("GOOS", system)
genv.MustSet("GOARCH", arch)
cmd = fmt.Sprintf(
`go build -o %s/%s/%s%s -ldflags "%s" %s%s`,
in.Path, system+"_"+arch, in.Name, ext, ldFlags, in.Extra, file,
// For example:
// `gf build`
// `gf build -o main.exe`
c.doBinaryBuild(
ctx, file,
in.Output, in.Path,
runtime.GOOS, runtime.GOARCH, in.Name, ldFlags, in.Extra,
in.ExitWhenError,
true,
)
}
mlog.Debug(cmd)
// It's not necessary printing the complete command string.
cmdShow, _ := gregex.ReplaceString(`\s+(-ldflags ".+?")\s+`, " ", cmd)
mlog.Print(cmdShow)
if result, err := gproc.ShellExec(ctx, cmd); err != nil {
mlog.Printf(
"failed to build, os:%s, arch:%s, error:\n%s\n\n%s\n",
system, arch, gstr.Trim(result),
`you may use command option "--debug" to enable debug info and check the details`,
)
if in.ExitWhenError {
os.Exit(1)
}
} else {
mlog.Debug(gstr.Trim(result))
c.doBinaryBuild(
ctx, file,
in.Output, in.Path,
system, arch, in.Name, ldFlags, in.Extra,
in.ExitWhenError,
false,
)
}
// single binary building.
if len(customSystems) == 0 && len(customArches) == 0 {
@ -305,6 +282,68 @@ buildDone:
return
}
func (c cBuild) doBinaryBuild(
ctx context.Context,
filePath string,
outputPath, dirPath string,
system, arch, name, ldFlags, extra string,
exitWhenError bool,
singleBuild bool,
) {
var (
cmd string
ext string
)
// Cross-building, output the compiled binary to specified path.
if system == "windows" {
ext = ".exe"
}
genv.MustSet("GOOS", system)
genv.MustSet("GOARCH", arch)
if outputPath != "" {
outputPath = "-o " + outputPath
} else {
if dirPath == "" {
dirPath = "."
} else {
dirPath = gstr.TrimRight(dirPath, "/")
}
if singleBuild {
outputPath = fmt.Sprintf(
"-o %s/%s%s",
dirPath, name, ext,
)
} else {
outputPath = fmt.Sprintf(
"-o %s/%s/%s%s",
dirPath, system+"_"+arch, name, ext,
)
}
}
cmd = fmt.Sprintf(
`go build %s -ldflags "%s" %s%s`,
outputPath, ldFlags, extra, filePath,
)
mlog.Debug(fmt.Sprintf("build for GOOS=%s GOARCH=%s", system, arch))
mlog.Debug(cmd)
// It's not necessary printing the complete command string, filtering ldFlags.
cmdShow, _ := gregex.ReplaceString(`\s+(-ldflags ".+?")\s+`, " ", cmd)
mlog.Print(cmdShow)
if result, err := gproc.ShellExec(ctx, cmd); err != nil {
mlog.Printf(
"failed to build, os:%s, arch:%s, error:\n%s\n\n%s\n",
system, arch, gstr.Trim(result),
`you may use command option "--debug" to enable debug info and check the details`,
)
if exitWhenError {
os.Exit(1)
}
} else {
mlog.Debug(gstr.Trim(result))
}
}
// getBuildInVarStr retrieves and returns the custom build-in variables in configuration
// file as json.
func (c cBuild) getBuildInVarStr(ctx context.Context, in cBuildInput) string {

View File

@ -1,20 +0,0 @@
package cmd
import (
"fmt"
"testing"
"github.com/gogf/gf/v2/test/gtest"
)
func Test_Fix_doFixV25Content(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
var (
content = gtest.DataContent(`fix25_content.go.txt`)
f = cFix{}
)
newContent, err := f.doFixV25Content(content)
t.AssertNil(err)
fmt.Println(newContent)
})
}

View File

@ -25,6 +25,7 @@ import (
)
var (
// Init .
Init = cInit{}
)
@ -64,14 +65,13 @@ type cInitInput struct {
Name string `name:"NAME" arg:"true" v:"required" brief:"{cInitNameBrief}"`
Mono bool `name:"mono" short:"m" brief:"initialize a mono-repo instead a single-repo" orphan:"true"`
Update bool `name:"update" short:"u" brief:"update to the latest goframe version" orphan:"true"`
Module string `name:"module" short:"g" brief:"custom go module"`
}
type cInitOutput struct{}
func (c cInit) Index(ctx context.Context, in cInitInput) (out *cInitOutput, err error) {
var (
overwrote = false
)
var overwrote = false
if !gfile.IsEmpty(in.Name) && !allyes.Check() {
s := gcmd.Scanf(`the folder "%s" is not empty, files might be overwrote, continue? [y/n]: `, in.Name)
if strings.EqualFold(s, "n") {
@ -105,7 +105,7 @@ func (c cInit) Index(ctx context.Context, in cInitInput) (out *cInitOutput, err
err = gfile.ReadLines(gitignoreFile, func(line string) error {
// Add only hidden files or directories
// If other directories are added, it may cause the entire directory to be ignored
// such as 'main' in the .gitignore file, but the path is 'D:\main\my-project'
// such as 'main' in the .gitignore file, but the path is ' D:\main\my-project '
if line != "" && strings.HasPrefix(line, ".") {
ignoreFiles = append(ignoreFiles, line)
}
@ -118,6 +118,11 @@ func (c cInit) Index(ctx context.Context, in cInitInput) (out *cInitOutput, err
}
}
// Replace module name.
if in.Module == "" {
in.Module = gfile.Basename(gfile.RealPath(in.Name))
}
// Replace template name to project name.
err = gfile.ReplaceDirFunc(func(path, content string) string {
for _, ignoreFile := range ignoreFiles {
@ -125,7 +130,7 @@ func (c cInit) Index(ctx context.Context, in cInitInput) (out *cInitOutput, err
return content
}
}
return gstr.Replace(gfile.GetContents(path), cInitRepoPrefix+templateRepoName, gfile.Basename(gfile.RealPath(in.Name)))
return gstr.Replace(gfile.GetContents(path), cInitRepoPrefix+templateRepoName, in.Module)
}, in.Name, "*", true)
if err != nil {
return

View File

@ -1,4 +1,4 @@
// Copyright GoFrame gf Author(https://goframe.org). All Rights Reserved.
// Copyright GoFrame gf Author(https://goframe.org). All Rights Reserved
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
@ -9,6 +9,7 @@ package cmd
import (
"context"
"fmt"
"path/filepath"
"runtime"
"strings"
@ -33,10 +34,11 @@ type cRun struct {
}
type cRunApp struct {
File string // Go run file name.
Path string // Directory storing built binary.
Options string // Extra "go run" options.
Args string // Custom arguments.
File string // Go run file name.
Path string // Directory storing built binary.
Options string // Extra "go run" options.
Args string // Custom arguments.
WatchPaths []string // Watch paths for live reload.
}
const (
@ -46,15 +48,17 @@ const (
gf run main.go
gf run main.go --args "server -p 8080"
gf run main.go -mod=vendor
gf run main.go -w "manifest/config/*.yaml"
`
cRunDc = `
The "run" command is used for running go codes with hot-compiled-like feature,
which compiles and runs the go codes asynchronously when codes change.
`
cRunFileBrief = `building file path.`
cRunPathBrief = `output directory path for built binary file. it's "manifest/output" in default`
cRunExtraBrief = `the same options as "go run"/"go build" except some options as follows defined`
cRunArgsBrief = `custom arguments for your process`
cRunFileBrief = `building file path.`
cRunPathBrief = `output directory path for built binary file. it's "manifest/output" in default`
cRunExtraBrief = `the same options as "go run"/"go build" except some options as follows defined`
cRunArgsBrief = `custom arguments for your process`
cRunWatchPathsBrief = `watch additional paths for live reload, separated by ",". i.e. "manifest/config/*.yaml"`
)
var (
@ -63,24 +67,26 @@ var (
func init() {
gtag.Sets(g.MapStrStr{
`cRunUsage`: cRunUsage,
`cRunBrief`: cRunBrief,
`cRunEg`: cRunEg,
`cRunDc`: cRunDc,
`cRunFileBrief`: cRunFileBrief,
`cRunPathBrief`: cRunPathBrief,
`cRunExtraBrief`: cRunExtraBrief,
`cRunArgsBrief`: cRunArgsBrief,
`cRunUsage`: cRunUsage,
`cRunBrief`: cRunBrief,
`cRunEg`: cRunEg,
`cRunDc`: cRunDc,
`cRunFileBrief`: cRunFileBrief,
`cRunPathBrief`: cRunPathBrief,
`cRunExtraBrief`: cRunExtraBrief,
`cRunArgsBrief`: cRunArgsBrief,
`cRunWatchPathsBrief`: cRunWatchPathsBrief,
})
}
type (
cRunInput struct {
g.Meta `name:"run"`
File string `name:"FILE" arg:"true" brief:"{cRunFileBrief}" v:"required"`
Path string `name:"path" short:"p" brief:"{cRunPathBrief}" d:"./"`
Extra string `name:"extra" short:"e" brief:"{cRunExtraBrief}"`
Args string `name:"args" short:"a" brief:"{cRunArgsBrief}"`
g.Meta `name:"run"`
File string `name:"FILE" arg:"true" brief:"{cRunFileBrief}" v:"required"`
Path string `name:"path" short:"p" brief:"{cRunPathBrief}" d:"./"`
Extra string `name:"extra" short:"e" brief:"{cRunExtraBrief}"`
Args string `name:"args" short:"a" brief:"{cRunArgsBrief}"`
WatchPaths []string `name:"watchPaths" short:"w" brief:"{cRunWatchPathsBrief}"`
}
cRunOutput struct{}
)
@ -91,31 +97,52 @@ func (c cRun) Index(ctx context.Context, in cRunInput) (out *cRunOutput, err err
mlog.Fatalf(`command "go" not found in your environment, please install golang first to proceed this command`)
}
if len(in.WatchPaths) == 1 {
in.WatchPaths = strings.Split(in.WatchPaths[0], ",")
mlog.Printf("watchPaths: %v", in.WatchPaths)
}
app := &cRunApp{
File: in.File,
Path: in.Path,
Options: in.Extra,
Args: in.Args,
File: in.File,
Path: in.Path,
Options: in.Extra,
Args: in.Args,
WatchPaths: in.WatchPaths,
}
dirty := gtype.NewBool()
_, err = gfsnotify.Add(gfile.RealPath("."), func(event *gfsnotify.Event) {
callbackFunc := func(event *gfsnotify.Event) {
if gfile.ExtName(event.Path) != "go" {
return
}
// Variable `dirty` is used for running the changes only one in one second.
if !dirty.Cas(false, true) {
return
}
// With some delay in case of multiple code changes in very short interval.
gtimer.SetTimeout(ctx, 1500*gtime.MS, func(ctx context.Context) {
defer dirty.Set(false)
mlog.Printf(`go file changes: %s`, event.String())
mlog.Printf(`watched file changes: %s`, event.String())
app.Run(ctx)
})
})
if err != nil {
mlog.Fatal(err)
}
if len(app.WatchPaths) > 0 {
for _, path := range app.WatchPaths {
_, err = gfsnotify.Add(gfile.RealPath(path), callbackFunc)
if err != nil {
mlog.Fatal(err)
}
}
} else {
_, err = gfsnotify.Add(gfile.RealPath("."), callbackFunc)
if err != nil {
mlog.Fatal(err)
}
}
go app.Run(ctx)
select {}
}
@ -152,7 +179,6 @@ func (app *cRunApp) Run(ctx context.Context) {
if process != nil {
if err := process.Kill(); err != nil {
mlog.Debugf("kill process error: %s", err.Error())
//return
}
}
// Run the binary file.
@ -171,3 +197,22 @@ func (app *cRunApp) Run(ctx context.Context) {
mlog.Printf("build running pid: %d", pid)
}
}
func matchWatchPaths(watchPaths []string, eventPath string) bool {
for _, path := range watchPaths {
absPath, err := filepath.Abs(path)
if err != nil {
mlog.Printf("match watchPath '%s' error: %s", path, err.Error())
continue
}
matched, err := filepath.Match(absPath, eventPath)
if err != nil {
mlog.Printf("match watchPath '%s' error: %s", path, err.Error())
continue
}
if matched {
return true
}
}
return false
}

View File

@ -11,7 +11,7 @@ import (
"fmt"
"runtime"
"github.com/minio/selfupdate"
"github.com/gogf/selfupdate"
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
"github.com/gogf/gf/cmd/gf/v2/internal/utility/utils"

View File

@ -7,14 +7,19 @@
package cmd
import (
"bytes"
"context"
"fmt"
"runtime"
"strings"
"time"
"github.com/gogf/gf/v2"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gbuild"
"github.com/gogf/gf/v2/os/gfile"
"github.com/gogf/gf/v2/os/gproc"
"github.com/gogf/gf/v2/text/gregex"
"github.com/gogf/gf/v2/text/gstr"
@ -25,6 +30,10 @@ var (
Version = cVersion{}
)
const (
defaultIndent = "{{indent}}"
)
type cVersion struct {
g.Meta `name:"version" brief:"show version information of current binary"`
}
@ -36,34 +45,90 @@ type cVersionInput struct {
type cVersionOutput struct{}
func (c cVersion) Index(ctx context.Context, in cVersionInput) (*cVersionOutput, error) {
info := gbuild.Info()
if info.Git == "" {
info.Git = "none"
}
mlog.Printf(`GoFrame CLI Tool %s, https://goframe.org`, gf.VERSION)
gfVersion, err := c.getGFVersionOfCurrentProject()
if err != nil {
gfVersion = err.Error()
detailBuffer := &detailBuffer{}
detailBuffer.WriteString(fmt.Sprintf("%s", gf.VERSION))
detailBuffer.appendLine(0, "Welcome to GoFrame!")
detailBuffer.appendLine(0, "Env Detail:")
goVersion, ok := getGoVersion()
if ok {
detailBuffer.appendLine(1, fmt.Sprintf("Go Version: %s", goVersion))
detailBuffer.appendLine(1, fmt.Sprintf("GF Version(go.mod): %s", getGoFrameVersion(2)))
} else {
gfVersion = gfVersion + " in current go.mod"
}
mlog.Printf(`GoFrame Version: %s`, gfVersion)
mlog.Printf(`CLI Installed At: %s`, gfile.SelfPath())
if info.GoFrame == "" {
mlog.Print(`Current is a custom installed version, no installation information.`)
return nil, nil
v, err := c.getGFVersionOfCurrentProject()
if err == nil {
detailBuffer.appendLine(1, fmt.Sprintf("GF Version(go.mod): %s", v))
} else {
detailBuffer.appendLine(1, fmt.Sprintf("GF Version(go.mod): %s", err.Error()))
}
}
mlog.Print(gstr.Trim(fmt.Sprintf(`
CLI Built Detail:
Go Version: %s
GF Version: %s
Git Commit: %s
Build Time: %s
`, info.Golang, info.GoFrame, info.Git, info.Time)))
detailBuffer.appendLine(0, "CLI Detail:")
detailBuffer.appendLine(1, fmt.Sprintf("Installed At: %s", gfile.SelfPath()))
info := gbuild.Info()
if info.GoFrame == "" {
detailBuffer.appendLine(1, fmt.Sprintf("Built Go Version: %s", runtime.Version()))
detailBuffer.appendLine(1, fmt.Sprintf("Built GF Version: %s", gf.VERSION))
} else {
if info.Git == "" {
info.Git = "none"
}
detailBuffer.appendLine(1, fmt.Sprintf("Built Go Version: %s", info.Golang))
detailBuffer.appendLine(1, fmt.Sprintf("Built GF Version: %s", info.GoFrame))
detailBuffer.appendLine(1, fmt.Sprintf("Git Commit: %s", info.Git))
detailBuffer.appendLine(1, fmt.Sprintf("Built Time: %s", info.Time))
}
detailBuffer.appendLine(0, "Others Detail:")
detailBuffer.appendLine(1, "Docs: https://goframe.org")
detailBuffer.appendLine(1, fmt.Sprintf("Now : %s", time.Now().Format(time.RFC3339)))
mlog.Print(detailBuffer.replaceAllIndent(" "))
return nil, nil
}
// detailBuffer is a buffer for detail information.
type detailBuffer struct {
bytes.Buffer
}
// appendLine appends a line to the buffer with given indent level.
func (d *detailBuffer) appendLine(indentLevel int, line string) {
d.WriteString(fmt.Sprintf("\n%s%s", strings.Repeat(defaultIndent, indentLevel), line))
}
// replaceAllIndent replaces the tab with given indent string and prints the buffer content.
func (d *detailBuffer) replaceAllIndent(indentStr string) string {
return strings.ReplaceAll(d.String(), defaultIndent, indentStr)
}
// getGoFrameVersion returns the goframe version of current project using.
func getGoFrameVersion(indentLevel int) (gfVersion string) {
pkgInfo, err := gproc.ShellExec(context.Background(), `go list -f "{{if (not .Main)}}{{.Path}}@{{.Version}}{{end}}" -m all`)
if err != nil {
return "cannot find go.mod"
}
pkgList := gstr.Split(pkgInfo, "\n")
for _, v := range pkgList {
if strings.HasPrefix(v, "github.com/gogf/gf") {
gfVersion += fmt.Sprintf("\n%s%s", strings.Repeat(defaultIndent, indentLevel), v)
}
}
return
}
// getGoVersion returns the go version
func getGoVersion() (goVersion string, ok bool) {
goVersion, err := gproc.ShellExec(context.Background(), "go version")
if err != nil {
return "", false
}
goVersion = gstr.TrimLeftStr(goVersion, "go version ")
goVersion = gstr.TrimRightStr(goVersion, "\n")
return goVersion, true
}
// getGFVersionOfCurrentProject checks and returns the GoFrame version current project using.
func (c cVersion) getGFVersionOfCurrentProject() (string, error) {
goModPath := gfile.Join(gfile.Pwd(), "go.mod")

View File

@ -0,0 +1,38 @@
// Copyright GoFrame gf Author(https://goframe.org). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://github.com/gogf/gf.
package cmd
import (
"context"
"fmt"
"github.com/gogf/gf/v2/database/gdb"
"github.com/gogf/gf/v2/test/gtest"
)
var (
ctx = context.Background()
testDB gdb.DB
link = "mysql:root:12345678@tcp(127.0.0.1:3306)/test?loc=Local&parseTime=true"
)
func init() {
var err error
testDB, err = gdb.New(gdb.ConfigNode{
Link: link,
})
if err != nil {
panic(err)
}
}
func dropTableWithDb(db gdb.DB, table string) {
dropTableStmt := fmt.Sprintf("DROP TABLE IF EXISTS `%s`", table)
if _, err := db.Exec(ctx, dropTableStmt); err != nil {
gtest.Error(err)
}
}

View File

@ -0,0 +1,151 @@
// Copyright GoFrame gf Author(https://goframe.org). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://github.com/gogf/gf.
package cmd
import (
"testing"
"github.com/gogf/gf/v2/os/gfile"
"github.com/gogf/gf/v2/os/gproc"
"github.com/gogf/gf/v2/test/gtest"
"github.com/gogf/gf/v2/text/gstr"
)
func Test_Build_Single(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
var (
buildPath = gtest.DataPath(`build`, `single`)
pwd = gfile.Pwd()
binaryName = `t.test`
binaryPath = gtest.DataPath(`build`, `single`, binaryName)
f = cBuild{}
)
defer gfile.Chdir(pwd)
defer gfile.Remove(binaryPath)
err := gfile.Chdir(buildPath)
t.AssertNil(err)
t.Assert(gfile.Exists(binaryPath), false)
_, err = f.Index(ctx, cBuildInput{
File: cBuildDefaultFile,
Name: binaryName,
})
t.AssertNil(err)
t.Assert(gfile.Exists(binaryPath), true)
})
}
func Test_Build_Single_Output(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
var (
buildPath = gtest.DataPath(`build`, `single`)
pwd = gfile.Pwd()
binaryName = `tt`
binaryDirPath = gtest.DataPath(`build`, `single`, `tt`)
binaryPath = gtest.DataPath(`build`, `single`, `tt`, binaryName)
f = cBuild{}
)
defer gfile.Chdir(pwd)
defer gfile.Remove(binaryDirPath)
err := gfile.Chdir(buildPath)
t.AssertNil(err)
t.Assert(gfile.Exists(binaryPath), false)
_, err = f.Index(ctx, cBuildInput{
Output: "./tt/tt",
})
t.AssertNil(err)
t.Assert(gfile.Exists(binaryPath), true)
})
}
func Test_Build_Single_Path(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
var (
buildPath = gtest.DataPath(`build`, `single`)
pwd = gfile.Pwd()
dirName = "ttt"
binaryName = `main`
binaryDirPath = gtest.DataPath(`build`, `single`, dirName)
binaryPath = gtest.DataPath(`build`, `single`, dirName, binaryName)
f = cBuild{}
)
defer gfile.Chdir(pwd)
defer gfile.Remove(binaryDirPath)
err := gfile.Chdir(buildPath)
t.AssertNil(err)
t.Assert(gfile.Exists(binaryPath), false)
_, err = f.Index(ctx, cBuildInput{
Path: "ttt",
})
t.AssertNil(err)
t.Assert(gfile.Exists(binaryPath), true)
})
}
func Test_Build_Single_VarMap(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
var (
buildPath = gtest.DataPath(`build`, `varmap`)
pwd = gfile.Pwd()
binaryName = `main`
binaryPath = gtest.DataPath(`build`, `varmap`, binaryName)
f = cBuild{}
)
defer gfile.Chdir(pwd)
defer gfile.Remove(binaryPath)
err := gfile.Chdir(buildPath)
t.AssertNil(err)
t.Assert(gfile.Exists(binaryPath), false)
_, err = f.Index(ctx, cBuildInput{
VarMap: map[string]interface{}{
"a": "1",
"b": "2",
},
})
t.AssertNil(err)
t.Assert(gfile.Exists(binaryPath), true)
result, err := gproc.ShellExec(ctx, binaryPath)
t.AssertNil(err)
t.Assert(gstr.Contains(result, `a: 1`), true)
t.Assert(gstr.Contains(result, `b: 2`), true)
})
}
func Test_Build_Multiple(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
var (
buildPath = gtest.DataPath(`build`, `multiple`)
pwd = gfile.Pwd()
binaryDirPath = gtest.DataPath(`build`, `multiple`, `temp`)
binaryPathLinux = gtest.DataPath(`build`, `multiple`, `temp`, `v1.1`, `linux_amd64`, `ttt`)
binaryPathWindows = gtest.DataPath(`build`, `multiple`, `temp`, `v1.1`, `windows_amd64`, `ttt.exe`)
f = cBuild{}
)
defer gfile.Chdir(pwd)
defer gfile.Remove(binaryDirPath)
err := gfile.Chdir(buildPath)
t.AssertNil(err)
t.Assert(gfile.Exists(binaryPathLinux), false)
t.Assert(gfile.Exists(binaryPathWindows), false)
_, err = f.Index(ctx, cBuildInput{
File: "multiple.go",
Name: "ttt",
Version: "v1.1",
Arch: "amd64",
System: "linux, windows",
Path: "temp",
})
t.AssertNil(err)
t.Assert(gfile.Exists(binaryPathLinux), true)
t.Assert(gfile.Exists(binaryPathWindows), true)
})
}

View File

@ -0,0 +1,24 @@
// Copyright GoFrame gf Author(https://goframe.org). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://github.com/gogf/gf.
package cmd
import (
"testing"
"github.com/gogf/gf/v2/test/gtest"
)
func Test_Fix_doFixV25Content(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
var (
content = gtest.DataContent(`fix`, `fix25_content.go`)
f = cFix{}
)
_, err := f.doFixV25Content(content)
t.AssertNil(err)
})
}

View File

@ -0,0 +1,309 @@
// Copyright GoFrame gf Author(https://goframe.org). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://github.com/gogf/gf.
package cmd
import (
"path/filepath"
"testing"
"github.com/gogf/gf/cmd/gf/v2/internal/cmd/genctrl"
"github.com/gogf/gf/v2/os/gfile"
"github.com/gogf/gf/v2/test/gtest"
"github.com/gogf/gf/v2/util/guid"
"github.com/gogf/gf/v2/util/gutil"
)
func Test_Gen_Ctrl_Default(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
var (
path = gfile.Temp(guid.S())
apiFolder = gtest.DataPath("genctrl", "api")
in = genctrl.CGenCtrlInput{
SrcFolder: apiFolder,
DstFolder: path,
WatchFile: "",
SdkPath: "",
SdkStdVersion: false,
SdkNoV1: false,
Clear: false,
Merge: false,
}
)
err := gutil.FillStructWithDefault(&in)
t.AssertNil(err)
err = gfile.Mkdir(path)
t.AssertNil(err)
defer gfile.Remove(path)
_, err = genctrl.CGenCtrl{}.Ctrl(ctx, in)
t.AssertNil(err)
// apiInterface file
var (
genApi = apiFolder + filepath.FromSlash("/article/article.go")
genApiExpect = apiFolder + filepath.FromSlash("/article/article_expect.go")
)
defer gfile.Remove(genApi)
t.Assert(gfile.GetContents(genApi), gfile.GetContents(genApiExpect))
// files
files, err := gfile.ScanDir(path, "*.go", true)
t.AssertNil(err)
t.Assert(files, []string{
path + filepath.FromSlash("/article/article.go"),
path + filepath.FromSlash("/article/article_new.go"),
path + filepath.FromSlash("/article/article_v1_create.go"),
path + filepath.FromSlash("/article/article_v1_get_list.go"),
path + filepath.FromSlash("/article/article_v1_get_one.go"),
path + filepath.FromSlash("/article/article_v1_update.go"),
path + filepath.FromSlash("/article/article_v2_create.go"),
path + filepath.FromSlash("/article/article_v2_update.go"),
})
// content
testPath := gtest.DataPath("genctrl", "controller")
expectFiles := []string{
testPath + filepath.FromSlash("/article/article.go"),
testPath + filepath.FromSlash("/article/article_new.go"),
testPath + filepath.FromSlash("/article/article_v1_create.go"),
testPath + filepath.FromSlash("/article/article_v1_get_list.go"),
testPath + filepath.FromSlash("/article/article_v1_get_one.go"),
testPath + filepath.FromSlash("/article/article_v1_update.go"),
testPath + filepath.FromSlash("/article/article_v2_create.go"),
testPath + filepath.FromSlash("/article/article_v2_update.go"),
}
for i := range files {
t.Assert(gfile.GetContents(files[i]), gfile.GetContents(expectFiles[i]))
}
})
}
// 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)
}
})
}
// gf gen ctrl -m
// In the same module, different API files are added
func Test_Gen_Ctrl_UseMerge_AddNewFile(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
var (
ctrlPath = gfile.Temp(guid.S())
//ctrlPath = gtest.DataPath("issue", "3460", "controller")
apiFolder = gtest.DataPath("genctrl-merge", "add_new_file", "api")
in = genctrl.CGenCtrlInput{
SrcFolder: apiFolder,
DstFolder: ctrlPath,
Merge: true,
}
)
const testNewApiFile = `
package v1
import "github.com/gogf/gf/v2/frame/g"
type DictTypeAddReq struct {
g.Meta
}
type DictTypeAddRes struct {
}
`
err := gfile.Mkdir(ctrlPath)
t.AssertNil(err)
defer gfile.Remove(ctrlPath)
_, err = genctrl.CGenCtrl{}.Ctrl(ctx, in)
t.AssertNil(err)
var (
genApi = filepath.Join(apiFolder, "/dict/dict.go")
genApiExpect = filepath.Join(apiFolder, "/dict/dict_expect.go")
)
defer gfile.Remove(genApi)
t.Assert(gfile.GetContents(genApi), gfile.GetContents(genApiExpect))
genCtrlFiles, err := gfile.ScanDir(ctrlPath, "*.go", true)
t.AssertNil(err)
t.Assert(genCtrlFiles, []string{
filepath.Join(ctrlPath, "/dict/dict.go"),
filepath.Join(ctrlPath, "/dict/dict_new.go"),
filepath.Join(ctrlPath, "/dict/dict_v1_dict_type.go"),
})
expectCtrlPath := gtest.DataPath("genctrl-merge", "add_new_file", "controller")
expectFiles := []string{
filepath.Join(expectCtrlPath, "/dict/dict.go"),
filepath.Join(expectCtrlPath, "/dict/dict_new.go"),
filepath.Join(expectCtrlPath, "/dict/dict_v1_dict_type.go"),
}
// Line Feed maybe \r\n or \n
expectFilesContent(t, genCtrlFiles, expectFiles)
// Add a new API file
newApiFilePath := filepath.Join(apiFolder, "/dict/v1/test_new.go")
err = gfile.PutContents(newApiFilePath, testNewApiFile)
t.AssertNil(err)
defer gfile.Remove(newApiFilePath)
// Then execute the command
_, err = genctrl.CGenCtrl{}.Ctrl(ctx, in)
t.AssertNil(err)
genApi = filepath.Join(apiFolder, "/dict.go")
genApiExpect = filepath.Join(apiFolder, "/dict_add_new_ctrl_expect.gotest")
t.Assert(gfile.GetContents(genApi), gfile.GetContents(genApiExpect))
genCtrlFiles = append(genCtrlFiles, filepath.Join(ctrlPath, "/dict/dict_v1_test_new.go"))
// Use the gotest suffix, otherwise the IDE will delete the import
expectFiles = append(expectFiles, filepath.Join(expectCtrlPath, "/dict/dict_v1_test_new.gotest"))
// Line Feed maybe \r\n or \n
expectFilesContent(t, genCtrlFiles, expectFiles)
})
}
// gf gen ctrl -m
// In the same module, Add the same file to the API
func Test_Gen_Ctrl_UseMerge_AddNewCtrl(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
var (
ctrlPath = gfile.Temp(guid.S())
//ctrlPath = gtest.DataPath("issue", "3460", "controller")
apiFolder = gtest.DataPath("genctrl-merge", "add_new_ctrl", "api")
in = genctrl.CGenCtrlInput{
SrcFolder: apiFolder,
DstFolder: ctrlPath,
Merge: true,
}
)
err := gfile.Mkdir(ctrlPath)
t.AssertNil(err)
defer gfile.Remove(ctrlPath)
_, err = genctrl.CGenCtrl{}.Ctrl(ctx, in)
t.AssertNil(err)
var (
genApi = filepath.Join(apiFolder, "/dict/dict.go")
genApiExpect = filepath.Join(apiFolder, "/dict/dict_expect.go")
)
defer gfile.Remove(genApi)
t.Assert(gfile.GetContents(genApi), gfile.GetContents(genApiExpect))
genCtrlFiles, err := gfile.ScanDir(ctrlPath, "*.go", true)
t.AssertNil(err)
t.Assert(genCtrlFiles, []string{
filepath.Join(ctrlPath, "/dict/dict.go"),
filepath.Join(ctrlPath, "/dict/dict_new.go"),
filepath.Join(ctrlPath, "/dict/dict_v1_dict_type.go"),
})
expectCtrlPath := gtest.DataPath("genctrl-merge", "add_new_ctrl", "controller")
expectFiles := []string{
filepath.Join(expectCtrlPath, "/dict/dict.go"),
filepath.Join(expectCtrlPath, "/dict/dict_new.go"),
filepath.Join(expectCtrlPath, "/dict/dict_v1_dict_type.go"),
}
// Line Feed maybe \r\n or \n
expectFilesContent(t, genCtrlFiles, expectFiles)
const testNewApiFile = `
type DictTypeAddReq struct {
g.Meta
}
type DictTypeAddRes struct {
}
`
dictModuleFileName := filepath.Join(apiFolder, "/dict/v1/dict_type.go")
// Save the contents of the file before the changes
apiFileContents := gfile.GetContents(dictModuleFileName)
// Add a new API file
err = gfile.PutContentsAppend(dictModuleFileName, testNewApiFile)
t.AssertNil(err)
//==================================
// Then execute the command
_, err = genctrl.CGenCtrl{}.Ctrl(ctx, in)
t.AssertNil(err)
genApi = filepath.Join(apiFolder, "/dict.go")
genApiExpect = filepath.Join(apiFolder, "/dict_add_new_ctrl_expect.gotest")
t.Assert(gfile.GetContents(genApi), gfile.GetContents(genApiExpect))
// Use the gotest suffix, otherwise the IDE will delete the import
expectFiles[2] = filepath.Join(expectCtrlPath, "/dict/dict_v1_test_new.gotest")
// Line Feed maybe \r\n or \n
expectFilesContent(t, genCtrlFiles, expectFiles)
// Restore the contents of the original API file
err = gfile.PutContents(dictModuleFileName, apiFileContents)
t.AssertNil(err)
})
}
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)
}
}

View File

@ -0,0 +1,693 @@
// Copyright GoFrame gf Author(https://goframe.org). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://github.com/gogf/gf.
package cmd
import (
"fmt"
"path/filepath"
"testing"
"github.com/gogf/gf/cmd/gf/v2/internal/cmd/gendao"
"github.com/gogf/gf/v2/database/gdb"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gcfg"
"github.com/gogf/gf/v2/os/gfile"
"github.com/gogf/gf/v2/test/gtest"
"github.com/gogf/gf/v2/text/gstr"
"github.com/gogf/gf/v2/util/guid"
"github.com/gogf/gf/v2/util/gutil"
)
func Test_Gen_Dao_Default(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
var (
err error
db = testDB
table = "table_user"
sqlContent = fmt.Sprintf(
gtest.DataContent(`gendao`, `user.tpl.sql`),
table,
)
)
dropTableWithDb(db, table)
array := gstr.SplitAndTrim(sqlContent, ";")
for _, v := range array {
if _, err = db.Exec(ctx, v); err != nil {
t.AssertNil(err)
}
}
defer dropTableWithDb(db, table)
var (
path = gfile.Temp(guid.S())
group = "test"
in = gendao.CGenDaoInput{
Path: path,
Link: link,
Tables: "",
TablesEx: "",
Group: group,
Prefix: "",
RemovePrefix: "",
JsonCase: "SnakeScreaming",
ImportPrefix: "",
DaoPath: "",
DoPath: "",
EntityPath: "",
TplDaoIndexPath: "",
TplDaoInternalPath: "",
TplDaoDoPath: "",
TplDaoEntityPath: "",
StdTime: false,
WithTime: false,
GJsonSupport: false,
OverwriteDao: false,
DescriptionTag: false,
NoJsonTag: false,
NoModelComment: false,
Clear: false,
TypeMapping: nil,
FieldMapping: nil,
}
)
err = gutil.FillStructWithDefault(&in)
t.AssertNil(err)
err = gfile.Mkdir(path)
t.AssertNil(err)
// for go mod import path auto retrieve.
err = gfile.Copy(
gtest.DataPath("gendao", "go.mod.txt"),
gfile.Join(path, "go.mod"),
)
t.AssertNil(err)
_, err = gendao.CGenDao{}.Dao(ctx, in)
t.AssertNil(err)
defer gfile.Remove(path)
// files
files, err := gfile.ScanDir(path, "*.go", true)
t.AssertNil(err)
t.Assert(files, []string{
filepath.FromSlash(path + "/dao/internal/table_user.go"),
filepath.FromSlash(path + "/dao/table_user.go"),
filepath.FromSlash(path + "/model/do/table_user.go"),
filepath.FromSlash(path + "/model/entity/table_user.go"),
})
// content
testPath := gtest.DataPath("gendao", "generated_user")
expectFiles := []string{
filepath.FromSlash(testPath + "/dao/internal/table_user.go"),
filepath.FromSlash(testPath + "/dao/table_user.go"),
filepath.FromSlash(testPath + "/model/do/table_user.go"),
filepath.FromSlash(testPath + "/model/entity/table_user.go"),
}
for i, _ := range files {
t.Assert(gfile.GetContents(files[i]), gfile.GetContents(expectFiles[i]))
}
})
}
func Test_Gen_Dao_TypeMapping(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
var (
err error
db = testDB
table = "table_user"
sqlContent = fmt.Sprintf(
gtest.DataContent(`gendao`, `user.tpl.sql`),
table,
)
)
defer dropTableWithDb(db, table)
array := gstr.SplitAndTrim(sqlContent, ";")
for _, v := range array {
if _, err = db.Exec(ctx, v); err != nil {
t.AssertNil(err)
}
}
defer dropTableWithDb(db, table)
var (
path = gfile.Temp(guid.S())
group = "test"
in = gendao.CGenDaoInput{
Path: path,
Link: link,
Tables: "",
TablesEx: "",
Group: group,
Prefix: "",
RemovePrefix: "",
JsonCase: "",
ImportPrefix: "",
DaoPath: "",
DoPath: "",
EntityPath: "",
TplDaoIndexPath: "",
TplDaoInternalPath: "",
TplDaoDoPath: "",
TplDaoEntityPath: "",
StdTime: false,
WithTime: false,
GJsonSupport: false,
OverwriteDao: false,
DescriptionTag: false,
NoJsonTag: false,
NoModelComment: false,
Clear: false,
TypeMapping: map[gendao.DBFieldTypeName]gendao.CustomAttributeType{
"int": {
Type: "int64",
Import: "",
},
"decimal": {
Type: "decimal.Decimal",
Import: "github.com/shopspring/decimal",
},
},
FieldMapping: nil,
}
)
err = gutil.FillStructWithDefault(&in)
t.AssertNil(err)
err = gfile.Mkdir(path)
t.AssertNil(err)
// for go mod import path auto retrieve.
err = gfile.Copy(
gtest.DataPath("gendao", "go.mod.txt"),
gfile.Join(path, "go.mod"),
)
t.AssertNil(err)
_, err = gendao.CGenDao{}.Dao(ctx, in)
t.AssertNil(err)
defer gfile.Remove(path)
// files
files, err := gfile.ScanDir(path, "*.go", true)
t.AssertNil(err)
t.Assert(files, []string{
filepath.FromSlash(path + "/dao/internal/table_user.go"),
filepath.FromSlash(path + "/dao/table_user.go"),
filepath.FromSlash(path + "/model/do/table_user.go"),
filepath.FromSlash(path + "/model/entity/table_user.go"),
})
// content
testPath := gtest.DataPath("gendao", "generated_user_type_mapping")
expectFiles := []string{
filepath.FromSlash(testPath + "/dao/internal/table_user.go"),
filepath.FromSlash(testPath + "/dao/table_user.go"),
filepath.FromSlash(testPath + "/model/do/table_user.go"),
filepath.FromSlash(testPath + "/model/entity/table_user.go"),
}
for i, _ := range files {
t.Assert(gfile.GetContents(files[i]), gfile.GetContents(expectFiles[i]))
}
})
}
func Test_Gen_Dao_FieldMapping(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
var (
err error
db = testDB
table = "table_user"
sqlContent = fmt.Sprintf(
gtest.DataContent(`gendao`, `user.tpl.sql`),
table,
)
)
defer dropTableWithDb(db, table)
array := gstr.SplitAndTrim(sqlContent, ";")
for _, v := range array {
if _, err = db.Exec(ctx, v); err != nil {
t.AssertNil(err)
}
}
defer dropTableWithDb(db, table)
var (
path = gfile.Temp(guid.S())
group = "test"
in = gendao.CGenDaoInput{
Path: path,
Link: link,
Tables: "",
TablesEx: "",
Group: group,
Prefix: "",
RemovePrefix: "",
JsonCase: "",
ImportPrefix: "",
DaoPath: "",
DoPath: "",
EntityPath: "",
TplDaoIndexPath: "",
TplDaoInternalPath: "",
TplDaoDoPath: "",
TplDaoEntityPath: "",
StdTime: false,
WithTime: false,
GJsonSupport: false,
OverwriteDao: false,
DescriptionTag: false,
NoJsonTag: false,
NoModelComment: false,
Clear: false,
TypeMapping: map[gendao.DBFieldTypeName]gendao.CustomAttributeType{
"int": {
Type: "int64",
Import: "",
},
},
FieldMapping: map[gendao.DBTableFieldName]gendao.CustomAttributeType{
"table_user.score": {
Type: "decimal.Decimal",
Import: "github.com/shopspring/decimal",
},
},
}
)
err = gutil.FillStructWithDefault(&in)
t.AssertNil(err)
err = gfile.Mkdir(path)
t.AssertNil(err)
// for go mod import path auto retrieve.
err = gfile.Copy(
gtest.DataPath("gendao", "go.mod.txt"),
gfile.Join(path, "go.mod"),
)
t.AssertNil(err)
_, err = gendao.CGenDao{}.Dao(ctx, in)
t.AssertNil(err)
defer gfile.Remove(path)
// files
files, err := gfile.ScanDir(path, "*.go", true)
t.AssertNil(err)
t.Assert(files, []string{
filepath.FromSlash(path + "/dao/internal/table_user.go"),
filepath.FromSlash(path + "/dao/table_user.go"),
filepath.FromSlash(path + "/model/do/table_user.go"),
filepath.FromSlash(path + "/model/entity/table_user.go"),
})
// content
testPath := gtest.DataPath("gendao", "generated_user_field_mapping")
expectFiles := []string{
filepath.FromSlash(testPath + "/dao/internal/table_user.go"),
filepath.FromSlash(testPath + "/dao/table_user.go"),
filepath.FromSlash(testPath + "/model/do/table_user.go"),
filepath.FromSlash(testPath + "/model/entity/table_user.go"),
}
for i, _ := range files {
t.Assert(gfile.GetContents(files[i]), gfile.GetContents(expectFiles[i]))
}
})
}
func execSqlFile(db gdb.DB, filePath string, args ...any) error {
sqlContent := fmt.Sprintf(
gfile.GetContents(filePath),
args...,
)
array := gstr.SplitAndTrim(sqlContent, ";")
for _, v := range array {
if _, err := db.Exec(ctx, v); err != nil {
return err
}
}
return nil
}
// https://github.com/gogf/gf/issues/2572
func Test_Gen_Dao_Issue2572(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
var (
err error
db = testDB
table1 = "user1"
table2 = "user2"
issueDirPath = gtest.DataPath(`issue`, `2572`)
)
t.AssertNil(execSqlFile(db, gtest.DataPath(`issue`, `2572`, `sql1.sql`)))
t.AssertNil(execSqlFile(db, gtest.DataPath(`issue`, `2572`, `sql2.sql`)))
defer dropTableWithDb(db, table1)
defer dropTableWithDb(db, table2)
var (
path = gfile.Temp(guid.S())
group = "test"
in = gendao.CGenDaoInput{
Path: path,
Link: "",
Tables: "",
TablesEx: "",
Group: group,
Prefix: "",
RemovePrefix: "",
JsonCase: "SnakeScreaming",
ImportPrefix: "",
DaoPath: "",
DoPath: "",
EntityPath: "",
TplDaoIndexPath: "",
TplDaoInternalPath: "",
TplDaoDoPath: "",
TplDaoEntityPath: "",
StdTime: false,
WithTime: false,
GJsonSupport: false,
OverwriteDao: false,
DescriptionTag: false,
NoJsonTag: false,
NoModelComment: false,
Clear: false,
TypeMapping: nil,
FieldMapping: nil,
}
)
err = gutil.FillStructWithDefault(&in)
t.AssertNil(err)
err = gfile.Copy(issueDirPath, path)
t.AssertNil(err)
defer gfile.Remove(path)
pwd := gfile.Pwd()
err = gfile.Chdir(path)
t.AssertNil(err)
defer gfile.Chdir(pwd)
_, err = gendao.CGenDao{}.Dao(ctx, in)
t.AssertNil(err)
generatedFiles, err := gfile.ScanDir(path, "*.go", true)
t.AssertNil(err)
t.Assert(len(generatedFiles), 8)
for i, generatedFile := range generatedFiles {
generatedFiles[i] = gstr.TrimLeftStr(generatedFile, path)
}
t.Assert(gstr.InArray(generatedFiles,
filepath.FromSlash("/dao/internal/user_1.go")), true)
t.Assert(gstr.InArray(generatedFiles,
filepath.FromSlash("/dao/internal/user_2.go")), true)
t.Assert(gstr.InArray(generatedFiles,
filepath.FromSlash("/dao/user_1.go")), true)
t.Assert(gstr.InArray(generatedFiles,
filepath.FromSlash("/dao/user_2.go")), true)
t.Assert(gstr.InArray(generatedFiles,
filepath.FromSlash("/model/do/user_1.go")), true)
t.Assert(gstr.InArray(generatedFiles,
filepath.FromSlash("/model/do/user_2.go")), true)
t.Assert(gstr.InArray(generatedFiles,
filepath.FromSlash("/model/entity/user_1.go")), true)
t.Assert(gstr.InArray(generatedFiles,
filepath.FromSlash("/model/entity/user_2.go")), true)
})
}
// https://github.com/gogf/gf/issues/2616
func Test_Gen_Dao_Issue2616(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
var (
err error
db = testDB
table1 = "user1"
table2 = "user2"
issueDirPath = gtest.DataPath(`issue`, `2616`)
)
t.AssertNil(execSqlFile(db, gtest.DataPath(`issue`, `2616`, `sql1.sql`)))
t.AssertNil(execSqlFile(db, gtest.DataPath(`issue`, `2616`, `sql2.sql`)))
defer dropTableWithDb(db, table1)
defer dropTableWithDb(db, table2)
var (
path = gfile.Temp(guid.S())
group = "test"
in = gendao.CGenDaoInput{
Path: path,
Link: "",
Tables: "",
TablesEx: "",
Group: group,
Prefix: "",
RemovePrefix: "",
JsonCase: "SnakeScreaming",
ImportPrefix: "",
DaoPath: "",
DoPath: "",
EntityPath: "",
TplDaoIndexPath: "",
TplDaoInternalPath: "",
TplDaoDoPath: "",
TplDaoEntityPath: "",
StdTime: false,
WithTime: false,
GJsonSupport: false,
OverwriteDao: false,
DescriptionTag: false,
NoJsonTag: false,
NoModelComment: false,
Clear: false,
TypeMapping: nil,
FieldMapping: nil,
}
)
err = gutil.FillStructWithDefault(&in)
t.AssertNil(err)
err = gfile.Copy(issueDirPath, path)
t.AssertNil(err)
defer gfile.Remove(path)
pwd := gfile.Pwd()
err = gfile.Chdir(path)
t.AssertNil(err)
defer gfile.Chdir(pwd)
_, err = gendao.CGenDao{}.Dao(ctx, in)
t.AssertNil(err)
generatedFiles, err := gfile.ScanDir(path, "*.go", true)
t.AssertNil(err)
t.Assert(len(generatedFiles), 8)
for i, generatedFile := range generatedFiles {
generatedFiles[i] = gstr.TrimLeftStr(generatedFile, path)
}
t.Assert(gstr.InArray(generatedFiles,
filepath.FromSlash("/dao/internal/user_1.go")), true)
t.Assert(gstr.InArray(generatedFiles,
filepath.FromSlash("/dao/internal/user_2.go")), true)
t.Assert(gstr.InArray(generatedFiles,
filepath.FromSlash("/dao/user_1.go")), true)
t.Assert(gstr.InArray(generatedFiles,
filepath.FromSlash("/dao/user_2.go")), true)
t.Assert(gstr.InArray(generatedFiles,
filepath.FromSlash("/model/do/user_1.go")), true)
t.Assert(gstr.InArray(generatedFiles,
filepath.FromSlash("/model/do/user_2.go")), true)
t.Assert(gstr.InArray(generatedFiles,
filepath.FromSlash("/model/entity/user_1.go")), true)
t.Assert(gstr.InArray(generatedFiles,
filepath.FromSlash("/model/entity/user_2.go")), true)
// Key string to check if overwrite the dao files.
// dao user1 is not be overwritten as configured in config.yaml.
// dao user2 is to be overwritten as configured in config.yaml.
var (
keyStr = `// I am not overwritten.`
daoUser1Content = gfile.GetContents(path + "/dao/user_1.go")
daoUser2Content = gfile.GetContents(path + "/dao/user_2.go")
)
t.Assert(gstr.Contains(daoUser1Content, keyStr), true)
t.Assert(gstr.Contains(daoUser2Content, keyStr), false)
})
}
// https://github.com/gogf/gf/issues/2746
func Test_Gen_Dao_Issue2746(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
var (
err error
mdb gdb.DB
link2746 = "mariadb:root:12345678@tcp(127.0.0.1:3307)/test?loc=Local&parseTime=true"
table = "issue2746"
sqlContent = fmt.Sprintf(
gtest.DataContent(`issue`, `2746`, `sql.sql`),
table,
)
)
mdb, err = gdb.New(gdb.ConfigNode{
Link: link2746,
})
t.AssertNil(err)
array := gstr.SplitAndTrim(sqlContent, ";")
for _, v := range array {
if _, err = mdb.Exec(ctx, v); err != nil {
t.AssertNil(err)
}
}
defer dropTableWithDb(mdb, table)
var (
path = gfile.Temp(guid.S())
group = "test"
in = gendao.CGenDaoInput{
Path: path,
Link: link2746,
Tables: "",
TablesEx: "",
Group: group,
Prefix: "",
RemovePrefix: "",
JsonCase: "SnakeScreaming",
ImportPrefix: "",
DaoPath: "",
DoPath: "",
EntityPath: "",
TplDaoIndexPath: "",
TplDaoInternalPath: "",
TplDaoDoPath: "",
TplDaoEntityPath: "",
StdTime: false,
WithTime: false,
GJsonSupport: true,
OverwriteDao: false,
DescriptionTag: false,
NoJsonTag: false,
NoModelComment: false,
Clear: false,
TypeMapping: nil,
FieldMapping: nil,
}
)
err = gutil.FillStructWithDefault(&in)
t.AssertNil(err)
err = gfile.Mkdir(path)
t.AssertNil(err)
_, err = gendao.CGenDao{}.Dao(ctx, in)
t.AssertNil(err)
defer gfile.Remove(path)
var (
file = filepath.FromSlash(path + "/model/entity/issue_2746.go")
expectContent = gtest.DataContent(`issue`, `2746`, `issue_2746.go`)
)
t.Assert(expectContent, gfile.GetContents(file))
})
}
// https://github.com/gogf/gf/issues/3459
func Test_Gen_Dao_Issue3459(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
var (
err error
db = testDB
table = "table_user"
sqlContent = fmt.Sprintf(
gtest.DataContent(`gendao`, `user.tpl.sql`),
table,
)
)
dropTableWithDb(db, table)
array := gstr.SplitAndTrim(sqlContent, ";")
for _, v := range array {
if _, err = db.Exec(ctx, v); err != nil {
t.AssertNil(err)
}
}
defer dropTableWithDb(db, table)
var (
confDir = gtest.DataPath("issue", "3459")
path = gfile.Temp(guid.S())
group = "test"
in = gendao.CGenDaoInput{
Path: path,
Link: link,
Tables: "",
TablesEx: "",
Group: group,
Prefix: "",
RemovePrefix: "",
JsonCase: "SnakeScreaming",
ImportPrefix: "",
DaoPath: "",
DoPath: "",
EntityPath: "",
TplDaoIndexPath: "",
TplDaoInternalPath: "",
TplDaoDoPath: "",
TplDaoEntityPath: "",
StdTime: false,
WithTime: false,
GJsonSupport: false,
OverwriteDao: false,
DescriptionTag: false,
NoJsonTag: false,
NoModelComment: false,
Clear: false,
TypeMapping: nil,
}
)
err = g.Cfg().GetAdapter().(*gcfg.AdapterFile).SetPath(confDir)
t.AssertNil(err)
err = gutil.FillStructWithDefault(&in)
t.AssertNil(err)
err = gfile.Mkdir(path)
t.AssertNil(err)
// for go mod import path auto retrieve.
err = gfile.Copy(
gtest.DataPath("gendao", "go.mod.txt"),
gfile.Join(path, "go.mod"),
)
t.AssertNil(err)
_, err = gendao.CGenDao{}.Dao(ctx, in)
t.AssertNil(err)
defer gfile.Remove(path)
// files
files, err := gfile.ScanDir(path, "*.go", true)
t.AssertNil(err)
t.Assert(files, []string{
filepath.FromSlash(path + "/dao/internal/table_user.go"),
filepath.FromSlash(path + "/dao/table_user.go"),
filepath.FromSlash(path + "/model/do/table_user.go"),
filepath.FromSlash(path + "/model/entity/table_user.go"),
})
// content
testPath := gtest.DataPath("gendao", "generated_user")
expectFiles := []string{
filepath.FromSlash(testPath + "/dao/internal/table_user.go"),
filepath.FromSlash(testPath + "/dao/table_user.go"),
filepath.FromSlash(testPath + "/model/do/table_user.go"),
filepath.FromSlash(testPath + "/model/entity/table_user.go"),
}
for i, _ := range files {
t.Assert(gfile.GetContents(files[i]), gfile.GetContents(expectFiles[i]))
}
})
}

View File

@ -0,0 +1,210 @@
// Copyright GoFrame gf Author(https://goframe.org). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://github.com/gogf/gf.
package cmd
import (
"fmt"
"path/filepath"
"testing"
"github.com/gogf/gf/cmd/gf/v2/internal/cmd/genpbentity"
"github.com/gogf/gf/v2/os/gfile"
"github.com/gogf/gf/v2/test/gtest"
"github.com/gogf/gf/v2/text/gstr"
"github.com/gogf/gf/v2/util/guid"
"github.com/gogf/gf/v2/util/gutil"
)
func Test_Gen_Pbentity_Default(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
var (
err error
db = testDB
table = "table_user"
sqlContent = fmt.Sprintf(
gtest.DataContent(`genpbentity`, `user.tpl.sql`),
table,
)
)
dropTableWithDb(db, table)
array := gstr.SplitAndTrim(sqlContent, ";")
for _, v := range array {
if _, err = db.Exec(ctx, v); err != nil {
t.AssertNil(err)
}
}
defer dropTableWithDb(db, table)
var (
path = gfile.Temp(guid.S())
in = genpbentity.CGenPbEntityInput{
Path: path,
Package: "unittest",
Link: link,
Tables: "",
Prefix: "",
RemovePrefix: "",
RemoveFieldPrefix: "",
NameCase: "",
JsonCase: "",
Option: "",
}
)
err = gutil.FillStructWithDefault(&in)
t.AssertNil(err)
err = gfile.Mkdir(path)
t.AssertNil(err)
defer gfile.Remove(path)
_, err = genpbentity.CGenPbEntity{}.PbEntity(ctx, in)
t.AssertNil(err)
// files
files, err := gfile.ScanDir(path, "*.proto", false)
t.AssertNil(err)
t.Assert(files, []string{
path + filepath.FromSlash("/table_user.proto"),
})
// contents
testPath := gtest.DataPath("genpbentity", "generated")
expectFiles := []string{
testPath + filepath.FromSlash("/table_user.proto"),
}
for i := range files {
t.Assert(gfile.GetContents(files[i]), gfile.GetContents(expectFiles[i]))
}
})
}
func Test_Gen_Pbentity_NameCase_SnakeScreaming(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
var (
err error
db = testDB
table = "table_user"
sqlContent = fmt.Sprintf(
gtest.DataContent(`genpbentity`, `user.tpl.sql`),
table,
)
)
dropTableWithDb(db, table)
array := gstr.SplitAndTrim(sqlContent, ";")
for _, v := range array {
if _, err = db.Exec(ctx, v); err != nil {
t.AssertNil(err)
}
}
defer dropTableWithDb(db, table)
var (
path = gfile.Temp(guid.S())
in = genpbentity.CGenPbEntityInput{
Path: path,
Package: "unittest",
Link: link,
Tables: "",
Prefix: "",
RemovePrefix: "",
RemoveFieldPrefix: "",
NameCase: "SnakeScreaming",
JsonCase: "",
Option: "",
}
)
err = gutil.FillStructWithDefault(&in)
t.AssertNil(err)
err = gfile.Mkdir(path)
t.AssertNil(err)
defer gfile.Remove(path)
_, err = genpbentity.CGenPbEntity{}.PbEntity(ctx, in)
t.AssertNil(err)
// files
files, err := gfile.ScanDir(path, "*.proto", false)
t.AssertNil(err)
t.Assert(files, []string{
path + filepath.FromSlash("/table_user.proto"),
})
// contents
testPath := gtest.DataPath("genpbentity", "generated")
expectFiles := []string{
testPath + filepath.FromSlash("/table_user_snake_screaming.proto"),
}
for i := range files {
t.Assert(gfile.GetContents(files[i]), gfile.GetContents(expectFiles[i]))
}
})
}
// https://github.com/gogf/gf/issues/3545
func Test_Issue_3545(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
var (
err error
db = testDB
table = "table_user"
sqlContent = fmt.Sprintf(
gtest.DataContent(`genpbentity`, `user.tpl.sql`),
table,
)
)
dropTableWithDb(db, table)
array := gstr.SplitAndTrim(sqlContent, ";")
for _, v := range array {
if _, err = db.Exec(ctx, v); err != nil {
t.AssertNil(err)
}
}
defer dropTableWithDb(db, table)
var (
path = gfile.Temp(guid.S())
in = genpbentity.CGenPbEntityInput{
Path: path,
Package: "",
Link: link,
Tables: "",
Prefix: "",
RemovePrefix: "",
RemoveFieldPrefix: "",
NameCase: "",
JsonCase: "",
Option: "",
}
)
err = gutil.FillStructWithDefault(&in)
t.AssertNil(err)
err = gfile.Mkdir(path)
t.AssertNil(err)
defer gfile.Remove(path)
_, err = genpbentity.CGenPbEntity{}.PbEntity(ctx, in)
t.AssertNil(err)
// files
files, err := gfile.ScanDir(path, "*.proto", false)
t.AssertNil(err)
t.Assert(files, []string{
path + filepath.FromSlash("/table_user.proto"),
})
// contents
testPath := gtest.DataPath("issue", "3545")
expectFiles := []string{
testPath + filepath.FromSlash("/table_user.proto"),
}
for i := range files {
t.Assert(gfile.GetContents(files[i]), gfile.GetContents(expectFiles[i]))
}
})
}

View File

@ -0,0 +1,71 @@
// Copyright GoFrame gf Author(https://goframe.org). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://github.com/gogf/gf.
package cmd
import (
"path/filepath"
"testing"
"github.com/gogf/gf/cmd/gf/v2/internal/cmd/genservice"
"github.com/gogf/gf/v2/os/gfile"
"github.com/gogf/gf/v2/test/gtest"
"github.com/gogf/gf/v2/util/guid"
"github.com/gogf/gf/v2/util/gutil"
)
func Test_Gen_Service_Default(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
var (
path = gfile.Temp(guid.S())
dstFolder = path + filepath.FromSlash("/service")
apiFolder = gtest.DataPath("genservice", "logic")
in = genservice.CGenServiceInput{
SrcFolder: apiFolder,
DstFolder: dstFolder,
DstFileNameCase: "Snake",
WatchFile: "",
StPattern: "",
Packages: nil,
ImportPrefix: "",
Clear: false,
}
)
err := gutil.FillStructWithDefault(&in)
t.AssertNil(err)
err = gfile.Mkdir(path)
t.AssertNil(err)
defer gfile.Remove(path)
_, err = genservice.CGenService{}.Service(ctx, in)
t.AssertNil(err)
// logic file
var (
genApi = apiFolder + filepath.FromSlash("/logic.go")
genApiExpect = apiFolder + filepath.FromSlash("/logic_expect.go")
)
defer gfile.Remove(genApi)
t.Assert(gfile.GetContents(genApi), gfile.GetContents(genApiExpect))
// files
files, err := gfile.ScanDir(dstFolder, "*.go", true)
t.AssertNil(err)
t.Assert(files, []string{
dstFolder + filepath.FromSlash("/article.go"),
})
// contents
testPath := gtest.DataPath("genservice", "service")
expectFiles := []string{
testPath + filepath.FromSlash("/article.go"),
}
for i := range files {
t.Assert(gfile.GetContents(files[i]), gfile.GetContents(expectFiles[i]))
}
})
}

View File

@ -9,15 +9,13 @@ package genctrl
import (
"context"
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
"github.com/gogf/gf/v2/container/gset"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gfile"
"github.com/gogf/gf/v2/os/gtime"
"github.com/gogf/gf/v2/text/gregex"
"github.com/gogf/gf/v2/util/gconv"
"github.com/gogf/gf/v2/util/gtag"
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
)
const (
@ -34,10 +32,10 @@ gf gen ctrl
CGenCtrlBriefSdkStdVersion = `use standard version prefix for generated sdk request path`
CGenCtrlBriefSdkNoV1 = `do not add version suffix for interface module name if version is v1`
CGenCtrlBriefClear = `auto delete generated and unimplemented controller go files if api definitions are missing`
CGenCtrlControllerMerge = `generate all controller files into one go file by name of api definition source go file`
)
const (
PatternApiDefinition = `type\s+(\w+)Req\s+struct\s+{`
PatternCtrlDefinition = `func\s+\(.+?\)\s+\w+\(.+?\*(\w+)\.(\w+)Req\)\s+\(.+?\*(\w+)\.(\w+)Res,\s+\w+\s+error\)\s+{`
)
@ -58,6 +56,7 @@ func init() {
`CGenCtrlBriefSdkStdVersion`: CGenCtrlBriefSdkStdVersion,
`CGenCtrlBriefSdkNoV1`: CGenCtrlBriefSdkNoV1,
`CGenCtrlBriefClear`: CGenCtrlBriefClear,
`CGenCtrlControllerMerge`: CGenCtrlControllerMerge,
})
}
@ -72,6 +71,7 @@ type (
SdkStdVersion bool `short:"v" name:"sdkStdVersion" brief:"{CGenCtrlBriefSdkStdVersion}" orphan:"true"`
SdkNoV1 bool `short:"n" name:"sdkNoV1" brief:"{CGenCtrlBriefSdkNoV1}" orphan:"true"`
Clear bool `short:"c" name:"clear" brief:"{CGenCtrlBriefClear}" orphan:"true"`
Merge bool `short:"m" name:"merge" brief:"{CGenCtrlControllerMerge}" orphan:"true"`
}
CGenCtrlOutput struct{}
)
@ -79,7 +79,7 @@ type (
func (c CGenCtrl) Ctrl(ctx context.Context, in CGenCtrlInput) (out *CGenCtrlOutput, err error) {
if in.WatchFile != "" {
err = c.generateByWatchFile(
in.WatchFile, in.SdkPath, in.SdkStdVersion, in.SdkNoV1, in.Clear,
in.WatchFile, in.SdkPath, in.SdkStdVersion, in.SdkNoV1, in.Clear, in.Merge,
)
mlog.Print(`done!`)
return
@ -104,7 +104,7 @@ func (c CGenCtrl) Ctrl(ctx context.Context, in CGenCtrlInput) (out *CGenCtrlOutp
)
err = c.generateByModule(
apiModuleFolderPath, dstModuleFolderPath, in.SdkPath,
in.SdkStdVersion, in.SdkNoV1, in.Clear,
in.SdkStdVersion, in.SdkNoV1, in.Clear, in.Merge,
)
if err != nil {
return nil, err
@ -115,7 +115,7 @@ func (c CGenCtrl) Ctrl(ctx context.Context, in CGenCtrlInput) (out *CGenCtrlOutp
return
}
func (c CGenCtrl) generateByWatchFile(watchFile, sdkPath string, sdkStdVersion, sdkNoV1, clear bool) (err error) {
func (c CGenCtrl) generateByWatchFile(watchFile, sdkPath string, sdkStdVersion, sdkNoV1, clear, merge bool) (err error) {
// File lock to avoid multiple processes.
var (
flockFilePath = gfile.Temp("gf.cli.gen.service.lock")
@ -143,7 +143,11 @@ func (c CGenCtrl) generateByWatchFile(watchFile, sdkPath string, sdkStdVersion,
}
// watch file should have api definitions.
if gfile.Exists(watchFile) {
if !gregex.IsMatchString(PatternApiDefinition, gfile.GetContents(watchFile)) {
structsInfo, err := c.getStructsNameInSrc(watchFile)
if err != nil {
return err
}
if len(structsInfo) == 0 {
return nil
}
}
@ -154,14 +158,14 @@ func (c CGenCtrl) generateByWatchFile(watchFile, sdkPath string, sdkStdVersion,
dstModuleFolderPath = gfile.Join(projectRootPath, "internal", "controller", module)
)
return c.generateByModule(
apiModuleFolderPath, dstModuleFolderPath, sdkPath, sdkStdVersion, sdkNoV1, clear,
apiModuleFolderPath, dstModuleFolderPath, sdkPath, sdkStdVersion, sdkNoV1, clear, merge,
)
}
// parseApiModule parses certain api and generate associated go files by certain module, not all api modules.
func (c CGenCtrl) generateByModule(
apiModuleFolderPath, dstModuleFolderPath, sdkPath string,
sdkStdVersion, sdkNoV1, clear bool,
sdkStdVersion, sdkNoV1, clear, merge bool,
) (err error) {
// parse src and dst folder go files.
apiItemsInSrc, err := c.getApiItemsInSrc(apiModuleFolderPath)
@ -194,7 +198,7 @@ func (c CGenCtrl) generateByModule(
toBeImplementedApiItems = append(toBeImplementedApiItems, item)
}
if len(toBeImplementedApiItems) > 0 {
err = newControllerGenerator().Generate(dstModuleFolderPath, toBeImplementedApiItems)
err = newControllerGenerator().Generate(dstModuleFolderPath, toBeImplementedApiItems, merge)
if err != nil {
return
}

View File

@ -10,6 +10,7 @@ import "github.com/gogf/gf/v2/text/gstr"
type apiItem struct {
Import string `eg:"demo.com/api/user/v1"`
FileName string `eg:"user"`
Module string `eg:"user"`
Version string `eg:"v1"`
MethodName string `eg:"GetList"`

View File

@ -7,6 +7,12 @@
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"
@ -14,10 +20,7 @@ import (
)
func (c CGenCtrl) getApiItemsInSrc(apiModuleFolderPath string) (items []apiItem, err error) {
var (
fileContent string
importPath string
)
var importPath string
// The second level folders: versions.
apiVersionFolderPaths, err := gfile.ScanDir(apiModuleFolderPath, "*", false)
if err != nil {
@ -37,17 +40,19 @@ func (c CGenCtrl) getApiItemsInSrc(apiModuleFolderPath string) (items []apiItem,
if gfile.IsDir(apiFileFolderPath) {
continue
}
fileContent = gfile.GetContents(apiFileFolderPath)
matches, err := gregex.MatchAllString(PatternApiDefinition, fileContent)
structsInfo, err := c.getStructsNameInSrc(apiFileFolderPath)
if err != nil {
return nil, err
}
for _, match := range matches {
for _, methodName := range structsInfo {
// remove end "Req"
methodName = gstr.TrimRightStr(methodName, "Req", 1)
item := apiItem{
Import: gstr.Trim(importPath, `"`),
FileName: gfile.Name(apiFileFolderPath),
Module: gfile.Basename(apiModuleFolderPath),
Version: gfile.Basename(apiVersionFolderPath),
MethodName: match[1],
MethodName: methodName,
}
items = append(items, item)
}
@ -64,26 +69,22 @@ func (c CGenCtrl) getApiItemsInDst(dstFolder string) (items []apiItem, err error
Path string
Alias string
}
var fileContent string
filePaths, err := gfile.ScanDir(dstFolder, "*.go", true)
if err != nil {
return nil, err
}
for _, filePath := range filePaths {
fileContent = gfile.GetContents(filePath)
match, err := gregex.MatchString(`import\s+\(([\s\S]+?)\)`, fileContent)
if err != nil {
return nil, err
}
if len(match) < 2 {
continue
}
var (
array []string
importItems []importItem
importLines = gstr.SplitAndTrim(match[1], "\n")
importLines []string
module = gfile.Basename(gfile.Dir(filePath))
)
importLines, err = c.getImportsInDst(filePath)
if err != nil {
return nil, err
}
// retrieve all imports.
for _, importLine := range importLines {
array = gstr.SplitAndTrim(importLine, " ")
@ -99,11 +100,15 @@ func (c CGenCtrl) getApiItemsInDst(dstFolder string) (items []apiItem, err error
}
}
// retrieve all api usages.
// retrieve it without using AST, but use regular expressions to retrieve.
// It's because the api definition is simple and regular.
// Use regular expressions to get better performance.
fileContent := gfile.GetContents(filePath)
matches, err := gregex.MatchAllString(PatternCtrlDefinition, fileContent)
if err != nil {
return nil, err
}
for _, match = range matches {
for _, match := range matches {
// try to find the import path of the api.
var (
importPath string
@ -134,3 +139,63 @@ 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

@ -8,6 +8,8 @@ package genctrl
import (
"fmt"
"path/filepath"
"strings"
"github.com/gogf/gf/cmd/gf/v2/internal/consts"
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
@ -23,7 +25,7 @@ func newControllerGenerator() *controllerGenerator {
return &controllerGenerator{}
}
func (c *controllerGenerator) Generate(dstModuleFolderPath string, apiModuleApiItems []apiItem) (err error) {
func (c *controllerGenerator) Generate(dstModuleFolderPath string, apiModuleApiItems []apiItem, merge bool) (err error) {
var (
doneApiItemSet = gset.NewStrSet()
)
@ -41,8 +43,16 @@ func (c *controllerGenerator) Generate(dstModuleFolderPath string, apiModuleApiI
); err != nil {
return
}
// use -merge
if merge {
err = c.doGenerateCtrlMergeItem(dstModuleFolderPath, subItems, doneApiItemSet)
continue
}
for _, subItem := range subItems {
if err = c.doGenerateCtrlItem(dstModuleFolderPath, subItem); err != nil {
err = c.doGenerateCtrlItem(dstModuleFolderPath, subItem)
if err != nil {
return
}
doneApiItemSet.Add(subItem.String())
@ -64,8 +74,8 @@ func (c *controllerGenerator) doGenerateCtrlNewByModuleAndVersion(
dstModuleFolderPath, module, version, importPath string,
) (err error) {
var (
moduleFilePath = gfile.Join(dstModuleFolderPath, module+".go")
moduleFilePathNew = gfile.Join(dstModuleFolderPath, module+"_new.go")
moduleFilePath = filepath.FromSlash(gfile.Join(dstModuleFolderPath, module+".go"))
moduleFilePathNew = filepath.FromSlash(gfile.Join(dstModuleFolderPath, module+"_new.go"))
ctrlName = fmt.Sprintf(`Controller%s`, gstr.UcFirst(version))
interfaceName = fmt.Sprintf(`%s.I%s%s`, module, gstr.CaseCamel(module), gstr.UcFirst(version))
newFuncName = fmt.Sprintf(`New%s`, gstr.UcFirst(version))
@ -107,7 +117,7 @@ func (c *controllerGenerator) doGenerateCtrlNewByModuleAndVersion(
"{NewFuncName}": newFuncName,
"{InterfaceName}": interfaceName,
})
err = gfile.PutContentsAppend(moduleFilePathNew, gstr.TrimLeft(content))
err = gfile.PutContentsAppend(moduleFilePathNew, content)
if err != nil {
return err
}
@ -119,20 +129,99 @@ func (c *controllerGenerator) doGenerateCtrlItem(dstModuleFolderPath string, ite
var (
methodNameSnake = gstr.CaseSnake(item.MethodName)
ctrlName = fmt.Sprintf(`Controller%s`, gstr.UcFirst(item.Version))
methodFilePath = gfile.Join(dstModuleFolderPath, fmt.Sprintf(
methodFilePath = filepath.FromSlash(gfile.Join(dstModuleFolderPath, fmt.Sprintf(
`%s_%s_%s.go`, item.Module, item.Version, methodNameSnake,
))
)))
)
content := gstr.ReplaceByMap(consts.TemplateGenCtrlControllerMethodFunc, g.MapStrStr{
"{Module}": item.Module,
"{ImportPath}": item.Import,
"{CtrlName}": ctrlName,
"{Version}": item.Version,
"{MethodName}": item.MethodName,
})
if err = gfile.PutContents(methodFilePath, gstr.TrimLeft(content)); err != nil {
return err
var content string
if gfile.Exists(methodFilePath) {
content = gstr.ReplaceByMap(consts.TemplateGenCtrlControllerMethodFuncMerge, g.MapStrStr{
"{Module}": item.Module,
"{CtrlName}": ctrlName,
"{Version}": item.Version,
"{MethodName}": item.MethodName,
})
if gstr.Contains(gfile.GetContents(methodFilePath), fmt.Sprintf(`func (c *%v) %v(`, ctrlName, item.MethodName)) {
return
}
if err = gfile.PutContentsAppend(methodFilePath, gstr.TrimLeft(content)); err != nil {
return err
}
} else {
content = gstr.ReplaceByMap(consts.TemplateGenCtrlControllerMethodFunc, g.MapStrStr{
"{Module}": item.Module,
"{ImportPath}": item.Import,
"{CtrlName}": ctrlName,
"{Version}": item.Version,
"{MethodName}": item.MethodName,
})
if err = gfile.PutContents(methodFilePath, gstr.TrimLeft(content)); err != nil {
return err
}
}
mlog.Printf(`generated: %s`, methodFilePath)
return
}
// use -merge
func (c *controllerGenerator) doGenerateCtrlMergeItem(dstModuleFolderPath string, apiItems []apiItem, doneApiSet *gset.StrSet) (err error) {
type controllerFileItem struct {
module string
version string
importPath string
// Each ctrlFileItem has multiple CTRLs
controllers strings.Builder
}
// It is possible that there are multiple files under one module
ctrlFileItemMap := make(map[string]*controllerFileItem)
for _, api := range apiItems {
ctrlFileItem, found := ctrlFileItemMap[api.FileName]
if !found {
ctrlFileItem = &controllerFileItem{
module: api.Module,
version: api.Version,
controllers: strings.Builder{},
importPath: api.Import,
}
ctrlFileItemMap[api.FileName] = ctrlFileItem
}
ctrl := gstr.TrimLeft(gstr.ReplaceByMap(consts.TemplateGenCtrlControllerMethodFuncMerge, g.MapStrStr{
"{Module}": api.Module,
"{CtrlName}": fmt.Sprintf(`Controller%s`, gstr.UcFirst(api.Version)),
"{Version}": api.Version,
"{MethodName}": api.MethodName,
}))
ctrlFileItem.controllers.WriteString(ctrl)
doneApiSet.Add(api.String())
}
for ctrlFileName, ctrlFileItem := range ctrlFileItemMap {
ctrlFilePath := gfile.Join(dstModuleFolderPath, fmt.Sprintf(
`%s_%s_%s.go`, ctrlFileItem.module, ctrlFileItem.version, ctrlFileName,
))
// This logic is only followed when a new ctrlFileItem is generated
// Most of the rest of the time, the following logic is followed
if !gfile.Exists(ctrlFilePath) {
ctrlFileHeader := gstr.TrimLeft(gstr.ReplaceByMap(consts.TemplateGenCtrlControllerHeader, g.MapStrStr{
"{Module}": ctrlFileItem.module,
"{ImportPath}": ctrlFileItem.importPath,
}))
err = gfile.PutContents(ctrlFilePath, ctrlFileHeader)
if err != nil {
return err
}
}
if err = gfile.PutContentsAppend(ctrlFilePath, ctrlFileItem.controllers.String()); err != nil {
return err
}
mlog.Printf(`generated: %s`, ctrlFilePath)
}
return
}

View File

@ -38,6 +38,7 @@ func (c *controllerClearer) doClear(dstModuleFolderPath string, item apiItem) (e
))
fileContent = gstr.Trim(gfile.GetContents(methodFilePath))
)
// retrieve it without using AST, because it's simple.
match, err := gregex.MatchString(`.+?Req.+?Res.+?{([\s\S]+?)}`, fileContent)
if err != nil {
return err

View File

@ -8,9 +8,11 @@ package genctrl
import (
"fmt"
"path/filepath"
"github.com/gogf/gf/cmd/gf/v2/internal/consts"
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
"github.com/gogf/gf/cmd/gf/v2/internal/utility/utils"
"github.com/gogf/gf/v2/container/gmap"
"github.com/gogf/gf/v2/container/gset"
"github.com/gogf/gf/v2/frame/g"
@ -38,13 +40,17 @@ func (c *apiInterfaceGenerator) Generate(apiModuleFolderPath string, apiModuleAp
func (c *apiInterfaceGenerator) doGenerate(apiModuleFolderPath string, module string, items []apiItem) (err error) {
var (
moduleFilePath = gfile.Join(apiModuleFolderPath, fmt.Sprintf(`%s.go`, module))
moduleFilePath = filepath.FromSlash(gfile.Join(apiModuleFolderPath, fmt.Sprintf(`%s.go`, module)))
importPathMap = gmap.NewListMap()
importPaths []string
)
// if there's already exist file that with the same but not auto generated go file,
// it uses another file name.
if !utils.IsFileDoNotEdit(moduleFilePath) {
moduleFilePath = filepath.FromSlash(gfile.Join(apiModuleFolderPath, fmt.Sprintf(`%s.if.go`, module)))
}
// all import paths.
importPathMap.Set("\t"+`"context"`, 1)
importPathMap.Set("\t"+``, 1)
importPathMap.Set("\t"+`"context"`+"\n", 1)
for _, item := range items {
importPathMap.Set(fmt.Sprintf("\t"+`"%s"`, item.Import), 1)
}
@ -85,7 +91,7 @@ func (c *apiInterfaceGenerator) doGenerate(apiModuleFolderPath string, module st
interfaceDefinition += "\n\n"
}
interfaceContent = gstr.TrimLeft(gstr.ReplaceByMap(interfaceContent, g.MapStrStr{
"{Interfaces}": interfaceDefinition,
"{Interfaces}": gstr.TrimRightStr(interfaceDefinition, "\n", 2),
}))
err = gfile.PutContents(moduleFilePath, interfaceContent)
mlog.Printf(`generated: %s`, moduleFilePath)

View File

@ -8,6 +8,7 @@ package genctrl
import (
"fmt"
"path/filepath"
"github.com/gogf/gf/cmd/gf/v2/internal/consts"
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
@ -54,7 +55,7 @@ func (c *apiSdkGenerator) Generate(apiModuleApiItems []apiItem, sdkFolderPath st
func (c *apiSdkGenerator) doGenerateSdkPkgFile(sdkFolderPath string) (err error) {
var (
pkgName = gfile.Basename(sdkFolderPath)
pkgFilePath = gfile.Join(sdkFolderPath, fmt.Sprintf(`%s.go`, pkgName))
pkgFilePath = filepath.FromSlash(gfile.Join(sdkFolderPath, fmt.Sprintf(`%s.go`, pkgName)))
fileContent string
)
if gfile.Exists(pkgFilePath) {
@ -79,7 +80,7 @@ func (c *apiSdkGenerator) doGenerateSdkIClient(
funcName = gstr.CaseCamel(module) + gstr.UcFirst(version)
interfaceName = fmt.Sprintf(`I%s`, funcName)
moduleImportPath = gstr.Replace(fmt.Sprintf(`"%s"`, gfile.Dir(versionImportPath)), "\\", "/", -1)
iClientFilePath = gfile.Join(sdkFolderPath, fmt.Sprintf(`%s.iclient.go`, pkgName))
iClientFilePath = filepath.FromSlash(gfile.Join(sdkFolderPath, fmt.Sprintf(`%s.iclient.go`, pkgName)))
interfaceFuncDefinition = fmt.Sprintf(
`%s() %s.%s`,
gstr.CaseCamel(module)+gstr.UcFirst(version), module, interfaceName,
@ -102,6 +103,7 @@ func (c *apiSdkGenerator) doGenerateSdkIClient(
// append the import path to current import paths.
if !gstr.Contains(fileContent, moduleImportPath) {
isDirty = true
// It is without using AST, because it is from a template.
fileContent, err = gregex.ReplaceString(
`(import \([\s\S]*?)\)`,
fmt.Sprintf("$1\t%s\n)", moduleImportPath),
@ -115,8 +117,9 @@ func (c *apiSdkGenerator) doGenerateSdkIClient(
// append the function definition to interface definition.
if !gstr.Contains(fileContent, interfaceFuncDefinition) {
isDirty = true
// It is without using AST, because it is from a template.
fileContent, err = gregex.ReplaceString(
`(type iClient interface {[\s\S]*?)}`,
`(type IClient interface {[\s\S]*?)}`,
fmt.Sprintf("$1\t%s\n}", interfaceFuncDefinition),
fileContent,
)
@ -145,9 +148,9 @@ func (c *apiSdkGenerator) doGenerateSdkImplementer(
moduleImportPath = gstr.Replace(gfile.Dir(versionImportPath), "\\", "/", -1)
versionPrefix = ""
implementerName = moduleNameCamel + gstr.UcFirst(version)
implementerFilePath = gfile.Join(sdkFolderPath, fmt.Sprintf(
implementerFilePath = filepath.FromSlash(gfile.Join(sdkFolderPath, fmt.Sprintf(
`%s_%s_%s.go`, pkgName, moduleNameSnake, version,
))
)))
)
if sdkNoV1 && version == "v1" {
implementerName = moduleNameCamel

View File

@ -9,9 +9,10 @@ package gendao
import (
"context"
"fmt"
"golang.org/x/mod/modfile"
"strings"
"golang.org/x/mod/modfile"
"github.com/gogf/gf/cmd/gf/v2/internal/utility/utils"
"github.com/gogf/gf/v2/container/garray"
"github.com/gogf/gf/v2/database/gdb"
@ -57,29 +58,35 @@ CONFIGURATION SUPPORT
import: github.com/shopspring/decimal
numeric:
type: string
fieldMapping:
table_name.field_name:
type: decimal.Decimal
import: github.com/shopspring/decimal
`
CGenDaoBriefPath = `directory path for generated files`
CGenDaoBriefLink = `database configuration, the same as the ORM configuration of GoFrame`
CGenDaoBriefTables = `generate models only for given tables, multiple table names separated with ','`
CGenDaoBriefTablesEx = `generate models excluding given tables, multiple table names separated with ','`
CGenDaoBriefPrefix = `add prefix for all table of specified link/database tables`
CGenDaoBriefRemovePrefix = `remove specified prefix of the table, multiple prefix separated with ','`
CGenDaoBriefStdTime = `use time.Time from stdlib instead of gtime.Time for generated time/date fields of tables`
CGenDaoBriefWithTime = `add created time for auto produced go files`
CGenDaoBriefGJsonSupport = `use gJsonSupport to use *gjson.Json instead of string for generated json fields of tables`
CGenDaoBriefImportPrefix = `custom import prefix for generated go files`
CGenDaoBriefDaoPath = `directory path for storing generated dao files under path`
CGenDaoBriefDoPath = `directory path for storing generated do files under path`
CGenDaoBriefEntityPath = `directory path for storing generated entity files under path`
CGenDaoBriefOverwriteDao = `overwrite all dao files both inside/outside internal folder`
CGenDaoBriefModelFile = `custom file name for storing generated model content`
CGenDaoBriefModelFileForDao = `custom file name generating model for DAO operations like Where/Data. It's empty in default`
CGenDaoBriefDescriptionTag = `add comment to description tag for each field`
CGenDaoBriefNoJsonTag = `no json tag will be added for each field`
CGenDaoBriefNoModelComment = `no model comment will be added for each field`
CGenDaoBriefClear = `delete all generated go files that do not exist in database`
CGenDaoBriefTypeMapping = `custom local type mapping for generated struct attributes relevant to fields of table`
CGenDaoBriefGroup = `
CGenDaoBriefPath = `directory path for generated files`
CGenDaoBriefLink = `database configuration, the same as the ORM configuration of GoFrame`
CGenDaoBriefTables = `generate models only for given tables, multiple table names separated with ','`
CGenDaoBriefTablesEx = `generate models excluding given tables, multiple table names separated with ','`
CGenDaoBriefPrefix = `add prefix for all table of specified link/database tables`
CGenDaoBriefRemovePrefix = `remove specified prefix of the table, multiple prefix separated with ','`
CGenDaoBriefRemoveFieldPrefix = `remove specified prefix of the field, multiple prefix separated with ','`
CGenDaoBriefStdTime = `use time.Time from stdlib instead of gtime.Time for generated time/date fields of tables`
CGenDaoBriefWithTime = `add created time for auto produced go files`
CGenDaoBriefGJsonSupport = `use gJsonSupport to use *gjson.Json instead of string for generated json fields of tables`
CGenDaoBriefImportPrefix = `custom import prefix for generated go files`
CGenDaoBriefDaoPath = `directory path for storing generated dao files under path`
CGenDaoBriefDoPath = `directory path for storing generated do files under path`
CGenDaoBriefEntityPath = `directory path for storing generated entity files under path`
CGenDaoBriefOverwriteDao = `overwrite all dao files both inside/outside internal folder`
CGenDaoBriefModelFile = `custom file name for storing generated model content`
CGenDaoBriefModelFileForDao = `custom file name generating model for DAO operations like Where/Data. It's empty in default`
CGenDaoBriefDescriptionTag = `add comment to description tag for each field`
CGenDaoBriefNoJsonTag = `no json tag will be added for each field`
CGenDaoBriefNoModelComment = `no model comment will be added for each field`
CGenDaoBriefClear = `delete all generated go files that do not exist in database`
CGenDaoBriefTypeMapping = `custom local type mapping for generated struct attributes relevant to fields of table`
CGenDaoBriefFieldMapping = `custom local type mapping for generated struct attributes relevant to specific fields of table`
CGenDaoBriefGroup = `
specifying the configuration group name of database for generated ORM instance,
it's not necessary and the default value is "default"
`
@ -115,7 +122,7 @@ generated json tag case for model struct, cases are as follows:
var (
createdAt = gtime.Now()
defaultTypeMapping = map[string]TypeMapping{
defaultTypeMapping = map[DBFieldTypeName]CustomAttributeType{
"decimal": {
Type: "float64",
},
@ -144,6 +151,7 @@ func init() {
`CGenDaoBriefTablesEx`: CGenDaoBriefTablesEx,
`CGenDaoBriefPrefix`: CGenDaoBriefPrefix,
`CGenDaoBriefRemovePrefix`: CGenDaoBriefRemovePrefix,
`CGenDaoBriefRemoveFieldPrefix`: CGenDaoBriefRemoveFieldPrefix,
`CGenDaoBriefStdTime`: CGenDaoBriefStdTime,
`CGenDaoBriefWithTime`: CGenDaoBriefWithTime,
`CGenDaoBriefDaoPath`: CGenDaoBriefDaoPath,
@ -159,6 +167,7 @@ func init() {
`CGenDaoBriefNoModelComment`: CGenDaoBriefNoModelComment,
`CGenDaoBriefClear`: CGenDaoBriefClear,
`CGenDaoBriefTypeMapping`: CGenDaoBriefTypeMapping,
`CGenDaoBriefFieldMapping`: CGenDaoBriefFieldMapping,
`CGenDaoBriefGroup`: CGenDaoBriefGroup,
`CGenDaoBriefJsonCase`: CGenDaoBriefJsonCase,
`CGenDaoBriefTplDaoIndexPath`: CGenDaoBriefTplDaoIndexPath,
@ -172,31 +181,35 @@ type (
CGenDao struct{}
CGenDaoInput struct {
g.Meta `name:"dao" config:"{CGenDaoConfig}" usage:"{CGenDaoUsage}" brief:"{CGenDaoBrief}" eg:"{CGenDaoEg}" ad:"{CGenDaoAd}"`
Path string `name:"path" short:"p" brief:"{CGenDaoBriefPath}" d:"internal"`
Link string `name:"link" short:"l" brief:"{CGenDaoBriefLink}"`
Tables string `name:"tables" short:"t" brief:"{CGenDaoBriefTables}"`
TablesEx string `name:"tablesEx" short:"x" brief:"{CGenDaoBriefTablesEx}"`
Group string `name:"group" short:"g" brief:"{CGenDaoBriefGroup}" d:"default"`
Prefix string `name:"prefix" short:"f" brief:"{CGenDaoBriefPrefix}"`
RemovePrefix string `name:"removePrefix" short:"r" brief:"{CGenDaoBriefRemovePrefix}"`
JsonCase string `name:"jsonCase" short:"j" brief:"{CGenDaoBriefJsonCase}" d:"CamelLower"`
ImportPrefix string `name:"importPrefix" short:"i" brief:"{CGenDaoBriefImportPrefix}"`
DaoPath string `name:"daoPath" short:"d" brief:"{CGenDaoBriefDaoPath}" d:"dao"`
DoPath string `name:"doPath" short:"o" brief:"{CGenDaoBriefDoPath}" d:"model/do"`
EntityPath string `name:"entityPath" short:"e" brief:"{CGenDaoBriefEntityPath}" d:"model/entity"`
TplDaoIndexPath string `name:"tplDaoIndexPath" short:"t1" brief:"{CGenDaoBriefTplDaoIndexPath}"`
TplDaoInternalPath string `name:"tplDaoInternalPath" short:"t2" brief:"{CGenDaoBriefTplDaoInternalPath}"`
TplDaoDoPath string `name:"tplDaoDoPath" short:"t3" brief:"{CGenDaoBriefTplDaoDoPathPath}"`
TplDaoEntityPath string `name:"tplDaoEntityPath" short:"t4" brief:"{CGenDaoBriefTplDaoEntityPath}"`
StdTime bool `name:"stdTime" short:"s" brief:"{CGenDaoBriefStdTime}" orphan:"true"`
WithTime bool `name:"withTime" short:"w" brief:"{CGenDaoBriefWithTime}" orphan:"true"`
GJsonSupport bool `name:"gJsonSupport" short:"n" brief:"{CGenDaoBriefGJsonSupport}" orphan:"true"`
OverwriteDao bool `name:"overwriteDao" short:"v" brief:"{CGenDaoBriefOverwriteDao}" orphan:"true"`
DescriptionTag bool `name:"descriptionTag" short:"c" brief:"{CGenDaoBriefDescriptionTag}" orphan:"true"`
NoJsonTag bool `name:"noJsonTag" short:"k" brief:"{CGenDaoBriefNoJsonTag}" orphan:"true"`
NoModelComment bool `name:"noModelComment" short:"m" brief:"{CGenDaoBriefNoModelComment}" orphan:"true"`
Clear bool `name:"clear" short:"a" brief:"{CGenDaoBriefClear}" orphan:"true"`
TypeMapping map[string]TypeMapping `name:"typeMapping" short:"y" brief:"{CGenDaoBriefTypeMapping}" orphan:"true"`
Path string `name:"path" short:"p" brief:"{CGenDaoBriefPath}" d:"internal"`
Link string `name:"link" short:"l" brief:"{CGenDaoBriefLink}"`
Tables string `name:"tables" short:"t" brief:"{CGenDaoBriefTables}"`
TablesEx string `name:"tablesEx" short:"x" brief:"{CGenDaoBriefTablesEx}"`
Group string `name:"group" short:"g" brief:"{CGenDaoBriefGroup}" d:"default"`
Prefix string `name:"prefix" short:"f" brief:"{CGenDaoBriefPrefix}"`
RemovePrefix string `name:"removePrefix" short:"r" brief:"{CGenDaoBriefRemovePrefix}"`
RemoveFieldPrefix string `name:"removeFieldPrefix" short:"rf" brief:"{CGenDaoBriefRemoveFieldPrefix}"`
JsonCase string `name:"jsonCase" short:"j" brief:"{CGenDaoBriefJsonCase}" d:"CamelLower"`
ImportPrefix string `name:"importPrefix" short:"i" brief:"{CGenDaoBriefImportPrefix}"`
DaoPath string `name:"daoPath" short:"d" brief:"{CGenDaoBriefDaoPath}" d:"dao"`
DoPath string `name:"doPath" short:"o" brief:"{CGenDaoBriefDoPath}" d:"model/do"`
EntityPath string `name:"entityPath" short:"e" brief:"{CGenDaoBriefEntityPath}" d:"model/entity"`
TplDaoIndexPath string `name:"tplDaoIndexPath" short:"t1" brief:"{CGenDaoBriefTplDaoIndexPath}"`
TplDaoInternalPath string `name:"tplDaoInternalPath" short:"t2" brief:"{CGenDaoBriefTplDaoInternalPath}"`
TplDaoDoPath string `name:"tplDaoDoPath" short:"t3" brief:"{CGenDaoBriefTplDaoDoPathPath}"`
TplDaoEntityPath string `name:"tplDaoEntityPath" short:"t4" brief:"{CGenDaoBriefTplDaoEntityPath}"`
StdTime bool `name:"stdTime" short:"s" brief:"{CGenDaoBriefStdTime}" orphan:"true"`
WithTime bool `name:"withTime" short:"w" brief:"{CGenDaoBriefWithTime}" orphan:"true"`
GJsonSupport bool `name:"gJsonSupport" short:"n" brief:"{CGenDaoBriefGJsonSupport}" orphan:"true"`
OverwriteDao bool `name:"overwriteDao" short:"v" brief:"{CGenDaoBriefOverwriteDao}" orphan:"true"`
DescriptionTag bool `name:"descriptionTag" short:"c" brief:"{CGenDaoBriefDescriptionTag}" orphan:"true"`
NoJsonTag bool `name:"noJsonTag" short:"k" brief:"{CGenDaoBriefNoJsonTag}" orphan:"true"`
NoModelComment bool `name:"noModelComment" short:"m" brief:"{CGenDaoBriefNoModelComment}" orphan:"true"`
Clear bool `name:"clear" short:"a" brief:"{CGenDaoBriefClear}" orphan:"true"`
TypeMapping map[DBFieldTypeName]CustomAttributeType `name:"typeMapping" short:"y" brief:"{CGenDaoBriefTypeMapping}" orphan:"true"`
FieldMapping map[DBTableFieldName]CustomAttributeType `name:"fieldMapping" short:"fm" brief:"{CGenDaoBriefFieldMapping}" orphan:"true"`
genItems *CGenDaoInternalGenItems
}
CGenDaoOutput struct{}
@ -206,15 +219,19 @@ type (
TableNames []string
NewTableNames []string
}
TypeMapping struct {
DBTableFieldName = string
DBFieldTypeName = string
CustomAttributeType struct {
Type string `brief:"custom attribute type name"`
Import string `brief:"custom import for this type"`
}
)
func (c CGenDao) Dao(ctx context.Context, in CGenDaoInput) (out *CGenDaoOutput, err error) {
if g.Cfg().Available(ctx) {
in.genItems = newCGenDaoInternalGenItems()
if in.Link != "" {
doGenDaoForArray(ctx, -1, in)
} else if g.Cfg().Available(ctx) {
v := g.Cfg().MustGet(ctx, CGenDaoConfig)
if v.IsSlice() {
for i := 0; i < len(v.Interfaces()); i++ {
@ -226,6 +243,7 @@ func (c CGenDao) Dao(ctx context.Context, in CGenDaoInput) (out *CGenDaoOutput,
} else {
doGenDaoForArray(ctx, -1, in)
}
doClear(in.genItems)
mlog.Print("done!")
return
}
@ -306,6 +324,8 @@ func doGenDaoForArray(ctx context.Context, index int, in CGenDaoInput) {
newTableNames[i] = newTableName
}
in.genItems.Scale()
// Dao: index and internal.
generateDao(ctx, CGenDaoInternalInput{
CGenDaoInput: in,
@ -327,6 +347,8 @@ func doGenDaoForArray(ctx context.Context, index int, in CGenDaoInput) {
TableNames: tableNames,
NewTableNames: newTableNames,
})
in.genItems.SetClear(in.Clear)
}
func getImportPartContent(ctx context.Context, source string, isDo bool, appendImports []string) string {
@ -348,7 +370,7 @@ func getImportPartContent(ctx context.Context, source string, isDo bool, appendI
}
// Check and update imports in go.mod
if appendImports != nil && len(appendImports) > 0 {
if len(appendImports) > 0 {
goModPath := utils.GetModPath()
if goModPath == "" {
mlog.Fatal("go.mod not found in current project")
@ -366,8 +388,9 @@ func getImportPartContent(ctx context.Context, source string, isDo bool, appendI
}
}
if !found {
err = gproc.ShellRun(ctx, `go get `+appendImport)
mlog.Fatalf(`%+v`, err)
if err = gproc.ShellRun(ctx, `go get `+appendImport); err != nil {
mlog.Fatalf(`%+v`, err)
}
}
packageImportsArray.Append(fmt.Sprintf(`"%s"`, appendImport))
}

View File

@ -7,22 +7,40 @@
package gendao
import (
"context"
"github.com/gogf/gf/v2/os/gfile"
"github.com/gogf/gf/v2/text/gstr"
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
"github.com/gogf/gf/cmd/gf/v2/internal/utility/utils"
)
func doClear(ctx context.Context, dirPath string, force bool) {
files, err := gfile.ScanDirFile(dirPath, "*.go", true)
if err != nil {
mlog.Fatal(err)
func doClear(items *CGenDaoInternalGenItems) {
var allGeneratedFilePaths = make([]string, 0)
for _, item := range items.Items {
allGeneratedFilePaths = append(allGeneratedFilePaths, item.GeneratedFilePaths...)
}
for _, file := range files {
if force || utils.IsFileDoNotEdit(file) {
if err = gfile.Remove(file); err != nil {
for i, v := range allGeneratedFilePaths {
allGeneratedFilePaths[i] = gfile.RealPath(v)
}
for _, item := range items.Items {
if !item.Clear {
continue
}
doClearItem(item, allGeneratedFilePaths)
}
}
func doClearItem(item CGenDaoInternalGenItem, allGeneratedFilePaths []string) {
var generatedFilePaths = make([]string, 0)
for _, dirPath := range item.StorageDirPaths {
filePaths, err := gfile.ScanDirFile(dirPath, "*.go", true)
if err != nil {
mlog.Fatal(err)
}
generatedFilePaths = append(generatedFilePaths, filePaths...)
}
for _, filePath := range generatedFilePaths {
if !gstr.InArray(allGeneratedFilePaths, filePath) {
if err := gfile.Remove(filePath); err != nil {
mlog.Print(err)
}
}

View File

@ -10,6 +10,7 @@ import (
"bytes"
"context"
"fmt"
"path/filepath"
"strings"
"github.com/olekukonko/tablewriter"
@ -29,9 +30,7 @@ func generateDao(ctx context.Context, in CGenDaoInternalInput) {
dirPathDao = gfile.Join(in.Path, in.DaoPath)
dirPathDaoInternal = gfile.Join(dirPathDao, "internal")
)
if in.Clear {
doClear(ctx, dirPathDao, true)
}
in.genItems.AppendDirPath(dirPathDao)
for i := 0; i < len(in.TableNames); i++ {
generateDaoSingle(ctx, generateDaoSingleInput{
CGenDaoInternalInput: in,
@ -106,7 +105,9 @@ type generateDaoIndexInput struct {
}
func generateDaoIndex(in generateDaoIndexInput) {
path := gfile.Join(in.DirPathDao, in.FileName+".go")
path := filepath.FromSlash(gfile.Join(in.DirPathDao, in.FileName+".go"))
// It should add path to result slice whenever it would generate the path file or not.
in.genItems.AppendGeneratedFilePath(path)
if in.OverwriteDao || !gfile.Exists(path) {
indexContent := gstr.ReplaceByMap(
getTemplateFromPathOrDefault(in.TplDaoIndexPath, consts.TemplateGenDaoIndexContent),
@ -136,7 +137,8 @@ type generateDaoInternalInput struct {
}
func generateDaoInternal(in generateDaoInternalInput) {
path := gfile.Join(in.DirPathDaoInternal, in.FileName+".go")
path := filepath.FromSlash(gfile.Join(in.DirPathDaoInternal, in.FileName+".go"))
removeFieldPrefixArray := gstr.SplitAndTrim(in.RemoveFieldPrefix, ",")
modelContent := gstr.ReplaceByMap(
getTemplateFromPathOrDefault(in.TplDaoInternalPath, consts.TemplateGenDaoInternalContent),
g.MapStrStr{
@ -145,10 +147,11 @@ func generateDaoInternal(in generateDaoInternalInput) {
tplVarGroupName: in.Group,
tplVarTableNameCamelCase: in.TableNameCamelCase,
tplVarTableNameCamelLowerCase: in.TableNameCamelLowerCase,
tplVarColumnDefine: gstr.Trim(generateColumnDefinitionForDao(in.FieldMap)),
tplVarColumnNames: gstr.Trim(generateColumnNamesForDao(in.FieldMap)),
tplVarColumnDefine: gstr.Trim(generateColumnDefinitionForDao(in.FieldMap, removeFieldPrefixArray)),
tplVarColumnNames: gstr.Trim(generateColumnNamesForDao(in.FieldMap, removeFieldPrefixArray)),
})
modelContent = replaceDefaultVar(in.CGenDaoInternalInput, modelContent)
in.genItems.AppendGeneratedFilePath(path)
if err := gfile.PutContents(path, strings.TrimSpace(modelContent)); err != nil {
mlog.Fatalf("writing content to '%s' failed: %v", path, err)
} else {
@ -159,16 +162,23 @@ func generateDaoInternal(in generateDaoInternalInput) {
// generateColumnNamesForDao generates and returns the column names assignment content of column struct
// for specified table.
func generateColumnNamesForDao(fieldMap map[string]*gdb.TableField) string {
func generateColumnNamesForDao(fieldMap map[string]*gdb.TableField, removeFieldPrefixArray []string) string {
var (
buffer = bytes.NewBuffer(nil)
array = make([][]string, len(fieldMap))
names = sortFieldKeyForDao(fieldMap)
)
for index, name := range names {
field := fieldMap[name]
newFiledName := field.Name
for _, v := range removeFieldPrefixArray {
newFiledName = gstr.TrimLeftStr(newFiledName, v, 1)
}
array[index] = []string{
" #" + gstr.CaseCamel(field.Name) + ":",
" #" + gstr.CaseCamel(newFiledName) + ":",
fmt.Sprintf(` #"%s",`, field.Name),
}
}
@ -188,12 +198,13 @@ func generateColumnNamesForDao(fieldMap map[string]*gdb.TableField) string {
}
// generateColumnDefinitionForDao generates and returns the column names definition for specified table.
func generateColumnDefinitionForDao(fieldMap map[string]*gdb.TableField) string {
func generateColumnDefinitionForDao(fieldMap map[string]*gdb.TableField, removeFieldPrefixArray []string) string {
var (
buffer = bytes.NewBuffer(nil)
array = make([][]string, len(fieldMap))
names = sortFieldKeyForDao(fieldMap)
)
for index, name := range names {
var (
field = fieldMap[name]
@ -202,8 +213,12 @@ func generateColumnDefinitionForDao(fieldMap map[string]*gdb.TableField) string
"\r", " ",
}))
)
newFiledName := field.Name
for _, v := range removeFieldPrefixArray {
newFiledName = gstr.TrimLeftStr(newFiledName, v, 1)
}
array[index] = []string{
" #" + gstr.CaseCamel(field.Name),
" #" + gstr.CaseCamel(newFiledName),
" # " + "string",
" #" + fmt.Sprintf(`// %s`, comment),
}

View File

@ -9,6 +9,7 @@ package gendao
import (
"context"
"fmt"
"path/filepath"
"strings"
"github.com/gogf/gf/v2/frame/g"
@ -22,10 +23,8 @@ import (
)
func generateDo(ctx context.Context, in CGenDaoInternalInput) {
var dirPathDo = gfile.Join(in.Path, in.DoPath)
if in.Clear {
doClear(ctx, dirPathDo, false)
}
var dirPathDo = filepath.FromSlash(gfile.Join(in.Path, in.DoPath))
in.genItems.AppendDirPath(dirPathDo)
in.NoJsonTag = true
in.DescriptionTag = false
in.NoModelComment = false
@ -65,6 +64,7 @@ func generateDo(ctx context.Context, in CGenDaoInternalInput) {
gstr.CaseCamel(newTableName),
structDefinition,
)
in.genItems.AppendGeneratedFilePath(doFilePath)
err = gfile.PutContents(doFilePath, strings.TrimSpace(modelContent))
if err != nil {
mlog.Fatalf(`writing content to "%s" failed: %v`, doFilePath, err)

View File

@ -8,6 +8,7 @@ package gendao
import (
"context"
"path/filepath"
"strings"
"github.com/gogf/gf/v2/frame/g"
@ -21,9 +22,7 @@ import (
func generateEntity(ctx context.Context, in CGenDaoInternalInput) {
var dirPathEntity = gfile.Join(in.Path, in.EntityPath)
if in.Clear {
doClear(ctx, dirPathEntity, false)
}
in.genItems.AppendDirPath(dirPathEntity)
// Model content.
for i, tableName := range in.TableNames {
fieldMap, err := in.DB.TableFields(ctx, tableName)
@ -33,7 +32,7 @@ func generateEntity(ctx context.Context, in CGenDaoInternalInput) {
var (
newTableName = in.NewTableNames[i]
entityFilePath = gfile.Join(dirPathEntity, gstr.CaseSnake(newTableName)+".go")
entityFilePath = filepath.FromSlash(gfile.Join(dirPathEntity, gstr.CaseSnake(newTableName)+".go"))
structDefinition, appendImports = generateStructDefinition(ctx, generateStructDefinitionInput{
CGenDaoInternalInput: in,
TableName: tableName,
@ -50,7 +49,7 @@ func generateEntity(ctx context.Context, in CGenDaoInternalInput) {
appendImports,
)
)
in.genItems.AppendGeneratedFilePath(entityFilePath)
err = gfile.PutContents(entityFilePath, strings.TrimSpace(entityContent))
if err != nil {
mlog.Fatalf("writing content to '%s' failed: %v", entityFilePath, err)

View File

@ -0,0 +1,53 @@
// Copyright GoFrame gf Author(https://goframe.org). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://github.com/gogf/gf.
package gendao
type (
CGenDaoInternalGenItems struct {
index int
Items []CGenDaoInternalGenItem
}
CGenDaoInternalGenItem struct {
Clear bool
StorageDirPaths []string
GeneratedFilePaths []string
}
)
func newCGenDaoInternalGenItems() *CGenDaoInternalGenItems {
return &CGenDaoInternalGenItems{
index: -1,
Items: make([]CGenDaoInternalGenItem, 0),
}
}
func (i *CGenDaoInternalGenItems) Scale() {
i.Items = append(i.Items, CGenDaoInternalGenItem{
StorageDirPaths: make([]string, 0),
GeneratedFilePaths: make([]string, 0),
Clear: false,
})
i.index++
}
func (i *CGenDaoInternalGenItems) SetClear(clear bool) {
i.Items[i.index].Clear = clear
}
func (i CGenDaoInternalGenItems) AppendDirPath(storageDirPath string) {
i.Items[i.index].StorageDirPaths = append(
i.Items[i.index].StorageDirPaths,
storageDirPath,
)
}
func (i CGenDaoInternalGenItems) AppendGeneratedFilePath(generatedFilePath string) {
i.Items[i.index].GeneratedFilePaths = append(
i.Items[i.index].GeneratedFilePaths,
generatedFilePath,
)
}

View File

@ -10,9 +10,10 @@ import (
"bytes"
"context"
"fmt"
"github.com/olekukonko/tablewriter"
"strings"
"github.com/olekukonko/tablewriter"
"github.com/gogf/gf/v2/database/gdb"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/text/gregex"
@ -67,9 +68,10 @@ func generateStructFieldDefinition(
ctx context.Context, field *gdb.TableField, in generateStructDefinitionInput,
) (attrLines []string, appendImport string) {
var (
err error
typeName string
jsonTag = getJsonTagFromCase(field.Name, in.JsonCase)
err error
localTypeName gdb.LocalType
localTypeNameStr string
jsonTag = gstr.CaseConvert(field.Name, gstr.CaseTypeMatch(in.JsonCase))
)
if in.TypeMapping != nil && len(in.TypeMapping) > 0 {
@ -84,38 +86,39 @@ func generateStructFieldDefinition(
}
if tryTypeName != "" {
if typeMapping, ok := in.TypeMapping[strings.ToLower(tryTypeName)]; ok {
typeName = typeMapping.Type
localTypeNameStr = typeMapping.Type
appendImport = typeMapping.Import
}
}
}
if typeName == "" {
typeName, err = in.DB.CheckLocalTypeForField(ctx, field.Type, nil)
if localTypeNameStr == "" {
localTypeName, err = in.DB.CheckLocalTypeForField(ctx, field.Type, nil)
if err != nil {
panic(err)
}
}
switch typeName {
case gdb.LocalTypeDate, gdb.LocalTypeDatetime:
if in.StdTime {
typeName = "time.Time"
} else {
typeName = "*gtime.Time"
}
localTypeNameStr = string(localTypeName)
switch localTypeName {
case gdb.LocalTypeDate, gdb.LocalTypeDatetime:
if in.StdTime {
localTypeNameStr = "time.Time"
} else {
localTypeNameStr = "*gtime.Time"
}
case gdb.LocalTypeInt64Bytes:
typeName = "int64"
case gdb.LocalTypeInt64Bytes:
localTypeNameStr = "int64"
case gdb.LocalTypeUint64Bytes:
typeName = "uint64"
case gdb.LocalTypeUint64Bytes:
localTypeNameStr = "uint64"
// Special type handle.
case gdb.LocalTypeJson, gdb.LocalTypeJsonb:
if in.GJsonSupport {
typeName = "*gjson.Json"
} else {
typeName = "string"
// Special type handle.
case gdb.LocalTypeJson, gdb.LocalTypeJsonb:
if in.GJsonSupport {
localTypeNameStr = "*gjson.Json"
} else {
localTypeNameStr = "string"
}
}
}
@ -123,13 +126,31 @@ func generateStructFieldDefinition(
tagKey = "`"
descriptionTag = gstr.Replace(formatComment(field.Comment), `"`, `\"`)
)
attrLines = []string{
" #" + gstr.CaseCamel(field.Name),
" #" + typeName,
removeFieldPrefixArray := gstr.SplitAndTrim(in.RemoveFieldPrefix, ",")
newFiledName := field.Name
for _, v := range removeFieldPrefixArray {
newFiledName = gstr.TrimLeftStr(newFiledName, v, 1)
}
attrLines = append(attrLines, " #"+fmt.Sprintf(tagKey+`json:"%s"`, jsonTag))
attrLines = append(attrLines, " #"+fmt.Sprintf(`description:"%s"`+tagKey, descriptionTag))
attrLines = append(attrLines, " #"+fmt.Sprintf(`// %s`, formatComment(field.Comment)))
if in.FieldMapping != nil && len(in.FieldMapping) > 0 {
if typeMapping, ok := in.FieldMapping[fmt.Sprintf("%s.%s", in.TableName, newFiledName)]; ok {
localTypeNameStr = typeMapping.Type
appendImport = typeMapping.Import
}
}
attrLines = []string{
" #" + gstr.CaseCamel(newFiledName),
" #" + localTypeNameStr,
}
attrLines = append(attrLines, fmt.Sprintf(` #%sjson:"%s"`, tagKey, jsonTag))
// orm tag
if !in.IsDo {
// entity
attrLines = append(attrLines, fmt.Sprintf(` #orm:"%s"`, field.Name))
}
attrLines = append(attrLines, fmt.Sprintf(` #description:"%s"%s`, descriptionTag, tagKey))
attrLines = append(attrLines, fmt.Sprintf(` #// %s`, formatComment(field.Comment)))
for k, v := range attrLines {
if in.NoJsonTag {
@ -156,30 +177,3 @@ func formatComment(comment string) string {
comment = gstr.Trim(comment)
return comment
}
// getJsonTagFromCase call gstr.Case* function to convert the s to specified case.
func getJsonTagFromCase(str, caseStr string) string {
switch gstr.ToLower(caseStr) {
case gstr.ToLower("Camel"):
return gstr.CaseCamel(str)
case gstr.ToLower("CamelLower"):
return gstr.CaseCamelLower(str)
case gstr.ToLower("Kebab"):
return gstr.CaseKebab(str)
case gstr.ToLower("KebabScreaming"):
return gstr.CaseKebabScreaming(str)
case gstr.ToLower("Snake"):
return gstr.CaseSnake(str)
case gstr.ToLower("SnakeFirstUpper"):
return gstr.CaseSnakeFirstUpper(str)
case gstr.ToLower("SnakeScreaming"):
return gstr.CaseSnakeScreaming(str)
}
return str
}

View File

@ -19,9 +19,10 @@ import (
const pkgLoadMode = 0xffffff
type EnumsParser struct {
enums []EnumItem
parsedPkg map[string]struct{}
prefixes []string
enums []EnumItem
parsedPkg map[string]struct{}
prefixes []string
standardPackages map[string]struct{}
}
type EnumItem struct {
@ -31,23 +32,12 @@ type EnumItem struct {
Type string // Pkg.ID + TypeName
}
var standardPackages = make(map[string]struct{})
func init() {
stdPackages, err := packages.Load(nil, "std")
if err != nil {
panic(err)
}
for _, p := range stdPackages {
standardPackages[p.ID] = struct{}{}
}
}
func NewEnumsParser(prefixes []string) *EnumsParser {
return &EnumsParser{
enums: make([]EnumItem, 0),
parsedPkg: make(map[string]struct{}),
prefixes: prefixes,
enums: make([]EnumItem, 0),
parsedPkg: make(map[string]struct{}),
prefixes: prefixes,
standardPackages: getStandardPackages(),
}
}
@ -59,7 +49,7 @@ func (p *EnumsParser) ParsePackages(pkgs []*packages.Package) {
func (p *EnumsParser) ParsePackage(pkg *packages.Package) {
// Ignore std packages.
if _, ok := standardPackages[pkg.ID]; ok {
if _, ok := p.standardPackages[pkg.ID]; ok {
return
}
// Ignore pared packages.
@ -144,3 +134,15 @@ func (p *EnumsParser) Export() string {
}
return gjson.MustEncodeString(typeEnumMap)
}
func getStandardPackages() map[string]struct{} {
standardPackages := make(map[string]struct{})
stdPackages, err := packages.Load(nil, "std")
if err != nil {
panic(err)
}
for _, p := range stdPackages {
standardPackages[p.ID] = struct{}{}
}
return standardPackages
}

View File

@ -10,8 +10,12 @@ import (
"bytes"
"context"
"fmt"
"path/filepath"
"strings"
"github.com/gogf/gf/cmd/gf/v2/internal/utility/utils"
"github.com/olekukonko/tablewriter"
"github.com/gogf/gf/cmd/gf/v2/internal/consts"
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
"github.com/gogf/gf/v2/database/gdb"
@ -23,22 +27,22 @@ import (
"github.com/gogf/gf/v2/text/gstr"
"github.com/gogf/gf/v2/util/gconv"
"github.com/gogf/gf/v2/util/gtag"
"github.com/olekukonko/tablewriter"
)
type (
CGenPbEntity struct{}
CGenPbEntityInput struct {
g.Meta `name:"pbentity" config:"{CGenPbEntityConfig}" brief:"{CGenPbEntityBrief}" eg:"{CGenPbEntityEg}" ad:"{CGenPbEntityAd}"`
Path string `name:"path" short:"p" brief:"{CGenPbEntityBriefPath}" d:"manifest/protobuf/pbentity"`
Package string `name:"package" short:"k" brief:"{CGenPbEntityBriefPackage}"`
Link string `name:"link" short:"l" brief:"{CGenPbEntityBriefLink}"`
Tables string `name:"tables" short:"t" brief:"{CGenPbEntityBriefTables}"`
Prefix string `name:"prefix" short:"f" brief:"{CGenPbEntityBriefPrefix}"`
RemovePrefix string `name:"removePrefix" short:"r" brief:"{CGenPbEntityBriefRemovePrefix}"`
NameCase string `name:"nameCase" short:"n" brief:"{CGenPbEntityBriefNameCase}" d:"Camel"`
JsonCase string `name:"jsonCase" short:"j" brief:"{CGenPbEntityBriefJsonCase}" d:"CamelLower"`
Option string `name:"option" short:"o" brief:"{CGenPbEntityBriefOption}"`
g.Meta `name:"pbentity" config:"{CGenPbEntityConfig}" brief:"{CGenPbEntityBrief}" eg:"{CGenPbEntityEg}" ad:"{CGenPbEntityAd}"`
Path string `name:"path" short:"p" brief:"{CGenPbEntityBriefPath}" d:"manifest/protobuf/pbentity"`
Package string `name:"package" short:"k" brief:"{CGenPbEntityBriefPackage}"`
Link string `name:"link" short:"l" brief:"{CGenPbEntityBriefLink}"`
Tables string `name:"tables" short:"t" brief:"{CGenPbEntityBriefTables}"`
Prefix string `name:"prefix" short:"f" brief:"{CGenPbEntityBriefPrefix}"`
RemovePrefix string `name:"removePrefix" short:"r" brief:"{CGenPbEntityBriefRemovePrefix}"`
RemoveFieldPrefix string `name:"removeFieldPrefix" short:"rf" brief:"{CGenPbEntityBriefRemoveFieldPrefix}"`
NameCase string `name:"nameCase" short:"n" brief:"{CGenPbEntityBriefNameCase}" d:"Camel"`
JsonCase string `name:"jsonCase" short:"j" brief:"{CGenPbEntityBriefJsonCase}" d:"none"`
Option string `name:"option" short:"o" brief:"{CGenPbEntityBriefOption}"`
}
CGenPbEntityOutput struct{}
@ -85,14 +89,15 @@ CONFIGURATION SUPPORT
option java_package = "protobuf/demos";
option php_namespace = "protobuf/demos";
`
CGenPbEntityBriefPath = `directory path for generated files storing`
CGenPbEntityBriefPackage = `package path for all entity proto files`
CGenPbEntityBriefLink = `database configuration, the same as the ORM configuration of GoFrame`
CGenPbEntityBriefTables = `generate models only for given tables, multiple table names separated with ','`
CGenPbEntityBriefPrefix = `add specified prefix for all entity names and entity proto files`
CGenPbEntityBriefRemovePrefix = `remove specified prefix of the table, multiple prefix separated with ','`
CGenPbEntityBriefOption = `extra protobuf options`
CGenPbEntityBriefGroup = `
CGenPbEntityBriefPath = `directory path for generated files storing`
CGenPbEntityBriefPackage = `package path for all entity proto files`
CGenPbEntityBriefLink = `database configuration, the same as the ORM configuration of GoFrame`
CGenPbEntityBriefTables = `generate models only for given tables, multiple table names separated with ','`
CGenPbEntityBriefPrefix = `add specified prefix for all entity names and entity proto files`
CGenPbEntityBriefRemovePrefix = `remove specified prefix of the table, multiple prefix separated with ','`
CGenPbEntityBriefRemoveFieldPrefix = `remove specified prefix of the field, multiple prefix separated with ','`
CGenPbEntityBriefOption = `extra protobuf options`
CGenPbEntityBriefGroup = `
specifying the configuration group name of database for generated ORM instance,
it's not necessary and the default value is "default"
`
@ -118,20 +123,21 @@ set it to "none" to ignore json tag generating.
func init() {
gtag.Sets(g.MapStrStr{
`CGenPbEntityConfig`: CGenPbEntityConfig,
`CGenPbEntityBrief`: CGenPbEntityBrief,
`CGenPbEntityEg`: CGenPbEntityEg,
`CGenPbEntityAd`: CGenPbEntityAd,
`CGenPbEntityBriefPath`: CGenPbEntityBriefPath,
`CGenPbEntityBriefPackage`: CGenPbEntityBriefPackage,
`CGenPbEntityBriefLink`: CGenPbEntityBriefLink,
`CGenPbEntityBriefTables`: CGenPbEntityBriefTables,
`CGenPbEntityBriefPrefix`: CGenPbEntityBriefPrefix,
`CGenPbEntityBriefRemovePrefix`: CGenPbEntityBriefRemovePrefix,
`CGenPbEntityBriefGroup`: CGenPbEntityBriefGroup,
`CGenPbEntityBriefNameCase`: CGenPbEntityBriefNameCase,
`CGenPbEntityBriefJsonCase`: CGenPbEntityBriefJsonCase,
`CGenPbEntityBriefOption`: CGenPbEntityBriefOption,
`CGenPbEntityConfig`: CGenPbEntityConfig,
`CGenPbEntityBrief`: CGenPbEntityBrief,
`CGenPbEntityEg`: CGenPbEntityEg,
`CGenPbEntityAd`: CGenPbEntityAd,
`CGenPbEntityBriefPath`: CGenPbEntityBriefPath,
`CGenPbEntityBriefPackage`: CGenPbEntityBriefPackage,
`CGenPbEntityBriefLink`: CGenPbEntityBriefLink,
`CGenPbEntityBriefTables`: CGenPbEntityBriefTables,
`CGenPbEntityBriefPrefix`: CGenPbEntityBriefPrefix,
`CGenPbEntityBriefRemovePrefix`: CGenPbEntityBriefRemovePrefix,
`CGenPbEntityBriefRemoveFieldPrefix`: CGenPbEntityBriefRemoveFieldPrefix,
`CGenPbEntityBriefGroup`: CGenPbEntityBriefGroup,
`CGenPbEntityBriefNameCase`: CGenPbEntityBriefNameCase,
`CGenPbEntityBriefJsonCase`: CGenPbEntityBriefJsonCase,
`CGenPbEntityBriefOption`: CGenPbEntityBriefOption,
})
}
@ -171,20 +177,8 @@ func doGenPbEntityForArray(ctx context.Context, index int, in CGenPbEntityInput)
}
if in.Package == "" {
mlog.Debug(`package parameter is empty, trying calculating the package path using go.mod`)
if !gfile.Exists("go.mod") {
mlog.Fatal("go.mod does not exist in current working directory")
}
var (
modName string
goModContent = gfile.GetContents("go.mod")
match, _ = gregex.MatchString(`^module\s+(.+)\s*`, goModContent)
)
if len(match) > 1 {
modName = gstr.Trim(match[1])
in.Package = modName + "/" + defaultPackageSuffix
} else {
mlog.Fatal("module name does not found in go.mod")
}
modName := utils.GetImportPath(gfile.Pwd())
in.Package = modName + "/" + defaultPackageSuffix
}
removePrefixArray := gstr.SplitAndTrim(in.RemovePrefix, ",")
// It uses user passed database configuration.
@ -196,7 +190,7 @@ func doGenPbEntityForArray(ctx context.Context, index int, in CGenPbEntityInput)
if len(match) == 3 {
gdb.AddConfigNode(tempGroup, gdb.ConfigNode{
Type: gstr.Trim(match[1]),
Link: gstr.Trim(match[2]),
Link: in.Link,
})
db, _ = gdb.Instance(tempGroup)
}
@ -245,7 +239,7 @@ func generatePbEntityContentFile(ctx context.Context, in CGenPbEntityInternalInp
tableNameSnakeCase = gstr.CaseSnake(newTableName)
entityMessageDefine = generateEntityMessageDefinition(tableNameCamelCase, fieldMap, in)
fileName = gstr.Trim(tableNameSnakeCase, "-_.")
path = gfile.Join(in.Path, fileName+".proto")
path = filepath.FromSlash(gfile.Join(in.Path, fileName+".proto"))
)
if gstr.Contains(entityMessageDefine, "google.protobuf.Timestamp") {
imports = `import "google/protobuf/timestamp.proto";`
@ -294,17 +288,17 @@ func generateEntityMessageDefinition(entityName string, fieldMap map[string]*gdb
// generateMessageFieldForPbEntity generates and returns the message definition for specified field.
func generateMessageFieldForPbEntity(index int, field *gdb.TableField, in CGenPbEntityInternalInput) []string {
var (
typeName string
comment string
jsonTagStr string
err error
ctx = gctx.GetInitCtx()
localTypeName gdb.LocalType
comment string
jsonTagStr string
err error
ctx = gctx.GetInitCtx()
)
typeName, err = in.DB.CheckLocalTypeForField(ctx, field.Type, nil)
localTypeName, err = in.DB.CheckLocalTypeForField(ctx, field.Type, nil)
if err != nil {
panic(err)
}
var typeMapping = map[string]string{
var typeMapping = map[gdb.LocalType]string{
gdb.LocalTypeString: "string",
gdb.LocalTypeDate: "google.protobuf.Timestamp",
gdb.LocalTypeDatetime: "google.protobuf.Timestamp",
@ -324,9 +318,9 @@ func generateMessageFieldForPbEntity(index int, field *gdb.TableField, in CGenPb
gdb.LocalTypeJson: "string",
gdb.LocalTypeJsonb: "string",
}
typeName = typeMapping[typeName]
if typeName == "" {
typeName = "string"
localTypeNameStr := typeMapping[localTypeName]
if localTypeNameStr == "" {
localTypeNameStr = "string"
}
comment = gstr.ReplaceByArray(field.Comment, g.SliceStr{
@ -337,6 +331,7 @@ func generateMessageFieldForPbEntity(index int, field *gdb.TableField, in CGenPb
comment = gstr.Replace(comment, `\n`, " ")
comment, _ = gregex.ReplaceString(`\s{2,}`, ` `, comment)
if jsonTagName := formatCase(field.Name, in.JsonCase); jsonTagName != "" {
jsonTagStr = fmt.Sprintf(`[json_name = "%s"]`, jsonTagName)
// beautiful indent.
if index < 10 {
// 3 spaces
@ -349,9 +344,16 @@ func generateMessageFieldForPbEntity(index int, field *gdb.TableField, in CGenPb
jsonTagStr = " " + jsonTagStr
}
}
removeFieldPrefixArray := gstr.SplitAndTrim(in.RemoveFieldPrefix, ",")
newFiledName := field.Name
for _, v := range removeFieldPrefixArray {
newFiledName = gstr.TrimLeftStr(newFiledName, v, 1)
}
return []string{
" #" + typeName,
" #" + formatCase(field.Name, in.NameCase),
" #" + localTypeNameStr,
" #" + formatCase(newFiledName, in.NameCase),
" #= " + gconv.String(index) + jsonTagStr + ";",
" #" + fmt.Sprintf(`// %s`, comment),
}
@ -366,32 +368,10 @@ func getTplPbEntityContent(tplEntityPath string) string {
// formatCase call gstr.Case* function to convert the s to specified case.
func formatCase(str, caseStr string) string {
switch gstr.ToLower(caseStr) {
case gstr.ToLower("Camel"):
return gstr.CaseCamel(str)
case gstr.ToLower("CamelLower"):
return gstr.CaseCamelLower(str)
case gstr.ToLower("Kebab"):
return gstr.CaseKebab(str)
case gstr.ToLower("KebabScreaming"):
return gstr.CaseKebabScreaming(str)
case gstr.ToLower("Snake"):
return gstr.CaseSnake(str)
case gstr.ToLower("SnakeFirstUpper"):
return gstr.CaseSnakeFirstUpper(str)
case gstr.ToLower("SnakeScreaming"):
return gstr.CaseSnakeScreaming(str)
case "none":
if caseStr == "none" {
return ""
}
return str
return gstr.CaseConvert(str, gstr.CaseTypeMatch(caseStr))
}
func sortFieldKeyForPbEntity(fieldMap map[string]*gdb.TableField) []string {

View File

@ -9,6 +9,7 @@ package genservice
import (
"context"
"fmt"
"path/filepath"
"github.com/gogf/gf/v2/container/garray"
"github.com/gogf/gf/v2/container/gmap"
@ -93,10 +94,10 @@ const (
)
func (c CGenService) Service(ctx context.Context, in CGenServiceInput) (out *CGenServiceOutput, err error) {
in.SrcFolder = gstr.TrimRight(in.SrcFolder, `\/`)
in.SrcFolder = gstr.Replace(in.SrcFolder, "\\", "/")
in.WatchFile = gstr.TrimRight(in.WatchFile, `\/`)
in.WatchFile = gstr.Replace(in.WatchFile, "\\", "/")
in.SrcFolder = filepath.ToSlash(in.SrcFolder)
in.SrcFolder = gstr.TrimRight(in.SrcFolder, `/`)
in.WatchFile = filepath.ToSlash(in.WatchFile)
in.WatchFile = gstr.TrimRight(in.WatchFile, `/`)
// Watch file handling.
if in.WatchFile != "" {
@ -173,7 +174,7 @@ func (c CGenService) Service(ctx context.Context, in CGenServiceInput) (out *CGe
// Parse single logic package folder.
var (
// StructName => FunctionDefinitions
srcPkgInterfaceMap = make(map[string]*garray.StrArray)
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
@ -194,7 +195,7 @@ func (c CGenService) Service(ctx context.Context, in CGenServiceInput) (out *CGe
return nil, err
}
// remove all comments.
fileContent, err = gregex.ReplaceString(`/[/|\*](.*)`, "", fileContent)
fileContent, err = gregex.ReplaceString(`(//.*)|((?s)/\*.*?\*/)`, "", fileContent)
if err != nil {
return nil, err
}

View File

@ -12,6 +12,7 @@ import (
"go/token"
"github.com/gogf/gf/v2/container/garray"
"github.com/gogf/gf/v2/container/gmap"
"github.com/gogf/gf/v2/text/gregex"
"github.com/gogf/gf/v2/text/gstr"
)
@ -99,10 +100,9 @@ func (c CGenService) calculateCodeCommented(in CGenServiceInput, fileContent str
}
func (c CGenService) calculateInterfaceFunctions(
in CGenServiceInput, fileContent string, srcPkgInterfaceMap map[string]*garray.StrArray,
in CGenServiceInput, fileContent string, srcPkgInterfaceMap *gmap.ListMap,
) (err error) {
var (
ok bool
matches [][]string
srcPkgInterfaceFuncArray *garray.StrArray
)
@ -142,9 +142,11 @@ func (c CGenService) calculateInterfaceFunctions(
continue
}
structName = gstr.CaseCamel(structMatch[1])
if srcPkgInterfaceFuncArray, ok = srcPkgInterfaceMap[structName]; !ok {
srcPkgInterfaceMap[structName] = garray.NewStrArray()
srcPkgInterfaceFuncArray = srcPkgInterfaceMap[structName]
if !srcPkgInterfaceMap.Contains(structName) {
srcPkgInterfaceFuncArray = garray.NewStrArray()
srcPkgInterfaceMap.Set(structName, srcPkgInterfaceFuncArray)
} else {
srcPkgInterfaceFuncArray = srcPkgInterfaceMap.Get(structName).(*garray.StrArray)
}
srcPkgInterfaceFuncArray.Append(functionHead)
}
@ -165,8 +167,8 @@ func (c CGenService) calculateInterfaceFunctions(
continue
}
structName = gstr.CaseCamel(structMatch[1])
if srcPkgInterfaceFuncArray, ok = srcPkgInterfaceMap[structName]; !ok {
srcPkgInterfaceMap[structName] = garray.NewStrArray()
if !srcPkgInterfaceMap.Contains(structName) {
srcPkgInterfaceMap.Set(structName, garray.NewStrArray())
}
}
return nil

View File

@ -10,6 +10,7 @@ import (
"fmt"
"github.com/gogf/gf/v2/container/garray"
"github.com/gogf/gf/v2/container/gmap"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gfile"
"github.com/gogf/gf/v2/text/gregex"
@ -23,7 +24,7 @@ import (
type generateServiceFilesInput struct {
CGenServiceInput
DstFilePath string // Absolute file path for generated service go file.
SrcStructFunctions map[string]*garray.StrArray
SrcStructFunctions *gmap.ListMap
SrcImportedPackages []string
SrcPackageName string
DstPackageName string
@ -46,7 +47,8 @@ func (c CGenService) generateServiceFile(in generateServiceFilesInput) (ok bool,
// Type definitions.
generatedContent += "type("
generatedContent += "\n"
for structName, funcArray := range in.SrcStructFunctions {
in.SrcStructFunctions.Iterator(func(key, value interface{}) bool {
structName, funcArray := key.(string), value.(*garray.StrArray)
allFuncArray.Append(funcArray.Slice()...)
// Add comments to a method.
for index, funcName := range funcArray.Slice() {
@ -60,7 +62,8 @@ func (c CGenService) generateServiceFile(in generateServiceFilesInput) (ok bool,
"{FuncDefinition}": funcArray.Join("\n\t"),
}))
generatedContent += "\n"
}
return true
})
generatedContent += ")"
generatedContent += "\n"
@ -70,17 +73,19 @@ func (c CGenService) generateServiceFile(in generateServiceFilesInput) (ok bool,
generatingInterfaceCheck string
)
// Variable definitions.
for structName := range in.SrcStructFunctions {
in.SrcStructFunctions.Iterator(func(key, value interface{}) bool {
structName := key.(string)
generatingInterfaceCheck = fmt.Sprintf(`[^\w\d]+%s.I%s[^\w\d]`, in.DstPackageName, structName)
if gregex.IsMatchString(generatingInterfaceCheck, generatedContent) {
continue
return true
}
variableContent += gstr.Trim(gstr.ReplaceByMap(consts.TemplateGenServiceContentVariable, g.MapStrStr{
"{StructName}": structName,
"{InterfaceName}": "I" + structName,
}))
variableContent += "\n"
}
return true
})
if variableContent != "" {
generatedContent += "var("
generatedContent += "\n"
@ -89,17 +94,19 @@ func (c CGenService) generateServiceFile(in generateServiceFilesInput) (ok bool,
generatedContent += "\n"
}
// Variable register function definitions.
for structName := range in.SrcStructFunctions {
in.SrcStructFunctions.Iterator(func(key, value interface{}) bool {
structName := key.(string)
generatingInterfaceCheck = fmt.Sprintf(`[^\w\d]+%s.I%s[^\w\d]`, in.DstPackageName, structName)
if gregex.IsMatchString(generatingInterfaceCheck, generatedContent) {
continue
return true
}
generatedContent += gstr.Trim(gstr.ReplaceByMap(consts.TemplateGenServiceContentRegister, g.MapStrStr{
"{StructName}": structName,
"{InterfaceName}": "I" + structName,
}))
generatedContent += "\n\n"
}
return true
})
// Replace empty braces that have new line.
generatedContent, _ = gregex.ReplaceString(`{[\s\t]+}`, `{}`, generatedContent)
@ -137,7 +144,7 @@ func (c CGenService) isToGenerateServiceGoFile(dstPackageName, filePath string,
return true
}
// remove all comments.
fileContent, err = gregex.ReplaceString(`/[/|\*](.*)`, "", fileContent)
fileContent, err = gregex.ReplaceString(`(//.*)|((?s)/\*.*?\*/)`, "", fileContent)
if err != nil {
panic(err)
return false
@ -194,28 +201,9 @@ func (c CGenService) generateInitializationFile(in CGenServiceInput, importSrcPa
}
// getDstFileNameCase call gstr.Case* function to convert the s to specified case.
func (c CGenService) getDstFileNameCase(str, caseStr string) string {
switch gstr.ToLower(caseStr) {
case gstr.ToLower("Lower"):
return gstr.ToLower(str)
case gstr.ToLower("Camel"):
return gstr.CaseCamel(str)
case gstr.ToLower("CamelLower"):
return gstr.CaseCamelLower(str)
case gstr.ToLower("Kebab"):
return gstr.CaseKebab(str)
case gstr.ToLower("KebabScreaming"):
return gstr.CaseKebabScreaming(str)
case gstr.ToLower("SnakeFirstUpper"):
return gstr.CaseSnakeFirstUpper(str)
case gstr.ToLower("SnakeScreaming"):
return gstr.CaseSnakeScreaming(str)
func (c CGenService) getDstFileNameCase(str, caseStr string) (newStr string) {
if newStr := gstr.CaseConvert(str, gstr.CaseTypeMatch(caseStr)); newStr != str {
return newStr
}
return gstr.CaseSnake(str)
}

View File

@ -0,0 +1,5 @@
package main
func main() {
}

View File

@ -0,0 +1,5 @@
package main
func main() {
}

View File

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

View File

@ -0,0 +1,26 @@
github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8=
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/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY=
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/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=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=

View File

@ -0,0 +1,13 @@
package main
import (
"fmt"
"github.com/gogf/gf/v2/os/gbuild"
)
func main() {
for k, v := range gbuild.Data() {
fmt.Printf("%s: %v\n", k, v)
}
}

View File

@ -27,4 +27,4 @@ func Test_Router_Hook_Multi(t *testing.T) {
r.Response.Write("2")
},
})
}
}

View File

@ -0,0 +1,17 @@
// =================================================================================
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
// =================================================================================
package dict
import (
"context"
"github.com/gogf/gf/cmd/gf/v2/internal/cmd/testdata/genctrl-merge/add_new_ctrl/api/dict/v1"
)
type IDictV1 interface {
DictTypeAddPage(ctx context.Context, req *v1.DictTypeAddPageReq) (res *v1.DictTypeAddPageRes, err error)
DictTypeAdd(ctx context.Context, req *v1.DictTypeAddReq) (res *v1.DictTypeAddRes, err error)
}

View File

@ -0,0 +1,15 @@
// =================================================================================
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
// =================================================================================
package dict
import (
"context"
"github.com/gogf/gf/cmd/gf/v2/internal/cmd/testdata/genctrl-merge/add_new_ctrl/api/dict/v1"
)
type IDictV1 interface {
DictTypeAddPage(ctx context.Context, req *v1.DictTypeAddPageReq) (res *v1.DictTypeAddPageRes, err error)
}

View File

@ -0,0 +1,17 @@
// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://github.com/gogf/gf.
package v1
import "github.com/gogf/gf/v2/frame/g"
type DictTypeAddPageReq struct {
g.Meta `path:"/dict/type/add" tags:"字典管理" method:"get" summary:"字典类型添加页面"`
}
type DictTypeAddPageRes struct {
g.Meta `mime:"text/html" type:"string" example:"<html/>"`
}

View File

@ -0,0 +1,5 @@
// =================================================================================
// This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish.
// =================================================================================
package dict

View File

@ -0,0 +1,15 @@
// =================================================================================
// This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish.
// =================================================================================
package dict
import (
"github.com/gogf/gf/cmd/gf/v2/internal/cmd/testdata/genctrl-merge/add_new_ctrl/api/dict"
)
type ControllerV1 struct{}
func NewV1() dict.IDictV1 {
return &ControllerV1{}
}

View File

@ -0,0 +1,14 @@
package dict
import (
"context"
"github.com/gogf/gf/v2/errors/gcode"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/cmd/gf/v2/internal/cmd/testdata/genctrl-merge/add_new_ctrl/api/dict/v1"
)
func (c *ControllerV1) DictTypeAddPage(ctx context.Context, req *v1.DictTypeAddPageReq) (res *v1.DictTypeAddPageRes, err error) {
return nil, gerror.NewCode(gcode.CodeNotImplemented)
}

View File

@ -0,0 +1,17 @@
package dict
import (
"context"
"github.com/gogf/gf/v2/errors/gcode"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/cmd/gf/v2/internal/cmd/testdata/genctrl-merge/add_new_ctrl/api/dict/v1"
)
func (c *ControllerV1) DictTypeAddPage(ctx context.Context, req *v1.DictTypeAddPageReq) (res *v1.DictTypeAddPageRes, err error) {
return nil, gerror.NewCode(gcode.CodeNotImplemented)
}
func (c *ControllerV1) DictTypeAdd(ctx context.Context, req *v1.DictTypeAddReq) (res *v1.DictTypeAddRes, err error) {
return nil, gerror.NewCode(gcode.CodeNotImplemented)
}

View File

@ -0,0 +1,17 @@
// =================================================================================
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
// =================================================================================
package dict
import (
"context"
"github.com/gogf/gf/cmd/gf/v2/internal/cmd/testdata/genctrl-merge/add_new_ctrl/api/dict/v1"
)
type IDictV1 interface {
DictTypeAddPage(ctx context.Context, req *v1.DictTypeAddPageReq) (res *v1.DictTypeAddPageRes, err error)
DictTypeAdd(ctx context.Context, req *v1.DictTypeAddReq) (res *v1.DictTypeAddRes, err error)
}

View File

@ -0,0 +1,15 @@
// =================================================================================
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
// =================================================================================
package dict
import (
"context"
"github.com/gogf/gf/cmd/gf/v2/internal/cmd/testdata/genctrl-merge/add_new_file/api/dict/v1"
)
type IDictV1 interface {
DictTypeAddPage(ctx context.Context, req *v1.DictTypeAddPageReq) (res *v1.DictTypeAddPageRes, err error)
}

View File

@ -0,0 +1,17 @@
// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://github.com/gogf/gf.
package v1
import "github.com/gogf/gf/v2/frame/g"
type DictTypeAddPageReq struct {
g.Meta `path:"/dict/type/add" tags:"字典管理" method:"get" summary:"字典类型添加页面"`
}
type DictTypeAddPageRes struct {
g.Meta `mime:"text/html" type:"string" example:"<html/>"`
}

View File

@ -0,0 +1,5 @@
// =================================================================================
// This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish.
// =================================================================================
package dict

View File

@ -0,0 +1,15 @@
// =================================================================================
// This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish.
// =================================================================================
package dict
import (
"github.com/gogf/gf/cmd/gf/v2/internal/cmd/testdata/genctrl-merge/add_new_file/api/dict"
)
type ControllerV1 struct{}
func NewV1() dict.IDictV1 {
return &ControllerV1{}
}

View File

@ -0,0 +1,14 @@
package dict
import (
"context"
"github.com/gogf/gf/v2/errors/gcode"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/cmd/gf/v2/internal/cmd/testdata/genctrl-merge/add_new_file/api/dict/v1"
)
func (c *ControllerV1) DictTypeAddPage(ctx context.Context, req *v1.DictTypeAddPageReq) (res *v1.DictTypeAddPageRes, err error) {
return nil, gerror.NewCode(gcode.CodeNotImplemented)
}

View File

@ -0,0 +1,14 @@
package dict
import (
"context"
"github.com/gogf/gf/v2/errors/gcode"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/cmd/gf/v2/internal/cmd/testdata/genctrl-merge/add_new_file/api/dict/v1"
)
func (c *ControllerV1) DictTypeAdd(ctx context.Context, req *v1.DictTypeAddReq) (res *v1.DictTypeAddRes, err error) {
return nil, gerror.NewCode(gcode.CodeNotImplemented)
}

View File

@ -0,0 +1,24 @@
// =================================================================================
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
// =================================================================================
package article
import (
"context"
"github.com/gogf/gf/cmd/gf/v2/internal/cmd/testdata/genctrl/api/article/v1"
"github.com/gogf/gf/cmd/gf/v2/internal/cmd/testdata/genctrl/api/article/v2"
)
type IArticleV1 interface {
Create(ctx context.Context, req *v1.CreateReq) (res *v1.CreateRes, err error)
Update(ctx context.Context, req *v1.UpdateReq) (res *v1.UpdateRes, err error)
GetList(ctx context.Context, req *v1.GetListReq) (res *v1.GetListRes, err error)
GetOne(ctx context.Context, req *v1.GetOneReq) (res *v1.GetOneRes, err error)
}
type IArticleV2 interface {
Create(ctx context.Context, req *v2.CreateReq) (res *v2.CreateRes, err error)
Update(ctx context.Context, req *v2.UpdateReq) (res *v2.UpdateRes, err error)
}

View File

@ -0,0 +1,27 @@
// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://github.com/gogf/gf.
package v1
import "github.com/gogf/gf/v2/frame/g"
type (
CreateReq struct {
g.Meta `path:"/article/create" method:"post" tags:"ArticleService"`
Title string `v:"required"`
}
CreateRes struct{}
)
type (
UpdateReq struct {
g.Meta `path:"/article/update" method:"post" tags:"ArticleService"`
Title string `v:"required"`
}
UpdateRes struct{}
)

View File

@ -0,0 +1,25 @@
// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://github.com/gogf/gf.
package v1
import "github.com/gogf/gf/v2/frame/g"
type GetListReq struct {
g.Meta `path:"/article/list" method:"get" tags:"ArticleService"`
}
type GetListRes struct {
list []struct{}
}
type GetOneReq struct {
g.Meta `path:"/article/one" method:"get" tags:"ArticleService"`
}
type GetOneRes struct {
one struct{}
}

View File

@ -0,0 +1,23 @@
// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://github.com/gogf/gf.
package v2
import "github.com/gogf/gf/v2/frame/g"
type CreateReq struct {
g.Meta `path:"/article/create" method:"post" tags:"ArticleService"`
Title string `v:"required"`
}
type CreateRes struct{}
type UpdateReq struct {
g.Meta `path:"/article/update" method:"post" tags:"ArticleService"`
Title string `v:"required"`
}
type UpdateRes struct{}

View File

@ -0,0 +1,5 @@
// =================================================================================
// This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish.
// =================================================================================
package article

View File

@ -0,0 +1,21 @@
// =================================================================================
// This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish.
// =================================================================================
package article
import (
"github.com/gogf/gf/cmd/gf/v2/internal/cmd/testdata/genctrl/api/article"
)
type ControllerV1 struct{}
func NewV1() article.IArticleV1 {
return &ControllerV1{}
}
type ControllerV2 struct{}
func NewV2() article.IArticleV2 {
return &ControllerV2{}
}

View File

@ -0,0 +1,14 @@
package article
import (
"context"
"github.com/gogf/gf/v2/errors/gcode"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/cmd/gf/v2/internal/cmd/testdata/genctrl/api/article/v1"
)
func (c *ControllerV1) Create(ctx context.Context, req *v1.CreateReq) (res *v1.CreateRes, err error) {
return nil, gerror.NewCode(gcode.CodeNotImplemented)
}

View File

@ -0,0 +1,14 @@
package article
import (
"context"
"github.com/gogf/gf/v2/errors/gcode"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/cmd/gf/v2/internal/cmd/testdata/genctrl/api/article/v1"
)
func (c *ControllerV1) GetList(ctx context.Context, req *v1.GetListReq) (res *v1.GetListRes, err error) {
return nil, gerror.NewCode(gcode.CodeNotImplemented)
}

View File

@ -0,0 +1,14 @@
package article
import (
"context"
"github.com/gogf/gf/v2/errors/gcode"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/cmd/gf/v2/internal/cmd/testdata/genctrl/api/article/v1"
)
func (c *ControllerV1) GetOne(ctx context.Context, req *v1.GetOneReq) (res *v1.GetOneRes, err error) {
return nil, gerror.NewCode(gcode.CodeNotImplemented)
}

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