From 31767f75e6dbe4005e4007d81603975da08d6840 Mon Sep 17 00:00:00 2001 From: Felipe Martin <812088+fmartingr@users.noreply.github.com> Date: Sat, 27 Apr 2024 07:46:36 +0200 Subject: [PATCH] feat: new migrations system (#876) * feat: new migration system * use newFuncMigration * database version -> database schema version * column name * use path instead of filepath for goembed * simplified migrations, added backwards compatible migrations --- go.mod | 19 +- go.sum | 168 +----------------- internal/cmd/root.go | 2 +- internal/database/database.go | 15 +- internal/database/migrations.go | 97 ++++++++++ .../mysql/0000_system_create.up.sql | 3 + .../mysql/0000_system_insert.up.sql | 1 + ...ial.up.sql => 0001_initial_account.up.sql} | 1 + .../migrations/mysql/0002_initial.up.sql | 14 -- .../mysql/0002_initial_bookmark.up.sql | 15 ++ ...initial.up.sql => 0003_initial_tag.up.sql} | 0 ...p.sql => 0004_initial_bookmark_tag.up.sql} | 0 .../migrations/mysql/0005_config.down.sql | 1 - .../migrations/mysql/0005_config.up.sql | 2 - .../migrations/postgres/0000_system.up.sql | 5 + .../migrations/postgres/0001_initial.up.sql | 24 +-- .../migrations/postgres/0002_config.down.sql | 1 - .../migrations/postgres/0002_config.up.sql | 2 - .../migrations/sqlite/0000_system.up.sql | 5 + .../migrations/sqlite/0001_initial.up.sql | 2 + .../sqlite/0002_denormalize_content.down.sql | 1 - .../sqlite/0002_denormalize_content.up.sql | 3 - .../migrations/sqlite/0003_config.down.sql | 1 - .../migrations/sqlite/0003_config.up.sql | 3 - internal/database/mysql.go | 96 ++++++++-- internal/database/mysql_test.go | 4 +- internal/database/pg.go | 97 +++++++--- internal/database/pg_test.go | 5 +- internal/database/sqlite.go | 93 ++++++++-- internal/database/sqlite_test.go | 4 +- internal/domains/bookmarks_test.go | 2 +- internal/testutil/shiori.go | 2 +- main.go | 5 - 33 files changed, 392 insertions(+), 301 deletions(-) create mode 100644 internal/database/migrations.go create mode 100644 internal/database/migrations/mysql/0000_system_create.up.sql create mode 100644 internal/database/migrations/mysql/0000_system_insert.up.sql rename internal/database/migrations/mysql/{0001_initial.up.sql => 0001_initial_account.up.sql} (86%) delete mode 100644 internal/database/migrations/mysql/0002_initial.up.sql create mode 100644 internal/database/migrations/mysql/0002_initial_bookmark.up.sql rename internal/database/migrations/mysql/{0003_initial.up.sql => 0003_initial_tag.up.sql} (100%) rename internal/database/migrations/mysql/{0004_initial.up.sql => 0004_initial_bookmark_tag.up.sql} (100%) delete mode 100644 internal/database/migrations/mysql/0005_config.down.sql delete mode 100644 internal/database/migrations/mysql/0005_config.up.sql create mode 100644 internal/database/migrations/postgres/0000_system.up.sql delete mode 100644 internal/database/migrations/postgres/0002_config.down.sql delete mode 100644 internal/database/migrations/postgres/0002_config.up.sql create mode 100644 internal/database/migrations/sqlite/0000_system.up.sql delete mode 100644 internal/database/migrations/sqlite/0002_denormalize_content.down.sql delete mode 100644 internal/database/migrations/sqlite/0003_config.down.sql delete mode 100644 internal/database/migrations/sqlite/0003_config.up.sql diff --git a/go.mod b/go.mod index 18fe50803..f245c1059 100644 --- a/go.mod +++ b/go.mod @@ -5,6 +5,7 @@ go 1.22.2 require ( github.com/PuerkitoBio/goquery v1.9.1 + github.com/blang/semver v3.5.1+incompatible github.com/disintegration/imaging v1.6.2 github.com/fatih/color v1.16.0 github.com/gin-contrib/requestid v1.0.0 @@ -16,7 +17,6 @@ require ( github.com/go-sql-driver/mysql v1.8.1 github.com/gofrs/uuid/v5 v5.1.0 github.com/golang-jwt/jwt/v5 v5.2.1 - github.com/golang-migrate/migrate/v4 v4.17.0 github.com/jmoiron/sqlx v1.3.5 github.com/julienschmidt/httprouter v1.3.0 github.com/lib/pq v1.10.9 @@ -28,6 +28,7 @@ require ( github.com/sirupsen/logrus v1.9.3 github.com/spf13/afero v1.11.0 github.com/spf13/cobra v1.8.0 + github.com/spf13/pflag v1.0.5 github.com/stretchr/testify v1.9.0 github.com/swaggo/files v1.0.1 github.com/swaggo/gin-swagger v1.6.0 @@ -62,15 +63,11 @@ require ( github.com/goccy/go-json v0.10.2 // indirect github.com/gogs/chardet v0.0.0-20211120154057-b7413eaefb8f // indirect github.com/google/uuid v1.6.0 // indirect - github.com/hashicorp/errwrap v1.1.0 // indirect - github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect github.com/klauspost/cpuid/v2 v2.2.7 // indirect - github.com/knz/go-libedit v1.10.1 // indirect github.com/leodido/go-urn v1.4.0 // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect @@ -83,33 +80,21 @@ require ( github.com/pmezard/go-difflib v1.0.0 // indirect github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect github.com/shurcooL/httpfs v0.0.0-20230704072500-f1e31cf0ba5c // indirect - github.com/spf13/pflag v1.0.5 // indirect github.com/tdewolff/parse v2.3.4+incompatible // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/ugorji/go/codec v1.2.12 // indirect github.com/vincent-petithory/dataurl v1.0.0 // indirect go.etcd.io/bbolt v1.3.9 // indirect - go.uber.org/atomic v1.11.0 // indirect golang.org/x/arch v0.7.0 // indirect - golang.org/x/mod v0.17.0 // indirect - golang.org/x/sync v0.7.0 // indirect golang.org/x/sys v0.19.0 // indirect golang.org/x/text v0.14.0 // indirect golang.org/x/tools v0.20.0 // indirect google.golang.org/protobuf v1.33.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - lukechampine.com/uint128 v1.3.0 // indirect - modernc.org/cc/v3 v3.41.0 // indirect - modernc.org/cc/v4 v4.20.0 // indirect - modernc.org/ccgo/v3 v3.17.0 // indirect - modernc.org/ccgo/v4 v4.16.0 // indirect - modernc.org/gc/v2 v2.4.1 // indirect modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6 // indirect modernc.org/libc v1.49.3 // indirect modernc.org/mathutil v1.6.0 // indirect modernc.org/memory v1.8.0 // indirect - modernc.org/opt v0.1.3 // indirect - modernc.org/sortutil v1.2.0 // indirect modernc.org/strutil v1.2.0 // indirect modernc.org/token v1.1.0 // indirect ) diff --git a/go.sum b/go.sum index 3b0f68854..9e1de685c 100644 --- a/go.sum +++ b/go.sum @@ -1,22 +1,15 @@ filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= -github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0= -github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc= github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE= -github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= -github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= -github.com/PuerkitoBio/goquery v1.8.1 h1:uQxhNlArOIdbrH1tr0UXwdVFgDcZDrZVdcpygAcwmWM= -github.com/PuerkitoBio/goquery v1.8.1/go.mod h1:Q8ICL1kNUJ2sXGoAhPGUdYDJvgQgHzJsnnd3H7Ho5jQ= github.com/PuerkitoBio/goquery v1.9.1 h1:mTL6XjbJTZdpfL+Gwl5U2h1l9yEkJjhmlTeV9VPW7UI= github.com/PuerkitoBio/goquery v1.9.1/go.mod h1:cW1n6TmIMDoORQU5IU/P1T3tGFunOeXEpGP2WHRwkbY= -github.com/andybalholm/cascadia v1.3.1/go.mod h1:R4bJ1UQfqADjvDa4P6HZHLh/3OxWWEqc0Sk8XGwHqvA= github.com/andybalholm/cascadia v1.3.2 h1:3Xi6Dw5lHF15JtdcmAHD3i1+T8plmv7BQ/nsViSLyss= github.com/andybalholm/cascadia v1.3.2/go.mod h1:7gtRlve5FxPPgIgX36uWBX58OdBsSS6lUvCFb+h7KvU= +github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ= +github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM= github.com/bytedance/sonic v1.10.0-rc/go.mod h1:ElCzW+ufi8qKqNW0FY314xriJhyJhuoJ3gFZdAHF7NM= -github.com/bytedance/sonic v1.10.2 h1:GQebETVBxYB7JGWJtLBi07OVzWwt+8dWA00gEVW2ZFE= -github.com/bytedance/sonic v1.10.2/go.mod h1:iZcSUejdk5aukTND/Eu/ivjQuEL0Cu9/rf50Hi0u/g4= github.com/bytedance/sonic v1.11.3 h1:jRN+yEjakWh8aK5FzrciUHG8OFXK+4/KrAX/ysEtHAA= github.com/bytedance/sonic v1.11.3/go.mod h1:iZcSUejdk5aukTND/Eu/ivjQuEL0Cu9/rf50Hi0u/g4= github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY= @@ -27,22 +20,11 @@ github.com/chenzhuoyu/iasm v0.9.0/go.mod h1:Xjy2NpN3h7aUqeqM+woSuuvxmIe6+DDsiNLI github.com/chenzhuoyu/iasm v0.9.1 h1:tUHQJXo3NhBqw6s33wkGn9SP3bvrWLdlVIJ3hQBL7P0= github.com/chenzhuoyu/iasm v0.9.1/go.mod h1:Xjy2NpN3h7aUqeqM+woSuuvxmIe6+DDsiNLIrkAmYog= github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= 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/dhui/dktest v0.4.0 h1:z05UmuXZHO/bgj/ds2bGMBu8FI4WA+Ag/m3ghL+om7M= -github.com/dhui/dktest v0.4.0/go.mod h1:v/Dbz1LgCBOi2Uki2nUqLBGa83hWBGFMu5MrgMDCc78= github.com/disintegration/imaging v1.6.2 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1ei82L+c= github.com/disintegration/imaging v1.6.2/go.mod h1:44/5580QXChDfwIclfc/PCwrr44amcmDAg8hxG0Ewe4= -github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8= -github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= -github.com/docker/docker v24.0.7+incompatible h1:Wo6l37AuwP3JaMnZa226lzVXGA3F9Ig1seQen0cKYlM= -github.com/docker/docker v24.0.7+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= -github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= -github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= -github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= @@ -51,51 +33,28 @@ github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uq github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= github.com/gin-contrib/gzip v0.0.6 h1:NjcunTcGAj5CO1gn4N8jHOSIeRFHIbn51z6K+xaN4d4= github.com/gin-contrib/gzip v0.0.6/go.mod h1:QOJlmV2xmayAjkNS2Y8NQsMneuRShOU/kjovCXNuzzk= -github.com/gin-contrib/requestid v0.0.6 h1:mGcxTnHQ45F6QU5HQRgQUDsAfHprD3P7g2uZ4cSZo9o= -github.com/gin-contrib/requestid v0.0.6/go.mod h1:9i4vKATX/CdggbkY252dPVasgVucy/ggBeELXuQztm4= github.com/gin-contrib/requestid v1.0.0 h1:Ms19AcktabHdXDiMDvsR+PrkBEOtURWliX89n9b0VHY= github.com/gin-contrib/requestid v1.0.0/go.mod h1:311ycyAmroVeV6hDO1Wojooq/jmWfrgqU33M1ncP/TI= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= -github.com/gin-contrib/static v0.0.1 h1:JVxuvHPuUfkoul12N7dtQw7KRn/pSMq7Ue1Va9Swm1U= -github.com/gin-contrib/static v0.0.1/go.mod h1:CSxeF+wep05e0kCOsqWdAWbSszmc31zTIbD8TvWl7Hs= github.com/gin-contrib/static v1.1.1 h1:XEvBd4DDLG1HBlyPBQU1XO8NlTpw6mgdqcPteetYA5k= github.com/gin-contrib/static v1.1.1/go.mod h1:yRGmar7+JYvbMLRPIi4H5TVVSBwULfT9vetnVD0IO74= -github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M= -github.com/gin-gonic/gin v1.8.1/go.mod h1:ji8BvRH1azfM+SYow9zQ6SZMvR8qOMZHmsCuWR9tTTk= github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg= github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU= -github.com/go-openapi/jsonpointer v0.20.2 h1:mQc3nmndL8ZBzStEo3JYF8wzmeWffDH4VbXz58sAx6Q= -github.com/go-openapi/jsonpointer v0.20.2/go.mod h1:bHen+N0u1KEO3YlmqOjTT9Adn1RfD91Ar825/PuiRVs= github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ= github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY= -github.com/go-openapi/jsonreference v0.20.4 h1:bKlDxQxQJgwpUSgOENiMPzCTBVuc7vTdXSSgNeAhojU= -github.com/go-openapi/jsonreference v0.20.4/go.mod h1:5pZJyJP2MnYCpoeoMAql78cCHauHj0V9Lhc506VOpw4= github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ= github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4= -github.com/go-openapi/spec v0.20.14 h1:7CBlRnw+mtjFGlPDRZmAMnq35cRzI91xj03HVyUi/Do= -github.com/go-openapi/spec v0.20.14/go.mod h1:8EOhTpBoFiask8rrgwbLC3zmJfz4zsCUueRuPM6GNkw= github.com/go-openapi/spec v0.21.0 h1:LTVzPc3p/RzRnkQqLRndbAzjY0d0BCL72A6j3CdL9ZY= github.com/go-openapi/spec v0.21.0/go.mod h1:78u6VdPw81XU44qEWGhtr982gJ5BWg2c0I5XwVMotYk= -github.com/go-openapi/swag v0.22.9 h1:XX2DssF+mQKM2DHsbgZK74y/zj4mo9I99+89xUmuZCE= -github.com/go-openapi/swag v0.22.9/go.mod h1:3/OXnFfnMAwBD099SwYRk7GD3xOrr1iL7d/XNLXVVwE= github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE= github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ= -github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= -github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= -github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs= github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= -github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= -github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA= github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= -github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI= -github.com/go-playground/validator/v10 v10.10.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos= -github.com/go-playground/validator/v10 v10.17.0 h1:SmVVlfAOtlZncTxRuinDPomC2DkXJ4E5T9gDA0AIH74= -github.com/go-playground/validator/v10 v10.17.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= github.com/go-playground/validator/v10 v10.19.0 h1:ol+5Fu+cSq9JD7SoSqe04GMI92cbn0+wvQ3bZ8b/AU4= github.com/go-playground/validator/v10 v10.19.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= github.com/go-shiori/dom v0.0.0-20190930082056-9d974a4f8b25/go.mod h1:360KoNl36ftFYhjLHuEty78kWUGw8i1opEicvIDLfRk= @@ -108,43 +67,23 @@ github.com/go-shiori/go-readability v0.0.0-20240204090920-819593fddc6b/go.mod h1 github.com/go-shiori/warc v0.0.0-20200621032813-359908319d1d h1:+SEf4hYDaAt2eyq8Xu3YyWCpnMsK8sZfbYsDRFCUgBM= github.com/go-shiori/warc v0.0.0-20200621032813-359908319d1d/go.mod h1:uaK5DAxFig7atOzy+aqLzhs6qJacMDfs8NxHV5+shzc= github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= -github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI= -github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y= github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg= -github.com/goccy/go-json v0.9.7/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= -github.com/gofrs/uuid/v5 v5.0.0 h1:p544++a97kEL+svbcFbCQVM9KFu0Yo25UoISXGNNH9M= -github.com/gofrs/uuid/v5 v5.0.0/go.mod h1:CDOjlDMVAtN56jqyRUZh58JT31Tiw7/oQyEXZV+9bD8= github.com/gofrs/uuid/v5 v5.1.0 h1:S5rqVKIigghZTCBKPCw0Y+bXkn26K3TB5mvQq2Ix8dk= github.com/gofrs/uuid/v5 v5.1.0/go.mod h1:CDOjlDMVAtN56jqyRUZh58JT31Tiw7/oQyEXZV+9bD8= -github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= -github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/gogs/chardet v0.0.0-20211120154057-b7413eaefb8f h1:3BSP1Tbs2djlpprl7wCLuiqMaUh5SJkkzI2gDs+FgLs= github.com/gogs/chardet v0.0.0-20211120154057-b7413eaefb8f/go.mod h1:Pcatq5tYkCW2Q6yrR2VRHlbHpZ/R4/7qyL1TCF7vl14= -github.com/golang-jwt/jwt/v5 v5.2.0 h1:d/ix8ftRUorsN+5eMIlF4T6J8CAt9rch3My2winC1Jw= -github.com/golang-jwt/jwt/v5 v5.2.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk= github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= -github.com/golang-migrate/migrate/v4 v4.17.0 h1:rd40H3QXU0AA4IoLllFcEAEo9dYKRHYND2gB4p7xcaU= -github.com/golang-migrate/migrate/v4 v4.17.0/go.mod h1:+Cp2mtLP4/aXDTKb9wmXYitdrNx2HGs45rbWAo6OsKM= -github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ= github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo= -github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= -github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= -github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= -github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= @@ -153,33 +92,20 @@ github.com/jmoiron/sqlx v1.3.5 h1:vFFPA71p1o5gAeqtEAwLU4dnX2napprKtHr7PYIcN3g= github.com/jmoiron/sqlx v1.3.5/go.mod h1:nRVWtLre0KfCLJvgxzCsLVMogSvQ1zNJtpYr2Ccp0mQ= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= -github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= -github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs= -github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= -github.com/klauspost/cpuid/v2 v2.2.6 h1:ndNyv040zDGIDh8thGkXYjnFtiN02M1PVVF+JE/48xc= -github.com/klauspost/cpuid/v2 v2.2.6/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM= github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= -github.com/knz/go-libedit v1.10.1 h1:0pHpWtx9vcvC0xGZqEQlQdfSQs7WRlAjuPvk3fOZDCo= github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= -github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY= github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= @@ -189,58 +115,38 @@ github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0 github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= -github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= -github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y= -github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU= +github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= -github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= -github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/muesli/go-app-paths v0.2.2 h1:NqG4EEZwNIhBq/pREgfBmgDmt3h1Smr1MjZiXbpZUnI= github.com/muesli/go-app-paths v0.2.2/go.mod h1:SxS3Umca63pcFcLtbjVb+J0oD7cl4ixQWoBKhGEtEho= github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4= github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls= -github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= -github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= -github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM= -github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc= github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= -github.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo= -github.com/pelletier/go-toml/v2 v2.1.1 h1:LWAJwfNvjQZCFIDKWYQaM62NcYeYViCmWIwmOStowAI= -github.com/pelletier/go-toml/v2 v2.1.1/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= github.com/pelletier/go-toml/v2 v2.2.1 h1:9TA9+T8+8CUCO2+WYnDLCgrYi9+omqKXyjDtosvtEhg= github.com/pelletier/go-toml/v2 v2.2.1/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= -github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= -github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= -github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= -github.com/sethvargo/go-envconfig v1.0.0 h1:1C66wzy4QrROf5ew4KdVw942CQDa55qmlYmw9FZxZdU= -github.com/sethvargo/go-envconfig v1.0.0/go.mod h1:Lzc75ghUn5ucmcRGIdGQ33DKJrcjk4kihFYgSTBmjIc= github.com/sethvargo/go-envconfig v1.0.1 h1:9wglip/5fUfaH0lQecLM8AyOClMw0gT0A9K2c2wozao= github.com/sethvargo/go-envconfig v1.0.1/go.mod h1:OKZ02xFaD3MvWBBmEW45fQr08sJEsonGrrOdicvQmQA= github.com/shurcooL/httpfs v0.0.0-20230704072500-f1e31cf0ba5c h1:aqg5Vm5dwtvL+YgDpBcK1ITf3o96N/K7/wsRXQnUTEs= @@ -263,13 +169,10 @@ github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpE github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= @@ -287,30 +190,19 @@ github.com/toorop/gin-logrus v0.0.0-20210225092905-2c785434f26f h1:oqdnd6OGlOUu1 github.com/toorop/gin-logrus v0.0.0-20210225092905-2c785434f26f/go.mod h1:X3Dd1SB8Gt1V968NTzpKFjMM6O8ccta2NPC6MprOxZQ= github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= -github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= -github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M= -github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= -github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY= github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE= github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= github.com/vincent-petithory/dataurl v1.0.0 h1:cXw+kPto8NLuJtlMsI152irrVw9fRDX8AbShPRpg2CI= github.com/vincent-petithory/dataurl v1.0.0/go.mod h1:FHafX5vmDzyP+1CQATJn7WFKc9CvnvxyvZy6I1MrG/U= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= -go.etcd.io/bbolt v1.3.8 h1:xs88BrvEv273UsB79e0hcVrlUWmS0a8upikMFhSyAtA= -go.etcd.io/bbolt v1.3.8/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw= go.etcd.io/bbolt v1.3.9 h1:8x7aARPEXiXbHmtUwAIv7eV2fQFHrLLavdiJ3uzJXoI= go.etcd.io/bbolt v1.3.9/go.mod h1:zaO32+Ti0PK1ivdPtgMESzuzL2VPoIG1PCQNvOdo/dE= -go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= -go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= golang.org/x/arch v0.7.0 h1:pskyeJh/3AmoQ8CPE95vxHLqp1G1GfGNXTmcl9NEKTc= golang.org/x/arch v0.7.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc= -golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= @@ -318,38 +210,27 @@ golang.org/x/image v0.15.0 h1:kOELfmgrmJlw4Cdb7g/QGuB3CvDrXbqEIww/pNtNBm8= golang.org/x/image v0.15.0/go.mod h1:HUYqC05R2ZcZ3ejNQsIHQDQiwWM4JBqmm6MKANTp4LE= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.15.0 h1:SernR4v+D55NyBH2QiEQrlBAnj1ECL6AGrA5+dPaMY8= -golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190926025831-c00fd9afed17/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210916014120-12bc252f5db8/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= -golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= -golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= -golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190927073244-c990c680b611/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -357,22 +238,16 @@ golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= -golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= -golang.org/x/term v0.16.0 h1:m+B6fahuftsE9qjo0VWp2FW0mB3MTJvR0BaMQrq0pmE= -golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= golang.org/x/term v0.19.0 h1:+ThwsDv+tYfnJFhF4L8jITxu1tdTWRTZpdsWgEgjL6Q= golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= 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.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= @@ -382,75 +257,42 @@ golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGm golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc= -golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps= golang.org/x/tools v0.20.0 h1:hz/CVckiOxybQvFw6h7b/q80NTr9IUQb4s1IIzW7KNY= golang.org/x/tools v0.20.0/go.mod h1:WvitBU7JJf6A4jOdg4S1tviW9bhUxkgeCui/0JHctQg= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= -google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -lukechampine.com/uint128 v1.3.0 h1:cDdUVfRwDUDovz610ABgFD17nXD4/uDgVHl2sC3+sbo= -lukechampine.com/uint128 v1.3.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= -modernc.org/cc/v3 v3.41.0 h1:QoR1Sn3YWlmA1T4vLaKZfawdVtSiGx8H+cEojbC7v1Q= -modernc.org/cc/v3 v3.41.0/go.mod h1:Ni4zjJYJ04CDOhG7dn640WGfwBzfE0ecX8TyMB0Fv0Y= modernc.org/cc/v4 v4.20.0 h1:45Or8mQfbUqJOG9WaxvlFYOAQO0lQ5RvqBcFCXngjxk= modernc.org/cc/v4 v4.20.0/go.mod h1:HM7VJTZbUCR3rV8EYBi9wxnJ0ZBRiGE5OeGXNA0IsLQ= -modernc.org/ccgo/v3 v3.16.15 h1:KbDR3ZAVU+wiLyMESPtbtE/Add4elztFyfsWoNTgxS0= -modernc.org/ccgo/v3 v3.16.15/go.mod h1:yT7B+/E2m43tmMOT51GMoM98/MtHIcQQSleGnddkUNI= -modernc.org/ccgo/v3 v3.17.0 h1:o3OmOqx4/OFnl4Vm3G8Bgmqxnvxnh0nbxeT5p/dWChA= -modernc.org/ccgo/v3 v3.17.0/go.mod h1:Sg3fwVpmLvCUTaqEUjiBDAvshIaKDB0RXaf+zgqFu8I= modernc.org/ccgo/v4 v4.16.0 h1:ofwORa6vx2FMm0916/CkZjpFPSR70VwTjUCe2Eg5BnA= modernc.org/ccgo/v4 v4.16.0/go.mod h1:dkNyWIjFrVIZ68DTo36vHK+6/ShBn4ysU61So6PIqCI= -modernc.org/ccorpus v1.11.6 h1:J16RXiiqiCgua6+ZvQot4yUuUy8zxgqbqEEUuGPlISk= -modernc.org/ccorpus v1.11.6/go.mod h1:2gEUTrWqdpH2pXsmTM1ZkjeSrUWDpjMu2T6m29L/ErQ= +modernc.org/fileutil v1.3.0 h1:gQ5SIzK3H9kdfai/5x41oQiKValumqNTDXMvKo62HvE= +modernc.org/fileutil v1.3.0/go.mod h1:XatxS8fZi3pS8/hKG2GH/ArUogfxjpEKs3Ku3aK4JyQ= modernc.org/gc/v2 v2.4.1 h1:9cNzOqPyMJBvrUipmynX0ZohMhcxPtMccYgGOJdOiBw= modernc.org/gc/v2 v2.4.1/go.mod h1:wzN5dK1AzVGoH6XOzc3YZ+ey/jPgYHLuVckd62P0GYU= modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6 h1:5D53IMaUuA5InSeMu9eJtlQXS2NxAhyWQvkKEgXZhHI= modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6/go.mod h1:Qz0X07sNOR1jWYCrJMEnbW/X55x206Q7Vt4mz6/wHp4= -modernc.org/httpfs v1.0.6 h1:AAgIpFZRXuYnkjftxTAZwMIiwEqAfk8aVB2/oA6nAeM= -modernc.org/httpfs v1.0.6/go.mod h1:7dosgurJGp0sPaRanU53W4xZYKh14wfzX420oZADeHM= -modernc.org/libc v1.41.0 h1:g9YAc6BkKlgORsUWj+JwqoB1wU3o4DE3bM3yvA3k+Gk= -modernc.org/libc v1.41.0/go.mod h1:w0eszPsiXoOnoMJgrXjglgLuDy/bt5RR4y3QzUUeodY= modernc.org/libc v1.49.3 h1:j2MRCRdwJI2ls/sGbeSk0t2bypOG/uvPZUsGQFDulqg= modernc.org/libc v1.49.3/go.mod h1:yMZuGkn7pXbKfoT/M35gFJOAEdSKdxL0q64sF7KqCDo= modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4= modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo= -modernc.org/memory v1.7.2 h1:Klh90S215mmH8c9gO98QxQFsY+W451E8AnzjoE2ee1E= -modernc.org/memory v1.7.2/go.mod h1:NO4NVCQy0N7ln+T9ngWqOQfi7ley4vpwvARR+Hjw95E= modernc.org/memory v1.8.0 h1:IqGTL6eFMaDZZhEWwcREgeMXYwmW83LYW8cROZYkg+E= modernc.org/memory v1.8.0/go.mod h1:XPZ936zp5OMKGWPqbD3JShgd/ZoQ7899TUuQqxY+peU= modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4= modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= modernc.org/sortutil v1.2.0 h1:jQiD3PfS2REGJNzNCMMaLSp/wdMNieTbKX920Cqdgqc= modernc.org/sortutil v1.2.0/go.mod h1:TKU2s7kJMf1AE84OoiGppNHJwvB753OYfNl2WRb++Ss= -modernc.org/sqlite v1.28.0 h1:Zx+LyDDmXczNnEQdvPuEfcFVA2ZPyaD7UCZDjef3BHQ= -modernc.org/sqlite v1.28.0/go.mod h1:Qxpazz0zH8Z1xCFyi5GSL3FzbtZ3fvbjmywNogldEW0= modernc.org/sqlite v1.29.6 h1:0lOXGrycJPptfHDuohfYgNqoe4hu+gYuN/pKgY5XjS4= modernc.org/sqlite v1.29.6/go.mod h1:S02dvcmm7TnTRvGhv8IGYyLnIt7AS2KPaB1F/71p75U= modernc.org/strutil v1.2.0 h1:agBi9dp1I+eOnxXeiZawM8F4LawKv4NzGWSaLfyeNZA= modernc.org/strutil v1.2.0/go.mod h1:/mdcBmfOibveCTBxUl5B5l6W+TTH1FXPLHZE6bTosX0= -modernc.org/tcl v1.15.2 h1:C4ybAYCGJw968e+Me18oW55kD/FexcHbqH2xak1ROSY= -modernc.org/tcl v1.15.2/go.mod h1:3+k/ZaEbKrC8ePv8zJWPtBSW0V7Gg9g8rkmhI1Kfs3c= modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y= modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= -modernc.org/z v1.7.3 h1:zDJf6iHjrnB+WRD88stbXokugjyc0/pB91ri1gO6LZY= -modernc.org/z v1.7.3/go.mod h1:Ipv4tsdxZRbQyLq9Q1M6gdbkxYzdlrciF2Hi/lS7nWE= nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50= rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= diff --git a/internal/cmd/root.go b/internal/cmd/root.go index 720cd913b..7060eef89 100644 --- a/internal/cmd/root.go +++ b/internal/cmd/root.go @@ -91,7 +91,7 @@ func initShiori(ctx context.Context, cmd *cobra.Command) (*config.Config, *depen } // Migrate - if err := db.Migrate(); err != nil { + if err := db.Migrate(ctx); err != nil { logger.WithError(err).Fatalf("Error running migration") } diff --git a/internal/database/database.go b/internal/database/database.go index d79c56ca0..c9322c4d7 100644 --- a/internal/database/database.go +++ b/internal/database/database.go @@ -2,7 +2,6 @@ package database import ( "context" - "embed" "fmt" "log" "net/url" @@ -13,9 +12,6 @@ import ( "github.com/pkg/errors" ) -//go:embed migrations/* -var migrations embed.FS - // OrderMethod is the order method for getting bookmarks type OrderMethod int @@ -68,8 +64,17 @@ func Connect(ctx context.Context, dbURL string) (DB, error) { // DB is interface for accessing and manipulating data in database. type DB interface { + // DBx is the underlying sqlx.DB + DBx() sqlx.DB + // Migrate runs migrations for this database - Migrate() error + Migrate(ctx context.Context) error + + // GetDatabaseSchemaVersion gets the version of the database + GetDatabaseSchemaVersion(ctx context.Context) (string, error) + + // SetDatabaseSchemaVersion sets the version of the database + SetDatabaseSchemaVersion(ctx context.Context, version string) error // SaveBookmarks saves bookmarks data to database. SaveBookmarks(ctx context.Context, create bool, bookmarks ...model.BookmarkDTO) ([]model.BookmarkDTO, error) diff --git a/internal/database/migrations.go b/internal/database/migrations.go new file mode 100644 index 000000000..dc4208491 --- /dev/null +++ b/internal/database/migrations.go @@ -0,0 +1,97 @@ +package database + +import ( + "context" + "database/sql" + "embed" + "fmt" + "path" + + "github.com/blang/semver" +) + +//go:embed migrations/* +var migrationFiles embed.FS + +type migration struct { + fromVersion semver.Version + toVersion semver.Version + migrationFunc func(db *sql.DB) error +} + +// txFunc is a function that runs in a transaction. +type txFn func(tx *sql.Tx) error + +// runInTransaction runs the given function in a transaction. +func runInTransaction(db *sql.DB, fn txFn) error { + tx, err := db.Begin() + if err != nil { + return fmt.Errorf("failed to start transaction: %w", err) + } + defer tx.Rollback() + + if err := fn(tx); err != nil { + return fmt.Errorf("failed to run transaction: %w", err) + } + + if err := tx.Commit(); err != nil { + return fmt.Errorf("failed to commit transaction: %w", err) + } + + return nil +} + +// newFuncMigration creates a new migration from a function. +func newFuncMigration(fromVersion, toVersion string, migrationFunc func(db *sql.DB) error) migration { + return migration{ + fromVersion: semver.MustParse(fromVersion), + toVersion: semver.MustParse(toVersion), + migrationFunc: migrationFunc, + } +} + +// newFileMigration creates a new migration from a file. +func newFileMigration(fromVersion, toVersion, filename string) migration { + return newFuncMigration(fromVersion, toVersion, func(db *sql.DB) error { + return runInTransaction(db, func(tx *sql.Tx) error { + migrationSQL, err := migrationFiles.ReadFile(path.Join("migrations", filename+".up.sql")) + if err != nil { + return fmt.Errorf("failed to read migration file: %w", err) + } + + if _, err := tx.Exec(string(migrationSQL)); err != nil { + return fmt.Errorf("failed to execute migration %s to %s: %w", fromVersion, toVersion, err) + } + return nil + }) + }) +} + +// runMigrations runs the given migrations. +func runMigrations(ctx context.Context, db DB, migrations []migration) error { + currentVersion := semver.Version{} + + // Get current database version + dbVersion, err := db.GetDatabaseSchemaVersion(ctx) + if err == nil && dbVersion != "" { + currentVersion = semver.MustParse(dbVersion) + } + + for _, migration := range migrations { + if !currentVersion.EQ(migration.fromVersion) { + continue + } + + if err := migration.migrationFunc(db.DBx().DB); err != nil { + return fmt.Errorf("failed to run migration from %s to %s: %w", migration.fromVersion, migration.toVersion, err) + } + + currentVersion = migration.toVersion + + if err := db.SetDatabaseSchemaVersion(ctx, currentVersion.String()); err != nil { + return fmt.Errorf("failed to store database version %s from %s to %s: %w", currentVersion.String(), migration.fromVersion, migration.toVersion, err) + } + } + + return nil +} diff --git a/internal/database/migrations/mysql/0000_system_create.up.sql b/internal/database/migrations/mysql/0000_system_create.up.sql new file mode 100644 index 000000000..a2b23e857 --- /dev/null +++ b/internal/database/migrations/mysql/0000_system_create.up.sql @@ -0,0 +1,3 @@ +CREATE TABLE IF NOT EXISTS shiori_system( + database_schema_version VARCHAR(12) NOT NULL DEFAULT '0.0.0' +); diff --git a/internal/database/migrations/mysql/0000_system_insert.up.sql b/internal/database/migrations/mysql/0000_system_insert.up.sql new file mode 100644 index 000000000..15087bb41 --- /dev/null +++ b/internal/database/migrations/mysql/0000_system_insert.up.sql @@ -0,0 +1 @@ +INSERT INTO shiori_system(database_schema_version) VALUES('0.0.0'); diff --git a/internal/database/migrations/mysql/0001_initial.up.sql b/internal/database/migrations/mysql/0001_initial_account.up.sql similarity index 86% rename from internal/database/migrations/mysql/0001_initial.up.sql rename to internal/database/migrations/mysql/0001_initial_account.up.sql index 97f5de2b7..e4c996a94 100644 --- a/internal/database/migrations/mysql/0001_initial.up.sql +++ b/internal/database/migrations/mysql/0001_initial_account.up.sql @@ -3,6 +3,7 @@ CREATE TABLE IF NOT EXISTS account( username VARCHAR(250) NOT NULL, password BINARY(80) NOT NULL, owner TINYINT(1) NOT NULL DEFAULT '0', + config JSON NOT NULL DEFAULT '{}', PRIMARY KEY (id), UNIQUE KEY account_username_UNIQUE (username)) CHARACTER SET utf8mb4; diff --git a/internal/database/migrations/mysql/0002_initial.up.sql b/internal/database/migrations/mysql/0002_initial.up.sql deleted file mode 100644 index 36a3481c7..000000000 --- a/internal/database/migrations/mysql/0002_initial.up.sql +++ /dev/null @@ -1,14 +0,0 @@ -CREATE TABLE IF NOT EXISTS bookmark( - id INT(11) NOT NULL AUTO_INCREMENT, - url TEXT NOT NULL, - title TEXT NOT NULL, - excerpt TEXT NOT NULL DEFAULT (''), - author TEXT NOT NULL DEFAULT (''), - public BOOLEAN NOT NULL DEFAULT 0, - content MEDIUMTEXT NOT NULL DEFAULT (''), - html MEDIUMTEXT NOT NULL DEFAULT (''), - modified TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - PRIMARY KEY(id), - UNIQUE KEY bookmark_url_UNIQUE (url(255)), - FULLTEXT (title, excerpt, content)) - CHARACTER SET utf8mb4; \ No newline at end of file diff --git a/internal/database/migrations/mysql/0002_initial_bookmark.up.sql b/internal/database/migrations/mysql/0002_initial_bookmark.up.sql new file mode 100644 index 000000000..5b8e3abb8 --- /dev/null +++ b/internal/database/migrations/mysql/0002_initial_bookmark.up.sql @@ -0,0 +1,15 @@ +CREATE TABLE IF NOT EXISTS bookmark( + id INT(11) NOT NULL AUTO_INCREMENT, + url TEXT NOT NULL, + title TEXT NOT NULL, + excerpt TEXT NOT NULL DEFAULT (''), + author TEXT NOT NULL DEFAULT (''), + public BOOLEAN NOT NULL DEFAULT 0, + content MEDIUMTEXT NOT NULL DEFAULT (''), + html MEDIUMTEXT NOT NULL DEFAULT (''), + modified TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + has_content BOOLEAN NOT NULL DEFAULT 0, + PRIMARY KEY(id), + UNIQUE KEY bookmark_url_UNIQUE (url(255)), + FULLTEXT (title, excerpt, content)) + CHARACTER SET utf8mb4; diff --git a/internal/database/migrations/mysql/0003_initial.up.sql b/internal/database/migrations/mysql/0003_initial_tag.up.sql similarity index 100% rename from internal/database/migrations/mysql/0003_initial.up.sql rename to internal/database/migrations/mysql/0003_initial_tag.up.sql diff --git a/internal/database/migrations/mysql/0004_initial.up.sql b/internal/database/migrations/mysql/0004_initial_bookmark_tag.up.sql similarity index 100% rename from internal/database/migrations/mysql/0004_initial.up.sql rename to internal/database/migrations/mysql/0004_initial_bookmark_tag.up.sql diff --git a/internal/database/migrations/mysql/0005_config.down.sql b/internal/database/migrations/mysql/0005_config.down.sql deleted file mode 100644 index a4ff9bce2..000000000 --- a/internal/database/migrations/mysql/0005_config.down.sql +++ /dev/null @@ -1 +0,0 @@ -ALTER TABLE account DROP COLUMN config; diff --git a/internal/database/migrations/mysql/0005_config.up.sql b/internal/database/migrations/mysql/0005_config.up.sql deleted file mode 100644 index e322304f4..000000000 --- a/internal/database/migrations/mysql/0005_config.up.sql +++ /dev/null @@ -1,2 +0,0 @@ -ALTER TABLE account - ADD COLUMN config JSON NOT NULL DEFAULT '{}'; diff --git a/internal/database/migrations/postgres/0000_system.up.sql b/internal/database/migrations/postgres/0000_system.up.sql new file mode 100644 index 000000000..74e0993b0 --- /dev/null +++ b/internal/database/migrations/postgres/0000_system.up.sql @@ -0,0 +1,5 @@ +CREATE TABLE IF NOT EXISTS shiori_system( + database_schema_version TEXT NOT NULL DEFAULT '0.0.0' +); + +INSERT INTO shiori_system(database_schema_version) VALUES('0.0.0'); diff --git a/internal/database/migrations/postgres/0001_initial.up.sql b/internal/database/migrations/postgres/0001_initial.up.sql index 3b2ed91be..c2872c488 100644 --- a/internal/database/migrations/postgres/0001_initial.up.sql +++ b/internal/database/migrations/postgres/0001_initial.up.sql @@ -1,21 +1,23 @@ CREATE TABLE IF NOT EXISTS account( id SERIAL, username VARCHAR(250) NOT NULL, - password BYTEA NOT NULL, - owner BOOLEAN NOT NULL DEFAULT FALSE, + password BYTEA NOT NULL, + owner BOOLEAN NOT NULL DEFAULT FALSE, + config JSONB NOT NULL DEFAULT '{}', PRIMARY KEY (id), CONSTRAINT account_username_UNIQUE UNIQUE (username)); CREATE TABLE IF NOT EXISTS bookmark( - id SERIAL, - url TEXT NOT NULL, - title TEXT NOT NULL, - excerpt TEXT NOT NULL DEFAULT '', - author TEXT NOT NULL DEFAULT '', - public SMALLINT NOT NULL DEFAULT 0, - content TEXT NOT NULL DEFAULT '', - html TEXT NOT NULL DEFAULT '', - modified TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP, + id SERIAL, + url TEXT NOT NULL, + title TEXT NOT NULL, + excerpt TEXT NOT NULL DEFAULT '', + author TEXT NOT NULL DEFAULT '', + public SMALLINT NOT NULL DEFAULT 0, + content TEXT NOT NULL DEFAULT '', + html TEXT NOT NULL DEFAULT '', + modified TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP, + has_content BOOLEAN NOT NULL DEFAULT FALSE, PRIMARY KEY(id), CONSTRAINT bookmark_url_UNIQUE UNIQUE (url)); diff --git a/internal/database/migrations/postgres/0002_config.down.sql b/internal/database/migrations/postgres/0002_config.down.sql deleted file mode 100644 index a4ff9bce2..000000000 --- a/internal/database/migrations/postgres/0002_config.down.sql +++ /dev/null @@ -1 +0,0 @@ -ALTER TABLE account DROP COLUMN config; diff --git a/internal/database/migrations/postgres/0002_config.up.sql b/internal/database/migrations/postgres/0002_config.up.sql deleted file mode 100644 index ecdc017da..000000000 --- a/internal/database/migrations/postgres/0002_config.up.sql +++ /dev/null @@ -1,2 +0,0 @@ -ALTER TABLE account - ADD COLUMN config JSONB NOT NULL DEFAULT '{}'; diff --git a/internal/database/migrations/sqlite/0000_system.up.sql b/internal/database/migrations/sqlite/0000_system.up.sql new file mode 100644 index 000000000..74e0993b0 --- /dev/null +++ b/internal/database/migrations/sqlite/0000_system.up.sql @@ -0,0 +1,5 @@ +CREATE TABLE IF NOT EXISTS shiori_system( + database_schema_version TEXT NOT NULL DEFAULT '0.0.0' +); + +INSERT INTO shiori_system(database_schema_version) VALUES('0.0.0'); diff --git a/internal/database/migrations/sqlite/0001_initial.up.sql b/internal/database/migrations/sqlite/0001_initial.up.sql index 94a176ffe..469d5e06a 100644 --- a/internal/database/migrations/sqlite/0001_initial.up.sql +++ b/internal/database/migrations/sqlite/0001_initial.up.sql @@ -3,6 +3,7 @@ CREATE TABLE IF NOT EXISTS account( username TEXT NOT NULL, password TEXT NOT NULL, owner INTEGER NOT NULL DEFAULT 0, + config JSON NOT NULL DEFAULT '{}', CONSTRAINT account_PK PRIMARY KEY(id), CONSTRAINT account_username_UNIQUE UNIQUE(username) ); @@ -15,6 +16,7 @@ CREATE TABLE IF NOT EXISTS bookmark( author TEXT NOT NULL DEFAULT "", public INTEGER NOT NULL DEFAULT 0, modified TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP, + has_content BOOLEAN DEFAULT FALSE NOT NULL, CONSTRAINT bookmark_PK PRIMARY KEY(id), CONSTRAINT bookmark_url_UNIQUE UNIQUE(url) ); diff --git a/internal/database/migrations/sqlite/0002_denormalize_content.down.sql b/internal/database/migrations/sqlite/0002_denormalize_content.down.sql deleted file mode 100644 index 69e5c5a06..000000000 --- a/internal/database/migrations/sqlite/0002_denormalize_content.down.sql +++ /dev/null @@ -1 +0,0 @@ -ALTER TABLE bookmark DROP COLUMN has_content; diff --git a/internal/database/migrations/sqlite/0002_denormalize_content.up.sql b/internal/database/migrations/sqlite/0002_denormalize_content.up.sql index 456864c54..c7417895c 100644 --- a/internal/database/migrations/sqlite/0002_denormalize_content.up.sql +++ b/internal/database/migrations/sqlite/0002_denormalize_content.up.sql @@ -1,6 +1,3 @@ -ALTER TABLE bookmark - ADD has_content BOOLEAN DEFAULT FALSE NOT NULL; - UPDATE bookmark SET has_content = bc.has_content FROM (SELECT docid, content <> '' AS has_content FROM bookmark_content) AS bc WHERE bookmark.id = bc.docid; diff --git a/internal/database/migrations/sqlite/0003_config.down.sql b/internal/database/migrations/sqlite/0003_config.down.sql deleted file mode 100644 index a4ff9bce2..000000000 --- a/internal/database/migrations/sqlite/0003_config.down.sql +++ /dev/null @@ -1 +0,0 @@ -ALTER TABLE account DROP COLUMN config; diff --git a/internal/database/migrations/sqlite/0003_config.up.sql b/internal/database/migrations/sqlite/0003_config.up.sql deleted file mode 100644 index 324465fe7..000000000 --- a/internal/database/migrations/sqlite/0003_config.up.sql +++ /dev/null @@ -1,3 +0,0 @@ -ALTER TABLE account - ADD config JSON NOT NULL DEFAULT '{}'; - diff --git a/internal/database/mysql.go b/internal/database/mysql.go index ad561e43b..7465efd67 100644 --- a/internal/database/mysql.go +++ b/internal/database/mysql.go @@ -3,18 +3,66 @@ package database import ( "context" "database/sql" + "fmt" "strings" "time" "github.com/go-shiori/shiori/internal/model" - "github.com/golang-migrate/migrate/v4" - "github.com/golang-migrate/migrate/v4/database/mysql" - "github.com/golang-migrate/migrate/v4/source/iofs" "github.com/jmoiron/sqlx" "github.com/pkg/errors" "golang.org/x/crypto/bcrypt" + + _ "github.com/go-sql-driver/mysql" ) +var mysqlMigrations = []migration{ + newFileMigration("0.0.0", "0.1.0", "mysql/0000_system_create"), + newFileMigration("0.1.0", "0.2.0", "mysql/0000_system_insert"), + newFileMigration("0.2.0", "0.3.0", "mysql/0001_initial_account"), + newFileMigration("0.3.0", "0.4.0", "mysql/0002_initial_bookmark"), + newFileMigration("0.4.0", "0.5.0", "mysql/0003_initial_tag"), + newFileMigration("0.5.0", "0.6.0", "mysql/0004_initial_bookmark_tag"), + newFuncMigration("0.6.0", "0.7.0", func(db *sql.DB) error { + // Ensure that bookmark table has `has_content` column and account table has `config` column + // for users upgrading from <1.5.4 directly into this version. + tx, err := db.Begin() + if err != nil { + return fmt.Errorf("failed to start transaction: %w", err) + } + defer tx.Rollback() + + _, err = tx.Exec(`ALTER TABLE bookmark ADD COLUMN has_content BOOLEAN DEFAULT 0`) + if strings.Contains(err.Error(), `Duplicate column name`) { + tx.Rollback() + } else if err != nil { + return fmt.Errorf("failed to add has_content column to bookmark table: %w", err) + } else if err == nil { + if errCommit := tx.Commit(); errCommit != nil { + return fmt.Errorf("failed to commit transaction: %w", errCommit) + } + } + + tx, err = db.Begin() + if err != nil { + return fmt.Errorf("failed to start transaction: %w", err) + } + defer tx.Rollback() + + _, err = tx.Exec(`ALTER TABLE account ADD COLUMN config JSON NOT NULL DEFAULT '{}'`) + if strings.Contains(err.Error(), `Duplicate column name`) { + tx.Rollback() + } else if err != nil { + return fmt.Errorf("failed to add config column to account table: %w", err) + } else if err == nil { + if errCommit := tx.Commit(); errCommit != nil { + return fmt.Errorf("failed to commit transaction: %w", errCommit) + } + } + + return nil + }), +} + // MySQLDatabase is implementation of Database interface // for connecting to MySQL or MariaDB database. type MySQLDatabase struct { @@ -36,33 +84,43 @@ func OpenMySQLDatabase(ctx context.Context, connString string) (mysqlDB *MySQLDa return mysqlDB, err } +// DBX returns the underlying sqlx.DB object +func (db *MySQLDatabase) DBx() sqlx.DB { + return db.DB +} + // Migrate runs migrations for this database engine -func (db *MySQLDatabase) Migrate() error { - sourceDriver, err := iofs.New(migrations, "migrations/mysql") - if err != nil { +func (db *MySQLDatabase) Migrate(ctx context.Context) error { + if err := runMigrations(ctx, db, mysqlMigrations); err != nil { return errors.WithStack(err) } - dbDriver, err := mysql.WithInstance(db.DB.DB, &mysql.Config{}) + return nil +} + +// GetDatabaseSchemaVersion fetches the current migrations version of the database +func (db *MySQLDatabase) GetDatabaseSchemaVersion(ctx context.Context) (string, error) { + var version string + + err := db.GetContext(ctx, &version, "SELECT database_schema_version FROM shiori_system") if err != nil { - return errors.WithStack(err) + return "", errors.WithStack(err) } - migration, err := migrate.NewWithInstance( - "iofs", - sourceDriver, - "mysql", - dbDriver, - ) + return version, nil +} + +// SetDatabaseSchemaVersion sets the current migrations version of the database +func (db *MySQLDatabase) SetDatabaseSchemaVersion(ctx context.Context, version string) error { + tx := db.MustBegin() + defer tx.Rollback() + + _, err := tx.Exec("UPDATE shiori_system SET database_schema_version = ?", version) if err != nil { return errors.WithStack(err) } - if err := migration.Up(); err != nil && !errors.Is(err, migrate.ErrNoChange) { - return err - } - - return nil + return tx.Commit() } // SaveBookmarks saves new or updated bookmarks to database. diff --git a/internal/database/mysql_test.go b/internal/database/mysql_test.go index 9ff2f2fe5..5ee4e3587 100644 --- a/internal/database/mysql_test.go +++ b/internal/database/mysql_test.go @@ -9,9 +9,7 @@ import ( "os" "testing" - "github.com/golang-migrate/migrate/v4" "github.com/jmoiron/sqlx" - "github.com/pkg/errors" ) func init() { @@ -51,7 +49,7 @@ func mysqlTestDatabaseFactory(_ *testing.T, ctx context.Context) (DB, error) { return nil, err } - if err = db.Migrate(); err != nil && !errors.Is(migrate.ErrNoChange, err) { + if err = db.Migrate(context.TODO()); err != nil { return nil, err } diff --git a/internal/database/pg.go b/internal/database/pg.go index 0a36929bf..115976daf 100644 --- a/internal/database/pg.go +++ b/internal/database/pg.go @@ -8,14 +8,57 @@ import ( "time" "github.com/go-shiori/shiori/internal/model" - "github.com/golang-migrate/migrate/v4" - "github.com/golang-migrate/migrate/v4/database/postgres" - "github.com/golang-migrate/migrate/v4/source/iofs" "github.com/jmoiron/sqlx" "github.com/pkg/errors" "golang.org/x/crypto/bcrypt" + + _ "github.com/lib/pq" ) +var postgresMigrations = []migration{ + newFileMigration("0.0.0", "0.1.0", "postgres/0000_system"), + newFileMigration("0.1.0", "0.2.0", "postgres/0001_initial"), + newFuncMigration("0.2.0", "0.3.0", func(db *sql.DB) error { + // Ensure that bookmark table has `has_content` column and account table has `config` column + // for users upgrading from <1.5.4 directly into this version. + tx, err := db.Begin() + if err != nil { + return fmt.Errorf("failed to start transaction: %w", err) + } + defer tx.Rollback() + + _, err = tx.Exec(`ALTER TABLE bookmark ADD COLUMN has_content BOOLEAN DEFAULT FALSE NOT NULL`) + if strings.Contains(err.Error(), `column "has_content" of relation "bookmark" already exists`) { + tx.Rollback() + } else if err != nil { + return fmt.Errorf("failed to add has_content column to bookmark table: %w", err) + } else if err == nil { + if errCommit := tx.Commit(); errCommit != nil { + return fmt.Errorf("failed to commit transaction: %w", errCommit) + } + } + + tx, err = db.Begin() + if err != nil { + return fmt.Errorf("failed to start transaction: %w", err) + } + defer tx.Rollback() + + _, err = tx.Exec(`ALTER TABLE account ADD COLUMN config JSONB NOT NULL DEFAULT '{}'`) + if strings.Contains(err.Error(), `column "config" of relation "account" already exists`) { + tx.Rollback() + } else if err != nil { + return fmt.Errorf("failed to add config column to account table: %w", err) + } else if err == nil { + if errCommit := tx.Commit(); errCommit != nil { + return fmt.Errorf("failed to commit transaction: %w", errCommit) + } + } + + return nil + }), +} + // PGDatabase is implementation of Database interface // for connecting to PostgreSQL database. type PGDatabase struct { @@ -37,33 +80,45 @@ func OpenPGDatabase(ctx context.Context, connString string) (pgDB *PGDatabase, e return pgDB, err } +// DBX returns the underlying sqlx.DB object +func (db *PGDatabase) DBx() sqlx.DB { + return db.DB +} + // Migrate runs migrations for this database engine -func (db *PGDatabase) Migrate() error { - sourceDriver, err := iofs.New(migrations, "migrations/postgres") - if err != nil { +func (db *PGDatabase) Migrate(ctx context.Context) error { + if err := runMigrations(ctx, db, postgresMigrations); err != nil { return errors.WithStack(err) } - dbDriver, err := postgres.WithInstance(db.DB.DB, &postgres.Config{}) - if err != nil { - return errors.WithStack(err) - } + return nil +} + +// GetDatabaseSchemaVersion fetches the current migrations version of the database +func (db *PGDatabase) GetDatabaseSchemaVersion(ctx context.Context) (string, error) { + var version string - migration, err := migrate.NewWithInstance( - "iofs", - sourceDriver, - "postgres", - dbDriver, - ) + err := db.GetContext(ctx, &version, "SELECT database_schema_version FROM shiori_system") if err != nil { - return errors.WithStack(err) + return "", errors.WithStack(err) } - if err := migration.Up(); err != nil && !errors.Is(err, migrate.ErrNoChange) { - return err - } + return version, nil +} - return nil +// SetDatabaseSchemaVersion sets the current migrations version of the database +func (db *PGDatabase) SetDatabaseSchemaVersion(ctx context.Context, version string) error { + tx := db.MustBegin() + defer tx.Rollback() + + return db.withTx(ctx, func(tx *sqlx.Tx) error { + _, err := tx.Exec("UPDATE shiori_system SET database_schema_version = $1", version) + if err != nil { + return errors.WithStack(err) + } + + return tx.Commit() + }) } // SaveBookmarks saves new or updated bookmarks to database. diff --git a/internal/database/pg_test.go b/internal/database/pg_test.go index eb1620386..f8172a0f0 100644 --- a/internal/database/pg_test.go +++ b/internal/database/pg_test.go @@ -5,12 +5,9 @@ package database import ( "context" - "errors" "log" "os" "testing" - - "github.com/golang-migrate/migrate/v4" ) func init() { @@ -31,7 +28,7 @@ func postgresqlTestDatabaseFactory(_ *testing.T, ctx context.Context) (DB, error return nil, err } - if err := db.Migrate(); err != nil && !errors.Is(migrate.ErrNoChange, err) { + if err := db.Migrate(context.TODO()); err != nil { return nil, err } diff --git a/internal/database/sqlite.go b/internal/database/sqlite.go index 01e649bf6..43f931794 100644 --- a/internal/database/sqlite.go +++ b/internal/database/sqlite.go @@ -3,19 +3,64 @@ package database import ( "context" "database/sql" + "fmt" "log" "strings" "time" "github.com/go-shiori/shiori/internal/model" - "github.com/golang-migrate/migrate/v4" - "github.com/golang-migrate/migrate/v4/database/sqlite" - "github.com/golang-migrate/migrate/v4/source/iofs" "github.com/jmoiron/sqlx" "github.com/pkg/errors" "golang.org/x/crypto/bcrypt" + + _ "modernc.org/sqlite" ) +var sqliteMigrations = []migration{ + newFileMigration("0.0.0", "0.1.0", "sqlite/0000_system"), + newFileMigration("0.1.0", "0.2.0", "sqlite/0001_initial"), + newFuncMigration("0.2.0", "0.3.0", func(db *sql.DB) error { + // Ensure that bookmark table has `has_content` column and account table has `config` column + // for users upgrading from <1.5.4 directly into this version. + tx, err := db.Begin() + if err != nil { + return fmt.Errorf("failed to start transaction: %w", err) + } + defer tx.Rollback() + + _, err = tx.Exec(`ALTER TABLE bookmark ADD COLUMN has_content BOOLEAN DEFAULT FALSE NOT NULL`) + if strings.Contains(err.Error(), `duplicate column name`) { + tx.Rollback() + } else if err != nil { + return fmt.Errorf("failed to add has_content column to bookmark table: %w", err) + } else if err == nil { + if errCommit := tx.Commit(); errCommit != nil { + return fmt.Errorf("failed to commit transaction: %w", errCommit) + } + } + + tx, err = db.Begin() + if err != nil { + return fmt.Errorf("failed to start transaction: %w", err) + } + defer tx.Rollback() + + _, err = tx.Exec(`ALTER TABLE account ADD COLUMN config JSON NOT NULL DEFAULT '{}'`) + if strings.Contains(err.Error(), `duplicate column name`) { + tx.Rollback() + } else if err != nil { + return fmt.Errorf("failed to add config column to account table: %w", err) + } else if err == nil { + if errCommit := tx.Commit(); errCommit != nil { + return fmt.Errorf("failed to commit transaction: %w", errCommit) + } + } + + return nil + }), + newFileMigration("0.3.0", "0.4.0", "sqlite/0002_denormalize_content"), +} + // SQLiteDatabase is implementation of Database interface // for connecting to SQLite3 database. type SQLiteDatabase struct { @@ -45,33 +90,43 @@ func OpenSQLiteDatabase(ctx context.Context, databasePath string) (sqliteDB *SQL return sqliteDB, nil } +// DBX returns the underlying sqlx.DB object +func (db *SQLiteDatabase) DBx() sqlx.DB { + return db.DB +} + // Migrate runs migrations for this database engine -func (db *SQLiteDatabase) Migrate() error { - sourceDriver, err := iofs.New(migrations, "migrations/sqlite") - if err != nil { +func (db *SQLiteDatabase) Migrate(ctx context.Context) error { + if err := runMigrations(ctx, db, sqliteMigrations); err != nil { return errors.WithStack(err) } - dbDriver, err := sqlite.WithInstance(db.DB.DB, &sqlite.Config{}) + return nil +} + +// GetDatabaseSchemaVersion fetches the current migrations version of the database +func (db *SQLiteDatabase) GetDatabaseSchemaVersion(ctx context.Context) (string, error) { + var version string + + err := db.GetContext(ctx, &version, "SELECT database_schema_version FROM shiori_system") if err != nil { - return errors.WithStack(err) + return "", errors.WithStack(err) } - migration, err := migrate.NewWithInstance( - "iofs", - sourceDriver, - "sqlite", - dbDriver, - ) + return version, nil +} + +// SetDatabaseSchemaVersion sets the current migrations version of the database +func (db *SQLiteDatabase) SetDatabaseSchemaVersion(ctx context.Context, version string) error { + tx := db.MustBegin() + defer tx.Rollback() + + _, err := tx.Exec("UPDATE shiori_system SET database_schema_version = ?", version) if err != nil { return errors.WithStack(err) } - if err := migration.Up(); err != nil && !errors.Is(err, migrate.ErrNoChange) { - return err - } - - return nil + return tx.Commit() } // SaveBookmarks saves new or updated bookmarks to database. diff --git a/internal/database/sqlite_test.go b/internal/database/sqlite_test.go index 264a05e44..9590686ff 100644 --- a/internal/database/sqlite_test.go +++ b/internal/database/sqlite_test.go @@ -7,8 +7,6 @@ import ( "testing" "github.com/go-shiori/shiori/internal/model" - "github.com/golang-migrate/migrate/v4" - "github.com/pkg/errors" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -22,7 +20,7 @@ func sqliteTestDatabaseFactory(t *testing.T, ctx context.Context) (DB, error) { return nil, err } - if err := db.Migrate(); err != nil && !errors.Is(migrate.ErrNoChange, err) { + if err := db.Migrate(context.TODO()); err != nil { return nil, err } diff --git a/internal/domains/bookmarks_test.go b/internal/domains/bookmarks_test.go index 950c7851a..c02f16960 100644 --- a/internal/domains/bookmarks_test.go +++ b/internal/domains/bookmarks_test.go @@ -20,7 +20,7 @@ func TestBookmarkDomain(t *testing.T) { db, err := database.OpenSQLiteDatabase(context.TODO(), ":memory:") require.NoError(t, err) - require.NoError(t, db.Migrate()) + require.NoError(t, db.Migrate(context.TODO())) deps := &dependencies.Dependencies{ Database: db, diff --git a/internal/testutil/shiori.go b/internal/testutil/shiori.go index fd6272cba..43ceb24d9 100644 --- a/internal/testutil/shiori.go +++ b/internal/testutil/shiori.go @@ -33,7 +33,7 @@ func GetTestConfigurationAndDependencies(t *testing.T, ctx context.Context, logg db, err := database.OpenSQLiteDatabase(ctx, tmp.Name()) require.NoError(t, err) - require.NoError(t, db.Migrate()) + require.NoError(t, db.Migrate(context.TODO())) cfg.Storage.DataDir = tmpDir diff --git a/main.go b/main.go index 400f9b355..b74376ee3 100644 --- a/main.go +++ b/main.go @@ -5,11 +5,6 @@ import ( "github.com/go-shiori/shiori/internal/model" "github.com/sirupsen/logrus" - // Database driver - _ "github.com/go-sql-driver/mysql" - _ "github.com/lib/pq" - _ "modernc.org/sqlite" - // Add this to prevent it removed by go mod tidy _ "github.com/shurcooL/vfsgen" )