mirror of https://github.com/gogs/gogs.git
release: able to add attchments to release (#1614)
Added new config section '[release.attachment]’.pull/3422/merge
parent
e6df2259ab
commit
1df54ea0cd
10
cmd/web.go
10
cmd/web.go
|
@ -339,15 +339,15 @@ func runWeb(ctx *cli.Context) error {
|
|||
defer fr.Close()
|
||||
|
||||
ctx.Header().Set("Cache-Control", "public,max-age=86400")
|
||||
fmt.Println("attach.Name:", attach.Name)
|
||||
ctx.Header().Set("Content-Disposition", fmt.Sprintf(`inline; filename="%s"`, attach.Name))
|
||||
// Fix #312. Attachments with , in their name are not handled correctly by Google Chrome.
|
||||
// We must put the name in " manually.
|
||||
if err = repo.ServeData(ctx, "\""+attach.Name+"\"", fr); err != nil {
|
||||
if err = repo.ServeData(ctx, attach.Name, fr); err != nil {
|
||||
ctx.Handle(500, "ServeData", err)
|
||||
return
|
||||
}
|
||||
})
|
||||
m.Post("/issues/attachments", repo.UploadIssueAttachment)
|
||||
m.Post("/releases/attachments", repo.UploadReleaseAttachment)
|
||||
}, ignSignIn)
|
||||
|
||||
m.Group("/:username", func() {
|
||||
|
@ -490,7 +490,7 @@ func runWeb(ctx *cli.Context) error {
|
|||
// So they can apply their own enable/disable logic on routers.
|
||||
m.Group("/issues", func() {
|
||||
m.Combo("/new", repo.MustEnableIssues).Get(context.RepoRef(), repo.NewIssue).
|
||||
Post(bindIgnErr(form.CreateIssue{}), repo.NewIssuePost)
|
||||
Post(bindIgnErr(form.NewIssue{}), repo.NewIssuePost)
|
||||
|
||||
m.Group("/:index", func() {
|
||||
m.Post("/label", repo.UpdateIssueLabel)
|
||||
|
@ -538,7 +538,7 @@ func runWeb(ctx *cli.Context) error {
|
|||
// e.g. /org1/test-repo/compare/master...org1:develop
|
||||
// which should be /org1/test-repo/compare/master...develop
|
||||
m.Combo("/compare/*", repo.MustAllowPulls).Get(repo.CompareAndPullRequest).
|
||||
Post(bindIgnErr(form.CreateIssue{}), repo.CompareAndPullRequestPost)
|
||||
Post(bindIgnErr(form.NewIssue{}), repo.CompareAndPullRequestPost)
|
||||
|
||||
m.Group("", func() {
|
||||
m.Combo("/_edit/*").Get(repo.EditFile).
|
||||
|
|
18
conf/app.ini
18
conf/app.ini
|
@ -114,6 +114,19 @@ FILE_MAX_SIZE = 3
|
|||
; Maximum number of files per upload
|
||||
MAX_FILES = 5
|
||||
|
||||
; Attachment settings for releases
|
||||
[release.attachment]
|
||||
; Whether attachments are enabled. Defaults to `true`
|
||||
ENABLED = true
|
||||
; Path for attachments. Defaults to `data/attachments`
|
||||
PATH = data/attachments
|
||||
; One or more allowed types, e.g. image/jpeg|image/png
|
||||
ALLOWED_TYPES = */*
|
||||
; Max size of each file. Defaults to 32MB
|
||||
MAX_SIZE = 32
|
||||
; Max number of files per upload. Defaults to 10
|
||||
MAX_FILES = 10
|
||||
|
||||
[markdown]
|
||||
; Enable hard line break extension
|
||||
ENABLE_HARD_LINE_BREAK = false
|
||||
|
@ -273,6 +286,7 @@ DISABLE_GRAVATAR = false
|
|||
; This value will be forced to be false in offline mode or Gravatar is disbaled.
|
||||
ENABLE_FEDERATED_AVATAR = true
|
||||
|
||||
; Attachment settings for issues
|
||||
[attachment]
|
||||
; Whether attachments are enabled. Defaults to `true`
|
||||
ENABLE = true
|
||||
|
@ -280,9 +294,9 @@ ENABLE = true
|
|||
PATH = data/attachments
|
||||
; One or more allowed types, e.g. image/jpeg|image/png
|
||||
ALLOWED_TYPES = image/jpeg|image/png
|
||||
; Max size of each file. Defaults to 32MB
|
||||
; Max size of each file. Defaults to 4MB
|
||||
MAX_SIZE = 4
|
||||
; Max number of files per upload. Defaults to 10
|
||||
; Max number of files per upload. Defaults to 5
|
||||
MAX_FILES = 5
|
||||
|
||||
[time]
|
||||
|
|
2
gogs.go
2
gogs.go
|
@ -16,7 +16,7 @@ import (
|
|||
"github.com/gogits/gogs/modules/setting"
|
||||
)
|
||||
|
||||
const APP_VER = "0.10.17.0313"
|
||||
const APP_VER = "0.10.18.0313"
|
||||
|
||||
func init() {
|
||||
setting.AppVer = APP_VER
|
||||
|
|
|
@ -110,7 +110,7 @@ func GetAttachmentByUUID(uuid string) (*Attachment, error) {
|
|||
}
|
||||
|
||||
func getAttachmentsByIssueID(e Engine, issueID int64) ([]*Attachment, error) {
|
||||
attachments := make([]*Attachment, 0, 10)
|
||||
attachments := make([]*Attachment, 0, 5)
|
||||
return attachments, e.Where("issue_id = ? AND comment_id = 0", issueID).Find(&attachments)
|
||||
}
|
||||
|
||||
|
@ -120,15 +120,25 @@ func GetAttachmentsByIssueID(issueID int64) ([]*Attachment, error) {
|
|||
}
|
||||
|
||||
func getAttachmentsByCommentID(e Engine, commentID int64) ([]*Attachment, error) {
|
||||
attachments := make([]*Attachment, 0, 10)
|
||||
attachments := make([]*Attachment, 0, 5)
|
||||
return attachments, e.Where("comment_id=?", commentID).Find(&attachments)
|
||||
}
|
||||
|
||||
// GetAttachmentsByCommentID returns all attachments if comment by given ID.
|
||||
// GetAttachmentsByCommentID returns all attachments of a comment.
|
||||
func GetAttachmentsByCommentID(commentID int64) ([]*Attachment, error) {
|
||||
return getAttachmentsByCommentID(x, commentID)
|
||||
}
|
||||
|
||||
func getAttachmentsByReleaseID(e Engine, releaseID int64) ([]*Attachment, error) {
|
||||
attachments := make([]*Attachment, 0, 10)
|
||||
return attachments, e.Where("release_id = ?", releaseID).Find(&attachments)
|
||||
}
|
||||
|
||||
// GetAttachmentsByReleaseID returns all attachments of a release.
|
||||
func GetAttachmentsByReleaseID(releaseID int64) ([]*Attachment, error) {
|
||||
return getAttachmentsByReleaseID(x, releaseID)
|
||||
}
|
||||
|
||||
// DeleteAttachment deletes the given attachment and optionally the associated file.
|
||||
func DeleteAttachment(a *Attachment, remove bool) error {
|
||||
_, err := DeleteAttachments([]*Attachment{a}, remove)
|
||||
|
|
|
@ -741,7 +741,7 @@ func newIssue(e *xorm.Session, opts NewIssueOptions) (err error) {
|
|||
return opts.Issue.loadAttributes(e)
|
||||
}
|
||||
|
||||
// NewIssue creates new issue with labels for repository.
|
||||
// NewIssue creates new issue with labels and attachments for repository.
|
||||
func NewIssue(repo *Repository, issue *Issue, labelIDs []int64, uuids []string) (err error) {
|
||||
sess := x.NewSession()
|
||||
defer sessionRelease(sess)
|
||||
|
|
|
@ -39,6 +39,8 @@ type Release struct {
|
|||
|
||||
Created time.Time `xorm:"-"`
|
||||
CreatedUnix int64
|
||||
|
||||
Attachments []*Attachment `xorm:"-"`
|
||||
}
|
||||
|
||||
func (r *Release) BeforeInsert() {
|
||||
|
@ -74,6 +76,13 @@ func (r *Release) loadAttributes(e Engine) (err error) {
|
|||
}
|
||||
}
|
||||
|
||||
if r.Attachments == nil {
|
||||
r.Attachments, err = getAttachmentsByReleaseID(e, r.ID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("getAttachmentsByReleaseID [%d]: %v", r.ID, err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -150,8 +159,8 @@ func (r *Release) preparePublishWebhooks() {
|
|||
}
|
||||
}
|
||||
|
||||
// CreateRelease creates a new release of repository.
|
||||
func CreateRelease(gitRepo *git.Repository, r *Release) error {
|
||||
// NewRelease creates a new release with attachments for repository.
|
||||
func NewRelease(gitRepo *git.Repository, r *Release, uuids []string) error {
|
||||
isExist, err := IsReleaseExist(r.RepoID, r.TagName)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -163,10 +172,27 @@ func CreateRelease(gitRepo *git.Repository, r *Release) error {
|
|||
return err
|
||||
}
|
||||
r.LowerTagName = strings.ToLower(r.TagName)
|
||||
if _, err = x.Insert(r); err != nil {
|
||||
|
||||
sess := x.NewSession()
|
||||
defer sessionRelease(sess)
|
||||
if err = sess.Begin(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err = sess.Insert(r); err != nil {
|
||||
return fmt.Errorf("Insert: %v", err)
|
||||
}
|
||||
|
||||
if len(uuids) > 0 {
|
||||
if _, err = sess.In("uuid", uuids).Cols("release_id").Update(&Attachment{ReleaseID: r.ID}); err != nil {
|
||||
return fmt.Errorf("link attachments: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
if err = sess.Commit(); err != nil {
|
||||
return fmt.Errorf("Commit: %v", err)
|
||||
}
|
||||
|
||||
// Only send webhook when actually published, skip drafts
|
||||
if r.IsDraft {
|
||||
return nil
|
||||
|
@ -254,15 +280,36 @@ func SortReleases(rels []*Release) {
|
|||
}
|
||||
|
||||
// UpdateRelease updates information of a release.
|
||||
func UpdateRelease(doer *User, gitRepo *git.Repository, r *Release, isPublish bool) (err error) {
|
||||
func UpdateRelease(doer *User, gitRepo *git.Repository, r *Release, isPublish bool, uuids []string) (err error) {
|
||||
if err = createTag(gitRepo, r); err != nil {
|
||||
return fmt.Errorf("createTag: %v", err)
|
||||
}
|
||||
|
||||
r.PublisherID = doer.ID
|
||||
if _, err = x.Id(r.ID).AllCols().Update(r); err != nil {
|
||||
|
||||
sess := x.NewSession()
|
||||
defer sessionRelease(sess)
|
||||
if err = sess.Begin(); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err = sess.Id(r.ID).AllCols().Update(r); err != nil {
|
||||
return fmt.Errorf("Update: %v", err)
|
||||
}
|
||||
|
||||
// Unlink all current attachments and link back later if still valid
|
||||
if _, err = sess.Exec("UPDATE attachment SET release_id = 0 WHERE release_id = ?", r.ID); err != nil {
|
||||
return fmt.Errorf("unlink current attachments: %v", err)
|
||||
}
|
||||
|
||||
if len(uuids) > 0 {
|
||||
if _, err = sess.In("uuid", uuids).Cols("release_id").Update(&Attachment{ReleaseID: r.ID}); err != nil {
|
||||
return fmt.Errorf("link attachments: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
if err = sess.Commit(); err != nil {
|
||||
return fmt.Errorf("Commit: %v", err)
|
||||
}
|
||||
|
||||
if !isPublish {
|
||||
return nil
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -200,7 +200,7 @@ func (f *NewDiscordHook) Validate(ctx *macaron.Context, errs binding.Errors) bin
|
|||
// |___/____ >____ >____/ \___ >
|
||||
// \/ \/ \/
|
||||
|
||||
type CreateIssue struct {
|
||||
type NewIssue struct {
|
||||
Title string `binding:"Required;MaxSize(255)"`
|
||||
LabelIDs string `form:"label_ids"`
|
||||
MilestoneID int64
|
||||
|
@ -209,7 +209,7 @@ type CreateIssue struct {
|
|||
Files []string
|
||||
}
|
||||
|
||||
func (f *CreateIssue) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
func (f *NewIssue) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
return validate(errs, ctx.Data, f, ctx.Locale)
|
||||
}
|
||||
|
||||
|
@ -279,6 +279,7 @@ type NewRelease struct {
|
|||
Content string
|
||||
Draft string
|
||||
Prerelease bool
|
||||
Files []string
|
||||
}
|
||||
|
||||
func (f *NewRelease) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
|
@ -290,6 +291,7 @@ type EditRelease struct {
|
|||
Content string
|
||||
Draft string
|
||||
Prerelease bool
|
||||
Files []string
|
||||
}
|
||||
|
||||
func (f *EditRelease) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||
|
|
|
@ -146,6 +146,17 @@ var (
|
|||
PagingNum int
|
||||
}
|
||||
|
||||
// Release settigns
|
||||
Release struct {
|
||||
Attachment struct {
|
||||
Enabled bool
|
||||
TempPath string
|
||||
AllowedTypes []string `delim:"|"`
|
||||
MaxSize int64
|
||||
MaxFiles int
|
||||
} `ini:"-"`
|
||||
}
|
||||
|
||||
// Markdown sttings
|
||||
Markdown struct {
|
||||
EnableHardLineBreak bool
|
||||
|
@ -590,6 +601,8 @@ func NewContext() {
|
|||
log.Fatal(2, "Fail to map HTTP settings: %v", err)
|
||||
} else if err = Cfg.Section("webhook").MapTo(&Webhook); err != nil {
|
||||
log.Fatal(2, "Fail to map Webhook settings: %v", err)
|
||||
} else if err = Cfg.Section("release.attachment").MapTo(&Release.Attachment); err != nil {
|
||||
log.Fatal(2, "Fail to map Release.Attachment settings: %v", err)
|
||||
} else if err = Cfg.Section("markdown").MapTo(&Markdown); err != nil {
|
||||
log.Fatal(2, "Fail to map Markdown settings: %v", err)
|
||||
} else if err = Cfg.Section("smartypants").MapTo(&Smartypants); err != nil {
|
||||
|
|
|
@ -23,7 +23,7 @@ func ServeData(ctx *context.Context, name string, reader io.Reader) error {
|
|||
|
||||
if !base.IsTextFile(buf) {
|
||||
if !base.IsImageFile(buf) {
|
||||
ctx.Resp.Header().Set("Content-Disposition", "attachment; filename=\""+path.Base(ctx.Repo.TreePath)+"\"")
|
||||
ctx.Resp.Header().Set("Content-Disposition", "attachment; filename=\""+name+"\"")
|
||||
ctx.Resp.Header().Set("Content-Transfer-Encoding", "binary")
|
||||
}
|
||||
} else if !ctx.QueryBool("render") {
|
||||
|
@ -40,7 +40,7 @@ func ServeBlob(ctx *context.Context, blob *git.Blob) error {
|
|||
return err
|
||||
}
|
||||
|
||||
return ServeData(ctx, ctx.Repo.TreePath, dataRc)
|
||||
return ServeData(ctx, path.Base(ctx.Repo.TreePath), dataRc)
|
||||
}
|
||||
|
||||
func SingleDownload(ctx *context.Context) {
|
||||
|
|
|
@ -348,7 +348,7 @@ func NewIssue(ctx *context.Context) {
|
|||
ctx.HTML(200, ISSUE_NEW)
|
||||
}
|
||||
|
||||
func ValidateRepoMetas(ctx *context.Context, f form.CreateIssue) ([]int64, int64, int64) {
|
||||
func ValidateRepoMetas(ctx *context.Context, f form.NewIssue) ([]int64, int64, int64) {
|
||||
var (
|
||||
repo = ctx.Repo.Repository
|
||||
err error
|
||||
|
@ -402,34 +402,30 @@ func ValidateRepoMetas(ctx *context.Context, f form.CreateIssue) ([]int64, int64
|
|||
return labelIDs, milestoneID, assigneeID
|
||||
}
|
||||
|
||||
func NewIssuePost(ctx *context.Context, f form.CreateIssue) {
|
||||
func NewIssuePost(ctx *context.Context, f form.NewIssue) {
|
||||
ctx.Data["Title"] = ctx.Tr("repo.issues.new")
|
||||
ctx.Data["PageIsIssueList"] = true
|
||||
ctx.Data["RequireHighlightJS"] = true
|
||||
ctx.Data["RequireSimpleMDE"] = true
|
||||
renderAttachmentSettings(ctx)
|
||||
|
||||
var (
|
||||
repo = ctx.Repo.Repository
|
||||
attachments []string
|
||||
)
|
||||
|
||||
labelIDs, milestoneID, assigneeID := ValidateRepoMetas(ctx, f)
|
||||
if ctx.Written() {
|
||||
return
|
||||
}
|
||||
|
||||
if setting.AttachmentEnabled {
|
||||
attachments = f.Files
|
||||
}
|
||||
|
||||
if ctx.HasError() {
|
||||
ctx.HTML(200, ISSUE_NEW)
|
||||
return
|
||||
}
|
||||
|
||||
var attachments []string
|
||||
if setting.AttachmentEnabled {
|
||||
attachments = f.Files
|
||||
}
|
||||
|
||||
issue := &models.Issue{
|
||||
RepoID: repo.ID,
|
||||
RepoID: ctx.Repo.Repository.ID,
|
||||
Title: f.Title,
|
||||
PosterID: ctx.User.ID,
|
||||
Poster: ctx.User,
|
||||
|
@ -437,21 +433,16 @@ func NewIssuePost(ctx *context.Context, f form.CreateIssue) {
|
|||
AssigneeID: assigneeID,
|
||||
Content: f.Content,
|
||||
}
|
||||
if err := models.NewIssue(repo, issue, labelIDs, attachments); err != nil {
|
||||
if err := models.NewIssue(ctx.Repo.Repository, issue, labelIDs, attachments); err != nil {
|
||||
ctx.Handle(500, "NewIssue", err)
|
||||
return
|
||||
}
|
||||
|
||||
log.Trace("Issue created: %d/%d", repo.ID, issue.ID)
|
||||
log.Trace("Issue created: %d/%d", ctx.Repo.Repository.ID, issue.ID)
|
||||
ctx.Redirect(ctx.Repo.RepoLink + "/issues/" + com.ToStr(issue.Index))
|
||||
}
|
||||
|
||||
func UploadIssueAttachment(ctx *context.Context) {
|
||||
if !setting.AttachmentEnabled {
|
||||
ctx.Error(404, "attachment is not enabled")
|
||||
return
|
||||
}
|
||||
|
||||
func uploadAttachment(ctx *context.Context, allowedTypes []string) {
|
||||
file, header, err := ctx.Req.FormFile("file")
|
||||
if err != nil {
|
||||
ctx.Error(500, fmt.Sprintf("FormFile: %v", err))
|
||||
|
@ -466,7 +457,6 @@ func UploadIssueAttachment(ctx *context.Context) {
|
|||
}
|
||||
fileType := http.DetectContentType(buf)
|
||||
|
||||
allowedTypes := strings.Split(setting.AttachmentAllowedTypes, ",")
|
||||
allowed := false
|
||||
for _, t := range allowedTypes {
|
||||
t := strings.Trim(t, " ")
|
||||
|
@ -493,6 +483,15 @@ func UploadIssueAttachment(ctx *context.Context) {
|
|||
})
|
||||
}
|
||||
|
||||
func UploadIssueAttachment(ctx *context.Context) {
|
||||
if !setting.AttachmentEnabled {
|
||||
ctx.NotFound()
|
||||
return
|
||||
}
|
||||
|
||||
uploadAttachment(ctx, strings.Split(setting.AttachmentAllowedTypes, ","))
|
||||
}
|
||||
|
||||
func ViewIssue(ctx *context.Context) {
|
||||
ctx.Data["RequireHighlightJS"] = true
|
||||
ctx.Data["RequireDropzone"] = true
|
||||
|
|
|
@ -634,7 +634,7 @@ func CompareAndPullRequest(ctx *context.Context) {
|
|||
ctx.HTML(200, COMPARE_PULL)
|
||||
}
|
||||
|
||||
func CompareAndPullRequestPost(ctx *context.Context, f form.CreateIssue) {
|
||||
func CompareAndPullRequestPost(ctx *context.Context, f form.NewIssue) {
|
||||
ctx.Data["Title"] = ctx.Tr("repo.pulls.compare_changes")
|
||||
ctx.Data["PageIsComparePull"] = true
|
||||
ctx.Data["IsDiffCompare"] = true
|
||||
|
|
|
@ -6,6 +6,7 @@ package repo
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
log "gopkg.in/clog.v1"
|
||||
|
||||
|
@ -14,6 +15,7 @@ import (
|
|||
"github.com/gogits/gogs/modules/context"
|
||||
"github.com/gogits/gogs/modules/form"
|
||||
"github.com/gogits/gogs/modules/markdown"
|
||||
"github.com/gogits/gogs/modules/setting"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -148,16 +150,26 @@ func Releases(ctx *context.Context) {
|
|||
ctx.HTML(200, RELEASES)
|
||||
}
|
||||
|
||||
func renderReleaseAttachmentSettings(ctx *context.Context) {
|
||||
ctx.Data["RequireDropzone"] = true
|
||||
ctx.Data["IsAttachmentEnabled"] = setting.Release.Attachment.Enabled
|
||||
ctx.Data["AttachmentAllowedTypes"] = strings.Join(setting.Release.Attachment.AllowedTypes, ",")
|
||||
ctx.Data["AttachmentMaxSize"] = setting.Release.Attachment.MaxSize
|
||||
ctx.Data["AttachmentMaxFiles"] = setting.Release.Attachment.MaxFiles
|
||||
}
|
||||
|
||||
func NewRelease(ctx *context.Context) {
|
||||
ctx.Data["Title"] = ctx.Tr("repo.release.new_release")
|
||||
ctx.Data["PageIsReleaseList"] = true
|
||||
ctx.Data["tag_target"] = ctx.Repo.Repository.DefaultBranch
|
||||
renderReleaseAttachmentSettings(ctx)
|
||||
ctx.HTML(200, RELEASE_NEW)
|
||||
}
|
||||
|
||||
func NewReleasePost(ctx *context.Context, f form.NewRelease) {
|
||||
ctx.Data["Title"] = ctx.Tr("repo.release.new_release")
|
||||
ctx.Data["PageIsReleaseList"] = true
|
||||
renderReleaseAttachmentSettings(ctx)
|
||||
|
||||
if ctx.HasError() {
|
||||
ctx.HTML(200, RELEASE_NEW)
|
||||
|
@ -169,6 +181,7 @@ func NewReleasePost(ctx *context.Context, f form.NewRelease) {
|
|||
return
|
||||
}
|
||||
|
||||
// Use current time if tag not yet exist, otherwise get time from Git
|
||||
var tagCreatedUnix int64
|
||||
tag, err := ctx.Repo.GitRepo.GetTag(f.TagName)
|
||||
if err == nil {
|
||||
|
@ -190,6 +203,11 @@ func NewReleasePost(ctx *context.Context, f form.NewRelease) {
|
|||
return
|
||||
}
|
||||
|
||||
var attachments []string
|
||||
if setting.Release.Attachment.Enabled {
|
||||
attachments = f.Files
|
||||
}
|
||||
|
||||
rel := &models.Release{
|
||||
RepoID: ctx.Repo.Repository.ID,
|
||||
PublisherID: ctx.User.ID,
|
||||
|
@ -203,7 +221,7 @@ func NewReleasePost(ctx *context.Context, f form.NewRelease) {
|
|||
IsPrerelease: f.Prerelease,
|
||||
CreatedUnix: tagCreatedUnix,
|
||||
}
|
||||
if err = models.CreateRelease(ctx.Repo.GitRepo, rel); err != nil {
|
||||
if err = models.NewRelease(ctx.Repo.GitRepo, rel, attachments); err != nil {
|
||||
ctx.Data["Err_TagName"] = true
|
||||
switch {
|
||||
case models.IsErrReleaseAlreadyExist(err):
|
||||
|
@ -211,7 +229,7 @@ func NewReleasePost(ctx *context.Context, f form.NewRelease) {
|
|||
case models.IsErrInvalidTagName(err):
|
||||
ctx.RenderWithErr(ctx.Tr("repo.release.tag_name_invalid"), RELEASE_NEW, &f)
|
||||
default:
|
||||
ctx.Handle(500, "CreateRelease", err)
|
||||
ctx.Handle(500, "NewRelease", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
@ -224,6 +242,7 @@ func EditRelease(ctx *context.Context) {
|
|||
ctx.Data["Title"] = ctx.Tr("repo.release.edit_release")
|
||||
ctx.Data["PageIsReleaseList"] = true
|
||||
ctx.Data["PageIsEditRelease"] = true
|
||||
renderReleaseAttachmentSettings(ctx)
|
||||
|
||||
tagName := ctx.Params("*")
|
||||
rel, err := models.GetRelease(ctx.Repo.Repository.ID, tagName)
|
||||
|
@ -240,6 +259,7 @@ func EditRelease(ctx *context.Context) {
|
|||
ctx.Data["tag_target"] = rel.Target
|
||||
ctx.Data["title"] = rel.Title
|
||||
ctx.Data["content"] = rel.Note
|
||||
ctx.Data["attachments"] = rel.Attachments
|
||||
ctx.Data["prerelease"] = rel.IsPrerelease
|
||||
ctx.Data["IsDraft"] = rel.IsDraft
|
||||
|
||||
|
@ -250,6 +270,7 @@ func EditReleasePost(ctx *context.Context, f form.EditRelease) {
|
|||
ctx.Data["Title"] = ctx.Tr("repo.release.edit_release")
|
||||
ctx.Data["PageIsReleaseList"] = true
|
||||
ctx.Data["PageIsEditRelease"] = true
|
||||
renderReleaseAttachmentSettings(ctx)
|
||||
|
||||
tagName := ctx.Params("*")
|
||||
rel, err := models.GetRelease(ctx.Repo.Repository.ID, tagName)
|
||||
|
@ -265,6 +286,7 @@ func EditReleasePost(ctx *context.Context, f form.EditRelease) {
|
|||
ctx.Data["tag_target"] = rel.Target
|
||||
ctx.Data["title"] = rel.Title
|
||||
ctx.Data["content"] = rel.Note
|
||||
ctx.Data["attachments"] = rel.Attachments
|
||||
ctx.Data["prerelease"] = rel.IsPrerelease
|
||||
ctx.Data["IsDraft"] = rel.IsDraft
|
||||
|
||||
|
@ -273,18 +295,31 @@ func EditReleasePost(ctx *context.Context, f form.EditRelease) {
|
|||
return
|
||||
}
|
||||
|
||||
var attachments []string
|
||||
if setting.Release.Attachment.Enabled {
|
||||
attachments = f.Files
|
||||
}
|
||||
|
||||
isPublish := rel.IsDraft && len(f.Draft) == 0
|
||||
rel.Title = f.Title
|
||||
rel.Note = f.Content
|
||||
rel.IsDraft = len(f.Draft) > 0
|
||||
rel.IsPrerelease = f.Prerelease
|
||||
if err = models.UpdateRelease(ctx.User, ctx.Repo.GitRepo, rel, isPublish); err != nil {
|
||||
if err = models.UpdateRelease(ctx.User, ctx.Repo.GitRepo, rel, isPublish, attachments); err != nil {
|
||||
ctx.Handle(500, "UpdateRelease", err)
|
||||
return
|
||||
}
|
||||
ctx.Redirect(ctx.Repo.RepoLink + "/releases")
|
||||
}
|
||||
|
||||
func UploadReleaseAttachment(ctx *context.Context) {
|
||||
if !setting.Release.Attachment.Enabled {
|
||||
ctx.NotFound()
|
||||
return
|
||||
}
|
||||
uploadAttachment(ctx, setting.Release.Attachment.AllowedTypes)
|
||||
}
|
||||
|
||||
func DeleteRelease(ctx *context.Context) {
|
||||
if err := models.DeleteReleaseOfRepoByID(ctx.Repo.Repository.ID, ctx.QueryInt64("id")); err != nil {
|
||||
ctx.Flash.Error("DeleteReleaseByID: " + err.Error())
|
||||
|
|
|
@ -1 +1 @@
|
|||
0.10.17.0313
|
||||
0.10.18.0313
|
|
@ -51,12 +51,19 @@
|
|||
<div class="download">
|
||||
<h2>{{$.i18n.Tr "repo.release.downloads"}}</h2>
|
||||
<ul class="list">
|
||||
<li>
|
||||
<a href="{{$.RepoLink}}/archive/{{.TagName}}.zip" rel="nofollow"><i class="octicon octicon-file-zip"></i> {{$.i18n.Tr "repo.release.source_code"}} (ZIP)</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="{{$.RepoLink}}/archive/{{.TagName}}.tar.gz"><i class="octicon octicon-file-zip"></i> {{$.i18n.Tr "repo.release.source_code"}} (TAR.GZ)</a>
|
||||
</li>
|
||||
{{range .Attachments}}
|
||||
<li>
|
||||
<i class="octicon octicon-package"></i> <a href="{{AppSubUrl}}/attachments/{{.UUID}}" rel="nofollow">{{.Name}}</a>
|
||||
</li>
|
||||
{{end}}
|
||||
{{if not .IsDraft}}
|
||||
<li>
|
||||
<i class="octicon octicon-file-zip"></i> <a href="{{$.RepoLink}}/archive/{{.TagName}}.zip" rel="nofollow">{{$.i18n.Tr "repo.release.source_code"}} (ZIP)</a>
|
||||
</li>
|
||||
<li>
|
||||
<i class="octicon octicon-file-zip"></i> <a href="{{$.RepoLink}}/archive/{{.TagName}}.tar.gz">{{$.i18n.Tr "repo.release.source_code"}} (TAR.GZ)</a>
|
||||
</li>
|
||||
{{end}}
|
||||
</ul>
|
||||
</div>
|
||||
{{else}}
|
||||
|
|
|
@ -48,42 +48,60 @@
|
|||
<label>{{.i18n.Tr "repo.release.content"}}</label>
|
||||
<textarea name="content">{{.content}}</textarea>
|
||||
</div>
|
||||
{{if .attachments}}
|
||||
<table class="ui table">
|
||||
<thead></thead>
|
||||
<tbody>
|
||||
{{range .attachments}}
|
||||
<tr>
|
||||
<td>
|
||||
<a target="_blank" href="{{AppSubUrl}}/attachments/{{.UUID}}" rel="nofollow">{{.Name}}</a>
|
||||
<a class="ui text red right delete-attachment-button" href="#"><i class="octicon octicon-x" data-uuid="{{.UUID}}"></i></a>
|
||||
<input name="files" type="hidden" value="{{.UUID}}">
|
||||
</td>
|
||||
</tr>
|
||||
{{end}}
|
||||
</tbody>
|
||||
</table>
|
||||
{{end}}
|
||||
{{if .IsAttachmentEnabled}}
|
||||
<div class="files"></div>
|
||||
<div class="ui basic button dropzone" id="dropzone" data-upload-url="{{AppSubUrl}}/releases/attachments" data-accepts="{{.AttachmentAllowedTypes}}" data-max-file="{{.AttachmentMaxFiles}}" data-max-size="{{.AttachmentMaxSize}}" data-default-message="{{.i18n.Tr "dropzone.default_message"}}" data-invalid-input-type="{{.i18n.Tr "dropzone.invalid_input_type"}}" data-file-too-big="{{.i18n.Tr "dropzone.file_too_big"}}" data-remove-file="{{.i18n.Tr "dropzone.remove_file"}}"></div>
|
||||
{{end}}
|
||||
</div>
|
||||
<div class="ui container">
|
||||
<div class="prerelease field">
|
||||
<div class="ui checkbox">
|
||||
<input type="checkbox" name="prerelease" {{if .prerelease}}checked{{end}}>
|
||||
<label><strong>{{.i18n.Tr "repo.release.prerelease_desc"}}</strong></label>
|
||||
</div>
|
||||
</div>
|
||||
<span class="help">{{.i18n.Tr "repo.release.prerelease_helper"}}</span>
|
||||
<div class="ui divider"></div>
|
||||
<div class="ui text right">
|
||||
<div class="prerelease field">
|
||||
<div class="ui checkbox">
|
||||
<input type="checkbox" name="prerelease" {{if .prerelease}}checked{{end}}>
|
||||
<label><strong>{{.i18n.Tr "repo.release.prerelease_desc"}}</strong></label>
|
||||
</div>
|
||||
</div>
|
||||
<span class="help">{{.i18n.Tr "repo.release.prerelease_helper"}}</span>
|
||||
<div class="field">
|
||||
<a class="ui blue basic button" href="{{.RepoLink}}/releases">
|
||||
{{.i18n.Tr "repo.release.cancel"}}
|
||||
</a>
|
||||
{{/* Release didn't save as draft at first time is not possible to be draft again because the Git tag had been created. */}}
|
||||
{{if or (not .PageIsEditRelease) .IsDraft}}
|
||||
<input class="ui grey button" type="submit" name="draft" value="{{.i18n.Tr "repo.release.save_draft"}}"/>
|
||||
{{end}}
|
||||
{{if .PageIsEditRelease}}
|
||||
<button class="ui green button">
|
||||
{{if .IsDraft}}
|
||||
{{.i18n.Tr "repo.release.publish"}}
|
||||
{{else}}
|
||||
{{.i18n.Tr "repo.release.edit_release"}}
|
||||
{{end}}
|
||||
</button>
|
||||
<a class="ui red button delete-button" data-url="{{$.RepoLink}}/releases/delete" data-id="{{.ID}}">
|
||||
{{$.i18n.Tr "repo.release.delete_release"}}
|
||||
</a>
|
||||
{{else}}
|
||||
<button class="ui green button">
|
||||
<div class="field">
|
||||
{{if .PageIsEditRelease}}
|
||||
<button class="ui green button">
|
||||
{{if .IsDraft}}
|
||||
{{.i18n.Tr "repo.release.publish"}}
|
||||
</button>
|
||||
{{end}}
|
||||
</div>
|
||||
{{else}}
|
||||
{{.i18n.Tr "repo.release.edit_release"}}
|
||||
{{end}}
|
||||
</button>
|
||||
<a class="ui red button delete-button" data-url="{{$.RepoLink}}/releases/delete" data-id="{{.ID}}">
|
||||
{{$.i18n.Tr "repo.release.delete_release"}}
|
||||
</a>
|
||||
{{else}}
|
||||
<button class="ui green button">
|
||||
{{.i18n.Tr "repo.release.publish"}}
|
||||
</button>
|
||||
{{end}}
|
||||
{{/* Release didn't save as draft at first time is not possible to be draft again because the Git tag had been created. */}}
|
||||
{{if or (not .PageIsEditRelease) .IsDraft}}
|
||||
<input class="ui grey button" type="submit" name="draft" value="{{.i18n.Tr "repo.release.save_draft"}}"/>
|
||||
{{end}}
|
||||
<a class="ui basic button" href="{{.RepoLink}}/releases">
|
||||
{{.i18n.Tr "repo.release.cancel"}}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
@ -102,4 +120,13 @@
|
|||
{{template "base/delete_modal_actions" .}}
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
<script>
|
||||
// Delete attachment field
|
||||
$('.delete-attachment-button').click(function (e) {
|
||||
$(this).parentsUntil('tbody').remove();
|
||||
e.preventDefault();
|
||||
})
|
||||
</script>
|
||||
|
||||
{{template "base/footer" .}}
|
||||
|
|
Loading…
Reference in New Issue