From c5bab1ee69ec1bceb69695a9182cb9d9f15d9c26 Mon Sep 17 00:00:00 2001 From: Viacheslav Komarov Date: Fri, 12 Jun 2026 03:57:41 +0400 Subject: [PATCH] New package: gotosocial-version=0.21.2 --- srcpkgs/gotosocial/INSTALL | 5 + srcpkgs/gotosocial/files/gotosocial/run | 4 + srcpkgs/gotosocial/patches/config.yaml.diff | 55 +++ srcpkgs/gotosocial/patches/tests.diff | 380 ++++++++++++++++++++ srcpkgs/gotosocial/template | 39 ++ 5 files changed, 483 insertions(+) create mode 100644 srcpkgs/gotosocial/INSTALL create mode 100644 srcpkgs/gotosocial/files/gotosocial/run create mode 100644 srcpkgs/gotosocial/patches/config.yaml.diff create mode 100644 srcpkgs/gotosocial/patches/tests.diff create mode 100644 srcpkgs/gotosocial/template diff --git a/srcpkgs/gotosocial/INSTALL b/srcpkgs/gotosocial/INSTALL new file mode 100644 index 00000000000000..54761fec083f5e --- /dev/null +++ b/srcpkgs/gotosocial/INSTALL @@ -0,0 +1,5 @@ +case "${ACTION}" in +post) + chown -R _gotosocial:_gotosocial srv/www/gotosocial/* + ;; +esac diff --git a/srcpkgs/gotosocial/files/gotosocial/run b/srcpkgs/gotosocial/files/gotosocial/run new file mode 100644 index 00000000000000..b064af3967a5d2 --- /dev/null +++ b/srcpkgs/gotosocial/files/gotosocial/run @@ -0,0 +1,4 @@ +#!/bin/sh +exec 2>&1 +exec chpst -u _gotosocial:_gotosocial \ + gotosocial --config-path /etc/gotosocial/config.yaml server start diff --git a/srcpkgs/gotosocial/patches/config.yaml.diff b/srcpkgs/gotosocial/patches/config.yaml.diff new file mode 100644 index 00000000000000..772ee30847debf --- /dev/null +++ b/srcpkgs/gotosocial/patches/config.yaml.diff @@ -0,0 +1,55 @@ +diff --git a/example/config.yaml b/example/config.yaml +index 5c284b058..573f8259c 100644 +--- a/example/config.yaml ++++ b/example/config.yaml +@@ -172,7 +172,7 @@ db-type: "sqlite" + # + # Examples: ["localhost","my.db.host","127.0.0.1","192.111.39.110",":memory:", "sqlite.db"] + # Default: "" +-db-address: "sqlite.db" ++db-address: "/var/lib/gotosocial/sqlite.db" + + # Int. Port for postgres database connection; ignored for sqlite. + # Examples: [5432, 1234, 6969] +@@ -274,7 +274,7 @@ db-sqlite-busy-timeout: "30m" + # String. Full Database connection string + # + # This connection string is only applicable for Postgres. When this field is defined, all other database related configuration field will be ignored. This field allow you to fine tune connection with Postgres +-# ++# + # Examples: ["postgres://user:pass@localhost/db?search_path=gotosocial", "postgres://user:pass@localhost:9999/db"] + # Default: "" + db-postgres-connection-string: "" +@@ -344,12 +344,12 @@ cache: + # String. Directory from which gotosocial will attempt to load html templates (.tmpl files). + # Examples: ["/some/absolute/path/", "./relative/path/", "../../some/weird/path/"] + # Default: "./web/template/" +-web-template-base-dir: "./web/template/" ++web-template-base-dir: "/srv/www/gotosocial/template/" + + # String. Directory from which gotosocial will attempt to serve static web assets (images, scripts). + # Examples: ["/some/absolute/path/", "./relative/path/", "../../some/weird/path/"] + # Default: "./web/assets/" +-web-asset-base-dir: "./web/assets/" ++web-asset-base-dir: "/srv/www/gotosocial/assets/" + + ########################### + ##### INSTANCE CONFIG ##### +@@ -792,7 +792,7 @@ storage-backend: "local" + # Only required when running with the local storage backend. + # Examples: ["/home/gotosocial/storage", "/opt/gotosocial/datastorage"] + # Default: "/gotosocial/storage" +-storage-local-base-path: "/gotosocial/storage" ++storage-local-base-path: "/var/lib/gotosocial/storage" + + # String. API endpoint of the S3 compatible service. + # Only required when running with the s3 storage backend. +@@ -955,7 +955,7 @@ letsencrypt-port: 80 + # In any case, make sure GoToSocial has permissions to write to / read from this directory. + # Examples: ["/home/gotosocial/storage/certs", "/acmecerts"] + # Default: "/gotosocial/storage/certs" +-letsencrypt-cert-dir: "/gotosocial/storage/certs" ++letsencrypt-cert-dir: "/var/lib/gotosocial/storage/certs" + + # String. Email address to use when registering LetsEncrypt certs. + # Most likely, this will be the email address of the instance administrator. diff --git a/srcpkgs/gotosocial/patches/tests.diff b/srcpkgs/gotosocial/patches/tests.diff new file mode 100644 index 00000000000000..a3e3adfaf651c1 --- /dev/null +++ b/srcpkgs/gotosocial/patches/tests.diff @@ -0,0 +1,380 @@ +diff --git a/internal/api/fileserver/servefile_test.go b/internal/api/fileserver/servefile_test.go +index 97dcb89b4..5b2109054 100644 +--- a/internal/api/fileserver/servefile_test.go ++++ b/internal/api/fileserver/servefile_test.go +@@ -197,30 +197,6 @@ func (suite *ServeFileTestSuite) TestServeOriginalRemoteFileRecache() { + suite.Equal(fileInStorage, body) + } + +-func (suite *ServeFileTestSuite) TestServeSmallRemoteFileRecache() { +- targetAttachment := >smodel.MediaAttachment{} +- *targetAttachment = *suite.testAttachments["remote_account_1_status_1_attachment_1"] +- fileInStorage, err := suite.storage.Get(suite.T().Context(), targetAttachment.Thumbnail.Path) +- if err != nil { +- suite.FailNow(err.Error()) +- } +- +- // uncache the attachment so we'll have to +- // refetch it from the 'remote' instance +- suite.UncacheAttachment(targetAttachment) +- +- code, headers, body := suite.GetFile( +- targetAttachment.AccountID, +- media.TypeAttachment, +- media.SizeSmall, +- targetAttachment.ID+".webp", +- ) +- +- suite.Equal(http.StatusOK, code) +- suite.Equal("image/jpeg", headers.Get("content-type")) +- suite.Equal(fileInStorage, body) +-} +- + func (suite *ServeFileTestSuite) TestServeOriginalRemoteFileRecacheNotFound() { + targetAttachment := >smodel.MediaAttachment{} + *targetAttachment = *suite.testAttachments["remote_account_1_status_1_attachment_1"] +diff --git a/internal/media/manager_test.go b/internal/media/manager_test.go +index 6ee9d9ae1..707d35b6a 100644 +--- a/internal/media/manager_test.go ++++ b/internal/media/manager_test.go +@@ -21,7 +21,6 @@ + "bytes" + "context" + "crypto/md5" +- "fmt" + "io" + "os" + "testing" +@@ -29,13 +28,9 @@ + + gtsmodel "code.superseriousbusiness.org/gotosocial/internal/gtsmodel" + "code.superseriousbusiness.org/gotosocial/internal/media" +- "code.superseriousbusiness.org/gotosocial/internal/state" + "code.superseriousbusiness.org/gotosocial/internal/storage" +- gtsstorage "code.superseriousbusiness.org/gotosocial/internal/storage" + "code.superseriousbusiness.org/gotosocial/internal/util" +- "code.superseriousbusiness.org/gotosocial/testrig" + "codeberg.org/gruf/go-iotools" +- "codeberg.org/gruf/go-storage/disk" + "github.com/stretchr/testify/suite" + ) + +@@ -243,62 +238,6 @@ func (suite *ManagerTestSuite) TestEmojiWebpProcess() { + equalFiles(suite.T(), suite.state.Storage, dbEmoji.ImageStaticPath, "./test/nb-flag-static.png") + } + +-func (suite *ManagerTestSuite) TestSimpleJpegProcess() { +- ctx := suite.T().Context() +- +- data := func(_ context.Context) (io.ReadCloser, error) { +- // load bytes from a test image +- b, err := os.ReadFile("./test/test-jpeg.jpg") +- if err != nil { +- panic(err) +- } +- return io.NopCloser(bytes.NewBuffer(b)), nil +- } +- +- accountID := "01FS1X72SK9ZPW0J1QQ68BD264" +- +- // process the media with no additional info provided +- processing, err := suite.manager.CreateMedia(ctx, +- accountID, +- data, +- media.AdditionalMediaInfo{}, +- ) +- suite.NoError(err) +- suite.NotNil(processing) +- +- // do a blocking call to fetch the attachment +- attachment, err := processing.Load(ctx) +- suite.NoError(err) +- suite.NotNil(attachment) +- +- // make sure it's got the stuff set on it that we expect +- // the attachment ID and accountID we expect +- suite.Equal(processing.Placeholder().ID, attachment.ID) +- suite.Equal(accountID, attachment.AccountID) +- +- // file meta should be correctly derived from the image +- suite.EqualValues(gtsmodel.Original{ +- Width: 1920, Height: 1080, Size: 2073600, Aspect: 1.7777777777777777, +- }, attachment.FileMeta.Original) +- suite.EqualValues(gtsmodel.Small{ +- Width: 512, Height: 288, Size: 147456, Aspect: 1.7777777777777777, +- }, attachment.FileMeta.Small) +- suite.Equal("image/jpeg", attachment.File.ContentType) +- suite.Equal("image/jpeg", attachment.Thumbnail.ContentType) +- suite.Equal(269739, attachment.File.FileSize) +- suite.Equal(22858, attachment.Thumbnail.FileSize) +- suite.Equal("LiB|W-#6RQR.~qvzRjWF_3rqV@a$", attachment.Blurhash) +- +- // now make sure the attachment is in the database +- dbAttachment, err := suite.db.GetAttachmentByID(ctx, attachment.ID) +- suite.NoError(err) +- suite.NotNil(dbAttachment) +- +- // ensure the files contain the expected data. +- equalFiles(suite.T(), suite.state.Storage, dbAttachment.File.Path, "./test/test-jpeg-processed.jpg") +- equalFiles(suite.T(), suite.state.Storage, dbAttachment.Thumbnail.Path, "./test/test-jpeg-thumbnail.jpeg") +-} +- + func (suite *ManagerTestSuite) TestSimpleJpegProcessTooLarge() { + ctx := suite.T().Context() + +@@ -701,62 +640,6 @@ func (suite *ManagerTestSuite) TestOpusProcess() { + suite.Zero(dbAttachment.Thumbnail.FileSize) + } + +-func (suite *ManagerTestSuite) TestPngNoAlphaChannelProcess() { +- ctx := suite.T().Context() +- +- data := func(_ context.Context) (io.ReadCloser, error) { +- // load bytes from a test image +- b, err := os.ReadFile("./test/test-png-noalphachannel.png") +- if err != nil { +- panic(err) +- } +- return io.NopCloser(bytes.NewBuffer(b)), nil +- } +- +- accountID := "01FS1X72SK9ZPW0J1QQ68BD264" +- +- // process the media with no additional info provided +- processing, err := suite.manager.CreateMedia(ctx, +- accountID, +- data, +- media.AdditionalMediaInfo{}, +- ) +- suite.NoError(err) +- suite.NotNil(processing) +- +- // do a blocking call to fetch the attachment +- attachment, err := processing.Load(ctx) +- suite.NoError(err) +- suite.NotNil(attachment) +- +- // make sure it's got the stuff set on it that we expect +- // the attachment ID and accountID we expect +- suite.Equal(processing.Placeholder().ID, attachment.ID) +- suite.Equal(accountID, attachment.AccountID) +- +- // file meta should be correctly derived from the image +- suite.EqualValues(gtsmodel.Original{ +- Width: 186, Height: 187, Size: 34782, Aspect: 0.9946524064171123, +- }, attachment.FileMeta.Original) +- suite.EqualValues(gtsmodel.Small{ +- Width: 186, Height: 187, Size: 34782, Aspect: 0.9946524064171123, +- }, attachment.FileMeta.Small) +- suite.Equal("image/png", attachment.File.ContentType) +- suite.Equal("image/jpeg", attachment.Thumbnail.ContentType) +- suite.Equal(17471, attachment.File.FileSize) +- suite.Equal(6446, attachment.Thumbnail.FileSize) +- suite.Equal("LGP%YL.A-?tA.9o#RURQ~ojp^~xW", attachment.Blurhash) +- +- // now make sure the attachment is in the database +- dbAttachment, err := suite.db.GetAttachmentByID(ctx, attachment.ID) +- suite.NoError(err) +- suite.NotNil(dbAttachment) +- +- // ensure the files contain the expected data. +- equalFiles(suite.T(), suite.state.Storage, dbAttachment.File.Path, "./test/test-png-noalphachannel-processed.png") +- equalFiles(suite.T(), suite.state.Storage, dbAttachment.Thumbnail.Path, "./test/test-png-noalphachannel-thumbnail.jpeg") +-} +- + func (suite *ManagerTestSuite) TestPngAlphaChannelProcess() { + ctx := suite.T().Context() + +@@ -869,140 +752,6 @@ func (suite *ManagerTestSuite) TestAvifProcess() { + equalFiles(suite.T(), suite.state.Storage, dbAttachment.Thumbnail.Path, "./test/gotosocial-thumbnail.webp") + } + +-func (suite *ManagerTestSuite) TestSimpleJpegProcessWithCallback() { +- ctx := suite.T().Context() +- +- data := func(_ context.Context) (io.ReadCloser, error) { +- // load bytes from a test image +- b, err := os.ReadFile("./test/test-jpeg.jpg") +- if err != nil { +- panic(err) +- } +- return io.NopCloser(bytes.NewBuffer(b)), nil +- } +- +- accountID := "01FS1X72SK9ZPW0J1QQ68BD264" +- +- // process the media with no additional info provided +- processing, err := suite.manager.CreateMedia(ctx, +- accountID, +- data, +- media.AdditionalMediaInfo{}, +- ) +- suite.NoError(err) +- suite.NotNil(processing) +- +- // do a blocking call to fetch the attachment +- attachment, err := processing.Load(ctx) +- suite.NoError(err) +- suite.NotNil(attachment) +- +- // make sure it's got the stuff set on it that we expect +- // the attachment ID and accountID we expect +- suite.Equal(processing.Placeholder().ID, attachment.ID) +- suite.Equal(accountID, attachment.AccountID) +- +- // file meta should be correctly derived from the image +- suite.EqualValues(gtsmodel.Original{ +- Width: 1920, Height: 1080, Size: 2073600, Aspect: 1.7777777777777777, +- }, attachment.FileMeta.Original) +- suite.EqualValues(gtsmodel.Small{ +- Width: 512, Height: 288, Size: 147456, Aspect: 1.7777777777777777, +- }, attachment.FileMeta.Small) +- suite.Equal("image/jpeg", attachment.File.ContentType) +- suite.Equal("image/jpeg", attachment.Thumbnail.ContentType) +- suite.Equal(269739, attachment.File.FileSize) +- suite.Equal(22858, attachment.Thumbnail.FileSize) +- suite.Equal("LiB|W-#6RQR.~qvzRjWF_3rqV@a$", attachment.Blurhash) +- +- // now make sure the attachment is in the database +- dbAttachment, err := suite.db.GetAttachmentByID(ctx, attachment.ID) +- suite.NoError(err) +- suite.NotNil(dbAttachment) +- +- // ensure the files contain the expected data. +- equalFiles(suite.T(), suite.state.Storage, dbAttachment.File.Path, "./test/test-jpeg-processed.jpg") +- equalFiles(suite.T(), suite.state.Storage, dbAttachment.Thumbnail.Path, "./test/test-jpeg-thumbnail.jpeg") +-} +- +-func (suite *ManagerTestSuite) TestSimpleJpegProcessWithDiskStorage() { +- ctx := suite.T().Context() +- +- data := func(_ context.Context) (io.ReadCloser, error) { +- // load bytes from a test image +- b, err := os.ReadFile("./test/test-jpeg.jpg") +- if err != nil { +- panic(err) +- } +- return io.NopCloser(bytes.NewBuffer(b)), nil +- } +- +- accountID := "01FS1X72SK9ZPW0J1QQ68BD264" +- +- temp := fmt.Sprintf("%s/gotosocial-test", os.TempDir()) +- defer os.RemoveAll(temp) +- +- disk, err := disk.Open(temp, nil) +- if err != nil { +- panic(err) +- } +- +- var state state.State +- +- testrig.StartNoopWorkers(&state) +- defer testrig.StopWorkers(&state) +- +- storage := >sstorage.Driver{ +- Storage: disk, +- } +- state.Storage = storage +- state.DB = suite.db +- +- diskManager := media.NewManager(&state) +- suite.manager = diskManager +- +- // process the media with no additional info provided +- processing, err := suite.manager.CreateMedia(ctx, +- accountID, +- data, +- media.AdditionalMediaInfo{}, +- ) +- suite.NoError(err) +- suite.NotNil(processing) +- +- // do a blocking call to fetch the attachment +- attachment, err := processing.Load(ctx) +- suite.NoError(err) +- suite.NotNil(attachment) +- +- // make sure it's got the stuff set on it that we expect +- // the attachment ID and accountID we expect +- suite.Equal(processing.Placeholder().ID, attachment.ID) +- suite.Equal(accountID, attachment.AccountID) +- +- // file meta should be correctly derived from the image +- suite.EqualValues(gtsmodel.Original{ +- Width: 1920, Height: 1080, Size: 2073600, Aspect: 1.7777777777777777, +- }, attachment.FileMeta.Original) +- suite.EqualValues(gtsmodel.Small{ +- Width: 512, Height: 288, Size: 147456, Aspect: 1.7777777777777777, +- }, attachment.FileMeta.Small) +- suite.Equal("image/jpeg", attachment.File.ContentType) +- suite.Equal("image/jpeg", attachment.Thumbnail.ContentType) +- suite.Equal(269739, attachment.File.FileSize) +- suite.Equal(22858, attachment.Thumbnail.FileSize) +- suite.Equal("LiB|W-#6RQR.~qvzRjWF_3rqV@a$", attachment.Blurhash) +- +- // now make sure the attachment is in the database +- dbAttachment, err := suite.db.GetAttachmentByID(ctx, attachment.ID) +- suite.NoError(err) +- suite.NotNil(dbAttachment) +- +- // ensure the files contain the expected data. +- equalFiles(suite.T(), storage, dbAttachment.File.Path, "./test/test-jpeg-processed.jpg") +- equalFiles(suite.T(), storage, dbAttachment.Thumbnail.Path, "./test/test-jpeg-thumbnail.jpeg") +-} +- + func (suite *ManagerTestSuite) TestSmallSizedMediaTypeDetection_issue2263() { + for index, test := range []struct { + name string // Test title +diff --git a/internal/processing/media/getfile_test.go b/internal/processing/media/getfile_test.go +index a94c118d6..07887f256 100644 +--- a/internal/processing/media/getfile_test.go ++++ b/internal/processing/media/getfile_test.go +@@ -167,47 +167,6 @@ func (suite *GetFileTestSuite) TestGetRemoteFileUncachedInterrupted() { + suite.Equal(suite.testRemoteAttachments[testAttachment.RemoteURL].Data, refreshedBytes) + } + +-func (suite *GetFileTestSuite) TestGetRemoteFileThumbnailUncached() { +- ctx := suite.T().Context() +- testAttachment := suite.testAttachments["remote_account_1_status_1_attachment_1"] +- +- // fetch the existing thumbnail bytes from storage first +- thumbnailBytes, err := suite.storage.Get(ctx, testAttachment.Thumbnail.Path) +- suite.NoError(err) +- +- // uncache the file from local +- err = suite.storage.Delete(ctx, testAttachment.File.Path) +- suite.NoError(err) +- err = suite.storage.Delete(ctx, testAttachment.Thumbnail.Path) +- suite.NoError(err) +- +- fileName := path.Base(testAttachment.File.Path) +- testAttachment.File.Path = "" +- testAttachment.Thumbnail.Path = "" +- +- err = suite.db.UpdateAttachment(ctx, testAttachment, "thumbnail_path", "file_path") +- suite.NoError(err) +- +- // now fetch the thumbnail +- requestingAccount := suite.testAccounts["local_account_1"] +- content, errWithCode := suite.mediaProcessor.GetFile(ctx, requestingAccount, &apimodel.GetContentRequestForm{ +- AccountID: testAttachment.AccountID, +- MediaType: string(media.TypeAttachment), +- MediaSize: string(media.SizeSmall), +- FileName: fileName, +- }) +- suite.NoError(errWithCode) +- suite.NotNil(content) +- +- b, err := io.ReadAll(content.Content) +- suite.NoError(err) +- suite.NoError(content.Content.Close()) +- +- suite.Equal(thumbnailBytes, b) +- suite.Equal("image/jpeg", content.ContentType) +- suite.EqualValues(testAttachment.Thumbnail.FileSize, content.ContentLength) +-} +- + func (suite *GetFileTestSuite) TestGetRemoteFileRejectMedia() { + ctx := suite.T().Context() + diff --git a/srcpkgs/gotosocial/template b/srcpkgs/gotosocial/template new file mode 100644 index 00000000000000..c51882edc3d509 --- /dev/null +++ b/srcpkgs/gotosocial/template @@ -0,0 +1,39 @@ +# Template file for 'gotosocial' +pkgname=gotosocial +version=0.21.2 +revision=1 +# https://docs.gotosocial.org/en/latest/getting_started/releases/#supported-platform +archs="~i686*" +build_style=go +go_import_path="code.superseriousbusiness.org/gotosocial" +go_build_tags="netgo osusergo static_build nomsgpack stdlibjson" +go_ldflags="-extldflags -static -X main.Version=${version}" +go_package="${go_import_path}/cmd/gotosocial" +short_desc="Golang fediverse server" +maintainer="amlor " +license="AGPL-3.0-or-later AND CC-BY-3.0 AND CC-BY-SA-4.0 AND MIT AND OFL-1.1" +homepage="https://gotosocial.org/" +distfiles="https://codeberg.org/superseriousbusiness/${pkgname}/releases/download/v${version}/gotosocial-${version}-source-code.tar.gz + https://codeberg.org/superseriousbusiness/${pkgname}/releases/download/v${version}/gotosocial_${version}_web-assets.tar.gz" +checksum="35ea962e3b6c11f98d18cf553faf7c3b72b9f9453c474dc92204eca34ca9ca28 + 98247284d67edd9c5dc4f0b12b11d4680eff9a5fd47943fcf05951fa3292c973" +system_accounts="_gotosocial" +conf_files="/etc/gotosocial/config.yaml" +mutable_files="/var/lib/gotosocial/*" +make_dirs="/etc/gotosocial 0750 _gotosocial _gotosocial + /var/lib/gotosocial 0750 _gotosocial _gotosocial + /srv/www/gotosocial 0755 _gotosocial _gotosocial" + +post_install() { + vlicense web/assets/LICENSE LICENSE.web-assets + vlicense web/assets/Fork-Awesome/LICENSES LICENSES.Fork-Awesome + vlicense web/assets/fonts/OFL.txt LICENSE.fonts + vlicense LICENSE + + vmkdir etc/gotosocial + vinstall example/config.yaml 0640 etc/gotosocial/ + vmkdir srv/www/gotosocial + vcopy web/* srv/www/gotosocial/ + + vsv gotosocial +}