(ctx context.Context, body io.ReadCloser, req types.UploadRequest)
| 295 | } |
| 296 | |
| 297 | func (c *GitHTTPComponent) LfsUpload(ctx context.Context, body io.ReadCloser, req types.UploadRequest) error { |
| 298 | var exists bool |
| 299 | repo, err := c.repo.FindByPath(ctx, req.RepoType, req.Namespace, req.Name) |
| 300 | if err != nil { |
| 301 | return fmt.Errorf("failed to find repo, error: %w", err) |
| 302 | } |
| 303 | |
| 304 | pointer := types.Pointer{Oid: req.Oid, Size: req.Size} |
| 305 | |
| 306 | if !pointer.Valid() { |
| 307 | slog.Error("invalid lfs oid", slog.String("oid", req.Oid)) |
| 308 | return errors.New("invalid lfs oid") |
| 309 | } |
| 310 | |
| 311 | objectKey := path.Join("lfs", pointer.RelativePath()) |
| 312 | _, err = c.s3Client.StatObject(ctx, c.config.S3.Bucket, objectKey, minio.StatObjectOptions{}) |
| 313 | if err != nil { |
| 314 | if os.IsNotExist(err) { |
| 315 | exists = false |
| 316 | } |
| 317 | slog.Error("failed to check if lfs file exists", slog.String("oid", objectKey), slog.Any("error", err)) |
| 318 | exists = false |
| 319 | } else { |
| 320 | exists = true |
| 321 | } |
| 322 | uploadOrVerify := func() error { |
| 323 | if exists { |
| 324 | allowed, err := c.AllowWriteAccess(ctx, req.RepoType, req.Namespace, req.Name, req.CurrentUser) |
| 325 | if err != nil { |
| 326 | slog.Error("Unable to check if LFS MetaObject [%s] is allowed. Error: %v", pointer.Oid, err) |
| 327 | return err |
| 328 | } |
| 329 | if !allowed { |
| 330 | // The file exists but the user has no access to it. |
| 331 | // The upload gets verified by hashing and size comparison to prove access to it. |
| 332 | hash := sha256.New() |
| 333 | written, err := io.Copy(hash, body) |
| 334 | if err != nil { |
| 335 | slog.Error("Error creating hash. Error: %v", err) |
| 336 | return err |
| 337 | } |
| 338 | |
| 339 | if written != pointer.Size { |
| 340 | return types.ErrSizeMismatch |
| 341 | } |
| 342 | if hex.EncodeToString(hash.Sum(nil)) != pointer.Oid { |
| 343 | return types.ErrHashMismatch |
| 344 | } |
| 345 | } |
| 346 | } else { |
| 347 | var ( |
| 348 | uploadErr error |
| 349 | uploadInfo minio.UploadInfo |
| 350 | ) |
| 351 | uploadInfo, uploadErr = c.s3Client.PutObject( |
| 352 | ctx, |
| 353 | c.config.S3.Bucket, |
| 354 | objectKey, |
nothing calls this directly
no test coverage detected