From 69a28299e2e3a8e40023581c27a5a2193949efa0 Mon Sep 17 00:00:00 2001
From: Aravinth Manivannan <realaravinth@batsense.net>
Date: Thu, 13 Jan 2022 06:03:30 +0000
Subject: [PATCH] migrations: a deadline at January 1st, 1970 is valid (#18237)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* migrations: a deadline at January 1st, 1970 is valid

Do not change the deadline value if it is set to January 1st, 1970.

Setting the deadline to year 9999 when it is zero (which is equal to
January 1st, 1970) modifies a deadline set to January 1st, 1970 which
is a valid date. In addition, setting a date in year 9999 will be
converted to a null date in some cases.

Signed-off-by: Loïc Dachary <loic@dachary.org>

* tests: set milestone.deadline_unix in fixtures

The value of deadline_unix must be set to 253370764800 (i.e. 9999-01-01) in
fixtures, otherwise it will be inserted as null which leads to
unexpected errors. For instance, DumpRepository will store a null
deadline_unix as 0 (i.e. 1970-01-01) and RestoreRepository will change
it to 9999-01-01.

Signed-off-by: Loïc Dachary <loic@dachary.org>

Co-authored-by: Loïc Dachary <loic@dachary.org>
Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
---
 integrations/dump_restore_test.go | 43 ++++++++++++++++++++++++++-----
 models/fixtures/milestone.yml     |  5 ++++
 2 files changed, 42 insertions(+), 6 deletions(-)

diff --git a/integrations/dump_restore_test.go b/integrations/dump_restore_test.go
index 6fe5d8fe6..f35af43a9 100644
--- a/integrations/dump_restore_test.go
+++ b/integrations/dump_restore_test.go
@@ -15,12 +15,14 @@ import (
 	repo_model "code.gitea.io/gitea/models/repo"
 	"code.gitea.io/gitea/models/unittest"
 	user_model "code.gitea.io/gitea/models/user"
+	base "code.gitea.io/gitea/modules/migration"
 	"code.gitea.io/gitea/modules/setting"
 	"code.gitea.io/gitea/modules/structs"
 	"code.gitea.io/gitea/modules/util"
 	"code.gitea.io/gitea/services/migrations"
 
 	"github.com/stretchr/testify/assert"
+	"gopkg.in/yaml.v2"
 )
 
 func TestDumpRestore(t *testing.T) {
@@ -56,6 +58,8 @@ func TestDumpRestore(t *testing.T) {
 		var opts = migrations.MigrateOptions{
 			GitServiceType: structs.GiteaService,
 			Issues:         true,
+			Labels:         true,
+			Milestones:     true,
 			Comments:       true,
 			AuthToken:      token,
 			CloneAddr:      repo.CloneLink().HTTPS,
@@ -68,7 +72,7 @@ func TestDumpRestore(t *testing.T) {
 		// Verify desired side effects of the dump
 		//
 		d := filepath.Join(basePath, repo.OwnerName, repo.Name)
-		for _, f := range []string{"repo.yml", "topic.yml", "issue.yml"} {
+		for _, f := range []string{"repo.yml", "topic.yml", "label.yml", "milestone.yml", "issue.yml"} {
 			assert.FileExists(t, filepath.Join(d, f))
 		}
 
@@ -77,7 +81,7 @@ func TestDumpRestore(t *testing.T) {
 		//
 
 		newreponame := "restoredrepo"
-		err = migrations.RestoreRepository(ctx, d, repo.OwnerName, newreponame, []string{"issues", "comments"})
+		err = migrations.RestoreRepository(ctx, d, repo.OwnerName, newreponame, []string{"labels", "milestones", "issues", "comments"})
 		assert.NoError(t, err)
 
 		newrepo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{Name: newreponame}).(*repo_model.Repository)
@@ -94,11 +98,38 @@ func TestDumpRestore(t *testing.T) {
 		// Verify the dump of restoredrepo is the same as the dump of repo1
 		//
 		newd := filepath.Join(basePath, newrepo.OwnerName, newrepo.Name)
-		beforeBytes, err := os.ReadFile(filepath.Join(d, "repo.yml"))
+		for _, filename := range []string{"repo.yml", "label.yml", "milestone.yml"} {
+			beforeBytes, err := os.ReadFile(filepath.Join(d, filename))
+			assert.NoError(t, err)
+			before := strings.ReplaceAll(string(beforeBytes), reponame, newreponame)
+			after, err := os.ReadFile(filepath.Join(newd, filename))
+			assert.NoError(t, err)
+			assert.EqualValues(t, before, string(after))
+		}
+
+		beforeBytes, err := os.ReadFile(filepath.Join(d, "issue.yml"))
 		assert.NoError(t, err)
-		before := strings.ReplaceAll(string(beforeBytes), reponame, newreponame)
-		after, err := os.ReadFile(filepath.Join(newd, "repo.yml"))
+		var before = make([]*base.Issue, 0, 10)
+		assert.NoError(t, yaml.Unmarshal(beforeBytes, &before))
+		afterBytes, err := os.ReadFile(filepath.Join(newd, "issue.yml"))
 		assert.NoError(t, err)
-		assert.EqualValues(t, before, string(after))
+		var after = make([]*base.Issue, 0, 10)
+		assert.NoError(t, yaml.Unmarshal(afterBytes, &after))
+
+		assert.EqualValues(t, len(before), len(after))
+		if len(before) == len(after) {
+			for i := 0; i < len(before); i++ {
+				assert.EqualValues(t, before[i].Number, after[i].Number)
+				assert.EqualValues(t, before[i].Title, after[i].Title)
+				assert.EqualValues(t, before[i].Content, after[i].Content)
+				assert.EqualValues(t, before[i].Ref, after[i].Ref)
+				assert.EqualValues(t, before[i].Milestone, after[i].Milestone)
+				assert.EqualValues(t, before[i].State, after[i].State)
+				assert.EqualValues(t, before[i].IsLocked, after[i].IsLocked)
+				assert.EqualValues(t, before[i].Created, after[i].Created)
+				assert.EqualValues(t, before[i].Updated, after[i].Updated)
+				assert.EqualValues(t, before[i].Labels, after[i].Labels)
+			}
+		}
 	})
 }
diff --git a/models/fixtures/milestone.yml b/models/fixtures/milestone.yml
index d439ce81c..4dd344594 100644
--- a/models/fixtures/milestone.yml
+++ b/models/fixtures/milestone.yml
@@ -6,6 +6,7 @@
   is_closed: false
   num_issues: 1
   num_closed_issues: 0
+  deadline_unix: 253370764800
 
 -
   id: 2
@@ -15,6 +16,7 @@
   is_closed: false
   num_issues: 0
   num_closed_issues: 0
+  deadline_unix: 253370764800
 
 -
   id: 3
@@ -24,6 +26,7 @@
   is_closed: true
   num_issues: 1
   num_closed_issues: 0
+  deadline_unix: 253370764800
 
 -
   id: 4
@@ -33,6 +36,7 @@
   is_closed: false
   num_issues: 0
   num_closed_issues: 0
+  deadline_unix: 253370764800
 
 - 
   id: 5
@@ -42,3 +46,4 @@
   is_closed: false
   num_issues: 0
   num_closed_issues: 0
+  deadline_unix: 253370764800