summaryrefslogtreecommitdiffstats
path: root/routers
diff options
context:
space:
mode:
Diffstat (limited to 'routers')
-rw-r--r--routers/api/v1/repo/file.go3
-rw-r--r--routers/common/repo.go26
-rw-r--r--routers/init.go4
-rw-r--r--routers/web/repo/repo.go114
-rw-r--r--routers/web/web.go3
5 files changed, 114 insertions, 36 deletions
diff --git a/routers/api/v1/repo/file.go b/routers/api/v1/repo/file.go
index 39a60df33f..e6427ea4f4 100644
--- a/routers/api/v1/repo/file.go
+++ b/routers/api/v1/repo/file.go
@@ -18,6 +18,7 @@ import (
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/routers/common"
+ "code.gitea.io/gitea/routers/web/repo"
)
// GetRawFile get a file by path on a repository
@@ -126,7 +127,7 @@ func GetArchive(ctx *context.APIContext) {
ctx.Repo.GitRepo = gitRepo
defer gitRepo.Close()
- common.Download(ctx.Context)
+ repo.Download(ctx.Context)
}
// GetEditorconfig get editor config of a repository
diff --git a/routers/common/repo.go b/routers/common/repo.go
index c61b5ec57f..22403da097 100644
--- a/routers/common/repo.go
+++ b/routers/common/repo.go
@@ -7,7 +7,6 @@ package common
import (
"fmt"
"io"
- "net/http"
"path"
"path/filepath"
"strings"
@@ -19,7 +18,6 @@ import (
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/typesniffer"
- "code.gitea.io/gitea/services/archiver"
)
// ServeBlob download a git.Blob
@@ -41,30 +39,6 @@ func ServeBlob(ctx *context.Context, blob *git.Blob) error {
return ServeData(ctx, ctx.Repo.TreePath, blob.Size(), dataRc)
}
-// Download an archive of a repository
-func Download(ctx *context.Context) {
- uri := ctx.Params("*")
- aReq := archiver.DeriveRequestFrom(ctx, uri)
-
- if aReq == nil {
- ctx.Error(http.StatusNotFound)
- return
- }
-
- downloadName := ctx.Repo.Repository.Name + "-" + aReq.GetArchiveName()
- complete := aReq.IsComplete()
- if !complete {
- aReq = archiver.ArchiveRepository(aReq)
- complete = aReq.WaitForCompletion(ctx)
- }
-
- if complete {
- ctx.ServeFile(aReq.GetArchivePath(), downloadName)
- } else {
- ctx.Error(http.StatusNotFound)
- }
-}
-
// ServeData download file from io.Reader
func ServeData(ctx *context.Context, name string, size int64, reader io.Reader) error {
buf := make([]byte, 1024)
diff --git a/routers/init.go b/routers/init.go
index 4c28a95395..bbf39a3f50 100644
--- a/routers/init.go
+++ b/routers/init.go
@@ -33,6 +33,7 @@ import (
"code.gitea.io/gitea/routers/common"
"code.gitea.io/gitea/routers/private"
web_routers "code.gitea.io/gitea/routers/web"
+ "code.gitea.io/gitea/services/archiver"
"code.gitea.io/gitea/services/auth"
"code.gitea.io/gitea/services/mailer"
mirror_service "code.gitea.io/gitea/services/mirror"
@@ -63,6 +64,9 @@ func NewServices() {
mailer.NewContext()
_ = cache.NewContext()
notification.NewContext()
+ if err := archiver.Init(); err != nil {
+ log.Fatal("archiver init failed: %v", err)
+ }
}
// GlobalInit is for global configuration reload-able.
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,
})
}
diff --git a/routers/web/web.go b/routers/web/web.go
index 2c8a6411a1..883213479c 100644
--- a/routers/web/web.go
+++ b/routers/web/web.go
@@ -22,7 +22,6 @@ import (
"code.gitea.io/gitea/modules/validation"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/routers/api/v1/misc"
- "code.gitea.io/gitea/routers/common"
"code.gitea.io/gitea/routers/web/admin"
"code.gitea.io/gitea/routers/web/dev"
"code.gitea.io/gitea/routers/web/events"
@@ -888,7 +887,7 @@ func RegisterRoutes(m *web.Route) {
}, context.RepoRef(), repo.MustBeNotEmpty, context.RequireRepoReaderOr(models.UnitTypeCode))
m.Group("/archive", func() {
- m.Get("/*", common.Download)
+ m.Get("/*", repo.Download)
m.Post("/*", repo.InitiateDownload)
}, repo.MustBeNotEmpty, reqRepoCodeReader)