62 lines
1.3 KiB
Go
62 lines
1.3 KiB
Go
package handlers
|
|
|
|
import (
|
|
"fmt"
|
|
"net/http"
|
|
|
|
"xorm.io/xorm"
|
|
|
|
gitdomain "github.com/forgeo/forgebucket/internal/domain/git"
|
|
)
|
|
|
|
type ArchiveHandler struct {
|
|
db *xorm.Engine
|
|
}
|
|
|
|
func NewArchiveHandler(db *xorm.Engine) *ArchiveHandler {
|
|
return &ArchiveHandler{db: db}
|
|
}
|
|
|
|
var archiveFormats = map[string]struct {
|
|
contentType string
|
|
ext string
|
|
}{
|
|
"zip": {"application/zip", "zip"},
|
|
"tar.gz": {"application/x-tar", "tar.gz"},
|
|
"bundle": {"application/octet-stream", "bundle"},
|
|
}
|
|
|
|
func (h *ArchiveHandler) Download(w http.ResponseWriter, r *http.Request) {
|
|
repo, ok := resolveRepo(h.db, w, r)
|
|
if !ok {
|
|
return
|
|
}
|
|
|
|
format := r.URL.Query().Get("format")
|
|
if format == "" {
|
|
format = "zip"
|
|
}
|
|
meta, allowed := archiveFormats[format]
|
|
if !allowed {
|
|
jsonError(w, "format must be zip, tar.gz, or bundle", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
ref := r.URL.Query().Get("ref")
|
|
if ref == "" {
|
|
ref = repo.DefaultBranch
|
|
}
|
|
if ref == "" {
|
|
ref = "HEAD"
|
|
}
|
|
|
|
filename := fmt.Sprintf("%s-%s.%s", repo.Name, ref, meta.ext)
|
|
w.Header().Set("Content-Type", meta.contentType)
|
|
w.Header().Set("Content-Disposition", fmt.Sprintf(`attachment; filename="%s"`, filename))
|
|
|
|
if err := gitdomain.ArchiveStream(repo.DiskPath, ref, format, w); err != nil {
|
|
// Headers already written — can't change status code; just log and close.
|
|
_ = err
|
|
}
|
|
}
|