mirror of
https://github.com/opencloud-eu/opencloud.git
synced 2026-01-21 04:18:21 -05:00
Merge pull request #9011 from kobergj/BackportRevaBump
[full-ci] Backport reva bump
This commit is contained in:
11
changelog/unreleased/bump-reva.md
Normal file
11
changelog/unreleased/bump-reva.md
Normal file
@@ -0,0 +1,11 @@
|
||||
Bugfix: Update reva to v2.19.5
|
||||
|
||||
We updated reva to v2.19.5
|
||||
|
||||
* Bugfix [cs3org/reva#4654](https://github.com/cs3org/reva/pull/4654): Write blob based on session id
|
||||
* Bugfix [cs3org/reva#4666](https://github.com/cs3org/reva/pull/4666): Fix uploading via a public link
|
||||
* Bugfix [cs3org/reva#4665](https://github.com/cs3org/reva/pull/4665): Fix creating documents in nested folders of public shares
|
||||
* Enhancement [cs3org/reva#4655](https://github.com/cs3org/reva/pull/4655): Bump mockery to v2.40.2
|
||||
* Enhancement [cs3org/reva#4664](https://github.com/cs3org/reva/pull/4664): Add ScanData to Uploadsession
|
||||
|
||||
https://github.com/owncloud/ocis/pull/9011
|
||||
5
changelog/unreleased/rework-virus-handling.md
Normal file
5
changelog/unreleased/rework-virus-handling.md
Normal file
@@ -0,0 +1,5 @@
|
||||
Bugfix: Fix infected file handling
|
||||
|
||||
Reworks virus handling. Shows scandate and outcome on ocis storage-users uploads sessions. Avoids retrying infected files on ocis postprocessing restart.
|
||||
|
||||
https://github.com/owncloud/ocis/pull/9011
|
||||
2
go.mod
2
go.mod
@@ -13,7 +13,7 @@ require (
|
||||
github.com/cenkalti/backoff v2.2.1+incompatible
|
||||
github.com/coreos/go-oidc/v3 v3.9.0
|
||||
github.com/cs3org/go-cs3apis v0.0.0-20231023073225-7748710e0781
|
||||
github.com/cs3org/reva/v2 v2.19.5
|
||||
github.com/cs3org/reva/v2 v2.19.6
|
||||
github.com/dhowden/tag v0.0.0-20230630033851-978a0926ee25
|
||||
github.com/dutchcoders/go-clamd v0.0.0-20170520113014-b970184f4d9e
|
||||
github.com/egirna/icap-client v0.1.1
|
||||
|
||||
4
go.sum
4
go.sum
@@ -1019,8 +1019,8 @@ github.com/crewjam/saml v0.4.14 h1:g9FBNx62osKusnFzs3QTN5L9CVA/Egfgm+stJShzw/c=
|
||||
github.com/crewjam/saml v0.4.14/go.mod h1:UVSZCf18jJkk6GpWNVqcyQJMD5HsRugBPf4I1nl2mME=
|
||||
github.com/cs3org/go-cs3apis v0.0.0-20231023073225-7748710e0781 h1:BUdwkIlf8IS2FasrrPg8gGPHQPOrQ18MS1Oew2tmGtY=
|
||||
github.com/cs3org/go-cs3apis v0.0.0-20231023073225-7748710e0781/go.mod h1:UXha4TguuB52H14EMoSsCqDj7k8a/t7g4gVP+bgY5LY=
|
||||
github.com/cs3org/reva/v2 v2.19.5 h1:Qh38wpPovnb0jPpgGR6L6HfbQ8vwObcrB8yUCRJldSw=
|
||||
github.com/cs3org/reva/v2 v2.19.5/go.mod h1:GRUrOp5HbFVwZTgR9bVrMZ/MvVy+Jhxw1PdMmhhKP9E=
|
||||
github.com/cs3org/reva/v2 v2.19.6 h1:n7fsTwdIN20vmQFkfOiJUbF2D7JFMLLMgOnEBRM5OTU=
|
||||
github.com/cs3org/reva/v2 v2.19.6/go.mod h1:GRUrOp5HbFVwZTgR9bVrMZ/MvVy+Jhxw1PdMmhhKP9E=
|
||||
github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4=
|
||||
github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg=
|
||||
github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=
|
||||
|
||||
@@ -146,7 +146,7 @@ func (av Antivirus) processEvent(e events.Event, s events.Publisher) error {
|
||||
}
|
||||
|
||||
if av.c.DebugScanOutcome != "" {
|
||||
av.l.Warn().Str("antivir, clamav", ">>>>>>> ANTIVIRUS_DEBUG_SCAN_OUTCOME IS SET NO ACTUAL VIRUS SCAN IS PERFORMED!")
|
||||
av.l.Warn().Str("antivir, clamav", ">>>>>>> ANTIVIRUS_DEBUG_SCAN_OUTCOME IS SET NO ACTUAL VIRUS SCAN IS PERFORMED!").Send()
|
||||
if err := events.Publish(ctx, s, events.PostprocessingStepFinished{
|
||||
FinishedStep: events.PPStepAntivirus,
|
||||
Outcome: events.PostprocessingOutcome(av.c.DebugScanOutcome),
|
||||
@@ -158,7 +158,6 @@ func (av Antivirus) processEvent(e events.Event, s events.Publisher) error {
|
||||
Description: "DEBUG: forced outcome",
|
||||
Scandate: time.Now(),
|
||||
ResourceID: ev.ResourceID,
|
||||
ErrorMsg: "DEBUG: forced outcome",
|
||||
},
|
||||
}); err != nil {
|
||||
av.l.Fatal().Err(err).Str("uploadid", ev.UploadID).Interface("resourceID", ev.ResourceID).Msg("cannot publish events - exiting")
|
||||
|
||||
@@ -97,6 +97,11 @@ func (cl *ClientlogService) processEvent(event events.Event) {
|
||||
default:
|
||||
err = errors.New("unhandled event")
|
||||
case events.UploadReady:
|
||||
if e.Failed {
|
||||
// we don't inform about failed uploads yet
|
||||
return
|
||||
}
|
||||
|
||||
info, err := utils.GetResource(ctx, e.FileRef, gwc)
|
||||
if err != nil {
|
||||
cl.log.Error().Err(err).Interface("event", event).Msg("error getting resource")
|
||||
|
||||
@@ -21,6 +21,7 @@ type Postprocessing struct {
|
||||
Steps []events.Postprocessingstep
|
||||
Status Status
|
||||
Failures int
|
||||
Finished bool
|
||||
|
||||
config config.Postprocessing
|
||||
}
|
||||
|
||||
@@ -148,8 +148,14 @@ func (pps *PostprocessingService) processEvent(e events.Event) error {
|
||||
next = pp.Delay()
|
||||
case events.UploadReady:
|
||||
if ev.Failed {
|
||||
// the upload failed - let's keep it around for a while
|
||||
return nil
|
||||
// the upload failed - let's keep it around for a while - but mark it as finished
|
||||
pp, err = pps.getPP(pps.store, ev.UploadID)
|
||||
if err != nil {
|
||||
pps.log.Error().Str("uploadID", ev.UploadID).Err(err).Msg("cannot get upload")
|
||||
return fmt.Errorf("%w: cannot get upload", ErrEvent)
|
||||
}
|
||||
pp.Finished = true
|
||||
return storePP(pps.store, pp)
|
||||
}
|
||||
|
||||
// the storage provider thinks the upload is done - so no need to keep it any more
|
||||
@@ -256,6 +262,11 @@ func (pps *PostprocessingService) resumePP(ctx context.Context, uploadID string)
|
||||
return fmt.Errorf("cannot get upload: %w", err)
|
||||
}
|
||||
|
||||
if pp.Finished {
|
||||
// dont retry finished uploads
|
||||
return nil
|
||||
}
|
||||
|
||||
return events.Publish(ctx, pps.pub, pp.CurrentStep())
|
||||
}
|
||||
|
||||
|
||||
@@ -191,6 +191,7 @@ func ListUploadSessions(cfg *config.Config) *cli.Command {
|
||||
if c.Bool("json") {
|
||||
for _, u := range uploads {
|
||||
ref := u.Reference()
|
||||
sr, sd := u.ScanData()
|
||||
s := struct {
|
||||
ID string `json:"id"`
|
||||
Space string `json:"space"`
|
||||
@@ -201,6 +202,8 @@ func ListUploadSessions(cfg *config.Config) *cli.Command {
|
||||
SpaceOwner *userpb.UserId `json:"spaceowner,omitempty"`
|
||||
Expires time.Time `json:"expires"`
|
||||
Processing bool `json:"processing"`
|
||||
ScanDate time.Time `json:"virus_scan_date"`
|
||||
ScanResult string `json:"virus_scan_result"`
|
||||
}{
|
||||
Space: ref.GetResourceId().GetSpaceId(),
|
||||
ID: u.ID(),
|
||||
@@ -211,6 +214,8 @@ func ListUploadSessions(cfg *config.Config) *cli.Command {
|
||||
SpaceOwner: u.SpaceOwner(),
|
||||
Expires: u.Expires(),
|
||||
Processing: u.IsProcessing(),
|
||||
ScanDate: sd,
|
||||
ScanResult: sr,
|
||||
}
|
||||
j, err := json.Marshal(s)
|
||||
if err != nil {
|
||||
@@ -236,10 +241,11 @@ func ListUploadSessions(cfg *config.Config) *cli.Command {
|
||||
|
||||
// start a table
|
||||
table = tw.NewWriter(os.Stdout)
|
||||
table.SetHeader([]string{"Space", "Upload Id", "Name", "Offset", "Size", "Executant", "Owner", "Expires", "Processing"})
|
||||
table.SetHeader([]string{"Space", "Upload Id", "Name", "Offset", "Size", "Executant", "Owner", "Expires", "Processing", "Scan Date", "Scan Result"})
|
||||
table.SetAutoFormatHeaders(false)
|
||||
|
||||
for _, u := range uploads {
|
||||
sr, sd := u.ScanData()
|
||||
table.Append([]string{
|
||||
u.Reference().ResourceId.GetSpaceId(),
|
||||
u.ID(),
|
||||
@@ -250,6 +256,8 @@ func ListUploadSessions(cfg *config.Config) *cli.Command {
|
||||
u.SpaceOwner().GetOpaqueId(),
|
||||
u.Expires().Format(time.RFC3339),
|
||||
strconv.FormatBool(u.IsProcessing()),
|
||||
sd.Format(time.RFC3339),
|
||||
sr,
|
||||
})
|
||||
|
||||
if c.Bool("restart") {
|
||||
|
||||
14
vendor/github.com/cs3org/reva/v2/internal/grpc/interceptors/auth/scope.go
generated
vendored
14
vendor/github.com/cs3org/reva/v2/internal/grpc/interceptors/auth/scope.go
generated
vendored
@@ -261,7 +261,7 @@ func checkIfNestedResource(ctx context.Context, ref *provider.Reference, parent
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if statResponse.Status.Code != rpc.Code_CODE_OK {
|
||||
if statResponse.GetStatus().GetCode() != rpc.Code_CODE_OK {
|
||||
return false, statuspkg.NewErrorFromCode(statResponse.Status.Code, "auth interceptor")
|
||||
}
|
||||
|
||||
@@ -313,14 +313,22 @@ func checkIfNestedResource(ctx context.Context, ref *provider.Reference, parent
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if childStat.Status.Code != rpc.Code_CODE_OK {
|
||||
if childStat.GetStatus().GetCode() == rpc.Code_CODE_NOT_FOUND && ref.GetPath() != "" && ref.GetPath() != "." {
|
||||
// The resource does not seem to exist (yet?). We might be part of an initiate upload request.
|
||||
// Stat the parent to get its path and check that against the root path.
|
||||
childStat, err = client.Stat(ctx, &provider.StatRequest{Ref: &provider.Reference{ResourceId: ref.GetResourceId()}})
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
if childStat.GetStatus().GetCode() != rpc.Code_CODE_OK {
|
||||
return false, statuspkg.NewErrorFromCode(childStat.Status.Code, "auth interceptor")
|
||||
}
|
||||
pathResp, err = client.GetPath(ctx, &provider.GetPathRequest{ResourceId: childStat.GetInfo().GetId()})
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if pathResp.Status.Code != rpc.Code_CODE_OK {
|
||||
if pathResp.GetStatus().GetCode() != rpc.Code_CODE_OK {
|
||||
return false, statuspkg.NewErrorFromCode(pathResp.Status.Code, "auth interceptor")
|
||||
}
|
||||
childPath = pathResp.Path
|
||||
|
||||
12
vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/tus.go
generated
vendored
12
vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/tus.go
generated
vendored
@@ -319,9 +319,15 @@ func (s *svc) handleTusPost(ctx context.Context, w http.ResponseWriter, r *http.
|
||||
w.Header().Set(net.HeaderOCMtime, httpRes.Header.Get(net.HeaderOCMtime))
|
||||
}
|
||||
|
||||
if resid, err := storagespace.ParseID(httpRes.Header.Get(net.HeaderOCFileID)); err == nil {
|
||||
sReq.Ref = &provider.Reference{
|
||||
ResourceId: &resid,
|
||||
if strings.HasPrefix(uReq.GetRef().GetPath(), "/public") && uReq.GetRef().GetResourceId() == nil {
|
||||
// Use the path based request for the public link
|
||||
sReq.Ref.Path = uReq.Ref.GetPath()
|
||||
sReq.Ref.ResourceId = nil
|
||||
} else {
|
||||
if resid, err := storagespace.ParseID(httpRes.Header.Get(net.HeaderOCFileID)); err == nil {
|
||||
sReq.Ref = &provider.Reference{
|
||||
ResourceId: &resid,
|
||||
}
|
||||
}
|
||||
}
|
||||
finishUpload = httpRes.Header.Get(net.HeaderUploadOffset) == r.Header.Get(net.HeaderUploadLength)
|
||||
|
||||
2
vendor/github.com/cs3org/reva/v2/pkg/publicshare/manager/owncloudsql/conversions.go
generated
vendored
2
vendor/github.com/cs3org/reva/v2/pkg/publicshare/manager/owncloudsql/conversions.go
generated
vendored
@@ -33,8 +33,6 @@ import (
|
||||
"github.com/jellydator/ttlcache/v2"
|
||||
)
|
||||
|
||||
//go:generate make --no-print-directory -C ../../../.. mockery NAME=UserConverter
|
||||
|
||||
// DBShare stores information about user and public shares.
|
||||
type DBShare struct {
|
||||
ID string
|
||||
|
||||
2
vendor/github.com/cs3org/reva/v2/pkg/share/manager/owncloudsql/conversions.go
generated
vendored
2
vendor/github.com/cs3org/reva/v2/pkg/share/manager/owncloudsql/conversions.go
generated
vendored
@@ -37,8 +37,6 @@ import (
|
||||
"github.com/jellydator/ttlcache/v2"
|
||||
)
|
||||
|
||||
//go:generate make --no-print-directory -C ../../../.. mockery NAME=UserConverter
|
||||
|
||||
// DBShare stores information about user and public shares.
|
||||
type DBShare struct {
|
||||
ID string
|
||||
|
||||
2
vendor/github.com/cs3org/reva/v2/pkg/share/share.go
generated
vendored
2
vendor/github.com/cs3org/reva/v2/pkg/share/share.go
generated
vendored
@@ -36,8 +36,6 @@ const (
|
||||
NoState collaboration.ShareState = -1
|
||||
)
|
||||
|
||||
//go:generate make --no-print-directory -C ../.. mockery NAME=Manager
|
||||
|
||||
// Metadata contains Metadata for a share
|
||||
type Metadata struct {
|
||||
ETag string
|
||||
|
||||
2
vendor/github.com/cs3org/reva/v2/pkg/storage/fs/posix/tree/tree.go
generated
vendored
2
vendor/github.com/cs3org/reva/v2/pkg/storage/fs/posix/tree/tree.go
generated
vendored
@@ -54,8 +54,6 @@ func init() {
|
||||
tracer = otel.Tracer("github.com/cs3org/reva/pkg/storage/utils/decomposedfs/tree")
|
||||
}
|
||||
|
||||
//go:generate make --no-print-directory -C ../../../../.. mockery NAME=Blobstore
|
||||
|
||||
// Blobstore defines an interface for storing blobs in a blobstore
|
||||
type Blobstore interface {
|
||||
Upload(node *node.Node, source string) error
|
||||
|
||||
2
vendor/github.com/cs3org/reva/v2/pkg/storage/registry/spaces/spaces.go
generated
vendored
2
vendor/github.com/cs3org/reva/v2/pkg/storage/registry/spaces/spaces.go
generated
vendored
@@ -48,8 +48,6 @@ import (
|
||||
"google.golang.org/grpc"
|
||||
)
|
||||
|
||||
//go:generate make --no-print-directory -C ../../../.. mockery NAME=StorageProviderClient
|
||||
|
||||
func init() {
|
||||
pkgregistry.Register("spaces", NewDefault)
|
||||
}
|
||||
|
||||
3
vendor/github.com/cs3org/reva/v2/pkg/storage/uploads.go
generated
vendored
3
vendor/github.com/cs3org/reva/v2/pkg/storage/uploads.go
generated
vendored
@@ -76,6 +76,9 @@ type UploadSession interface {
|
||||
|
||||
// Purge allows completely removing an upload. Should emit a PostprocessingFinished event with a Delete outcome
|
||||
Purge(ctx context.Context) error
|
||||
|
||||
// ScanData returns the scan data for the UploadSession
|
||||
ScanData() (string, time.Time)
|
||||
}
|
||||
|
||||
// UploadSessionFilter can be used to filter upload sessions
|
||||
|
||||
19
vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/decomposedfs.go
generated
vendored
19
vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/decomposedfs.go
generated
vendored
@@ -310,9 +310,16 @@ func (fs *Decomposedfs) Postprocessing(ch <-chan events.Event) {
|
||||
|
||||
now := time.Now()
|
||||
if failed {
|
||||
// propagate sizeDiff after failed postprocessing
|
||||
if err := fs.tp.Propagate(ctx, n, -session.SizeDiff()); err != nil {
|
||||
log.Error().Err(err).Str("uploadID", ev.UploadID).Msg("could not propagate tree size change")
|
||||
// if no other upload session is in progress (processing id != session id) or has finished (processing id == "")
|
||||
latestSession, err := n.ProcessingID(ctx)
|
||||
if err != nil {
|
||||
log.Error().Err(err).Str("node", n.ID).Str("uploadID", ev.UploadID).Msg("reading node for session failed")
|
||||
}
|
||||
if latestSession == session.ID() {
|
||||
// propagate reverted sizeDiff after failed postprocessing
|
||||
if err := fs.tp.Propagate(ctx, n, -session.SizeDiff()); err != nil {
|
||||
log.Error().Err(err).Str("uploadID", ev.UploadID).Msg("could not propagate tree size change")
|
||||
}
|
||||
}
|
||||
} else if p := getParent(); p != nil {
|
||||
// update parent tmtime to propagate etag change after successful postprocessing
|
||||
@@ -486,6 +493,12 @@ func (fs *Decomposedfs) Postprocessing(ch <-chan events.Event) {
|
||||
log.Error().Err(err).Interface("uploadID", ev.UploadID).Msg("Failed to get node after scan")
|
||||
continue
|
||||
}
|
||||
sublog := log.With().Str("spaceid", session.SpaceID()).Str("nodeid", session.NodeID()).Logger()
|
||||
|
||||
session.SetScanData(res.Description, res.Scandate)
|
||||
if err := session.Persist(ctx); err != nil {
|
||||
sublog.Error().Err(err).Msg("Failed to persist scan results")
|
||||
}
|
||||
}
|
||||
|
||||
if err := n.SetScanData(ctx, res.Description, res.Scandate); err != nil {
|
||||
|
||||
8
vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/node/node.go
generated
vendored
8
vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/node/node.go
generated
vendored
@@ -54,8 +54,6 @@ import (
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
)
|
||||
|
||||
//go:generate make --no-print-directory -C ../../../../.. mockery NAME=Tree
|
||||
|
||||
var tracer trace.Tracer
|
||||
|
||||
func init() {
|
||||
@@ -1278,6 +1276,12 @@ func (n *Node) IsProcessing(ctx context.Context) bool {
|
||||
return err == nil && strings.HasPrefix(v, ProcessingStatus)
|
||||
}
|
||||
|
||||
// ProcessingID returns the latest upload session id
|
||||
func (n *Node) ProcessingID(ctx context.Context) (string, error) {
|
||||
v, err := n.XattrString(ctx, prefixes.StatusPrefix)
|
||||
return strings.TrimPrefix(v, ProcessingStatus), err
|
||||
}
|
||||
|
||||
// IsSpaceRoot checks if the node is a space root
|
||||
func (n *Node) IsSpaceRoot(ctx context.Context) bool {
|
||||
_, err := n.Xattr(ctx, prefixes.SpaceNameAttr)
|
||||
|
||||
@@ -16,9 +16,6 @@ import (
|
||||
"google.golang.org/grpc"
|
||||
)
|
||||
|
||||
//go:generate make --no-print-directory -C ../../../../.. mockery NAME=PermissionsChecker
|
||||
//go:generate make --no-print-directory -C ../../../../.. mockery NAME=CS3PermissionsClient
|
||||
|
||||
var (
|
||||
tracer trace.Tracer
|
||||
)
|
||||
|
||||
2
vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/tree/tree.go
generated
vendored
2
vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/tree/tree.go
generated
vendored
@@ -53,8 +53,6 @@ func init() {
|
||||
tracer = otel.Tracer("github.com/cs3org/reva/pkg/storage/utils/decomposedfs/tree")
|
||||
}
|
||||
|
||||
//go:generate make --no-print-directory -C ../../../../.. mockery NAME=Blobstore
|
||||
|
||||
// Blobstore defines an interface for storing blobs in a blobstore
|
||||
type Blobstore interface {
|
||||
Upload(node *node.Node, source string) error
|
||||
|
||||
24
vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/upload/session.go
generated
vendored
24
vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/upload/session.go
generated
vendored
@@ -297,7 +297,8 @@ func (s *OcisSession) MTime() time.Time {
|
||||
|
||||
// IsProcessing returns true if all bytes have been received. The session then has entered postprocessing state.
|
||||
func (s *OcisSession) IsProcessing() bool {
|
||||
return s.info.Size == s.info.Offset
|
||||
// We might need a more sophisticated way to determine processing status soon
|
||||
return s.info.Size == s.info.Offset && s.info.MetaData["scanResult"] == ""
|
||||
}
|
||||
|
||||
// binPath returns the path to the file storing the binary data.
|
||||
@@ -305,6 +306,27 @@ func (s *OcisSession) binPath() string {
|
||||
return filepath.Join(s.store.root, "uploads", s.info.ID)
|
||||
}
|
||||
|
||||
// InitiatorID returns the id of the initiating client
|
||||
func (s *OcisSession) InitiatorID() string {
|
||||
return s.info.MetaData["initiatorid"]
|
||||
}
|
||||
|
||||
// SetScanData sets virus scan data to the upload session
|
||||
func (s *OcisSession) SetScanData(result string, date time.Time) {
|
||||
s.info.MetaData["scanResult"] = result
|
||||
s.info.MetaData["scanDate"] = date.Format(time.RFC3339)
|
||||
}
|
||||
|
||||
// ScanData returns the virus scan data
|
||||
func (s *OcisSession) ScanData() (string, time.Time) {
|
||||
date := s.info.MetaData["scanDate"]
|
||||
if date == "" {
|
||||
return "", time.Time{}
|
||||
}
|
||||
d, _ := time.Parse(time.RFC3339, date)
|
||||
return s.info.MetaData["scanResult"], d
|
||||
}
|
||||
|
||||
// sessionPath returns the path to the .info file storing the file's info.
|
||||
func sessionPath(root, id string) string {
|
||||
return filepath.Join(root, "uploads", id+".info")
|
||||
|
||||
10
vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/upload/store.go
generated
vendored
10
vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/upload/store.go
generated
vendored
@@ -205,7 +205,15 @@ func (store OcisStore) CreateNodeForUpload(session *OcisSession, initAttrs node.
|
||||
}
|
||||
|
||||
var f *lockedfile.File
|
||||
if session.NodeExists() {
|
||||
if session.NodeExists() { // TODO this is wrong. The node should be created when the upload starts, the revisions should be created independently of the node
|
||||
// we do not need to propagate a change when a node is created, only when the upload is ready.
|
||||
// that still creates problems for desktop clients because if another change causes propagation it will detects an empty file
|
||||
// so the first upload has to point to the first revision with the expected size. The file cannot be downloaded, but it can be overwritten (which will create a new revision and make the node reflect the latest revision)
|
||||
// any finished postprocessing will not affect the node metadata.
|
||||
// *thinking* but then initializing an upload will lock the file until the upload has finished. That sucks.
|
||||
// so we have to check if the node has been created meanwhile (well, only in case the upload does not know the nodeid ... or the NodeExists array that is checked by session.NodeExists())
|
||||
// FIXME look at the disk again to see if the file has been created in between, or just try initializing a new node and do the update existing node as a fallback. <- the latter!
|
||||
|
||||
f, err = store.updateExistingNode(ctx, session, n, session.SpaceID(), uint64(session.Size()))
|
||||
if f != nil {
|
||||
appctx.GetLogger(ctx).Info().Str("lockfile", f.Name()).Interface("err", err).Msg("got lock file from updateExistingNode")
|
||||
|
||||
27
vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/upload/upload.go
generated
vendored
27
vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/upload/upload.go
generated
vendored
@@ -276,14 +276,12 @@ func (session *OcisSession) ConcatUploads(_ context.Context, uploads []tusd.Uplo
|
||||
func (session *OcisSession) Finalize() (err error) {
|
||||
ctx, span := tracer.Start(session.Context(context.Background()), "Finalize")
|
||||
defer span.End()
|
||||
n, err := session.Node(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
revisionNode := &node.Node{SpaceID: session.SpaceID(), BlobID: session.ID(), Blobsize: session.Size()}
|
||||
|
||||
// upload the data to the blobstore
|
||||
_, subspan := tracer.Start(ctx, "WriteBlob")
|
||||
err = session.store.tp.WriteBlob(n, session.binPath())
|
||||
err = session.store.tp.WriteBlob(revisionNode, session.binPath())
|
||||
subspan.End()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to upload file to blobstore")
|
||||
@@ -316,12 +314,12 @@ func (session *OcisSession) Cleanup(revertNodeMetadata, cleanBin, cleanInfo bool
|
||||
ctx := session.Context(context.Background())
|
||||
|
||||
if revertNodeMetadata {
|
||||
n, err := session.Node(ctx)
|
||||
if err != nil {
|
||||
appctx.GetLogger(ctx).Error().Err(err).Str("node", n.ID).Str("sessionid", session.ID()).Msg("reading node for session failed")
|
||||
}
|
||||
if session.NodeExists() {
|
||||
p := session.info.MetaData["versionsPath"]
|
||||
n, err := session.Node(ctx)
|
||||
if err != nil {
|
||||
appctx.GetLogger(ctx).Error().Err(err).Str("sessionid", session.ID()).Msg("reading node for session failed")
|
||||
}
|
||||
if err := session.store.lu.CopyMetadata(ctx, p, n.InternalPath(), func(attributeName string, value []byte) (newValue []byte, copy bool) {
|
||||
return value, strings.HasPrefix(attributeName, prefixes.ChecksumPrefix) ||
|
||||
attributeName == prefixes.TypeAttr ||
|
||||
@@ -337,7 +335,16 @@ func (session *OcisSession) Cleanup(revertNodeMetadata, cleanBin, cleanInfo bool
|
||||
}
|
||||
|
||||
} else {
|
||||
session.removeNode(ctx)
|
||||
// if no other upload session is in progress (processing id != session id) or has finished (processing id == "")
|
||||
latestSession, err := n.ProcessingID(ctx)
|
||||
if err != nil {
|
||||
appctx.GetLogger(ctx).Error().Err(err).Str("node", n.ID).Str("sessionid", session.ID()).Msg("reading processingid for session failed")
|
||||
}
|
||||
if latestSession == session.ID() {
|
||||
// actually delete the node
|
||||
session.removeNode(ctx)
|
||||
}
|
||||
// FIXME else if the upload has become a revision, delete the revision, or if it is the last one, delete the node
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
2
vendor/github.com/cs3org/reva/v2/pkg/storage/utils/indexer/indexer.go
generated
vendored
2
vendor/github.com/cs3org/reva/v2/pkg/storage/utils/indexer/indexer.go
generated
vendored
@@ -36,8 +36,6 @@ import (
|
||||
"github.com/cs3org/reva/v2/pkg/storage/utils/sync"
|
||||
)
|
||||
|
||||
//go:generate make --no-print-directory -C ../../../.. mockery NAME=Indexer
|
||||
|
||||
// Indexer is a facade to configure and query over multiple indices.
|
||||
type Indexer interface {
|
||||
AddIndex(t interface{}, indexBy option.IndexBy, pkName, entityDirName, indexType string, bound *option.Bound, caseInsensitive bool) error
|
||||
|
||||
2
vendor/github.com/cs3org/reva/v2/pkg/storage/utils/metadata/storage.go
generated
vendored
2
vendor/github.com/cs3org/reva/v2/pkg/storage/utils/metadata/storage.go
generated
vendored
@@ -28,8 +28,6 @@ import (
|
||||
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
|
||||
)
|
||||
|
||||
//go:generate make --no-print-directory -C ../../../.. mockery NAME=Storage
|
||||
|
||||
// UploadRequest represents an upload request and its options
|
||||
type UploadRequest struct {
|
||||
Path string
|
||||
|
||||
345
vendor/github.com/cs3org/reva/v2/tests/cs3mocks/mocks/CollaborationAPIClient.go
generated
vendored
345
vendor/github.com/cs3org/reva/v2/tests/cs3mocks/mocks/CollaborationAPIClient.go
generated
vendored
@@ -16,7 +16,7 @@
|
||||
// granted to it by virtue of its status as an Intergovernmental Organization
|
||||
// or submit itself to any jurisdiction.
|
||||
|
||||
// Code generated by mockery v2.22.1. DO NOT EDIT.
|
||||
// Code generated by mockery v2.40.2. DO NOT EDIT.
|
||||
|
||||
package mocks
|
||||
|
||||
@@ -35,6 +35,14 @@ type CollaborationAPIClient struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
type CollaborationAPIClient_Expecter struct {
|
||||
mock *mock.Mock
|
||||
}
|
||||
|
||||
func (_m *CollaborationAPIClient) EXPECT() *CollaborationAPIClient_Expecter {
|
||||
return &CollaborationAPIClient_Expecter{mock: &_m.Mock}
|
||||
}
|
||||
|
||||
// CreateShare provides a mock function with given fields: ctx, in, opts
|
||||
func (_m *CollaborationAPIClient) CreateShare(ctx context.Context, in *collaborationv1beta1.CreateShareRequest, opts ...grpc.CallOption) (*collaborationv1beta1.CreateShareResponse, error) {
|
||||
_va := make([]interface{}, len(opts))
|
||||
@@ -46,6 +54,10 @@ func (_m *CollaborationAPIClient) CreateShare(ctx context.Context, in *collabora
|
||||
_ca = append(_ca, _va...)
|
||||
ret := _m.Called(_ca...)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for CreateShare")
|
||||
}
|
||||
|
||||
var r0 *collaborationv1beta1.CreateShareResponse
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *collaborationv1beta1.CreateShareRequest, ...grpc.CallOption) (*collaborationv1beta1.CreateShareResponse, error)); ok {
|
||||
@@ -68,6 +80,43 @@ func (_m *CollaborationAPIClient) CreateShare(ctx context.Context, in *collabora
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// CollaborationAPIClient_CreateShare_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'CreateShare'
|
||||
type CollaborationAPIClient_CreateShare_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// CreateShare is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - in *collaborationv1beta1.CreateShareRequest
|
||||
// - opts ...grpc.CallOption
|
||||
func (_e *CollaborationAPIClient_Expecter) CreateShare(ctx interface{}, in interface{}, opts ...interface{}) *CollaborationAPIClient_CreateShare_Call {
|
||||
return &CollaborationAPIClient_CreateShare_Call{Call: _e.mock.On("CreateShare",
|
||||
append([]interface{}{ctx, in}, opts...)...)}
|
||||
}
|
||||
|
||||
func (_c *CollaborationAPIClient_CreateShare_Call) Run(run func(ctx context.Context, in *collaborationv1beta1.CreateShareRequest, opts ...grpc.CallOption)) *CollaborationAPIClient_CreateShare_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
variadicArgs := make([]grpc.CallOption, len(args)-2)
|
||||
for i, a := range args[2:] {
|
||||
if a != nil {
|
||||
variadicArgs[i] = a.(grpc.CallOption)
|
||||
}
|
||||
}
|
||||
run(args[0].(context.Context), args[1].(*collaborationv1beta1.CreateShareRequest), variadicArgs...)
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *CollaborationAPIClient_CreateShare_Call) Return(_a0 *collaborationv1beta1.CreateShareResponse, _a1 error) *CollaborationAPIClient_CreateShare_Call {
|
||||
_c.Call.Return(_a0, _a1)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *CollaborationAPIClient_CreateShare_Call) RunAndReturn(run func(context.Context, *collaborationv1beta1.CreateShareRequest, ...grpc.CallOption) (*collaborationv1beta1.CreateShareResponse, error)) *CollaborationAPIClient_CreateShare_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// GetReceivedShare provides a mock function with given fields: ctx, in, opts
|
||||
func (_m *CollaborationAPIClient) GetReceivedShare(ctx context.Context, in *collaborationv1beta1.GetReceivedShareRequest, opts ...grpc.CallOption) (*collaborationv1beta1.GetReceivedShareResponse, error) {
|
||||
_va := make([]interface{}, len(opts))
|
||||
@@ -79,6 +128,10 @@ func (_m *CollaborationAPIClient) GetReceivedShare(ctx context.Context, in *coll
|
||||
_ca = append(_ca, _va...)
|
||||
ret := _m.Called(_ca...)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for GetReceivedShare")
|
||||
}
|
||||
|
||||
var r0 *collaborationv1beta1.GetReceivedShareResponse
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *collaborationv1beta1.GetReceivedShareRequest, ...grpc.CallOption) (*collaborationv1beta1.GetReceivedShareResponse, error)); ok {
|
||||
@@ -101,6 +154,43 @@ func (_m *CollaborationAPIClient) GetReceivedShare(ctx context.Context, in *coll
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// CollaborationAPIClient_GetReceivedShare_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetReceivedShare'
|
||||
type CollaborationAPIClient_GetReceivedShare_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// GetReceivedShare is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - in *collaborationv1beta1.GetReceivedShareRequest
|
||||
// - opts ...grpc.CallOption
|
||||
func (_e *CollaborationAPIClient_Expecter) GetReceivedShare(ctx interface{}, in interface{}, opts ...interface{}) *CollaborationAPIClient_GetReceivedShare_Call {
|
||||
return &CollaborationAPIClient_GetReceivedShare_Call{Call: _e.mock.On("GetReceivedShare",
|
||||
append([]interface{}{ctx, in}, opts...)...)}
|
||||
}
|
||||
|
||||
func (_c *CollaborationAPIClient_GetReceivedShare_Call) Run(run func(ctx context.Context, in *collaborationv1beta1.GetReceivedShareRequest, opts ...grpc.CallOption)) *CollaborationAPIClient_GetReceivedShare_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
variadicArgs := make([]grpc.CallOption, len(args)-2)
|
||||
for i, a := range args[2:] {
|
||||
if a != nil {
|
||||
variadicArgs[i] = a.(grpc.CallOption)
|
||||
}
|
||||
}
|
||||
run(args[0].(context.Context), args[1].(*collaborationv1beta1.GetReceivedShareRequest), variadicArgs...)
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *CollaborationAPIClient_GetReceivedShare_Call) Return(_a0 *collaborationv1beta1.GetReceivedShareResponse, _a1 error) *CollaborationAPIClient_GetReceivedShare_Call {
|
||||
_c.Call.Return(_a0, _a1)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *CollaborationAPIClient_GetReceivedShare_Call) RunAndReturn(run func(context.Context, *collaborationv1beta1.GetReceivedShareRequest, ...grpc.CallOption) (*collaborationv1beta1.GetReceivedShareResponse, error)) *CollaborationAPIClient_GetReceivedShare_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// GetShare provides a mock function with given fields: ctx, in, opts
|
||||
func (_m *CollaborationAPIClient) GetShare(ctx context.Context, in *collaborationv1beta1.GetShareRequest, opts ...grpc.CallOption) (*collaborationv1beta1.GetShareResponse, error) {
|
||||
_va := make([]interface{}, len(opts))
|
||||
@@ -112,6 +202,10 @@ func (_m *CollaborationAPIClient) GetShare(ctx context.Context, in *collaboratio
|
||||
_ca = append(_ca, _va...)
|
||||
ret := _m.Called(_ca...)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for GetShare")
|
||||
}
|
||||
|
||||
var r0 *collaborationv1beta1.GetShareResponse
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *collaborationv1beta1.GetShareRequest, ...grpc.CallOption) (*collaborationv1beta1.GetShareResponse, error)); ok {
|
||||
@@ -134,6 +228,43 @@ func (_m *CollaborationAPIClient) GetShare(ctx context.Context, in *collaboratio
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// CollaborationAPIClient_GetShare_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetShare'
|
||||
type CollaborationAPIClient_GetShare_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// GetShare is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - in *collaborationv1beta1.GetShareRequest
|
||||
// - opts ...grpc.CallOption
|
||||
func (_e *CollaborationAPIClient_Expecter) GetShare(ctx interface{}, in interface{}, opts ...interface{}) *CollaborationAPIClient_GetShare_Call {
|
||||
return &CollaborationAPIClient_GetShare_Call{Call: _e.mock.On("GetShare",
|
||||
append([]interface{}{ctx, in}, opts...)...)}
|
||||
}
|
||||
|
||||
func (_c *CollaborationAPIClient_GetShare_Call) Run(run func(ctx context.Context, in *collaborationv1beta1.GetShareRequest, opts ...grpc.CallOption)) *CollaborationAPIClient_GetShare_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
variadicArgs := make([]grpc.CallOption, len(args)-2)
|
||||
for i, a := range args[2:] {
|
||||
if a != nil {
|
||||
variadicArgs[i] = a.(grpc.CallOption)
|
||||
}
|
||||
}
|
||||
run(args[0].(context.Context), args[1].(*collaborationv1beta1.GetShareRequest), variadicArgs...)
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *CollaborationAPIClient_GetShare_Call) Return(_a0 *collaborationv1beta1.GetShareResponse, _a1 error) *CollaborationAPIClient_GetShare_Call {
|
||||
_c.Call.Return(_a0, _a1)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *CollaborationAPIClient_GetShare_Call) RunAndReturn(run func(context.Context, *collaborationv1beta1.GetShareRequest, ...grpc.CallOption) (*collaborationv1beta1.GetShareResponse, error)) *CollaborationAPIClient_GetShare_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// ListReceivedShares provides a mock function with given fields: ctx, in, opts
|
||||
func (_m *CollaborationAPIClient) ListReceivedShares(ctx context.Context, in *collaborationv1beta1.ListReceivedSharesRequest, opts ...grpc.CallOption) (*collaborationv1beta1.ListReceivedSharesResponse, error) {
|
||||
_va := make([]interface{}, len(opts))
|
||||
@@ -145,6 +276,10 @@ func (_m *CollaborationAPIClient) ListReceivedShares(ctx context.Context, in *co
|
||||
_ca = append(_ca, _va...)
|
||||
ret := _m.Called(_ca...)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for ListReceivedShares")
|
||||
}
|
||||
|
||||
var r0 *collaborationv1beta1.ListReceivedSharesResponse
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *collaborationv1beta1.ListReceivedSharesRequest, ...grpc.CallOption) (*collaborationv1beta1.ListReceivedSharesResponse, error)); ok {
|
||||
@@ -167,6 +302,43 @@ func (_m *CollaborationAPIClient) ListReceivedShares(ctx context.Context, in *co
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// CollaborationAPIClient_ListReceivedShares_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ListReceivedShares'
|
||||
type CollaborationAPIClient_ListReceivedShares_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// ListReceivedShares is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - in *collaborationv1beta1.ListReceivedSharesRequest
|
||||
// - opts ...grpc.CallOption
|
||||
func (_e *CollaborationAPIClient_Expecter) ListReceivedShares(ctx interface{}, in interface{}, opts ...interface{}) *CollaborationAPIClient_ListReceivedShares_Call {
|
||||
return &CollaborationAPIClient_ListReceivedShares_Call{Call: _e.mock.On("ListReceivedShares",
|
||||
append([]interface{}{ctx, in}, opts...)...)}
|
||||
}
|
||||
|
||||
func (_c *CollaborationAPIClient_ListReceivedShares_Call) Run(run func(ctx context.Context, in *collaborationv1beta1.ListReceivedSharesRequest, opts ...grpc.CallOption)) *CollaborationAPIClient_ListReceivedShares_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
variadicArgs := make([]grpc.CallOption, len(args)-2)
|
||||
for i, a := range args[2:] {
|
||||
if a != nil {
|
||||
variadicArgs[i] = a.(grpc.CallOption)
|
||||
}
|
||||
}
|
||||
run(args[0].(context.Context), args[1].(*collaborationv1beta1.ListReceivedSharesRequest), variadicArgs...)
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *CollaborationAPIClient_ListReceivedShares_Call) Return(_a0 *collaborationv1beta1.ListReceivedSharesResponse, _a1 error) *CollaborationAPIClient_ListReceivedShares_Call {
|
||||
_c.Call.Return(_a0, _a1)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *CollaborationAPIClient_ListReceivedShares_Call) RunAndReturn(run func(context.Context, *collaborationv1beta1.ListReceivedSharesRequest, ...grpc.CallOption) (*collaborationv1beta1.ListReceivedSharesResponse, error)) *CollaborationAPIClient_ListReceivedShares_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// ListShares provides a mock function with given fields: ctx, in, opts
|
||||
func (_m *CollaborationAPIClient) ListShares(ctx context.Context, in *collaborationv1beta1.ListSharesRequest, opts ...grpc.CallOption) (*collaborationv1beta1.ListSharesResponse, error) {
|
||||
_va := make([]interface{}, len(opts))
|
||||
@@ -178,6 +350,10 @@ func (_m *CollaborationAPIClient) ListShares(ctx context.Context, in *collaborat
|
||||
_ca = append(_ca, _va...)
|
||||
ret := _m.Called(_ca...)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for ListShares")
|
||||
}
|
||||
|
||||
var r0 *collaborationv1beta1.ListSharesResponse
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *collaborationv1beta1.ListSharesRequest, ...grpc.CallOption) (*collaborationv1beta1.ListSharesResponse, error)); ok {
|
||||
@@ -200,6 +376,43 @@ func (_m *CollaborationAPIClient) ListShares(ctx context.Context, in *collaborat
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// CollaborationAPIClient_ListShares_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ListShares'
|
||||
type CollaborationAPIClient_ListShares_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// ListShares is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - in *collaborationv1beta1.ListSharesRequest
|
||||
// - opts ...grpc.CallOption
|
||||
func (_e *CollaborationAPIClient_Expecter) ListShares(ctx interface{}, in interface{}, opts ...interface{}) *CollaborationAPIClient_ListShares_Call {
|
||||
return &CollaborationAPIClient_ListShares_Call{Call: _e.mock.On("ListShares",
|
||||
append([]interface{}{ctx, in}, opts...)...)}
|
||||
}
|
||||
|
||||
func (_c *CollaborationAPIClient_ListShares_Call) Run(run func(ctx context.Context, in *collaborationv1beta1.ListSharesRequest, opts ...grpc.CallOption)) *CollaborationAPIClient_ListShares_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
variadicArgs := make([]grpc.CallOption, len(args)-2)
|
||||
for i, a := range args[2:] {
|
||||
if a != nil {
|
||||
variadicArgs[i] = a.(grpc.CallOption)
|
||||
}
|
||||
}
|
||||
run(args[0].(context.Context), args[1].(*collaborationv1beta1.ListSharesRequest), variadicArgs...)
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *CollaborationAPIClient_ListShares_Call) Return(_a0 *collaborationv1beta1.ListSharesResponse, _a1 error) *CollaborationAPIClient_ListShares_Call {
|
||||
_c.Call.Return(_a0, _a1)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *CollaborationAPIClient_ListShares_Call) RunAndReturn(run func(context.Context, *collaborationv1beta1.ListSharesRequest, ...grpc.CallOption) (*collaborationv1beta1.ListSharesResponse, error)) *CollaborationAPIClient_ListShares_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// RemoveShare provides a mock function with given fields: ctx, in, opts
|
||||
func (_m *CollaborationAPIClient) RemoveShare(ctx context.Context, in *collaborationv1beta1.RemoveShareRequest, opts ...grpc.CallOption) (*collaborationv1beta1.RemoveShareResponse, error) {
|
||||
_va := make([]interface{}, len(opts))
|
||||
@@ -211,6 +424,10 @@ func (_m *CollaborationAPIClient) RemoveShare(ctx context.Context, in *collabora
|
||||
_ca = append(_ca, _va...)
|
||||
ret := _m.Called(_ca...)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for RemoveShare")
|
||||
}
|
||||
|
||||
var r0 *collaborationv1beta1.RemoveShareResponse
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *collaborationv1beta1.RemoveShareRequest, ...grpc.CallOption) (*collaborationv1beta1.RemoveShareResponse, error)); ok {
|
||||
@@ -233,6 +450,43 @@ func (_m *CollaborationAPIClient) RemoveShare(ctx context.Context, in *collabora
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// CollaborationAPIClient_RemoveShare_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'RemoveShare'
|
||||
type CollaborationAPIClient_RemoveShare_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// RemoveShare is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - in *collaborationv1beta1.RemoveShareRequest
|
||||
// - opts ...grpc.CallOption
|
||||
func (_e *CollaborationAPIClient_Expecter) RemoveShare(ctx interface{}, in interface{}, opts ...interface{}) *CollaborationAPIClient_RemoveShare_Call {
|
||||
return &CollaborationAPIClient_RemoveShare_Call{Call: _e.mock.On("RemoveShare",
|
||||
append([]interface{}{ctx, in}, opts...)...)}
|
||||
}
|
||||
|
||||
func (_c *CollaborationAPIClient_RemoveShare_Call) Run(run func(ctx context.Context, in *collaborationv1beta1.RemoveShareRequest, opts ...grpc.CallOption)) *CollaborationAPIClient_RemoveShare_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
variadicArgs := make([]grpc.CallOption, len(args)-2)
|
||||
for i, a := range args[2:] {
|
||||
if a != nil {
|
||||
variadicArgs[i] = a.(grpc.CallOption)
|
||||
}
|
||||
}
|
||||
run(args[0].(context.Context), args[1].(*collaborationv1beta1.RemoveShareRequest), variadicArgs...)
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *CollaborationAPIClient_RemoveShare_Call) Return(_a0 *collaborationv1beta1.RemoveShareResponse, _a1 error) *CollaborationAPIClient_RemoveShare_Call {
|
||||
_c.Call.Return(_a0, _a1)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *CollaborationAPIClient_RemoveShare_Call) RunAndReturn(run func(context.Context, *collaborationv1beta1.RemoveShareRequest, ...grpc.CallOption) (*collaborationv1beta1.RemoveShareResponse, error)) *CollaborationAPIClient_RemoveShare_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// UpdateReceivedShare provides a mock function with given fields: ctx, in, opts
|
||||
func (_m *CollaborationAPIClient) UpdateReceivedShare(ctx context.Context, in *collaborationv1beta1.UpdateReceivedShareRequest, opts ...grpc.CallOption) (*collaborationv1beta1.UpdateReceivedShareResponse, error) {
|
||||
_va := make([]interface{}, len(opts))
|
||||
@@ -244,6 +498,10 @@ func (_m *CollaborationAPIClient) UpdateReceivedShare(ctx context.Context, in *c
|
||||
_ca = append(_ca, _va...)
|
||||
ret := _m.Called(_ca...)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for UpdateReceivedShare")
|
||||
}
|
||||
|
||||
var r0 *collaborationv1beta1.UpdateReceivedShareResponse
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *collaborationv1beta1.UpdateReceivedShareRequest, ...grpc.CallOption) (*collaborationv1beta1.UpdateReceivedShareResponse, error)); ok {
|
||||
@@ -266,6 +524,43 @@ func (_m *CollaborationAPIClient) UpdateReceivedShare(ctx context.Context, in *c
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// CollaborationAPIClient_UpdateReceivedShare_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UpdateReceivedShare'
|
||||
type CollaborationAPIClient_UpdateReceivedShare_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// UpdateReceivedShare is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - in *collaborationv1beta1.UpdateReceivedShareRequest
|
||||
// - opts ...grpc.CallOption
|
||||
func (_e *CollaborationAPIClient_Expecter) UpdateReceivedShare(ctx interface{}, in interface{}, opts ...interface{}) *CollaborationAPIClient_UpdateReceivedShare_Call {
|
||||
return &CollaborationAPIClient_UpdateReceivedShare_Call{Call: _e.mock.On("UpdateReceivedShare",
|
||||
append([]interface{}{ctx, in}, opts...)...)}
|
||||
}
|
||||
|
||||
func (_c *CollaborationAPIClient_UpdateReceivedShare_Call) Run(run func(ctx context.Context, in *collaborationv1beta1.UpdateReceivedShareRequest, opts ...grpc.CallOption)) *CollaborationAPIClient_UpdateReceivedShare_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
variadicArgs := make([]grpc.CallOption, len(args)-2)
|
||||
for i, a := range args[2:] {
|
||||
if a != nil {
|
||||
variadicArgs[i] = a.(grpc.CallOption)
|
||||
}
|
||||
}
|
||||
run(args[0].(context.Context), args[1].(*collaborationv1beta1.UpdateReceivedShareRequest), variadicArgs...)
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *CollaborationAPIClient_UpdateReceivedShare_Call) Return(_a0 *collaborationv1beta1.UpdateReceivedShareResponse, _a1 error) *CollaborationAPIClient_UpdateReceivedShare_Call {
|
||||
_c.Call.Return(_a0, _a1)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *CollaborationAPIClient_UpdateReceivedShare_Call) RunAndReturn(run func(context.Context, *collaborationv1beta1.UpdateReceivedShareRequest, ...grpc.CallOption) (*collaborationv1beta1.UpdateReceivedShareResponse, error)) *CollaborationAPIClient_UpdateReceivedShare_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// UpdateShare provides a mock function with given fields: ctx, in, opts
|
||||
func (_m *CollaborationAPIClient) UpdateShare(ctx context.Context, in *collaborationv1beta1.UpdateShareRequest, opts ...grpc.CallOption) (*collaborationv1beta1.UpdateShareResponse, error) {
|
||||
_va := make([]interface{}, len(opts))
|
||||
@@ -277,6 +572,10 @@ func (_m *CollaborationAPIClient) UpdateShare(ctx context.Context, in *collabora
|
||||
_ca = append(_ca, _va...)
|
||||
ret := _m.Called(_ca...)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for UpdateShare")
|
||||
}
|
||||
|
||||
var r0 *collaborationv1beta1.UpdateShareResponse
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, *collaborationv1beta1.UpdateShareRequest, ...grpc.CallOption) (*collaborationv1beta1.UpdateShareResponse, error)); ok {
|
||||
@@ -299,13 +598,49 @@ func (_m *CollaborationAPIClient) UpdateShare(ctx context.Context, in *collabora
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
type mockConstructorTestingTNewCollaborationAPIClient interface {
|
||||
mock.TestingT
|
||||
Cleanup(func())
|
||||
// CollaborationAPIClient_UpdateShare_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'UpdateShare'
|
||||
type CollaborationAPIClient_UpdateShare_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// UpdateShare is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - in *collaborationv1beta1.UpdateShareRequest
|
||||
// - opts ...grpc.CallOption
|
||||
func (_e *CollaborationAPIClient_Expecter) UpdateShare(ctx interface{}, in interface{}, opts ...interface{}) *CollaborationAPIClient_UpdateShare_Call {
|
||||
return &CollaborationAPIClient_UpdateShare_Call{Call: _e.mock.On("UpdateShare",
|
||||
append([]interface{}{ctx, in}, opts...)...)}
|
||||
}
|
||||
|
||||
func (_c *CollaborationAPIClient_UpdateShare_Call) Run(run func(ctx context.Context, in *collaborationv1beta1.UpdateShareRequest, opts ...grpc.CallOption)) *CollaborationAPIClient_UpdateShare_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
variadicArgs := make([]grpc.CallOption, len(args)-2)
|
||||
for i, a := range args[2:] {
|
||||
if a != nil {
|
||||
variadicArgs[i] = a.(grpc.CallOption)
|
||||
}
|
||||
}
|
||||
run(args[0].(context.Context), args[1].(*collaborationv1beta1.UpdateShareRequest), variadicArgs...)
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *CollaborationAPIClient_UpdateShare_Call) Return(_a0 *collaborationv1beta1.UpdateShareResponse, _a1 error) *CollaborationAPIClient_UpdateShare_Call {
|
||||
_c.Call.Return(_a0, _a1)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *CollaborationAPIClient_UpdateShare_Call) RunAndReturn(run func(context.Context, *collaborationv1beta1.UpdateShareRequest, ...grpc.CallOption) (*collaborationv1beta1.UpdateShareResponse, error)) *CollaborationAPIClient_UpdateShare_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// NewCollaborationAPIClient creates a new instance of CollaborationAPIClient. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
|
||||
func NewCollaborationAPIClient(t mockConstructorTestingTNewCollaborationAPIClient) *CollaborationAPIClient {
|
||||
// The first argument is typically a *testing.T value.
|
||||
func NewCollaborationAPIClient(t interface {
|
||||
mock.TestingT
|
||||
Cleanup(func())
|
||||
}) *CollaborationAPIClient {
|
||||
mock := &CollaborationAPIClient{}
|
||||
mock.Mock.Test(t)
|
||||
|
||||
|
||||
3994
vendor/github.com/cs3org/reva/v2/tests/cs3mocks/mocks/GatewayAPIClient.go
generated
vendored
3994
vendor/github.com/cs3org/reva/v2/tests/cs3mocks/mocks/GatewayAPIClient.go
generated
vendored
File diff suppressed because it is too large
Load Diff
462
vendor/github.com/kovidgoyal/imaging/README.md
generated
vendored
462
vendor/github.com/kovidgoyal/imaging/README.md
generated
vendored
@@ -1,231 +1,231 @@
|
||||
# Imaging
|
||||
|
||||
Package imaging provides basic image processing functions (resize, rotate, crop, brightness/contrast adjustments, etc.).
|
||||
|
||||
All the image processing functions provided by the package accept any image type that implements `image.Image` interface
|
||||
as an input, and return a new image of `*image.NRGBA` type (32bit RGBA colors, non-premultiplied alpha).
|
||||
|
||||
## Installation
|
||||
|
||||
go get -u github.com/kovidgoyal/imaging
|
||||
|
||||
## Documentation
|
||||
|
||||
https://pkg.go.dev/github.com/kovidgoyal/imaging
|
||||
|
||||
## Usage examples
|
||||
|
||||
A few usage examples can be found below. See the documentation for the full list of supported functions.
|
||||
|
||||
### Image resizing
|
||||
|
||||
```go
|
||||
// Resize srcImage to size = 128x128px using the Lanczos filter.
|
||||
dstImage128 := imaging.Resize(srcImage, 128, 128, imaging.Lanczos)
|
||||
|
||||
// Resize srcImage to width = 800px preserving the aspect ratio.
|
||||
dstImage800 := imaging.Resize(srcImage, 800, 0, imaging.Lanczos)
|
||||
|
||||
// Scale down srcImage to fit the 800x600px bounding box.
|
||||
dstImageFit := imaging.Fit(srcImage, 800, 600, imaging.Lanczos)
|
||||
|
||||
// Resize and crop the srcImage to fill the 100x100px area.
|
||||
dstImageFill := imaging.Fill(srcImage, 100, 100, imaging.Center, imaging.Lanczos)
|
||||
```
|
||||
|
||||
Imaging supports image resizing using various resampling filters. The most notable ones:
|
||||
- `Lanczos` - A high-quality resampling filter for photographic images yielding sharp results.
|
||||
- `CatmullRom` - A sharp cubic filter that is faster than Lanczos filter while providing similar results.
|
||||
- `MitchellNetravali` - A cubic filter that produces smoother results with less ringing artifacts than CatmullRom.
|
||||
- `Linear` - Bilinear resampling filter, produces smooth output. Faster than cubic filters.
|
||||
- `Box` - Simple and fast averaging filter appropriate for downscaling. When upscaling it's similar to NearestNeighbor.
|
||||
- `NearestNeighbor` - Fastest resampling filter, no antialiasing.
|
||||
|
||||
The full list of supported filters: NearestNeighbor, Box, Linear, Hermite, MitchellNetravali, CatmullRom, BSpline, Gaussian, Lanczos, Hann, Hamming, Blackman, Bartlett, Welch, Cosine. Custom filters can be created using ResampleFilter struct.
|
||||
|
||||
**Resampling filters comparison**
|
||||
|
||||
Original image:
|
||||
|
||||

|
||||
|
||||
The same image resized from 600x400px to 150x100px using different resampling filters.
|
||||
From faster (lower quality) to slower (higher quality):
|
||||
|
||||
Filter | Resize result
|
||||
--------------------------|---------------------------------------------
|
||||
`imaging.NearestNeighbor` | 
|
||||
`imaging.Linear` | 
|
||||
`imaging.CatmullRom` | 
|
||||
`imaging.Lanczos` | 
|
||||
|
||||
|
||||
### Gaussian Blur
|
||||
|
||||
```go
|
||||
dstImage := imaging.Blur(srcImage, 0.5)
|
||||
```
|
||||
|
||||
Sigma parameter allows to control the strength of the blurring effect.
|
||||
|
||||
Original image | Sigma = 0.5 | Sigma = 1.5
|
||||
-----------------------------------|----------------------------------------|---------------------------------------
|
||||
 |  | 
|
||||
|
||||
### Sharpening
|
||||
|
||||
```go
|
||||
dstImage := imaging.Sharpen(srcImage, 0.5)
|
||||
```
|
||||
|
||||
`Sharpen` uses gaussian function internally. Sigma parameter allows to control the strength of the sharpening effect.
|
||||
|
||||
Original image | Sigma = 0.5 | Sigma = 1.5
|
||||
-----------------------------------|-------------------------------------------|------------------------------------------
|
||||
 |  | 
|
||||
|
||||
### Gamma correction
|
||||
|
||||
```go
|
||||
dstImage := imaging.AdjustGamma(srcImage, 0.75)
|
||||
```
|
||||
|
||||
Original image | Gamma = 0.75 | Gamma = 1.25
|
||||
-----------------------------------|------------------------------------------|-----------------------------------------
|
||||
 |  | 
|
||||
|
||||
### Contrast adjustment
|
||||
|
||||
```go
|
||||
dstImage := imaging.AdjustContrast(srcImage, 20)
|
||||
```
|
||||
|
||||
Original image | Contrast = 15 | Contrast = -15
|
||||
-----------------------------------|--------------------------------------------|-------------------------------------------
|
||||
 |  | 
|
||||
|
||||
### Brightness adjustment
|
||||
|
||||
```go
|
||||
dstImage := imaging.AdjustBrightness(srcImage, 20)
|
||||
```
|
||||
|
||||
Original image | Brightness = 10 | Brightness = -10
|
||||
-----------------------------------|----------------------------------------------|---------------------------------------------
|
||||
 |  | 
|
||||
|
||||
### Saturation adjustment
|
||||
|
||||
```go
|
||||
dstImage := imaging.AdjustSaturation(srcImage, 20)
|
||||
```
|
||||
|
||||
Original image | Saturation = 30 | Saturation = -30
|
||||
-----------------------------------|----------------------------------------------|---------------------------------------------
|
||||
 |  | 
|
||||
|
||||
### Hue adjustment
|
||||
|
||||
```go
|
||||
dstImage := imaging.AdjustHue(srcImage, 20)
|
||||
```
|
||||
|
||||
Original image | Hue = 60 | Hue = -60
|
||||
-----------------------------------|----------------------------------------------|---------------------------------------------
|
||||
 |  | 
|
||||
|
||||
## FAQ
|
||||
|
||||
### Incorrect image orientation after processing (e.g. an image appears rotated after resizing)
|
||||
|
||||
Most probably, the given image contains the EXIF orientation tag.
|
||||
The standard `image/*` packages do not support loading and saving
|
||||
this kind of information. To fix the issue, try opening images with
|
||||
the `AutoOrientation` decode option. If this option is set to `true`,
|
||||
the image orientation is changed after decoding, according to the
|
||||
orientation tag (if present). Here's the example:
|
||||
|
||||
```go
|
||||
img, err := imaging.Open("test.jpg", imaging.AutoOrientation(true))
|
||||
```
|
||||
|
||||
### What's the difference between `imaging` and `gift` packages?
|
||||
|
||||
[imaging](https://github.com/kovidgoyal/imaging)
|
||||
is designed to be a lightweight and simple image manipulation package.
|
||||
It provides basic image processing functions and a few helper functions
|
||||
such as `Open` and `Save`. It consistently returns *image.NRGBA image
|
||||
type (8 bits per channel, RGBA).
|
||||
|
||||
[gift](https://github.com/disintegration/gift)
|
||||
supports more advanced image processing, for example, sRGB/Linear color
|
||||
space conversions. It also supports different output image types
|
||||
(e.g. 16 bits per channel) and provides easy-to-use API for chaining
|
||||
multiple processing steps together.
|
||||
|
||||
## Example code
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"image"
|
||||
"image/color"
|
||||
"log"
|
||||
|
||||
"github.com/kovidgoyal/imaging"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Open a test image.
|
||||
src, err := imaging.Open("testdata/flowers.png")
|
||||
if err != nil {
|
||||
log.Fatalf("failed to open image: %v", err)
|
||||
}
|
||||
|
||||
// Crop the original image to 300x300px size using the center anchor.
|
||||
src = imaging.CropAnchor(src, 300, 300, imaging.Center)
|
||||
|
||||
// Resize the cropped image to width = 200px preserving the aspect ratio.
|
||||
src = imaging.Resize(src, 200, 0, imaging.Lanczos)
|
||||
|
||||
// Create a blurred version of the image.
|
||||
img1 := imaging.Blur(src, 5)
|
||||
|
||||
// Create a grayscale version of the image with higher contrast and sharpness.
|
||||
img2 := imaging.Grayscale(src)
|
||||
img2 = imaging.AdjustContrast(img2, 20)
|
||||
img2 = imaging.Sharpen(img2, 2)
|
||||
|
||||
// Create an inverted version of the image.
|
||||
img3 := imaging.Invert(src)
|
||||
|
||||
// Create an embossed version of the image using a convolution filter.
|
||||
img4 := imaging.Convolve3x3(
|
||||
src,
|
||||
[9]float64{
|
||||
-1, -1, 0,
|
||||
-1, 1, 1,
|
||||
0, 1, 1,
|
||||
},
|
||||
nil,
|
||||
)
|
||||
|
||||
// Create a new image and paste the four produced images into it.
|
||||
dst := imaging.New(400, 400, color.NRGBA{0, 0, 0, 0})
|
||||
dst = imaging.Paste(dst, img1, image.Pt(0, 0))
|
||||
dst = imaging.Paste(dst, img2, image.Pt(0, 200))
|
||||
dst = imaging.Paste(dst, img3, image.Pt(200, 0))
|
||||
dst = imaging.Paste(dst, img4, image.Pt(200, 200))
|
||||
|
||||
// Save the resulting image as JPEG.
|
||||
err = imaging.Save(dst, "testdata/out_example.jpg")
|
||||
if err != nil {
|
||||
log.Fatalf("failed to save image: %v", err)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||

|
||||
# Imaging
|
||||
|
||||
Package imaging provides basic image processing functions (resize, rotate, crop, brightness/contrast adjustments, etc.).
|
||||
|
||||
All the image processing functions provided by the package accept any image type that implements `image.Image` interface
|
||||
as an input, and return a new image of `*image.NRGBA` type (32bit RGBA colors, non-premultiplied alpha).
|
||||
|
||||
## Installation
|
||||
|
||||
go get -u github.com/kovidgoyal/imaging
|
||||
|
||||
## Documentation
|
||||
|
||||
https://pkg.go.dev/github.com/kovidgoyal/imaging
|
||||
|
||||
## Usage examples
|
||||
|
||||
A few usage examples can be found below. See the documentation for the full list of supported functions.
|
||||
|
||||
### Image resizing
|
||||
|
||||
```go
|
||||
// Resize srcImage to size = 128x128px using the Lanczos filter.
|
||||
dstImage128 := imaging.Resize(srcImage, 128, 128, imaging.Lanczos)
|
||||
|
||||
// Resize srcImage to width = 800px preserving the aspect ratio.
|
||||
dstImage800 := imaging.Resize(srcImage, 800, 0, imaging.Lanczos)
|
||||
|
||||
// Scale down srcImage to fit the 800x600px bounding box.
|
||||
dstImageFit := imaging.Fit(srcImage, 800, 600, imaging.Lanczos)
|
||||
|
||||
// Resize and crop the srcImage to fill the 100x100px area.
|
||||
dstImageFill := imaging.Fill(srcImage, 100, 100, imaging.Center, imaging.Lanczos)
|
||||
```
|
||||
|
||||
Imaging supports image resizing using various resampling filters. The most notable ones:
|
||||
- `Lanczos` - A high-quality resampling filter for photographic images yielding sharp results.
|
||||
- `CatmullRom` - A sharp cubic filter that is faster than Lanczos filter while providing similar results.
|
||||
- `MitchellNetravali` - A cubic filter that produces smoother results with less ringing artifacts than CatmullRom.
|
||||
- `Linear` - Bilinear resampling filter, produces smooth output. Faster than cubic filters.
|
||||
- `Box` - Simple and fast averaging filter appropriate for downscaling. When upscaling it's similar to NearestNeighbor.
|
||||
- `NearestNeighbor` - Fastest resampling filter, no antialiasing.
|
||||
|
||||
The full list of supported filters: NearestNeighbor, Box, Linear, Hermite, MitchellNetravali, CatmullRom, BSpline, Gaussian, Lanczos, Hann, Hamming, Blackman, Bartlett, Welch, Cosine. Custom filters can be created using ResampleFilter struct.
|
||||
|
||||
**Resampling filters comparison**
|
||||
|
||||
Original image:
|
||||
|
||||

|
||||
|
||||
The same image resized from 600x400px to 150x100px using different resampling filters.
|
||||
From faster (lower quality) to slower (higher quality):
|
||||
|
||||
Filter | Resize result
|
||||
--------------------------|---------------------------------------------
|
||||
`imaging.NearestNeighbor` | 
|
||||
`imaging.Linear` | 
|
||||
`imaging.CatmullRom` | 
|
||||
`imaging.Lanczos` | 
|
||||
|
||||
|
||||
### Gaussian Blur
|
||||
|
||||
```go
|
||||
dstImage := imaging.Blur(srcImage, 0.5)
|
||||
```
|
||||
|
||||
Sigma parameter allows to control the strength of the blurring effect.
|
||||
|
||||
Original image | Sigma = 0.5 | Sigma = 1.5
|
||||
-----------------------------------|----------------------------------------|---------------------------------------
|
||||
 |  | 
|
||||
|
||||
### Sharpening
|
||||
|
||||
```go
|
||||
dstImage := imaging.Sharpen(srcImage, 0.5)
|
||||
```
|
||||
|
||||
`Sharpen` uses gaussian function internally. Sigma parameter allows to control the strength of the sharpening effect.
|
||||
|
||||
Original image | Sigma = 0.5 | Sigma = 1.5
|
||||
-----------------------------------|-------------------------------------------|------------------------------------------
|
||||
 |  | 
|
||||
|
||||
### Gamma correction
|
||||
|
||||
```go
|
||||
dstImage := imaging.AdjustGamma(srcImage, 0.75)
|
||||
```
|
||||
|
||||
Original image | Gamma = 0.75 | Gamma = 1.25
|
||||
-----------------------------------|------------------------------------------|-----------------------------------------
|
||||
 |  | 
|
||||
|
||||
### Contrast adjustment
|
||||
|
||||
```go
|
||||
dstImage := imaging.AdjustContrast(srcImage, 20)
|
||||
```
|
||||
|
||||
Original image | Contrast = 15 | Contrast = -15
|
||||
-----------------------------------|--------------------------------------------|-------------------------------------------
|
||||
 |  | 
|
||||
|
||||
### Brightness adjustment
|
||||
|
||||
```go
|
||||
dstImage := imaging.AdjustBrightness(srcImage, 20)
|
||||
```
|
||||
|
||||
Original image | Brightness = 10 | Brightness = -10
|
||||
-----------------------------------|----------------------------------------------|---------------------------------------------
|
||||
 |  | 
|
||||
|
||||
### Saturation adjustment
|
||||
|
||||
```go
|
||||
dstImage := imaging.AdjustSaturation(srcImage, 20)
|
||||
```
|
||||
|
||||
Original image | Saturation = 30 | Saturation = -30
|
||||
-----------------------------------|----------------------------------------------|---------------------------------------------
|
||||
 |  | 
|
||||
|
||||
### Hue adjustment
|
||||
|
||||
```go
|
||||
dstImage := imaging.AdjustHue(srcImage, 20)
|
||||
```
|
||||
|
||||
Original image | Hue = 60 | Hue = -60
|
||||
-----------------------------------|----------------------------------------------|---------------------------------------------
|
||||
 |  | 
|
||||
|
||||
## FAQ
|
||||
|
||||
### Incorrect image orientation after processing (e.g. an image appears rotated after resizing)
|
||||
|
||||
Most probably, the given image contains the EXIF orientation tag.
|
||||
The standard `image/*` packages do not support loading and saving
|
||||
this kind of information. To fix the issue, try opening images with
|
||||
the `AutoOrientation` decode option. If this option is set to `true`,
|
||||
the image orientation is changed after decoding, according to the
|
||||
orientation tag (if present). Here's the example:
|
||||
|
||||
```go
|
||||
img, err := imaging.Open("test.jpg", imaging.AutoOrientation(true))
|
||||
```
|
||||
|
||||
### What's the difference between `imaging` and `gift` packages?
|
||||
|
||||
[imaging](https://github.com/kovidgoyal/imaging)
|
||||
is designed to be a lightweight and simple image manipulation package.
|
||||
It provides basic image processing functions and a few helper functions
|
||||
such as `Open` and `Save`. It consistently returns *image.NRGBA image
|
||||
type (8 bits per channel, RGBA).
|
||||
|
||||
[gift](https://github.com/disintegration/gift)
|
||||
supports more advanced image processing, for example, sRGB/Linear color
|
||||
space conversions. It also supports different output image types
|
||||
(e.g. 16 bits per channel) and provides easy-to-use API for chaining
|
||||
multiple processing steps together.
|
||||
|
||||
## Example code
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"image"
|
||||
"image/color"
|
||||
"log"
|
||||
|
||||
"github.com/kovidgoyal/imaging"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Open a test image.
|
||||
src, err := imaging.Open("testdata/flowers.png")
|
||||
if err != nil {
|
||||
log.Fatalf("failed to open image: %v", err)
|
||||
}
|
||||
|
||||
// Crop the original image to 300x300px size using the center anchor.
|
||||
src = imaging.CropAnchor(src, 300, 300, imaging.Center)
|
||||
|
||||
// Resize the cropped image to width = 200px preserving the aspect ratio.
|
||||
src = imaging.Resize(src, 200, 0, imaging.Lanczos)
|
||||
|
||||
// Create a blurred version of the image.
|
||||
img1 := imaging.Blur(src, 5)
|
||||
|
||||
// Create a grayscale version of the image with higher contrast and sharpness.
|
||||
img2 := imaging.Grayscale(src)
|
||||
img2 = imaging.AdjustContrast(img2, 20)
|
||||
img2 = imaging.Sharpen(img2, 2)
|
||||
|
||||
// Create an inverted version of the image.
|
||||
img3 := imaging.Invert(src)
|
||||
|
||||
// Create an embossed version of the image using a convolution filter.
|
||||
img4 := imaging.Convolve3x3(
|
||||
src,
|
||||
[9]float64{
|
||||
-1, -1, 0,
|
||||
-1, 1, 1,
|
||||
0, 1, 1,
|
||||
},
|
||||
nil,
|
||||
)
|
||||
|
||||
// Create a new image and paste the four produced images into it.
|
||||
dst := imaging.New(400, 400, color.NRGBA{0, 0, 0, 0})
|
||||
dst = imaging.Paste(dst, img1, image.Pt(0, 0))
|
||||
dst = imaging.Paste(dst, img2, image.Pt(0, 200))
|
||||
dst = imaging.Paste(dst, img3, image.Pt(200, 0))
|
||||
dst = imaging.Paste(dst, img4, image.Pt(200, 200))
|
||||
|
||||
// Save the resulting image as JPEG.
|
||||
err = imaging.Save(dst, "testdata/out_example.jpg")
|
||||
if err != nil {
|
||||
log.Fatalf("failed to save image: %v", err)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||

|
||||
|
||||
2
vendor/modules.txt
vendored
2
vendor/modules.txt
vendored
@@ -359,7 +359,7 @@ github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1
|
||||
github.com/cs3org/go-cs3apis/cs3/storage/registry/v1beta1
|
||||
github.com/cs3org/go-cs3apis/cs3/tx/v1beta1
|
||||
github.com/cs3org/go-cs3apis/cs3/types/v1beta1
|
||||
# github.com/cs3org/reva/v2 v2.19.5
|
||||
# github.com/cs3org/reva/v2 v2.19.6
|
||||
## explicit; go 1.21
|
||||
github.com/cs3org/reva/v2/cmd/revad/internal/grace
|
||||
github.com/cs3org/reva/v2/cmd/revad/runtime
|
||||
|
||||
Reference in New Issue
Block a user