diff --git a/conf/app.ini b/conf/app.ini index b4b2509f2..9674b815c 100644 --- a/conf/app.ini +++ b/conf/app.ini @@ -389,7 +389,7 @@ MODE = console ; Buffer length of channel, keep it as it is if you don't know what it is. BUFFER_LEN = 10000 ; Either "Trace", "Debug", "Info", "Warn", "Error", "Critical", default is "Trace" -LEVEL = Debug +LEVEL = Trace ; For "console" mode only [log.console] diff --git a/models/issue_comment.go b/models/issue_comment.go index a3e54b4fc..bc2b86a25 100644 --- a/models/issue_comment.go +++ b/models/issue_comment.go @@ -62,6 +62,8 @@ const ( CommentTypeCancelTracking // Dependency added CommentTypeAddedDependency + //Dependency removed + CommentTypeRemovedDependency ) // CommentTag defines comment tag type diff --git a/models/issue_dependency.go b/models/issue_dependency.go index 802514565..95a4517b4 100644 --- a/models/issue_dependency.go +++ b/models/issue_dependency.go @@ -6,18 +6,19 @@ package models import ( "time" + "strconv" ) // IssueDependency is connection request for receiving issue notification. type IssueDependency struct { - ID int64 `xorm:"pk autoincr"` - UserID int64 `xorm:"UNIQUE(watch) NOT NULL"` - IssueID int64 `xorm:"UNIQUE(watch) NOT NULL"` + ID int64 `xorm:"pk autoincr"` + UserID int64 `xorm:"UNIQUE(watch) NOT NULL"` + IssueID int64 `xorm:"UNIQUE(watch) NOT NULL"` DependencyID int64 `xorm:"UNIQUE(watch) NOT NULL"` - Created time.Time `xorm:"-"` - CreatedUnix int64 `xorm:"NOT NULL"` - Updated time.Time `xorm:"-"` - UpdatedUnix int64 `xorm:"NOT NULL"` + Created time.Time `xorm:"-"` + CreatedUnix int64 `xorm:"NOT NULL"` + Updated time.Time `xorm:"-"` + UpdatedUnix int64 `xorm:"NOT NULL"` } // BeforeInsert is invoked from XORM before inserting an object of this type. @@ -43,61 +44,70 @@ func (iw *IssueDependency) BeforeUpdate() { } // CreateIssueDependency creates a new dependency for an issue -func CreateIssueDependency(user *User, issue, dep *Issue) (err error, exists bool, depExists bool) { - sess := x.NewSession() - - // TODO: Move this to the appropriate place +// TODO: prevent issues having itself as dependency +func CreateIssueDependency(userID, issueID int64, depID int64) (err error, exists bool, depExists bool) { err = x.Sync(new(IssueDependency)) if err != nil { return err, exists, false } // Check if it aleready exists - exists, err = issueDepExists(x, issue.ID, dep.ID) + exists, err = issueDepExists(x, issueID, depID) if err != nil { return err, exists, false } // If it not exists, create it, otherwise show an error message if !exists { - newId := new(IssueDependency) - newId.UserID = user.ID - newId.IssueID = issue.ID - newId.DependencyID = dep.ID + // Check if the other issue exists + var issue = Issue{} + issueExists, err := x.Id(depID).Get(&issue) + if issueExists { + newId := new(IssueDependency) + newId.UserID = userID + newId.IssueID = issueID + newId.DependencyID = depID - if _, err := x.Insert(newId); err != nil { - return err, exists, false - } - - // Add comment referencing the new dependency - _, err = createIssueDependencyComment(sess, user, issue, dep, true) - - if err != nil { - return err, exists, false - } - - // Create a new comment for the dependent issue - _, err = createIssueDependencyComment(sess, user, dep, issue, true) - - if err != nil { - return err, exists, false + if _, err := x.Insert(newId); err != nil { + return err, exists, false + } + + // Add comment referencing the new dependency + comment := &Comment{ + IssueID: issueID, + PosterID: userID, + Type: CommentTypeAddedDependency, + Content: strconv.FormatInt(depID, 10), + } + + if _, err := x.Insert(comment); err != nil { + return err, exists, false + } + comment = &Comment{ + IssueID: depID, + PosterID: userID, + Type: CommentTypeAddedDependency, + Content: strconv.FormatInt(issueID, 10), + } + + if _, err := x.Insert(comment); err != nil { + return err, exists, false + } } + return err, exists, true } - return nil, exists, true + return nil, exists, false } // Removes a dependency from an issue -func RemoveIssueDependency(user *User, issue *Issue, dep *Issue, depType int64) (err error) { - sess := x.NewSession() - - // TODO: Same as above +func RemoveIssueDependency(userID, issueID int64, depID int64, depType int64) (err error) { err = x.Sync(new(IssueDependency)) if err != nil { return err } // Check if it exists - exists, err := issueDepExists(x, issue.ID, dep.ID) + exists, err := issueDepExists(x, issueID, depID) if err != nil { return err } @@ -105,31 +115,40 @@ func RemoveIssueDependency(user *User, issue *Issue, dep *Issue, depType int64) // If it exists, remove it, otherwise show an error message if exists { - if depType == 1 { - _, err := x.Delete(&IssueDependency{IssueID: issue.ID, DependencyID: dep.ID}) + if depType == 1{ + _, err := x.Delete(&IssueDependency{IssueID: issueID, DependencyID: depID}) if err != nil { return err } } - if depType == 2 { - _, err := x.Delete(&IssueDependency{IssueID: dep.ID, DependencyID: issue.ID}) + if depType == 2{ + _, err := x.Delete(&IssueDependency{IssueID: depID, DependencyID: issueID}) if err != nil { return err } } // Add comment referencing the removed dependency - _, err = createIssueDependencyComment(sess, user, issue, dep, false) + comment := &Comment{ + IssueID: issueID, + PosterID: userID, + Type: CommentTypeRemovedDependency, + Content: strconv.FormatInt(depID, 10), + } - if err != nil { + if _, err := x.Insert(comment); err != nil { return err } - // Create a new comment for the dependent issue - _, err = createIssueDependencyComment(sess, user, dep, issue, false) + comment = &Comment{ + IssueID: depID, + PosterID: userID, + Type: CommentTypeRemovedDependency, + Content: strconv.FormatInt(issueID, 10), + } - if err != nil { + if _, err := x.Insert(comment); err != nil { return err } } @@ -152,34 +171,3 @@ func issueDepExists(e Engine, issueID int64, depID int64) (exists bool, err erro return } - -// check if issue can be closed -func IssueNoDependenciesLeft(issue *Issue) bool { - - // Check if the Repo is allowed to have dependencies, if not return true (= issue can be closed) - // Otherwise check for all open dependencies - r, err := getRepositoryByID(x, issue.RepoID) - if err != nil { - return false - } - - if !r.UnitEnabled(UnitTypeIssueDependencies) { - return true - } - - var issueDeps []IssueDependency - err = x.Where("issue_id = ?", issue.ID).Find(&issueDeps) - - for _, issueDep := range issueDeps { - issueDetails, _ := getIssueByID(x, issueDep.DependencyID) - if !issueDetails.IsClosed { - return false - } - } - - if err != nil { - return false - } - - return true -} diff --git a/models/issue_dependency_add.go b/models/issue_dependency_add.go deleted file mode 100644 index 702a0a795..000000000 --- a/models/issue_dependency_add.go +++ /dev/null @@ -1,98 +0,0 @@ -// Copyright 2017 The Gitea Authors. All rights reserved. -// Use of this source code is governed by a MIT-style -// license that can be found in the LICENSE file. - -package models - -import ( - "time" -) - -// IssueDependency is connection request for receiving issue notification. -type IssueDependency struct { - ID int64 `xorm:"pk autoincr"` - UserID int64 `xorm:"UNIQUE(watch) NOT NULL"` - IssueID int64 `xorm:"UNIQUE(watch) NOT NULL"` - DependencyID int64 `xorm:"UNIQUE(watch) NOT NULL"` - Created time.Time `xorm:"-"` - CreatedUnix int64 `xorm:"NOT NULL"` - Updated time.Time `xorm:"-"` - UpdatedUnix int64 `xorm:"NOT NULL"` -} - -// BeforeInsert is invoked from XORM before inserting an object of this type. -func (iw *IssueDependency) BeforeInsert() { - var ( - t = time.Now() - u = t.Unix() - ) - iw.Created = t - iw.CreatedUnix = u - iw.Updated = t - iw.UpdatedUnix = u -} - -// BeforeUpdate is invoked from XORM before updating an object of this type. -func (iw *IssueDependency) BeforeUpdate() { - var ( - t = time.Now() - u = t.Unix() - ) - iw.Updated = t - iw.UpdatedUnix = u -} - -// CreateOrUpdateIssueDependency creates a new dependency for an issue -func CreateOrUpdateIssueDependency(userID, issueID int64, depID int64) (err error, exists bool) { - err = x.Sync(new(IssueDependency)) - if err != nil { - return err, exists - } - - // Check if it aleready exists - exists, err = issueDepExists(x, issueID, depID) - if err != nil { - return err, exists - } - - // If it not exists, create it, otherwise show an error message - if !exists { - newId := new(IssueDependency) - newId.UserID = userID - newId.IssueID = issueID - newId.DependencyID = depID - - if _, err := x.Insert(newId); err != nil { - return err, exists - } - - // Add comment referencing to the stopwatch - comment := &Comment{ - IssueID: issueID, - PosterID: userID, - Type: CommentTypeAddedDependency, - } - - if _, err := x.Insert(comment); err != nil { - return err, exists - } - } - return nil, exists -} - -// Check if the dependency already exists -func issueDepExists(e Engine, issueID int64, depID int64) (exists bool, err error) { - var Dependencies = IssueDependency{IssueID: issueID, DependencyID: depID} - - exists, err = e.Get(&Dependencies) - - // Check for dependencies the other way around - // Otherwise two issues could block each other which would result in none of them could be closed. - if !exists { - Dependencies.IssueID = depID - Dependencies.DependencyID = issueID - exists, err = e.Get(&Dependencies) - } - - return -} diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index dc2fc4968..1f7188f82 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -732,6 +732,7 @@ issues.dependency.cancel = Cancel issues.dependency.add_header = Add New Dependency issues.dependency.issue_number = Issuenumber issues.dependency.added_dependency = `%[2]s added a new dependency %[3]s` +issues.dependency.removed_dependency = `%[2]s removed a dependency %[3]s` pulls.desc = Pulls management your code review and merge requests diff --git a/routers/repo/issue_dependency_add.go b/routers/repo/issue_dependency_add.go index 03c4b3db4..ceb672356 100644 --- a/routers/repo/issue_dependency_add.go +++ b/routers/repo/issue_dependency_add.go @@ -28,12 +28,16 @@ func AddDependency(c *context.Context) { return } - err, exists := models.CreateOrUpdateIssueDependency(c.User.ID, issue.ID, dep); + err, exists, depExists := models.CreateIssueDependency(c.User.ID, issue.ID, dep); if err != nil { c.Handle(http.StatusInternalServerError, "CreateOrUpdateIssueDependency", err) return } + if !depExists { + c.Flash.Error("Dependend issue does not exist!") + } + if exists { c.Flash.Error("Dependency already exists!") } diff --git a/routers/repo/issue_dependency_remove.go b/routers/repo/issue_dependency_remove.go index 2885673c8..a12ed63da 100644 --- a/routers/repo/issue_dependency_remove.go +++ b/routers/repo/issue_dependency_remove.go @@ -15,7 +15,7 @@ import ( // IssueWatch sets issue watching func RemoveDependency(c *context.Context) { - depID, err := strconv.ParseInt(c.Req.PostForm.Get("removeDependencyID"), 10, 64) + dep, err := strconv.ParseInt(c.Req.PostForm.Get("removeDependencyID"), 10, 64) if err != nil { c.Handle(http.StatusBadRequest, "issue ID is not int", err) return @@ -41,14 +41,7 @@ func RemoveDependency(c *context.Context) { return } - // Dependency - dep, err := models.GetIssueByID(depID) - if err != nil { - c.Handle(http.StatusInternalServerError, "GetIssueByID", err) - return - } - - err = models.RemoveIssueDependency(c.User, issue, dep, depType) + err = models.RemoveIssueDependency(c.User.ID, issue.ID, dep, depType) if err != nil { c.Handle(http.StatusInternalServerError, "CreateOrUpdateIssueDependency", err) return diff --git a/routers/routes/routes.go b/routers/routes/routes.go index a2e6cbcb6..7dfaffe70 100644 --- a/routers/routes/routes.go +++ b/routers/routes/routes.go @@ -485,6 +485,7 @@ func RegisterRoutes(m *macaron.Macaron) { m.Post("/content", repo.UpdateIssueContent) m.Post("/watch", repo.IssueWatch) m.Post("/addDependency", repo.AddDependency) + m.Post("/removeDependency", repo.RemoveDependency) m.Group("/times", func() { m.Post("/add", bindIgnErr(auth.AddTimeManuallyForm{}), repo.AddTimeManually) m.Group("/stopwatch", func() { diff --git a/templates/repo/issue/view_content/comments.tmpl b/templates/repo/issue/view_content/comments.tmpl index f4224f44a..d9da733ec 100644 --- a/templates/repo/issue/view_content/comments.tmpl +++ b/templates/repo/issue/view_content/comments.tmpl @@ -193,5 +193,33 @@ {{$.i18n.Tr "repo.issues.dependency.added_dependency" .Poster.HomeLink .Poster.Name $createdStr | Safe}} {{end}} - + {{else if eq .Type 17}} +
+ + + + + + {{$.i18n.Tr "repo.issues.dependency.added_dependency" .Poster.HomeLink .Poster.Name $createdStr | Safe}} + +
+ + {{.Content}} +
+
+ {{else if eq .Type 18}} +
+ + + + + + {{$.i18n.Tr "repo.issues.dependency.removed_dependency" .Poster.HomeLink .Poster.Name $createdStr | Safe}} + +
+ + {{.Content}}  +
+
+ {{end}} {{end}} diff --git a/templates/repo/issue/view_content/sidebar.tmpl b/templates/repo/issue/view_content/sidebar.tmpl index 90b149ced..b9ec76f66 100644 --- a/templates/repo/issue/view_content/sidebar.tmpl +++ b/templates/repo/issue/view_content/sidebar.tmpl @@ -196,11 +196,15 @@
{{.i18n.Tr "repo.issues.dependency.title"}}
+ {{if .BlockedByDependencies}} This issue is blocked by:
{{range .BlockedByDependencies}}
+ + + {{if .IsClosed}}
@@ -216,14 +220,19 @@
{{end}}
+ {{end}} + {{if .BlockingDependencies}}
This issue blocks the following issues: {{range .BlockingDependencies}}
+ + + {{if .IsClosed}} -
+
{{else}} @@ -236,8 +245,12 @@ {{.Title}}
{{end}} -

{{.i18n.Tr "repo.issues.dependency.no_dependencies"}}

+ {{end}} + + {{if (and (not .BlockedByDependencies) (not .BlockingDependencies))}} +

{{.i18n.Tr "repo.issues.dependency.no_dependencies"}}

+ {{end}}
-
+ + +