From 9f7de03ae6101873f6245c35100388826d8ceac9 Mon Sep 17 00:00:00 2001 From: Alex Jeannopoulos Date: Wed, 8 Jul 2020 12:52:32 -0400 Subject: [PATCH] added fail fast on error in code gen --- README.md | 11 +- _test/dbmeta/main.go | 2 +- code_http.md | 4 +- dbmeta/codegen.go | 24 ++-- go.mod | 2 +- main.go | 191 ++++++++++++++++++-------- packrd/packed-packr.go | 4 +- main-packr.go => readme/main-packr.go | 0 readme/main.go | 2 +- template/GEN_README.md.tmpl | 5 + 10 files changed, 163 insertions(+), 82 deletions(-) rename main-packr.go => readme/main-packr.go (100%) diff --git a/README.md b/README.md index 421ac77..d8a15b5 100644 --- a/README.md +++ b/README.md @@ -273,7 +273,7 @@ The following info is available within use of the exec template. "AdvancesSample" string "\n{{ range $i, $table := .tables }}\n {{$singular := singular $table -}}\n {{$plural := pluralize $table -}}\n {{$title := title $table -}}\n {{$lower := toLower $table -}}\n {{$lowerCamel := toLowerCamelCase $table -}}\n {{$snakeCase := toSnakeCase $table -}}\n {{ printf \"[%-2d] %-20s %-20s %-20s %-20s %-20s %-20s %-20s\" $i $table $singular $plural $title $lower $lowerCamel $snakeCase}}{{- end }}\n\n\n{{ range $i, $table := .tables }}\n {{$name := toUpper $table -}}\n {{$filename := printf \"My%s\" $name -}}\n {{ printf \"[%-2d] %-20s %-20s\" $i $table $filename}}\n {{ GenerateTableFile $table \"custom.go.tmpl\" \"test\" $filename true}}\n{{- end }}\n" - "Config" *dbmeta.Config &dbmeta.Config{SQLType:"sqlite3", SQLConnStr:"./example/sample.db", SQLDatabase:"main", Module:"github.com/alexj212/test", ModelPackageName:"model", ModelFQPN:"github.com/alexj212/test/model", AddJSONAnnotation:true, AddGormAnnotation:true, AddProtobufAnnotation:true, AddXMLAnnotation:true, AddDBAnnotation:true, UseGureguTypes:false, JSONNameFormat:"snake", XMLNameFormat:"snake", ProtobufNameFormat:"", DaoPackageName:"dao", DaoFQPN:"github.com/alexj212/test/dao", APIPackageName:"api", APIFQPN:"github.com/alexj212/test/api", GrpcPackageName:"", GrpcFQPN:"", Swagger:(*dbmeta.SwaggerInfoDetails)(0xc001af2480), ServerPort:8080, ServerHost:"127.0.0.1", Verbose:false, OutDir:".", Overwrite:true, LineEndingCRLF:false, CmdLine:"/tmp/go-build951728821/b001/exe/readme --sqltype=sqlite3 --connstr ./example/sample.db --database main --table invoices", CmdLineWrapped:"/tmp/go-build951728821/b001/exe/readme \\\n --sqltype=sqlite3 \\\n --connstr \\\n ./example/sample.db \\\n --database \\\n main \\\n --table \\\n invoices", CmdLineArgs:[]string{"/tmp/go-build951728821/b001/exe/readme", "--sqltype=sqlite3", "--connstr", "./example/sample.db", "--database", "main", "--table", "invoices"}, FileNamingTemplate:"{{.}}", ModelNamingTemplate:"{{FmtFieldName .}}", FieldNamingTemplate:"{{FmtFieldName (stringifyFirstChar .) }}", string:"", ContextMap:map[string]interface {}{"GenHelp":"Usage of gen:\n\tgen [-v] --sqltype=mysql --connstr \"user:password@/dbname\" --database --module=example.com/example [--json] [--gorm] [--guregu] [--generate-dao] [--generate-proj]\ngit fetch up\n sqltype - sql database type such as [ mysql, mssql, postgres, sqlite, etc. ]\n\n\nOptions:\n --sqltype=mysql sql database type such as [ mysql, mssql, postgres, sqlite, etc. ]\n -c, --connstr=nil database connection string\n -d, --database=nil Database to for connection\n -t, --table= Table to build struct from\n -x, --exclude= Table(s) to exclude\n --templateDir= Template Dir\n --save= Save templates to dir\n --model=model name to set for model package\n --model_naming={{FmtFieldName .}} model naming template to name structs\n --field_naming={{FmtFieldName (stringifyFirstChar .) }} field naming template to name structs\n --file_naming={{.}} file_naming template to name files\n --dao=dao name to set for dao package\n --api=api name to set for api package\n --grpc=grpc name to set for grpc package\n --out=. output dir\n --module=example.com/example module path\n --overwrite Overwrite existing files (default)\n --no-overwrite disable overwriting files\n --context= context file (json) to populate context with\n --mapping= mapping file (json) to map sql types to golang/protobuf etc\n --exec= execute script for custom code generation\n --json Add json annotations (default)\n --no-json Disable json annotations\n --json-fmt=snake json name format [snake | camel | lower_camel | none]\n --xml Add xml annotations (default)\n --no-xml Disable xml annotations\n --xml-fmt=snake xml name format [snake | camel | lower_camel | none]\n --gorm Add gorm annotations (tags)\n --protobuf Add protobuf annotations (tags)\n --proto-fmt=snake proto name format [snake | camel | lower_camel | none]\n --gogo-proto= location of gogo import \n --db Add db annotations (tags)\n --guregu Add guregu null types\n --copy-templates Copy regeneration templates to project directory\n --mod Generate go.mod in output dir\n --makefile Generate Makefile in output dir\n --server Generate server app output dir\n --generate-dao Generate dao functions\n --generate-proj Generate project readme and gitignore\n --rest Enable generating RESTful api\n --run-gofmt run gofmt on output dir\n --host=localhost host for server\n --port=8080 port for server\n --swagger_version=1.0 swagger version\n --swagger_path=/ swagger base path\n --swagger_tos= swagger tos url\n --swagger_contact_name=Me swagger contact name\n --swagger_contact_url=http://me.com/terms.html swagger contact url\n --swagger_contact_email=me@me.com swagger contact email\n -v, --verbose Enable verbose output\n --name_test= perform name test using the --model_naming or --file_naming options\n -h, --help Show usage message\n --version Show version\n\n", "tableInfos":map[string]*dbmeta.ModelInfo{"invoices":(*dbmeta.ModelInfo)(0xc001b9b4a0)}}, TemplateLoader:(dbmeta.TemplateLoader)(0x8a2070)} + "Config" *dbmeta.Config &dbmeta.Config{SQLType:"sqlite3", SQLConnStr:"./example/sample.db", SQLDatabase:"main", Module:"github.com/alexj212/test", ModelPackageName:"model", ModelFQPN:"github.com/alexj212/test/model", AddJSONAnnotation:true, AddGormAnnotation:true, AddProtobufAnnotation:true, AddXMLAnnotation:true, AddDBAnnotation:true, UseGureguTypes:false, JSONNameFormat:"snake", XMLNameFormat:"snake", ProtobufNameFormat:"", DaoPackageName:"dao", DaoFQPN:"github.com/alexj212/test/dao", APIPackageName:"api", APIFQPN:"github.com/alexj212/test/api", GrpcPackageName:"", GrpcFQPN:"", Swagger:(*dbmeta.SwaggerInfoDetails)(0xc00182a510), ServerPort:8080, ServerHost:"127.0.0.1", Verbose:false, OutDir:".", Overwrite:true, LineEndingCRLF:false, CmdLine:"/tmp/go-build394270054/b001/exe/readme --sqltype=sqlite3 --connstr ./example/sample.db --database main --table invoices", CmdLineWrapped:"/tmp/go-build394270054/b001/exe/readme \\\n --sqltype=sqlite3 \\\n --connstr \\\n ./example/sample.db \\\n --database \\\n main \\\n --table \\\n invoices", CmdLineArgs:[]string{"/tmp/go-build394270054/b001/exe/readme", "--sqltype=sqlite3", "--connstr", "./example/sample.db", "--database", "main", "--table", "invoices"}, FileNamingTemplate:"{{.}}", ModelNamingTemplate:"{{FmtFieldName .}}", FieldNamingTemplate:"{{FmtFieldName (stringifyFirstChar .) }}", string:"", ContextMap:map[string]interface {}{"GenHelp":"Usage of gen:\n\tgen [-v] --sqltype=mysql --connstr \"user:password@/dbname\" --database --module=example.com/example [--json] [--gorm] [--guregu] [--generate-dao] [--generate-proj]\ngit fetch up\n sqltype - sql database type such as [ mysql, mssql, postgres, sqlite, etc. ]\n\n\nOptions:\n --sqltype=mysql sql database type such as [ mysql, mssql, postgres, sqlite, etc. ]\n -c, --connstr=nil database connection string\n -d, --database=nil Database to for connection\n -t, --table= Table to build struct from\n -x, --exclude= Table(s) to exclude\n --templateDir= Template Dir\n --save= Save templates to dir\n --model=model name to set for model package\n --model_naming={{FmtFieldName .}} model naming template to name structs\n --field_naming={{FmtFieldName (stringifyFirstChar .) }} field naming template to name structs\n --file_naming={{.}} file_naming template to name files\n --dao=dao name to set for dao package\n --api=api name to set for api package\n --grpc=grpc name to set for grpc package\n --out=. output dir\n --module=example.com/example module path\n --overwrite Overwrite existing files (default)\n --no-overwrite disable overwriting files\n --context= context file (json) to populate context with\n --mapping= mapping file (json) to map sql types to golang/protobuf etc\n --exec= execute script for custom code generation\n --json Add json annotations (default)\n --no-json Disable json annotations\n --json-fmt=snake json name format [snake | camel | lower_camel | none]\n --xml Add xml annotations (default)\n --no-xml Disable xml annotations\n --xml-fmt=snake xml name format [snake | camel | lower_camel | none]\n --gorm Add gorm annotations (tags)\n --protobuf Add protobuf annotations (tags)\n --proto-fmt=snake proto name format [snake | camel | lower_camel | none]\n --gogo-proto= location of gogo import \n --db Add db annotations (tags)\n --guregu Add guregu null types\n --copy-templates Copy regeneration templates to project directory\n --mod Generate go.mod in output dir\n --makefile Generate Makefile in output dir\n --server Generate server app output dir\n --generate-dao Generate dao functions\n --generate-proj Generate project readme and gitignore\n --rest Enable generating RESTful api\n --run-gofmt run gofmt on output dir\n --host=localhost host for server\n --port=8080 port for server\n --swagger_version=1.0 swagger version\n --swagger_path=/ swagger base path\n --swagger_tos= swagger tos url\n --swagger_contact_name=Me swagger contact name\n --swagger_contact_url=http://me.com/terms.html swagger contact url\n --swagger_contact_email=me@me.com swagger contact email\n -v, --verbose Enable verbose output\n --name_test= perform name test using the --model_naming or --file_naming options\n -h, --help Show usage message\n --version Show version\n\n", "tableInfos":map[string]*dbmeta.ModelInfo{"invoices":(*dbmeta.ModelInfo)(0xc0000f9680)}}, TemplateLoader:(dbmeta.TemplateLoader)(0x8a57c0)} "DatabaseName" string "main" "GenHelp" string "Usage of gen:\n\tgen [-v] --sqltype=mysql --connstr \"user:password@/dbname\" --database --module=example.com/example [--json] [--gorm] [--guregu] [--generate-dao] [--generate-proj]\ngit fetch up\n sqltype - sql database type such as [ mysql, mssql, postgres, sqlite, etc. ]\n\n\nOptions:\n --sqltype=mysql sql database type such as [ mysql, mssql, postgres, sqlite, etc. ]\n -c, --connstr=nil database connection string\n -d, --database=nil Database to for connection\n -t, --table= Table to build struct from\n -x, --exclude= Table(s) to exclude\n --templateDir= Template Dir\n --save= Save templates to dir\n --model=model name to set for model package\n --model_naming={{FmtFieldName .}} model naming template to name structs\n --field_naming={{FmtFieldName (stringifyFirstChar .) }} field naming template to name structs\n --file_naming={{.}} file_naming template to name files\n --dao=dao name to set for dao package\n --api=api name to set for api package\n --grpc=grpc name to set for grpc package\n --out=. output dir\n --module=example.com/example module path\n --overwrite Overwrite existing files (default)\n --no-overwrite disable overwriting files\n --context= context file (json) to populate context with\n --mapping= mapping file (json) to map sql types to golang/protobuf etc\n --exec= execute script for custom code generation\n --json Add json annotations (default)\n --no-json Disable json annotations\n --json-fmt=snake json name format [snake | camel | lower_camel | none]\n --xml Add xml annotations (default)\n --no-xml Disable xml annotations\n --xml-fmt=snake xml name format [snake | camel | lower_camel | none]\n --gorm Add gorm annotations (tags)\n --protobuf Add protobuf annotations (tags)\n --proto-fmt=snake proto name format [snake | camel | lower_camel | none]\n --gogo-proto= location of gogo import \n --db Add db annotations (tags)\n --guregu Add guregu null types\n --copy-templates Copy regeneration templates to project directory\n --mod Generate go.mod in output dir\n --makefile Generate Makefile in output dir\n --server Generate server app output dir\n --generate-dao Generate dao functions\n --generate-proj Generate project readme and gitignore\n --rest Enable generating RESTful api\n --run-gofmt run gofmt on output dir\n --host=localhost host for server\n --port=8080 port for server\n --swagger_version=1.0 swagger version\n --swagger_path=/ swagger base path\n --swagger_tos= swagger tos url\n --swagger_contact_name=Me swagger contact name\n --swagger_contact_url=http://me.com/terms.html swagger contact url\n --swagger_contact_email=me@me.com swagger contact email\n -v, --verbose Enable verbose output\n --name_test= perform name test using the --model_naming or --file_naming options\n -h, --help Show usage message\n --version Show version\n\n" "NonPrimaryKeyNamesList" []string []string{"CustomerId", "InvoiceDate", "BillingAddress", "BillingCity", "BillingState", "BillingCountry", "BillingPostalCode", "Total"} @@ -283,7 +283,7 @@ The following info is available within use of the exec template. "ShortStructName" string "i" "StructName" string "Invoices" "SwaggerInfo" *dbmeta.SwaggerInfoDetails &dbmeta.SwaggerInfoDetails{Version:"1.0.0", Host:"127.0.0.1:8080", BasePath:"/", Title:"Sample CRUD api for main db", Description:"Sample CRUD api for main db", TOS:"My Custom TOS", ContactName:"", ContactURL:"", ContactEmail:""} - "TableInfo" *dbmeta.ModelInfo &dbmeta.ModelInfo{Index:0, IndexPlus1:1, PackageName:"model", StructName:"Invoices", ShortStructName:"i", TableName:"invoices", Fields:[]string{"//[ 0] InvoiceId integer null: false primary: true isArray: false auto: true col: integer len: -1 default: []\n InvoiceID int32 `gorm:\"primary_key;AUTO_INCREMENT;column:InvoiceId;type:integer;\" json:\"invoice_id\" xml:\"invoice_id\" db:\"InvoiceId\" protobuf:\"int32,0,opt,name=InvoiceId\"`", "//[ 1] CustomerId integer null: false primary: false isArray: false auto: false col: integer len: -1 default: []\n CustomerID int32 `gorm:\"column:CustomerId;type:integer;\" json:\"customer_id\" xml:\"customer_id\" db:\"CustomerId\" protobuf:\"int32,1,opt,name=CustomerId\"`", "//[ 2] InvoiceDate datetime null: false primary: false isArray: false auto: false col: datetime len: -1 default: []\n InvoiceDate time.Time `gorm:\"column:InvoiceDate;type:datetime;\" json:\"invoice_date\" xml:\"invoice_date\" db:\"InvoiceDate\" protobuf:\"google.protobuf.Timestamp,2,opt,name=InvoiceDate\"`", "//[ 3] BillingAddress nvarchar(70) null: true primary: false isArray: false auto: false col: nvarchar len: 70 default: []\n BillingAddress sql.NullString `gorm:\"column:BillingAddress;type:nvarchar;size:70;\" json:\"billing_address\" xml:\"billing_address\" db:\"BillingAddress\" protobuf:\"string,3,opt,name=BillingAddress\"`", "//[ 4] BillingCity nvarchar(40) null: true primary: false isArray: false auto: false col: nvarchar len: 40 default: []\n BillingCity sql.NullString `gorm:\"column:BillingCity;type:nvarchar;size:40;\" json:\"billing_city\" xml:\"billing_city\" db:\"BillingCity\" protobuf:\"string,4,opt,name=BillingCity\"`", "//[ 5] BillingState nvarchar(40) null: true primary: false isArray: false auto: false col: nvarchar len: 40 default: []\n BillingState sql.NullString `gorm:\"column:BillingState;type:nvarchar;size:40;\" json:\"billing_state\" xml:\"billing_state\" db:\"BillingState\" protobuf:\"string,5,opt,name=BillingState\"`", "//[ 6] BillingCountry nvarchar(40) null: true primary: false isArray: false auto: false col: nvarchar len: 40 default: []\n BillingCountry sql.NullString `gorm:\"column:BillingCountry;type:nvarchar;size:40;\" json:\"billing_country\" xml:\"billing_country\" db:\"BillingCountry\" protobuf:\"string,6,opt,name=BillingCountry\"`", "//[ 7] BillingPostalCode nvarchar(10) null: true primary: false isArray: false auto: false col: nvarchar len: 10 default: []\n BillingPostalCode sql.NullString `gorm:\"column:BillingPostalCode;type:nvarchar;size:10;\" json:\"billing_postal_code\" xml:\"billing_postal_code\" db:\"BillingPostalCode\" protobuf:\"string,7,opt,name=BillingPostalCode\"`", "//[ 8] Total numeric null: false primary: false isArray: false auto: false col: numeric len: -1 default: []\n Total float64 `gorm:\"column:Total;type:numeric;\" json:\"total\" xml:\"total\" db:\"Total\" protobuf:\"float,8,opt,name=Total\"`"}, DBMeta:(*dbmeta.dbTableMeta)(0xc001b73440), Instance:(*struct { CustomerID int "json:\"customer_id\""; BillingAddress string "json:\"billing_address\""; Total float64 "json:\"total\""; BillingPostalCode string "json:\"billing_postal_code\""; InvoiceID int "json:\"invoice_id\""; InvoiceDate time.Time "json:\"invoice_date\""; BillingCity string "json:\"billing_city\""; BillingState string "json:\"billing_state\""; BillingCountry string "json:\"billing_country\"" })(0xc001aaf580), CodeFields:[]*dbmeta.FieldInfo{(*dbmeta.FieldInfo)(0xc001bdc640), (*dbmeta.FieldInfo)(0xc001bdc780), (*dbmeta.FieldInfo)(0xc001bdc8c0), (*dbmeta.FieldInfo)(0xc001bdca00), (*dbmeta.FieldInfo)(0xc001bdcb40), (*dbmeta.FieldInfo)(0xc001bdcc80), (*dbmeta.FieldInfo)(0xc001bdcdc0), (*dbmeta.FieldInfo)(0xc001bdcf00), (*dbmeta.FieldInfo)(0xc001bdd040)}} + "TableInfo" *dbmeta.ModelInfo &dbmeta.ModelInfo{Index:0, IndexPlus1:1, PackageName:"model", StructName:"Invoices", ShortStructName:"i", TableName:"invoices", Fields:[]string{"//[ 0] InvoiceId integer null: false primary: true isArray: false auto: true col: integer len: -1 default: []\n InvoiceID int32 `gorm:\"primary_key;AUTO_INCREMENT;column:InvoiceId;type:integer;\" json:\"invoice_id\" xml:\"invoice_id\" db:\"InvoiceId\" protobuf:\"int32,0,opt,name=InvoiceId\"`", "//[ 1] CustomerId integer null: false primary: false isArray: false auto: false col: integer len: -1 default: []\n CustomerID int32 `gorm:\"column:CustomerId;type:integer;\" json:\"customer_id\" xml:\"customer_id\" db:\"CustomerId\" protobuf:\"int32,1,opt,name=CustomerId\"`", "//[ 2] InvoiceDate datetime null: false primary: false isArray: false auto: false col: datetime len: -1 default: []\n InvoiceDate time.Time `gorm:\"column:InvoiceDate;type:datetime;\" json:\"invoice_date\" xml:\"invoice_date\" db:\"InvoiceDate\" protobuf:\"google.protobuf.Timestamp,2,opt,name=InvoiceDate\"`", "//[ 3] BillingAddress nvarchar(70) null: true primary: false isArray: false auto: false col: nvarchar len: 70 default: []\n BillingAddress sql.NullString `gorm:\"column:BillingAddress;type:nvarchar;size:70;\" json:\"billing_address\" xml:\"billing_address\" db:\"BillingAddress\" protobuf:\"string,3,opt,name=BillingAddress\"`", "//[ 4] BillingCity nvarchar(40) null: true primary: false isArray: false auto: false col: nvarchar len: 40 default: []\n BillingCity sql.NullString `gorm:\"column:BillingCity;type:nvarchar;size:40;\" json:\"billing_city\" xml:\"billing_city\" db:\"BillingCity\" protobuf:\"string,4,opt,name=BillingCity\"`", "//[ 5] BillingState nvarchar(40) null: true primary: false isArray: false auto: false col: nvarchar len: 40 default: []\n BillingState sql.NullString `gorm:\"column:BillingState;type:nvarchar;size:40;\" json:\"billing_state\" xml:\"billing_state\" db:\"BillingState\" protobuf:\"string,5,opt,name=BillingState\"`", "//[ 6] BillingCountry nvarchar(40) null: true primary: false isArray: false auto: false col: nvarchar len: 40 default: []\n BillingCountry sql.NullString `gorm:\"column:BillingCountry;type:nvarchar;size:40;\" json:\"billing_country\" xml:\"billing_country\" db:\"BillingCountry\" protobuf:\"string,6,opt,name=BillingCountry\"`", "//[ 7] BillingPostalCode nvarchar(10) null: true primary: false isArray: false auto: false col: nvarchar len: 10 default: []\n BillingPostalCode sql.NullString `gorm:\"column:BillingPostalCode;type:nvarchar;size:10;\" json:\"billing_postal_code\" xml:\"billing_postal_code\" db:\"BillingPostalCode\" protobuf:\"string,7,opt,name=BillingPostalCode\"`", "//[ 8] Total numeric null: false primary: false isArray: false auto: false col: numeric len: -1 default: []\n Total float64 `gorm:\"column:Total;type:numeric;\" json:\"total\" xml:\"total\" db:\"Total\" protobuf:\"float,8,opt,name=Total\"`"}, DBMeta:(*dbmeta.dbTableMeta)(0xc0000c9920), Instance:(*struct { InvoiceID int "json:\"invoice_id\""; CustomerID int "json:\"customer_id\""; BillingAddress string "json:\"billing_address\""; BillingState string "json:\"billing_state\""; BillingCountry string "json:\"billing_country\""; Total float64 "json:\"total\""; InvoiceDate time.Time "json:\"invoice_date\""; BillingCity string "json:\"billing_city\""; BillingPostalCode string "json:\"billing_postal_code\"" })(0xc000402700), CodeFields:[]*dbmeta.FieldInfo{(*dbmeta.FieldInfo)(0xc00020a640), (*dbmeta.FieldInfo)(0xc00020a780), (*dbmeta.FieldInfo)(0xc00020a8c0), (*dbmeta.FieldInfo)(0xc00020aa00), (*dbmeta.FieldInfo)(0xc00020ab40), (*dbmeta.FieldInfo)(0xc00020ac80), (*dbmeta.FieldInfo)(0xc00020adc0), (*dbmeta.FieldInfo)(0xc00020af00), (*dbmeta.FieldInfo)(0xc00020b040)}} "TableName" string "invoices" "apiFQPN" string "github.com/alexj212/test/api" "apiPackageName" string "api" @@ -301,7 +301,7 @@ The following info is available within use of the exec template. "serverPort" int 8080 "sqlConnStr" string "./example/sample.db" "sqlType" string "sqlite3" - "tableInfos" map[string]*dbmeta.ModelInfo map[string]*dbmeta.ModelInfo{"invoices":(*dbmeta.ModelInfo)(0xc001b9b4a0)} + "tableInfos" map[string]*dbmeta.ModelInfo map[string]*dbmeta.ModelInfo{"invoices":(*dbmeta.ModelInfo)(0xc0000f9680)} "updateSql" string "UPDATE `invoices` set CustomerId = ?, InvoiceDate = ?, BillingAddress = ?, BillingCity = ?, BillingState = ?, BillingCountry = ?, BillingPostalCode = ?, Total = ? WHERE InvoiceId = ?" @@ -357,6 +357,11 @@ Table Name: registration_source |ms sql |y | y | y | y | y | y| n ## Version History +- v0.9.22 (07/08/2020) + - Modified gogo.proto check to use GOPATH not hardcoded. + - Updated gen to error exit on first error encountered + - Added color output for error + - Added --no-color option for non colorized output - v0.9.21 (07/07/2020) - Repacking templates, update version number in info. - v0.9.20 (07/07/2020) diff --git a/_test/dbmeta/main.go b/_test/dbmeta/main.go index 3cc811e..6c5feb7 100644 --- a/_test/dbmeta/main.go +++ b/_test/dbmeta/main.go @@ -30,7 +30,7 @@ func init() { goopt.Description = func() string { return "ORM and RESTful meta data viewer for SQl databases" } - goopt.Version = "v0.9.21 (07/07/2020)" + goopt.Version = "v0.9.22 (07/08/2020)" goopt.Summary = `dbmeta [-v] --sqltype=mysql --connstr "user:password@/dbname" --database sqltype - sql database type such as [ mysql, mssql, postgres, sqlite, etc. ] diff --git a/code_http.md b/code_http.md index 87b588a..36f83df 100644 --- a/code_http.md +++ b/code_http.md @@ -138,7 +138,7 @@ func GetInvoices(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { // @Failure 400 {object} api.HTTPError // @Failure 404 {object} api.HTTPError // @Router /invoices [post] -// echo '{"customer_id": 24,"billing_address": "rNkjAsJjDKZGnsBxyUdpYvOkx","total": 0.37826635766312366,"billing_postal_code": "rNFjBOckDaCuciKulxAGnQGcj","invoice_id": 93,"invoice_date": "2255-08-11T14:38:49.47073267-05:00","billing_city": "fKvdAmQUufQYkjzsZhXrhWhqP","billing_state": "XdpPhuBIMnWbSRnmstifsKwvI","billing_country": "QdCWUxaOiascxToHVCZxnSPfO"}' | http POST "http://127.0.0.1:8080/invoices" X-Api-User:user123 +// echo '{"invoice_id": 57,"customer_id": 9,"billing_address": "rMHppATYFwjWxvjTGASkYSPkf","billing_state": "HIwKVtaMVGnQJHqXTJdibIzeA","billing_country": "ZHahDVUYbQzFAbJQkRbRsAPQy","total": 0.4534626433499875,"invoice_date": "2038-10-09T12:04:09.946815184-05:00","billing_city": "zNFsMoKCBYsOawVubnYRDvcmX","billing_postal_code": "BYylGmiCSWSFgfxRsSogPbKxg"}' | http POST "http://127.0.0.1:8080/invoices" X-Api-User:user123 func AddInvoices(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { ctx := initializeContext(r) invoices := &model.Invoices{} @@ -192,7 +192,7 @@ func AddInvoices(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { // @Failure 400 {object} api.HTTPError // @Failure 404 {object} api.HTTPError // @Router /invoices/{argInvoiceID} [patch] -// echo '{"customer_id": 24,"billing_address": "rNkjAsJjDKZGnsBxyUdpYvOkx","total": 0.37826635766312366,"billing_postal_code": "rNFjBOckDaCuciKulxAGnQGcj","invoice_id": 93,"invoice_date": "2255-08-11T14:38:49.47073267-05:00","billing_city": "fKvdAmQUufQYkjzsZhXrhWhqP","billing_state": "XdpPhuBIMnWbSRnmstifsKwvI","billing_country": "QdCWUxaOiascxToHVCZxnSPfO"}' | http PUT "http://127.0.0.1:8080/invoices/1" X-Api-User:user123 +// echo '{"invoice_id": 57,"customer_id": 9,"billing_address": "rMHppATYFwjWxvjTGASkYSPkf","billing_state": "HIwKVtaMVGnQJHqXTJdibIzeA","billing_country": "ZHahDVUYbQzFAbJQkRbRsAPQy","total": 0.4534626433499875,"invoice_date": "2038-10-09T12:04:09.946815184-05:00","billing_city": "zNFsMoKCBYsOawVubnYRDvcmX","billing_postal_code": "BYylGmiCSWSFgfxRsSogPbKxg"}' | http PUT "http://127.0.0.1:8080/invoices/1" X-Api-User:user123 func UpdateInvoices(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { ctx := initializeContext(r) diff --git a/dbmeta/codegen.go b/dbmeta/codegen.go index b12184c..6aaf62b 100644 --- a/dbmeta/codegen.go +++ b/dbmeta/codegen.go @@ -390,7 +390,7 @@ func (c *Config) GenerateTableFile(tableInfos map[string]*ModelInfo, tableName, outputFile := filepath.Join(fileOutDir, outputFileName) buf.WriteString(fmt.Sprintf("Writing %s -> %s\n", templateFilename, outputFile)) - c.WriteTemplate(tpl, data, outputFile, formatOutput) + err = c.WriteTemplate(tpl, data, outputFile, formatOutput) return buf.String() } @@ -439,10 +439,10 @@ func (c *Config) CreateContextForTableFile(tableInfo *ModelInfo) map[string]inte } // WriteTemplate write a template out -func (c *Config) WriteTemplate(genTemplate *GenTemplate, data map[string]interface{}, outputFile string, formatOutput bool) { +func (c *Config) WriteTemplate(genTemplate *GenTemplate, data map[string]interface{}, outputFile string, formatOutput bool) error{ if !c.Overwrite && Exists(outputFile) { fmt.Printf("not overwriting %s\n", outputFile) - return + return nil } for key, value := range c.ContextMap { @@ -471,21 +471,18 @@ func (c *Config) WriteTemplate(genTemplate *GenTemplate, data map[string]interfa rt, err := c.GetTemplate(genTemplate) if err != nil { - fmt.Printf("Error in loading %s template, error: %v\n", genTemplate.Name, err) - return + return fmt.Errorf("Error in loading %s template, error: %v\n", genTemplate.Name, err) } var buf bytes.Buffer err = rt.Execute(&buf, data) if err != nil { - fmt.Printf("Error in rendering %s: %s\n", genTemplate.Name, err.Error()) - return + return fmt.Errorf("Error in rendering %s: %s\n", genTemplate.Name, err.Error()) } if formatOutput { formattedSource, err := format.Source(buf.Bytes()) if err != nil { - fmt.Printf("Error in formatting template: %s outputfile: %s source: %s\n", genTemplate.Name, outputFile, err.Error()) - formattedSource = buf.Bytes() + return fmt.Errorf("Error in formatting template: %s outputfile: %s source: %s\n", genTemplate.Name, outputFile, err.Error()) } fileContents := NormalizeNewlines(formattedSource) @@ -504,13 +501,13 @@ func (c *Config) WriteTemplate(genTemplate *GenTemplate, data map[string]interfa } if err != nil { - fmt.Printf("error writing %s - error: %v\n", outputFile, err) - return + return fmt.Errorf("error writing %s - error: %v\n", outputFile, err) } if c.Verbose { fmt.Printf("writing %s\n", outputFile) } + return nil } // NormalizeNewlines normalizes \r\n (windows) and \r (mac) @@ -561,7 +558,10 @@ func (c *Config) GenerateFile(templateFilename, outDir, outputDirectory, outputF outputFile := filepath.Join(fileOutDir, outputFileName) buf.WriteString(fmt.Sprintf("Writing %s -> %s\n", templateFilename, outputFile)) - c.WriteTemplate(tpl, data, outputFile, formatOutput) + err = c.WriteTemplate(tpl, data, outputFile, formatOutput) + if err != nil { + buf.WriteString(fmt.Sprintf("Error calling WriteTemplate %s -> %v\n", templateFilename, err)) + } return buf.String() } diff --git a/go.mod b/go.mod index de86cb7..63f4ed7 100644 --- a/go.mod +++ b/go.mod @@ -24,7 +24,7 @@ require ( github.com/karrick/godirwalk v1.15.6 // indirect github.com/kr/pretty v0.2.0 // indirect github.com/lib/pq v1.3.0 - github.com/logrusorgru/aurora v2.0.3+incompatible // indirect + github.com/logrusorgru/aurora v2.0.3+incompatible github.com/mattn/go-sqlite3 v2.0.3+incompatible github.com/mwitkow/go-proto-validators v0.3.0 // indirect github.com/ompluscator/dynamic-struct v1.2.0 diff --git a/main.go b/main.go index 20e64c5..1c870c9 100644 --- a/main.go +++ b/main.go @@ -99,7 +99,7 @@ func init() { goopt.Description = func() string { return "ORM and RESTful API generator for SQl databases" } - goopt.Version = "v0.9.21 (07/07/2020)" + goopt.Version = "v0.9.22 (07/08/2020)" goopt.Summary = `gen [-v] --sqltype=mysql --connstr "user:password@/dbname" --database --module=example.com/example [--json] [--gorm] [--guregu] [--generate-dao] [--generate-proj] git fetch up sqltype - sql database type such as [ mysql, mssql, postgres, sqlite, etc. ] @@ -188,20 +188,20 @@ func main() { // Username is required if sqlConnStr == nil || *sqlConnStr == "" || *sqlConnStr == "nil" { - fmt.Printf("sql connection string is required! Add it with --connstr=s\n\n") + fmt.Print(au.Red("sql connection string is required! Add it with --connstr=s\n\n")) fmt.Println(goopt.Usage()) return } if sqlDatabase == nil || *sqlDatabase == "" || *sqlDatabase == "nil" { - fmt.Printf("Database can not be null\n\n") + fmt.Print(au.Red("Database can not be null\n\n")) fmt.Println(goopt.Usage()) return } db, err := initializeDB() if err != nil { - fmt.Printf("Error in initializing db %v\n", err) + fmt.Print(au.Red(fmt.Sprintf("Error in initializing db %v\n", err))) os.Exit(1) return } @@ -215,7 +215,7 @@ func main() { } else { dbTables, err = schema.TableNames(db) if err != nil { - fmt.Printf("Error in fetching tables information from %s information schema from %s\n", *sqlType, *sqlConnStr) + fmt.Print(au.Red(fmt.Sprintf("Error in fetching tables information from %s information schema from %s\n", *sqlType, *sqlConnStr))) os.Exit(1) return } @@ -237,7 +237,7 @@ func main() { err = loadDefaultDBMappings(conf) if err != nil { - fmt.Printf("Error processing default mapping file error: %v\n", err) + fmt.Print(au.Red(fmt.Sprintf("Error processing default mapping file error: %v\n", err))) os.Exit(1) return } @@ -245,7 +245,7 @@ func main() { if *mappingFileName != "" { err := dbmeta.LoadMappings(*mappingFileName, *verbose) if err != nil { - fmt.Printf("Error loading mappings file %s error: %v\n", *mappingFileName, err) + fmt.Print(au.Red(fmt.Sprintf("Error loading mappings file %s error: %v\n", *mappingFileName, err))) os.Exit(1) return } @@ -258,7 +258,7 @@ func main() { tableInfos = dbmeta.LoadTableInfo(db, dbTables, excludeDbTables, conf) if len(tableInfos) == 0 { - fmt.Printf("No tables loaded\n") + fmt.Print(au.Red(fmt.Sprintf("No tables loaded\n"))) os.Exit(1) } @@ -274,7 +274,7 @@ func main() { if *execCustomScript != "" { err = executeCustomScript(conf) if err != nil { - fmt.Printf("Error in executing custom script %v\n", err) + fmt.Print(au.Red(fmt.Sprintf("Error in executing custom script %v\n", err))) os.Exit(1) } os.Exit(0) @@ -283,7 +283,7 @@ func main() { err = generate(conf) if err != nil { - fmt.Printf("Error in executing generate %v\n", err) + fmt.Print(au.Red(fmt.Sprintf("Error in executing generate %v\n", err))) os.Exit(1) } @@ -294,13 +294,13 @@ func initializeDB() (db *sql.DB, err error) { db, err = sql.Open(*sqlType, *sqlConnStr) if err != nil { - fmt.Printf("Error in open database: %v\n\n", err.Error()) + fmt.Print(au.Red(fmt.Sprintf("Error in open database: %v\n\n", err.Error()))) return nil, err } err = db.Ping() if err != nil { - fmt.Printf("Error pinging database: %v\n\n", err.Error()) + fmt.Print(au.Red(fmt.Sprintf("Error pinging database: %v\n\n", err.Error()))) return } @@ -439,7 +439,7 @@ func execTemplate(conf *dbmeta.Config, genTemplate *dbmeta.GenTemplate, data map rt, err := conf.GetTemplate(genTemplate) if err != nil { - fmt.Printf("Error in loading %s template, error: %v\n", genTemplate.Name, err) + fmt.Print(au.Red(fmt.Sprintf("Error in loading %s template, error: %v\n", genTemplate.Name, err))) return err } var buf bytes.Buffer @@ -464,20 +464,20 @@ func generate(conf *dbmeta.Config) error { err = os.MkdirAll(*outDir, 0777) if err != nil && !*overwrite { - fmt.Printf("unable to create outDir: %s error: %v\n", *outDir, err) + fmt.Print(au.Red(fmt.Sprintf("unable to create outDir: %s error: %v\n", *outDir, err))) return err } err = os.MkdirAll(modelDir, 0777) if err != nil && !*overwrite { - fmt.Printf("unable to create modelDir: %s error: %v\n", modelDir, err) + fmt.Print(au.Red(fmt.Sprintf("unable to create modelDir: %s error: %v\n", modelDir, err))) return err } if *daoGenerate { err = os.MkdirAll(daoDir, 0777) if err != nil && !*overwrite { - fmt.Printf("unable to create daoDir: %s error: %v\n", daoDir, err) + fmt.Print(au.Red(fmt.Sprintf("unable to create daoDir: %s error: %v\n", daoDir, err))) return err } } @@ -485,7 +485,7 @@ func generate(conf *dbmeta.Config) error { if *restAPIGenerate { err = os.MkdirAll(apiDir, 0777) if err != nil && !*overwrite { - fmt.Printf("unable to create apiDir: %s error: %v\n", apiDir, err) + fmt.Print(au.Red(fmt.Sprintf("unable to create apiDir: %s error: %v\n", apiDir, err))) return err } } @@ -498,41 +498,41 @@ func generate(conf *dbmeta.Config) error { var GoModuleTmpl *dbmeta.GenTemplate if ControllerTmpl, err = LoadTemplate("api.go.tmpl"); err != nil { - fmt.Printf("Error loading template %v\n", err) + fmt.Print(au.Red(fmt.Sprintf("Error loading template %v\n", err))) return err } if *addGormAnnotation { if DaoTmpl, err = LoadTemplate("dao_gorm.go.tmpl"); err != nil { - fmt.Printf("Error loading template %v\n", err) + fmt.Print(au.Red(fmt.Sprintf("Error loading template %v\n", err))) return err } if DaoInitTmpl, err = LoadTemplate("dao_gorm_init.go.tmpl"); err != nil { - fmt.Printf("Error loading template %v\n", err) + fmt.Print(au.Red(fmt.Sprintf("Error loading template %v\n", err))) return err } } else { if DaoTmpl, err = LoadTemplate("dao_sqlx.go.tmpl"); err != nil { - fmt.Printf("Error loading template %v\n", err) + fmt.Print(au.Red(fmt.Sprintf("Error loading template %v\n", err))) return err } if DaoInitTmpl, err = LoadTemplate("dao_sqlx_init.go.tmpl"); err != nil { - fmt.Printf("Error loading template %v\n", err) + fmt.Print(au.Red(fmt.Sprintf("Error loading template %v\n", err))) return err } } if GoModuleTmpl, err = LoadTemplate("gomod.tmpl"); err != nil { - fmt.Printf("Error loading template %v\n", err) + fmt.Print(au.Red(fmt.Sprintf("Error loading template %v\n", err))) return err } if ModelTmpl, err = LoadTemplate("model.go.tmpl"); err != nil { - fmt.Printf("Error loading template %v\n", err) + fmt.Print(au.Red(fmt.Sprintf("Error loading template %v\n", err))) return err } if ModelBaseTmpl, err = LoadTemplate("model_base.go.tmpl"); err != nil { - fmt.Printf("Error loading template %v\n", err) + fmt.Print(au.Red(fmt.Sprintf("Error loading template %v\n", err))) return err } @@ -553,17 +553,30 @@ func generate(conf *dbmeta.Config) error { modelInfo := conf.CreateContextForTableFile(tableInfo) modelFile := filepath.Join(modelDir, CreateGoSrcFileName(tableName)) - conf.WriteTemplate(ModelTmpl, modelInfo, modelFile, true) + err = conf.WriteTemplate(ModelTmpl, modelInfo, modelFile, true) + if err != nil { + fmt.Print(au.Red(fmt.Sprintf("Error writing file: %v\n", err))) + os.Exit(1) + } if *restAPIGenerate { restFile := filepath.Join(apiDir, CreateGoSrcFileName(tableName)) - conf.WriteTemplate(ControllerTmpl, modelInfo, restFile, true) + err = conf.WriteTemplate(ControllerTmpl, modelInfo, restFile, true) + if err != nil { + fmt.Print(au.Red(fmt.Sprintf("Error writing file: %v\n", err))) + os.Exit(1) + } + } if *daoGenerate { //write dao outputFile := filepath.Join(daoDir, CreateGoSrcFileName(tableName)) - conf.WriteTemplate(DaoTmpl, modelInfo, outputFile, true) + err = conf.WriteTemplate(DaoTmpl, modelInfo, outputFile, true) + if err != nil { + fmt.Print(au.Red(fmt.Sprintf("Error writing file: %v\n", err))) + os.Exit(1) + } } } @@ -576,13 +589,26 @@ func generate(conf *dbmeta.Config) error { } if *daoGenerate { - conf.WriteTemplate(DaoInitTmpl, data, filepath.Join(daoDir, "dao_base.go"), true) + err = conf.WriteTemplate(DaoInitTmpl, data, filepath.Join(daoDir, "dao_base.go"), true) + if err != nil { + fmt.Print(au.Red(fmt.Sprintf("Error writing file: %v\n", err))) + os.Exit(1) + } + } + + err = conf.WriteTemplate(ModelBaseTmpl, data, filepath.Join(modelDir, "model_base.go"), true) + if err != nil { + fmt.Print(au.Red(fmt.Sprintf("Error writing file: %v\n", err))) + os.Exit(1) } - conf.WriteTemplate(ModelBaseTmpl, data, filepath.Join(modelDir, "model_base.go"), true) if *modGenerate { - conf.WriteTemplate(GoModuleTmpl, data, filepath.Join(*outDir, "go.mod"), false) + err = conf.WriteTemplate(GoModuleTmpl, data, filepath.Join(*outDir, "go.mod"), false) + if err != nil { + fmt.Print(au.Red(fmt.Sprintf("Error writing file: %v\n", err))) + os.Exit(1) + } } if *makefileGenerate { @@ -635,16 +661,26 @@ func generateRestBaseFiles(conf *dbmeta.Config, apiDir string) (err error) { var HTTPUtilsTmpl *dbmeta.GenTemplate if HTTPUtilsTmpl, err = LoadTemplate("http_utils.go.tmpl"); err != nil { - fmt.Printf("Error loading template %v\n", err) + fmt.Print(au.Red(fmt.Sprintf("Error loading template %v\n", err))) return } if RouterTmpl, err = LoadTemplate("router.go.tmpl"); err != nil { - fmt.Printf("Error loading template %v\n", err) + fmt.Print(au.Red(fmt.Sprintf("Error loading template %v\n", err))) return } - conf.WriteTemplate(RouterTmpl, data, filepath.Join(apiDir, "router.go"), true) - conf.WriteTemplate(HTTPUtilsTmpl, data, filepath.Join(apiDir, "http_utils.go"), true) + err = conf.WriteTemplate(RouterTmpl, data, filepath.Join(apiDir, "router.go"), true) + if err != nil { + fmt.Print(au.Red(fmt.Sprintf("Error writing file: %v\n", err))) + os.Exit(1) + } + + err = conf.WriteTemplate(HTTPUtilsTmpl, data, filepath.Join(apiDir, "http_utils.go"), true) + if err != nil { + fmt.Print(au.Red(fmt.Sprintf("Error writing file: %v\n", err))) + os.Exit(1) + } + return nil } @@ -652,7 +688,7 @@ func generateMakefile(conf *dbmeta.Config) (err error) { var MakefileTmpl *dbmeta.GenTemplate if MakefileTmpl, err = LoadTemplate("Makefile.tmpl"); err != nil { - fmt.Printf("Error loading template %v\n", err) + fmt.Print(au.Red(fmt.Sprintf("Error loading template %v\n", err))) return } @@ -666,7 +702,12 @@ func generateMakefile(conf *dbmeta.Config) (err error) { populateProtoCinContext(conf, data) } - conf.WriteTemplate(MakefileTmpl, data, filepath.Join(*outDir, "Makefile"), false) + err = conf.WriteTemplate(MakefileTmpl, data, filepath.Join(*outDir, "Makefile"), false) + if err != nil { + fmt.Print(au.Red(fmt.Sprintf("Error writing file: %v\n", err))) + os.Exit(1) + } + return nil } @@ -676,23 +717,28 @@ func generateProtobufDefinitionFile(conf *dbmeta.Config, data map[string]interfa serverDir := filepath.Join(*outDir, conf.GrpcPackageName) err = os.MkdirAll(serverDir, 0777) if err != nil { - fmt.Printf("unable to create serverDir: %s error: %v\n", serverDir, err) + fmt.Print(au.Red(fmt.Sprintf("unable to create serverDir: %s error: %v\n", serverDir, err))) return } var ProtobufTmpl *dbmeta.GenTemplate if ProtobufTmpl, err = LoadTemplate("protobuf.tmpl"); err != nil { - fmt.Printf("Error loading template %v\n", err) + fmt.Print(au.Red(fmt.Sprintf("Error loading template %v\n", err))) return err } protofile := fmt.Sprintf("%s.proto", *sqlDatabase) - conf.WriteTemplate(ProtobufTmpl, data, filepath.Join(*outDir, protofile), false) + err = conf.WriteTemplate(ProtobufTmpl, data, filepath.Join(*outDir, protofile), false) + if err != nil { + fmt.Print(au.Red(fmt.Sprintf("Error writing file: %v\n", err))) + os.Exit(1) + } + compileOutput, err := CompileProtoC(*outDir, moduleDir, filepath.Join(*outDir, protofile)) if err != nil { - fmt.Printf("Error compiling proto file %v\n", err) + fmt.Print(au.Red(fmt.Sprintf("Error compiling proto file %v\n", err))) return err } fmt.Printf("----------------------------\n") @@ -701,18 +747,28 @@ func generateProtobufDefinitionFile(conf *dbmeta.Config, data map[string]interfa // protoc -I./ --go_out=plugins=grpc:./ ./dvdrental.proto if ProtobufTmpl, err = LoadTemplate("protomain.go.tmpl"); err != nil { - fmt.Printf("Error loading template %v\n", err) + fmt.Print(au.Red(fmt.Sprintf("Error loading template %v\n", err))) return err } - conf.WriteTemplate(ProtobufTmpl, data, filepath.Join(serverDir, "main.go"), true) + err = conf.WriteTemplate(ProtobufTmpl, data, filepath.Join(serverDir, "main.go"), true) + if err != nil { + fmt.Print(au.Red(fmt.Sprintf("Error writing file: %v\n", err))) + os.Exit(1) + } + if ProtobufTmpl, err = LoadTemplate("protoserver.go.tmpl"); err != nil { - fmt.Printf("Error loading template %v\n", err) + fmt.Print(au.Red(fmt.Sprintf("Error loading template %v\n", err))) return err } - conf.WriteTemplate(ProtobufTmpl, data, filepath.Join(serverDir, "protoserver.go"), true) + err = conf.WriteTemplate(ProtobufTmpl, data, filepath.Join(serverDir, "protoserver.go"), true) + if err != nil { + fmt.Print(au.Red(fmt.Sprintf("Error writing file: %v\n", err))) + os.Exit(1) + } + return nil } @@ -721,7 +777,7 @@ func createProtocCmdLine(protoBufDir, protoBufOutDir, protoBufFile string) ([]st if *gogoProtoImport != "" { if !dbmeta.Exists(*gogoProtoImport) { - fmt.Printf("%s does not exist on path - install with\ngo get -u github.com/gogo/protobuf/proto\n\n", *gogoProtoImport) + fmt.Print(au.Red(fmt.Sprintf("%s does not exist on path - install with\ngo get -u github.com/gogo/protobuf/proto\n\n", *gogoProtoImport))) return nil, fmt.Errorf("supplied gogo proto location does not exist") } } @@ -771,8 +827,8 @@ func CompileProtoC(protoBufDir, protoBufOutDir, protoBufFile string) (string, er stdoutStderr, err := cmd.CombinedOutput() if err != nil { - fmt.Printf("error calling protoc: %T %v\n", err, err) - fmt.Printf("%s\n", stdoutStderr) + fmt.Print(au.Red(fmt.Sprintf("error calling protoc: %T %v\n", err, err))) + fmt.Print(au.Red(fmt.Sprintf("%s\n", stdoutStderr))) return "", err } @@ -789,8 +845,8 @@ func GoFmt(codeDir string) (string, error) { stdoutStderr, err := cmd.CombinedOutput() if err != nil { - fmt.Printf("error calling protoc: %T %v\n", err, err) - fmt.Printf("%s\n", stdoutStderr) + fmt.Print(au.Red(fmt.Sprintf("error calling protoc: %T %v\n", err, err))) + fmt.Print(au.Red(fmt.Sprintf("%s\n", stdoutStderr))) return "", err } @@ -801,17 +857,27 @@ func generateProjectFiles(conf *dbmeta.Config, data map[string]interface{}) (err var GitIgnoreTmpl *dbmeta.GenTemplate if GitIgnoreTmpl, err = LoadTemplate("gitignore.tmpl"); err != nil { - fmt.Printf("Error loading template %v\n", err) + fmt.Print(au.Red(fmt.Sprintf("Error loading template %v\n", err))) return } var ReadMeTmpl *dbmeta.GenTemplate if ReadMeTmpl, err = LoadTemplate("README.md.tmpl"); err != nil { - fmt.Printf("Error loading template %v\n", err) + fmt.Print(au.Red(fmt.Sprintf("Error loading template %v\n", err))) return } populateProtoCinContext(conf, data) - conf.WriteTemplate(GitIgnoreTmpl, data, filepath.Join(*outDir, ".gitignore"), false) - conf.WriteTemplate(ReadMeTmpl, data, filepath.Join(*outDir, "README.md"), false) + err = conf.WriteTemplate(GitIgnoreTmpl, data, filepath.Join(*outDir, ".gitignore"), false) + if err != nil { + fmt.Print(au.Red(fmt.Sprintf("Error writing file: %v\n", err))) + os.Exit(1) + } + + err = conf.WriteTemplate(ReadMeTmpl, data, filepath.Join(*outDir, "README.md"), false) + if err != nil { + fmt.Print(au.Red(fmt.Sprintf("Error writing file: %v\n", err))) + os.Exit(1) + } + return nil } @@ -833,12 +899,12 @@ func generateServerCode(conf *dbmeta.Config) (err error) { if *addGormAnnotation { if MainServerTmpl, err = LoadTemplate("main_gorm.go.tmpl"); err != nil { - fmt.Printf("Error loading template %v\n", err) + fmt.Print(au.Red(fmt.Sprintf("Error loading template %v\n", err))) return } } else { if MainServerTmpl, err = LoadTemplate("main_sqlx.go.tmpl"); err != nil { - fmt.Printf("Error loading template %v\n", err) + fmt.Print(au.Red(fmt.Sprintf("Error loading template %v\n", err))) return } } @@ -846,10 +912,15 @@ func generateServerCode(conf *dbmeta.Config) (err error) { serverDir := filepath.Join(*outDir, "app/server") err = os.MkdirAll(serverDir, 0777) if err != nil { - fmt.Printf("unable to create serverDir: %s error: %v\n", serverDir, err) + fmt.Print(au.Red(fmt.Sprintf("unable to create serverDir: %s error: %v\n", serverDir, err))) return } - conf.WriteTemplate(MainServerTmpl, data, filepath.Join(serverDir, "main.go"), true) + err = conf.WriteTemplate(MainServerTmpl, data, filepath.Join(serverDir, "main.go"), true) + if err != nil { + fmt.Print(au.Red(fmt.Sprintf("Error writing file: %v\n", err))) + os.Exit(1) + } + return nil } @@ -857,14 +928,14 @@ func copyTemplatesToTarget() (err error) { templatesDir := filepath.Join(*outDir, "templates") err = os.MkdirAll(templatesDir, 0777) if err != nil && !*overwrite { - fmt.Printf("unable to create templatesDir: %s error: %v\n", templatesDir, err) + fmt.Print(au.Red(fmt.Sprintf("unable to create templatesDir: %s error: %v\n", templatesDir, err))) return } fmt.Printf("Saving templates to %s\n", templatesDir) err = SaveAssets(templatesDir, baseTemplates) if err != nil { - fmt.Printf("Error saving: %v\n", err) + fmt.Print(au.Red(fmt.Sprintf("Error saving: %v\n", err))) } return nil } diff --git a/packrd/packed-packr.go b/packrd/packed-packr.go index cca2d65..52c7b36 100644 --- a/packrd/packed-packr.go +++ b/packrd/packed-packr.go @@ -33,7 +33,7 @@ var _ = func() error { "93bd183343e73a133e7c243e834a15f8": "1f8b08000000000000ffac554d73db36103d13bf62c31399b854cf4d7d882d67c69d54f2d4b1a7d31b082c243820402f405baaa3ffde014849946ccff4201f2c72f1f6bdfd20765b2e7ef005c2cb4b25b9bbe9df66bcc1cd8631ddb48e02142ccb85b301572167598e448e7c7c524d32102a8322e48c65f94287655757c23593076dff5d769385a32667256393095c74dac86bab1c680f9d4709c18144a52d425822f0b6355af0a09d853a62415be5ce80dbf8f48022c013371d7ad0363878d23cb9f5d0969c40ef2b16d62d8ea47ca04e0478610c00601bc594070419fff940da2ec029785ee256f7997b689194a30625286d0cc610a05ec32f7f83704dab0d82327cc1b23d1fc0c0c6583699c0371ed0874bd7343a9c48eb8072ac958298754d8d74cab406c65752616eaf6f4e28d4f3c19b42737f5aa1b93f16faabb34137787fb2da8d08774a1bd67f99dfdce2f6d180eaac284458c170b5aacbfef70cfca3197c4ac69e3841b1fd72af88662e7c759d9590ae611f1fa17024c1ba002a9eb16c0c8473504da8ae225e15f9009eb900e93c2ffb1a5c11dd595e1bfceefee4e497dcfc713b9f8d651ebcb3d0f2b5715c8270445d1b5264efb81e09bfe51ec5f7b9ddb5b1fa5fb98e951d0977c90e8a6be3536e07c02319596ff1896194deb5f548e135bd4ef611fd01f035fd803fa69fa2c1b7a297c93ea23f00bea61ff0c7f4175cde70e28d1f73d75c42db5b5bee7dfa2093c61e7d2430f2d8290c1d985e00a142422b300d661e78cd3db26c7a01fbbf8f71a257d38b3eb22f6dbb1fb507eefb01ceb203d4c7dde33026dd6281942e449afc61c9033c6b63a046d0f6c9fd4009352a4708b842d1857839fda361d9e0da5fa9b864d29ab974ed1a387812dbe19fd60507893e68dbef97fe8445d5e450489f70488a0b7cd99c25ff91a11c0affc232e9c33dfc760ec3e6abaeadd48422145bc37ddc52731539cb92659ec4ffc37b12656cb956f0218a5497dc7e91928a32ca6684a123dbc7e1ab193e17b988b9c65d1819d25ab55c4a42efe385cc4b966d7abe1843f57ddd6251c2877348ecc3eb3bd452abd4ce00716e7910dcc68e08d76a945b66e50874ccedd7cfa0e1f79e77d6355f351a59949f417ffa94045404a520fa235db22ce5a9fd3f486eaeeeac44326b6d17292c555d6f6b5f947d8ca9ee3bf7ea1643a122cba60f6548c16a13676ddfd977c857878dad9d3351616058c1f979a4819f3f772d9b22b6578f1d37c5ea6c678cdcbb1e46e2b92a5665791039dbb0ff020000ffff099f892465090000", "9ec72c1db17b72aeed9a9dfae4794622": "1f8b08000000000000ff84924d6bdb401086effb2b5e924b0c967a2f6d21d8b49796b46e028510a2b176b45ebada51b52bbb69c87f2f2bc91f710cbe8e9e79e69dd1de9752d7ece3c37b7cf884abdb950db00104c39e5b8aac5159c7681c5360b0b61141bab664588ffc5de4ba7114394cd491eada39d4a26d654b8a563c36d6392c194e429ce2493aac68cd58327b6ca8f5acdf38264a5d5e62b6b89b637e7d83cf9d2f932aa8c2b02f06e336283409aa2d015b21ae1845966d814c931469b98642608d28e835396e578c5234a3249f12965d8852db7facb1b171b51569928fbda37264527be0d87ff35433641898523454fe26c3b952b303ebfea2d6236e2469d6d2b5618a9f3fbefec2f2099a2bea5c04798d2f378b6ffbf1fdc8b48cb475a194da451ead56fcf4e81efb5b54d2aa0cf70b8eade5b5f5062d97d2ea30f81b32d69b87abcb11e0ec3b19d6d962802607bd0c4268b84c7f75941cf60d95be61d6720a417b6aa81c32778d3e6286ca213367c7af99a1b263d20bd9a5eb83630cae8aa230a29e9fb78f14179ae431fc717f1f0d47722e3792c7ba7117c85f5e12feda368c38a339ed18d73f6f20ad4f1bc6e39c37743d785a325eefbc44f7e05bc9ff000000ffff6236e43020040000", "9ecd3f03cbe3e3ef5337a260a193f876": "1f8b08000000000000ff8c945f6fd33014c59f934f71895448509ac1847898d4876d5d61b07f6a2721046873939b60e1d8ad7dc356ac7c77e4c4ddbaf247ed4b1dfbdedf39b64f626d8125970851c1d48d598afb9b0a890991552aa37a21a2b60df7f6e01dd2a110d66633d24d4e17acc6b6056e8041d9c89cb892400a2a24606004cf1154091a73a58bd824506a5583b5d9359b0bf4dde4c6c025d077746b63466ccecc7ab9f08f4e7ec134ab0d0c61c12a04f7f3438dcb060d61017181256b0419e7e355f24797e1bf1086209b7a8efad19c710698e73e61ec6f41942e50f7d2c51c8cd2e4a772259a5aba5ad45a6918c289d6178a26aa9145ea8a275c16fd62e84eebefa719e7740fb99284f7941df7ff69672c7ddc0097f4f64dea850d692eab04628da673fde5db4b6bb35a1528ae58fe8355fe2cb32da9144811135375e7b64fa9f3d6fb4bc08681590a381841646d6650604ee78d203e5b8ab68dc230e0a5d77f368228720d6eaa37633ae78c4b73285771579642f4e26b1475e420e83b5d6318046d18b49bc0d103f0a1ccdaec4af39ae9d5475c990f8a4b2c9c8d75e3f8281b6bfe13b5db599c7488da98a5e8396e2b23286bca660bcd25957134305e6dbe828181cbc96476720d8302a6979f663039b93e7e0f93d3e9ec71eef2e2ec739482590a7ff2dbd79284410b280cc23f1c2d94a14aa3d9c9d4edc0dc6ed83a3b3d3f75831d1dec2ab0c6a6bba0438f1c1f65539c7359c4662992fe06ce5455f561905c74f2fd8ccb73c74dfacb7219eb08b32e533ee17dd5739fe0753d2fbb486e303552a3a57b4c61f8ba4b6c8fcd25411fe083917bb1a6eaee5835d283a3a7df9ce87fec070fc3fd0dfef662eedf97b00d436b51166d1bfe0e0000ffff9fb98df146050000", - "a2d5586edb9ff79f53fe610c4e91de3d": "1f8b08000000000000ffbc3bfd5324b7b13f7bfe8acee254e06a771638dbb1712e290eb833153e2ec0f92585af58ed8c765646230d9266610dbcbffd55b7a4f980e572ae974aaae263a45677abbbd55fd25e66ba2cb9729f76e02f7f85f58bb9b0202c3028b8e286399ec34c480e95e4cc72e0b97060756d320e42413a76bcac2473dc6e244f50ed4a09a5cec54c64cc09ade0564809530e525b3784a5ae61ce161ca69c2bb86546f1fc198e8d646d0d394992cb3f5c1e898c2bcb3fadcf9dabecce782cca22b573c1656e53a1c75396177c1ca046bb15cbe6fc8fdb9bafd3cdd154d63cb58b62a35dac2baefc46526d8ab1f4cbecd8af1bbd4e3737e0f20f97eff5beceda5585ce75460b0ae1e6f534cd7439b625935271ebc605577fb38eb9daa6958ad4be68d906203567d842d8969cff1e6582d6f616e076fe36354c65f33725b38e9b8d2f5a17760567bcd2c6c11e3379777b8686336672e2d1cbf445a63fb3d27fbebc34492ee61c750b4e6b0995d1799d71b4bcbdb38ffbb0be6738737c0886b37c08759533c781a91c722eb9e31b7076707e01ac12b8f4579e3988a60833a34bb460b1e00a72e6d894599e428f1e1a639269a568a50637e7904f218ca0b95a67842a80292697bf710f1070111ff180d04ca6730e38958356343293acb0c8db42e43c4f93e4ed92f6823873ee9890d633da473cd5b50b18655d121775e66ac387c47b244a275443a6cb8a3931953c00825b563cb9156e4e480cbfa985e179c4a658c9ed90c811a41dd2569852dad121b569921c3ab07585dab37059685376b4dc6af357a17e9bd7a8f772031cee153189b2921c0fb005ab4b0eb565c85cc9dd5ce73685f78d57697900a13259e73c52859936a06a2969a9e7dcc2a5bd91e9492de53ffdaaaee949a60ab2f4eaba1847598eed8d1cafe18ab75acb0dd0062e8bdaf0a226e4e9733cede63cdc18e13612dc170a93df553c43d6a7cc8a0ca6b5900e9d60a13da6344926055713f49fde14c62094ad4801d325e1b8d5e61af40cceb99bc3f99c4b553bf7270b97f974db6b70253f11727bdcc06d78d5ed4fb7cfbde623d5f14b34f7e6a2e486ede99c9b3f5928f4af562ba85876cd0a8e9ac6ef95e4bb2bc71e6e234d9204bd339dd6a056a155d24610cbd018c005352ac784e239a0710a7f46d231bf23a0b1874df3299cdf48e1f8ebceb9fd68f1cc78d1520ce99dbc999652df2284974b9a4c26137b2393bdb383dd8b03b8d87d7b74000326a7756907c97a020070b98b9f87f92780c3938b83f70767f0e1ecf078f7ec5ff0f7837fc1eec78bd3c393bdb383e383930b3839bd80938f474743bff44238c93fe19f273fef9eedfdb47bb6bef5dde6c653b05de38475482252e803bc3b3d3b387c7f42f4d65b68f46bef0ece0e4ef60ece61c068d80e7a10c9575f9d9ec0fec1d1c1c5019c9cc2eedec5e1e9099c9ec0c70ffbbbddb164038591acadadadc18561caceb429f1bc398d13854ed0708184111dc87df2d5787c099b9f20c808bef07f42395e70d31fc413b40333262d07a88c289959ee8033350700563bdd7c645aee3cc321b9da81d196ffc8f98cd5d2edc0e5a7e42bcfdc3eae80093aa19d41407f75cd973fa206af1a15fee89dc84ed8d18fb8eb9da0961f0780f6bce32de44ae403c8a73b83003a400feef4b49eed0c8472afb7879b435db9213ad237cd8a8997d9d62720e3f8528901a80533d99c196f419f9559f8f6320b1f24b388a327b3adef369fcbcc3317e25a105a900c4d79b9f4acfa472b7ee33b5bdf6d36627208e96574e1ff6c25e4510fb75a1179e8209fed4f10adf83f6f532fcae777d89467ae6754d17202df2f980ecdb6b613809f1bcf76c7789a3593e4918e29bad7e8db3001c130c828c463c2e31dade1d635098fb050696b29fc53c8dfdf3d85ccd439cc6a45498c1d02ba739833954b6eec104a76cd31a11f46f76cb9597003cc70600b2628e8a6b037e7d935602e42615ccfc8d75e661d16791e50d84feb6b4d5c1f9dfbb1263ebc158a99251c2aeb98943e464c2693b7bbe73fe1b4f0e36d62b66ee7ba9639160a618ee798a0fdefb8d0e3a9507e0b606bc39b31948450585218a8989ba7c9d718950bee6054c34b2928b197eb5b2535cb1b7150f869a24ff235dc229a1541b1876b6cd8edd8a7e1cf635a12aa181fb49ea78a4f68c27a5470ac983e1f3c2117660377cc158c46f646a28dbeb1218efe82d1e6abd108335beb0c0cd296b14133dbd02e9950d00c5386103ff040b41f3e938a9f6497f103cda6e52e8e963aaf2566519ebaaf11ac5b05d7fc1d8cb3990ac6dbe36f342bdd1babd0281ae682ac4739d3cf0751ba2daf0b6e6e8d709c9484395d1e59f49a5af76395d119b7d6ab241a2de64e661bc40c9476adb9a232b2bc1541f2b5b7d9f84994fcb1686be28c4e1443c94d856a96aeadc1ed9c2b90ac56d91c1d776bfe6ece7cad70fe8f233420124d9b4909dba00d26635949d602ccd2b76702b9ad204dc769c73400f010b55b20a64f2bae80c1d4e85bcb0d9eca50df221d39d7d6ed7cbff9fde6d8deb2a2e0662c54ceefd2b92b252dff68399da671561b39c6a58223921977d91c16829c5d8959ad148a27de73ad24e0b3b904f1bc04e133a7843c6ba0ce0a8e9f9956564b9edcdfa7efb9fa89cbead13b607257a86da10aaa4ee3390ce70f93dac604d13b736697de667ca598d306f054337b6dd3e4154c485b732eab098c400aeb5a2f0b8e99823bdb80112684eb25b8c1522629fa9949031c1483e0a6f6ea450710ed34b89668cae737924c249f766da251af854ab2ccd3f34d11db9b4f4edd1c15ee19067e871b4109e47c11378bd23b08e05de18512b8531104736d7c4eb0ce49436e8246ca33a7cd328577b1488e0827c7410713c898c2d3535b1f237a72eb9e622a0ad229b3f3a4771249eba12f10625acff706c53f2934c82fd42a4789bcc877f20a229f09c02be47156cb668ca4173c06e2c4d8675b5b8a5c7097a570686dcdbdda27b8cd5cd84ab2259915c6e8aa76482e2d841385d2c6132c8403ff49b40a1d9126afa0d069a9730fa6217866cb5d5d0da162d6c224faeb0935320883e5ce11ab1d5d84a5218d8249d7bb47a124afe0ec6077fff8202d3dc90f61b1e12c2f79f20a58558dbdab1f63fc490b4d703e9580f742c139cd0e7d9a13dc0b08255c73eab8a293c42a31fe8b2f3931cdfa6bc445dd22ca8d50a7464b4c8792579033bd121e53a9268b0a368c9ba72c8c6574c65015314f7885a2e072252e5fa05b30bc32dc7245526460f46df022d9bc3d0cb49e3cd6da5aa75d12d2aae4155cbe3f3d3b26fe88977791c94febe9182df32a67fa0a63755ae61b087ffe8fa37ffe3b787b23ef22fc4fe87709f6a7903636a0e86b23d831eeb799a1ddc7a90f21ed857d3e432509ad1ac0981213ac3f7c4d272f84fbda09297ee33e46a1f6678695fc569beb21d0e6f32981a3eacf6f8375b62a8ae691ebac46b3f039270a4eac6e6f14428d0aad44867f7991210abd1298b06bfa8740df7f49830c017db2b09a0114c88c493d26a08d903a9ffb7e18cf613f58874df66a63b87272d9ce0e93111c3323d8fe5bfc6b79fe8fa364041fb47585e1fee35864465b3d73e87bc3614a46c11127c907c91466970165328253c3b290a9f4b9808b65c56d921c6bebba3d3cac1f6cc31169e478696fe430326287d1efa3da8ecff12b0d5d9dda721f5bab0a154859273949ca709e387996e70da4efbbc1db65f44043b2192cf98c62b2812364940fb11cb32cd524743c4fe1701669c46cd07105587de539192f93719779eefb6ab58d9e103da5a7f286df39c352e47ed2cb6440578825f5d6def8cab02c2c6859f4e1b997e937b72c1860524aa42621dd670bfea60340010207431359396ac68602aec5e334c6ad76599abce552dfface1d6a112bd0b0aa2bc521d8b98f82bd196d6012fa109394922edc1535baee135f6a0fec8dbc42310e7660106007c33859e866ce7711daa9e8311a80e9d271db594aa548334bcdddf327380a7d153bca2d9dd0500eb004fad8e68bbbf982a98ce7a4346fa7f1a6c2e733313c3029dc12052ad9124b1f2a43f5ad6a82e44c9b9239529bb1fed26b3bd80425891f3c4652bdece8a869e34f46a338ba2fcc9b49580c237073619f34457d76d2d8e713a4295c34f8d1e8b9a0cc6e4aed6d7fcce95682369c604eeeedc85b73c7e8201d97cb8efdc045c34a637ebc9c723a31ed9ed0523c4b1ccf962ae85e866a77b8a5c2df563c13b3e567374e25516c9550300db24e139427b3be653c1af13b9ebd69eb1ad262488d7b2794f8a63e0091ed82dbcc88cae71988ad761c84f3b749616ace6c2725a073464980505ef3c8312ed7246a1ca524cbbb331274901ec30cd36252cda5aed0589c86acb64e97225c4175fa437ae6735bf897ae2123d949ad2b7073a3ebc25b0e551c788c91a17045a316fa9a2793985b5ce0d43b4aa7b50168c669284d12c2ce1430693554baaa657be9a51cbf73de334f974f2d97dca18f11d325edb8e333696de6defca571f67f8ddaf5b26d8340ac916300789907328b8a194fa831790ca7d4ee8e43c9780c473d51b5e2a98c508e3a5f6d2647130b6684aec982cbd6a13630584e0697617db2f6f89820a167725ea74527ace4c386491c5734e2f3f9fd5847c40104c025a17d3b0c4ee5942661aab5dce812f374fe83c8c3940f616d2944c68c96db14b5216ed5b6e91ae2a969369a26c9fd3d18a60a0e5f5ff3e510be5e305973d87903293c3ea217bebff75a98c1e08f6ba3ed6f17030285c7c72793a3d79b17f0c7359cf748c23f8f8ff7f7c0558ef892a6b40ff7648a95b1be675341be9bea593a6c963b60ed4d32e51f3dfba352aaeb786c83955322d2b5732a9d7c29c5e59527fce6fe7e707f9f3e3e0e1e1f27c445c010c920a6fc8971a5f073b4bea626e9a645215168f9d6fee985f7a264c2b6cee6c06c7b9e514338cb4c416932328a90578e5bf7a6b6dc4c106fa6d5af81662f2075f7449e63321ae171c5213e19220b0bc16fe13636a93c6870f253348487a618018007a003026487f000def89287d168d4fc3f7940d1d6922e3b1e7c3845d8c9fd7d3331a0e1013c3e4e001e92874ad6866139f16c493bf3748d0bb7387d783ffa0c561fe95bfe9ca138fe1cfe6355ad84f7e32fe0df6325977b5820be40a8057881e2e7303c01788ee15cb16bfec2e276eec93a5fc63c3978b147649356df3b607821acf381edca77a0d03ea8c644105cf88e9c1292ed94c51e3522493a6632a14336787c4ce9bf0362081ee0fe7eb082d2801c0b2ef3e85e58dc4c7e290a688df245641d982f46fb5ce32fa37f0efb3bc83c358bcf91790afb3bc8740ce873143a60ff25519103befa2f09ec7713fbfd62fb7f905807c37d8f38855f02a25f06f0cbe097c1069ef7806135e176f1675888730318104af02e646d0d4eb4e3d6b7366ee4108e6dafafe0db40fe0a8d6a2bd636d34aee1825a074c540fdda18d06f6a6e96e1d9977f4a13de98514cac9d06a132436f9986f19619300b41d0e67512e53f9813506eae4dd9794b9526231fd3ac271b98535a8dac632a6726ef215e3f393d696eabc305a1015f9d6e7412829828f8e66eee3beffb6fe1983be67b34479ade99250f384ca1755951503d897cc3037c08a4ffce97f8b98b5b3e8c5bc6913dff66ec882b7868ba163f6382f50019bdce833c97fd08bdeaffc943b8e0047858123bcba7ff7980e5032c93872aeaf4df80aae4a15cda1bf905284b0b5f00e82f837fe6c66236f293b0981e2723586ca63fa4db5bb0bef9e7f1e69fc7db9bdb9b1bd42818c119af5876ddab349a778a8b8048d5e5944a3e3294b441b8b90ae13b71c773309c2e16b83174410046d78e9bb4d0a92b2b1940ebaa30d4c96ade3e6acae77c5f1fb6d2ad6f22adad1f56d1daa5b27c34ba152ac792933255a781ae42a9ec0a45dcded9d13b8850542a7385b66587be9cbd153e8d5cfa17045242adc45d30dfa377bd250d4bdfc3fae677e3d79b2bb61f92044c689b6a92ddb2a5ef4accf1cc60d19bfb767b7cbdd64876ebcfab509ff119c382a7d389a0629f6a1da761ca9de306fc93d556f44db9d89559e840384dd76e859e950eb018f7b55273ffd330f41d31b4fdc3b3bd52bdd1d7aedf64c6e442a86cce5571d723dd9c8e7cda7b2b2914f7fd09274a6e1d2b2bf75b43ff5b4fff758f3e3d35c92467aaae42afc8ef24940a45c16d684ff905b169140cdc76eb20ee55f285f8225fdface2cbefd3ab365cea00b501b80c8d1a31ebd49a24aee6a1600f07bfab34f1411ef810ddf44230ba36c898942d1faf3d1fdb3d3e66648b99f428a8d112df055bc293f3193701785a17b480ae4ced8dbc7b229886d43691dafaa6478a6e67b23916c4391cd7d61d50b9ac81fea5dbad39273f3336dcd546214764a201c147d2481e8464783c4133c8eb4a0aea260f417112ace1c0252f98722da4d5b2f6f1aa2f40ff28d769c08230b5f3661f5b7e1fab54172b6ae75b5c9ea961d0286e863a3a81b0ef32342ecd6f038985c69aed7906922cba721fb9299f986b9973d33a964dcfd9568fb3b75e3fde9f19ee8ce00b241fdfcd49ae0a37f7c64451a5b7a3ee41f331a75656148ae790f34c944cc2084a56d1719e49cd5ce4e68755ccf8bd08bad125863c4e3abd4db99fc3449b9c9b497f51b8d5203b7bcfdd6edbf5458f442f912901f1b26a4cdc7bdbadcdcfabcb72d7534ea6d582abe6211a69909e8eeb219e229f7615a6caa05bf93f6b707c869aed95851d7a9fed98742582278f84d8dcaa77e46178a949cf37b5f64751358ffa850aaf280ca73e7790940f1e9b3fac9014ed34dc4f76888ce07f0e3fc0bad4fa3ade83902f146565f4c2bf847f51e4cd11a324f145ab6becadb5504cbc1afdfa08b3f97d8febe815bc7bd139eef3c954ef32c856523888effb3a6d26a1485d95bf5ca0cca0c769efca7908bd1b651f5bbb3f25a2b71c916edc0086a86fc75bdfad107b977d9876aef93cbf39d3dd3e6f8cf6a185f694ce379eceb73d3afbdd5be218dee2eb484b0f30e2fad77e7ddf7f3791b1090343df87f661d077eff1c4d0d9a153f32475097180bb5e35101e95e14109970a3361ac0bbf87888bae45d52a4dcc7a18c26f3e840dafd31c9613a18deb972f98147913a748efd1cb0da1f46556d52db3c2a3c2de21ec3a0d116e1a30e30b0924b513d342fb78e38dedcad1508bc6bf258ae12a84320f2ee26f6020af291ac5b8d5b3132a11c3f1f3bf17693caa1fb6c2d5fe172ea81d4c55fbd2b6de250995711257ce67f4e05228c8a7ab7c37aa38262af175a6e73b147b39dc229db69d4bafef986fe1dad827f7ef2692a632f026b6fd72b64679d5b067975bfd457e7415a21863f32955c6fe6e2624c2be44f6bf4ef2a51ef5d2e361f737dfbd2954063dc770ace8fb8478630b29fdd571983d300af5acaaba6f9a1abee2dec3b6f7f78f5e42d3f59521a66fd36f9c38e6c3db431f95bf1fc2c7f383b3abfd8377872707fb5e4adf86dfb068e58c98d64e532e71c924bffb757b6bf5638d38b9012300065351a0c6d53559769c2466e6c2fad746881a4d2f49ce39f75958d621b90397ddcfd5cf4e7aaf8d0bc3aab91d77576d24ff170000ffff753306f8cb390000", + "a2d5586edb9ff79f53fe610c4e91de3d": "1f8b08000000000000ffbc3bfd531cb9b13fdffc159de55201d7ee2ce0bbcb1d17278501fb5cc1e000be9714e7f26a67b4b33a66a441d280f780f7b7bfea6e693ef8707cf5524955ce8cd4ea6e75b7fa4bdaf3cc5495d4fec30efce5afb07eb6540e94030185d4d20a2f7358a852425d4ae124c85c7970a6b19904a5219d7a59d5a5f0d26d24f750ed96255426570b9509af8c866b55963097501ae7c7b0320d2cc59584b9941aae85d5327f806323595b434e92e4fc0fe7872a93dac90feb4bef6bb7339daaaa48dd52c93277a932d3b9c80b390d5093dd5a644bf9c7edcde7e9e6645e36327557c546b7d8d452f34652638b69c9cbdc94d74d9ea79b1b70fe87f3d766df64ddaac2e426a30585f2cb669e66a69aba4a94a596ce4f0ba9ffe6bcf08d4b6b1da97dd1b20d406ade8a2be53a72fc3dc914ad1d2cc0edfc6d6e85ce962f2ae1bcb41b5fb42eec0a4e646dac873d61f3fef62c0d67c2e6c423cbf449a63fb3923f9f5e9a24674b89ba056f4c09b535799349b4bcbd93f7fbb0be67a5f0720c568a7c0c4d9d0b2f41e81c72594a2f37e0e4e0f40c44ad70e9af32f3104d1116d65468c1ea4a6ac8851773e1640a037a688c4966b4a69506fc52423e873082e6eabc55ba00a145b9fa4d3240c0457cc403423399c925e0540e46d3c8a2148543deae542ef334495eae682f8833975ea8d231a343c473d3f880b16c2ae2a2c97c63e598788f44e9841ac84c550bafe6a50c80e057b54cae955f12122b2f1b65651eb169514937267204e9c6b415a1b5f174485d9a246f3cb8a646ed39382f8cad7a5aeeb4f9abd2bf2d1bd47bb5011ef78a98545597120fb003672a098d13c85c25fdd2e42e85d7ad57e97800a5b3b2c965a40a0b63413765494b997307e7eeb24c8f9ab2fc27afea9b5e297441965e5f14d328cba9bb2ca76bb8e2a531e506180be7456365d110f2f4219e6e730c3745b88d04f785c2949f6a9921eb73e15406f346951e9d606118539a24b342ea19fa4f36852928ed6a52c07c4538ae8dbd00b38053e99770ba94a56ebcff9383f37cbecd1a7c949f08b93d6de1365875fbf3ed53d67ca43a7d8ae6de5255d28a3d934bfb270785f9d5190db5c82e442151d3f8fd28f9feca29c36da44992a077a6d31ad4aa8c4eba08e2041a03f8a046ed85d23207344ec567249dca4f043465d8349fc3e965a9bc7cde3bb7ef1d9e19162dc590c1c95b98b234d708c1724993d96ce62ecb64efe460f7ec00ce765f1e1ec04894f3a672a3643d010038dfc5cf37f9078037476707af0f4ee0ddc99bb7bb27ff82bf1ffc0b76df9f1dbf39da3b39787b70740647c76770f4fef070cc4bcf942fe507fcf3e8e7dd93bd9f764fd6b7bedbdcb80fb66bbd721e49440a438057c727076f5e1f11bdf50e1afddaab839383a3bd835318091a76a30144f2d557c747b07f707870760047c7b0bb77f6e6f8088e8fe0fdbbfdddfe58b281c248d6d6d6d6e0cc0aed16c65678debcc189c22468b840c2880ee426f96a3a3d87cd0f1064045ff83fa5bd2ca41d0ee209da8185289d04a8adaa845ded80b78d0400d178d37e64a6dc7980a3947a07265bfc91cb85684abf03e71f92af98b97d5c013374423ba380fee3855cfd881afcd8aaf04776223b61473fe2ae77825a7e1c01daf30e5bc847958f209fef8c02e8083db837f366b13352da3fdf1e6f8e4dedc7e8485fb42b662cb3ad0f40c6f1a51203d057c2664b61d9823e2bb3f0cd320b1f24b3886320b3adef361fca8c990b712d082d4886a6582e03abfed1a9dfe4ced6779bad983c42b28ccef8cf4e428c7abcd58988a1837cb63f40b4e2ffbc4d3d299fdf6153ccdcc0a8a2e504be9f301d9aed6c27003f349eed9ef1b46b66c91d1d5374afd1b761028261505088c784871dad95ceb7098f72501be728fc53c8dfdf3d86cc36392c1a4d498c1b03ba73580a9d97d2ba3154e24262423f8eeed9497b252d082b415c0945413785bda5cc2e0073110ae36641bef63cebb128f380c27d585f6be3fae494c7daf8f052696157f0463b2fca9263c46c367bb97bfa134e2b1eef12b375b7344d9963a110e6648e09daff4e0b339d2bcd5b00d758d98ea12494c692c2422dfc324dbec6a85c480f93069e4a4189bddc5cebd288bc1507859f36fa245fc335a27924280e704dadb89e721afe30a625a18ae1a0f53055bc4713d6a38263c5f4f9e009b9b21bb863a96132719725dae80b17e2e82f186dbe9a4c30b375dec228ed181bb5b32ded4a280ded306508f1030f44f7c19954fc24bb8c1f68361d7771b43279536216c5d4b94670fe31b8f6ef609ced5430de017f9345e55f388d46d13217643dc985793888d2ed78bd92f6da2a2f494998d3e59145d6d43a8fd5d664d2395649345acc9dec36a80568e33b73456564792782e46bb6d9f84994f85874357146274aa0e4e64ab74bd7d6e07a293594a2d1d9121d7767fe7e29b85638fdc7211a1089a6cba4946bd1069371a2226b01e1e89b99406e6b48d369da330d003c44dd1688e9e35a6a1030b7e6da498ba732d4b748a75c1ae777bedffc7e73eaae4551483b553a979fd2a5af4a5afede493a4dd3acb1e514972a894816d2674bb852e4ec2acc6a4ba565c29eeb51029ccd2588e72908ce9c12f2ac81ba28247e66463b53cae4e6267d2df54fb2acefd80193bb426d2b5d50751acf61387f98d4b62688de590ab7629be14a31a70de0a916eec2a5c9339891b696b2ac6730815239df7959f0c216d2bb168c3021dc20c10d96324bd1cfcc5ae0a01804b70dab171d40b4d3e05aa2299f5e966422f9bc6f13ad7a1dd4a5c8981e3745dc603e39f64b5438330cf2136e042590cbabb85994de4100ef0b2f94c0bd8a20986beb738275ce5a723334529979635729bc8a457244387b1b7430834c683c3d8de31831905bff14535190ce855b268393485a0f7d8110d306be3728fe5ea1417ea1d1394ae449be936710f94c009e218f8ba66cc7487ac163204e8c7daeb3a5c885f4590a6f9c6b24ab7d86dbcc95ab4bb122b3c2185d371ec9a585f2aad0c632c14279e04fa255988834790685492b93339881e0999df44d3d865a3807b3e8af67d4c8200c4e7a4facf674119686340a667def1e85923c839383ddfdb70769c524df85c5568abc92c93310753d65573fc5f8931686e0389580d74ac329cd8e39cd09ee059456be3d7552d34912b59afe854b4e4cb3fe1a7151b7887223d4a93525a643c933c88579141e53a9368b0a368c9ba72c4c6474c65015314f7886a290e5a3b8b8407760656da5939aa428c09aebe045b2657718683d79acb5b55ebb24a455c933387f7d7cf296f8235e5e45263faca753b4cc8fb9301f3156a755be81f0a7ff38fce7bf837797e5a708ff13fa5d82fd29a48d2d28fada08f616f7dbced0eee3d4bb90f6c2be5ca09294d12d604c8909960f5fdbc90be1bef1aa54bf498e51a8fd851595bc36f6620cb4f97c4ee0a8fad3eb609d9d8aa279e4266bd02c38e744c1a9c7db1b85d293c26895e15f2c3244611e0526ec86fe21d0d75fd22043404e161e670005b210a59912d046489d4fb91f2673d80fd6e192bdc65aa97db9ea66c7c904de0aabc4fe4bfc6b75fa8fc36402ef8cf38595fcf15665d638b3f0e87bc3614a26c11127c9bb5268cc2e03ca6402c75664215319720167ab5aba24796b9ceff7f0b07e702d47a491b72b77598e23236e1cfd3eaaeded297ea5a1abd338c9b1b5ae518194759293a40ce79e931779de4272df0d5eaea2071a93cd60c967b5285b384246f990c831cbd26d4227f314de2c228d980d7aa901abaf3c27e31565dc659e735fad71d113a2a7642a2fe4276f458adccf06990c981ab1a46cedadaf0ccbc2828e450ecf834cbfbd65c100935222350be9beb8922f7a00142070303491b5a7666c28e03a3cde60dcea96a5c94b599a6beedca116b1020dabfa521c835b72141ccc180bb3d08798a59474e1aea8d1759370a93d7297e54714e36807460176348e938569e7b88bd04d458fd102cc575ebade522a45da596aee9edec351988fb1a3dcd1090de5004ba0775dbeb89b5f099dc99c94c6761a6f2a389f89e14194caaf50a0a55861e94365a8b9d66d905c185b094f6ab38e2fbdb6834d5092f88e3192eacb9e8eda36fe6c3289a3fbcabe9885c53001bf54ee5e5394b393d63eef214de1acc58f462f156576736a6ff331a75b09da70823939db115b73cfe8209d56ab9efdc059cb4a6b7eb29a4b3a31dd9ed052982589674b17742f43b53b5c53e1ef6a99a9c5eab31ba79228b64a28980659a709ca53386e194f26f293cc5e74750d6931a4c683134a7c531f80c8f6c15d6655cd7906626bbc04e5f936294c2d85eba50474ce2809509a358f1ce37243a2c6514ab2d89d91a083f40466980e936a599a1a8dc51bc81ae74da5c21554af3f64169cdbc2bf4c0319c9ae34a606bfb4a629d872a8e2c0638c0c852b1a7d652e64328bb9c5194ebda274da5880769c86d22421ec4283289d81dad44dd95d7a692f3f79f6ccf3d57dcb2577c83162bea21df77c26adcdfc8bbfb4cefeaf51bb2cdb2e08c41a390680a77920b3a8856542adc96338a576771c4aa653381c88aa134f6d95f6d4f9ea32399ab8125699862cb8ea1c6a0b83e56470198e93b5bbbb04093d90f33a2d3a12951cb74ce2b8a611cee7f7631d110710009784f6ed383895639a84b931e5469f18d3f90f220f531cc2ba52888c192db72d6a43dc6a5cdb35c453d36e344d929b1bb0421712bebe90ab317c7d25ca46c2ce0b48e1ee0ebdf0cd0d6b6101a33fae4db6bfbd1a1128dcdddd9b9c3cdf3c833faee13c2309ffdcdddddc80d439e24bdad23edc936951c5fa5ecc15f96eaa67e9b039e9417437c9947f0cec8f4aa9bee3712d56498948dfcea974e2524a961f99f08b9b9bd1cd4d7a7737babb9b11170143248398f27bc695c2cfd1fada9aa49f168544a1e3dbf0d30bf6a264c2aec996205c779e5143382b6c416932328a901fbd74fe45e3a49d21decce85f03cd4140eaef893cc76c32c1e38a4372364616ae94bc86ebd8a462d0e0e4e76808b76d310200b7400704c80ee116d8f892dbc964d2fe3fb945d136255d76dc723845d8d9cd4d3b31a2e111dcddcd006e93dbba6cacc072e2c1926ee6fe1a1f6e7186f03cfa00d61c9a6bf990a138fe10fe7d5d3f0acfe34fe0df13952cf7b0407c825007f004c5cf61b807f010c3a91617f289c5dddcbd755cc6dc3b78b147e4924edf3b6065a19ce7c0f6913b50681f546322082e7c454e09c9f6ca62468d48929e99cce8908deeee52faef8818825bb8b9193d4269448e059731ba2716b7935f8a023aa37c12590fe68bd13ed4f8d3e81fc2fe0e32f7cde27364eec3fe0e323d03fa1c851ed87f4954e4803ffe9704f6bb89fd7eb1fd3f48ac8395dc234ee19780e89711fc32fa65b481e73d60789c70b7f8332cc4b9118c0825b00b595b8323e3a5e3d6c6653986b76ed057e036105fa1516d25ba665a25bda00494ae18a85f1b03fa6523ed2a3cfbe2a734e18d19c5c4c61b503ab3f496691c6f9901b310046d5f2751fe833901e5e6c656bdb7546932e198e6986c604e1b3d715ee85cd87c8078fde8f8a8bdad0e178416b83adde825043151e0e66ece9df7fd97f0567ac13d9a4343efcc925b1ca6d0baaa29a81e45bee116de05d27f972bfcdcc52dbf895bc6913d7e33762835dcb65d8b9f31c1ba858c5ee7419e97c308fdd8ff93db70c10970bb227656f7ff730bab5b5825b775d4e9bf01d5c96db57297e517a0ac1c7c01205f06ff2cadc36ce427e5303d4e2670b599fe906e6fc3fae69fa79bdf4fb737b73737a85130c1d8a4164ae65098c2a4d4a4808caecdbda1e4eaf5f1bbddb39fe86a70296c8eb55a9e86c5efc9d6f270ed0dd25a63310df540558f753e8ee9cc34da4b2bf3b074972aeacc94c686f49dbbc8083e00994cb49904b8ba7d51a08de6c5ea373430ceb2e246b778a37f1e6cf444d622bb189454ed83ccab2031dd5473aa6de944a42dc2cdc710be529f640e56d20d0a6f5369b0a6f1d2a685497d559701b4a90b4b2dbbf69127cb962f30602bddfa26d2dafae1315a5114d74ae7585b534aee0dd09d2fd597a15add3b397c05118a7a0252e3217263aedbaf15e7cb2b7e2a5196d068f5299cd3c35783252d4bdfc3fae677d3e79b8f6c3f644398b9b765b3b8162b6ebfa0c150759ff3bd427ca6d74a76ebcf8fa13e910b81955dafe5425d0d2aeabc81b9f45e5ae0b7b99de8dbbab82fb36033ded0fd62611615196730b9f6a2ab65e83b6268fb87077ba5c26aa85dde6426ca2ba5b3a5d4c5a701e9d60de4f3c1a350a5253762bcaaa4f3a2aafd6f2dfd6f99fef3017d7a53939552e8a60e4d31de49a8898a42bad087e305b13b160cdcf50b3ec92af9427c91af6f1ee38bf7c9aa0db7577cf265193a526ad12baa495ced8bc8010ef9a936c407859a37188fae94a0fb914c9465c7c773e6637bc0c7826c312b19057594e20368477872b990d1adcc9b8216d0ddb0bb2c3fdd134c4b6a9b486d7d332045d750d9122bff1cde36ce1f505fc000fd4bd778e83d952ea656fac66ae4a8efd5a2cf642159194fd002f2a62e15b5cdc7a02509d64a90a52c84f61da43365c3817928407e7dec0d60e59bba65bb8f2ddec763aa8bad03cfbd3c666a1c348a9ba1d65520cced94d6a5f1369058e820ba816720c962cce2148512a7a52973693bc7b2c99c6d0d387bc9fa617f66a5b74a5e21f9f840b094baf04b36260a9f831df50f1a07d7463b556899432e335589122650899a8ef3a234a20d1b3f3cc60cef45d1d53531c438e9f4b67d8d1c66c6e6d2ce868bc2f50dd9d96be977bbf6367a247a724d9916cbaa3571f6b65b9b9f5797937ea09ccce82ba9dbf8481aa437f2668ca788f3cbc2d619f45b1c0f3a399fa1e606f56f8fde675b437d89e0c92321b6cf077af2b0b232a4e7cbc6f051d4edaf17940ecf45aca4867e9014078fcd1f1e9114ed345cc4f6884ce07fdebc83f5d2988b78e143be5055b53557fce4ff4991b7478cb2e127adaeb5b7ce4231c36cf5cb11e65e1a16bd02bb1793e33eef4d0d6ebd5c5d2a0ff12163af9fa634a9abe65b14ca0cee655cbdbbf5310caece39b6f67f33458f5622ddb8010c51df4eb7be7b44ec7df661debbcf647e7361fa0ded18ed43aff03e9d6f98ceb7033afbfdebf018dee23350472f4de2fae7bc7ee8bfdbc8d886813137dc390cf235059e183a3b746aeea52e210e483f287bc2eb393c28e1f684f35f7e791b175da8ba539a5a0c30841fb728179ee179ac9b42bf9a975f8952e56d9c22bd472f37868aebc9ba5f4f86d7938343d8771a2a5ca960c6171248ea9ba685e178c3c6f6d1d35087861f4dc57015421983abf8631fc81b8a46316e0dec846ae170fcf88731ad47e561a77cc33fe541ed60aa3a94b66397a47426495cb95cd0cb52a5219f3fe6bb51c5315189cf5099ef50d5e6708d74babe353d3314dcab76f142801f88246d65c026b6fd74b64679d57860975bc3453cfa18a21863f339b500f8122a24c2dc0be09f61714d4b9706f1b0f315ff600a9541ef4ebc28863e215e4d43a8ff3a873900a3502feabaff78abe52bee3d6c7b7ffff029347d5f1962fa36fd984b623ebc3de6a8fcfd18de9f1e9c7cdc3f78f5e6e8609fa5f46df8b18ed1deaa79e30de512e7a2949f7eddde7afc554a9cdc80098080b92a50e3fa822c3b4e12334be5f85915a246d34b925329390bcb7a2477e0bcfff9f8fb9ac1b3eac28a7ae9a6fd551bc9ff050000ffffc183681cb43a0000", "a42f6cfa87833f9ac66f4293e399925f": "1f8b08000000000000ffbc55df6fdb36107eb6fe8a9b50acf6a0c859d7270f0196a60ddaadedbcdad9060c43c1506799ad4c7247aa4ec6f27f1f48298e65589e3b74cd4b94e3fdf8bebbfb2ece15b8101221655abcad75c12ce6a5caed4a57a9f7c9780c57d1e85c3eb35473fb9aadd0fbd60a0c8c90658540c81515b020b502e7f239bbaeb075b5e11b8404bbc4f0f6945976cdccdd73d1fe196afd30ab572b46b79bf4f22e71088f79bac963d053349c84b642c9ff0bd79c9506767a101fce39476d01de1925a3614aaaa839b616e788c912e1c1426055c0e40c1a082fe442e517aac0cb6037de3b0762d1bae55312a10b3fe1ed39954db1989a115b0138d7eb07de836676b9e533fbe5e52ba6b590653e5bb3b2449adfeae868a94648ef3d2f5455afe42bb42c6f73a5cea12c02b8f82be980e8eec3b52a6e8371a50aaca68cbf6765dbc87cd7b5a9db0e6af7b19957da2e03e7680c3c3a3d05a7aedf21b7feb81a31fc9289aa2684c73be14c8b6ef0f3f97cfa8c48d14ed8e34f097ba36a8b04e30e12f80856bd546ba4d0c4cfb50a0e9c3be9df8113efc17727077f6866f9f2cf8014f952c143e7e6eac7d9cfafb741bc90c632c9114ebd7f081f6169ad86e9d51cd2f035198f9d7b901ba40f48cf95b1de4fee0d53453640fb02ec370b7bc9de63102df81dba29c0ef27e75a9c5c19a4496d90be7df45db2a825df7fcd86ebc8357f83462b69f03712162903826f5afb5f351a9b8136d191e2acf328053302970cb8bd099c841456b04afc8d174a5abcb1431a1d7f0392c3dcc1fb241938d7df9b0c902814d8e3148b4c1999308da13659907e7faa74940cc422e6fbea0ca4a802cb01a1ad49c6a51f727b93c13a038a55479bd764108874ee4640ddb31701edd74769daf90da2c91910b222ecef9032e84d3efafe4802cee50553ddf2cf889eb0a29d71875d0200f7487aabe74f70a10867ec030e779140fcf9cf6800a081d15f7c4aa819e1707434dc5f59258238863d37b691cee767b2096f696d4df90e522bc02635c5d5ddfe579e66c743fe94353eb0b719bc6dd476b697e4fe33136a859c47de03f8d77bb04fe8f7d7604785fd64f669fdc054639f0060cba7e9d63adccda8ca3bef032537572249fe090000ffffb63231ca860a0000", "abfb948144ce2666cf818384c00cc754": "1f8b08000000000000ff84924d6bdb401086effb2b5ee24b0c967a2f6d21d8b49796b46e028510a2b176b45ebada11da954d1af2dfcb4af2471c83afa3679e7967b40fa5d435fbf8f8119fbee0fa6e6d036c00c1b0e796226b54d6311ac71418ac6d4490ae2d19d623ff10b96e1c450e5375a2ba710eb5685bd992a2158fad750e2b8693106778960e6bda3056cc1e5b6a3deb778ea9529309e6cbfb051637b7f8daf932a9822a0cfb6230ee824293a0da11b015e29a5164d90ec8344991966b2804d688825e93e36ecd2845334af22961d98528b5fdc71a5b1bd73b9126f9dc3b2a4726b5078efd374f35438681294543e55f329c2b353fb21e2e6a3de2569266235d1b66f8fdebfb1fac9ea1b9a2ce4590d7f876bbfc7118df8f4ccb485b174aa97de4d16ac5cf4eee71b84525adcaf0b0e4d85ade586fd07229ad0e83bf2163bd79bc9e8c00673fc9b0ce9603343dea651042c365faaba3e4b86fa8f40df39653083a5043e598b96ff40933548e99053b7ecb0c953d935ec83e5d1f1c637055148511f5f2b27ba4b8d2244fe9844f862339971bc963ddb82be4afaf097f6b1b465cd09c778ceb5f3690d6e70de3712e1bba1e3c2f19af7759a27bf0bde47f000000ffffa7724c4920040000", "ac60daf3c3958d476b98234112b3896c": "1f8b08000000000000ffcc5a7b53e33812ffdbfe14bdaebd2d7bca38c070d4547653750c0c4cae76598ec7de555114232c396871249f2cc330b97cf7ab9664c7491cc8bca89d3f8658ea6ef5af5f564b2e487a47460c26938414fcc43e1d93319b4e7d9f8f0ba93484be17a45268f65107be1730914acac5a8f76729050e646333ce658fcb4af31c1f04d3bd5bad0bfc5d6a954a718f3f351f33fc5b899264f8eb1a8211d7b7d54d92ca71af245a2ade1bc9a4aa380d7cdf0b2693841279f8af93e3e934b0cf6349595e8ff85e5bc0888b8d91143cc55fc1fcdc9f55ce9928d3db31a75639252bcd54e047be7f4f14843e00c0350c00d54cce582a05855e0f9c1ddaa3995450893b211f0454255a900b2005f7bd5455f49da085e442973026c565a91517a3ab57fbaaa27b27435caed703f7049495a9e237ac04c5fe5bb1529740ee09cfc94dcecc321a7f95285fdf32a044931b52325f3f16ac11526a55a51a26be87be83d63fbb786be003baad1f083266c107dfdb578c687671faeb33f4a9a1bbae548e5ca74c2bceeed9efc2b2aee2528eee5a8a25dedf887844e66779c7443cd6cc17055d4bddcad0d55c072c67eb70514357731d329dde1e1cfc5af3ade2ca90ee9ad2bc663c478f0d45261dddab3a68e7f22b99913941c6d3d75c6432f8e04f7d13262764c4e8292bab5c6384d8bf18160519b1128e98decbf37a22b15131c7330b0d1c6e74e742efeecce34089a83ed29df14fec29baeb927f32c4074493b650a63292b2c9b43129d124f86032eb5c6a929fb2542a8ae1ac17eda871fe5a59026b815e0fde9f9f9fbc534a2a601fc9b8c85de4cf866700f725654e8d76e44aca829ab91fec6c6ea2debfb1d2a4ad73aaa31ddbd11679a989ae4ab821b4cecf996ff6a5c8f8e8d4541148cd43a518606949de134173a6c0d6183fab443a471f46f37413dfb3a4d01fc0ac3825c7ec218c7c6f3251448c18fc6862040328861f1199899ffe00125d4753399d5a5d26938622393346b281e714b00b44c635930913743aad75488ede9d87418fd2bcd7276a343c08628cb4039a47cb24cd5c53f59088e94a891afd9cbd8eb85832d9888b0e4b35944e57244b8666a88cd0625f6295232ed6348cb78655f6a5b867ea7de3af7379c445e86cd56daca75866266c6cd832de321b3c2852b4c3c5861368696ce582ebb0126963d78eb5b36509d122bf0950eb549414a6f00a29f6edbec078c3c39768411419976d812766c4f7bceb9c09744ace4498bae1c8f73c9e81991a0c60d3c8f19c9001089efb9e370596976c612a0c5f5d6ec12fbfc0d6e6d5e26a51683718c989342529fca95eef72f32a8aa2cb3e2e7885a27ddff3b2304dfeadb8662a863439b5691e3b2891ef4d8d0fac05b9e09a939c7f620e7aa8e095c964c7174198ea8fe0364c7306e219b8c7612345c10f06a641878c830e9a10a3b165054ba76ae1a1d1b1764faa3f1a7d8dba7f909ce39bd029d7a55a0c0b0862bbe570a53106926a2e054c263f76bdc5f6cc6c04cc14638bd209728bcb398c4ecb4512d42c06e5d6ae1735c01a64180d53dfd6ff457e13a33632bf2f44bb575c42d8a58f5375d99f3365d70b1ebb6647ec748bf69b68558cd0a1588a5117db0dfc7bfb9a8f20347f638bd4c46c8119ab9243a9c67f90bc62a1e18c8c9b0b4cd92068bbf53eb639dbf29adbfe6302960c952962d8da8c617727426f1a3d1f30fbfe79f6fb71b7f71ec0695f165294acced5fbf686c3688bbb8d18ae51677ca127bf1155de923cbc8f7cef2179cf08c5376f72c6741818e9426f9c3f162c8821204591f394a0ab4d6bf333a4b7a8b21e543adb7813748920e92ddb40414a62690f84dc4871cc121b3d43d46901e9a97c28f7b28ca59ad1700538d5a2a9ddf304c236f95f062c869ff1ea52fc2db8ae291e375566a20ff1d96e32396584eee579a892b7923edac8438ae59ac2949a8b3c63a00b31762632b2efa35971b4646617f95971b78406d599a58cdb32f6079bbe573e709dde1a8289efa5a434ad362572bec2bc53ea58ea435909daf7bd5a82dd082667e6e92da16ebda7e55c08ac6ce7d205069affab459a66ea90f09c7db57a435132a5bf8d2cdbd67d1b596f09b53b8475045196912ad7eb904e7dcfeee99b860503163b95beed299121f6bdba21e963ac243626a3d886f31913368d1ecc1b92e18b9f32fc11d5bbc363f630df249900af474d74b7f76bb15b18b370317cbf525ddc9c24465b47dca8e9b2aec03a73c1857e13161d1bc518eed8a37b3345105648d87e21717aa68d864599bc7d44078677cc9405da548ea5578e61b2af9d374f5510b35ac86914d7c564c5cc7401cbd6eeba60b676bf259aaddde7e06cedaec4d39e5a04f47a7b5d40afb7bf25a0d7dbcf017abdbd12507b6a11d0eeceba80e637405f0b08b7394f03dadd5909a83dd50664b651cfa3a9b3fb45a06c6c2d41e086bf5bffb5b2ff4593bf1bc08aa41fae9bf32f9cf2dd205665fa70dd447fe13cef46b12abd87eb66f7374feebf7f7646d065f5cf8c7aebe85ff76b6b0068d633badaceb955102f86072fb0a0fdd7ebb90342e02510d3f79a6e5b4b1831ed3a712e3269ceb5493360ee3b2693e4c05d79d8cddaec06a4d7837f9c55e331518fb8c0170b829b4730e77946e2391995d01ccd9ba1e1416bfec0dcd71406c17783b597a6acd0603a183370a224ad52d61e311dbc550c0aa26fcdb1b756158380d3c059274d5959c2f6e6264ce4cd9f2cd5d3aeabbea4be9a4226dc4f578ac1ce734ccd1671816d674d36085a6d4f0cf406ecd9bfb117a720a4860ce760c3b56a25d4e4667f6ad69a519920b5c0dd01b339ab9d18134de172c4f415ce62d04380fff77bbd5ca624bf95a5eebfd97cb369183e3e7e0ae03f1b7b05dfb82899ea5725535bdbaf6dfa5897af6cda97ce593a72cce411eec8b1c75d3e4e8c7cdfb35e9dcbb2c01e39e3ac2b38fd41d7f19e6911027bd4dc7def54df6b453f77d7ada66588a16e3854d4ccd61d367a2a0679876accdd795e1a45af8c9a3fc8bba70467636d7b872c0c2ad3b762f6645c509b2d7df85b19c436c62358d461eed0c88a345ab96ea3293bb3dbd8ce442590f35283cc80d21c5843fcd42decfa55a9fc1ef23b6ad472597a79d86b54ad2faa48ad6c5e3b8b9fcbe0c63adf3b95ff02c9ba9c2873093b3baf4308a1c534f715c300c6e48e851d1f3320c27ba2408f0b683e70b0378ad07137d75cc72d5ccec174ea7b2863003f39290811b9fa104c263321d36910fbdeecb3853e04bd7a7ee1420ffe075afe2a1f98724cf35f2d7c09a7fb66e173589b2f163e87a9f960e173985adf2b209b79f72d590ee3418f8bd9c707b1f9e265c5cdc711d30d61b8e88768214c2e1709ae608081e1cf6e52b130ff3f0000ffffcdc4073773240000", @@ -60,7 +60,7 @@ var _ = func() error { g.DefaultResolver = hgr func() { - b := packr.New("gen", "./template") + b := packr.New("gen", "../template") b.SetResolver("GEN_README.md.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "a2d5586edb9ff79f53fe610c4e91de3d"}) b.SetResolver("Makefile.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "3ceb52e1f1f3624e5a1a43ca87b692d5"}) b.SetResolver("README.md.tmpl", packr.Pointer{ForwardBox: gk, ForwardPath: "b90aee21f6dfc810704f9344330644a8"}) diff --git a/main-packr.go b/readme/main-packr.go similarity index 100% rename from main-packr.go rename to readme/main-packr.go diff --git a/readme/main.go b/readme/main.go index 2ae8368..55860e2 100644 --- a/readme/main.go +++ b/readme/main.go @@ -32,7 +32,7 @@ func init() { goopt.Description = func() string { return "ORM and RESTful meta data viewer for SQl databases" } - goopt.Version = "v0.9.21 (07/07/2020)" + goopt.Version = "v0.9.22 (07/08/2020)" goopt.Summary = `dbmeta [-v] --sqltype=mysql --connstr "user:password@/dbname" --database sqltype - sql database type such as [ mysql, mssql, postgres, sqlite, etc. ] diff --git a/template/GEN_README.md.tmpl b/template/GEN_README.md.tmpl index 1cf33a3..1637b1a 100644 --- a/template/GEN_README.md.tmpl +++ b/template/GEN_README.md.tmpl @@ -249,6 +249,11 @@ Table Name: registration_source |ms sql |y | y | y | y | y | y| n ## Version History +- v0.9.22 (07/08/2020) + - Modified gogo.proto check to use GOPATH not hardcoded. + - Updated gen to error exit on first error encountered + - Added color output for error + - Added --no-color option for non colorized output - v0.9.21 (07/07/2020) - Repacking templates, update version number in info. - v0.9.20 (07/07/2020)