From 4aff4d66ec3e118248129505bc1d70395f47dfbb Mon Sep 17 00:00:00 2001 From: ᴜɴᴋɴᴡᴏɴ Date: Sun, 5 Apr 2020 00:45:08 +0800 Subject: lfs: support upload retry (#6061) --- internal/route/lfs/basic.go | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) (limited to 'internal/route') diff --git a/internal/route/lfs/basic.go b/internal/route/lfs/basic.go index f15873ad..e266c541 100644 --- a/internal/route/lfs/basic.go +++ b/internal/route/lfs/basic.go @@ -7,6 +7,7 @@ package lfs import ( "encoding/json" "io" + "io/ioutil" "net/http" "os" "strconv" @@ -63,7 +64,22 @@ func serveBasicDownload(c *context.Context, repo *db.Repository, oid lfsutil.OID // PUT /{owner}/{repo}.git/info/lfs/object/basic/{oid} func serveBasicUpload(c *context.Context, repo *db.Repository, oid lfsutil.OID) { - err := db.LFS.CreateObject(repo.ID, oid, c.Req.Request.Body, lfsutil.StorageLocal) + // NOTE: LFS client will retry upload the same object if there was a partial failure, + // therefore we would like to skip ones that already exist. + _, err := db.LFS.GetObjectByOID(repo.ID, oid) + if err == nil { + // Object exists, drain the request body and we're good. + _, _ = io.Copy(ioutil.Discard, c.Req.Request.Body) + c.Req.Request.Body.Close() + c.Status(http.StatusOK) + return + } else if !db.IsErrLFSObjectNotExist(err) { + internalServerError(c.Resp) + log.Error("Failed to get object [repo_id: %d, oid: %s]: %v", repo.ID, oid, err) + return + } + + err = db.LFS.CreateObject(repo.ID, oid, c.Req.Request.Body, lfsutil.StorageLocal) if err != nil { internalServerError(c.Resp) log.Error("Failed to create object [repo_id: %d, oid: %s]: %v", repo.ID, oid, err) -- cgit v1.2.3