summaryrefslogtreecommitdiffstats
path: root/modules/repofiles
diff options
context:
space:
mode:
authorLauris BH <lauris@nix.lv>2020-09-04 18:37:37 +0300
committerGitHub <noreply@github.com>2020-09-04 11:37:37 -0400
commite710a3498129a53343e08279012ea9c45988349f (patch)
treead353035dbb8a1b3bbebe29f043c92bc150f29ba /modules/repofiles
parent4c557eff5d4002299dd8a9dfca7917084c2307f6 (diff)
downloadgitea-e710a3498129a53343e08279012ea9c45988349f.tar.gz
gitea-e710a3498129a53343e08279012ea9c45988349f.zip
Add spent time to referenced issue in commit message (#12220)
Diffstat (limited to 'modules/repofiles')
-rw-r--r--modules/repofiles/action.go72
1 files changed, 72 insertions, 0 deletions
diff --git a/modules/repofiles/action.go b/modules/repofiles/action.go
index 464249d19b..05e9fc958d 100644
--- a/modules/repofiles/action.go
+++ b/modules/repofiles/action.go
@@ -8,7 +8,10 @@ import (
"encoding/json"
"fmt"
"html"
+ "regexp"
+ "strconv"
"strings"
+ "time"
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/modules/git"
@@ -19,6 +22,16 @@ import (
"code.gitea.io/gitea/modules/setting"
)
+const (
+ secondsByMinute = float64(time.Minute / time.Second) // seconds in a minute
+ secondsByHour = 60 * secondsByMinute // seconds in an hour
+ secondsByDay = 8 * secondsByHour // seconds in a day
+ secondsByWeek = 5 * secondsByDay // seconds in a week
+ secondsByMonth = 4 * secondsByWeek // seconds in a month
+)
+
+var reDuration = regexp.MustCompile(`(?i)^(?:(\d+([\.,]\d+)?)(?:mo))?(?:(\d+([\.,]\d+)?)(?:w))?(?:(\d+([\.,]\d+)?)(?:d))?(?:(\d+([\.,]\d+)?)(?:h))?(?:(\d+([\.,]\d+)?)(?:m))?$`)
+
// getIssueFromRef returns the issue referenced by a ref. Returns a nil *Issue
// if the provided ref references a non-existent issue.
func getIssueFromRef(repo *models.Repository, index int64) (*models.Issue, error) {
@@ -32,6 +45,60 @@ func getIssueFromRef(repo *models.Repository, index int64) (*models.Issue, error
return issue, nil
}
+// timeLogToAmount parses time log string and returns amount in seconds
+func timeLogToAmount(str string) int64 {
+ matches := reDuration.FindAllStringSubmatch(str, -1)
+ if len(matches) == 0 {
+ return 0
+ }
+
+ match := matches[0]
+
+ var a int64
+
+ // months
+ if len(match[1]) > 0 {
+ mo, _ := strconv.ParseFloat(strings.Replace(match[1], ",", ".", 1), 64)
+ a += int64(mo * secondsByMonth)
+ }
+
+ // weeks
+ if len(match[3]) > 0 {
+ w, _ := strconv.ParseFloat(strings.Replace(match[3], ",", ".", 1), 64)
+ a += int64(w * secondsByWeek)
+ }
+
+ // days
+ if len(match[5]) > 0 {
+ d, _ := strconv.ParseFloat(strings.Replace(match[5], ",", ".", 1), 64)
+ a += int64(d * secondsByDay)
+ }
+
+ // hours
+ if len(match[7]) > 0 {
+ h, _ := strconv.ParseFloat(strings.Replace(match[7], ",", ".", 1), 64)
+ a += int64(h * secondsByHour)
+ }
+
+ // minutes
+ if len(match[9]) > 0 {
+ d, _ := strconv.ParseFloat(strings.Replace(match[9], ",", ".", 1), 64)
+ a += int64(d * secondsByMinute)
+ }
+
+ return a
+}
+
+func issueAddTime(issue *models.Issue, doer *models.User, time time.Time, timeLog string) error {
+ amount := timeLogToAmount(timeLog)
+ if amount == 0 {
+ return nil
+ }
+
+ _, err := models.AddTime(doer, issue, amount, time)
+ return err
+}
+
func changeIssueStatus(repo *models.Repository, issue *models.Issue, doer *models.User, closed bool) error {
stopTimerIfAvailable := func(doer *models.User, issue *models.Issue) error {
@@ -139,6 +206,11 @@ func UpdateIssuesCommit(doer *models.User, repo *models.Repository, commits []*r
}
}
close := (ref.Action == references.XRefActionCloses)
+ if close && len(ref.TimeLog) > 0 {
+ if err := issueAddTime(refIssue, doer, c.Timestamp, ref.TimeLog); err != nil {
+ return err
+ }
+ }
if close != refIssue.IsClosed {
if err := changeIssueStatus(refRepo, refIssue, doer, close); err != nil {
return err