mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-11-04 08:34:30 +01:00 
			
		
		
		
	fix hard-coded timeout and error panic in API archive download endpoint (#20925)
* fix hard-coded timeout and error panic in API archive download endpoint
This commit updates the `GET /api/v1/repos/{owner}/{repo}/archive/{archive}`
endpoint which prior to this PR had a couple of issues.
1. The endpoint had a hard-coded 20s timeout for the archiver to complete after
   which a 500 (Internal Server Error) was returned to client. For a scripted
   API client there was no clear way of telling that the operation timed out and
   that it should retry.
2. Whenever the timeout _did occur_, the code used to panic. This was caused by
   the API endpoint "delegating" to the same call path as the web, which uses a
   slightly different way of reporting errors (HTML rather than JSON for
   example).
   More specifically, `api/v1/repo/file.go#GetArchive` just called through to
   `web/repo/repo.go#Download`, which expects the `Context` to have a `Render`
   field set, but which is `nil` for API calls. Hence, a `nil` pointer error.
The code addresses (1) by dropping the hard-coded timeout. Instead, any
timeout/cancelation on the incoming `Context` is used.
The code addresses (2) by updating the API endpoint to use a separate call path
for the API-triggered archive download. This avoids producing HTML-errors on
errors (it now produces JSON errors).
Signed-off-by: Peter Gardfjäll <peter.gardfjall.work@gmail.com>
			
			
This commit is contained in:
		
							parent
							
								
									41c76ad714
								
							
						
					
					
						commit
						4562d40fce
					
				@ -112,11 +112,8 @@ func migrateRepoAvatars(ctx context.Context, dstStorage storage.ObjectStorage) e
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
func migrateRepoArchivers(ctx context.Context, dstStorage storage.ObjectStorage) error {
 | 
					func migrateRepoArchivers(ctx context.Context, dstStorage storage.ObjectStorage) error {
 | 
				
			||||||
	return db.IterateObjects(ctx, func(archiver *repo_model.RepoArchiver) error {
 | 
						return db.IterateObjects(ctx, func(archiver *repo_model.RepoArchiver) error {
 | 
				
			||||||
		p, err := archiver.RelativePath()
 | 
							p := archiver.RelativePath()
 | 
				
			||||||
		if err != nil {
 | 
							_, err := storage.Copy(dstStorage, p, storage.RepoArchives, p)
 | 
				
			||||||
			return err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		_, err = storage.Copy(dstStorage, p, storage.RepoArchives, p)
 | 
					 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -218,8 +218,7 @@ func DeleteRepository(doer *user_model.User, uid, repoID int64) error {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	archivePaths := make([]string, 0, len(archives))
 | 
						archivePaths := make([]string, 0, len(archives))
 | 
				
			||||||
	for _, v := range archives {
 | 
						for _, v := range archives {
 | 
				
			||||||
		p, _ := v.RelativePath()
 | 
							archivePaths = append(archivePaths, v.RelativePath())
 | 
				
			||||||
		archivePaths = append(archivePaths, p)
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if _, err := db.DeleteByBean(ctx, &repo_model.RepoArchiver{RepoID: repoID}); err != nil {
 | 
						if _, err := db.DeleteByBean(ctx, &repo_model.RepoArchiver{RepoID: repoID}); err != nil {
 | 
				
			||||||
 | 
				
			|||||||
@ -39,9 +39,9 @@ func init() {
 | 
				
			|||||||
	db.RegisterModel(new(RepoArchiver))
 | 
						db.RegisterModel(new(RepoArchiver))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// RelativePath returns relative path
 | 
					// RelativePath returns the archive path relative to the archive storage root.
 | 
				
			||||||
func (archiver *RepoArchiver) RelativePath() (string, error) {
 | 
					func (archiver *RepoArchiver) RelativePath() string {
 | 
				
			||||||
	return fmt.Sprintf("%d/%s/%s.%s", archiver.RepoID, archiver.CommitID[:2], archiver.CommitID, archiver.Type.String()), nil
 | 
						return fmt.Sprintf("%d/%s/%s.%s", archiver.RepoID, archiver.CommitID[:2], archiver.CommitID, archiver.Type.String())
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var delRepoArchiver = new(RepoArchiver)
 | 
					var delRepoArchiver = new(RepoArchiver)
 | 
				
			||||||
 | 
				
			|||||||
@ -8,6 +8,7 @@ package repo
 | 
				
			|||||||
import (
 | 
					import (
 | 
				
			||||||
	"bytes"
 | 
						"bytes"
 | 
				
			||||||
	"encoding/base64"
 | 
						"encoding/base64"
 | 
				
			||||||
 | 
						"errors"
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"io"
 | 
						"io"
 | 
				
			||||||
	"net/http"
 | 
						"net/http"
 | 
				
			||||||
@ -28,7 +29,7 @@ import (
 | 
				
			|||||||
	api "code.gitea.io/gitea/modules/structs"
 | 
						api "code.gitea.io/gitea/modules/structs"
 | 
				
			||||||
	"code.gitea.io/gitea/modules/web"
 | 
						"code.gitea.io/gitea/modules/web"
 | 
				
			||||||
	"code.gitea.io/gitea/routers/common"
 | 
						"code.gitea.io/gitea/routers/common"
 | 
				
			||||||
	"code.gitea.io/gitea/routers/web/repo"
 | 
						archiver_service "code.gitea.io/gitea/services/repository/archiver"
 | 
				
			||||||
	files_service "code.gitea.io/gitea/services/repository/files"
 | 
						files_service "code.gitea.io/gitea/services/repository/files"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -294,7 +295,53 @@ func GetArchive(ctx *context.APIContext) {
 | 
				
			|||||||
		defer gitRepo.Close()
 | 
							defer gitRepo.Close()
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	repo.Download(ctx.Context)
 | 
						archiveDownload(ctx)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func archiveDownload(ctx *context.APIContext) {
 | 
				
			||||||
 | 
						uri := ctx.Params("*")
 | 
				
			||||||
 | 
						aReq, err := archiver_service.NewRequest(ctx.Repo.Repository.ID, ctx.Repo.GitRepo, uri)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							if errors.Is(err, archiver_service.ErrUnknownArchiveFormat{}) {
 | 
				
			||||||
 | 
								ctx.Error(http.StatusBadRequest, "unknown archive format", err)
 | 
				
			||||||
 | 
							} else if errors.Is(err, archiver_service.RepoRefNotFoundError{}) {
 | 
				
			||||||
 | 
								ctx.Error(http.StatusNotFound, "unrecognized reference", err)
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								ctx.ServerError("archiver_service.NewRequest", err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						archiver, err := aReq.Await(ctx)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							ctx.ServerError("archiver.Await", err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						download(ctx, aReq.GetArchiveName(), archiver)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func download(ctx *context.APIContext, archiveName string, archiver *repo_model.RepoArchiver) {
 | 
				
			||||||
 | 
						downloadName := ctx.Repo.Repository.Name + "-" + archiveName
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						rPath := archiver.RelativePath()
 | 
				
			||||||
 | 
						if setting.RepoArchive.ServeDirect {
 | 
				
			||||||
 | 
							// If we have a signed url (S3, object storage), redirect to this directly.
 | 
				
			||||||
 | 
							u, err := storage.RepoArchives.URL(rPath, downloadName)
 | 
				
			||||||
 | 
							if u != nil && err == nil {
 | 
				
			||||||
 | 
								ctx.Redirect(u.String())
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// If we have matched and access to release or issue
 | 
				
			||||||
 | 
						fr, err := storage.RepoArchives.Open(rPath)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							ctx.ServerError("Open", err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						defer fr.Close()
 | 
				
			||||||
 | 
						ctx.ServeContent(downloadName, fr, archiver.CreatedUnix.AsLocalTime())
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetEditorconfig get editor config of a repository
 | 
					// GetEditorconfig get editor config of a repository
 | 
				
			||||||
 | 
				
			|||||||
@ -10,7 +10,6 @@ import (
 | 
				
			|||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"net/http"
 | 
						"net/http"
 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
	"time"
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"code.gitea.io/gitea/models"
 | 
						"code.gitea.io/gitea/models"
 | 
				
			||||||
	"code.gitea.io/gitea/models/db"
 | 
						"code.gitea.io/gitea/models/db"
 | 
				
			||||||
@ -22,7 +21,6 @@ import (
 | 
				
			|||||||
	"code.gitea.io/gitea/modules/base"
 | 
						"code.gitea.io/gitea/modules/base"
 | 
				
			||||||
	"code.gitea.io/gitea/modules/context"
 | 
						"code.gitea.io/gitea/modules/context"
 | 
				
			||||||
	"code.gitea.io/gitea/modules/convert"
 | 
						"code.gitea.io/gitea/modules/convert"
 | 
				
			||||||
	"code.gitea.io/gitea/modules/graceful"
 | 
					 | 
				
			||||||
	"code.gitea.io/gitea/modules/log"
 | 
						"code.gitea.io/gitea/modules/log"
 | 
				
			||||||
	repo_module "code.gitea.io/gitea/modules/repository"
 | 
						repo_module "code.gitea.io/gitea/modules/repository"
 | 
				
			||||||
	"code.gitea.io/gitea/modules/setting"
 | 
						"code.gitea.io/gitea/modules/setting"
 | 
				
			||||||
@ -390,68 +388,27 @@ func Download(ctx *context.Context) {
 | 
				
			|||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		if errors.Is(err, archiver_service.ErrUnknownArchiveFormat{}) {
 | 
							if errors.Is(err, archiver_service.ErrUnknownArchiveFormat{}) {
 | 
				
			||||||
			ctx.Error(http.StatusBadRequest, err.Error())
 | 
								ctx.Error(http.StatusBadRequest, err.Error())
 | 
				
			||||||
 | 
							} else if errors.Is(err, archiver_service.RepoRefNotFoundError{}) {
 | 
				
			||||||
 | 
								ctx.Error(http.StatusNotFound, err.Error())
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			ctx.ServerError("archiver_service.NewRequest", err)
 | 
								ctx.ServerError("archiver_service.NewRequest", err)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if aReq == nil {
 | 
					 | 
				
			||||||
		ctx.Error(http.StatusNotFound)
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	archiver, err := repo_model.GetRepoArchiver(ctx, aReq.RepoID, aReq.Type, aReq.CommitID)
 | 
						archiver, err := aReq.Await(ctx)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		ctx.ServerError("models.GetRepoArchiver", err)
 | 
							ctx.ServerError("archiver.Await", err)
 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if archiver != nil && archiver.Status == repo_model.ArchiverReady {
 | 
					 | 
				
			||||||
		download(ctx, aReq.GetArchiveName(), archiver)
 | 
					 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err := archiver_service.StartArchive(aReq); err != nil {
 | 
						download(ctx, aReq.GetArchiveName(), archiver)
 | 
				
			||||||
		ctx.ServerError("archiver_service.StartArchive", err)
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	var times int
 | 
					 | 
				
			||||||
	t := time.NewTicker(time.Second * 1)
 | 
					 | 
				
			||||||
	defer t.Stop()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for {
 | 
					 | 
				
			||||||
		select {
 | 
					 | 
				
			||||||
		case <-graceful.GetManager().HammerContext().Done():
 | 
					 | 
				
			||||||
			log.Warn("exit archive download because system stop")
 | 
					 | 
				
			||||||
			return
 | 
					 | 
				
			||||||
		case <-t.C:
 | 
					 | 
				
			||||||
			if times > 20 {
 | 
					 | 
				
			||||||
				ctx.ServerError("wait download timeout", nil)
 | 
					 | 
				
			||||||
				return
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			times++
 | 
					 | 
				
			||||||
			archiver, err = repo_model.GetRepoArchiver(ctx, aReq.RepoID, aReq.Type, aReq.CommitID)
 | 
					 | 
				
			||||||
			if err != nil {
 | 
					 | 
				
			||||||
				ctx.ServerError("archiver_service.StartArchive", err)
 | 
					 | 
				
			||||||
				return
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			if archiver != nil && archiver.Status == repo_model.ArchiverReady {
 | 
					 | 
				
			||||||
				download(ctx, aReq.GetArchiveName(), archiver)
 | 
					 | 
				
			||||||
				return
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func download(ctx *context.Context, archiveName string, archiver *repo_model.RepoArchiver) {
 | 
					func download(ctx *context.Context, archiveName string, archiver *repo_model.RepoArchiver) {
 | 
				
			||||||
	downloadName := ctx.Repo.Repository.Name + "-" + archiveName
 | 
						downloadName := ctx.Repo.Repository.Name + "-" + archiveName
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	rPath, err := archiver.RelativePath()
 | 
						rPath := archiver.RelativePath()
 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		ctx.ServerError("archiver.RelativePath", err)
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if setting.RepoArchive.ServeDirect {
 | 
						if setting.RepoArchive.ServeDirect {
 | 
				
			||||||
		// If we have a signed url (S3, object storage), redirect to this directly.
 | 
							// If we have a signed url (S3, object storage), redirect to this directly.
 | 
				
			||||||
		u, err := storage.RepoArchives.URL(rPath, downloadName)
 | 
							u, err := storage.RepoArchives.URL(rPath, downloadName)
 | 
				
			||||||
 | 
				
			|||||||
@ -57,6 +57,21 @@ func (ErrUnknownArchiveFormat) Is(err error) bool {
 | 
				
			|||||||
	return ok
 | 
						return ok
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// RepoRefNotFoundError is returned when a requested reference (commit, tag) was not found.
 | 
				
			||||||
 | 
					type RepoRefNotFoundError struct {
 | 
				
			||||||
 | 
						RefName string
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Error implements error.
 | 
				
			||||||
 | 
					func (e RepoRefNotFoundError) Error() string {
 | 
				
			||||||
 | 
						return fmt.Sprintf("unrecognized repository reference: %s", e.RefName)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (e RepoRefNotFoundError) Is(err error) bool {
 | 
				
			||||||
 | 
						_, ok := err.(RepoRefNotFoundError)
 | 
				
			||||||
 | 
						return ok
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// NewRequest creates an archival request, based on the URI.  The
 | 
					// NewRequest creates an archival request, based on the URI.  The
 | 
				
			||||||
// resulting ArchiveRequest is suitable for being passed to ArchiveRepository()
 | 
					// resulting ArchiveRequest is suitable for being passed to ArchiveRepository()
 | 
				
			||||||
// if it's determined that the request still needs to be satisfied.
 | 
					// if it's determined that the request still needs to be satisfied.
 | 
				
			||||||
@ -103,7 +118,7 @@ func NewRequest(repoID int64, repo *git.Repository, uri string) (*ArchiveRequest
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		return nil, fmt.Errorf("Unknow ref %s type", r.refName)
 | 
							return nil, RepoRefNotFoundError{RefName: r.refName}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return r, nil
 | 
						return r, nil
 | 
				
			||||||
@ -115,6 +130,49 @@ func (aReq *ArchiveRequest) GetArchiveName() string {
 | 
				
			|||||||
	return strings.ReplaceAll(aReq.refName, "/", "-") + "." + aReq.Type.String()
 | 
						return strings.ReplaceAll(aReq.refName, "/", "-") + "." + aReq.Type.String()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Await awaits the completion of an ArchiveRequest. If the archive has
 | 
				
			||||||
 | 
					// already been prepared the method returns immediately. Otherwise an archiver
 | 
				
			||||||
 | 
					// process will be started and its completion awaited. On success the returned
 | 
				
			||||||
 | 
					// RepoArchiver may be used to download the archive. Note that even if the
 | 
				
			||||||
 | 
					// context is cancelled/times out a started archiver will still continue to run
 | 
				
			||||||
 | 
					// in the background.
 | 
				
			||||||
 | 
					func (aReq *ArchiveRequest) Await(ctx context.Context) (*repo_model.RepoArchiver, error) {
 | 
				
			||||||
 | 
						archiver, err := repo_model.GetRepoArchiver(ctx, aReq.RepoID, aReq.Type, aReq.CommitID)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, fmt.Errorf("models.GetRepoArchiver: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if archiver != nil && archiver.Status == repo_model.ArchiverReady {
 | 
				
			||||||
 | 
							// Archive already generated, we're done.
 | 
				
			||||||
 | 
							return archiver, nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err := StartArchive(aReq); err != nil {
 | 
				
			||||||
 | 
							return nil, fmt.Errorf("archiver.StartArchive: %v", err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						poll := time.NewTicker(time.Second * 1)
 | 
				
			||||||
 | 
						defer poll.Stop()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for {
 | 
				
			||||||
 | 
							select {
 | 
				
			||||||
 | 
							case <-graceful.GetManager().HammerContext().Done():
 | 
				
			||||||
 | 
								// System stopped.
 | 
				
			||||||
 | 
								return nil, graceful.GetManager().HammerContext().Err()
 | 
				
			||||||
 | 
							case <-ctx.Done():
 | 
				
			||||||
 | 
								return nil, ctx.Err()
 | 
				
			||||||
 | 
							case <-poll.C:
 | 
				
			||||||
 | 
								archiver, err = repo_model.GetRepoArchiver(ctx, aReq.RepoID, aReq.Type, aReq.CommitID)
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									return nil, fmt.Errorf("repo_model.GetRepoArchiver: %v", err)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if archiver != nil && archiver.Status == repo_model.ArchiverReady {
 | 
				
			||||||
 | 
									return archiver, nil
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func doArchive(r *ArchiveRequest) (*repo_model.RepoArchiver, error) {
 | 
					func doArchive(r *ArchiveRequest) (*repo_model.RepoArchiver, error) {
 | 
				
			||||||
	txCtx, committer, err := db.TxContext()
 | 
						txCtx, committer, err := db.TxContext()
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
@ -147,11 +205,7 @@ func doArchive(r *ArchiveRequest) (*repo_model.RepoArchiver, error) {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	rPath, err := archiver.RelativePath()
 | 
						rPath := archiver.RelativePath()
 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return nil, err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	_, err = storage.RepoArchives.Stat(rPath)
 | 
						_, err = storage.RepoArchives.Stat(rPath)
 | 
				
			||||||
	if err == nil {
 | 
						if err == nil {
 | 
				
			||||||
		if archiver.Status == repo_model.ArchiverGenerating {
 | 
							if archiver.Status == repo_model.ArchiverGenerating {
 | 
				
			||||||
@ -284,13 +338,10 @@ func StartArchive(request *ArchiveRequest) error {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func deleteOldRepoArchiver(ctx context.Context, archiver *repo_model.RepoArchiver) error {
 | 
					func deleteOldRepoArchiver(ctx context.Context, archiver *repo_model.RepoArchiver) error {
 | 
				
			||||||
	p, err := archiver.RelativePath()
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		return err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if err := repo_model.DeleteRepoArchiver(ctx, archiver); err != nil {
 | 
						if err := repo_model.DeleteRepoArchiver(ctx, archiver); err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						p := archiver.RelativePath()
 | 
				
			||||||
	if err := storage.RepoArchives.Delete(p); err != nil {
 | 
						if err := storage.RepoArchives.Delete(p); err != nil {
 | 
				
			||||||
		log.Error("delete repo archive file failed: %v", err)
 | 
							log.Error("delete repo archive file failed: %v", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user