forgejo/services/f3/driver/attachment.go
Renovate Bot 6ce9d764bc Update module code.forgejo.org/f3/gof3/v3 to v3.11.0 (forgejo) (#8056)
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| code.forgejo.org/f3/gof3/v3 | require | minor | `v3.10.8` -> `v3.11.0` |

---

### Configuration

📅 **Schedule**: Branch creation - On day 1 of the month, every 3 months ( * * 1 */3 * ) (UTC), Automerge - Between 12:00 AM and 03:59 AM ( * 0-3 * * * ) (UTC).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0MC40MC4wIiwidXBkYXRlZEluVmVyIjoiNDAuNDAuMCIsInRhcmdldEJyYW5jaCI6ImZvcmdlam8iLCJsYWJlbHMiOlsiZGVwZW5kZW5jeS11cGdyYWRlIiwidGVzdC9ub3QtbmVlZGVkIl19-->

Co-authored-by: limiting-factor <limiting-factor@posteo.com>
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/8056
Co-authored-by: Renovate Bot <forgejo-renovate-action@forgejo.org>
Co-committed-by: Renovate Bot <forgejo-renovate-action@forgejo.org>
2025-06-03 14:24:57 +02:00

185 lines
4.8 KiB
Go

// Copyright Earl Warren <contact@earl-warren.org>
// Copyright Loïc Dachary <loic@dachary.org>
// SPDX-License-Identifier: MIT
package driver
import (
"context"
"crypto/sha256"
"encoding/hex"
"fmt"
"io"
"os"
"forgejo.org/models/db"
repo_model "forgejo.org/models/repo"
user_model "forgejo.org/models/user"
"forgejo.org/modules/storage"
"forgejo.org/modules/timeutil"
forgejo_attachment "forgejo.org/services/attachment"
"code.forgejo.org/f3/gof3/v3/f3"
f3_id "code.forgejo.org/f3/gof3/v3/id"
f3_tree "code.forgejo.org/f3/gof3/v3/tree/f3"
"code.forgejo.org/f3/gof3/v3/tree/generic"
f3_util "code.forgejo.org/f3/gof3/v3/util"
"github.com/google/uuid"
)
var _ f3_tree.ForgeDriverInterface = &issue{}
type attachment struct {
common
forgejoAttachment *repo_model.Attachment
sha string
contentType string
downloadFunc f3.DownloadFuncType
}
func (o *attachment) SetNative(attachment any) {
o.forgejoAttachment = attachment.(*repo_model.Attachment)
}
func (o *attachment) GetNativeID() string {
return fmt.Sprintf("%d", o.forgejoAttachment.ID)
}
func (o *attachment) NewFormat() f3.Interface {
node := o.GetNode()
return node.GetTree().(f3_tree.TreeInterface).NewFormat(node.GetKind())
}
func (o *attachment) ToFormat() f3.Interface {
if o.forgejoAttachment == nil {
return o.NewFormat()
}
return &f3.Attachment{
Common: f3.NewCommon(o.GetNativeID()),
Name: o.forgejoAttachment.Name,
ContentType: o.contentType,
Size: o.forgejoAttachment.Size,
DownloadCount: o.forgejoAttachment.DownloadCount,
Created: o.forgejoAttachment.CreatedUnix.AsTime(),
SHA256: o.sha,
DownloadURL: o.forgejoAttachment.DownloadURL(),
DownloadFunc: o.downloadFunc,
}
}
func (o *attachment) FromFormat(content f3.Interface) {
attachment := content.(*f3.Attachment)
o.forgejoAttachment = &repo_model.Attachment{
ID: f3_util.ParseInt(attachment.GetID()),
Name: attachment.Name,
Size: attachment.Size,
DownloadCount: attachment.DownloadCount,
CreatedUnix: timeutil.TimeStamp(attachment.Created.Unix()),
CustomDownloadURL: attachment.DownloadURL,
}
o.contentType = attachment.ContentType
o.sha = attachment.SHA256
o.downloadFunc = attachment.DownloadFunc
}
func (o *attachment) Get(ctx context.Context) bool {
node := o.GetNode()
o.Trace("%s", node.GetID())
id := node.GetID().Int64()
attachment, err := repo_model.GetAttachmentByID(ctx, id)
if repo_model.IsErrAttachmentNotExist(err) {
return false
}
if err != nil {
panic(fmt.Errorf("attachment %v %w", id, err))
}
o.forgejoAttachment = attachment
path := o.forgejoAttachment.RelativePath()
{
f, err := storage.Attachments.Open(path)
if err != nil {
panic(err)
}
hasher := sha256.New()
if _, err := io.Copy(hasher, f); err != nil {
panic(fmt.Errorf("io.Copy to hasher: %v", err))
}
o.sha = hex.EncodeToString(hasher.Sum(nil))
}
o.downloadFunc = func() io.ReadCloser {
o.Trace("download %s from copy stored in temporary file %s", o.forgejoAttachment.DownloadURL, path)
f, err := os.Open(path)
if err != nil {
panic(err)
}
return f
}
return true
}
func (o *attachment) Patch(ctx context.Context) {
o.Trace("%d", o.forgejoAttachment.ID)
if _, err := db.GetEngine(ctx).ID(o.forgejoAttachment.ID).Cols("name").Update(o.forgejoAttachment); err != nil {
panic(fmt.Errorf("UpdateAttachmentCols: %v %v", o.forgejoAttachment, err))
}
}
func (o *attachment) Put(ctx context.Context) f3_id.NodeID {
node := o.GetNode()
o.Trace("%s", node.GetID())
uploader, err := user_model.GetAdminUser(ctx)
if err != nil {
panic(fmt.Errorf("GetAdminUser %w", err))
}
attachable := f3_tree.GetAttachable(o.GetNode())
attachableID := f3_tree.GetAttachableID(o.GetNode())
switch attachable.GetKind() {
case f3_tree.KindRelease:
o.forgejoAttachment.ReleaseID = attachableID
case f3_tree.KindComment:
o.forgejoAttachment.CommentID = attachableID
case f3_tree.KindIssue, f3_tree.KindPullRequest:
o.forgejoAttachment.IssueID = attachableID
default:
panic(fmt.Errorf("unexpected type %s", attachable.GetKind()))
}
o.forgejoAttachment.UploaderID = uploader.ID
o.forgejoAttachment.RepoID = f3_tree.GetProjectID(o.GetNode())
o.forgejoAttachment.UUID = uuid.New().String()
download := o.downloadFunc()
defer download.Close()
_, err = forgejo_attachment.NewAttachment(ctx, o.forgejoAttachment, download, o.forgejoAttachment.Size)
if err != nil {
panic(err)
}
o.Trace("attachment created %d", o.forgejoAttachment.ID)
return f3_id.NewNodeID(o.forgejoAttachment.ID)
}
func (o *attachment) Delete(ctx context.Context) {
node := o.GetNode()
o.Trace("%s", node.GetID())
if err := repo_model.DeleteAttachment(ctx, o.forgejoAttachment, true); err != nil {
panic(err)
}
}
func newAttachment() generic.NodeDriverInterface {
return &attachment{}
}