Compare commits

..

4 Commits

Author SHA1 Message Date
d2c1d773db Merge branch 'master' of https://github.com/gogf/gf 2022-07-12 14:08:56 +08:00
d957102769 v2.1.2 2022-07-12 12:01:00 +08:00
3f40000000 Merge branch 'master' of https://github.com/gogf/gf 2022-07-12 12:00:43 +08:00
d7229c6843 go mod tidy 2022-07-07 21:45:28 +08:00
710 changed files with 8889 additions and 32555 deletions

View File

@ -1,42 +0,0 @@
version: '2'
services:
apollo-quick-start:
image: "loads/apollo-quick-start:latest"
container_name: apollo-quick-start
depends_on:
- apollo-db
ports:
- "8080:8080"
- "8070:8070"
- "8060:8060"
links:
- apollo-db
#environment:
#JAVA_OPTS: '-Xms100m -Xmx1000m -Xmn100m -Xss256k -XX:MetaspaceSize=10m -XX:MaxMetaspaceSize=250m'
#APOLLO_CONFIG_DB_USERNAME: 'root'
#APOLLO_CONFIG_DB_PASSWORD: 'apollo'
#APOLLO_PORTAL_DB_USERNAME: 'root'
#APOLLO_PORTAL_DB_PASSWORD: 'apollo'
apollo-db:
image: "loads/mysql:5.7"
container_name: apollo-db
environment:
TZ: Asia/Shanghai
MYSQL_ALLOW_EMPTY_PASSWORD: 'yes'
#MYSQL_ROOT_PASSWORD: 'apollo'
depends_on:
- apollo-dbdata
ports:
- "13306:3306"
volumes:
- ./sql:/docker-entrypoint-initdb.d
volumes_from:
- apollo-dbdata
apollo-dbdata:
image: "loads/alpine:3.8"
container_name: apollo-dbdata
volumes:
- /var/lib/mysql

View File

@ -1,467 +0,0 @@
--
-- Copyright 2022 Apollo Authors
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
-- You may obtain a copy of the License at
--
-- http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.
--
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
# Create Database
# ------------------------------------------------------------
CREATE DATABASE IF NOT EXISTS ApolloConfigDB DEFAULT CHARACTER SET = utf8mb4;
Use ApolloConfigDB;
# Dump of table app
# ------------------------------------------------------------
DROP TABLE IF EXISTS `App`;
CREATE TABLE `App` (
`Id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
`AppId` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'AppID',
`Name` varchar(500) NOT NULL DEFAULT 'default' COMMENT '应用名',
`OrgId` varchar(32) NOT NULL DEFAULT 'default' COMMENT '部门Id',
`OrgName` varchar(64) NOT NULL DEFAULT 'default' COMMENT '部门名字',
`OwnerName` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'ownerName',
`OwnerEmail` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'ownerEmail',
`IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal',
`DeletedAt` BIGINT(20) NOT NULL DEFAULT '0' COMMENT 'Delete timestamp based on milliseconds',
`DataChange_CreatedBy` varchar(64) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀',
`DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`DataChange_LastModifiedBy` varchar(64) DEFAULT '' COMMENT '最后修改人邮箱前缀',
`DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
PRIMARY KEY (`Id`),
UNIQUE KEY `UK_AppId_DeletedAt` (`AppId`,`DeletedAt`),
KEY `DataChange_LastTime` (`DataChange_LastTime`),
KEY `IX_Name` (`Name`(191))
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='应用表';
# Dump of table appnamespace
# ------------------------------------------------------------
DROP TABLE IF EXISTS `AppNamespace`;
CREATE TABLE `AppNamespace` (
`Id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键',
`Name` varchar(32) NOT NULL DEFAULT '' COMMENT 'namespace名字注意需要全局唯一',
`AppId` varchar(64) NOT NULL DEFAULT '' COMMENT 'app id',
`Format` varchar(32) NOT NULL DEFAULT 'properties' COMMENT 'namespace的format类型',
`IsPublic` bit(1) NOT NULL DEFAULT b'0' COMMENT 'namespace是否为公共',
`Comment` varchar(64) NOT NULL DEFAULT '' COMMENT '注释',
`IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal',
`DeletedAt` BIGINT(20) NOT NULL DEFAULT '0' COMMENT 'Delete timestamp based on milliseconds',
`DataChange_CreatedBy` varchar(64) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀',
`DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`DataChange_LastModifiedBy` varchar(64) DEFAULT '' COMMENT '最后修改人邮箱前缀',
`DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
PRIMARY KEY (`Id`),
UNIQUE KEY `UK_AppId_Name_DeletedAt` (`AppId`,`Name`,`DeletedAt`),
KEY `Name_AppId` (`Name`,`AppId`),
KEY `DataChange_LastTime` (`DataChange_LastTime`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='应用namespace定义';
# Dump of table audit
# ------------------------------------------------------------
DROP TABLE IF EXISTS `Audit`;
CREATE TABLE `Audit` (
`Id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
`EntityName` varchar(50) NOT NULL DEFAULT 'default' COMMENT '表名',
`EntityId` int(10) unsigned DEFAULT NULL COMMENT '记录ID',
`OpName` varchar(50) NOT NULL DEFAULT 'default' COMMENT '操作类型',
`Comment` varchar(500) DEFAULT NULL COMMENT '备注',
`IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal',
`DeletedAt` BIGINT(20) NOT NULL DEFAULT '0' COMMENT 'Delete timestamp based on milliseconds',
`DataChange_CreatedBy` varchar(64) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀',
`DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`DataChange_LastModifiedBy` varchar(64) DEFAULT '' COMMENT '最后修改人邮箱前缀',
`DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
PRIMARY KEY (`Id`),
KEY `DataChange_LastTime` (`DataChange_LastTime`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='日志审计表';
# Dump of table cluster
# ------------------------------------------------------------
DROP TABLE IF EXISTS `Cluster`;
CREATE TABLE `Cluster` (
`Id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键',
`Name` varchar(32) NOT NULL DEFAULT '' COMMENT '集群名字',
`AppId` varchar(64) NOT NULL DEFAULT '' COMMENT 'App id',
`ParentClusterId` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '父cluster',
`IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal',
`DeletedAt` BIGINT(20) NOT NULL DEFAULT '0' COMMENT 'Delete timestamp based on milliseconds',
`DataChange_CreatedBy` varchar(64) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀',
`DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`DataChange_LastModifiedBy` varchar(64) DEFAULT '' COMMENT '最后修改人邮箱前缀',
`DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
PRIMARY KEY (`Id`),
UNIQUE KEY `UK_AppId_Name_DeletedAt` (`AppId`,`Name`,`DeletedAt`),
KEY `IX_ParentClusterId` (`ParentClusterId`),
KEY `DataChange_LastTime` (`DataChange_LastTime`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='集群';
# Dump of table commit
# ------------------------------------------------------------
DROP TABLE IF EXISTS `Commit`;
CREATE TABLE `Commit` (
`Id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
`ChangeSets` longtext NOT NULL COMMENT '修改变更集',
`AppId` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'AppID',
`ClusterName` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'ClusterName',
`NamespaceName` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'namespaceName',
`Comment` varchar(500) DEFAULT NULL COMMENT '备注',
`IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal',
`DeletedAt` BIGINT(20) NOT NULL DEFAULT '0' COMMENT 'Delete timestamp based on milliseconds',
`DataChange_CreatedBy` varchar(64) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀',
`DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`DataChange_LastModifiedBy` varchar(64) DEFAULT '' COMMENT '最后修改人邮箱前缀',
`DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
PRIMARY KEY (`Id`),
KEY `DataChange_LastTime` (`DataChange_LastTime`),
KEY `AppId` (`AppId`(191)),
KEY `ClusterName` (`ClusterName`(191)),
KEY `NamespaceName` (`NamespaceName`(191))
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='commit 历史表';
# Dump of table grayreleaserule
# ------------------------------------------------------------
DROP TABLE IF EXISTS `GrayReleaseRule`;
CREATE TABLE `GrayReleaseRule` (
`Id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
`AppId` varchar(64) NOT NULL DEFAULT 'default' COMMENT 'AppID',
`ClusterName` varchar(32) NOT NULL DEFAULT 'default' COMMENT 'Cluster Name',
`NamespaceName` varchar(32) NOT NULL DEFAULT 'default' COMMENT 'Namespace Name',
`BranchName` varchar(32) NOT NULL DEFAULT 'default' COMMENT 'branch name',
`Rules` varchar(16000) DEFAULT '[]' COMMENT '灰度规则',
`ReleaseId` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '灰度对应的release',
`BranchStatus` tinyint(2) DEFAULT '1' COMMENT '灰度分支状态: 0:删除分支,1:正在使用的规则 2全量发布',
`IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal',
`DeletedAt` BIGINT(20) NOT NULL DEFAULT '0' COMMENT 'Delete timestamp based on milliseconds',
`DataChange_CreatedBy` varchar(64) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀',
`DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`DataChange_LastModifiedBy` varchar(64) DEFAULT '' COMMENT '最后修改人邮箱前缀',
`DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
PRIMARY KEY (`Id`),
KEY `DataChange_LastTime` (`DataChange_LastTime`),
KEY `IX_Namespace` (`AppId`,`ClusterName`,`NamespaceName`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='灰度规则表';
# Dump of table instance
# ------------------------------------------------------------
DROP TABLE IF EXISTS `Instance`;
CREATE TABLE `Instance` (
`Id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id',
`AppId` varchar(64) NOT NULL DEFAULT 'default' COMMENT 'AppID',
`ClusterName` varchar(32) NOT NULL DEFAULT 'default' COMMENT 'ClusterName',
`DataCenter` varchar(64) NOT NULL DEFAULT 'default' COMMENT 'Data Center Name',
`Ip` varchar(32) NOT NULL DEFAULT '' COMMENT 'instance ip',
`DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`DataChange_LastTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
PRIMARY KEY (`Id`),
UNIQUE KEY `IX_UNIQUE_KEY` (`AppId`,`ClusterName`,`Ip`,`DataCenter`),
KEY `IX_IP` (`Ip`),
KEY `IX_DataChange_LastTime` (`DataChange_LastTime`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='使用配置的应用实例';
# Dump of table instanceconfig
# ------------------------------------------------------------
DROP TABLE IF EXISTS `InstanceConfig`;
CREATE TABLE `InstanceConfig` (
`Id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id',
`InstanceId` int(11) unsigned DEFAULT NULL COMMENT 'Instance Id',
`ConfigAppId` varchar(64) NOT NULL DEFAULT 'default' COMMENT 'Config App Id',
`ConfigClusterName` varchar(32) NOT NULL DEFAULT 'default' COMMENT 'Config Cluster Name',
`ConfigNamespaceName` varchar(32) NOT NULL DEFAULT 'default' COMMENT 'Config Namespace Name',
`ReleaseKey` varchar(64) NOT NULL DEFAULT '' COMMENT '发布的Key',
`ReleaseDeliveryTime` timestamp NULL DEFAULT NULL COMMENT '配置获取时间',
`DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`DataChange_LastTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
PRIMARY KEY (`Id`),
UNIQUE KEY `IX_UNIQUE_KEY` (`InstanceId`,`ConfigAppId`,`ConfigNamespaceName`),
KEY `IX_ReleaseKey` (`ReleaseKey`),
KEY `IX_DataChange_LastTime` (`DataChange_LastTime`),
KEY `IX_Valid_Namespace` (`ConfigAppId`,`ConfigClusterName`,`ConfigNamespaceName`,`DataChange_LastTime`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='应用实例的配置信息';
# Dump of table item
# ------------------------------------------------------------
DROP TABLE IF EXISTS `Item`;
CREATE TABLE `Item` (
`Id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id',
`NamespaceId` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '集群NamespaceId',
`Key` varchar(128) NOT NULL DEFAULT 'default' COMMENT '配置项Key',
`Value` longtext NOT NULL COMMENT '配置项值',
`Comment` varchar(1024) DEFAULT '' COMMENT '注释',
`LineNum` int(10) unsigned DEFAULT '0' COMMENT '行号',
`IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal',
`DeletedAt` BIGINT(20) NOT NULL DEFAULT '0' COMMENT 'Delete timestamp based on milliseconds',
`DataChange_CreatedBy` varchar(64) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀',
`DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`DataChange_LastModifiedBy` varchar(64) DEFAULT '' COMMENT '最后修改人邮箱前缀',
`DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
PRIMARY KEY (`Id`),
KEY `IX_GroupId` (`NamespaceId`),
KEY `DataChange_LastTime` (`DataChange_LastTime`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='配置项目';
# Dump of table namespace
# ------------------------------------------------------------
DROP TABLE IF EXISTS `Namespace`;
CREATE TABLE `Namespace` (
`Id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键',
`AppId` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'AppID',
`ClusterName` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'Cluster Name',
`NamespaceName` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'Namespace Name',
`IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal',
`DeletedAt` BIGINT(20) NOT NULL DEFAULT '0' COMMENT 'Delete timestamp based on milliseconds',
`DataChange_CreatedBy` varchar(64) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀',
`DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`DataChange_LastModifiedBy` varchar(64) DEFAULT '' COMMENT '最后修改人邮箱前缀',
`DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
PRIMARY KEY (`Id`),
UNIQUE KEY `UK_AppId_ClusterName_NamespaceName_DeletedAt` (`AppId`(191),`ClusterName`(191),`NamespaceName`(191),`DeletedAt`),
KEY `DataChange_LastTime` (`DataChange_LastTime`),
KEY `IX_NamespaceName` (`NamespaceName`(191))
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='命名空间';
# Dump of table namespacelock
# ------------------------------------------------------------
DROP TABLE IF EXISTS `NamespaceLock`;
CREATE TABLE `NamespaceLock` (
`Id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增id',
`NamespaceId` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '集群NamespaceId',
`DataChange_CreatedBy` varchar(64) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀',
`DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`DataChange_LastModifiedBy` varchar(64) DEFAULT '' COMMENT '最后修改人邮箱前缀',
`DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
`IsDeleted` bit(1) DEFAULT b'0' COMMENT '软删除',
`DeletedAt` BIGINT(20) NOT NULL DEFAULT '0' COMMENT 'Delete timestamp based on milliseconds',
PRIMARY KEY (`Id`),
UNIQUE KEY `UK_NamespaceId_DeletedAt` (`NamespaceId`,`DeletedAt`),
KEY `DataChange_LastTime` (`DataChange_LastTime`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='namespace的编辑锁';
# Dump of table release
# ------------------------------------------------------------
DROP TABLE IF EXISTS `Release`;
CREATE TABLE `Release` (
`Id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键',
`ReleaseKey` varchar(64) NOT NULL DEFAULT '' COMMENT '发布的Key',
`Name` varchar(64) NOT NULL DEFAULT 'default' COMMENT '发布名字',
`Comment` varchar(256) DEFAULT NULL COMMENT '发布说明',
`AppId` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'AppID',
`ClusterName` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'ClusterName',
`NamespaceName` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'namespaceName',
`Configurations` longtext NOT NULL COMMENT '发布配置',
`IsAbandoned` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否废弃',
`IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal',
`DeletedAt` BIGINT(20) NOT NULL DEFAULT '0' COMMENT 'Delete timestamp based on milliseconds',
`DataChange_CreatedBy` varchar(64) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀',
`DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`DataChange_LastModifiedBy` varchar(64) DEFAULT '' COMMENT '最后修改人邮箱前缀',
`DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
PRIMARY KEY (`Id`),
UNIQUE KEY `UK_ReleaseKey_DeletedAt` (`ReleaseKey`,`DeletedAt`),
KEY `AppId_ClusterName_GroupName` (`AppId`(191),`ClusterName`(191),`NamespaceName`(191)),
KEY `DataChange_LastTime` (`DataChange_LastTime`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='发布';
# Dump of table releasehistory
# ------------------------------------------------------------
DROP TABLE IF EXISTS `ReleaseHistory`;
CREATE TABLE `ReleaseHistory` (
`Id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id',
`AppId` varchar(64) NOT NULL DEFAULT 'default' COMMENT 'AppID',
`ClusterName` varchar(32) NOT NULL DEFAULT 'default' COMMENT 'ClusterName',
`NamespaceName` varchar(32) NOT NULL DEFAULT 'default' COMMENT 'namespaceName',
`BranchName` varchar(32) NOT NULL DEFAULT 'default' COMMENT '发布分支名',
`ReleaseId` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '关联的Release Id',
`PreviousReleaseId` int(11) unsigned NOT NULL DEFAULT '0' COMMENT '前一次发布的ReleaseId',
`Operation` tinyint(3) unsigned NOT NULL DEFAULT '0' COMMENT '发布类型0: 普通发布1: 回滚2: 灰度发布3: 灰度规则更新4: 灰度合并回主分支发布5: 主分支发布灰度自动发布6: 主分支回滚灰度自动发布7: 放弃灰度',
`OperationContext` longtext NOT NULL COMMENT '发布上下文信息',
`IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal',
`DeletedAt` BIGINT(20) NOT NULL DEFAULT '0' COMMENT 'Delete timestamp based on milliseconds',
`DataChange_CreatedBy` varchar(64) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀',
`DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`DataChange_LastModifiedBy` varchar(64) DEFAULT '' COMMENT '最后修改人邮箱前缀',
`DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
PRIMARY KEY (`Id`),
KEY `IX_Namespace` (`AppId`,`ClusterName`,`NamespaceName`,`BranchName`),
KEY `IX_ReleaseId` (`ReleaseId`),
KEY `IX_DataChange_LastTime` (`DataChange_LastTime`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='发布历史';
# Dump of table releasemessage
# ------------------------------------------------------------
DROP TABLE IF EXISTS `ReleaseMessage`;
CREATE TABLE `ReleaseMessage` (
`Id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键',
`Message` varchar(1024) NOT NULL DEFAULT '' COMMENT '发布的消息内容',
`DataChange_LastTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
PRIMARY KEY (`Id`),
KEY `DataChange_LastTime` (`DataChange_LastTime`),
KEY `IX_Message` (`Message`(191))
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='发布消息';
# Dump of table serverconfig
# ------------------------------------------------------------
DROP TABLE IF EXISTS `ServerConfig`;
CREATE TABLE `ServerConfig` (
`Id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id',
`Key` varchar(64) NOT NULL DEFAULT 'default' COMMENT '配置项Key',
`Cluster` varchar(32) NOT NULL DEFAULT 'default' COMMENT '配置对应的集群default为不针对特定的集群',
`Value` varchar(2048) NOT NULL DEFAULT 'default' COMMENT '配置项值',
`Comment` varchar(1024) DEFAULT '' COMMENT '注释',
`IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal',
`DeletedAt` BIGINT(20) NOT NULL DEFAULT '0' COMMENT 'Delete timestamp based on milliseconds',
`DataChange_CreatedBy` varchar(64) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀',
`DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`DataChange_LastModifiedBy` varchar(64) DEFAULT '' COMMENT '最后修改人邮箱前缀',
`DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
PRIMARY KEY (`Id`),
UNIQUE KEY `UK_Key_Cluster_DeletedAt` (`Key`,`Cluster`,`DeletedAt`),
KEY `DataChange_LastTime` (`DataChange_LastTime`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='配置服务自身配置';
# Dump of table accesskey
# ------------------------------------------------------------
DROP TABLE IF EXISTS `AccessKey`;
CREATE TABLE `AccessKey` (
`Id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键',
`AppId` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'AppID',
`Secret` varchar(128) NOT NULL DEFAULT '' COMMENT 'Secret',
`IsEnabled` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: enabled, 0: disabled',
`IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal',
`DeletedAt` BIGINT(20) NOT NULL DEFAULT '0' COMMENT 'Delete timestamp based on milliseconds',
`DataChange_CreatedBy` varchar(64) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀',
`DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`DataChange_LastModifiedBy` varchar(64) DEFAULT '' COMMENT '最后修改人邮箱前缀',
`DataChange_LastTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
PRIMARY KEY (`Id`),
UNIQUE KEY `UK_AppId_Secret_DeletedAt` (`AppId`,`Secret`,`DeletedAt`),
KEY `DataChange_LastTime` (`DataChange_LastTime`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='访问密钥';
# Config
# ------------------------------------------------------------
INSERT INTO `ServerConfig` (`Key`, `Cluster`, `Value`, `Comment`)
VALUES
('eureka.service.url', 'default', 'http://localhost:8080/eureka/', 'Eureka服务Url多个service以英文逗号分隔'),
('namespace.lock.switch', 'default', 'false', '一次发布只能有一个人修改开关'),
('item.value.length.limit', 'default', '20000', 'item value最大长度限制'),
('config-service.cache.enabled', 'default', 'false', 'ConfigService是否开启缓存开启后能提高性能但是会增大内存消耗'),
('item.key.length.limit', 'default', '128', 'item key 最大长度限制');
# Sample Data
# ------------------------------------------------------------
INSERT INTO `App` (`AppId`, `Name`, `OrgId`, `OrgName`, `OwnerName`, `OwnerEmail`)
VALUES
('SampleApp', 'Sample App', 'TEST1', '样例部门1', 'apollo', 'apollo@acme.com');
INSERT INTO `AppNamespace` (`Name`, `AppId`, `Format`, `IsPublic`, `Comment`)
VALUES
('application', 'SampleApp', 'properties', 0, 'default app namespace');
INSERT INTO `Cluster` (`Name`, `AppId`)
VALUES
('default', 'SampleApp');
INSERT INTO `Namespace` (`Id`, `AppId`, `ClusterName`, `NamespaceName`)
VALUES
(1, 'SampleApp', 'default', 'application');
INSERT INTO `Item` VALUES (1,1,'timeout','100','sample timeout配置',1,_binary '\0',0,'default','2022-09-28 15:43:17','','2022-09-28 15:43:17'),
(2,1,'','','',2,_binary '\0',0,'apollo','2022-09-28 15:47:55','apollo','2022-09-28 15:47:55'),
(3,1,'server.address',':8000','',3,_binary '\0',0,'apollo','2022-09-28 15:47:55','apollo','2022-09-28 15:47:55'),
(4,1,'server.dumpRouterMap','true','',4,_binary '\0',0,'apollo','2022-09-28 15:47:55','apollo','2022-09-28 15:47:55'),
(5,1,'server.routeOverWrite','true','',5,_binary '\0',0,'apollo','2022-09-28 15:47:55','apollo','2022-09-28 15:47:55'),
(6,1,'server.accessLogEnabled','true','',6,_binary '\0',0,'apollo','2022-09-28 15:47:55','apollo','2022-09-28 15:47:55'),
(7,1,'server.openapiPath','/api.json','',7,_binary '\0',0,'apollo','2022-09-28 15:47:55','apollo','2022-09-28 15:47:55'),
(8,1,'server.swaggerPath','/swagger','',8,_binary '\0',0,'apollo','2022-09-28 15:47:55','apollo','2022-09-28 15:47:55'),
(9,1,'','','',9,_binary '\0',0,'apollo','2022-09-28 15:47:55','apollo','2022-09-28 15:47:55'),
(10,1,'','','# Global logging.',10,_binary '\0',0,'apollo','2022-09-28 15:47:55','apollo','2022-09-28 15:47:55'),
(11,1,'logger.level','all','',11,_binary '\0',0,'apollo','2022-09-28 15:47:55','apollo','2022-09-28 15:47:55'),
(12,1,'logger.stdout','true','',12,_binary '\0',0,'apollo','2022-09-28 15:47:55','apollo','2022-09-28 15:47:55');
INSERT INTO `Release` VALUES (1,'20161009155425-d3a0749c6e20bc15','20161009155424-release','Sample发布','SampleApp','default','application','{\"timeout\":\"100\"}',_binary '\0',_binary '\0',0,'default','2022-09-28 15:59:38','','2022-09-28 15:59:38'),
(2,'20220929000151-1dc5634459e19171','20220929000148-release','','SampleApp','default','application','{\"timeout\":\"100\",\"server.address\":\":8000\",\"server.dumpRouterMap\":\"true\",\"server.routeOverWrite\":\"true\",\"server.accessLogEnabled\":\"true\",\"server.openapiPath\":\"/api.json\",\"server.swaggerPath\":\"/swagger\",\"logger.level\":\"all\",\"logger.stdout\":\"true\"}',_binary '\0',_binary '\0',0,'apollo','2022-09-28 16:01:51','apollo','2022-09-28 16:01:51');
INSERT INTO `ReleaseHistory` VALUES (1,'SampleApp','default','application','default',1,0,0,'{}',_binary '\0',0,'apollo','2022-09-28 15:59:38','apollo','2022-09-28 15:59:38'),
(2,'SampleApp','default','application','default',2,1,0,'{\"isEmergencyPublish\":false}',_binary '\0',0,'apollo','2022-09-28 16:01:51','apollo','2022-09-28 16:01:51');
INSERT INTO `ReleaseMessage` VALUES (1,'SampleApp+default+application','2022-09-28 15:59:38'),
(2,'SampleApp+default+application','2022-09-28 16:01:51');
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;

View File

@ -1,420 +0,0 @@
--
-- Copyright 2022 Apollo Authors
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
-- You may obtain a copy of the License at
--
-- http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.
--
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
# Create Database
# ------------------------------------------------------------
CREATE DATABASE IF NOT EXISTS ApolloPortalDB DEFAULT CHARACTER SET = utf8mb4;
Use ApolloPortalDB;
# Dump of table app
# ------------------------------------------------------------
DROP TABLE IF EXISTS `App`;
CREATE TABLE `App` (
`Id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
`AppId` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'AppID',
`Name` varchar(500) NOT NULL DEFAULT 'default' COMMENT '应用名',
`OrgId` varchar(32) NOT NULL DEFAULT 'default' COMMENT '部门Id',
`OrgName` varchar(64) NOT NULL DEFAULT 'default' COMMENT '部门名字',
`OwnerName` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'ownerName',
`OwnerEmail` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'ownerEmail',
`IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal',
`DeletedAt` BIGINT(20) NOT NULL DEFAULT '0' COMMENT 'Delete timestamp based on milliseconds',
`DataChange_CreatedBy` varchar(64) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀',
`DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`DataChange_LastModifiedBy` varchar(64) DEFAULT '' COMMENT '最后修改人邮箱前缀',
`DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
PRIMARY KEY (`Id`),
UNIQUE KEY `UK_AppId_DeletedAt` (`AppId`,`DeletedAt`),
KEY `DataChange_LastTime` (`DataChange_LastTime`),
KEY `IX_Name` (`Name`(191))
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='应用表';
# Dump of table appnamespace
# ------------------------------------------------------------
DROP TABLE IF EXISTS `AppNamespace`;
CREATE TABLE `AppNamespace` (
`Id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键',
`Name` varchar(32) NOT NULL DEFAULT '' COMMENT 'namespace名字注意需要全局唯一',
`AppId` varchar(64) NOT NULL DEFAULT '' COMMENT 'app id',
`Format` varchar(32) NOT NULL DEFAULT 'properties' COMMENT 'namespace的format类型',
`IsPublic` bit(1) NOT NULL DEFAULT b'0' COMMENT 'namespace是否为公共',
`Comment` varchar(64) NOT NULL DEFAULT '' COMMENT '注释',
`IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal',
`DeletedAt` BIGINT(20) NOT NULL DEFAULT '0' COMMENT 'Delete timestamp based on milliseconds',
`DataChange_CreatedBy` varchar(64) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀',
`DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`DataChange_LastModifiedBy` varchar(64) DEFAULT '' COMMENT '最后修改人邮箱前缀',
`DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
PRIMARY KEY (`Id`),
UNIQUE KEY `UK_AppId_Name_DeletedAt` (`AppId`,`Name`,`DeletedAt`),
KEY `Name_AppId` (`Name`,`AppId`),
KEY `DataChange_LastTime` (`DataChange_LastTime`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='应用namespace定义';
# Dump of table consumer
# ------------------------------------------------------------
DROP TABLE IF EXISTS `Consumer`;
CREATE TABLE `Consumer` (
`Id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id',
`AppId` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'AppID',
`Name` varchar(500) NOT NULL DEFAULT 'default' COMMENT '应用名',
`OrgId` varchar(32) NOT NULL DEFAULT 'default' COMMENT '部门Id',
`OrgName` varchar(64) NOT NULL DEFAULT 'default' COMMENT '部门名字',
`OwnerName` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'ownerName',
`OwnerEmail` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'ownerEmail',
`IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal',
`DeletedAt` BIGINT(20) NOT NULL DEFAULT '0' COMMENT 'Delete timestamp based on milliseconds',
`DataChange_CreatedBy` varchar(64) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀',
`DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`DataChange_LastModifiedBy` varchar(64) DEFAULT '' COMMENT '最后修改人邮箱前缀',
`DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
PRIMARY KEY (`Id`),
UNIQUE KEY `UK_AppId_DeletedAt` (`AppId`,`DeletedAt`),
KEY `DataChange_LastTime` (`DataChange_LastTime`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='开放API消费者';
# Dump of table consumeraudit
# ------------------------------------------------------------
DROP TABLE IF EXISTS `ConsumerAudit`;
CREATE TABLE `ConsumerAudit` (
`Id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id',
`ConsumerId` int(11) unsigned DEFAULT NULL COMMENT 'Consumer Id',
`Uri` varchar(1024) NOT NULL DEFAULT '' COMMENT '访问的Uri',
`Method` varchar(16) NOT NULL DEFAULT '' COMMENT '访问的Method',
`DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
PRIMARY KEY (`Id`),
KEY `IX_DataChange_LastTime` (`DataChange_LastTime`),
KEY `IX_ConsumerId` (`ConsumerId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='consumer审计表';
# Dump of table consumerrole
# ------------------------------------------------------------
DROP TABLE IF EXISTS `ConsumerRole`;
CREATE TABLE `ConsumerRole` (
`Id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id',
`ConsumerId` int(11) unsigned DEFAULT NULL COMMENT 'Consumer Id',
`RoleId` int(10) unsigned DEFAULT NULL COMMENT 'Role Id',
`IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal',
`DeletedAt` BIGINT(20) NOT NULL DEFAULT '0' COMMENT 'Delete timestamp based on milliseconds',
`DataChange_CreatedBy` varchar(64) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀',
`DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`DataChange_LastModifiedBy` varchar(64) DEFAULT '' COMMENT '最后修改人邮箱前缀',
`DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
PRIMARY KEY (`Id`),
UNIQUE KEY `UK_ConsumerId_RoleId_DeletedAt` (`ConsumerId`,`RoleId`,`DeletedAt`),
KEY `IX_DataChange_LastTime` (`DataChange_LastTime`),
KEY `IX_RoleId` (`RoleId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='consumer和role的绑定表';
# Dump of table consumertoken
# ------------------------------------------------------------
DROP TABLE IF EXISTS `ConsumerToken`;
CREATE TABLE `ConsumerToken` (
`Id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id',
`ConsumerId` int(11) unsigned DEFAULT NULL COMMENT 'ConsumerId',
`Token` varchar(128) NOT NULL DEFAULT '' COMMENT 'token',
`Expires` datetime NOT NULL DEFAULT '2099-01-01 00:00:00' COMMENT 'token失效时间',
`IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal',
`DeletedAt` BIGINT(20) NOT NULL DEFAULT '0' COMMENT 'Delete timestamp based on milliseconds',
`DataChange_CreatedBy` varchar(64) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀',
`DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`DataChange_LastModifiedBy` varchar(64) DEFAULT '' COMMENT '最后修改人邮箱前缀',
`DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
PRIMARY KEY (`Id`),
UNIQUE KEY `UK_Token_DeletedAt` (`Token`,`DeletedAt`),
KEY `DataChange_LastTime` (`DataChange_LastTime`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='consumer token表';
# Dump of table favorite
# ------------------------------------------------------------
DROP TABLE IF EXISTS `Favorite`;
CREATE TABLE `Favorite` (
`Id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',
`UserId` varchar(32) NOT NULL DEFAULT 'default' COMMENT '收藏的用户',
`AppId` varchar(500) NOT NULL DEFAULT 'default' COMMENT 'AppID',
`Position` int(32) NOT NULL DEFAULT '10000' COMMENT '收藏顺序',
`IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal',
`DeletedAt` BIGINT(20) NOT NULL DEFAULT '0' COMMENT 'Delete timestamp based on milliseconds',
`DataChange_CreatedBy` varchar(64) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀',
`DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`DataChange_LastModifiedBy` varchar(64) DEFAULT '' COMMENT '最后修改人邮箱前缀',
`DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
PRIMARY KEY (`Id`),
UNIQUE KEY `UK_UserId_AppId_DeletedAt` (`UserId`,`AppId`,`DeletedAt`),
KEY `AppId` (`AppId`(191)),
KEY `DataChange_LastTime` (`DataChange_LastTime`)
) ENGINE=InnoDB AUTO_INCREMENT=23 DEFAULT CHARSET=utf8mb4 COMMENT='应用收藏表';
# Dump of table permission
# ------------------------------------------------------------
DROP TABLE IF EXISTS `Permission`;
CREATE TABLE `Permission` (
`Id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id',
`PermissionType` varchar(32) NOT NULL DEFAULT '' COMMENT '权限类型',
`TargetId` varchar(256) NOT NULL DEFAULT '' COMMENT '权限对象类型',
`IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal',
`DeletedAt` BIGINT(20) NOT NULL DEFAULT '0' COMMENT 'Delete timestamp based on milliseconds',
`DataChange_CreatedBy` varchar(64) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀',
`DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`DataChange_LastModifiedBy` varchar(64) DEFAULT '' COMMENT '最后修改人邮箱前缀',
`DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
PRIMARY KEY (`Id`),
UNIQUE KEY `UK_TargetId_PermissionType_DeletedAt` (`TargetId`,`PermissionType`,`DeletedAt`),
KEY `IX_DataChange_LastTime` (`DataChange_LastTime`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='permission表';
# Dump of table role
# ------------------------------------------------------------
DROP TABLE IF EXISTS `Role`;
CREATE TABLE `Role` (
`Id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id',
`RoleName` varchar(256) NOT NULL DEFAULT '' COMMENT 'Role name',
`IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal',
`DeletedAt` BIGINT(20) NOT NULL DEFAULT '0' COMMENT 'Delete timestamp based on milliseconds',
`DataChange_CreatedBy` varchar(64) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀',
`DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`DataChange_LastModifiedBy` varchar(64) DEFAULT '' COMMENT '最后修改人邮箱前缀',
`DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
PRIMARY KEY (`Id`),
UNIQUE KEY `UK_RoleName_DeletedAt` (`RoleName`,`DeletedAt`),
KEY `IX_DataChange_LastTime` (`DataChange_LastTime`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='角色表';
# Dump of table rolepermission
# ------------------------------------------------------------
DROP TABLE IF EXISTS `RolePermission`;
CREATE TABLE `RolePermission` (
`Id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id',
`RoleId` int(10) unsigned DEFAULT NULL COMMENT 'Role Id',
`PermissionId` int(10) unsigned DEFAULT NULL COMMENT 'Permission Id',
`IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal',
`DeletedAt` BIGINT(20) NOT NULL DEFAULT '0' COMMENT 'Delete timestamp based on milliseconds',
`DataChange_CreatedBy` varchar(64) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀',
`DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`DataChange_LastModifiedBy` varchar(64) DEFAULT '' COMMENT '最后修改人邮箱前缀',
`DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
PRIMARY KEY (`Id`),
UNIQUE KEY `UK_RoleId_PermissionId_DeletedAt` (`RoleId`,`PermissionId`,`DeletedAt`),
KEY `IX_DataChange_LastTime` (`DataChange_LastTime`),
KEY `IX_PermissionId` (`PermissionId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='角色和权限的绑定表';
# Dump of table serverconfig
# ------------------------------------------------------------
DROP TABLE IF EXISTS `ServerConfig`;
CREATE TABLE `ServerConfig` (
`Id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id',
`Key` varchar(64) NOT NULL DEFAULT 'default' COMMENT '配置项Key',
`Value` varchar(2048) NOT NULL DEFAULT 'default' COMMENT '配置项值',
`Comment` varchar(1024) DEFAULT '' COMMENT '注释',
`IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal',
`DeletedAt` BIGINT(20) NOT NULL DEFAULT '0' COMMENT 'Delete timestamp based on milliseconds',
`DataChange_CreatedBy` varchar(64) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀',
`DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`DataChange_LastModifiedBy` varchar(64) DEFAULT '' COMMENT '最后修改人邮箱前缀',
`DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
PRIMARY KEY (`Id`),
UNIQUE KEY `UK_Key_DeletedAt` (`Key`,`DeletedAt`),
KEY `DataChange_LastTime` (`DataChange_LastTime`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='配置服务自身配置';
# Dump of table userrole
# ------------------------------------------------------------
DROP TABLE IF EXISTS `UserRole`;
CREATE TABLE `UserRole` (
`Id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id',
`UserId` varchar(128) DEFAULT '' COMMENT '用户身份标识',
`RoleId` int(10) unsigned DEFAULT NULL COMMENT 'Role Id',
`IsDeleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '1: deleted, 0: normal',
`DeletedAt` BIGINT(20) NOT NULL DEFAULT '0' COMMENT 'Delete timestamp based on milliseconds',
`DataChange_CreatedBy` varchar(64) NOT NULL DEFAULT 'default' COMMENT '创建人邮箱前缀',
`DataChange_CreatedTime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`DataChange_LastModifiedBy` varchar(64) DEFAULT '' COMMENT '最后修改人邮箱前缀',
`DataChange_LastTime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
PRIMARY KEY (`Id`),
UNIQUE KEY `UK_UserId_RoleId_DeletedAt` (`UserId`,`RoleId`,`DeletedAt`),
KEY `IX_DataChange_LastTime` (`DataChange_LastTime`),
KEY `IX_RoleId` (`RoleId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户和role的绑定表';
# Dump of table Users
# ------------------------------------------------------------
DROP TABLE IF EXISTS `Users`;
CREATE TABLE `Users` (
`Id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id',
`Username` varchar(64) NOT NULL DEFAULT 'default' COMMENT '用户登录账户',
`Password` varchar(512) NOT NULL DEFAULT 'default' COMMENT '密码',
`UserDisplayName` varchar(512) NOT NULL DEFAULT 'default' COMMENT '用户名称',
`Email` varchar(64) NOT NULL DEFAULT 'default' COMMENT '邮箱地址',
`Enabled` tinyint(4) DEFAULT NULL COMMENT '是否有效',
PRIMARY KEY (`Id`),
UNIQUE KEY `UK_Username` (`Username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表';
# Dump of table Authorities
# ------------------------------------------------------------
DROP TABLE IF EXISTS `Authorities`;
CREATE TABLE `Authorities` (
`Id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增Id',
`Username` varchar(64) NOT NULL,
`Authority` varchar(50) NOT NULL,
PRIMARY KEY (`Id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
# Config
# ------------------------------------------------------------
INSERT INTO `ServerConfig` (`Key`, `Value`, `Comment`)
VALUES
('apollo.portal.envs', 'dev', '可支持的环境列表'),
('organizations', '[{\"orgId\":\"TEST1\",\"orgName\":\"样例部门1\"},{\"orgId\":\"TEST2\",\"orgName\":\"样例部门2\"}]', '部门列表'),
('superAdmin', 'apollo', 'Portal超级管理员'),
('api.readTimeout', '10000', 'http接口read timeout'),
('consumer.token.salt', 'someSalt', 'consumer token salt'),
('admin.createPrivateNamespace.switch', 'true', '是否允许项目管理员创建私有namespace'),
('configView.memberOnly.envs', 'dev', '只对项目成员显示配置信息的环境列表多个env以英文逗号分隔'),
('apollo.portal.meta.servers', '{}', '各环境Meta Service列表');
INSERT INTO `Users` (`Username`, `Password`, `UserDisplayName`, `Email`, `Enabled`)
VALUES
('apollo', '$2a$10$7r20uS.BQ9uBpf3Baj3uQOZvMVvB1RN3PYoKE94gtz2.WAOuiiwXS', 'apollo', 'apollo@acme.com', 1);
INSERT INTO `Authorities` (`Username`, `Authority`) VALUES ('apollo', 'ROLE_user');
# Sample Data
# ------------------------------------------------------------
INSERT INTO `App` (`AppId`, `Name`, `OrgId`, `OrgName`, `OwnerName`, `OwnerEmail`)
VALUES
('SampleApp', 'Sample App', 'TEST1', '样例部门1', 'apollo', 'apollo@acme.com');
INSERT INTO `AppNamespace` (`Name`, `AppId`, `Format`, `IsPublic`, `Comment`)
VALUES
('application', 'SampleApp', 'properties', 0, 'default app namespace');
INSERT INTO `Permission` (`Id`, `PermissionType`, `TargetId`)
VALUES
(1, 'CreateCluster', 'SampleApp'),
(2, 'CreateNamespace', 'SampleApp'),
(3, 'AssignRole', 'SampleApp'),
(4, 'ModifyNamespace', 'SampleApp+application'),
(5, 'ReleaseNamespace', 'SampleApp+application');
INSERT INTO `Role` (`Id`, `RoleName`)
VALUES
(1, 'Master+SampleApp'),
(2, 'ModifyNamespace+SampleApp+application'),
(3, 'ReleaseNamespace+SampleApp+application');
INSERT INTO `RolePermission` (`RoleId`, `PermissionId`)
VALUES
(1, 1),
(1, 2),
(1, 3),
(2, 4),
(3, 5);
INSERT INTO `UserRole` (`UserId`, `RoleId`)
VALUES
('apollo', 1),
('apollo', 2),
('apollo', 3);
-- spring session (https://github.com/spring-projects/spring-session/blob/faee8f1bdb8822a5653a81eba838dddf224d92d6/spring-session-jdbc/src/main/resources/org/springframework/session/jdbc/schema-mysql.sql)
CREATE TABLE SPRING_SESSION (
PRIMARY_ID CHAR(36) NOT NULL,
SESSION_ID CHAR(36) NOT NULL,
CREATION_TIME BIGINT NOT NULL,
LAST_ACCESS_TIME BIGINT NOT NULL,
MAX_INACTIVE_INTERVAL INT NOT NULL,
EXPIRY_TIME BIGINT NOT NULL,
PRINCIPAL_NAME VARCHAR(100),
CONSTRAINT SPRING_SESSION_PK PRIMARY KEY (PRIMARY_ID)
) ENGINE=InnoDB ROW_FORMAT=DYNAMIC;
CREATE UNIQUE INDEX SPRING_SESSION_IX1 ON SPRING_SESSION (SESSION_ID);
CREATE INDEX SPRING_SESSION_IX2 ON SPRING_SESSION (EXPIRY_TIME);
CREATE INDEX SPRING_SESSION_IX3 ON SPRING_SESSION (PRINCIPAL_NAME);
CREATE TABLE SPRING_SESSION_ATTRIBUTES (
SESSION_PRIMARY_ID CHAR(36) NOT NULL,
ATTRIBUTE_NAME VARCHAR(200) NOT NULL,
ATTRIBUTE_BYTES BLOB NOT NULL,
CONSTRAINT SPRING_SESSION_ATTRIBUTES_PK PRIMARY KEY (SESSION_PRIMARY_ID, ATTRIBUTE_NAME),
CONSTRAINT SPRING_SESSION_ATTRIBUTES_FK FOREIGN KEY (SESSION_PRIMARY_ID) REFERENCES SPRING_SESSION(PRIMARY_ID) ON DELETE CASCADE
) ENGINE=InnoDB ROW_FORMAT=DYNAMIC;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;

View File

@ -1,6 +0,0 @@
#!/usr/bin/env bash
find . -name "*.go" | xargs gofmt -w
git diff --name-only --exit-code || if [ $? != 0 ]; then echo "Notice: gofmt check failed,please gofmt before pr." && exit 1; fi
echo "gofmt check pass."
sudo echo "127.0.0.1 local" | sudo tee -a /etc/hosts

View File

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

View File

@ -52,7 +52,7 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with: with:
tag_name: ${{ github.ref }} tag_name: ${{ github.ref }}
release_name: GoFrame Release ${{ github.ref }} release_name: GoFrame CLI Release ${{ github.ref }}
draft: false draft: false
prerelease: false prerelease: false

View File

@ -3,7 +3,7 @@ version: "2"
services: services:
redis-master: redis-master:
container_name: redis-master container_name: redis-master
image: "loads/redis:7.0-sentinel" image: "loads/redis:7.0"
environment: environment:
- REDIS_REPLICATION_MODE=master - REDIS_REPLICATION_MODE=master
- REDIS_PASSWORD=111111 - REDIS_PASSWORD=111111
@ -12,7 +12,7 @@ services:
redis-slave1: redis-slave1:
container_name: redis-slave1 container_name: redis-slave1
image: "loads/redis:7.0-sentinel" image: "loads/redis:7.0"
environment: environment:
- REDIS_REPLICATION_MODE=slave - REDIS_REPLICATION_MODE=slave
- REDIS_MASTER_HOST=redis-master - REDIS_MASTER_HOST=redis-master
@ -27,7 +27,7 @@ services:
redis-slave2: redis-slave2:
container_name: redis-slave2 container_name: redis-slave2
image: "loads/redis:7.0-sentinel" image: "loads/redis:7.0"
environment: environment:
- REDIS_REPLICATION_MODE=slave - REDIS_REPLICATION_MODE=slave
- REDIS_MASTER_HOST=redis-master - REDIS_MASTER_HOST=redis-master

View File

@ -8,7 +8,6 @@ on:
- develop - develop
- personal/** - personal/**
- feature/** - feature/**
- enhance/**
- fix/** - fix/**
pull_request: pull_request:
@ -17,14 +16,8 @@ on:
- develop - develop
- personal/** - personal/**
- feature/** - feature/**
- enhance/**
- fix/** - 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: env:
TZ: "Asia/Shanghai" TZ: "Asia/Shanghai"
@ -37,7 +30,7 @@ jobs:
services: services:
# Redis backend server. # Redis backend server.
redis: redis:
image : loads/redis:7.0 image : loads/redis:latest
options: >- options: >-
--health-cmd "redis-cli ping" --health-cmd "redis-cli ping"
--health-interval 10s --health-interval 10s
@ -58,7 +51,6 @@ jobs:
- 3306:3306 - 3306:3306
# PostgreSQL backend server. # 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
postgres: postgres:
image: loads/postgres:13 image: loads/postgres:13
env: env:
@ -77,7 +69,7 @@ jobs:
# MSSQL backend server. # MSSQL backend server.
mssql: mssql:
image: loads/mssqldocker:14.0.3391.2 image: loads/mssqldocker:latest
env: env:
ACCEPT_EULA: Y ACCEPT_EULA: Y
SA_PASSWORD: LoremIpsum86 SA_PASSWORD: LoremIpsum86
@ -94,25 +86,22 @@ jobs:
--health-retries 10 --health-retries 10
# ClickHouse backend server. # ClickHouse backend server.
# docker run -d --name clickhouse -p 9000:9000 -p 8123:8123 -p 9001:9001 loads/clickhouse-server:22.1.3.7
clickhouse-server: clickhouse-server:
image: loads/clickhouse-server:22.1.3.7 image: loads/clickhouse-server:latest
ports: ports:
- 9000:9000 - 9000:9000
- 8123:8123 - 8123:8123
- 9001:9001 - 9001:9001
# Polaris backend server.
polaris: polaris:
image: loads/polaris-server-standalone:1.11.2 image: polarismesh/polaris-server-standalone:latest
ports: ports:
- 8090:8090 - 8090:8090
- 8091:8091 - 8091:8091
- 8093:8093
# Oracle 11g server #oracle 11g server
oracle-server: oracle-server:
image: loads/oracle-xe-11g-r2:11.2.0 image: loads/oracle-xe-11g-r2:latest
env: env:
ORACLE_ALLOW_REMOTE: true ORACLE_ALLOW_REMOTE: true
ORACLE_SID: XE ORACLE_SID: XE
@ -121,79 +110,65 @@ jobs:
ports: ports:
- 1521:1521 - 1521:1521
# dm8 server
# docker run -d --name dm -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:
- 5236:5236
zookeeper:
image: loads/zookeeper:3.8
ports:
- 2181:2181
strategy: strategy:
matrix: matrix:
go-version: [ "1.15", "1.16", "1.17", "1.18" ] go: [ "1.15", "1.16", "1.17" ]
goarch: [ "386", "amd64" ] goarch: [ "386", "amd64" ]
steps: steps:
# TODO: szenius/set-timezone update to node16 - name: Set Up Timezone
- name: Setup Timezone uses: szenius/set-timezone@v1.0
uses: szenius/set-timezone@v1.1
with: with:
timezoneLinux: "Asia/Shanghai" timezoneLinux: "Asia/Shanghai"
- name: Checkout Repository - name: Checkout Repository
uses: actions/checkout@v3 uses: actions/checkout@v2
- name: Start Apollo Containers - name: Set Up Go
run: docker-compose -f ".github/workflows/apollo/docker-compose.yml" up -d --build uses: actions/setup-go@v2
- name: Start Nacos Containers
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
- name: Start Minikube
uses: medyagh/setup-minikube@master
- name: Setup Golang ${{ matrix.go-version }}
uses: actions/setup-go@v3
with: with:
go-version: ${{ matrix.go-version }} go-version: ${{ matrix.go }}
- name: Setup Golang caches - name: Start containers
uses: actions/cache@v3 run: docker-compose -f ".github/workflows/docker-compose.yml" up -d --build
with:
path: |
~/go/pkg/mod
~/.cache/go-build
~/Library/Caches/go-build
~\AppData\Local\go-build
key: ${{ runner.os }}-go-${{ matrix.go-version }}-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-go-${{ matrix.go-version }}-
- name: Before Script - name: Before Script
run: bash .github/workflows/before_script.sh run: |
find . -name "*.go" | xargs gofmt -w
git diff --name-only --exit-code || if [ $? != 0 ]; then echo "Notice: gofmt check failed,please gofmt before pr." && exit 1; fi
echo "gofmt check pass."
sudo echo "127.0.0.1 local" | sudo tee -a /etc/hosts
- name: Build & Test - name: Build & Test
run: bash .github/workflows/build_and_test.sh run: |
GOARCH=${{ matrix.goarch }}
for file in `find . -name go.mod`; do
dirpath=$(dirname $file)
- name: Stop Redis Cluster Containers if [ "oracle" = $(basename $dirpath) ]; then
run: docker-compose -f ".github/workflows/redis/docker-compose.yml" down if ! go version|grep -q "1.17"; then
continue 1
fi
fi
- name: Stop Apollo Containers cd $dirpath
run: docker-compose -f ".github/workflows/apollo/docker-compose.yml" down 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
- name: Stop Nacos Containers - name: Stop containers
run: docker-compose -f ".github/workflows/nacos/docker-compose.yml" down run: docker-compose -f ".github/workflows/docker-compose.yml" down
- name: Report Coverage - name: Report Coverage
uses: codecov/codecov-action@v3 uses: codecov/codecov-action@v2
with: with:
flags: go-${{ matrix.go-version }}-${{ matrix.goarch }} flags: go-${{ matrix.go }}-${{ matrix.goarch }}

View File

@ -1,50 +0,0 @@
# Tencent is pleased to support the open source community by making Polaris available.
#
# Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
#
# Licensed under the BSD 3-Clause License (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://opensource.org/licenses/BSD-3-Clause
#
# Unless required by applicable law or agreed to in writing, software distributed
# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
# CONDITIONS OF ANY KIND, either express or implied. See the License for the
# specific language governing permissions and limitations under the License.
name: GolangCI-Lint
on:
push:
branches:
- master
- develop
- personal/**
- feature/**
- enhance/**
- fix/**
pull_request:
branches:
- master
- develop
- personal/**
- feature/**
- enhance/**
- fix/**
jobs:
golangci:
strategy:
matrix:
go-version: [1.15.x,1.16.x,1.17.x,1.18.x]
name: golangci-lint
runs-on: ubuntu-latest
steps:
- uses: actions/setup-go@v3
- uses: actions/checkout@v3
- name: golangci-lint
uses: golangci/golangci-lint-action@v3.3.0
with:
# Required: the version of golangci-lint is required and must be specified without patch version: we always use the latest patch version.
version: latest
args: --timeout 3m0s

View File

@ -1,28 +0,0 @@
# 规则描述每天凌晨3点(GMT+8)执行一次将最近7天没有活跃且非BUG的ISSUE设置标签:inactive
name: Issue Check Inactive
on:
schedule:
- cron: "0 19 * * *"
env: # 设置环境变量
TZ: Asia/Shanghai #时区(设置时区可使页面中的`最近更新时间`使用时区时间)
permissions:
contents: read
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
runs-on: ubuntu-latest
steps:
- name: check-inactive
uses: actions-cool/issues-helper@v3
with:
actions: 'check-inactive'
inactive-label: 'inactive'
inactive-day: 7
issue-state: open
exclude-labels: 'bug,planned,$exclude-empty'

View File

@ -1,23 +0,0 @@
# 规则描述每天凌晨4点(GMT+8)执行一次将最近30天没有活跃且非BUG的ISSUE关闭
name: Issue Close Inactive
on:
schedule:
- cron: "0 20 * * *"
env: # 设置环境变量
TZ: Asia/Shanghai #时区(设置时区可使页面中的`最近更新时间`使用时区时间)
jobs:
close-issues:
runs-on: ubuntu-latest
steps:
- name: need close
uses: actions-cool/issues-helper@v3
with:
actions: "close-issues"
# token: ${{ secrets.GF_TOKEN }}
labels: 'inactive'
inactive-day: 30
exclude-labels: 'bug,$exclude-empty'
close-reason: 'not active'

View File

@ -1,25 +0,0 @@
## 规则描述当issue被标记为help wanted 时,增加评论
name: Issue Labeled
on:
issues:
types: [labeled]
env: # 设置环境变量
TZ: Asia/Shanghai # 时区(设置时区可使页面中的`最近更新时间`使用时区时间)
jobs:
reply-labeled:
runs-on: ubuntu-latest
steps:
- name: contribution welcome
if: github.event.label.name == 'help wanted'
uses: actions-cool/issues-helper@v3
with:
actions: "create-comment, remove-labels"
# token: ${{ secrets.GF_TOKEN }}
issue-number: ${{ github.event.issue.number }}
body: |
Hello @${{ github.event.issue.user.login }}. We like your proposal/feedback and would appreciate a contribution via a Pull Request by you or another community member. We thank you in advance for your contribution and are looking forward to reviewing it!
你好 @${{ github.event.issue.user.login }}。我们喜欢您的提案/反馈,并希望您或其他社区成员通过拉取请求做出贡献。我们提前感谢您的贡献,并期待对其进行审查。

View File

@ -1,29 +0,0 @@
# 规则描述在issue没有活跃且尚未被关闭期间若issue作者更新或评论该ISSUE则移除其inactive标签
name: Issue Remove Inactive
on:
issues:
types: [edited]
issue_comment:
types: [created, edited]
env: # 设置环境变量
TZ: Asia/Shanghai #时区(设置时区可使页面中的`最近更新时间`使用时区时间)
permissions:
contents: read
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
runs-on: ubuntu-latest
steps:
- name: remove inactive
if: github.event.issue.state == 'open' && github.actor == github.event.issue.user.login
uses: actions-cool/issues-helper@v3
with:
actions: 'remove-labels'
issue-number: ${{ github.event.issue.number }}
labels: 'inactive'

View File

@ -1,29 +0,0 @@
# 规则描述将需要提供更多细节且暂未关闭的issue在issue作者评论后移除 need more details 标签
name: Issue Remove Need More Details
on:
issues:
types: [edited]
issue_comment:
types: [created, edited]
env: # 设置环境变量
TZ: Asia/Shanghai #时区(设置时区可使页面中的`最近更新时间`使用时区时间)
permissions:
contents: read
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
runs-on: ubuntu-latest
steps:
- name: remove need more details
if: github.event.issue.state == 'open' && github.actor == github.event.issue.user.login
uses: actions-cool/issues-helper@v3
with:
actions: 'remove-labels'
issue-number: ${{ github.event.issue.number }}
labels: 'need more details'

View File

@ -1,40 +0,0 @@
version: "3.8"
services:
nacos:
image: loads/nacos-server:v2.1.2
container_name: nacos
env_file:
- ./env/nacos.env
ports:
- "8848:8848"
- "9848:9848"
- "9555:9555"
healthcheck:
test: [ "CMD", "curl" ,"http://localhost:8848/nacos" ]
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
depends_on:
nacos:
condition: service_healthy
command: [ "sh", "-c", "curl -X POST 'http://nacos:8848/nacos/v1/cs/configs?dataId=config.toml&group=test&content=%5Bserver%5D%0A%09address%3D%22%3A8000%22'" ]

View File

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

View File

@ -1,9 +0,0 @@
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"]

5
.gitignore vendored
View File

@ -7,12 +7,13 @@
.settings/ .settings/
.vscode/ .vscode/
vendor/ vendor/
composer.lock
gitpush.sh
pkg/ pkg/
bin/ bin/
cbuild
**/.DS_Store **/.DS_Store
.test/ .test/
cmd/gf/main cmd/gf/main
cmd/gf/gf cmd/gf/gf
go.work go.work
go.work.sum
temp/

View File

@ -2,56 +2,31 @@
## with their default values. ## with their default values.
# See https://github.com/golangci/golangci-lint#config-file # See https://github.com/golangci/golangci-lint#config-file
# See https://golangci-lint.run/usage/configuration/
# Options for analysis running.
run: run:
# Exit code when at least one issue was found. issues-exit-code: 1 #Default
# Default: 1 tests: true #Default
issues-exit-code: 2
# Include test files or not.
# Default: true
tests: false
# Which dirs to skip: issues from them won't be reported.
# Can use regexp here: `generated.*`, regexp is applied on full path.
# Default value is empty list,
# but default dirs are skipped independently of this option's value (see skip-dirs-use-default).
# "/" will be replaced by current OS file path separator to properly work on Windows.
skip-dirs: []
# Which files to skip: they will be analyzed, but issues from them won't be reported.
# Default value is empty list,
# but there is no need to include all autogenerated files,
# we confidently recognize autogenerated files.
# If it's not please let us know.
# "/" will be replaced by current OS file path separator to properly work on Windows.
skip-files: []
# Main linters configurations.
# See https://golangci-lint.run/usage/linters
linters: linters:
# Disable all default enabled linters. # Disable everything by default so upgrades to not include new "default
# enabled" linters.
disable-all: true disable-all: true
# Custom enable linters we want to use. # Specifically enable linters we want to use.
enable: enable:
- errcheck # Errcheck is a program for checking for unchecked errors in go programs. - deadcode
- errchkjson # Checks types passed to the json encoding functions. Reports unsupported types and optionally reports occasions, where the check for the returned error can be omitted. - errcheck
- funlen # Tool for detection of long functions - gofmt
- goconst # Finds repeated strings that could be replaced by a constant - goimports
- gocritic # Provides diagnostics that check for bugs, performance and style issues. - gosimple
- gofmt # Gofmt checks whether code was gofmt-ed. By default this tool runs with -s option to check for code simplification - govet
- gosimple # Linter for Go source code that specializes in simplifying code - godot
- govet # Vet examines Go source code and reports suspicious constructs, such as Printf calls whose arguments do not align with the format string - ineffassign
- misspell # Finds commonly misspelled English words in comments - misspell
- nolintlint # Reports ill-formed or insufficient nolint directives - revive
- revive # Fast, configurable, extensible, flexible, and beautiful linter for Go. Drop-in replacement of golint. - staticcheck
- staticcheck # It's a set of rules from staticcheck. It's not the same thing as the staticcheck binary. - structcheck
- typecheck # Like the front-end of a Go compiler, parses and type-checks Go code - typecheck
- usestdlibvars # A linter that detect the possibility to use variables/constants from the Go standard library. - unused
- whitespace # Tool for detection of leading and trailing whitespace - varcheck
issues: issues:
@ -66,217 +41,26 @@ issues:
text: "exported func.*returns unexported type.*which can be annoying to use" text: "exported func.*returns unexported type.*which can be annoying to use"
linters: linters:
- revive - revive
# https://github.com/go-critic/go-critic/issues/926
- linters:
- gocritic
text: "unnecessaryDefer:"
# https://golangci-lint.run/usage/linters
linters-settings: linters-settings:
# https://golangci-lint.run/usage/linters/#misspell
misspell: misspell:
locale: US locale: US
ignore-words: ignore-words:
- cancelled - cancelled
goimports:
# https://golangci-lint.run/usage/linters/#revive local-prefixes: github.com/gogf/gf
# https://github.com/mgechev/revive/blob/master/RULES_DESCRIPTIONS.md godot:
revive: # Comments to be checked: `declarations`, `toplevel`, or `all`.
ignore-generated-header: true # Default: declarations
severity: error scope: toplevel
rules: exclude:
- name: atomic # Exclude sentence fragments for lists.
- name: line-length-limit - '^[ ]*[-•]'
severity: error # Exclude sentences prefixing a list.
arguments: [ 380 ] - ':$'
- name: unhandled-error # Check that each sentence ends with a period.
severity: warning
disabled: true
arguments: []
- name: var-naming
severity: warning
disabled: true
arguments:
# AllowList
- [ "ID","URL","IP","HTTP","JSON","API","UID","Id","Api","Uid","Http","Json","Ip","Url" ]
# DenyList
- [ "VM" ]
- name: string-format
severity: warning
disabled: false
arguments:
- - 'core.WriteError[1].Message'
- '/^([^A-Z]|$)/'
- must not start with a capital letter
- - 'fmt.Errorf[0]'
- '/(^|[^\.!?])$/'
- must not end in punctuation
- - panic
- '/^[^\n]*$/'
- must not contain line breaks
- name: function-result-limit
severity: warning
disabled: false
arguments: [ 4 ]
# https://golangci-lint.run/usage/linters/#funlen
funlen:
# Checks the number of lines in a function.
# If lower than 0, disable the check.
# Default: 60
lines: 330
# Checks the number of statements in a function.
# If lower than 0, disable the check.
# Default: 40
statements: -1
# https://golangci-lint.run/usage/linters/#goconst
goconst:
# Minimal length of string constant.
# Default: 3
min-len: 2
# Minimum occurrences of constant string count to trigger issue.
# Default: 3
# For subsequent optimization, the value is reduced.
min-occurrences: 30
# Ignore test files.
# Default: false
ignore-tests: true
# Look for existing constants matching the values.
# Default: true # Default: true
match-constant: false period: false
# Search also for duplicated numbers. # Check that each sentence starts with a capital letter.
# Default: false # Default: false
numbers: true capital: false
# Minimum value, only works with goconst.numbers
# Default: 3
min: 5
# Maximum value, only works with goconst.numbers
# Default: 3
max: 20
# Ignore when constant is not used as function argument.
# Default: true
ignore-calls: false
# https://golangci-lint.run/usage/linters/#gocritic
gocritic:
disabled-checks:
- ifElseChain
- assignOp
- appendAssign
- singleCaseSwitch
- regexpMust
- typeSwitchVar
- elseif
# https://golangci-lint.run/usage/linters/#gosimple
gosimple:
# Select the Go version to target.
# Default: 1.13
# Deprecated: use the global `run.go` instead.
go: "1.15"
# Sxxxx checks in https://staticcheck.io/docs/configuration/options/#checks
# Default: ["*"]
checks: [
"all", "-S1000", "-S1001", "-S1002", "-S1008", "-S1009", "-S1016", "-S1023", "-S1025", "-S1029", "-S1034", "-S1040"
]
# https://golangci-lint.run/usage/linters/#govet
govet:
# Report about shadowed variables.
# Default: false
check-shadowing: true
# Settings per analyzer.
settings:
# Analyzer name, run `go tool vet help` to see all analyzers.
printf:
# Comma-separated list of print function names to check (in addition to default, see `go tool vet help printf`).
# Default: []
funcs:
- (github.com/golangci/golangci-lint/pkg/logutils.Log).Infof
- (github.com/golangci/golangci-lint/pkg/logutils.Log).Warnf
- (github.com/golangci/golangci-lint/pkg/logutils.Log).Errorf
- (github.com/golangci/golangci-lint/pkg/logutils.Log).Fatalf
# shadow:
# Whether to be strict about shadowing; can be noisy.
# Default: false
# strict: false
unusedresult:
# Comma-separated list of functions whose results must be used
# (in addition to defaults context.WithCancel,context.WithDeadline,context.WithTimeout,context.WithValue,
# errors.New,fmt.Errorf,fmt.Sprint,fmt.Sprintf,sort.Reverse)
# Default []
funcs:
- pkg.MyFunc
- context.WithCancel
# Comma-separated list of names of methods of type func() string whose results must be used
# (in addition to default Error,String)
# Default []
stringmethods:
- MyMethod
# Enable all analyzers.
# Default: false
enable-all: true
# Disable analyzers by name.
# Run `go tool vet help` to see all analyzers.
# Default: []
disable:
- asmdecl
- assign
- atomic
- atomicalign
- bools
- buildtag
- cgocall
- composites
- copylocks
- deepequalerrors
- errorsas
- fieldalignment
- findcall
- framepointer
- httpresponse
- ifaceassert
- loopclosure
- lostcancel
- nilfunc
- nilness
- reflectvaluecompare
- shift
- shadow
- sigchanyzer
- sortslice
- stdmethods
- stringintconv
- structtag
- testinggoroutine
- tests
- unmarshal
- unreachable
- unsafeptr
- unusedwrite
# https://golangci-lint.run/usage/linters/#staticcheck
staticcheck:
# Select the Go version to target.
# Default: "1.13"
# Deprecated: use the global `run.go` instead.
go: "1.15"
# SAxxxx checks in https://staticcheck.io/docs/configuration/options/#checks
# Default: ["*"]
checks: [ "all","-SA1019","-SA4015","-SA1029","-SA1016","-SA9003","-SA4006","-SA6003" ]
# https://golangci-lint.run/usage/linters/#gofmt
gofmt:
# Simplify code: gofmt with `-s` option.
# Default: true
simplify: true
# Apply the rewrite rules to the source before reformatting.
# https://pkg.go.dev/cmd/gofmt
# Default: []
rewrite-rules: [ ]
# - pattern: 'interface{}'
# replacement: 'any'
# - pattern: 'a[b:len(a)]'
# replacement: 'a[b:]'

View File

@ -11,6 +11,3 @@ tidy:
cd -; \ cd -; \
done done
.PHONY: lint
lint:
golangci-lint run

View File

@ -53,7 +53,7 @@ golang version >= 1.15
# Documentation # Documentation
* Chinese Official Site(中文官网): [https://goframe.org](https://goframe.org/display/gf) * Chinese Official Site(中文官网): [https://goframe.org](https://goframe.org/display/gf)
* GoDoc API: [https://pkg.go.dev/github.com/gogf/gf/v2](https://pkg.go.dev/github.com/gogf/gf/v2) * GoDoc API: [https://pkg.go.dev/github.com/gogf/gf](https://pkg.go.dev/github.com/gogf/gf)
# License # License

View File

@ -1,58 +1,20 @@
module github.com/gogf/gf/cmd/gf/v2 module github.com/gogf/gf/cmd/gf/v2
go 1.18 go 1.15
require ( require (
github.com/gogf/gf/contrib/drivers/mssql/v2 v2.1.0 github.com/gogf/gf/contrib/drivers/mssql/v2 v2.1.0
github.com/gogf/gf/contrib/drivers/mysql/v2 v2.1.0 github.com/gogf/gf/contrib/drivers/mysql/v2 v2.1.0
github.com/gogf/gf/contrib/drivers/oracle/v2 v2.1.0
github.com/gogf/gf/contrib/drivers/pgsql/v2 v2.1.0 github.com/gogf/gf/contrib/drivers/pgsql/v2 v2.1.0
github.com/gogf/gf/contrib/drivers/sqlite/v2 v2.1.0 github.com/gogf/gf/contrib/drivers/sqlite/v2 v2.1.0
github.com/gogf/gf/v2 v2.2.2 github.com/gogf/gf/v2 v2.1.0
github.com/olekukonko/tablewriter v0.0.5 github.com/olekukonko/tablewriter v0.0.5
golang.org/x/tools v0.2.0 golang.org/x/tools v0.1.11
)
require (
github.com/BurntSushi/toml v1.2.1 // 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/go-logr/stdr v1.2.2 // indirect
github.com/go-sql-driver/mysql v1.6.0 // indirect
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe // 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/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 // indirect
github.com/sijms/go-ora/v2 v2.4.20 // indirect
go.opentelemetry.io/otel v1.7.0 // indirect
go.opentelemetry.io/otel/sdk v1.7.0 // indirect
go.opentelemetry.io/otel/trace v1.7.0 // indirect
golang.org/x/crypto v0.1.0 // indirect
golang.org/x/mod v0.6.0 // indirect
golang.org/x/net v0.1.0 // indirect
golang.org/x/sys v0.1.0 // indirect
golang.org/x/text v0.4.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 ( replace (
github.com/gogf/gf/contrib/drivers/mssql/v2 => ../../contrib/drivers/mssql/ 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/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/pgsql/v2 => ../../contrib/drivers/pgsql/
github.com/gogf/gf/contrib/drivers/sqlite/v2 => ../../contrib/drivers/sqlite/ github.com/gogf/gf/contrib/drivers/sqlite/v2 => ../../contrib/drivers/sqlite/
github.com/gogf/gf/v2 => ../../ github.com/gogf/gf/v2 => ../../

View File

@ -1,15 +1,24 @@
github.com/BurntSushi/toml v1.1.0 h1:ksErzDEI1khOiGPgpwuI7x2ebx/uXQNw7xJpn9Eq1+I=
github.com/BurntSushi/toml v1.1.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/toml v1.1.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak= github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/clbanning/mxj/v2 v2.5.5 h1:oT81vUeEiQQ/DcHbzSytRngP6Ky9O+L+0Bw0zSJag9E= 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.5.5/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn/Qo+ve2s=
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/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/denisenkom/go-mssqldb v0.11.0 h1:9rHa233rhdOyrz2GcP9NM+gi2psgJZ4GWDpL/7ND8HI= 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/denisenkom/go-mssqldb v0.11.0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= 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 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w=
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI= github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI=
github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= 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 h1:Rji9ROVSTTfjuWD6j5B+8DtkNvPILoUC3xRhkQzGxvk=
@ -19,19 +28,39 @@ 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.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI=
github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo=
github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= 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.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY= 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/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 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 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.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= 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/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 h1:0fThFwLbW7P/kOiTBs03FsJSV9RM2M/Q/MOnCQxKMo0=
github.com/grokify/html-strip-tags-go v0.0.1/go.mod h1:2Su6romC5/1VXOQMaWL2yb618ARB8iVo6/DR99A6d78= github.com/grokify/html-strip-tags-go v0.0.1/go.mod h1:2Su6romC5/1VXOQMaWL2yb618ARB8iVo6/DR99A6d78=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
github.com/lib/pq v1.10.4 h1:SO9z7FRPzA03QhHKJrH5BXA6HU1rS4V2nIVrrNC1iYk= github.com/lib/pq v1.10.4 h1:SO9z7FRPzA03QhHKJrH5BXA6HU1rS4V2nIVrrNC1iYk=
github.com/lib/pq v1.10.4/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lib/pq v1.10.4/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
@ -45,19 +74,34 @@ github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27k
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/mattn/go-sqlite3 v1.14.12/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/mattn/go-sqlite3 v1.14.12/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
github.com/onsi/ginkgo/v2 v2.0.0 h1:CcuG/HvWNkkaqCUpJifQY8z7qEMBJya6aLPx6ftGyjQ=
github.com/onsi/ginkgo/v2 v2.0.0/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c=
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE=
github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6OkFY5QxjkYwrChwuRruF69c169dPK26NUlk= 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-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
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/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/yuin/goldmark v1.2.1/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/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
go.opentelemetry.io/otel v1.7.0 h1:Z2lA3Tdch0iDcrhJXDIlC94XE+bxok1F9B+4Lz/lGsM= 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 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 h1:4OmStpcKVOfvDOgCt7UriAPtKolwIhxpnSNI/yK+1B0=
@ -68,60 +112,92 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/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-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.1.0 h1:MDRAIl0xIo9Io2xV565hzXHw3zVseKrJKodhohM5CjU= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 h1:7I4JAnoQBe7ZtJcBaYHi5UtiO8tQHbUSXxL+pnGRANg=
golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0 h1:b9gGHsz9/HhJ3HF5DHQytPpuwocVTChQJK3AvoLRD5I= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 h1:CIJ76btIcR3eFI5EgSo6k1qKw9KJexJuRLI9G7Hp5wE=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.1.0 h1:hZ/3BUoy5aId7sCpA/Tc5lt8DkFgdVS2onTpJsZ/fl0= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/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-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/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-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-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-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-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/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-20220405052023-b1e9470b6e64/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad h1:ntjMns5wyP/fN65tdBD4g8J5w8n015+iIIs9rtjXkY0=
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 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.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.3.8-0.20211105212822-18b340fc7af2 h1:GLw7MR8AfAG2GmGcmVgObFOHXYypgGjnGno25RDwn3Y=
golang.org/x/text v0.3.8-0.20211105212822-18b340fc7af2/go.mod h1:EFNZuWvGYxIRUEX+K8UmCFwYmZjqcrnq15ZuVldZkZ0= golang.org/x/text v0.3.8-0.20211105212822-18b340fc7af2/go.mod h1:EFNZuWvGYxIRUEX+K8UmCFwYmZjqcrnq15ZuVldZkZ0=
golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg=
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo=
golang.org/x/tools v0.2.0 h1:G6AHpWxTMGY1KyEYoAQ5WTtIekUUvDNjan3ugu60JvE= golang.org/x/tools v0.1.11 h1:loJ25fNOEhSXfHrpoGj91eCUThwdNX6u24rO1xnNteY=
golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA= golang.org/x/tools v0.1.11/go.mod h1:SgwaegtQh8clINPpECJMqnxLv9I09HLqnW3RMqW0CA4=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/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= 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/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-20220428102840-41399a37e894/go.mod h1:eI31LL8EwEBKPpNpA4bU1/i+sKOwOrQy8D87zWUcRZc=

View File

@ -4,12 +4,11 @@ import (
"context" "context"
"strings" "strings"
"github.com/gogf/gf/cmd/gf/v2/internal/service"
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
"github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gcmd" "github.com/gogf/gf/v2/os/gcmd"
"github.com/gogf/gf/v2/util/gtag" "github.com/gogf/gf/v2/util/gtag"
"github.com/gogf/gf/cmd/gf/v2/internal/service"
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
) )
var ( var (
@ -39,7 +38,6 @@ type cGFInput struct {
Version bool `short:"v" name:"version" brief:"show version information of current binary" orphan:"true"` Version bool `short:"v" name:"version" brief:"show version information of current binary" orphan:"true"`
Debug bool `short:"d" name:"debug" brief:"show internal detailed debugging information" orphan:"true"` Debug bool `short:"d" name:"debug" brief:"show internal detailed debugging information" orphan:"true"`
} }
type cGFOutput struct{} type cGFOutput struct{}
func (c cGF) Index(ctx context.Context, in cGFInput) (out *cGFOutput, err error) { func (c cGF) Index(ctx context.Context, in cGFInput) (out *cGFOutput, err error) {

View File

@ -9,6 +9,7 @@ import (
"runtime" "runtime"
"strings" "strings"
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
"github.com/gogf/gf/v2/encoding/gbase64" "github.com/gogf/gf/v2/encoding/gbase64"
"github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gcmd" "github.com/gogf/gf/v2/os/gcmd"
@ -19,8 +20,6 @@ import (
"github.com/gogf/gf/v2/text/gregex" "github.com/gogf/gf/v2/text/gregex"
"github.com/gogf/gf/v2/text/gstr" "github.com/gogf/gf/v2/text/gstr"
"github.com/gogf/gf/v2/util/gtag" "github.com/gogf/gf/v2/util/gtag"
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
) )
var ( var (
@ -125,13 +124,9 @@ type cBuildInput struct {
PackDst string `short:"pd" name:"packDst" brief:"temporary go file path for pack, this go file will be automatically removed after built" d:"internal/packed/build_pack_data.go"` PackDst string `short:"pd" name:"packDst" brief:"temporary go file path for pack, this go file will be automatically removed after built" d:"internal/packed/build_pack_data.go"`
ExitWhenError bool `short:"ew" name:"exitWhenError" brief:"exit building when any error occurs, default is false" orphan:"true"` ExitWhenError bool `short:"ew" name:"exitWhenError" brief:"exit building when any error occurs, default is false" orphan:"true"`
} }
type cBuildOutput struct{} type cBuildOutput struct{}
func (c cBuild) Index(ctx context.Context, in cBuildInput) (out *cBuildOutput, err error) { func (c cBuild) Index(ctx context.Context, in cBuildInput) (out *cBuildOutput, err error) {
// print used go env
_, _ = Env.Index(ctx, cEnvInput{})
mlog.SetHeaderPrint(true) mlog.SetHeaderPrint(true)
mlog.Debugf(`build input: %+v`, in) mlog.Debugf(`build input: %+v`, in)
@ -209,9 +204,7 @@ func (c cBuild) Index(ctx context.Context, in cBuildInput) (out *cBuildOutput, e
mlog.Printf(`remove the automatically generated resource go file: %s`, in.PackDst) mlog.Printf(`remove the automatically generated resource go file: %s`, in.PackDst)
}() }()
} }
// remove black space in separator. packCmd := fmt.Sprintf(`gf pack %s %s`, in.PackSrc, in.PackDst)
in.PackSrc, _ = gregex.ReplaceString(`,\s+`, `,`, in.PackSrc)
packCmd := fmt.Sprintf(`gf pack %s %s --keepPath=true`, in.PackSrc, in.PackDst)
mlog.Print(packCmd) mlog.Print(packCmd)
gproc.MustShellRun(ctx, packCmd) gproc.MustShellRun(ctx, packCmd)
} }

View File

@ -5,13 +5,12 @@ import (
"fmt" "fmt"
"runtime" "runtime"
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
"github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gfile" "github.com/gogf/gf/v2/os/gfile"
"github.com/gogf/gf/v2/os/gproc" "github.com/gogf/gf/v2/os/gproc"
"github.com/gogf/gf/v2/text/gstr" "github.com/gogf/gf/v2/text/gstr"
"github.com/gogf/gf/v2/util/gtag" "github.com/gogf/gf/v2/util/gtag"
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
) )
var ( var (
@ -33,7 +32,6 @@ gf docker main.go
gf docker main.go -t hub.docker.com/john/image:tag gf docker main.go -t hub.docker.com/john/image:tag
gf docker main.go -t hub.docker.com/john/image:tag gf docker main.go -t hub.docker.com/john/image:tag
gf docker main.go -p -t hub.docker.com/john/image:tag gf docker main.go -p -t hub.docker.com/john/image:tag
gf docker main.go -p -tp ["hub.docker.com/john","hub.docker.com/smith"] -tn image:tag
` `
cDockerDc = ` cDockerDc = `
The "docker" command builds the GF project to a docker images. The "docker" command builds the GF project to a docker images.
@ -46,7 +44,6 @@ You should have docker installed, and there must be a Dockerfile in the root of
cDockerFileBrief = `file path of the Dockerfile. it's "manifest/docker/Dockerfile" in default` cDockerFileBrief = `file path of the Dockerfile. it's "manifest/docker/Dockerfile" in default`
cDockerShellBrief = `path of the shell file which is executed before docker build` cDockerShellBrief = `path of the shell file which is executed before docker build`
cDockerPushBrief = `auto push the docker image to docker registry if "-t" option passed` cDockerPushBrief = `auto push the docker image to docker registry if "-t" option passed`
cDockerTagBrief = `full tag for this docker, pattern like "xxx.xxx.xxx/image:tag"`
cDockerTagNameBrief = `tag name for this docker, pattern like "image:tag". this option is required with TagPrefixes` cDockerTagNameBrief = `tag name for this docker, pattern like "image:tag". this option is required with TagPrefixes`
cDockerTagPrefixesBrief = `tag prefixes for this docker, which are used for docker push. this option is required with TagName` cDockerTagPrefixesBrief = `tag prefixes for this docker, which are used for docker push. this option is required with TagName`
cDockerExtraBrief = `extra build options passed to "docker image"` cDockerExtraBrief = `extra build options passed to "docker image"`
@ -63,7 +60,6 @@ func init() {
`cDockerShellBrief`: cDockerShellBrief, `cDockerShellBrief`: cDockerShellBrief,
`cDockerBuildBrief`: cDockerBuildBrief, `cDockerBuildBrief`: cDockerBuildBrief,
`cDockerPushBrief`: cDockerPushBrief, `cDockerPushBrief`: cDockerPushBrief,
`cDockerTagBrief`: cDockerTagBrief,
`cDockerTagNameBrief`: cDockerTagNameBrief, `cDockerTagNameBrief`: cDockerTagNameBrief,
`cDockerTagPrefixesBrief`: cDockerTagPrefixesBrief, `cDockerTagPrefixesBrief`: cDockerTagPrefixesBrief,
`cDockerExtraBrief`: cDockerExtraBrief, `cDockerExtraBrief`: cDockerExtraBrief,
@ -76,13 +72,11 @@ type cDockerInput struct {
File string `name:"file" short:"f" brief:"{cDockerFileBrief}" d:"manifest/docker/Dockerfile"` File string `name:"file" short:"f" brief:"{cDockerFileBrief}" d:"manifest/docker/Dockerfile"`
Shell string `name:"shell" short:"s" brief:"{cDockerShellBrief}" d:"manifest/docker/docker.sh"` Shell string `name:"shell" short:"s" brief:"{cDockerShellBrief}" d:"manifest/docker/docker.sh"`
Build string `name:"build" short:"b" brief:"{cDockerBuildBrief}" d:"-a amd64 -s linux"` Build string `name:"build" short:"b" brief:"{cDockerBuildBrief}" d:"-a amd64 -s linux"`
Tag string `name:"tag" short:"t" brief:"{cDockerTagBrief}"`
TagName string `name:"tagName" short:"tn" brief:"{cDockerTagNameBrief}" v:"required-with:TagPrefixes"` TagName string `name:"tagName" short:"tn" brief:"{cDockerTagNameBrief}" v:"required-with:TagPrefixes"`
TagPrefixes []string `name:"tagPrefixes" short:"tp" brief:"{cDockerTagPrefixesBrief}" v:"required-with:TagName"` TagPrefixes []string `name:"tagPrefixes" short:"tp" brief:"{cDockerTagPrefixesBrief}" v:"required-with:TagName"`
Push bool `name:"push" short:"p" brief:"{cDockerPushBrief}" orphan:"true"` Push bool `name:"push" short:"p" brief:"{cDockerPushBrief}" orphan:"true"`
Extra string `name:"extra" short:"e" brief:"{cDockerExtraBrief}"` Extra string `name:"extra" short:"e" brief:"{cDockerExtraBrief}"`
} }
type cDockerOutput struct{} type cDockerOutput struct{}
func (c cDocker) Index(ctx context.Context, in cDockerInput) (out *cDockerOutput, err error) { func (c cDocker) Index(ctx context.Context, in cDockerInput) (out *cDockerOutput, err error) {
@ -118,7 +112,7 @@ func (c cDocker) Index(ctx context.Context, in cDockerInput) (out *cDockerOutput
} }
} }
if len(dockerTags) == 0 { if len(dockerTags) == 0 {
dockerTags = []string{in.Tag} dockerTags = []string{""}
} }
for i, dockerTag := range dockerTags { for i, dockerTag := range dockerTags {
if i > 0 { if i > 0 {

View File

@ -4,13 +4,12 @@ import (
"bytes" "bytes"
"context" "context"
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
"github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gproc" "github.com/gogf/gf/v2/os/gproc"
"github.com/gogf/gf/v2/text/gregex" "github.com/gogf/gf/v2/text/gregex"
"github.com/gogf/gf/v2/text/gstr" "github.com/gogf/gf/v2/text/gstr"
"github.com/olekukonko/tablewriter" "github.com/olekukonko/tablewriter"
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
) )
var ( var (
@ -24,7 +23,6 @@ type cEnv struct {
type cEnvInput struct { type cEnvInput struct {
g.Meta `name:"env"` g.Meta `name:"env"`
} }
type cEnvOutput struct{} type cEnvOutput struct{}
func (c cEnv) Index(ctx context.Context, in cEnvInput) (out *cEnvOutput, err error) { func (c cEnv) Index(ctx context.Context, in cEnvInput) (out *cEnvOutput, err error) {

View File

@ -1,121 +0,0 @@
package cmd
import (
"context"
"github.com/gogf/gf/v2/os/gproc"
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gfile"
"github.com/gogf/gf/v2/text/gstr"
)
var (
Fix = cFix{}
)
type cFix struct {
g.Meta `name:"fix" brief:"auto fixing codes after upgrading to new GoFrame version" usage:"gf fix" `
}
type cFixInput struct {
g.Meta `name:"fix"`
Path string `name:"path" short:"p" brief:"directory path, it uses current working directory in default"`
Version string `name:"version" short:"v" brief:"custom specified version to fix, leave it empty to auto detect"`
}
type cFixOutput struct{}
type cFixItem struct {
Version string
Func func(version string) error
}
func (c cFix) Index(ctx context.Context, in cFixInput) (out *cFixOutput, err error) {
if in.Path == "" {
in.Path = gfile.Pwd()
}
if in.Version == "" {
in.Version, err = c.autoDetectVersion(in)
if err != nil {
mlog.Fatal(err)
}
if in.Version == "" {
mlog.Print(`no GoFrame usage found, exit fixing`)
return
}
mlog.Debugf(`current GoFrame version auto detect "%s"`, in.Version)
}
if !gproc.IsChild() {
mlog.Printf(`start auto fixing directory path "%s"...`, in.Path)
defer mlog.Print(`done!`)
}
err = c.doFix(in)
return
}
func (c cFix) doFix(in cFixInput) (err error) {
var items = []cFixItem{
{Version: "v2.3", Func: c.doFixV23},
}
for _, item := range items {
if gstr.CompareVersionGo(in.Version, item.Version) < 0 {
mlog.Debugf(
`current GoFrame or contrib package version "%s" is lesser than "%s", nothing to do`,
in.Version, item.Version,
)
continue
}
if err = item.Func(in.Version); err != nil {
return
}
}
return
}
// doFixV23 fixes code when upgrading to GoFrame v2.3.
func (c cFix) doFixV23(version string) error {
replaceFunc := func(path, content string) string {
// gdb.TX from struct to interface.
content = gstr.Replace(content, "*gdb.TX", "gdb.TX")
// function name changes for package gtcp/gudp.
if gstr.Contains(content, "/gf/v2/net/gtcp") || gstr.Contains(content, "/gf/v2/net/gudp") {
content = gstr.ReplaceByMap(content, g.MapStrStr{
".SetSendDeadline": ".SetDeadlineSend",
".SetReceiveDeadline": ".SetDeadlineRecv",
".SetReceiveBufferWait": ".SetBufferWaitRecv",
})
}
return content
}
return gfile.ReplaceDirFunc(replaceFunc, ".", "*.go", true)
}
func (c cFix) autoDetectVersion(in cFixInput) (string, error) {
var (
err error
path = gfile.Join(in.Path, "go.mod")
version string
)
if !gfile.Exists(path) {
return "", gerror.Newf(`"%s" not found in current working directory`, path)
}
err = gfile.ReadLines(path, func(line string) error {
array := gstr.SplitAndTrim(line, " ")
if len(array) > 0 {
if gstr.HasPrefix(array[0], gfPackage) {
version = array[1]
}
}
return nil
})
if err != nil {
mlog.Fatal(err)
}
return version, nil
}

View File

@ -3,9 +3,9 @@ package cmd
import ( import (
_ "github.com/gogf/gf/contrib/drivers/mssql/v2" _ "github.com/gogf/gf/contrib/drivers/mssql/v2"
_ "github.com/gogf/gf/contrib/drivers/mysql/v2" _ "github.com/gogf/gf/contrib/drivers/mysql/v2"
_ "github.com/gogf/gf/contrib/drivers/oracle/v2"
_ "github.com/gogf/gf/contrib/drivers/pgsql/v2" _ "github.com/gogf/gf/contrib/drivers/pgsql/v2"
_ "github.com/gogf/gf/contrib/drivers/sqlite/v2" _ "github.com/gogf/gf/contrib/drivers/sqlite/v2"
//_ "github.com/gogf/gf/contrib/drivers/oracle/v2"
"github.com/gogf/gf/cmd/gf/v2/internal/cmd/gendao" "github.com/gogf/gf/cmd/gf/v2/internal/cmd/gendao"
) )

View File

@ -6,6 +6,8 @@ import (
"fmt" "fmt"
"strings" "strings"
"github.com/gogf/gf/cmd/gf/v2/internal/consts"
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
"github.com/gogf/gf/v2/database/gdb" "github.com/gogf/gf/v2/database/gdb"
"github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gfile" "github.com/gogf/gf/v2/os/gfile"
@ -15,9 +17,6 @@ import (
"github.com/gogf/gf/v2/util/gconv" "github.com/gogf/gf/v2/util/gconv"
"github.com/gogf/gf/v2/util/gtag" "github.com/gogf/gf/v2/util/gtag"
"github.com/olekukonko/tablewriter" "github.com/olekukonko/tablewriter"
"github.com/gogf/gf/cmd/gf/v2/internal/consts"
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
) )
type ( type (

View File

@ -1,9 +1,441 @@
package cmd package cmd
import ( import (
"github.com/gogf/gf/cmd/gf/v2/internal/cmd/genservice" "context"
"fmt"
"go/parser"
"go/token"
"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/garray"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gfile"
"github.com/gogf/gf/v2/os/gproc"
"github.com/gogf/gf/v2/os/gtime"
"github.com/gogf/gf/v2/text/gregex"
"github.com/gogf/gf/v2/text/gstr"
"github.com/gogf/gf/v2/util/gconv"
"github.com/gogf/gf/v2/util/gtag"
) )
type ( const (
cGenService = genservice.CGenService cGenServiceConfig = `gfcli.gen.service`
cGenServiceUsage = `gf gen service [OPTION]`
cGenServiceBrief = `parse struct and associated functions from packages to generate service go file`
cGenServiceEg = `
gf gen service
gf gen service -f Snake
`
cGenServiceBriefSrcFolder = `source folder path to be parsed. default: internal/logic`
cGenServiceBriefDstFolder = `destination folder path storing automatically generated go files. default: internal/service`
cGenServiceBriefFileNameCase = `
destination file name storing automatically generated go files, cases are as follows:
| Case | Example |
|---------------- |--------------------|
| Lower | anykindofstring |
| Camel | AnyKindOfString |
| CamelLower | anyKindOfString |
| Snake | any_kind_of_string | default
| SnakeScreaming | ANY_KIND_OF_STRING |
| SnakeFirstUpper | rgb_code_md5 |
| Kebab | any-kind-of-string |
| KebabScreaming | ANY-KIND-OF-STRING |
`
cGenServiceBriefWatchFile = `used in file watcher, it generates service go files only if given file is under srcFolder`
cGenServiceBriefStPattern = `regular expression matching struct name for generating service. default: s([A-Z]\\\\w+)`
cGenServiceBriefPackages = `produce go files only for given source packages`
cGenServiceBriefImportPrefix = `custom import prefix to calculate import path for generated importing go file of logic`
cGenServiceBriefOverWrite = `overwrite service go files that already exist in generating folder. default: true`
) )
func init() {
gtag.Sets(g.MapStrStr{
`cGenServiceConfig`: cGenServiceConfig,
`cGenServiceUsage`: cGenServiceUsage,
`cGenServiceBrief`: cGenServiceBrief,
`cGenServiceEg`: cGenServiceEg,
`cGenServiceBriefSrcFolder`: cGenServiceBriefSrcFolder,
`cGenServiceBriefDstFolder`: cGenServiceBriefDstFolder,
`cGenServiceBriefFileNameCase`: cGenServiceBriefFileNameCase,
`cGenServiceBriefWatchFile`: cGenServiceBriefWatchFile,
`cGenServiceBriefStPattern`: cGenServiceBriefStPattern,
`cGenServiceBriefPackages`: cGenServiceBriefPackages,
`cGenServiceBriefImportPrefix`: cGenServiceBriefImportPrefix,
`cGenServiceBriefOverWrite`: cGenServiceBriefOverWrite,
})
}
type (
cGenService struct{}
cGenServiceInput struct {
g.Meta `name:"service" config:"{cGenServiceConfig}" usage:"{cGenServiceUsage}" brief:"{cGenServiceBrief}" eg:"{cGenServiceEg}"`
SrcFolder string `short:"s" name:"srcFolder" brief:"{cGenServiceBriefSrcFolder}" d:"internal/logic"`
DstFolder string `short:"d" name:"dstFolder" brief:"{cGenServiceBriefDstFolder}" d:"internal/service"`
DstFileNameCase string `short:"f" name:"dstFileNameCase" brief:"{cGenServiceBriefFileNameCase}" d:"Snake"`
WatchFile string `short:"w" name:"watchFile" brief:"{cGenServiceBriefWatchFile}"`
StPattern string `short:"a" name:"stPattern" brief:"{cGenServiceBriefStPattern}" d:"s([A-Z]\\w+)"`
Packages []string `short:"p" name:"packages" brief:"{cGenServiceBriefPackages}"`
ImportPrefix string `short:"i" name:"importPrefix" brief:"{cGenServiceBriefImportPrefix}"`
OverWrite bool `short:"o" name:"overwrite" brief:"{cGenServiceBriefOverWrite}" d:"true" orphan:"true"`
}
cGenServiceOutput struct{}
)
const (
genServiceFileLockSeconds = 10
)
func (c cGenService) Service(ctx context.Context, in cGenServiceInput) (out *cGenServiceOutput, err error) {
// File lock to avoid multiple processes.
var (
flockFilePath = gfile.Temp("gf.cli.gen.service.lock")
flockContent = gfile.GetContents(flockFilePath)
)
if flockContent != "" {
if gtime.Timestamp()-gconv.Int64(flockContent) < genServiceFileLockSeconds {
// If another "gen service" process is running, it just exits.
mlog.Debug(`another "gen service" process is running, exit`)
return
}
}
defer gfile.Remove(flockFilePath)
_ = gfile.PutContents(flockFilePath, gtime.TimestampStr())
in.SrcFolder = gstr.TrimRight(in.SrcFolder, `\/`)
in.SrcFolder = gstr.Replace(in.SrcFolder, "\\", "/")
in.WatchFile = gstr.TrimRight(in.WatchFile, `\/`)
in.WatchFile = gstr.Replace(in.WatchFile, "\\", "/")
// Watch file handling.
if in.WatchFile != "" {
// It works only if given WatchFile is in SrcFolder.
var (
watchFileDir = gfile.Dir(in.WatchFile)
srcFolderDir = gfile.Dir(watchFileDir)
)
mlog.Debug("watchFileDir:", watchFileDir)
mlog.Debug("logicFolderDir:", srcFolderDir)
if !gstr.HasSuffix(gstr.Replace(srcFolderDir, `\`, `/`), in.SrcFolder) {
mlog.Printf(`ignore watch file "%s", not in source path "%s"`, in.WatchFile, in.SrcFolder)
return
}
var newWorkingDir = gfile.Dir(gfile.Dir(srcFolderDir))
if err = gfile.Chdir(newWorkingDir); err != nil {
mlog.Fatalf(`%+v`, err)
}
mlog.Debug("Chdir:", newWorkingDir)
_ = gfile.Remove(flockFilePath)
var command = fmt.Sprintf(
`%s gen service -packages=%s`,
gfile.SelfName(), gfile.Basename(watchFileDir),
)
err = gproc.ShellRun(ctx, command)
return
}
if !gfile.Exists(in.SrcFolder) {
mlog.Fatalf(`source folder path "%s" does not exist`, in.SrcFolder)
}
if in.ImportPrefix == "" {
if !gfile.Exists("go.mod") {
mlog.Fatal("ImportPrefix is empty and go.mod does not exist in current working directory")
}
var (
goModContent = gfile.GetContents("go.mod")
match, _ = gregex.MatchString(`^module\s+(.+)\s*`, goModContent)
)
if len(match) > 1 {
in.ImportPrefix = fmt.Sprintf(`%s/%s`, gstr.Trim(match[1]), gstr.Replace(in.SrcFolder, `\`, `/`))
}
}
var (
isDirty bool
files []string
fileContent string
initImportSrcPackages []string
inputPackages = in.Packages
dstPackageName = gstr.ToLower(gfile.Basename(in.DstFolder))
)
srcFolders, err := gfile.ScanDir(in.SrcFolder, "*", false)
if err != nil {
return nil, err
}
for _, srcFolder := range srcFolders {
if !gfile.IsDir(srcFolder) {
continue
}
if files, err = gfile.ScanDir(srcFolder, "*.go", false); err != nil {
return nil, err
}
if len(files) == 0 {
continue
}
var (
// StructName => FunctionDefinitions
srcPkgInterfaceMap = make(map[string]*garray.StrArray)
srcImportedPackages = garray.NewSortedStrArray().SetUnique(true)
ok bool
)
for _, file := range files {
fileContent = gfile.GetContents(file)
// Calculate imported packages of source go files.
err = c.calculateImportedPackages(fileContent, srcImportedPackages)
if err != nil {
return nil, err
}
// Calculate functions and interfaces for service generating.
err = c.calculateInterfaceFunctions(in, fileContent, srcPkgInterfaceMap, dstPackageName)
if err != nil {
return nil, err
}
}
initImportSrcPackages = append(
initImportSrcPackages,
fmt.Sprintf(`%s/%s`, in.ImportPrefix, gfile.Basename(srcFolder)),
)
// Ignore source packages if input packages given.
if len(inputPackages) > 0 && !gstr.InArray(inputPackages, gfile.Basename(srcFolder)) {
mlog.Debugf(
`ignore source package "%s" as it is not in desired packages: %+v`,
gfile.Basename(srcFolder), inputPackages,
)
continue
}
// Generating go files for service.
if ok, err = c.generateServiceFiles(in, srcPkgInterfaceMap, srcImportedPackages.Slice(), dstPackageName); err != nil {
return
}
if ok {
isDirty = true
}
}
if isDirty {
// Generate initialization go file.
if len(initImportSrcPackages) > 0 {
if err = c.generateInitializationFile(in, initImportSrcPackages); err != nil {
return
}
}
// Replace v1 to v2 for GoFrame.
if err = c.replaceGeneratedServiceContentGFV2(in); err != nil {
return nil, err
}
mlog.Printf(`gofmt go files in "%s"`, in.DstFolder)
utils.GoFmt(in.DstFolder)
}
mlog.Print(`done!`)
return
}
func (c cGenService) calculateImportedPackages(fileContent string, srcImportedPackages *garray.SortedStrArray) (err error) {
f, err := parser.ParseFile(token.NewFileSet(), "", fileContent, parser.ImportsOnly)
if err != nil {
return err
}
for _, s := range f.Imports {
if s.Path != nil {
if s.Name != nil {
// has alias and is not `_`
if pkgAlias := s.Name.String(); pkgAlias != "_" {
srcImportedPackages.Add(pkgAlias + " " + s.Path.Value)
}
} else {
// no alias
srcImportedPackages.Add(s.Path.Value)
}
}
}
return nil
}
func (c cGenService) calculateInterfaceFunctions(
in cGenServiceInput, fileContent string, srcPkgInterfaceMap map[string]*garray.StrArray, dstPackageName string,
) (err error) {
var (
ok bool
matches [][]string
srcPkgInterfaceFuncArray *garray.StrArray
)
matches, err = gregex.MatchAllString(`func \((.+?)\) ([\s\S]+?) {`, fileContent)
if err != nil {
return err
}
for _, match := range matches {
var (
structName string
structMatch []string
funcReceiver = gstr.Trim(match[1])
receiverArray = gstr.SplitAndTrim(funcReceiver, " ")
functionHead = gstr.Trim(gstr.Replace(match[2], "\n", ""))
)
if len(receiverArray) > 1 {
structName = receiverArray[1]
} else {
structName = receiverArray[0]
}
structName = gstr.Trim(structName, "*")
// Xxx(\n ctx context.Context, req *v1.XxxReq,\n) -> Xxx(ctx context.Context, req *v1.XxxReq)
functionHead = gstr.Replace(functionHead, `,)`, `)`)
functionHead, _ = gregex.ReplaceString(`\(\s+`, `(`, functionHead)
functionHead, _ = gregex.ReplaceString(`\s{2,}`, ` `, functionHead)
if !gstr.IsLetterUpper(functionHead[0]) {
continue
}
if structMatch, err = gregex.MatchString(in.StPattern, structName); err != nil {
return err
}
if len(structMatch) < 1 {
continue
}
structName = gstr.CaseCamel(structMatch[1])
if srcPkgInterfaceFuncArray, ok = srcPkgInterfaceMap[structName]; !ok {
srcPkgInterfaceMap[structName] = garray.NewStrArray()
srcPkgInterfaceFuncArray = srcPkgInterfaceMap[structName]
}
// Remove package name calls of `dstPackageName` in produced codes.
functionHead, _ = gregex.ReplaceString(fmt.Sprintf(`\*{0,1}%s\.`, dstPackageName), ``, functionHead)
srcPkgInterfaceFuncArray.Append(functionHead)
}
return nil
}
func (c cGenService) generateServiceFiles(
in cGenServiceInput,
srcPkgInterfaceMap map[string]*garray.StrArray,
srcImportedPackages []string,
dstPackageName string,
) (ok bool, err error) {
srcImportedPackagesContent := fmt.Sprintf(
"import (\n%s\n)", gstr.Join(srcImportedPackages, "\n"),
)
for structName, funcArray := range srcPkgInterfaceMap {
var (
filePath = gfile.Join(in.DstFolder, c.getDstFileNameCase(structName, in.DstFileNameCase)+".go")
generatedContent = gstr.ReplaceByMap(consts.TemplateGenServiceContent, g.MapStrStr{
"{Imports}": srcImportedPackagesContent,
"{StructName}": structName,
"{PackageName}": dstPackageName,
"{FuncDefinition}": funcArray.Join("\n\t"),
})
)
if gfile.Exists(filePath) {
if !in.OverWrite {
mlog.Printf(`not overwrite, ignore generating service go file: %s`, filePath)
continue
}
if !c.isToGenerateServiceGoFile(filePath, funcArray) {
mlog.Printf(`not dirty, ignore generating service go file: %s`, filePath)
continue
}
}
ok = true
mlog.Printf(`generating service go file: %s`, filePath)
if err = gfile.PutContents(filePath, generatedContent); err != nil {
return ok, err
}
}
return ok, nil
}
// isToGenerateServiceGoFile checks and returns whether the service content dirty.
func (c cGenService) isToGenerateServiceGoFile(filePath string, funcArray *garray.StrArray) bool {
if !utils.IsFileDoNotEdit(filePath) {
mlog.Debugf(`ignore file as it is manually maintained: %s`, filePath)
return false
}
var (
fileContent = gfile.GetContents(filePath)
generatedFuncArray = garray.NewSortedStrArrayFrom(funcArray.Slice())
contentFuncArray = garray.NewSortedStrArray()
)
if fileContent == "" {
return true
}
match, _ := gregex.MatchString(`interface\s+{([\s\S]+?)}`, fileContent)
if len(match) != 2 {
return false
}
contentFuncArray.Append(gstr.SplitAndTrim(match[1], "\n")...)
if generatedFuncArray.Len() != contentFuncArray.Len() {
return true
}
for i := 0; i < generatedFuncArray.Len(); i++ {
if generatedFuncArray.At(i) != contentFuncArray.At(i) {
mlog.Debugf(`dirty, %s != %s`, generatedFuncArray.At(i), contentFuncArray.At(i))
return true
}
}
return false
}
func (c cGenService) generateInitializationFile(in cGenServiceInput, importSrcPackages []string) (err error) {
var (
srcPackageName = gstr.ToLower(gfile.Basename(in.SrcFolder))
srcFilePath = gfile.Join(in.SrcFolder, srcPackageName+".go")
srcImports string
generatedContent string
)
if !utils.IsFileDoNotEdit(srcFilePath) {
mlog.Debugf(`ignore file as it is manually maintained: %s`, srcFilePath)
return nil
}
for _, importSrcPackage := range importSrcPackages {
srcImports += fmt.Sprintf(`%s_ "%s"%s`, "\t", importSrcPackage, "\n")
}
generatedContent = gstr.ReplaceByMap(consts.TemplateGenServiceLogicContent, g.MapStrStr{
"{PackageName}": srcPackageName,
"{Imports}": srcImports,
})
mlog.Printf(`generating init go file: %s`, srcFilePath)
if err = gfile.PutContents(srcFilePath, generatedContent); err != nil {
return err
}
utils.GoFmt(srcFilePath)
return nil
}
func (c cGenService) replaceGeneratedServiceContentGFV2(in cGenServiceInput) (err error) {
return gfile.ReplaceDirFunc(func(path, content string) string {
if gstr.Contains(content, `"github.com/gogf/gf`) && !gstr.Contains(content, `"github.com/gogf/gf/v2`) {
content = gstr.Replace(content, `"github.com/gogf/gf"`, `"github.com/gogf/gf/v2"`)
content = gstr.Replace(content, `"github.com/gogf/gf/`, `"github.com/gogf/gf/v2/`)
return content
}
return content
}, in.DstFolder, "*.go", false)
}
// 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)
}
return gstr.CaseSnake(str)
}

View File

@ -5,15 +5,14 @@ import (
"fmt" "fmt"
"strings" "strings"
"github.com/gogf/gf/cmd/gf/v2/internal/utility/allyes"
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
"github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gcmd" "github.com/gogf/gf/v2/os/gcmd"
"github.com/gogf/gf/v2/os/gfile" "github.com/gogf/gf/v2/os/gfile"
"github.com/gogf/gf/v2/os/gproc" "github.com/gogf/gf/v2/os/gproc"
"github.com/gogf/gf/v2/os/gres" "github.com/gogf/gf/v2/os/gres"
"github.com/gogf/gf/v2/util/gtag" "github.com/gogf/gf/v2/util/gtag"
"github.com/gogf/gf/cmd/gf/v2/internal/utility/allyes"
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
) )
var ( var (
@ -53,7 +52,6 @@ type cInitInput struct {
Mono bool `name:"mono" short:"m" brief:"initialize a mono-repo instead a single-repo" orphan:"true"` Mono bool `name:"mono" short:"m" brief:"initialize a mono-repo instead a single-repo" orphan:"true"`
Update bool `name:"update" short:"u" brief:"update to the latest goframe version" orphan:"true"` Update bool `name:"update" short:"u" brief:"update to the latest goframe version" orphan:"true"`
} }
type cInitOutput struct{} type cInitOutput struct{}
func (c cInit) Index(ctx context.Context, in cInitInput) (out *cInitOutput, err error) { func (c cInit) Index(ctx context.Context, in cInitInput) (out *cInitOutput, err error) {
@ -96,7 +94,6 @@ func (c cInit) Index(ctx context.Context, in cInitInput) (out *cInitOutput, err
// Update the GoFrame version. // Update the GoFrame version.
if in.Update { if in.Update {
mlog.Print("update goframe...") mlog.Print("update goframe...")
// go get -u github.com/gogf/gf/v2@latest
updateCommand := `go get -u github.com/gogf/gf/v2@latest` updateCommand := `go get -u github.com/gogf/gf/v2@latest`
if in.Name != "." { if in.Name != "." {
updateCommand = fmt.Sprintf(`cd %s && %s`, in.Name, updateCommand) updateCommand = fmt.Sprintf(`cd %s && %s`, in.Name, updateCommand)
@ -104,14 +101,6 @@ func (c cInit) Index(ctx context.Context, in cInitInput) (out *cInitOutput, err
if err = gproc.ShellRun(ctx, updateCommand); err != nil { if err = gproc.ShellRun(ctx, updateCommand); err != nil {
mlog.Fatal(err) mlog.Fatal(err)
} }
// go mod tidy
gomModTidyCommand := `go mod tidy`
if in.Name != "." {
gomModTidyCommand = fmt.Sprintf(`cd %s && %s`, in.Name, gomModTidyCommand)
}
if err = gproc.ShellRun(ctx, gomModTidyCommand); err != nil {
mlog.Fatal(err)
}
} }
mlog.Print("initialization done! ") mlog.Print("initialization done! ")

View File

@ -3,9 +3,8 @@ package cmd
import ( import (
"context" "context"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/cmd/gf/v2/internal/service" "github.com/gogf/gf/cmd/gf/v2/internal/service"
"github.com/gogf/gf/v2/frame/g"
) )
var ( var (
@ -19,7 +18,6 @@ type cInstall struct {
type cInstallInput struct { type cInstallInput struct {
g.Meta `name:"install"` g.Meta `name:"install"`
} }
type cInstallOutput struct{} type cInstallOutput struct{}
func (c cInstall) Index(ctx context.Context, in cInstallInput) (out *cInstallOutput, err error) { func (c cInstall) Index(ctx context.Context, in cInstallInput) (out *cInstallOutput, err error) {

View File

@ -4,14 +4,13 @@ import (
"context" "context"
"strings" "strings"
"github.com/gogf/gf/cmd/gf/v2/internal/utility/allyes"
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
"github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gcmd" "github.com/gogf/gf/v2/os/gcmd"
"github.com/gogf/gf/v2/os/gfile" "github.com/gogf/gf/v2/os/gfile"
"github.com/gogf/gf/v2/os/gres" "github.com/gogf/gf/v2/os/gres"
"github.com/gogf/gf/v2/util/gtag" "github.com/gogf/gf/v2/util/gtag"
"github.com/gogf/gf/cmd/gf/v2/internal/utility/allyes"
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
) )
var ( var (
@ -38,33 +37,29 @@ gf pack /var/www/public packed/data.go -n=packed
destination file path for packed file. if extension of the filename is ".go" and "-n" option is given, destination file path for packed file. if extension of the filename is ".go" and "-n" option is given,
it enables packing SRC to go file, or else it packs SRC into a binary file. it enables packing SRC to go file, or else it packs SRC into a binary file.
` `
cPackNameBrief = `package name for output go file, it's set as its directory name if no name passed` cPackNameBrief = `package name for output go file, it's set as its directory name if no name passed`
cPackPrefixBrief = `prefix for each file packed into the resource file` cPackPrefixBrief = `prefix for each file packed into the resource file`
cPackKeepPathBrief = `keep the source path from system to resource file, usually for relative path`
) )
func init() { func init() {
gtag.Sets(g.MapStrStr{ gtag.Sets(g.MapStrStr{
`cPackUsage`: cPackUsage, `cPackUsage`: cPackUsage,
`cPackBrief`: cPackBrief, `cPackBrief`: cPackBrief,
`cPackEg`: cPackEg, `cPackEg`: cPackEg,
`cPackSrcBrief`: cPackSrcBrief, `cPackSrcBrief`: cPackSrcBrief,
`cPackDstBrief`: cPackDstBrief, `cPackDstBrief`: cPackDstBrief,
`cPackNameBrief`: cPackNameBrief, `cPackNameBrief`: cPackNameBrief,
`cPackPrefixBrief`: cPackPrefixBrief, `cPackPrefixBrief`: cPackPrefixBrief,
`cPackKeepPathBrief`: cPackKeepPathBrief,
}) })
} }
type cPackInput struct { type cPackInput struct {
g.Meta `name:"pack"` g.Meta `name:"pack"`
Src string `name:"SRC" arg:"true" v:"required" brief:"{cPackSrcBrief}"` Src string `name:"SRC" arg:"true" v:"required" brief:"{cPackSrcBrief}"`
Dst string `name:"DST" arg:"true" v:"required" brief:"{cPackDstBrief}"` Dst string `name:"DST" arg:"true" v:"required" brief:"{cPackDstBrief}"`
Name string `name:"name" short:"n" brief:"{cPackNameBrief}"` Name string `name:"name" short:"n" brief:"{cPackNameBrief}"`
Prefix string `name:"prefix" short:"p" brief:"{cPackPrefixBrief}"` Prefix string `name:"prefix" short:"p" brief:"{cPackPrefixBrief}"`
KeepPath bool `name:"keepPath" short:"k" brief:"{cPackKeepPathBrief}" orphan:"true"`
} }
type cPackOutput struct{} type cPackOutput struct{}
func (c cPack) Index(ctx context.Context, in cPackInput) (out *cPackOutput, err error) { func (c cPack) Index(ctx context.Context, in cPackInput) (out *cPackOutput, err error) {
@ -80,16 +75,12 @@ func (c cPack) Index(ctx context.Context, in cPackInput) (out *cPackOutput, err
if in.Name == "" && gfile.ExtName(in.Dst) == "go" { if in.Name == "" && gfile.ExtName(in.Dst) == "go" {
in.Name = gfile.Basename(gfile.Dir(in.Dst)) in.Name = gfile.Basename(gfile.Dir(in.Dst))
} }
var option = gres.Option{
Prefix: in.Prefix,
KeepPath: in.KeepPath,
}
if in.Name != "" { if in.Name != "" {
if err = gres.PackToGoFileWithOption(in.Src, in.Dst, in.Name, option); err != nil { if err = gres.PackToGoFile(in.Src, in.Dst, in.Name, in.Prefix); err != nil {
mlog.Fatalf("pack failed: %v", err) mlog.Fatalf("pack failed: %v", err)
} }
} else { } else {
if err = gres.PackToFileWithOption(in.Src, in.Dst, option); err != nil { if err = gres.PackToFile(in.Src, in.Dst, in.Prefix); err != nil {
mlog.Fatalf("pack failed: %v", err) mlog.Fatalf("pack failed: %v", err)
} }
} }

View File

@ -4,8 +4,8 @@ import (
"context" "context"
"fmt" "fmt"
"runtime" "runtime"
"strings"
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
"github.com/gogf/gf/v2/container/gtype" "github.com/gogf/gf/v2/container/gtype"
"github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gfile" "github.com/gogf/gf/v2/os/gfile"
@ -14,8 +14,6 @@ import (
"github.com/gogf/gf/v2/os/gtime" "github.com/gogf/gf/v2/os/gtime"
"github.com/gogf/gf/v2/os/gtimer" "github.com/gogf/gf/v2/os/gtimer"
"github.com/gogf/gf/v2/util/gtag" "github.com/gogf/gf/v2/util/gtag"
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
) )
var ( var (
@ -155,7 +153,7 @@ func (app *cRunApp) Run(ctx context.Context) {
if runtime.GOOS == "windows" { if runtime.GOOS == "windows" {
// Special handling for windows platform. // Special handling for windows platform.
// DO NOT USE "cmd /c" command. // DO NOT USE "cmd /c" command.
process = gproc.NewProcess(outputPath, strings.Fields(app.Args)) process = gproc.NewProcess(runCommand, nil)
} else { } else {
process = gproc.NewProcessCmd(runCommand, nil) process = gproc.NewProcessCmd(runCommand, nil)
} }

View File

@ -3,6 +3,7 @@ package cmd
import ( import (
"context" "context"
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
"github.com/gogf/gf/v2/encoding/gjson" "github.com/gogf/gf/v2/encoding/gjson"
"github.com/gogf/gf/v2/errors/gerror" "github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/frame/g"
@ -10,8 +11,6 @@ import (
"github.com/gogf/gf/v2/text/gstr" "github.com/gogf/gf/v2/text/gstr"
"github.com/gogf/gf/v2/util/gtag" "github.com/gogf/gf/v2/util/gtag"
"github.com/gogf/gf/v2/util/gutil" "github.com/gogf/gf/v2/util/gutil"
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
) )
var ( var (

View File

@ -1,207 +0,0 @@
package cmd
import (
"context"
"fmt"
"github.com/gogf/gf/cmd/gf/v2/internal/utility/utils"
"github.com/gogf/gf/v2/container/gset"
"runtime"
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gfile"
"github.com/gogf/gf/v2/os/gproc"
"github.com/gogf/gf/v2/text/gstr"
"github.com/gogf/gf/v2/util/gtag"
)
var (
Up = cUp{}
)
type cUp struct {
g.Meta `name:"up" brief:"upgrade GoFrame version/tool to latest one in current project" eg:"{cUpEg}" `
}
const (
gfPackage = `github.com/gogf/gf/`
cUpEg = `
gf up
gf up -a
gf up -c
gf up -cf
`
)
func init() {
gtag.Sets(g.MapStrStr{
`cUpEg`: cUpEg,
})
}
type cUpInput struct {
g.Meta `name:"up" config:"gfcli.up"`
All bool `name:"all" short:"a" brief:"upgrade both version and cli, auto fix codes" orphan:"true"`
Cli bool `name:"cli" short:"c" brief:"also upgrade CLI tool" orphan:"true"`
Fix bool `name:"fix" short:"f" brief:"auto fix codes(it only make sense if cli is to be upgraded)" orphan:"true"`
}
type cUpOutput struct{}
func (c cUp) Index(ctx context.Context, in cUpInput) (out *cUpOutput, err error) {
defer func() {
if err == nil {
mlog.Print()
mlog.Print(`👏congratulations! you've upgraded to the latest version of GoFrame! enjoy it!👏`)
mlog.Print()
}
}()
var doUpgradeVersionOut *doUpgradeVersionOutput
if in.All {
in.Cli = true
in.Fix = true
}
if doUpgradeVersionOut, err = c.doUpgradeVersion(ctx, in); err != nil {
return nil, err
}
if in.Cli {
if err = c.doUpgradeCLI(ctx); err != nil {
return nil, err
}
}
if in.Cli && in.Fix {
if doUpgradeVersionOut != nil && len(doUpgradeVersionOut.Items) > 0 {
upgradedPathSet := gset.NewStrSet()
for _, item := range doUpgradeVersionOut.Items {
if !upgradedPathSet.AddIfNotExist(item.DirPath) {
continue
}
if err = c.doAutoFixing(ctx, item.DirPath, item.Version); err != nil {
return nil, err
}
}
}
}
return
}
type doUpgradeVersionOutput struct {
Items []doUpgradeVersionOutputItem
}
type doUpgradeVersionOutputItem struct {
DirPath string
Version string
}
func (c cUp) doUpgradeVersion(ctx context.Context, in cUpInput) (out *doUpgradeVersionOutput, err error) {
mlog.Print(`start upgrading version...`)
out = &doUpgradeVersionOutput{
Items: make([]doUpgradeVersionOutputItem, 0),
}
type Package struct {
Name string
Version string
}
var (
temp string
dirPath = gfile.Pwd()
goModPath = gfile.Join(dirPath, "go.mod")
)
// It recursively upgrades the go.mod from sub folder to its parent folders.
for {
if gfile.Exists(goModPath) {
var packages []Package
err = gfile.ReadLines(goModPath, func(line string) error {
line = gstr.Trim(line)
if gstr.HasPrefix(line, gfPackage) {
array := gstr.SplitAndTrim(line, " ")
packages = append(packages, Package{
Name: array[0],
Version: array[1],
})
}
return nil
})
if err != nil {
return
}
for _, pkg := range packages {
mlog.Printf(`upgrading "%s" from "%s" to "latest"`, pkg.Name, pkg.Version)
// go get -u
command := fmt.Sprintf(`cd %s && go get -u %s@latest`, dirPath, pkg.Name)
if err = gproc.ShellRun(ctx, command); err != nil {
return
}
// go mod tidy
if err = utils.GoModTidy(ctx, dirPath); err != nil {
return nil, err
}
out.Items = append(out.Items, doUpgradeVersionOutputItem{
DirPath: dirPath,
Version: pkg.Version,
})
}
return
}
temp = gfile.Dir(dirPath)
if temp == "" || temp == dirPath {
return
}
dirPath = temp
goModPath = gfile.Join(dirPath, "go.mod")
}
}
// doUpgradeCLI downloads the new version binary with process.
func (c cUp) doUpgradeCLI(ctx context.Context) (err error) {
mlog.Print(`start upgrading cli...`)
var (
downloadUrl = fmt.Sprintf(
`https://github.com/gogf/gf/releases/latest/download/gf_%s_%s`,
runtime.GOOS, runtime.GOARCH,
)
localSaveFilePath = gfile.SelfPath() + "~"
)
mlog.Printf(`start downloading "%s" to "%s", it may take some time`, downloadUrl, localSaveFilePath)
err = utils.HTTPDownloadFileWithPercent(downloadUrl, localSaveFilePath)
if err != nil {
return err
}
defer func() {
mlog.Printf(`new version cli binary is successfully installed to "%s"`, gfile.SelfPath())
mlog.Printf(`remove temporary buffer file "%s"`, localSaveFilePath)
_ = gfile.Remove(localSaveFilePath)
}()
// It fails if file not exist or its size is less than 1MB.
if !gfile.Exists(localSaveFilePath) || gfile.Size(localSaveFilePath) < 1024*1024 {
mlog.Fatalf(`download "%s" to "%s" failed`, downloadUrl, localSaveFilePath)
}
// It replaces self binary with new version cli binary.
switch runtime.GOOS {
case "windows":
if err := gfile.Rename(localSaveFilePath, gfile.SelfPath()); err != nil {
mlog.Fatalf(`install failed: %s`, err.Error())
}
default:
if err := gfile.PutBytes(gfile.SelfPath(), gfile.GetBytes(localSaveFilePath)); err != nil {
mlog.Fatalf(`install failed: %s`, err.Error())
}
}
return
}
func (c cUp) doAutoFixing(ctx context.Context, dirPath string, version string) (err error) {
mlog.Printf(`auto fixing directory path "%s" from version "%s" ...`, dirPath, version)
command := fmt.Sprintf(`gf fix -p %s`, dirPath)
_ = gproc.ShellRun(ctx, command)
return
}

View File

@ -4,6 +4,7 @@ import (
"context" "context"
"fmt" "fmt"
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
"github.com/gogf/gf/v2" "github.com/gogf/gf/v2"
"github.com/gogf/gf/v2/errors/gerror" "github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/frame/g"
@ -11,8 +12,6 @@ import (
"github.com/gogf/gf/v2/os/gfile" "github.com/gogf/gf/v2/os/gfile"
"github.com/gogf/gf/v2/text/gregex" "github.com/gogf/gf/v2/text/gregex"
"github.com/gogf/gf/v2/text/gstr" "github.com/gogf/gf/v2/text/gstr"
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
) )
var ( var (
@ -26,7 +25,6 @@ type cVersion struct {
type cVersionInput struct { type cVersionInput struct {
g.Meta `name:"version"` g.Meta `name:"version"`
} }
type cVersionOutput struct{} type cVersionOutput struct{}
func (c cVersion) Index(ctx context.Context, in cVersionInput) (*cVersionOutput, error) { func (c cVersion) Index(ctx context.Context, in cVersionInput) (*cVersionOutput, error) {

View File

@ -5,6 +5,7 @@ import (
"fmt" "fmt"
"strings" "strings"
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
"github.com/gogf/gf/v2/container/garray" "github.com/gogf/gf/v2/container/garray"
"github.com/gogf/gf/v2/database/gdb" "github.com/gogf/gf/v2/database/gdb"
"github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/frame/g"
@ -13,8 +14,6 @@ import (
"github.com/gogf/gf/v2/text/gregex" "github.com/gogf/gf/v2/text/gregex"
"github.com/gogf/gf/v2/text/gstr" "github.com/gogf/gf/v2/text/gstr"
"github.com/gogf/gf/v2/util/gtag" "github.com/gogf/gf/v2/util/gtag"
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
) )
const ( const (
@ -63,7 +62,6 @@ CONFIGURATION SUPPORT
CGenDaoBriefDescriptionTag = `add comment to description tag for each field` CGenDaoBriefDescriptionTag = `add comment to description tag for each field`
CGenDaoBriefNoJsonTag = `no json tag will be added for each field` CGenDaoBriefNoJsonTag = `no json tag will be added for each field`
CGenDaoBriefNoModelComment = `no model comment will be added for each field` CGenDaoBriefNoModelComment = `no model comment will be added for each field`
CGenDaoBriefClear = `delete all generated go files that do not exist in database`
CGenDaoBriefGroup = ` CGenDaoBriefGroup = `
specifying the configuration group name of database for generated ORM instance, specifying the configuration group name of database for generated ORM instance,
it's not necessary and the default value is "default" it's not necessary and the default value is "default"
@ -80,10 +78,6 @@ generated json tag case for model struct, cases are as follows:
| Kebab | any-kind-of-string | | Kebab | any-kind-of-string |
| KebabScreaming | ANY-KIND-OF-STRING | | KebabScreaming | ANY-KIND-OF-STRING |
` `
CGenDaoBriefTplDaoIndexPath = `template file path for dao index file`
CGenDaoBriefTplDaoInternalPath = `template file path for dao internal file`
CGenDaoBriefTplDaoDoPathPath = `template file path for dao do file`
CGenDaoBriefTplDaoEntityPath = `template file path for dao entity file`
tplVarTableName = `{TplTableName}` tplVarTableName = `{TplTableName}`
tplVarTableNameCamelCase = `{TplTableNameCamelCase}` tplVarTableNameCamelCase = `{TplTableNameCamelCase}`
@ -95,7 +89,6 @@ generated json tag case for model struct, cases are as follows:
tplVarColumnNames = `{TplColumnNames}` tplVarColumnNames = `{TplColumnNames}`
tplVarGroupName = `{TplGroupName}` tplVarGroupName = `{TplGroupName}`
tplVarDatetimeStr = `{TplDatetimeStr}` tplVarDatetimeStr = `{TplDatetimeStr}`
tplVarCreatedAtDatetimeStr = `{TplCreatedAtDatetimeStr}`
) )
var ( var (
@ -104,77 +97,66 @@ var (
func init() { func init() {
gtag.Sets(g.MapStrStr{ gtag.Sets(g.MapStrStr{
`CGenDaoConfig`: CGenDaoConfig, `CGenDaoConfig`: CGenDaoConfig,
`CGenDaoUsage`: CGenDaoUsage, `CGenDaoUsage`: CGenDaoUsage,
`CGenDaoBrief`: CGenDaoBrief, `CGenDaoBrief`: CGenDaoBrief,
`CGenDaoEg`: CGenDaoEg, `CGenDaoEg`: CGenDaoEg,
`CGenDaoAd`: CGenDaoAd, `CGenDaoAd`: CGenDaoAd,
`CGenDaoBriefPath`: CGenDaoBriefPath, `CGenDaoBriefPath`: CGenDaoBriefPath,
`CGenDaoBriefLink`: CGenDaoBriefLink, `CGenDaoBriefLink`: CGenDaoBriefLink,
`CGenDaoBriefTables`: CGenDaoBriefTables, `CGenDaoBriefTables`: CGenDaoBriefTables,
`CGenDaoBriefTablesEx`: CGenDaoBriefTablesEx, `CGenDaoBriefTablesEx`: CGenDaoBriefTablesEx,
`CGenDaoBriefPrefix`: CGenDaoBriefPrefix, `CGenDaoBriefPrefix`: CGenDaoBriefPrefix,
`CGenDaoBriefRemovePrefix`: CGenDaoBriefRemovePrefix, `CGenDaoBriefRemovePrefix`: CGenDaoBriefRemovePrefix,
`CGenDaoBriefStdTime`: CGenDaoBriefStdTime, `CGenDaoBriefStdTime`: CGenDaoBriefStdTime,
`CGenDaoBriefWithTime`: CGenDaoBriefWithTime, `CGenDaoBriefWithTime`: CGenDaoBriefWithTime,
`CGenDaoBriefDaoPath`: CGenDaoBriefDaoPath, `CGenDaoBriefDaoPath`: CGenDaoBriefDaoPath,
`CGenDaoBriefDoPath`: CGenDaoBriefDoPath, `CGenDaoBriefDoPath`: CGenDaoBriefDoPath,
`CGenDaoBriefEntityPath`: CGenDaoBriefEntityPath, `CGenDaoBriefEntityPath`: CGenDaoBriefEntityPath,
`CGenDaoBriefGJsonSupport`: CGenDaoBriefGJsonSupport, `CGenDaoBriefGJsonSupport`: CGenDaoBriefGJsonSupport,
`CGenDaoBriefImportPrefix`: CGenDaoBriefImportPrefix, `CGenDaoBriefImportPrefix`: CGenDaoBriefImportPrefix,
`CGenDaoBriefOverwriteDao`: CGenDaoBriefOverwriteDao, `CGenDaoBriefOverwriteDao`: CGenDaoBriefOverwriteDao,
`CGenDaoBriefModelFile`: CGenDaoBriefModelFile, `CGenDaoBriefModelFile`: CGenDaoBriefModelFile,
`CGenDaoBriefModelFileForDao`: CGenDaoBriefModelFileForDao, `CGenDaoBriefModelFileForDao`: CGenDaoBriefModelFileForDao,
`CGenDaoBriefDescriptionTag`: CGenDaoBriefDescriptionTag, `CGenDaoBriefDescriptionTag`: CGenDaoBriefDescriptionTag,
`CGenDaoBriefNoJsonTag`: CGenDaoBriefNoJsonTag, `CGenDaoBriefNoJsonTag`: CGenDaoBriefNoJsonTag,
`CGenDaoBriefNoModelComment`: CGenDaoBriefNoModelComment, `CGenDaoBriefNoModelComment`: CGenDaoBriefNoModelComment,
`CGenDaoBriefClear`: CGenDaoBriefClear, `CGenDaoBriefGroup`: CGenDaoBriefGroup,
`CGenDaoBriefGroup`: CGenDaoBriefGroup, `CGenDaoBriefJsonCase`: CGenDaoBriefJsonCase,
`CGenDaoBriefJsonCase`: CGenDaoBriefJsonCase,
`CGenDaoBriefTplDaoIndexPath`: CGenDaoBriefTplDaoIndexPath,
`CGenDaoBriefTplDaoInternalPath`: CGenDaoBriefTplDaoInternalPath,
`CGenDaoBriefTplDaoDoPathPath`: CGenDaoBriefTplDaoDoPathPath,
`CGenDaoBriefTplDaoEntityPath`: CGenDaoBriefTplDaoEntityPath,
}) })
} }
type ( type (
CGenDao struct{} CGenDao struct{}
CGenDaoInput struct { CGenDaoInput struct {
g.Meta `name:"dao" config:"{CGenDaoConfig}" usage:"{CGenDaoUsage}" brief:"{CGenDaoBrief}" eg:"{CGenDaoEg}" ad:"{CGenDaoAd}"` g.Meta `name:"dao" config:"{CGenDaoConfig}" usage:"{CGenDaoUsage}" brief:"{CGenDaoBrief}" eg:"{CGenDaoEg}" ad:"{CGenDaoAd}"`
Path string `name:"path" short:"p" brief:"{CGenDaoBriefPath}" d:"internal"` Path string `name:"path" short:"p" brief:"{CGenDaoBriefPath}" d:"internal"`
Link string `name:"link" short:"l" brief:"{CGenDaoBriefLink}"` Link string `name:"link" short:"l" brief:"{CGenDaoBriefLink}"`
Tables string `name:"tables" short:"t" brief:"{CGenDaoBriefTables}"` Tables string `name:"tables" short:"t" brief:"{CGenDaoBriefTables}"`
TablesEx string `name:"tablesEx" short:"x" brief:"{CGenDaoBriefTablesEx}"` TablesEx string `name:"tablesEx" short:"x" brief:"{CGenDaoBriefTablesEx}"`
Group string `name:"group" short:"g" brief:"{CGenDaoBriefGroup}" d:"default"` Group string `name:"group" short:"g" brief:"{CGenDaoBriefGroup}" d:"default"`
Prefix string `name:"prefix" short:"f" brief:"{CGenDaoBriefPrefix}"` Prefix string `name:"prefix" short:"f" brief:"{CGenDaoBriefPrefix}"`
RemovePrefix string `name:"removePrefix" short:"r" brief:"{CGenDaoBriefRemovePrefix}"` RemovePrefix string `name:"removePrefix" short:"r" brief:"{CGenDaoBriefRemovePrefix}"`
JsonCase string `name:"jsonCase" short:"j" brief:"{CGenDaoBriefJsonCase}" d:"CamelLower"` JsonCase string `name:"jsonCase" short:"j" brief:"{CGenDaoBriefJsonCase}" d:"CamelLower"`
ImportPrefix string `name:"importPrefix" short:"i" brief:"{CGenDaoBriefImportPrefix}"` ImportPrefix string `name:"importPrefix" short:"i" brief:"{CGenDaoBriefImportPrefix}"`
DaoPath string `name:"daoPath" short:"d" brief:"{CGenDaoBriefDaoPath}" d:"dao"` DaoPath string `name:"daoPath" short:"d" brief:"{CGenDaoBriefDaoPath}" d:"dao"`
DoPath string `name:"doPath" short:"o" brief:"{CGenDaoBriefDoPath}" d:"model/do"` DoPath string `name:"doPath" short:"o" brief:"{CGenDaoBriefDoPath}" d:"model/do"`
EntityPath string `name:"entityPath" short:"e" brief:"{CGenDaoBriefEntityPath}" d:"model/entity"` EntityPath string `name:"entityPath" short:"e" brief:"{CGenDaoBriefEntityPath}" d:"model/entity"`
TplDaoIndexPath string `name:"tplDaoIndexPath" short:"t1" brief:"{CGenDaoBriefTplDaoIndexPath}"` StdTime bool `name:"stdTime" short:"s" brief:"{CGenDaoBriefStdTime}" orphan:"true"`
TplDaoInternalPath string `name:"tplDaoInternalPath" short:"t2" brief:"{CGenDaoBriefTplDaoInternalPath}"` WithTime bool `name:"withTime" short:"w" brief:"{CGenDaoBriefWithTime}" orphan:"true"`
TplDaoDoPath string `name:"tplDaoDoPath" short:"t3" brief:"{CGenDaoBriefTplDaoDoPathPath}"` GJsonSupport bool `name:"gJsonSupport" short:"n" brief:"{CGenDaoBriefGJsonSupport}" orphan:"true"`
TplDaoEntityPath string `name:"tplDaoEntityPath" short:"t4" brief:"{CGenDaoBriefTplDaoEntityPath}"` OverwriteDao bool `name:"overwriteDao" short:"v" brief:"{CGenDaoBriefOverwriteDao}" orphan:"true"`
StdTime bool `name:"stdTime" short:"s" brief:"{CGenDaoBriefStdTime}" orphan:"true"` DescriptionTag bool `name:"descriptionTag" short:"c" brief:"{CGenDaoBriefDescriptionTag}" orphan:"true"`
WithTime bool `name:"withTime" short:"w" brief:"{CGenDaoBriefWithTime}" orphan:"true"` NoJsonTag bool `name:"noJsonTag" short:"k" brief:"{CGenDaoBriefNoJsonTag" orphan:"true"`
GJsonSupport bool `name:"gJsonSupport" short:"n" brief:"{CGenDaoBriefGJsonSupport}" orphan:"true"` NoModelComment bool `name:"noModelComment" short:"m" brief:"{CGenDaoBriefNoModelComment}" 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"`
} }
CGenDaoOutput struct{} CGenDaoOutput struct{}
CGenDaoInternalInput struct { CGenDaoInternalInput struct {
CGenDaoInput CGenDaoInput
DB gdb.DB TableName string // TableName specifies the table name of the table.
TableNames []string NewTableName string // NewTableName specifies the prefix-stripped name of the table.
NewTableNames []string ModName string // ModName specifies the module name of current golang project, which is used for import purpose.
ModName string // Module name of current golang project, which is used for import purpose.
} }
) )
@ -273,30 +255,23 @@ func doGenDaoForArray(ctx context.Context, index int, in CGenDaoInput) {
} }
newTableName = in.Prefix + newTableName newTableName = in.Prefix + newTableName
newTableNames[i] = newTableName newTableNames[i] = newTableName
// Dao.
generateDao(ctx, db, CGenDaoInternalInput{
CGenDaoInput: in,
TableName: tableName,
NewTableName: newTableName,
ModName: modName,
})
} }
// Dao: index and internal.
generateDao(ctx, CGenDaoInternalInput{
CGenDaoInput: in,
DB: db,
TableNames: tableNames,
NewTableNames: newTableNames,
ModName: modName,
})
// Do. // Do.
generateDo(ctx, CGenDaoInternalInput{ generateDo(ctx, db, tableNames, newTableNames, CGenDaoInternalInput{
CGenDaoInput: in, CGenDaoInput: in,
DB: db, ModName: modName,
TableNames: tableNames,
NewTableNames: newTableNames,
ModName: modName,
}) })
// Entity. // Entity.
generateEntity(ctx, CGenDaoInternalInput{ generateEntity(ctx, db, tableNames, newTableNames, CGenDaoInternalInput{
CGenDaoInput: in, CGenDaoInput: in,
DB: db, ModName: modName,
TableNames: tableNames,
NewTableNames: newTableNames,
ModName: modName,
}) })
} }
@ -330,14 +305,12 @@ func getImportPartContent(source string, isDo bool) string {
} }
func replaceDefaultVar(in CGenDaoInternalInput, origin string) string { func replaceDefaultVar(in CGenDaoInternalInput, origin string) string {
var tplCreatedAtDatetimeStr string var tplDatetimeStr string
var tplDatetimeStr string = createdAt.String()
if in.WithTime { if in.WithTime {
tplCreatedAtDatetimeStr = fmt.Sprintf(`Created at %s`, tplDatetimeStr) tplDatetimeStr = fmt.Sprintf(`Created at %s`, createdAt.String())
} }
return gstr.ReplaceByMap(origin, g.MapStrStr{ return gstr.ReplaceByMap(origin, g.MapStrStr{
tplVarDatetimeStr: tplDatetimeStr, tplVarDatetimeStr: tplDatetimeStr,
tplVarCreatedAtDatetimeStr: tplCreatedAtDatetimeStr,
}) })
} }
@ -364,12 +337,3 @@ func sortFieldKeyForDao(fieldMap map[string]*gdb.TableField) []string {
} }
return result return result
} }
func getTemplateFromPathOrDefault(filePath string, def string) string {
if filePath != "" {
if contents := gfile.GetContents(filePath); contents != "" {
return contents
}
}
return def
}

View File

@ -1,24 +0,0 @@
package gendao
import (
"context"
"github.com/gogf/gf/v2/os/gfile"
"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) {
files, err := gfile.ScanDirFile(dirPath, "*.go", true)
if err != nil {
mlog.Fatal(err)
}
for _, file := range files {
if utils.IsFileDoNotEdit(file) {
if err = gfile.Remove(file); err != nil {
mlog.Print(err)
}
}
}
}

View File

@ -6,54 +6,27 @@ import (
"fmt" "fmt"
"strings" "strings"
"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/database/gdb" "github.com/gogf/gf/v2/database/gdb"
"github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gfile" "github.com/gogf/gf/v2/os/gfile"
"github.com/gogf/gf/v2/text/gregex" "github.com/gogf/gf/v2/text/gregex"
"github.com/gogf/gf/v2/text/gstr" "github.com/gogf/gf/v2/text/gstr"
"github.com/olekukonko/tablewriter" "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/cmd/gf/v2/internal/utility/utils"
) )
func generateDao(ctx context.Context, in CGenDaoInternalInput) { // generateDaoContentFile generates the dao and model content of given table.
var ( func generateDao(ctx context.Context, db gdb.DB, in CGenDaoInternalInput) {
dirPathDao = gfile.Join(in.Path, in.DaoPath)
dirPathDaoInternal = gfile.Join(dirPathDao, "internal")
)
if in.Clear {
doClear(ctx, dirPathDao)
}
for i := 0; i < len(in.TableNames); i++ {
generateDaoSingle(ctx, generateDaoSingleInput{
CGenDaoInternalInput: in,
TableName: in.TableNames[i],
NewTableName: in.NewTableNames[i],
DirPathDao: dirPathDao,
DirPathDaoInternal: dirPathDaoInternal,
})
}
}
type generateDaoSingleInput struct {
CGenDaoInternalInput
TableName string // TableName specifies the table name of the table.
NewTableName string // NewTableName specifies the prefix-stripped name of the table.
DirPathDao string
DirPathDaoInternal string
}
// generateDaoSingle generates the dao and model content of given table.
func generateDaoSingle(ctx context.Context, in generateDaoSingleInput) {
// Generating table data preparing. // Generating table data preparing.
fieldMap, err := in.DB.TableFields(ctx, in.TableName) fieldMap, err := db.TableFields(ctx, in.TableName)
if err != nil { if err != nil {
mlog.Fatalf(`fetching tables fields failed for table "%s": %+v`, in.TableName, err) mlog.Fatalf(`fetching tables fields failed for table "%s": %+v`, in.TableName, err)
} }
var ( var (
dirRealPath = gfile.RealPath(in.Path) dirRealPath = gfile.RealPath(in.Path)
dirPathDao = gfile.Join(in.Path, in.DaoPath)
tableNameCamelCase = gstr.CaseCamel(in.NewTableName) tableNameCamelCase = gstr.CaseCamel(in.NewTableName)
tableNameCamelLowerCase = gstr.CaseCamelLower(in.NewTableName) tableNameCamelLowerCase = gstr.CaseCamelLower(in.NewTableName)
tableNameSnakeCase = gstr.CaseSnake(in.NewTableName) tableNameSnakeCase = gstr.CaseSnake(in.NewTableName)
@ -82,45 +55,22 @@ func generateDaoSingle(ctx context.Context, in generateDaoSingleInput) {
} }
// dao - index // dao - index
generateDaoIndex(generateDaoIndexInput{ generateDaoIndex(in, tableNameCamelCase, tableNameCamelLowerCase, importPrefix, dirPathDao, fileName)
generateDaoSingleInput: in,
TableNameCamelCase: tableNameCamelCase,
TableNameCamelLowerCase: tableNameCamelLowerCase,
ImportPrefix: importPrefix,
FileName: fileName,
})
// dao - internal // dao - internal
generateDaoInternal(generateDaoInternalInput{ generateDaoInternal(in, tableNameCamelCase, tableNameCamelLowerCase, importPrefix, dirPathDao, fileName, fieldMap)
generateDaoSingleInput: in,
TableNameCamelCase: tableNameCamelCase,
TableNameCamelLowerCase: tableNameCamelLowerCase,
ImportPrefix: importPrefix,
FileName: fileName,
FieldMap: fieldMap,
})
} }
type generateDaoIndexInput struct { func generateDaoIndex(in CGenDaoInternalInput, tableNameCamelCase, tableNameCamelLowerCase, importPrefix, dirPathDao, fileName string) {
generateDaoSingleInput path := gfile.Join(dirPathDao, fileName+".go")
TableNameCamelCase string
TableNameCamelLowerCase string
ImportPrefix string
FileName string
}
func generateDaoIndex(in generateDaoIndexInput) {
path := gfile.Join(in.DirPathDao, in.FileName+".go")
if in.OverwriteDao || !gfile.Exists(path) { if in.OverwriteDao || !gfile.Exists(path) {
indexContent := gstr.ReplaceByMap( indexContent := gstr.ReplaceByMap(getTplDaoIndexContent(""), g.MapStrStr{
getTemplateFromPathOrDefault(in.TplDaoIndexPath, consts.TemplateGenDaoIndexContent), tplVarImportPrefix: importPrefix,
g.MapStrStr{ tplVarTableName: in.TableName,
tplVarImportPrefix: in.ImportPrefix, tplVarTableNameCamelCase: tableNameCamelCase,
tplVarTableName: in.TableName, tplVarTableNameCamelLowerCase: tableNameCamelLowerCase,
tplVarTableNameCamelCase: in.TableNameCamelCase, })
tplVarTableNameCamelLowerCase: in.TableNameCamelLowerCase, indexContent = replaceDefaultVar(in, indexContent)
})
indexContent = replaceDefaultVar(in.CGenDaoInternalInput, indexContent)
if err := gfile.PutContents(path, strings.TrimSpace(indexContent)); err != nil { if err := gfile.PutContents(path, strings.TrimSpace(indexContent)); err != nil {
mlog.Fatalf("writing content to '%s' failed: %v", path, err) mlog.Fatalf("writing content to '%s' failed: %v", path, err)
} else { } else {
@ -130,29 +80,23 @@ func generateDaoIndex(in generateDaoIndexInput) {
} }
} }
type generateDaoInternalInput struct { func generateDaoInternal(
generateDaoSingleInput in CGenDaoInternalInput,
TableNameCamelCase string tableNameCamelCase, tableNameCamelLowerCase, importPrefix string,
TableNameCamelLowerCase string dirPathDao, fileName string,
ImportPrefix string fieldMap map[string]*gdb.TableField,
FileName string ) {
FieldMap map[string]*gdb.TableField path := gfile.Join(dirPathDao, "internal", fileName+".go")
} modelContent := gstr.ReplaceByMap(getTplDaoInternalContent(""), g.MapStrStr{
tplVarImportPrefix: importPrefix,
func generateDaoInternal(in generateDaoInternalInput) { tplVarTableName: in.TableName,
path := gfile.Join(in.DirPathDaoInternal, in.FileName+".go") tplVarGroupName: in.Group,
modelContent := gstr.ReplaceByMap( tplVarTableNameCamelCase: tableNameCamelCase,
getTemplateFromPathOrDefault(in.TplDaoInternalPath, consts.TemplateGenDaoInternalContent), tplVarTableNameCamelLowerCase: tableNameCamelLowerCase,
g.MapStrStr{ tplVarColumnDefine: gstr.Trim(generateColumnDefinitionForDao(fieldMap)),
tplVarImportPrefix: in.ImportPrefix, tplVarColumnNames: gstr.Trim(generateColumnNamesForDao(fieldMap)),
tplVarTableName: in.TableName, })
tplVarGroupName: in.Group, modelContent = replaceDefaultVar(in, modelContent)
tplVarTableNameCamelCase: in.TableNameCamelCase,
tplVarTableNameCamelLowerCase: in.TableNameCamelLowerCase,
tplVarColumnDefine: gstr.Trim(generateColumnDefinitionForDao(in.FieldMap)),
tplVarColumnNames: gstr.Trim(generateColumnNamesForDao(in.FieldMap)),
})
modelContent = replaceDefaultVar(in.CGenDaoInternalInput, modelContent)
if err := gfile.PutContents(path, strings.TrimSpace(modelContent)); err != nil { if err := gfile.PutContents(path, strings.TrimSpace(modelContent)); err != nil {
mlog.Fatalf("writing content to '%s' failed: %v", path, err) mlog.Fatalf("writing content to '%s' failed: %v", path, err)
} else { } else {
@ -161,6 +105,20 @@ func generateDaoInternal(in generateDaoInternalInput) {
} }
} }
func getTplDaoIndexContent(tplDaoIndexPath string) string {
if tplDaoIndexPath != "" {
return gfile.GetContents(tplDaoIndexPath)
}
return consts.TemplateDaoDaoIndexContent
}
func getTplDaoInternalContent(tplDaoInternalPath string) string {
if tplDaoInternalPath != "" {
return gfile.GetContents(tplDaoInternalPath)
}
return consts.TemplateDaoDaoInternalContent
}
// generateColumnNamesForDao generates and returns the column names assignment content of column struct // generateColumnNamesForDao generates and returns the column names assignment content of column struct
// for specified table. // for specified table.
func generateColumnNamesForDao(fieldMap map[string]*gdb.TableField) string { func generateColumnNamesForDao(fieldMap map[string]*gdb.TableField) string {

View File

@ -5,36 +5,35 @@ import (
"fmt" "fmt"
"strings" "strings"
"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/database/gdb"
"github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gfile" "github.com/gogf/gf/v2/os/gfile"
"github.com/gogf/gf/v2/text/gregex" "github.com/gogf/gf/v2/text/gregex"
"github.com/gogf/gf/v2/text/gstr" "github.com/gogf/gf/v2/text/gstr"
"github.com/gogf/gf/cmd/gf/v2/internal/consts"
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
"github.com/gogf/gf/cmd/gf/v2/internal/utility/utils"
) )
func generateDo(ctx context.Context, in CGenDaoInternalInput) { func generateDo(ctx context.Context, db gdb.DB, tableNames, newTableNames []string, in CGenDaoInternalInput) {
var dirPathDo = gfile.Join(in.Path, in.DoPath) var (
if in.Clear { doDirPath = gfile.Join(in.Path, in.DoPath)
doClear(ctx, dirPathDo) )
}
in.NoJsonTag = true in.NoJsonTag = true
in.DescriptionTag = false in.DescriptionTag = false
in.NoModelComment = false in.NoModelComment = false
// Model content. // Model content.
for i, tableName := range in.TableNames { for i, tableName := range tableNames {
fieldMap, err := in.DB.TableFields(ctx, tableName) in.TableName = tableName
fieldMap, err := db.TableFields(ctx, tableName)
if err != nil { if err != nil {
mlog.Fatalf("fetching tables fields failed for table '%s':\n%v", tableName, err) mlog.Fatalf("fetching tables fields failed for table '%s':\n%v", in.TableName, err)
} }
var ( var (
newTableName = in.NewTableNames[i] newTableName = newTableNames[i]
doFilePath = gfile.Join(dirPathDo, gstr.CaseSnake(newTableName)+".go") doFilePath = gfile.Join(doDirPath, gstr.CaseSnake(newTableName)+".go")
structDefinition = generateStructDefinition(ctx, generateStructDefinitionInput{ structDefinition = generateStructDefinition(generateStructDefinitionInput{
CGenDaoInternalInput: in, CGenDaoInternalInput: in,
TableName: tableName,
StructName: gstr.CaseCamel(newTableName), StructName: gstr.CaseCamel(newTableName),
FieldMap: fieldMap, FieldMap: fieldMap,
IsDo: true, IsDo: true,
@ -69,14 +68,12 @@ func generateDo(ctx context.Context, in CGenDaoInternalInput) {
} }
func generateDoContent(in CGenDaoInternalInput, tableName, tableNameCamelCase, structDefine string) string { func generateDoContent(in CGenDaoInternalInput, tableName, tableNameCamelCase, structDefine string) string {
doContent := gstr.ReplaceByMap( doContent := gstr.ReplaceByMap(consts.TemplateGenDaoDoContent, g.MapStrStr{
getTemplateFromPathOrDefault(in.TplDaoDoPath, consts.TemplateGenDaoDoContent), tplVarTableName: tableName,
g.MapStrStr{ tplVarPackageImports: getImportPartContent(structDefine, true),
tplVarTableName: tableName, tplVarTableNameCamelCase: tableNameCamelCase,
tplVarPackageImports: getImportPartContent(structDefine, true), tplVarStructDefine: structDefine,
tplVarTableNameCamelCase: tableNameCamelCase, })
tplVarStructDefine: structDefine,
})
doContent = replaceDefaultVar(in, doContent) doContent = replaceDefaultVar(in, doContent)
return doContent return doContent
} }

View File

@ -4,36 +4,32 @@ import (
"context" "context"
"strings" "strings"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gfile"
"github.com/gogf/gf/v2/text/gstr"
"github.com/gogf/gf/cmd/gf/v2/internal/consts" "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/mlog"
"github.com/gogf/gf/cmd/gf/v2/internal/utility/utils" "github.com/gogf/gf/cmd/gf/v2/internal/utility/utils"
"github.com/gogf/gf/v2/database/gdb"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gfile"
"github.com/gogf/gf/v2/text/gstr"
) )
func generateEntity(ctx context.Context, in CGenDaoInternalInput) { func generateEntity(ctx context.Context, db gdb.DB, tableNames, newTableNames []string, in CGenDaoInternalInput) {
var dirPathEntity = gfile.Join(in.Path, in.EntityPath) var entityDirPath = gfile.Join(in.Path, in.EntityPath)
if in.Clear {
doClear(ctx, dirPathEntity)
}
// Model content. // Model content.
for i, tableName := range in.TableNames { for i, tableName := range tableNames {
fieldMap, err := in.DB.TableFields(ctx, tableName) fieldMap, err := db.TableFields(ctx, tableName)
if err != nil { if err != nil {
mlog.Fatalf("fetching tables fields failed for table '%s':\n%v", tableName, err) mlog.Fatalf("fetching tables fields failed for table '%s':\n%v", in.TableName, err)
} }
var ( var (
newTableName = in.NewTableNames[i] newTableName = newTableNames[i]
entityFilePath = gfile.Join(dirPathEntity, gstr.CaseSnake(newTableName)+".go") entityFilePath = gfile.Join(entityDirPath, gstr.CaseSnake(newTableName)+".go")
entityContent = generateEntityContent( entityContent = generateEntityContent(
in, in,
newTableName, newTableName,
gstr.CaseCamel(newTableName), gstr.CaseCamel(newTableName),
generateStructDefinition(ctx, generateStructDefinitionInput{ generateStructDefinition(generateStructDefinitionInput{
CGenDaoInternalInput: in, CGenDaoInternalInput: in,
TableName: tableName,
StructName: gstr.CaseCamel(newTableName), StructName: gstr.CaseCamel(newTableName),
FieldMap: fieldMap, FieldMap: fieldMap,
IsDo: false, IsDo: false,
@ -51,14 +47,12 @@ func generateEntity(ctx context.Context, in CGenDaoInternalInput) {
} }
func generateEntityContent(in CGenDaoInternalInput, tableName, tableNameCamelCase, structDefine string) string { func generateEntityContent(in CGenDaoInternalInput, tableName, tableNameCamelCase, structDefine string) string {
entityContent := gstr.ReplaceByMap( entityContent := gstr.ReplaceByMap(consts.TemplateGenDaoEntityContent, g.MapStrStr{
getTemplateFromPathOrDefault(in.TplDaoEntityPath, consts.TemplateGenDaoEntityContent), tplVarTableName: tableName,
g.MapStrStr{ tplVarPackageImports: getImportPartContent(structDefine, false),
tplVarTableName: tableName, tplVarTableNameCamelCase: tableNameCamelCase,
tplVarPackageImports: getImportPartContent(structDefine, false), tplVarStructDefine: structDefine,
tplVarTableNameCamelCase: tableNameCamelCase, })
tplVarStructDefine: structDefine,
})
entityContent = replaceDefaultVar(in, entityContent) entityContent = replaceDefaultVar(in, entityContent)
return entityContent return entityContent
} }

View File

@ -2,8 +2,8 @@ package gendao
import ( import (
"bytes" "bytes"
"context"
"fmt" "fmt"
"strings"
"github.com/gogf/gf/v2/database/gdb" "github.com/gogf/gf/v2/database/gdb"
"github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/frame/g"
@ -14,19 +14,18 @@ import (
type generateStructDefinitionInput struct { type generateStructDefinitionInput struct {
CGenDaoInternalInput CGenDaoInternalInput
TableName string // Table name.
StructName string // Struct name. StructName string // Struct name.
FieldMap map[string]*gdb.TableField // Table field map. FieldMap map[string]*gdb.TableField // Table field map.
IsDo bool // Is generating DTO struct. IsDo bool // Is generating DTO struct.
} }
func generateStructDefinition(ctx context.Context, in generateStructDefinitionInput) string { func generateStructDefinition(in generateStructDefinitionInput) string {
buffer := bytes.NewBuffer(nil) buffer := bytes.NewBuffer(nil)
array := make([][]string, len(in.FieldMap)) array := make([][]string, len(in.FieldMap))
names := sortFieldKeyForDao(in.FieldMap) names := sortFieldKeyForDao(in.FieldMap)
for index, name := range names { for index, name := range names {
field := in.FieldMap[name] field := in.FieldMap[name]
array[index] = generateStructFieldDefinition(ctx, field, in) array[index] = generateStructFieldDefinition(field, in)
} }
tw := tablewriter.NewWriter(buffer) tw := tablewriter.NewWriter(buffer)
tw.SetBorder(false) tw.SetBorder(false)
@ -51,39 +50,92 @@ func generateStructDefinition(ctx context.Context, in generateStructDefinitionIn
} }
// generateStructFieldForModel generates and returns the attribute definition for specified field. // generateStructFieldForModel generates and returns the attribute definition for specified field.
func generateStructFieldDefinition( func generateStructFieldDefinition(field *gdb.TableField, in generateStructDefinitionInput) []string {
ctx context.Context, field *gdb.TableField, in generateStructDefinitionInput,
) []string {
var ( var (
err error
typeName string typeName string
jsonTag = getJsonTagFromCase(field.Name, in.JsonCase) jsonTag = getJsonTagFromCase(field.Name, in.JsonCase)
) )
typeName, err = in.DB.CheckLocalTypeForField(ctx, field.Type, nil) t, _ := gregex.ReplaceString(`\(.+\)`, "", field.Type)
if err != nil { t = gstr.Split(gstr.Trim(t), " ")[0]
panic(err) t = gstr.ToLower(t)
}
switch typeName { switch t {
case gdb.LocalTypeDate, gdb.LocalTypeDatetime: case "binary", "varbinary", "blob", "tinyblob", "mediumblob", "longblob":
typeName = "[]byte"
case "bit", "int", "int2", "tinyint", "small_int", "smallint", "medium_int", "mediumint", "serial":
if gstr.ContainsI(field.Type, "unsigned") {
typeName = "uint"
} else {
typeName = "int"
}
case "int4", "int8", "big_int", "bigint", "bigserial":
if gstr.ContainsI(field.Type, "unsigned") {
typeName = "uint64"
} else {
typeName = "int64"
}
// pgsql int32 slice.
case "_int2":
if gstr.ContainsI(field.Type, "unsigned") {
typeName = "[]uint"
} else {
typeName = "[]int"
}
// pgsql int64 slice.
case "_int4", "_int8":
if gstr.ContainsI(field.Type, "unsigned") {
typeName = "[]uint64"
} else {
typeName = "[]int64"
}
case "real":
typeName = "float32"
case "float", "double", "decimal", "smallmoney", "numeric":
typeName = "float64"
case "bool":
typeName = "bool"
case "datetime", "timestamp", "date", "time":
if in.StdTime { if in.StdTime {
typeName = "time.Time" typeName = "time.Time"
} else { } else {
typeName = "*gtime.Time" typeName = "*gtime.Time"
} }
case "json", "jsonb":
case gdb.LocalTypeInt64Bytes:
typeName = "int64"
case gdb.LocalTypeUint64Bytes:
typeName = "uint64"
// Special type handle.
case gdb.LocalTypeJson, gdb.LocalTypeJsonb:
if in.GJsonSupport { if in.GJsonSupport {
typeName = "*gjson.Json" typeName = "*gjson.Json"
} else { } else {
typeName = "string" typeName = "string"
} }
default:
// Automatically detect its data type.
switch {
case strings.Contains(t, "int"):
typeName = "int"
case strings.Contains(t, "text") || strings.Contains(t, "char"):
typeName = "string"
case strings.Contains(t, "float") || strings.Contains(t, "double"):
typeName = "float64"
case strings.Contains(t, "bool"):
typeName = "bool"
case strings.Contains(t, "binary") || strings.Contains(t, "blob"):
typeName = "[]byte"
case strings.Contains(t, "date") || strings.Contains(t, "time"):
if in.StdTime {
typeName = "time.Time"
} else {
typeName = "*gtime.Time"
}
default:
typeName = "string"
}
} }
var ( var (

View File

@ -1,277 +0,0 @@
package genservice
import (
"context"
"fmt"
"github.com/gogf/gf/v2/container/garray"
"github.com/gogf/gf/v2/container/gset"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gfile"
"github.com/gogf/gf/v2/os/gproc"
"github.com/gogf/gf/v2/os/gtime"
"github.com/gogf/gf/v2/text/gregex"
"github.com/gogf/gf/v2/text/gstr"
"github.com/gogf/gf/v2/util/gconv"
"github.com/gogf/gf/v2/util/gtag"
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
"github.com/gogf/gf/cmd/gf/v2/internal/utility/utils"
)
const (
CGenServiceConfig = `gfcli.gen.service`
CGenServiceUsage = `gf gen service [OPTION]`
CGenServiceBrief = `parse struct and associated functions from packages to generate service go file`
CGenServiceEg = `
gf gen service
gf gen service -f Snake
`
CGenServiceBriefSrcFolder = `source folder path to be parsed. default: internal/logic`
CGenServiceBriefDstFolder = `destination folder path storing automatically generated go files. default: internal/service`
CGenServiceBriefFileNameCase = `
destination file name storing automatically generated go files, cases are as follows:
| Case | Example |
|---------------- |--------------------|
| Lower | anykindofstring |
| Camel | AnyKindOfString |
| CamelLower | anyKindOfString |
| Snake | any_kind_of_string | default
| SnakeScreaming | ANY_KIND_OF_STRING |
| SnakeFirstUpper | rgb_code_md5 |
| Kebab | any-kind-of-string |
| KebabScreaming | ANY-KIND-OF-STRING |
`
CGenServiceBriefWatchFile = `used in file watcher, it re-generates all service go files only if given file is under srcFolder`
CGenServiceBriefStPattern = `regular expression matching struct name for generating service. default: ^s([A-Z]\\\\w+)$`
CGenServiceBriefPackages = `produce go files only for given source packages`
CGenServiceBriefImportPrefix = `custom import prefix to calculate import path for generated importing go file of logic`
CGenServiceBriefClear = `delete all generated go files that are not used any further`
)
func init() {
gtag.Sets(g.MapStrStr{
`CGenServiceConfig`: CGenServiceConfig,
`CGenServiceUsage`: CGenServiceUsage,
`CGenServiceBrief`: CGenServiceBrief,
`CGenServiceEg`: CGenServiceEg,
`CGenServiceBriefSrcFolder`: CGenServiceBriefSrcFolder,
`CGenServiceBriefDstFolder`: CGenServiceBriefDstFolder,
`CGenServiceBriefFileNameCase`: CGenServiceBriefFileNameCase,
`CGenServiceBriefWatchFile`: CGenServiceBriefWatchFile,
`CGenServiceBriefStPattern`: CGenServiceBriefStPattern,
`CGenServiceBriefPackages`: CGenServiceBriefPackages,
`CGenServiceBriefImportPrefix`: CGenServiceBriefImportPrefix,
`CGenServiceBriefClear`: CGenServiceBriefClear,
})
}
type (
CGenService struct{}
CGenServiceInput struct {
g.Meta `name:"service" config:"{CGenServiceConfig}" usage:"{CGenServiceUsage}" brief:"{CGenServiceBrief}" eg:"{CGenServiceEg}"`
SrcFolder string `short:"s" name:"srcFolder" brief:"{CGenServiceBriefSrcFolder}" d:"internal/logic"`
DstFolder string `short:"d" name:"dstFolder" brief:"{CGenServiceBriefDstFolder}" d:"internal/service"`
DstFileNameCase string `short:"f" name:"dstFileNameCase" brief:"{CGenServiceBriefFileNameCase}" d:"Snake"`
WatchFile string `short:"w" name:"watchFile" brief:"{CGenServiceBriefWatchFile}"`
StPattern string `short:"a" name:"stPattern" brief:"{CGenServiceBriefStPattern}" d:"^s([A-Z]\\w+)$"`
Packages []string `short:"p" name:"packages" brief:"{CGenServiceBriefPackages}"`
ImportPrefix string `short:"i" name:"importPrefix" brief:"{CGenServiceBriefImportPrefix}"`
Clear bool `short:"l" name:"clear" brief:"{CGenServiceBriefClear}" orphan:"true"`
}
CGenServiceOutput struct{}
)
const (
genServiceFileLockSeconds = 10
)
func (c CGenService) Service(ctx context.Context, in CGenServiceInput) (out *CGenServiceOutput, err error) {
// File lock to avoid multiple processes.
var (
flockFilePath = gfile.Temp("gf.cli.gen.service.lock")
flockContent = gfile.GetContents(flockFilePath)
)
if flockContent != "" {
if gtime.Timestamp()-gconv.Int64(flockContent) < genServiceFileLockSeconds {
// If another "gen service" process is running, it just exits.
mlog.Debug(`another "gen service" process is running, exit`)
return
}
}
defer gfile.Remove(flockFilePath)
_ = gfile.PutContents(flockFilePath, gtime.TimestampStr())
in.SrcFolder = gstr.TrimRight(in.SrcFolder, `\/`)
in.SrcFolder = gstr.Replace(in.SrcFolder, "\\", "/")
in.WatchFile = gstr.TrimRight(in.WatchFile, `\/`)
in.WatchFile = gstr.Replace(in.WatchFile, "\\", "/")
// Watch file handling.
if in.WatchFile != "" {
// It works only if given WatchFile is in SrcFolder.
var (
watchFileDir = gfile.Dir(in.WatchFile)
srcFolderDir = gfile.Dir(watchFileDir)
)
mlog.Debug("watchFileDir:", watchFileDir)
mlog.Debug("logicFolderDir:", srcFolderDir)
if !gstr.HasSuffix(gstr.Replace(srcFolderDir, `\`, `/`), in.SrcFolder) {
mlog.Printf(`ignore watch file "%s", not in source path "%s"`, in.WatchFile, in.SrcFolder)
return
}
var newWorkingDir = gfile.Dir(gfile.Dir(srcFolderDir))
if err = gfile.Chdir(newWorkingDir); err != nil {
mlog.Fatalf(`%+v`, err)
}
mlog.Debug("Chdir:", newWorkingDir)
_ = gfile.Remove(flockFilePath)
var command = fmt.Sprintf(
`%s gen service -packages=%s`,
gfile.SelfName(), gfile.Basename(watchFileDir),
)
err = gproc.ShellRun(ctx, command)
return
}
if !gfile.Exists(in.SrcFolder) {
mlog.Fatalf(`source folder path "%s" does not exist`, in.SrcFolder)
}
if in.ImportPrefix == "" {
if !gfile.Exists("go.mod") {
mlog.Fatal("ImportPrefix is empty and go.mod does not exist in current working directory")
}
var (
goModContent = gfile.GetContents("go.mod")
match, _ = gregex.MatchString(`^module\s+(.+)\s*`, goModContent)
)
if len(match) > 1 {
in.ImportPrefix = fmt.Sprintf(`%s/%s`, gstr.Trim(match[1]), gstr.Replace(in.SrcFolder, `\`, `/`))
}
}
var (
isDirty bool // Temp boolean.
files []string // Temp file array.
fileContent string // Temp file content for handling go file.
initImportSrcPackages []string // Used for generating logic.go.
inputPackages = in.Packages // Custom packages.
dstPackageName = gstr.ToLower(gfile.Basename(in.DstFolder)) // Package name for generated go files.
generatedDstFilePathSet = gset.NewStrSet() // All generated file path set.
)
// The first level folders.
srcFolderPaths, err := gfile.ScanDir(in.SrcFolder, "*", false)
if err != nil {
return nil, err
}
for _, srcFolderPath := range srcFolderPaths {
if !gfile.IsDir(srcFolderPath) {
continue
}
// Only retrieve sub files, no recursively.
if files, err = gfile.ScanDir(srcFolderPath, "*.go", false); err != nil {
return nil, err
}
if len(files) == 0 {
continue
}
var (
// StructName => FunctionDefinitions
srcPkgInterfaceMap = make(map[string]*garray.StrArray)
srcImportedPackages = garray.NewSortedStrArray().SetUnique(true)
srcPackageName = gfile.Basename(srcFolderPath)
ok bool
dstFilePath = gfile.Join(in.DstFolder,
c.getDstFileNameCase(srcPackageName, in.DstFileNameCase)+".go",
)
)
generatedDstFilePathSet.Add(dstFilePath)
for _, file := range files {
fileContent = gfile.GetContents(file)
// Calculate imported packages of source go files.
err = c.calculateImportedPackages(fileContent, srcImportedPackages)
if err != nil {
return nil, err
}
// Calculate functions and interfaces for service generating.
err = c.calculateInterfaceFunctions(in, fileContent, srcPkgInterfaceMap, dstPackageName)
if err != nil {
return nil, err
}
}
initImportSrcPackages = append(
initImportSrcPackages,
fmt.Sprintf(`%s/%s`, in.ImportPrefix, srcPackageName),
)
// Ignore source packages if input packages given.
if len(inputPackages) > 0 && !gstr.InArray(inputPackages, srcPackageName) {
mlog.Debugf(
`ignore source package "%s" as it is not in desired packages: %+v`,
srcPackageName, inputPackages,
)
continue
}
// Generating service go file for logic.
if ok, err = c.generateServiceFile(generateServiceFilesInput{
CGenServiceInput: in,
SrcStructFunctions: srcPkgInterfaceMap,
SrcImportedPackages: srcImportedPackages.Slice(),
SrcPackageName: srcPackageName,
DstPackageName: dstPackageName,
DstFilePath: dstFilePath,
}); err != nil {
return
}
if ok {
isDirty = true
}
}
if in.Clear {
files, err = gfile.ScanDirFile(in.DstFolder, "*.go", false)
if err != nil {
return nil, err
}
var relativeFilePath string
for _, file := range files {
relativeFilePath = gstr.SubStrFromR(file, in.DstFolder)
if !generatedDstFilePathSet.Contains(relativeFilePath) && utils.IsFileDoNotEdit(relativeFilePath) {
mlog.Printf(`remove no longer used service file: %s`, relativeFilePath)
if err = gfile.Remove(file); err != nil {
return nil, err
}
}
}
}
if isDirty {
// Generate initialization go file.
if len(initImportSrcPackages) > 0 {
if err = c.generateInitializationFile(in, initImportSrcPackages); err != nil {
return
}
}
// Replace v1 to v2 for GoFrame.
if err = c.replaceGeneratedServiceContentGFV2(in); err != nil {
return nil, err
}
mlog.Printf(`gofmt go files in "%s"`, in.DstFolder)
utils.GoFmt(in.DstFolder)
}
mlog.Print(`done!`)
return
}
func (c CGenService) replaceGeneratedServiceContentGFV2(in CGenServiceInput) (err error) {
return gfile.ReplaceDirFunc(func(path, content string) string {
if gstr.Contains(content, `"github.com/gogf/gf`) && !gstr.Contains(content, `"github.com/gogf/gf/v2`) {
content = gstr.Replace(content, `"github.com/gogf/gf"`, `"github.com/gogf/gf/v2"`)
content = gstr.Replace(content, `"github.com/gogf/gf/`, `"github.com/gogf/gf/v2/`)
return content
}
return content
}, in.DstFolder, "*.go", false)
}

View File

@ -1,105 +0,0 @@
package genservice
import (
"go/parser"
"go/token"
"github.com/gogf/gf/v2/container/garray"
"github.com/gogf/gf/v2/text/gregex"
"github.com/gogf/gf/v2/text/gstr"
)
func (c CGenService) calculateImportedPackages(fileContent string, srcImportedPackages *garray.SortedStrArray) (err error) {
f, err := parser.ParseFile(token.NewFileSet(), "", fileContent, parser.ImportsOnly)
if err != nil {
return err
}
for _, s := range f.Imports {
if s.Path != nil {
if s.Name != nil {
// If it has alias, and it is not `_`.
if pkgAlias := s.Name.String(); pkgAlias != "_" {
srcImportedPackages.Add(pkgAlias + " " + s.Path.Value)
}
} else {
// no alias
srcImportedPackages.Add(s.Path.Value)
}
}
}
return nil
}
func (c CGenService) calculateInterfaceFunctions(
in CGenServiceInput, fileContent string, srcPkgInterfaceMap map[string]*garray.StrArray, dstPackageName string,
) (err error) {
var (
ok bool
matches [][]string
srcPkgInterfaceFuncArray *garray.StrArray
)
// calculate struct name and its functions according function definitions.
matches, err = gregex.MatchAllString(`func \((.+?)\) ([\s\S]+?) {`, fileContent)
if err != nil {
return err
}
for _, match := range matches {
var (
structName string
structMatch []string
funcReceiver = gstr.Trim(match[1])
receiverArray = gstr.SplitAndTrim(funcReceiver, " ")
functionHead = gstr.Trim(gstr.Replace(match[2], "\n", ""))
)
if len(receiverArray) > 1 {
structName = receiverArray[1]
} else {
structName = receiverArray[0]
}
structName = gstr.Trim(structName, "*")
// Case of:
// Xxx(\n ctx context.Context, req *v1.XxxReq,\n) -> Xxx(ctx context.Context, req *v1.XxxReq)
functionHead = gstr.Replace(functionHead, `,)`, `)`)
functionHead, _ = gregex.ReplaceString(`\(\s+`, `(`, functionHead)
functionHead, _ = gregex.ReplaceString(`\s{2,}`, ` `, functionHead)
if !gstr.IsLetterUpper(functionHead[0]) {
continue
}
// Match and pick the struct name from receiver.
if structMatch, err = gregex.MatchString(in.StPattern, structName); err != nil {
return err
}
if len(structMatch) < 1 {
continue
}
structName = gstr.CaseCamel(structMatch[1])
if srcPkgInterfaceFuncArray, ok = srcPkgInterfaceMap[structName]; !ok {
srcPkgInterfaceMap[structName] = garray.NewStrArray()
srcPkgInterfaceFuncArray = srcPkgInterfaceMap[structName]
}
srcPkgInterfaceFuncArray.Append(functionHead)
}
// calculate struct name according type definitions.
matches, err = gregex.MatchAllString(`type (.+) struct\s*{`, fileContent)
if err != nil {
return err
}
for _, match := range matches {
var (
structName string
structMatch []string
)
if structMatch, err = gregex.MatchString(in.StPattern, match[1]); err != nil {
return err
}
if len(structMatch) < 1 {
continue
}
structName = gstr.CaseCamel(structMatch[1])
if srcPkgInterfaceFuncArray, ok = srcPkgInterfaceMap[structName]; !ok {
srcPkgInterfaceMap[structName] = garray.NewStrArray()
}
}
return nil
}

View File

@ -1,199 +0,0 @@
package genservice
import (
"fmt"
"github.com/gogf/gf/v2/container/garray"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gfile"
"github.com/gogf/gf/v2/text/gregex"
"github.com/gogf/gf/v2/text/gstr"
"github.com/gogf/gf/cmd/gf/v2/internal/consts"
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
"github.com/gogf/gf/cmd/gf/v2/internal/utility/utils"
)
type generateServiceFilesInput struct {
CGenServiceInput
DstFilePath string // Absolute file path for generated service go file.
SrcStructFunctions map[string]*garray.StrArray
SrcImportedPackages []string
SrcPackageName string
DstPackageName string
}
func (c CGenService) generateServiceFile(in generateServiceFilesInput) (ok bool, err error) {
var (
generatedContent string
allFuncArray = garray.NewStrArray() // Used for check whether interface dirty, going to change file content.
importedPackagesContent = fmt.Sprintf(
"import (\n%s\n)", gstr.Join(in.SrcImportedPackages, "\n"),
)
)
generatedContent += gstr.ReplaceByMap(consts.TemplateGenServiceContentHead, g.MapStrStr{
"{Imports}": importedPackagesContent,
"{PackageName}": in.DstPackageName,
})
// Type definitions.
generatedContent += "type("
generatedContent += "\n"
for structName, funcArray := range in.SrcStructFunctions {
allFuncArray.Append(funcArray.Slice()...)
generatedContent += gstr.Trim(gstr.ReplaceByMap(consts.TemplateGenServiceContentInterface, g.MapStrStr{
"{InterfaceName}": "I" + structName,
"{FuncDefinition}": funcArray.Join("\n\t"),
}))
generatedContent += "\n"
}
generatedContent += ")"
generatedContent += "\n"
// Generating variable and register definitions.
var (
variableContent string
generatingInterfaceCheck string
)
// Variable definitions.
for structName, _ := range in.SrcStructFunctions {
generatingInterfaceCheck = fmt.Sprintf(`[^\w\d]+%s.I%s[^\w\d]`, in.DstPackageName, structName)
if gregex.IsMatchString(generatingInterfaceCheck, generatedContent) {
continue
}
variableContent += gstr.Trim(gstr.ReplaceByMap(consts.TemplateGenServiceContentVariable, g.MapStrStr{
"{StructName}": structName,
"{InterfaceName}": "I" + structName,
}))
variableContent += "\n"
}
if variableContent != "" {
generatedContent += "var("
generatedContent += "\n"
generatedContent += variableContent
generatedContent += ")"
generatedContent += "\n"
}
// Variable register function definitions.
for structName, _ := range in.SrcStructFunctions {
generatingInterfaceCheck = fmt.Sprintf(`[^\w\d]+%s.I%s[^\w\d]`, in.DstPackageName, structName)
if gregex.IsMatchString(generatingInterfaceCheck, generatedContent) {
continue
}
generatedContent += gstr.Trim(gstr.ReplaceByMap(consts.TemplateGenServiceContentRegister, g.MapStrStr{
"{StructName}": structName,
"{InterfaceName}": "I" + structName,
}))
generatedContent += "\n\n"
}
// Replace empty braces that have new line.
generatedContent, _ = gregex.ReplaceString(`{[\s\t]+}`, `{}`, generatedContent)
// Remove package name calls of `dstPackageName` in produced codes.
generatedContent, _ = gregex.ReplaceString(fmt.Sprintf(`\*{0,1}%s\.`, in.DstPackageName), ``, generatedContent)
// Write file content to disk.
if gfile.Exists(in.DstFilePath) {
if !utils.IsFileDoNotEdit(in.DstFilePath) {
mlog.Printf(`ignore file as it is manually maintained: %s`, in.DstFilePath)
return false, nil
}
if !c.isToGenerateServiceGoFile(in.DstPackageName, in.DstFilePath, allFuncArray) {
mlog.Printf(`not dirty, ignore generating service go file: %s`, in.DstFilePath)
return false, nil
}
}
mlog.Printf(`generating service go file: %s`, in.DstFilePath)
if err = gfile.PutContents(in.DstFilePath, generatedContent); err != nil {
return true, err
}
return true, nil
}
// isToGenerateServiceGoFile checks and returns whether the service content dirty.
func (c CGenService) isToGenerateServiceGoFile(dstPackageName, filePath string, funcArray *garray.StrArray) bool {
var (
fileContent = gfile.GetContents(filePath)
generatedFuncArray = garray.NewSortedStrArrayFrom(funcArray.Slice())
contentFuncArray = garray.NewSortedStrArray()
)
if fileContent == "" {
return true
}
matches, _ := gregex.MatchAllString(`\s+interface\s+{([\s\S]+?)}`, fileContent)
for _, match := range matches {
contentFuncArray.Append(gstr.SplitAndTrim(match[1], "\n")...)
}
if generatedFuncArray.Len() != contentFuncArray.Len() {
mlog.Debugf(
`dirty, generatedFuncArray.Len()[%d] != contentFuncArray.Len()[%d]`,
generatedFuncArray.Len(), contentFuncArray.Len(),
)
return true
}
var funcDefinition string
for i := 0; i < generatedFuncArray.Len(); i++ {
funcDefinition, _ = gregex.ReplaceString(
fmt.Sprintf(`\*{0,1}%s\.`, dstPackageName), ``, generatedFuncArray.At(i),
)
if funcDefinition != contentFuncArray.At(i) {
mlog.Debugf(`dirty, %s != %s`, funcDefinition, contentFuncArray.At(i))
return true
}
}
return false
}
func (c CGenService) generateInitializationFile(in CGenServiceInput, importSrcPackages []string) (err error) {
var (
srcPackageName = gstr.ToLower(gfile.Basename(in.SrcFolder))
srcFilePath = gfile.Join(in.SrcFolder, srcPackageName+".go")
srcImports string
generatedContent string
)
if !utils.IsFileDoNotEdit(srcFilePath) {
mlog.Debugf(`ignore file as it is manually maintained: %s`, srcFilePath)
return nil
}
for _, importSrcPackage := range importSrcPackages {
srcImports += fmt.Sprintf(`%s_ "%s"%s`, "\t", importSrcPackage, "\n")
}
generatedContent = gstr.ReplaceByMap(consts.TemplateGenServiceLogicContent, g.MapStrStr{
"{PackageName}": srcPackageName,
"{Imports}": srcImports,
})
mlog.Printf(`generating init go file: %s`, srcFilePath)
if err = gfile.PutContents(srcFilePath, generatedContent); err != nil {
return err
}
utils.GoFmt(srcFilePath)
return nil
}
// getDstFileNameCase call gstr.Case* function to convert the s to specified case.
func (c CGenService) getDstFileNameCase(str, caseStr string) string {
switch gstr.ToLower(caseStr) {
case gstr.ToLower("Lower"):
return gstr.ToLower(str)
case gstr.ToLower("Camel"):
return gstr.CaseCamel(str)
case gstr.ToLower("CamelLower"):
return gstr.CaseCamelLower(str)
case gstr.ToLower("Kebab"):
return gstr.CaseKebab(str)
case gstr.ToLower("KebabScreaming"):
return gstr.CaseKebabScreaming(str)
case gstr.ToLower("SnakeFirstUpper"):
return gstr.CaseSnakeFirstUpper(str)
case gstr.ToLower("SnakeScreaming"):
return gstr.CaseSnakeScreaming(str)
}
return gstr.CaseSnake(str)
}

View File

@ -1,6 +1,6 @@
package consts package consts
const TemplateGenDaoIndexContent = ` const TemplateDaoDaoIndexContent = `
// ================================================================================= // =================================================================================
// This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish. // This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish.
// ================================================================================= // =================================================================================
@ -31,9 +31,9 @@ var (
` `
const TemplateGenDaoInternalContent = ` const TemplateDaoDaoInternalContent = `
// ========================================================================== // ==========================================================================
// Code generated by GoFrame CLI tool. DO NOT EDIT. {TplCreatedAtDatetimeStr} // Code generated by GoFrame CLI tool. DO NOT EDIT. {TplDatetimeStr}
// ========================================================================== // ==========================================================================
package internal package internal
@ -57,7 +57,7 @@ type {TplTableNameCamelCase}Columns struct {
{TplColumnDefine} {TplColumnDefine}
} }
// {TplTableNameCamelLowerCase}Columns holds the columns for table {TplTableName}. // {TplTableNameCamelLowerCase}Columns holds the columns for table {TplTableName}.
var {TplTableNameCamelLowerCase}Columns = {TplTableNameCamelCase}Columns{ var {TplTableNameCamelLowerCase}Columns = {TplTableNameCamelCase}Columns{
{TplColumnNames} {TplColumnNames}
} }
@ -102,7 +102,7 @@ func (dao *{TplTableNameCamelCase}Dao) Ctx(ctx context.Context) *gdb.Model {
// //
// Note that, you should not Commit or Rollback the transaction in function f // Note that, you should not Commit or Rollback the transaction in function f
// as it is automatically handled by this function. // as it is automatically handled by this function.
func (dao *{TplTableNameCamelCase}Dao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) { func (dao *{TplTableNameCamelCase}Dao) Transaction(ctx context.Context, f func(ctx context.Context, tx *gdb.TX) error) (err error) {
return dao.Ctx(ctx).Transaction(ctx, f) return dao.Ctx(ctx).Transaction(ctx, f)
} }
` `

View File

@ -2,7 +2,7 @@ package consts
const TemplateGenDaoDoContent = ` const TemplateGenDaoDoContent = `
// ================================================================================= // =================================================================================
// Code generated by GoFrame CLI tool. DO NOT EDIT. {TplCreatedAtDatetimeStr} // Code generated by GoFrame CLI tool. DO NOT EDIT. {TplDatetimeStr}
// ================================================================================= // =================================================================================
package do package do

View File

@ -2,7 +2,7 @@ package consts
const TemplateGenDaoEntityContent = ` const TemplateGenDaoEntityContent = `
// ================================================================================= // =================================================================================
// Code generated by GoFrame CLI tool. DO NOT EDIT. {TplCreatedAtDatetimeStr} // Code generated by GoFrame CLI tool. DO NOT EDIT. {TplDatetimeStr}
// ================================================================================= // =================================================================================
package entity package entity

View File

@ -1,35 +1,28 @@
package consts package consts
const TemplateGenServiceContentHead = ` const TemplateGenServiceContent = `
// ================================================================================ // ==========================================================================
// Code generated by GoFrame CLI tool. DO NOT EDIT. // Code generated by GoFrame CLI tool. DO NOT EDIT.
// You can delete these comments if you wish manually maintain this interface file. // ==========================================================================
// ================================================================================
package {PackageName} package {PackageName}
{Imports} {Imports}
`
const TemplateGenServiceContentInterface = ` type I{StructName} interface {
{InterfaceName} interface {
{FuncDefinition} {FuncDefinition}
} }
`
const TemplateGenServiceContentVariable = ` var local{StructName} I{StructName}
local{StructName} {InterfaceName}
`
const TemplateGenServiceContentRegister = ` func {StructName}() I{StructName} {
func {StructName}() {InterfaceName} {
if local{StructName} == nil { if local{StructName} == nil {
panic("implement not found for interface {InterfaceName}, forgot register?") panic("implement not found for interface I{StructName}, forgot register?")
} }
return local{StructName} return local{StructName}
} }
func Register{StructName}(i {InterfaceName}) { func Register{StructName}(i I{StructName}) {
local{StructName} = i local{StructName} = i
} }
` `

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -5,6 +5,8 @@ import (
"runtime" "runtime"
"strings" "strings"
"github.com/gogf/gf/cmd/gf/v2/internal/utility/allyes"
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
"github.com/gogf/gf/v2/container/garray" "github.com/gogf/gf/v2/container/garray"
"github.com/gogf/gf/v2/container/gset" "github.com/gogf/gf/v2/container/gset"
"github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/frame/g"
@ -13,9 +15,6 @@ import (
"github.com/gogf/gf/v2/os/gfile" "github.com/gogf/gf/v2/os/gfile"
"github.com/gogf/gf/v2/text/gstr" "github.com/gogf/gf/v2/text/gstr"
"github.com/gogf/gf/v2/util/gconv" "github.com/gogf/gf/v2/util/gconv"
"github.com/gogf/gf/cmd/gf/v2/internal/utility/allyes"
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
) )
var ( var (
@ -119,13 +118,20 @@ func (s serviceInstall) Run(ctx context.Context) (err error) {
dstPath := paths[selectedID] dstPath := paths[selectedID]
// Install the new binary. // Install the new binary.
mlog.Debugf(`copy file from "%s" to "%s"`, gfile.SelfPath(), dstPath.filePath)
err = gfile.CopyFile(gfile.SelfPath(), dstPath.filePath) err = gfile.CopyFile(gfile.SelfPath(), dstPath.filePath)
if err != nil { if err != nil {
mlog.Printf("install gf binary to '%s' failed: %v", dstPath.dirPath, err) mlog.Printf("install gf binary to '%s' failed: %v", dstPath.dirPath, err)
mlog.Printf("you can manually install gf by copying the binary to folder: %s", dstPath.dirPath) mlog.Printf("you can manually install gf by copying the binary to folder: %s", dstPath.dirPath)
} else { } else {
mlog.Printf("gf binary is successfully installed to: %s", dstPath.filePath) mlog.Printf("gf binary is successfully installed to: %s", dstPath.dirPath)
}
// Uninstall the old binary.
for _, path := range paths {
// Do not delete myself.
if path.filePath != "" && path.filePath != dstPath.filePath && gfile.SelfPath() != path.filePath {
_ = gfile.Remove(path.filePath)
}
} }
return return
} }

View File

@ -1,12 +1,9 @@
package utils package utils
import ( import (
"context"
"fmt"
"github.com/gogf/gf/cmd/gf/v2/internal/consts" "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/mlog"
"github.com/gogf/gf/v2/os/gfile" "github.com/gogf/gf/v2/os/gfile"
"github.com/gogf/gf/v2/os/gproc"
"github.com/gogf/gf/v2/text/gstr" "github.com/gogf/gf/v2/text/gstr"
"golang.org/x/tools/imports" "golang.org/x/tools/imports"
) )
@ -38,13 +35,6 @@ func GoFmt(path string) {
} }
} }
// GoModTidy executes `go mod tidy` at specified directory `dirPath`.
func GoModTidy(ctx context.Context, dirPath string) error {
command := fmt.Sprintf(`cd %s && go mod tidy`, dirPath)
err := gproc.ShellRun(ctx, command)
return err
}
// IsFileDoNotEdit checks and returns whether file contains `do not edit` key. // IsFileDoNotEdit checks and returns whether file contains `do not edit` key.
func IsFileDoNotEdit(filePath string) bool { func IsFileDoNotEdit(filePath string) bool {
if !gfile.Exists(filePath) { if !gfile.Exists(filePath) {

View File

@ -1,98 +0,0 @@
package utils
import (
"fmt"
"github.com/gogf/gf/v2/errors/gerror"
"io"
"net/http"
"os"
"strconv"
"time"
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
)
// HTTPDownloadFileWithPercent downloads target url file to local path with percent process printing.
func HTTPDownloadFileWithPercent(url string, localSaveFilePath string) error {
start := time.Now()
out, err := os.Create(localSaveFilePath)
if err != nil {
return gerror.Wrapf(err, `download "%s" to "%s" failed`, url, localSaveFilePath)
}
defer out.Close()
headResp, err := http.Head(url)
if err != nil {
return gerror.Wrapf(err, `download "%s" to "%s" failed`, url, localSaveFilePath)
}
defer headResp.Body.Close()
size, err := strconv.Atoi(headResp.Header.Get("Content-Length"))
if err != nil {
return gerror.Wrap(err, "retrieve Content-Length failed")
}
doneCh := make(chan int64)
go doPrintDownloadPercent(doneCh, localSaveFilePath, int64(size))
resp, err := http.Get(url)
if err != nil {
return gerror.Wrapf(err, `download "%s" to "%s" failed`, url, localSaveFilePath)
}
defer resp.Body.Close()
wroteBytesCount, err := io.Copy(out, resp.Body)
if err != nil {
return gerror.Wrapf(err, `download "%s" to "%s" failed`, url, localSaveFilePath)
}
doneCh <- wroteBytesCount
elapsed := time.Since(start)
if elapsed > time.Minute {
mlog.Printf(`download completed in %.0fm`, float64(elapsed)/float64(time.Minute))
} else {
mlog.Printf(`download completed in %.0fs`, elapsed.Seconds())
}
return nil
}
func doPrintDownloadPercent(doneCh chan int64, localSaveFilePath string, total int64) {
var (
stop = false
lastPercentFmt string
)
for {
select {
case <-doneCh:
stop = true
default:
file, err := os.Open(localSaveFilePath)
if err != nil {
mlog.Fatal(err)
}
fi, err := file.Stat()
if err != nil {
mlog.Fatal(err)
}
size := fi.Size()
if size == 0 {
size = 1
}
var (
percent = float64(size) / float64(total) * 100
percentFmt = fmt.Sprintf(`%.0f`, percent) + "%"
)
if lastPercentFmt != percentFmt {
lastPercentFmt = percentFmt
mlog.Print(percentFmt)
}
}
if stop {
break
}
time.Sleep(time.Second)
}
}

View File

@ -2,17 +2,16 @@ package main
import ( import (
_ "github.com/gogf/gf/cmd/gf/v2/internal/packed" _ "github.com/gogf/gf/cmd/gf/v2/internal/packed"
"github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gcfg" "github.com/gogf/gf/v2/os/gcfg"
"github.com/gogf/gf/v2/os/gcmd"
"github.com/gogf/gf/v2/os/gctx"
"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/cmd"
"github.com/gogf/gf/cmd/gf/v2/internal/utility/allyes" "github.com/gogf/gf/cmd/gf/v2/internal/utility/allyes"
"github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog" "github.com/gogf/gf/cmd/gf/v2/internal/utility/mlog"
"github.com/gogf/gf/v2/os/gcmd"
"github.com/gogf/gf/v2/os/gctx"
"github.com/gogf/gf/v2/os/gfile"
"github.com/gogf/gf/v2/text/gstr"
) )
const ( const (
@ -53,9 +52,7 @@ func main() {
panic(err) panic(err)
} }
err = command.AddObject( err = command.AddObject(
cmd.Up,
cmd.Env, cmd.Env,
cmd.Fix,
cmd.Run, cmd.Run,
cmd.Gen, cmd.Gen,
cmd.Tpl, cmd.Tpl,
@ -69,10 +66,7 @@ func main() {
if err != nil { if err != nil {
panic(err) panic(err)
} }
err = command.RunWithError(ctx) command.Run(ctx)
if err != nil {
panic(err)
}
} }
// zsh alias "git fetch" conflicts checks. // zsh alias "git fetch" conflicts checks.

View File

@ -53,16 +53,16 @@ func NewArraySize(size int, cap int, safe ...bool) *Array {
} }
} }
// NewArrayRange creates and returns an array by a range from `start` to `end` // NewArrayRange creates and returns a array by a range from `start` to `end`
// with step value `step`. // with step value `step`.
func NewArrayRange(start, end, step int, safe ...bool) *Array { func NewArrayRange(start, end, step int, safe ...bool) *Array {
if step == 0 { if step == 0 {
panic(fmt.Sprintf(`invalid step value: %d`, step)) panic(fmt.Sprintf(`invalid step value: %d`, step))
} }
slice := make([]interface{}, 0) slice := make([]interface{}, (end-start+1)/step)
index := 0 index := 0
for i := start; i <= end; i += step { for i := start; i <= end; i += step {
slice = append(slice, i) slice[index] = i
index++ index++
} }
return NewArrayFrom(slice, safe...) return NewArrayFrom(slice, safe...)
@ -173,28 +173,28 @@ func (a *Array) SortFunc(less func(v1, v2 interface{}) bool) *Array {
return a return a
} }
// InsertBefore inserts the `values` to the front of `index`. // InsertBefore inserts the `value` to the front of `index`.
func (a *Array) InsertBefore(index int, values ...interface{}) error { func (a *Array) InsertBefore(index int, value interface{}) error {
a.mu.Lock() a.mu.Lock()
defer a.mu.Unlock() defer a.mu.Unlock()
if index < 0 || index >= len(a.array) { if index < 0 || index >= len(a.array) {
return gerror.NewCodef(gcode.CodeInvalidParameter, "index %d out of array range %d", index, len(a.array)) return gerror.NewCodef(gcode.CodeInvalidParameter, "index %d out of array range %d", index, len(a.array))
} }
rear := append([]interface{}{}, a.array[index:]...) rear := append([]interface{}{}, a.array[index:]...)
a.array = append(a.array[0:index], values...) a.array = append(a.array[0:index], value)
a.array = append(a.array, rear...) a.array = append(a.array, rear...)
return nil return nil
} }
// InsertAfter inserts the `values` to the back of `index`. // InsertAfter inserts the `value` to the back of `index`.
func (a *Array) InsertAfter(index int, values ...interface{}) error { func (a *Array) InsertAfter(index int, value interface{}) error {
a.mu.Lock() a.mu.Lock()
defer a.mu.Unlock() defer a.mu.Unlock()
if index < 0 || index >= len(a.array) { if index < 0 || index >= len(a.array) {
return gerror.NewCodef(gcode.CodeInvalidParameter, "index %d out of array range %d", index, len(a.array)) return gerror.NewCodef(gcode.CodeInvalidParameter, "index %d out of array range %d", index, len(a.array))
} }
rear := append([]interface{}{}, a.array[index+1:]...) rear := append([]interface{}{}, a.array[index+1:]...)
a.array = append(a.array[0:index+1], values...) a.array = append(a.array[0:index+1], value)
a.array = append(a.array, rear...) a.array = append(a.array, rear...)
return nil return nil
} }

View File

@ -45,16 +45,16 @@ func NewIntArraySize(size int, cap int, safe ...bool) *IntArray {
} }
} }
// NewIntArrayRange creates and returns an array by a range from `start` to `end` // NewIntArrayRange creates and returns a array by a range from `start` to `end`
// with step value `step`. // with step value `step`.
func NewIntArrayRange(start, end, step int, safe ...bool) *IntArray { func NewIntArrayRange(start, end, step int, safe ...bool) *IntArray {
if step == 0 { if step == 0 {
panic(fmt.Sprintf(`invalid step value: %d`, step)) panic(fmt.Sprintf(`invalid step value: %d`, step))
} }
slice := make([]int, 0) slice := make([]int, (end-start+1)/step)
index := 0 index := 0
for i := start; i <= end; i += step { for i := start; i <= end; i += step {
slice = append(slice, i) slice[index] = i
index++ index++
} }
return NewIntArrayFrom(slice, safe...) return NewIntArrayFrom(slice, safe...)
@ -168,28 +168,28 @@ func (a *IntArray) SortFunc(less func(v1, v2 int) bool) *IntArray {
return a return a
} }
// InsertBefore inserts the `values` to the front of `index`. // InsertBefore inserts the `value` to the front of `index`.
func (a *IntArray) InsertBefore(index int, values ...int) error { func (a *IntArray) InsertBefore(index int, value int) error {
a.mu.Lock() a.mu.Lock()
defer a.mu.Unlock() defer a.mu.Unlock()
if index < 0 || index >= len(a.array) { if index < 0 || index >= len(a.array) {
return gerror.NewCodef(gcode.CodeInvalidParameter, "index %d out of array range %d", index, len(a.array)) return gerror.NewCodef(gcode.CodeInvalidParameter, "index %d out of array range %d", index, len(a.array))
} }
rear := append([]int{}, a.array[index:]...) rear := append([]int{}, a.array[index:]...)
a.array = append(a.array[0:index], values...) a.array = append(a.array[0:index], value)
a.array = append(a.array, rear...) a.array = append(a.array, rear...)
return nil return nil
} }
// InsertAfter inserts the `value` to the back of `index`. // InsertAfter inserts the `value` to the back of `index`.
func (a *IntArray) InsertAfter(index int, values ...int) error { func (a *IntArray) InsertAfter(index int, value int) error {
a.mu.Lock() a.mu.Lock()
defer a.mu.Unlock() defer a.mu.Unlock()
if index < 0 || index >= len(a.array) { if index < 0 || index >= len(a.array) {
return gerror.NewCodef(gcode.CodeInvalidParameter, "index %d out of array range %d", index, len(a.array)) return gerror.NewCodef(gcode.CodeInvalidParameter, "index %d out of array range %d", index, len(a.array))
} }
rear := append([]int{}, a.array[index+1:]...) rear := append([]int{}, a.array[index+1:]...)
a.array = append(a.array[0:index+1], values...) a.array = append(a.array[0:index+1], value)
a.array = append(a.array, rear...) a.array = append(a.array, rear...)
return nil return nil
} }

View File

@ -155,28 +155,28 @@ func (a *StrArray) SortFunc(less func(v1, v2 string) bool) *StrArray {
return a return a
} }
// InsertBefore inserts the `values` to the front of `index`. // InsertBefore inserts the `value` to the front of `index`.
func (a *StrArray) InsertBefore(index int, values ...string) error { func (a *StrArray) InsertBefore(index int, value string) error {
a.mu.Lock() a.mu.Lock()
defer a.mu.Unlock() defer a.mu.Unlock()
if index < 0 || index >= len(a.array) { if index < 0 || index >= len(a.array) {
return gerror.NewCodef(gcode.CodeInvalidParameter, "index %d out of array range %d", index, len(a.array)) return gerror.NewCodef(gcode.CodeInvalidParameter, "index %d out of array range %d", index, len(a.array))
} }
rear := append([]string{}, a.array[index:]...) rear := append([]string{}, a.array[index:]...)
a.array = append(a.array[0:index], values...) a.array = append(a.array[0:index], value)
a.array = append(a.array, rear...) a.array = append(a.array, rear...)
return nil return nil
} }
// InsertAfter inserts the `values` to the back of `index`. // InsertAfter inserts the `value` to the back of `index`.
func (a *StrArray) InsertAfter(index int, values ...string) error { func (a *StrArray) InsertAfter(index int, value string) error {
a.mu.Lock() a.mu.Lock()
defer a.mu.Unlock() defer a.mu.Unlock()
if index < 0 || index >= len(a.array) { if index < 0 || index >= len(a.array) {
return gerror.NewCodef(gcode.CodeInvalidParameter, "index %d out of array range %d", index, len(a.array)) return gerror.NewCodef(gcode.CodeInvalidParameter, "index %d out of array range %d", index, len(a.array))
} }
rear := append([]string{}, a.array[index+1:]...) rear := append([]string{}, a.array[index+1:]...)
a.array = append(a.array[0:index+1], values...) a.array = append(a.array[0:index+1], value)
a.array = append(a.array, rear...) a.array = append(a.array, rear...)
return nil return nil
} }

View File

@ -55,16 +55,16 @@ func NewSortedArraySize(cap int, comparator func(a, b interface{}) int, safe ...
} }
} }
// NewSortedArrayRange creates and returns an array by a range from `start` to `end` // NewSortedArrayRange creates and returns a array by a range from `start` to `end`
// with step value `step`. // with step value `step`.
func NewSortedArrayRange(start, end, step int, comparator func(a, b interface{}) int, safe ...bool) *SortedArray { func NewSortedArrayRange(start, end, step int, comparator func(a, b interface{}) int, safe ...bool) *SortedArray {
if step == 0 { if step == 0 {
panic(fmt.Sprintf(`invalid step value: %d`, step)) panic(fmt.Sprintf(`invalid step value: %d`, step))
} }
slice := make([]interface{}, 0) slice := make([]interface{}, (end-start+1)/step)
index := 0 index := 0
for i := start; i <= end; i += step { for i := start; i <= end; i += step {
slice = append(slice, i) slice[index] = i
index++ index++
} }
return NewSortedArrayFrom(slice, comparator, safe...) return NewSortedArrayFrom(slice, comparator, safe...)

View File

@ -56,16 +56,16 @@ func NewSortedIntArraySize(cap int, safe ...bool) *SortedIntArray {
} }
} }
// NewSortedIntArrayRange creates and returns an array by a range from `start` to `end` // NewSortedIntArrayRange creates and returns a array by a range from `start` to `end`
// with step value `step`. // with step value `step`.
func NewSortedIntArrayRange(start, end, step int, safe ...bool) *SortedIntArray { func NewSortedIntArrayRange(start, end, step int, safe ...bool) *SortedIntArray {
if step == 0 { if step == 0 {
panic(fmt.Sprintf(`invalid step value: %d`, step)) panic(fmt.Sprintf(`invalid step value: %d`, step))
} }
slice := make([]int, 0) slice := make([]int, (end-start+1)/step)
index := 0 index := 0
for i := start; i <= end; i += step { for i := start; i <= end; i += step {
slice = append(slice, i) slice[index] = i
index++ index++
} }
return NewSortedIntArrayFrom(slice, safe...) return NewSortedIntArrayFrom(slice, safe...)

View File

@ -59,7 +59,7 @@ func ExampleNewIntArrayRange() {
fmt.Println(s.Slice(), s.Len(), cap(s.Slice())) fmt.Println(s.Slice(), s.Len(), cap(s.Slice()))
// Output: // Output:
// [1 2 3 4 5] 5 8 // [1 2 3 4 5] 5 5
} }
func ExampleNewIntArrayFrom() { func ExampleNewIntArrayFrom() {

View File

@ -813,14 +813,3 @@ func TestIntArray_Walk(t *testing.T) {
}), g.Slice{11, 12}) }), g.Slice{11, 12})
}) })
} }
func TestIntArray_NewIntArrayRange(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
array := garray.NewIntArrayRange(0, 128, 4)
t.Assert(array.String(), `[0,4,8,12,16,20,24,28,32,36,40,44,48,52,56,60,64,68,72,76,80,84,88,92,96,100,104,108,112,116,120,124,128]`)
})
gtest.C(t, func(t *gtest.T) {
array := garray.NewIntArrayRange(1, 128, 4)
t.Assert(array.String(), `[1,5,9,13,17,21,25,29,33,37,41,45,49,53,57,61,65,69,73,77,81,85,89,93,97,101,105,109,113,117,121,125]`)
})
}

View File

@ -9,6 +9,7 @@
package garray_test package garray_test
import ( import (
"github.com/gogf/gf/v2/text/gstr"
"testing" "testing"
"time" "time"
@ -16,7 +17,6 @@ import (
"github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/internal/json" "github.com/gogf/gf/v2/internal/json"
"github.com/gogf/gf/v2/test/gtest" "github.com/gogf/gf/v2/test/gtest"
"github.com/gogf/gf/v2/text/gstr"
"github.com/gogf/gf/v2/util/gconv" "github.com/gogf/gf/v2/util/gconv"
) )

View File

@ -407,6 +407,7 @@ func (l *List) Removes(es []*Element) {
for _, e := range es { for _, e := range es {
l.list.Remove(e) l.list.Remove(e)
} }
return
} }
// RemoveAll removes all elements from list `l`. // RemoveAll removes all elements from list `l`.

View File

@ -157,7 +157,7 @@ func (m *AnyAnyMap) Search(key interface{}) (value interface{}, found bool) {
func (m *AnyAnyMap) Get(key interface{}) (value interface{}) { func (m *AnyAnyMap) Get(key interface{}) (value interface{}) {
m.mu.RLock() m.mu.RLock()
if m.data != nil { if m.data != nil {
value = m.data[key] value, _ = m.data[key]
} }
m.mu.RUnlock() m.mu.RUnlock()
return return

View File

@ -157,7 +157,7 @@ func (m *IntAnyMap) Search(key int) (value interface{}, found bool) {
func (m *IntAnyMap) Get(key int) (value interface{}) { func (m *IntAnyMap) Get(key int) (value interface{}) {
m.mu.RLock() m.mu.RLock()
if m.data != nil { if m.data != nil {
value = m.data[key] value, _ = m.data[key]
} }
m.mu.RUnlock() m.mu.RUnlock()
return return

View File

@ -143,7 +143,7 @@ func (m *IntIntMap) Search(key int) (value int, found bool) {
func (m *IntIntMap) Get(key int) (value int) { func (m *IntIntMap) Get(key int) (value int) {
m.mu.RLock() m.mu.RLock()
if m.data != nil { if m.data != nil {
value = m.data[key] value, _ = m.data[key]
} }
m.mu.RUnlock() m.mu.RUnlock()
return return

View File

@ -143,7 +143,7 @@ func (m *IntStrMap) Search(key int) (value string, found bool) {
func (m *IntStrMap) Get(key int) (value string) { func (m *IntStrMap) Get(key int) (value string) {
m.mu.RLock() m.mu.RLock()
if m.data != nil { if m.data != nil {
value = m.data[key] value, _ = m.data[key]
} }
m.mu.RUnlock() m.mu.RUnlock()
return return

View File

@ -16,7 +16,6 @@ import (
"github.com/gogf/gf/v2/util/gconv" "github.com/gogf/gf/v2/util/gconv"
) )
// StrAnyMap implements map[string]interface{} with RWMutex that has switch.
type StrAnyMap struct { type StrAnyMap struct {
mu rwmutex.RWMutex mu rwmutex.RWMutex
data map[string]interface{} data map[string]interface{}
@ -152,7 +151,7 @@ func (m *StrAnyMap) Search(key string) (value interface{}, found bool) {
func (m *StrAnyMap) Get(key string) (value interface{}) { func (m *StrAnyMap) Get(key string) (value interface{}) {
m.mu.RLock() m.mu.RLock()
if m.data != nil { if m.data != nil {
value = m.data[key] value, _ = m.data[key]
} }
m.mu.RUnlock() m.mu.RUnlock()
return return

View File

@ -144,7 +144,7 @@ func (m *StrIntMap) Search(key string) (value int, found bool) {
func (m *StrIntMap) Get(key string) (value int) { func (m *StrIntMap) Get(key string) (value int) {
m.mu.RLock() m.mu.RLock()
if m.data != nil { if m.data != nil {
value = m.data[key] value, _ = m.data[key]
} }
m.mu.RUnlock() m.mu.RUnlock()
return return

View File

@ -144,7 +144,7 @@ func (m *StrStrMap) Search(key string) (value string, found bool) {
func (m *StrStrMap) Get(key string) (value string) { func (m *StrStrMap) Get(key string) (value string) {
m.mu.RLock() m.mu.RLock()
if m.data != nil { if m.data != nil {
value = m.data[key] value, _ = m.data[key]
} }
m.mu.RUnlock() m.mu.RUnlock()
return return

View File

@ -101,7 +101,6 @@ func Test_Map_Basic(t *testing.T) {
t.Assert(m2.Map(), map[interface{}]interface{}{1: 1, "key1": "val1"}) t.Assert(m2.Map(), map[interface{}]interface{}{1: 1, "key1": "val1"})
}) })
} }
func Test_Map_Set_Fun(t *testing.T) { func Test_Map_Set_Fun(t *testing.T) {
gtest.C(t, func(t *gtest.T) { gtest.C(t, func(t *gtest.T) {
m := gmap.New() m := gmap.New()
@ -124,7 +123,6 @@ func Test_Map_Batch(t *testing.T) {
t.Assert(m.Map(), map[interface{}]interface{}{"key2": "val2", "key3": "val3"}) t.Assert(m.Map(), map[interface{}]interface{}{"key2": "val2", "key3": "val3"})
}) })
} }
func Test_Map_Iterator(t *testing.T) { func Test_Map_Iterator(t *testing.T) {
gtest.C(t, func(t *gtest.T) { gtest.C(t, func(t *gtest.T) {
expect := map[interface{}]interface{}{1: 1, "key1": "val1"} expect := map[interface{}]interface{}{1: 1, "key1": "val1"}
@ -177,7 +175,6 @@ func Test_Map_Clone(t *testing.T) {
t.AssertIN("key1", m.Keys()) t.AssertIN("key1", m.Keys())
}) })
} }
func Test_Map_Basic_Merge(t *testing.T) { func Test_Map_Basic_Merge(t *testing.T) {
gtest.C(t, func(t *gtest.T) { gtest.C(t, func(t *gtest.T) {
m1 := gmap.New() m1 := gmap.New()

View File

@ -16,9 +16,7 @@ import (
) )
var hashMap = gmap.New(true) var hashMap = gmap.New(true)
var listMap = gmap.NewListMap(true) var listMap = gmap.NewListMap(true)
var treeMap = gmap.NewTreeMap(gutil.ComparatorInt, true) var treeMap = gmap.NewTreeMap(gutil.ComparatorInt, true)
func Benchmark_HashMap_Set(b *testing.B) { func Benchmark_HashMap_Set(b *testing.B) {

View File

@ -16,17 +16,11 @@ import (
) )
var anyAnyMap = gmap.NewAnyAnyMap(true) var anyAnyMap = gmap.NewAnyAnyMap(true)
var intIntMap = gmap.NewIntIntMap(true) var intIntMap = gmap.NewIntIntMap(true)
var intAnyMap = gmap.NewIntAnyMap(true) var intAnyMap = gmap.NewIntAnyMap(true)
var intStrMap = gmap.NewIntStrMap(true) var intStrMap = gmap.NewIntStrMap(true)
var strIntMap = gmap.NewStrIntMap(true) var strIntMap = gmap.NewStrIntMap(true)
var strAnyMap = gmap.NewStrAnyMap(true) var strAnyMap = gmap.NewStrAnyMap(true)
var strStrMap = gmap.NewStrStrMap(true) var strStrMap = gmap.NewStrStrMap(true)
func Benchmark_IntIntMap_Set(b *testing.B) { func Benchmark_IntIntMap_Set(b *testing.B) {

View File

@ -16,7 +16,6 @@ import (
) )
var gm = gmap.NewIntIntMap(true) var gm = gmap.NewIntIntMap(true)
var sm = sync.Map{} var sm = sync.Map{}
func Benchmark_GMapSet(b *testing.B) { func Benchmark_GMapSet(b *testing.B) {

View File

@ -16,17 +16,11 @@ import (
) )
var anyAnyMapUnsafe = gmap.New() var anyAnyMapUnsafe = gmap.New()
var intIntMapUnsafe = gmap.NewIntIntMap() var intIntMapUnsafe = gmap.NewIntIntMap()
var intAnyMapUnsafe = gmap.NewIntAnyMap() var intAnyMapUnsafe = gmap.NewIntAnyMap()
var intStrMapUnsafe = gmap.NewIntStrMap() var intStrMapUnsafe = gmap.NewIntStrMap()
var strIntMapUnsafe = gmap.NewStrIntMap() var strIntMapUnsafe = gmap.NewStrIntMap()
var strAnyMapUnsafe = gmap.NewStrAnyMap() var strAnyMapUnsafe = gmap.NewStrAnyMap()
var strStrMapUnsafe = gmap.NewStrStrMap() var strStrMapUnsafe = gmap.NewStrStrMap()
// Writing benchmarks. // Writing benchmarks.

View File

@ -8,11 +8,11 @@ package gmap_test
import ( import (
"fmt" "fmt"
"github.com/gogf/gf/v2/internal/json"
"github.com/gogf/gf/v2/util/gconv"
"github.com/gogf/gf/v2/container/gmap" "github.com/gogf/gf/v2/container/gmap"
"github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/internal/json"
"github.com/gogf/gf/v2/util/gconv"
) )
func ExampleAnyAnyMap_Iterator() { func ExampleAnyAnyMap_Iterator() {

View File

@ -8,7 +8,6 @@ package gmap_test
import ( import (
"fmt" "fmt"
"github.com/gogf/gf/v2/container/gmap" "github.com/gogf/gf/v2/container/gmap"
"github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/internal/json" "github.com/gogf/gf/v2/internal/json"

View File

@ -8,7 +8,6 @@ package gmap_test
import ( import (
"fmt" "fmt"
"github.com/gogf/gf/v2/container/gmap" "github.com/gogf/gf/v2/container/gmap"
"github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/internal/json" "github.com/gogf/gf/v2/internal/json"

View File

@ -8,11 +8,11 @@ package gmap_test
import ( import (
"fmt" "fmt"
"github.com/gogf/gf/v2/internal/json"
"github.com/gogf/gf/v2/util/gconv"
"github.com/gogf/gf/v2/container/gmap" "github.com/gogf/gf/v2/container/gmap"
"github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/internal/json"
"github.com/gogf/gf/v2/util/gconv"
) )
func ExampleStrAnyMap_Iterator() { func ExampleStrAnyMap_Iterator() {

View File

@ -8,7 +8,6 @@ package gmap_test
import ( import (
"fmt" "fmt"
"github.com/gogf/gf/v2/container/gmap" "github.com/gogf/gf/v2/container/gmap"
"github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/internal/json" "github.com/gogf/gf/v2/internal/json"

View File

@ -8,11 +8,12 @@ package gmap_test
import ( import (
"fmt" "fmt"
"github.com/gogf/gf/v2/internal/json"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/util/gconv"
"github.com/gogf/gf/v2/container/gmap" "github.com/gogf/gf/v2/container/gmap"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/internal/json"
"github.com/gogf/gf/v2/util/gconv"
) )
func ExampleStrStrMap_Iterator() { func ExampleStrStrMap_Iterator() {

View File

@ -9,8 +9,9 @@ package gmap_test
import ( import (
"fmt" "fmt"
"github.com/gogf/gf/v2/container/gmap"
"github.com/gogf/gf/v2/util/gutil" "github.com/gogf/gf/v2/util/gutil"
"github.com/gogf/gf/v2/container/gmap"
) )
func ExampleNew() { func ExampleNew() {

View File

@ -117,7 +117,6 @@ func Test_IntAnyMap_Batch(t *testing.T) {
t.Assert(m.Map(), map[int]interface{}{3: 3}) t.Assert(m.Map(), map[int]interface{}{3: 3})
}) })
} }
func Test_IntAnyMap_Iterator(t *testing.T) { func Test_IntAnyMap_Iterator(t *testing.T) {
gtest.C(t, func(t *gtest.T) { gtest.C(t, func(t *gtest.T) {
expect := map[int]interface{}{1: 1, 2: "2"} expect := map[int]interface{}{1: 1, 2: "2"}
@ -155,7 +154,6 @@ func Test_IntAnyMap_Lock(t *testing.T) {
}) })
}) })
} }
func Test_IntAnyMap_Clone(t *testing.T) { func Test_IntAnyMap_Clone(t *testing.T) {
gtest.C(t, func(t *gtest.T) { gtest.C(t, func(t *gtest.T) {
// clone 方法是深克隆 // clone 方法是深克隆
@ -171,7 +169,6 @@ func Test_IntAnyMap_Clone(t *testing.T) {
t.AssertIN(2, m.Keys()) t.AssertIN(2, m.Keys())
}) })
} }
func Test_IntAnyMap_Merge(t *testing.T) { func Test_IntAnyMap_Merge(t *testing.T) {
gtest.C(t, func(t *gtest.T) { gtest.C(t, func(t *gtest.T) {
m1 := gmap.NewIntAnyMap() m1 := gmap.NewIntAnyMap()

View File

@ -152,7 +152,6 @@ func Test_IntStrMap_Batch(t *testing.T) {
t.Assert(m.Map(), map[int]interface{}{3: "c"}) t.Assert(m.Map(), map[int]interface{}{3: "c"})
}) })
} }
func Test_IntStrMap_Iterator(t *testing.T) { func Test_IntStrMap_Iterator(t *testing.T) {
gtest.C(t, func(t *gtest.T) { gtest.C(t, func(t *gtest.T) {
expect := map[int]string{1: "a", 2: "b"} expect := map[int]string{1: "a", 2: "b"}
@ -205,7 +204,6 @@ func Test_IntStrMap_Clone(t *testing.T) {
t.AssertIN(2, m.Keys()) t.AssertIN(2, m.Keys())
}) })
} }
func Test_IntStrMap_Merge(t *testing.T) { func Test_IntStrMap_Merge(t *testing.T) {
gtest.C(t, func(t *gtest.T) { gtest.C(t, func(t *gtest.T) {
m1 := gmap.NewIntStrMap() m1 := gmap.NewIntStrMap()

View File

@ -146,7 +146,6 @@ func Test_StrAnyMap_Lock(t *testing.T) {
}) })
}) })
} }
func Test_StrAnyMap_Clone(t *testing.T) { func Test_StrAnyMap_Clone(t *testing.T) {
gtest.C(t, func(t *gtest.T) { gtest.C(t, func(t *gtest.T) {
// clone 方法是深克隆 // clone 方法是深克隆
@ -162,7 +161,6 @@ func Test_StrAnyMap_Clone(t *testing.T) {
t.AssertIN("b", m.Keys()) t.AssertIN("b", m.Keys())
}) })
} }
func Test_StrAnyMap_Merge(t *testing.T) { func Test_StrAnyMap_Merge(t *testing.T) {
gtest.C(t, func(t *gtest.T) { gtest.C(t, func(t *gtest.T) {
m1 := gmap.NewStrAnyMap() m1 := gmap.NewStrAnyMap()

View File

@ -117,7 +117,6 @@ func Test_StrIntMap_Batch(t *testing.T) {
t.Assert(m.Map(), map[string]int{"c": 3}) t.Assert(m.Map(), map[string]int{"c": 3})
}) })
} }
func Test_StrIntMap_Iterator(t *testing.T) { func Test_StrIntMap_Iterator(t *testing.T) {
gtest.C(t, func(t *gtest.T) { gtest.C(t, func(t *gtest.T) {
expect := map[string]int{"a": 1, "b": 2} expect := map[string]int{"a": 1, "b": 2}
@ -171,7 +170,6 @@ func Test_StrIntMap_Clone(t *testing.T) {
t.AssertIN("b", m.Keys()) t.AssertIN("b", m.Keys())
}) })
} }
func Test_StrIntMap_Merge(t *testing.T) { func Test_StrIntMap_Merge(t *testing.T) {
gtest.C(t, func(t *gtest.T) { gtest.C(t, func(t *gtest.T) {
m1 := gmap.NewStrIntMap() m1 := gmap.NewStrIntMap()

View File

@ -116,7 +116,6 @@ func Test_StrStrMap_Batch(t *testing.T) {
t.Assert(m.Map(), map[string]string{"c": "c"}) t.Assert(m.Map(), map[string]string{"c": "c"})
}) })
} }
func Test_StrStrMap_Iterator(t *testing.T) { func Test_StrStrMap_Iterator(t *testing.T) {
gtest.C(t, func(t *gtest.T) { gtest.C(t, func(t *gtest.T) {
expect := map[string]string{"a": "a", "b": "b"} expect := map[string]string{"a": "a", "b": "b"}
@ -154,7 +153,6 @@ func Test_StrStrMap_Lock(t *testing.T) {
}) })
}) })
} }
func Test_StrStrMap_Clone(t *testing.T) { func Test_StrStrMap_Clone(t *testing.T) {
gtest.C(t, func(t *gtest.T) { gtest.C(t, func(t *gtest.T) {
// clone 方法是深克隆 // clone 方法是深克隆
@ -170,7 +168,6 @@ func Test_StrStrMap_Clone(t *testing.T) {
t.AssertIN("b", m.Keys()) t.AssertIN("b", m.Keys())
}) })
} }
func Test_StrStrMap_Merge(t *testing.T) { func Test_StrStrMap_Merge(t *testing.T) {
gtest.C(t, func(t *gtest.T) { gtest.C(t, func(t *gtest.T) {
m1 := gmap.NewStrStrMap() m1 := gmap.NewStrStrMap()

View File

@ -106,7 +106,6 @@ func Test_ListMap_Batch(t *testing.T) {
t.Assert(m.Map(), map[interface{}]interface{}{"key2": "val2", "key3": "val3"}) t.Assert(m.Map(), map[interface{}]interface{}{"key2": "val2", "key3": "val3"})
}) })
} }
func Test_ListMap_Iterator(t *testing.T) { func Test_ListMap_Iterator(t *testing.T) {
gtest.C(t, func(t *gtest.T) { gtest.C(t, func(t *gtest.T) {
expect := map[interface{}]interface{}{1: 1, "key1": "val1"} expect := map[interface{}]interface{}{1: 1, "key1": "val1"}

View File

@ -107,7 +107,6 @@ func Test_TreeMap_Batch(t *testing.T) {
t.Assert(m.Map(), map[interface{}]interface{}{"key2": "val2", "key3": "val3"}) t.Assert(m.Map(), map[interface{}]interface{}{"key2": "val2", "key3": "val3"})
}) })
} }
func Test_TreeMap_Iterator(t *testing.T) { func Test_TreeMap_Iterator(t *testing.T) {
gtest.C(t, func(t *gtest.T) { gtest.C(t, func(t *gtest.T) {
expect := map[interface{}]interface{}{1: 1, "key1": "val1"} expect := map[interface{}]interface{}{1: 1, "key1": "val1"}

View File

@ -84,13 +84,6 @@ func (p *Pool) Put(value interface{}) error {
return nil return nil
} }
// MustPut puts an item to pool, it panics if any error occurs.
func (p *Pool) MustPut(value interface{}) {
if err := p.Put(value); err != nil {
panic(err)
}
}
// Clear clears pool, which means it will remove all items from pool. // Clear clears pool, which means it will remove all items from pool.
func (p *Pool) Clear() { func (p *Pool) Clear() {
if p.ExpireFunc != nil { if p.ExpireFunc != nil {
@ -104,6 +97,7 @@ func (p *Pool) Clear() {
} else { } else {
p.list.RemoveAll() p.list.RemoveAll()
} }
} }
// Get picks and returns an item from pool. If the pool is empty and NewFunc is defined, // Get picks and returns an item from pool. If the pool is empty and NewFunc is defined,

View File

@ -17,7 +17,6 @@ import (
) )
var pool = gpool.New(time.Hour, nil) var pool = gpool.New(time.Hour, nil)
var syncp = sync.Pool{} var syncp = sync.Pool{}
func BenchmarkGPoolPut(b *testing.B) { func BenchmarkGPoolPut(b *testing.B) {

View File

@ -9,9 +9,8 @@ package gpool_test
import ( import (
"database/sql" "database/sql"
"fmt" "fmt"
"time"
"github.com/gogf/gf/v2/container/gpool" "github.com/gogf/gf/v2/container/gpool"
"time"
) )
func ExampleNew() { func ExampleNew() {
@ -61,7 +60,7 @@ func ExamplePool_Put() {
// conn.(*DBConn).Conn.QueryContext(context.Background(), "select * from user") // conn.(*DBConn).Conn.QueryContext(context.Background(), "select * from user")
// put back conn // put back conn
dbConnPool.MustPut(conn) dbConnPool.Put(conn)
fmt.Println(conn.(*DBConn).Limit) fmt.Println(conn.(*DBConn).Limit)
@ -88,8 +87,8 @@ func ExamplePool_Clear() {
}) })
conn, _ := dbConnPool.Get() conn, _ := dbConnPool.Get()
dbConnPool.MustPut(conn) dbConnPool.Put(conn)
dbConnPool.MustPut(conn) dbConnPool.Put(conn)
fmt.Println(dbConnPool.Size()) fmt.Println(dbConnPool.Size())
dbConnPool.Clear() dbConnPool.Clear()
fmt.Println(dbConnPool.Size()) fmt.Println(dbConnPool.Size())
@ -144,8 +143,8 @@ func ExamplePool_Size() {
conn, _ := dbConnPool.Get() conn, _ := dbConnPool.Get()
fmt.Println(dbConnPool.Size()) fmt.Println(dbConnPool.Size())
dbConnPool.MustPut(conn) dbConnPool.Put(conn)
dbConnPool.MustPut(conn) dbConnPool.Put(conn)
fmt.Println(dbConnPool.Size()) fmt.Println(dbConnPool.Size())
// Output: // Output:
@ -158,28 +157,27 @@ func ExamplePool_Close() {
Conn *sql.Conn Conn *sql.Conn
Limit int Limit int
} }
var (
newFunc = func() (interface{}, error) { dbConnPool := gpool.New(time.Hour,
func() (interface{}, error) {
dbConn := new(DBConn) dbConn := new(DBConn)
dbConn.Limit = 10 dbConn.Limit = 10
return dbConn, nil return dbConn, nil
} },
closeFunc = func(i interface{}) { func(i interface{}) {
fmt.Println("Close The Pool") fmt.Println("Close The Pool")
// sample : close db conn // sample : close db conn
// i.(DBConn).Conn.Close() // i.(DBConn).Conn.Close()
} })
)
dbConnPool := gpool.New(time.Hour, newFunc, closeFunc)
conn, _ := dbConnPool.Get() conn, _ := dbConnPool.Get()
dbConnPool.MustPut(conn) dbConnPool.Put(conn)
dbConnPool.Close() dbConnPool.Close()
// wait for pool close // wait for pool close
time.Sleep(time.Second * 1) time.Sleep(time.Second * 1)
// May Output: // Output:
// Close The Pool // Close The Pool
} }

View File

@ -21,7 +21,6 @@ var nf gpool.NewFunc = func() (i interface{}, e error) {
} }
var assertIndex int = 0 var assertIndex int = 0
var ef gpool.ExpireFunc = func(i interface{}) { var ef gpool.ExpireFunc = func(i interface{}) {
assertIndex++ assertIndex++
gtest.Assert(i, assertIndex) gtest.Assert(i, assertIndex)

View File

@ -15,6 +15,7 @@
// 3. Support dynamic queue size(unlimited queue size); // 3. Support dynamic queue size(unlimited queue size);
// //
// 4. Blocking when reading data from queue; // 4. Blocking when reading data from queue;
//
package gqueue package gqueue
import ( import (
@ -27,7 +28,6 @@ import (
// Queue is a concurrent-safe queue built on doubly linked list and channel. // Queue is a concurrent-safe queue built on doubly linked list and channel.
type Queue struct { type Queue struct {
limit int // Limit for queue size. limit int // Limit for queue size.
length *gtype.Int64 // Queue length.
list *glist.List // Underlying list structure for data maintaining. list *glist.List // Underlying list structure for data maintaining.
closed *gtype.Bool // Whether queue is closed. closed *gtype.Bool // Whether queue is closed.
events chan struct{} // Events for data writing. events chan struct{} // Events for data writing.
@ -45,7 +45,6 @@ const (
func New(limit ...int) *Queue { func New(limit ...int) *Queue {
q := &Queue{ q := &Queue{
closed: gtype.NewBool(), closed: gtype.NewBool(),
length: gtype.NewInt64(),
} }
if len(limit) > 0 && limit[0] > 0 { if len(limit) > 0 && limit[0] > 0 {
q.limit = limit[0] q.limit = limit[0]
@ -59,59 +58,6 @@ func New(limit ...int) *Queue {
return q return q
} }
// Push pushes the data `v` into the queue.
// Note that it would panic if Push is called after the queue is closed.
func (q *Queue) Push(v interface{}) {
q.length.Add(1)
if q.limit > 0 {
q.C <- v
} else {
q.list.PushBack(v)
if len(q.events) < defaultQueueSize {
q.events <- struct{}{}
}
}
}
// Pop pops an item from the queue in FIFO way.
// Note that it would return nil immediately if Pop is called after the queue is closed.
func (q *Queue) Pop() interface{} {
item := <-q.C
q.length.Add(-1)
return item
}
// Close closes the queue.
// Notice: It would notify all goroutines return immediately,
// which are being blocked reading using Pop method.
func (q *Queue) Close() {
if !q.closed.Cas(false, true) {
return
}
if q.events != nil {
close(q.events)
}
if q.limit > 0 {
close(q.C)
} else {
for i := 0; i < defaultBatchSize; i++ {
q.Pop()
}
}
}
// Len returns the length of the queue.
// Note that the result might not be accurate as there's an
// asynchronous channel reading the list constantly.
func (q *Queue) Len() (length int64) {
return q.length.Val()
}
// Size is alias of Len.
func (q *Queue) Size() int64 {
return q.Len()
}
// asyncLoopFromListToChannel starts an asynchronous goroutine, // asyncLoopFromListToChannel starts an asynchronous goroutine,
// which handles the data synchronization from list `q.list` to channel `q.C`. // which handles the data synchronization from list `q.list` to channel `q.C`.
func (q *Queue) asyncLoopFromListToChannel() { func (q *Queue) asyncLoopFromListToChannel() {
@ -145,3 +91,55 @@ func (q *Queue) asyncLoopFromListToChannel() {
// It's the sender's responsibility to close channel when it should be closed. // It's the sender's responsibility to close channel when it should be closed.
close(q.C) close(q.C)
} }
// Push pushes the data `v` into the queue.
// Note that it would panic if Push is called after the queue is closed.
func (q *Queue) Push(v interface{}) {
if q.limit > 0 {
q.C <- v
} else {
q.list.PushBack(v)
if len(q.events) < defaultQueueSize {
q.events <- struct{}{}
}
}
}
// Pop pops an item from the queue in FIFO way.
// Note that it would return nil immediately if Pop is called after the queue is closed.
func (q *Queue) Pop() interface{} {
return <-q.C
}
// Close closes the queue.
// Notice: It would notify all goroutines return immediately,
// which are being blocked reading using Pop method.
func (q *Queue) Close() {
q.closed.Set(true)
if q.events != nil {
close(q.events)
}
if q.limit > 0 {
close(q.C)
} else {
for i := 0; i < defaultBatchSize; i++ {
q.Pop()
}
}
}
// Len returns the length of the queue.
// Note that the result might not be accurate as there's an
// asynchronous channel reading the list constantly.
func (q *Queue) Len() (length int) {
if q.list != nil {
length += q.list.Len()
}
length += len(q.C)
return
}
// Size is alias of Len.
func (q *Queue) Size() int {
return q.Len()
}

View File

@ -15,13 +15,9 @@ import (
) )
var bn = 20000000 var bn = 20000000
var length = 1000000 var length = 1000000
var qstatic = gqueue.New(length) var qstatic = gqueue.New(length)
var qdynamic = gqueue.New() var qdynamic = gqueue.New()
var cany = make(chan interface{}, length) var cany = make(chan interface{}, length)
func Benchmark_Gqueue_StaticPushAndPop(b *testing.B) { func Benchmark_Gqueue_StaticPushAndPop(b *testing.B) {

View File

@ -153,6 +153,7 @@ func (r *Ring) Next() *Ring {
// them creates a single ring with the elements of s inserted // them creates a single ring with the elements of s inserted
// after r. The result points to the element following the // after r. The result points to the element following the
// last element of s after insertion. // last element of s after insertion.
//
func (r *Ring) Link(s *Ring) *Ring { func (r *Ring) Link(s *Ring) *Ring {
r.mu.Lock() r.mu.Lock()
s.mu.Lock() s.mu.Lock()
@ -167,6 +168,7 @@ func (r *Ring) Link(s *Ring) *Ring {
// Unlink removes n % r.Len() elements from the ring r, starting // Unlink removes n % r.Len() elements from the ring r, starting
// at r.Next(). If n % r.Len() == 0, r remains unchanged. // at r.Next(). If n % r.Len() == 0, r remains unchanged.
// The result is the removed sub-ring. r must not be empty. // The result is the removed sub-ring. r must not be empty.
//
func (r *Ring) Unlink(n int) *Ring { func (r *Ring) Unlink(n int) *Ring {
r.mu.Lock() r.mu.Lock()
resultRing := r.ring.Unlink(n) resultRing := r.ring.Unlink(n)

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