aboutsummaryrefslogtreecommitdiffstats
path: root/routers/web/repo/repo.go
diff options
context:
space:
mode:
authorLunny Xiao <xiaolunwen@gmail.com>2021-06-24 05:12:38 +0800
committerGitHub <noreply@github.com>2021-06-23 17:12:38 -0400
commitb223d361955f8b722f7dd0b358b2e57e6f359edf (patch)
treecaa934320b264b969df679508eb19458e0cc6029 /routers/web/repo/repo.go
parentc9c7afda1a80bda7b61ded222163db796132b78f (diff)
downloadgitea-b223d361955f8b722f7dd0b358b2e57e6f359edf.tar.gz
gitea-b223d361955f8b722f7dd0b358b2e57e6f359edf.zip
Rework repository archive (#14723)
* Use storage to store archive files * Fix backend lint * Add archiver table on database * Finish archive download * Fix test * Add database migrations * Add status for archiver * Fix lint * Add queue * Add doctor to check and delete old archives * Improve archive queue * Fix tests * improve archive storage * Delete repo archives * Add missing fixture * fix fixture * Fix fixture * Fix test * Fix archiver cleaning * Fix bug * Add docs for repository archive storage * remove repo-archive configuration * Fix test * Fix test * Fix lint Co-authored-by: 6543 <6543@obermui.de> Co-authored-by: techknowlogick <techknowlogick@gitea.io>
Diffstat (limited to 'routers/web/repo/repo.go')
-rw-r--r--routers/web/repo/repo.go114
1 files changed, 107 insertions, 7 deletions
diff --git a/routers/web/repo/repo.go b/routers/web/repo/repo.go
index f149e92a8b..919fd4620d 100644
--- a/routers/web/repo/repo.go
+++ b/routers/web/repo/repo.go
@@ -15,8 +15,10 @@ import (
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/context"
+ "code.gitea.io/gitea/modules/graceful"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
+ "code.gitea.io/gitea/modules/storage"
"code.gitea.io/gitea/modules/web"
archiver_service "code.gitea.io/gitea/services/archiver"
"code.gitea.io/gitea/services/forms"
@@ -364,25 +366,123 @@ func RedirectDownload(ctx *context.Context) {
ctx.Error(http.StatusNotFound)
}
+// Download an archive of a repository
+func Download(ctx *context.Context) {
+ uri := ctx.Params("*")
+ aReq, err := archiver_service.NewRequest(ctx.Repo.Repository.ID, ctx.Repo.GitRepo, uri)
+ if err != nil {
+ ctx.ServerError("archiver_service.NewRequest", err)
+ return
+ }
+ if aReq == nil {
+ ctx.Error(http.StatusNotFound)
+ return
+ }
+
+ archiver, err := models.GetRepoArchiver(models.DefaultDBContext(), aReq.RepoID, aReq.Type, aReq.CommitID)
+ if err != nil {
+ ctx.ServerError("models.GetRepoArchiver", err)
+ return
+ }
+ if archiver != nil && archiver.Status == models.RepoArchiverReady {
+ download(ctx, aReq.GetArchiveName(), archiver)
+ return
+ }
+
+ if err := archiver_service.StartArchive(aReq); err != nil {
+ ctx.ServerError("archiver_service.StartArchive", err)
+ return
+ }
+
+ var times int
+ var 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 = models.GetRepoArchiver(models.DefaultDBContext(), aReq.RepoID, aReq.Type, aReq.CommitID)
+ if err != nil {
+ ctx.ServerError("archiver_service.StartArchive", err)
+ return
+ }
+ if archiver != nil && archiver.Status == models.RepoArchiverReady {
+ download(ctx, aReq.GetArchiveName(), archiver)
+ return
+ }
+ }
+ }
+}
+
+func download(ctx *context.Context, archiveName string, archiver *models.RepoArchiver) {
+ downloadName := ctx.Repo.Repository.Name + "-" + archiveName
+
+ rPath, err := archiver.RelativePath()
+ if err != nil {
+ ctx.ServerError("archiver.RelativePath", err)
+ return
+ }
+
+ 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.ServeStream(fr, downloadName)
+}
+
// InitiateDownload will enqueue an archival request, as needed. It may submit
// a request that's already in-progress, but the archiver service will just
// kind of drop it on the floor if this is the case.
func InitiateDownload(ctx *context.Context) {
uri := ctx.Params("*")
- aReq := archiver_service.DeriveRequestFrom(ctx, uri)
-
+ aReq, err := archiver_service.NewRequest(ctx.Repo.Repository.ID, ctx.Repo.GitRepo, uri)
+ if err != nil {
+ ctx.ServerError("archiver_service.NewRequest", err)
+ return
+ }
if aReq == nil {
ctx.Error(http.StatusNotFound)
return
}
- complete := aReq.IsComplete()
- if !complete {
- aReq = archiver_service.ArchiveRepository(aReq)
- complete, _ = aReq.TimedWaitForCompletion(ctx, 2*time.Second)
+ archiver, err := models.GetRepoArchiver(models.DefaultDBContext(), aReq.RepoID, aReq.Type, aReq.CommitID)
+ if err != nil {
+ ctx.ServerError("archiver_service.StartArchive", err)
+ return
+ }
+ if archiver == nil || archiver.Status != models.RepoArchiverReady {
+ if err := archiver_service.StartArchive(aReq); err != nil {
+ ctx.ServerError("archiver_service.StartArchive", err)
+ return
+ }
+ }
+
+ var completed bool
+ if archiver != nil && archiver.Status == models.RepoArchiverReady {
+ completed = true
}
ctx.JSON(http.StatusOK, map[string]interface{}{
- "complete": complete,
+ "complete": completed,
})
}