Skip to content

Commit

Permalink
Fix milestone deadline and date related problems (#32339)
Browse files Browse the repository at this point in the history
Use zero instead of 9999-12-31 for deadline
Fix #32291

---------

Co-authored-by: wxiaoguang <[email protected]>
Co-authored-by: Giteabot <[email protected]>
  • Loading branch information
3 people authored Nov 5, 2024
1 parent 1887c75 commit 24b83ff
Show file tree
Hide file tree
Showing 23 changed files with 147 additions and 165 deletions.
8 changes: 3 additions & 5 deletions models/actions/schedule_spec_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,17 @@ import (
"testing"
"time"

"code.gitea.io/gitea/modules/test"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestActionScheduleSpec_Parse(t *testing.T) {
// Mock the local timezone is not UTC
local := time.Local
tz, err := time.LoadLocation("Asia/Shanghai")
require.NoError(t, err)
defer func() {
time.Local = local
}()
time.Local = tz
defer test.MockVariableValue(&time.Local, tz)()

now, err := time.Parse(time.RFC3339, "2024-07-31T15:47:55+08:00")
require.NoError(t, err)
Expand Down
3 changes: 1 addition & 2 deletions models/issues/milestone.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,10 +84,9 @@ func (m *Milestone) BeforeUpdate() {
// this object.
func (m *Milestone) AfterLoad() {
m.NumOpenIssues = m.NumIssues - m.NumClosedIssues
if m.DeadlineUnix.Year() == 9999 {
if m.DeadlineUnix == 0 {
return
}

m.DeadlineString = m.DeadlineUnix.FormatDate()
if m.IsClosed {
m.IsOverdue = m.ClosedDateUnix >= m.DeadlineUnix
Expand Down
1 change: 1 addition & 0 deletions models/migrations/migrations.go
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,7 @@ func prepareMigrationTasks() []*migration {
newMigration(304, "Add index for release sha1", v1_23.AddIndexForReleaseSha1),
newMigration(305, "Add Repository Licenses", v1_23.AddRepositoryLicenses),
newMigration(306, "Add BlockAdminMergeOverride to ProtectedBranch", v1_23.AddBlockAdminMergeOverrideBranchProtection),
newMigration(307, "Fix milestone deadline_unix when there is no due date", v1_23.FixMilestoneNoDueDate),
}
return preparedMigrations
}
Expand Down
21 changes: 21 additions & 0 deletions models/migrations/v1_23/v307.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Copyright 2024 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT

package v1_23 //nolint

import (
"code.gitea.io/gitea/modules/timeutil"

"xorm.io/xorm"
)

func FixMilestoneNoDueDate(x *xorm.Engine) error {
type Milestone struct {
DeadlineUnix timeutil.TimeStamp
}
// Wednesday, December 1, 9999 12:00:00 AM GMT+00:00
_, err := x.Table("milestone").Where("deadline_unix > 253399622400").
Cols("deadline_unix").
Update(&Milestone{DeadlineUnix: 0})
return err
}
2 changes: 1 addition & 1 deletion modules/gitgraph/graph.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ func GetCommitGraph(r *git.Repository, page, maxAllowedColors int, hidePRRefs bo
graphCmd.AddArguments("--all")
}

graphCmd.AddArguments("-C", "-M", "--date=iso").
graphCmd.AddArguments("-C", "-M", "--date=iso-strict").
AddOptionFormat("-n %d", setting.UI.GraphMaxCommitNum*page).
AddOptionFormat("--pretty=format:%s", format)

Expand Down
13 changes: 11 additions & 2 deletions modules/gitgraph/graph_models.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"context"
"fmt"
"strings"
"time"

asymkey_model "code.gitea.io/gitea/models/asymkey"
"code.gitea.io/gitea/models/db"
Expand Down Expand Up @@ -192,6 +193,14 @@ var RelationCommit = &Commit{
Row: -1,
}

func parseGitTime(timeStr string) time.Time {
t, err := time.Parse(time.RFC3339, timeStr)
if err != nil {
return time.Unix(0, 0)
}
return t
}

// NewCommit creates a new commit from a provided line
func NewCommit(row, column int, line []byte) (*Commit, error) {
data := bytes.SplitN(line, []byte("|"), 5)
Expand All @@ -206,7 +215,7 @@ func NewCommit(row, column int, line []byte) (*Commit, error) {
// 1 matches git log --pretty=format:%H => commit hash
Rev: string(data[1]),
// 2 matches git log --pretty=format:%ad => author date (format respects --date= option)
Date: string(data[2]),
Date: parseGitTime(string(data[2])),
// 3 matches git log --pretty=format:%h => abbreviated commit hash
ShortRev: string(data[3]),
// 4 matches git log --pretty=format:%s => subject
Expand Down Expand Up @@ -245,7 +254,7 @@ type Commit struct {
Column int
Refs []git.Reference
Rev string
Date string
Date time.Time
ShortRev string
Subject string
}
Expand Down
2 changes: 1 addition & 1 deletion modules/templates/util_date.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ func (du *DateUtils) AbsoluteShort(time any) template.HTML {

// AbsoluteLong renders in "January 01, 2006" format
func (du *DateUtils) AbsoluteLong(time any) template.HTML {
return dateTimeFormat("short", time)
return dateTimeFormat("long", time)
}

// FullTime renders in "Jan 01, 2006 20:33:44" format
Expand Down
12 changes: 3 additions & 9 deletions routers/api/v1/repo/issue.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (
"code.gitea.io/gitea/modules/timeutil"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/routers/api/v1/utils"
"code.gitea.io/gitea/routers/common"
"code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/convert"
issue_service "code.gitea.io/gitea/services/issue"
Expand Down Expand Up @@ -1046,18 +1047,11 @@ func UpdateIssueDeadline(ctx *context.APIContext) {
return
}

var deadlineUnix timeutil.TimeStamp
var deadline time.Time
if form.Deadline != nil && !form.Deadline.IsZero() {
deadline = time.Date(form.Deadline.Year(), form.Deadline.Month(), form.Deadline.Day(),
23, 59, 59, 0, time.Local)
deadlineUnix = timeutil.TimeStamp(deadline.Unix())
}

deadlineUnix, _ := common.ParseAPIDeadlineToEndOfDay(form.Deadline)
if err := issues_model.UpdateIssueDeadline(ctx, issue, deadlineUnix, ctx.Doer); err != nil {
ctx.Error(http.StatusInternalServerError, "UpdateIssueDeadline", err)
return
}

ctx.JSON(http.StatusCreated, api.IssueDeadline{Deadline: &deadline})
ctx.JSON(http.StatusCreated, api.IssueDeadline{Deadline: deadlineUnix.AsTimePtr()})
}
14 changes: 6 additions & 8 deletions routers/api/v1/repo/milestone.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ package repo
import (
"net/http"
"strconv"
"time"

"code.gitea.io/gitea/models/db"
issues_model "code.gitea.io/gitea/models/issues"
Expand All @@ -16,6 +15,7 @@ import (
"code.gitea.io/gitea/modules/timeutil"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/routers/api/v1/utils"
"code.gitea.io/gitea/routers/common"
"code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/convert"
)
Expand Down Expand Up @@ -155,16 +155,16 @@ func CreateMilestone(ctx *context.APIContext) {
// "$ref": "#/responses/notFound"
form := web.GetForm(ctx).(*api.CreateMilestoneOption)

if form.Deadline == nil {
defaultDeadline, _ := time.ParseInLocation("2006-01-02", "9999-12-31", time.Local)
form.Deadline = &defaultDeadline
var deadlineUnix int64
if form.Deadline != nil {
deadlineUnix = form.Deadline.Unix()
}

milestone := &issues_model.Milestone{
RepoID: ctx.Repo.Repository.ID,
Name: form.Title,
Content: form.Description,
DeadlineUnix: timeutil.TimeStamp(form.Deadline.Unix()),
DeadlineUnix: timeutil.TimeStamp(deadlineUnix),
}

if form.State == "closed" {
Expand Down Expand Up @@ -225,9 +225,7 @@ func EditMilestone(ctx *context.APIContext) {
if form.Description != nil {
milestone.Content = *form.Description
}
if form.Deadline != nil && !form.Deadline.IsZero() {
milestone.DeadlineUnix = timeutil.TimeStamp(form.Deadline.Unix())
}
milestone.DeadlineUnix, _ = common.ParseAPIDeadlineToEndOfDay(form.Deadline)

oldIsClosed := milestone.IsClosed
if form.State != nil {
Expand Down
31 changes: 31 additions & 0 deletions routers/common/deadline.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Copyright 2024 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT

package common

import (
"time"

"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/timeutil"
)

func ParseDeadlineDateToEndOfDay(date string) (timeutil.TimeStamp, error) {
if date == "" {
return 0, nil
}
deadline, err := time.ParseInLocation("2006-01-02", date, setting.DefaultUILocation)
if err != nil {
return 0, err
}
deadline = time.Date(deadline.Year(), deadline.Month(), deadline.Day(), 23, 59, 59, 0, deadline.Location())
return timeutil.TimeStamp(deadline.Unix()), nil
}

func ParseAPIDeadlineToEndOfDay(t *time.Time) (timeutil.TimeStamp, error) {
if t == nil || t.IsZero() || t.Unix() == 0 {
return 0, nil
}
deadline := time.Date(t.Year(), t.Month(), t.Day(), 23, 59, 59, 0, setting.DefaultUILocation)
return timeutil.TimeStamp(deadline.Unix()), nil
}
15 changes: 3 additions & 12 deletions routers/web/repo/issue.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import (
"sort"
"strconv"
"strings"
"time"

activities_model "code.gitea.io/gitea/models/activities"
"code.gitea.io/gitea/models/db"
Expand Down Expand Up @@ -45,9 +44,9 @@ import (
api "code.gitea.io/gitea/modules/structs"
"code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/modules/templates/vars"
"code.gitea.io/gitea/modules/timeutil"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/routers/common"
"code.gitea.io/gitea/routers/utils"
shared_user "code.gitea.io/gitea/routers/web/shared/user"
asymkey_service "code.gitea.io/gitea/services/asymkey"
Expand Down Expand Up @@ -2329,7 +2328,6 @@ func UpdateIssueContent(ctx *context.Context) {

// UpdateIssueDeadline updates an issue deadline
func UpdateIssueDeadline(ctx *context.Context) {
form := web.GetForm(ctx).(*api.EditDeadlineOption)
issue, err := issues_model.GetIssueByIndex(ctx, ctx.Repo.Repository.ID, ctx.PathParamInt64(":index"))
if err != nil {
if issues_model.IsErrIssueNotExist(err) {
Expand All @@ -2345,20 +2343,13 @@ func UpdateIssueDeadline(ctx *context.Context) {
return
}

var deadlineUnix timeutil.TimeStamp
var deadline time.Time
if form.Deadline != nil && !form.Deadline.IsZero() {
deadline = time.Date(form.Deadline.Year(), form.Deadline.Month(), form.Deadline.Day(),
23, 59, 59, 0, time.Local)
deadlineUnix = timeutil.TimeStamp(deadline.Unix())
}

deadlineUnix, _ := common.ParseDeadlineDateToEndOfDay(ctx.FormString("deadline"))
if err := issues_model.UpdateIssueDeadline(ctx, issue, deadlineUnix, ctx.Doer); err != nil {
ctx.Error(http.StatusInternalServerError, "UpdateIssueDeadline", err.Error())
return
}

ctx.JSON(http.StatusCreated, api.IssueDeadline{Deadline: &deadline})
ctx.JSONRedirect("")
}

// UpdateIssueMilestone change issue's milestone
Expand Down
21 changes: 6 additions & 15 deletions routers/web/repo/milestone.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (
"fmt"
"net/http"
"net/url"
"time"

"code.gitea.io/gitea/models/db"
issues_model "code.gitea.io/gitea/models/issues"
Expand All @@ -16,8 +15,8 @@ import (
"code.gitea.io/gitea/modules/markup/markdown"
"code.gitea.io/gitea/modules/optional"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/timeutil"
"code.gitea.io/gitea/modules/web"
"code.gitea.io/gitea/routers/common"
"code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/forms"
"code.gitea.io/gitea/services/issue"
Expand Down Expand Up @@ -134,22 +133,18 @@ func NewMilestonePost(ctx *context.Context) {
return
}

if len(form.Deadline) == 0 {
form.Deadline = "9999-12-31"
}
deadline, err := time.ParseInLocation("2006-01-02", form.Deadline, time.Local)
deadlineUnix, err := common.ParseDeadlineDateToEndOfDay(form.Deadline)
if err != nil {
ctx.Data["Err_Deadline"] = true
ctx.RenderWithErr(ctx.Tr("repo.milestones.invalid_due_date_format"), tplMilestoneNew, &form)
return
}

deadline = time.Date(deadline.Year(), deadline.Month(), deadline.Day(), 23, 59, 59, 0, deadline.Location())
if err = issues_model.NewMilestone(ctx, &issues_model.Milestone{
if err := issues_model.NewMilestone(ctx, &issues_model.Milestone{
RepoID: ctx.Repo.Repository.ID,
Name: form.Title,
Content: form.Content,
DeadlineUnix: timeutil.TimeStamp(deadline.Unix()),
DeadlineUnix: deadlineUnix,
}); err != nil {
ctx.ServerError("NewMilestone", err)
return
Expand Down Expand Up @@ -194,17 +189,13 @@ func EditMilestonePost(ctx *context.Context) {
return
}

if len(form.Deadline) == 0 {
form.Deadline = "9999-12-31"
}
deadline, err := time.ParseInLocation("2006-01-02", form.Deadline, time.Local)
deadlineUnix, err := common.ParseDeadlineDateToEndOfDay(form.Deadline)
if err != nil {
ctx.Data["Err_Deadline"] = true
ctx.RenderWithErr(ctx.Tr("repo.milestones.invalid_due_date_format"), tplMilestoneNew, &form)
return
}

deadline = time.Date(deadline.Year(), deadline.Month(), deadline.Day(), 23, 59, 59, 0, deadline.Location())
m, err := issues_model.GetMilestoneByRepoID(ctx, ctx.Repo.Repository.ID, ctx.PathParamInt64(":id"))
if err != nil {
if issues_model.IsErrMilestoneNotExist(err) {
Expand All @@ -216,7 +207,7 @@ func EditMilestonePost(ctx *context.Context) {
}
m.Name = form.Title
m.Content = form.Content
m.DeadlineUnix = timeutil.TimeStamp(deadline.Unix())
m.DeadlineUnix = deadlineUnix
if err = issues_model.UpdateMilestone(ctx, m, m.IsClosed); err != nil {
ctx.ServerError("UpdateMilestone", err)
return
Expand Down
2 changes: 1 addition & 1 deletion routers/web/web.go
Original file line number Diff line number Diff line change
Expand Up @@ -1208,7 +1208,7 @@ func registerRoutes(m *web.Router) {
m.Group("/{index}", func() {
m.Post("/title", repo.UpdateIssueTitle)
m.Post("/content", repo.UpdateIssueContent)
m.Post("/deadline", web.Bind(structs.EditDeadlineOption{}), repo.UpdateIssueDeadline)
m.Post("/deadline", repo.UpdateIssueDeadline)
m.Post("/watch", repo.IssueWatch)
m.Post("/ref", repo.UpdateIssueRef)
m.Post("/pin", reqRepoAdmin, repo.IssuePinOrUnpin)
Expand Down
2 changes: 1 addition & 1 deletion services/convert/issue.go
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,7 @@ func ToAPIMilestone(m *issues_model.Milestone) *api.Milestone {
if m.IsClosed {
apiMilestone.Closed = m.ClosedDateUnix.AsTimePtr()
}
if m.DeadlineUnix.Year() < 9999 {
if m.DeadlineUnix > 0 {
apiMilestone.Deadline = m.DeadlineUnix.AsTimePtr()
}
return apiMilestone
Expand Down
2 changes: 1 addition & 1 deletion templates/repo/graph/commits.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@
{{end}}
{{end}}
</span>
<span class="author tw-flex tw-items-center tw-mr-2 tw-gap-[1px]">
<span class="author tw-flex tw-items-center tw-mr-2 tw-gap-1">
{{$userName := $commit.Commit.Author.Name}}
{{if $commit.User}}
{{if and $commit.User.FullName DefaultShowFullName}}
Expand Down
4 changes: 2 additions & 2 deletions templates/repo/issue/milestone_new.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@
<div class="field {{if .Err_Deadline}}error{{end}}">
<label>
{{ctx.Locale.Tr "repo.milestones.due_date"}}
<a id="clear-date">{{ctx.Locale.Tr "repo.milestones.clear"}}</a>
<a id="milestone-clear-deadline">{{ctx.Locale.Tr "repo.milestones.clear"}}</a>
</label>
<input type="date" id="deadline" name="deadline" value="{{.deadline}}" placeholder="{{ctx.Locale.Tr "repo.issues.due_date_form"}}">
<input type="date" name="deadline" class="tw-w-auto" value="{{.deadline}}" placeholder="{{ctx.Locale.Tr "repo.issues.due_date_form"}}">
</div>
<div class="field">
<label>{{ctx.Locale.Tr "repo.milestones.desc"}}</label>
Expand Down
Loading

0 comments on commit 24b83ff

Please sign in to comment.