Skip to content

Commit 56fa6d4

Browse files
Loïc Dacharysilentcodeg
Loïc Dachary
authored andcommitted
gofff: replace Gitea migration
1 parent 786c592 commit 56fa6d4

File tree

14 files changed

+459
-1939
lines changed

14 files changed

+459
-1939
lines changed

integrations/api_repo_test.go

-3
Original file line numberDiff line numberDiff line change
@@ -337,10 +337,7 @@ func TestAPIRepoMigrate(t *testing.T) {
337337
cloneURL, repoName string
338338
expectedStatus int
339339
}{
340-
{ctxUserID: 1, userID: 2, cloneURL: "https://github.com/go-gitea/test_repo.git", repoName: "git-admin", expectedStatus: http.StatusCreated},
341-
{ctxUserID: 2, userID: 2, cloneURL: "https://github.com/go-gitea/test_repo.git", repoName: "git-own", expectedStatus: http.StatusCreated},
342340
{ctxUserID: 2, userID: 1, cloneURL: "https://github.com/go-gitea/test_repo.git", repoName: "git-bad", expectedStatus: http.StatusForbidden},
343-
{ctxUserID: 2, userID: 3, cloneURL: "https://github.com/go-gitea/test_repo.git", repoName: "git-org", expectedStatus: http.StatusCreated},
344341
{ctxUserID: 2, userID: 6, cloneURL: "https://github.com/go-gitea/test_repo.git", repoName: "git-bad-org", expectedStatus: http.StatusForbidden},
345342
{ctxUserID: 2, userID: 3, cloneURL: "https://localhost:3000/user/test_repo.git", repoName: "private-ip", expectedStatus: http.StatusUnprocessableEntity},
346343
{ctxUserID: 2, userID: 3, cloneURL: "https://10.0.0.1/user/test_repo.git", repoName: "private-ip", expectedStatus: http.StatusUnprocessableEntity},

integrations/dump_restore_test.go

+121-99
Original file line numberDiff line numberDiff line change
@@ -12,20 +12,21 @@ import (
1212
"os"
1313
"path/filepath"
1414
"reflect"
15-
"strings"
1615
"testing"
1716

1817
repo_model "code.gitea.io/gitea/models/repo"
1918
"code.gitea.io/gitea/models/unittest"
2019
user_model "code.gitea.io/gitea/models/user"
20+
"code.gitea.io/gitea/modules/json"
2121
base "code.gitea.io/gitea/modules/migration"
2222
"code.gitea.io/gitea/modules/setting"
2323
"code.gitea.io/gitea/modules/structs"
24-
"code.gitea.io/gitea/modules/util"
2524
"code.gitea.io/gitea/services/migrations"
2625

2726
"github.com/stretchr/testify/assert"
28-
"gopkg.in/yaml.v2"
27+
"lab.forgefriends.org/friendlyforgeformat/gofff"
28+
"lab.forgefriends.org/friendlyforgeformat/gofff/forges/file"
29+
"lab.forgefriends.org/friendlyforgeformat/gofff/format"
2930
)
3031

3132
func TestDumpRestore(t *testing.T) {
@@ -40,83 +41,91 @@ func TestDumpRestore(t *testing.T) {
4041
setting.AppVer = AppVer
4142
}()
4243

43-
assert.NoError(t, migrations.Init())
44-
45-
reponame := "repo1"
46-
47-
basePath, err := os.MkdirTemp("", reponame)
48-
assert.NoError(t, err)
49-
defer util.RemoveAll(basePath)
50-
51-
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{Name: reponame}).(*repo_model.Repository)
52-
repoOwner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID}).(*user_model.User)
44+
repoOwner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1}).(*user_model.User)
5345
session := loginUser(t, repoOwner.Name)
5446
token := getTokenForLoggedInUser(t, session)
5547

56-
//
57-
// Phase 1: dump repo1 from the Gitea instance to the filesystem
58-
//
48+
fixture := file.NewFixture(t, gofff.AllFeatures)
49+
fixture.CreateEverything(file.User{
50+
ID: repoOwner.ID,
51+
Name: repoOwner.Name,
52+
Email: repoOwner.Email,
53+
})
5954

60-
ctx := context.Background()
61-
opts := migrations.MigrateOptions{
62-
GitServiceType: structs.GiteaService,
63-
Issues: true,
64-
PullRequests: true,
65-
Labels: true,
66-
Milestones: true,
67-
Comments: true,
68-
AuthToken: token,
69-
CloneAddr: repo.CloneLink().HTTPS,
70-
RepoName: reponame,
71-
}
72-
err = migrations.DumpRepository(ctx, basePath, repoOwner.Name, opts)
73-
assert.NoError(t, err)
74-
75-
//
76-
// Verify desired side effects of the dump
77-
//
78-
d := filepath.Join(basePath, repo.OwnerName, repo.Name)
79-
for _, f := range []string{"repo.yml", "topic.yml", "label.yml", "milestone.yml", "issue.yml"} {
80-
assert.FileExists(t, filepath.Join(d, f))
81-
}
55+
assert.NoError(t, migrations.Init())
8256

57+
ctx := context.Background()
8358
//
84-
// Phase 2: restore from the filesystem to the Gitea instance in restoredrepo
59+
// Phase 1: restore from the filesystem to the Gitea instance in restoredrepo
8560
//
8661

87-
newreponame := "restored"
88-
err = migrations.RestoreRepository(ctx, d, repo.OwnerName, newreponame, []string{
89-
"labels", "issues", "comments", "milestones", "pull_requests",
62+
restoredRepoName := "restored"
63+
restoredRepoDirectory := fixture.GetDirectory()
64+
err := migrations.RestoreRepository(ctx, restoredRepoDirectory, repoOwner.Name, restoredRepoName, []string{
65+
"issues", "milestones", "labels", "releases", "release_assets", "comments", "pull_requests",
66+
// wiki",
9067
}, false)
9168
assert.NoError(t, err)
9269

93-
newrepo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{Name: newreponame}).(*repo_model.Repository)
70+
restoredRepo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{Name: restoredRepoName}).(*repo_model.Repository)
71+
unittest.AssertExistsAndLoadBean(t, &repo_model.Attachment{Name: file.Asset1})
9472

9573
//
96-
// Phase 3: dump restored from the Gitea instance to the filesystem
74+
// Phase 2: dump restoredRepo from the Gitea instance to the filesystem
9775
//
98-
opts.RepoName = newreponame
99-
opts.CloneAddr = newrepo.CloneLink().HTTPS
100-
err = migrations.DumpRepository(ctx, basePath, repoOwner.Name, opts)
76+
77+
opts := base.MigrateOptions{
78+
GitServiceType: structs.GiteaService,
79+
80+
Wiki: true,
81+
Issues: true,
82+
Milestones: true,
83+
Labels: true,
84+
Releases: true,
85+
Comments: true,
86+
PullRequests: true,
87+
ReleaseAssets: true,
88+
89+
AuthToken: token,
90+
CloneAddr: restoredRepo.CloneLink().HTTPS,
91+
RepoName: restoredRepoName,
92+
}
93+
dumpedRepoDirectory := t.TempDir()
94+
err = migrations.DumpRepository(ctx, dumpedRepoDirectory, repoOwner.Name, opts)
10195
assert.NoError(t, err)
10296

10397
//
10498
// Verify the dump of restored is the same as the dump of repo1
10599
//
100+
//fixture.AssertEquals(restoredRepoDirectory, dumpedRepoDirectory)
101+
//
102+
// Verify the fixture files are the same as the restored files
103+
//
104+
project := fixture.GetFile().GetProject()
106105
comparator := &compareDump{
107-
t: t,
108-
basePath: basePath,
106+
t: t,
107+
108+
repoBefore: project.Name,
109+
ownerBefore: project.Owner,
110+
dirBefore: restoredRepoDirectory,
111+
112+
repoAfter: restoredRepoName,
113+
ownerAfter: repoOwner.Name,
114+
dirAfter: dumpedRepoDirectory,
109115
}
110-
comparator.assertEquals(repo, newrepo)
116+
comparator.assertEquals()
111117
})
112118
}
113119

114120
type compareDump struct {
115-
t *testing.T
116-
basePath string
117-
repoBefore *repo_model.Repository
118-
dirBefore string
119-
repoAfter *repo_model.Repository
121+
t *testing.T
122+
123+
repoBefore string
124+
ownerBefore string
125+
dirBefore string
126+
127+
repoAfter string
128+
ownerAfter string
120129
dirAfter string
121130
}
122131

@@ -130,92 +139,99 @@ type compareField struct {
130139

131140
type compareFields map[string]compareField
132141

133-
func (c *compareDump) replaceRepoName(original string) string {
134-
return strings.ReplaceAll(original, c.repoBefore.Name, c.repoAfter.Name)
135-
}
136-
137-
func (c *compareDump) assertEquals(repoBefore, repoAfter *repo_model.Repository) {
138-
c.repoBefore = repoBefore
139-
c.dirBefore = filepath.Join(c.basePath, repoBefore.OwnerName, repoBefore.Name)
140-
c.repoAfter = repoAfter
141-
c.dirAfter = filepath.Join(c.basePath, repoAfter.OwnerName, repoAfter.Name)
142-
142+
func (c *compareDump) assertEquals() {
143143
//
144144
// base.Repository
145145
//
146-
_ = c.assertEqual("repo.yml", base.Repository{}, compareFields{
146+
_ = c.assertEqual("project.json", format.Project{}, compareFields{
147147
"Name": {
148-
before: c.repoBefore.Name,
149-
after: c.repoAfter.Name,
148+
before: c.repoBefore,
149+
after: c.repoAfter,
150+
},
151+
"Owner": {
152+
before: c.ownerBefore,
153+
after: c.ownerAfter,
150154
},
151-
"CloneURL": {transform: c.replaceRepoName},
152-
"OriginalURL": {transform: c.replaceRepoName},
155+
"Index": {ignore: true},
156+
"CloneURL": {ignore: true},
153157
})
154158

155159
//
156160
// base.Label
157161
//
158-
labels, ok := c.assertEqual("label.yml", []base.Label{}, compareFields{}).([]*base.Label)
162+
compareLabels := compareFields{
163+
"Index": {ignore: true},
164+
}
165+
labels, ok := c.assertEqual("label.json", []format.Label{}, compareLabels).([]*format.Label)
159166
assert.True(c.t, ok)
160167
assert.GreaterOrEqual(c.t, len(labels), 1)
161168

162169
//
163170
// base.Milestone
164171
//
165-
milestones, ok := c.assertEqual("milestone.yml", []base.Milestone{}, compareFields{
172+
milestones, ok := c.assertEqual("milestone.json", []format.Milestone{}, compareFields{
173+
"Index": {ignore: true},
166174
"Updated": {ignore: true}, // the database updates that field independently
167-
}).([]*base.Milestone)
175+
}).([]*format.Milestone)
168176
assert.True(c.t, ok)
169177
assert.GreaterOrEqual(c.t, len(milestones), 1)
170178

171179
//
172-
// base.Issue and the associated comments
180+
// format.Issue and the associated comments
173181
//
174-
issues, ok := c.assertEqual("issue.yml", []base.Issue{}, compareFields{
182+
issues, ok := c.assertEqual("issue.json", []format.Issue{}, compareFields{
183+
"Index": {ignore: true},
175184
"Assignees": {ignore: true}, // not implemented yet
176-
}).([]*base.Issue)
185+
"Labels": {nested: &compareLabels},
186+
}).([]*format.Issue)
177187
assert.True(c.t, ok)
178188
assert.GreaterOrEqual(c.t, len(issues), 1)
179189
for _, issue := range issues {
180-
filename := filepath.Join("comments", fmt.Sprintf("%d.yml", issue.Number))
181-
comments, ok := c.assertEqual(filename, []base.Comment{}, compareFields{
190+
filename := filepath.Join("comments", fmt.Sprintf("%d.json", issue.Number))
191+
comments, ok := c.assertEqual(filename, []format.Comment{}, compareFields{
182192
"Index": {ignore: true},
183-
}).([]*base.Comment)
193+
}).([]*format.Comment)
184194
assert.True(c.t, ok)
185195
for _, comment := range comments {
186196
assert.EqualValues(c.t, issue.Number, comment.IssueIndex)
187197
}
188198
}
189199

190200
//
191-
// base.PullRequest and the associated comments
201+
// format.PullRequest and the associated comments
192202
//
193203
comparePullRequestBranch := &compareFields{
194204
"RepoName": {
195-
before: c.repoBefore.Name,
196-
after: c.repoAfter.Name,
205+
before: c.repoBefore,
206+
after: c.repoAfter,
207+
},
208+
"OwnerName": {
209+
before: c.ownerBefore,
210+
after: c.ownerAfter,
197211
},
198-
"CloneURL": {transform: c.replaceRepoName},
212+
"CloneURL": {ignore: true},
199213
}
200-
prs, ok := c.assertEqual("pull_request.yml", []base.PullRequest{}, compareFields{
214+
prs, ok := c.assertEqual("pull_request.json", []format.PullRequest{}, compareFields{
201215
"Assignees": {ignore: true}, // not implemented yet
202216
"Head": {nested: comparePullRequestBranch},
203217
"Base": {nested: comparePullRequestBranch},
218+
"PatchURL": {ignore: true},
219+
"CloneURL": {ignore: true},
204220
"Labels": {ignore: true}, // because org labels are not handled properly
205-
}).([]*base.PullRequest)
221+
}).([]*format.PullRequest)
206222
assert.True(c.t, ok)
207223
assert.GreaterOrEqual(c.t, len(prs), 1)
208224
for _, pr := range prs {
209-
filename := filepath.Join("comments", fmt.Sprintf("%d.yml", pr.Number))
210-
comments, ok := c.assertEqual(filename, []base.Comment{}, compareFields{}).([]*base.Comment)
225+
filename := filepath.Join("comments", fmt.Sprintf("%d.json", pr.Number))
226+
comments, ok := c.assertEqual(filename, []format.Comment{}, compareFields{}).([]*format.Comment)
211227
assert.True(c.t, ok)
212228
for _, comment := range comments {
213229
assert.EqualValues(c.t, pr.Number, comment.IssueIndex)
214230
}
215231
}
216232
}
217233

218-
func (c *compareDump) assertLoadYAMLFiles(beforeFilename, afterFilename string, before, after interface{}) {
234+
func (c *compareDump) assertLoadJSONFiles(beforeFilename, afterFilename string, before, after interface{}) {
219235
_, beforeErr := os.Stat(beforeFilename)
220236
_, afterErr := os.Stat(afterFilename)
221237
assert.EqualValues(c.t, errors.Is(beforeErr, os.ErrNotExist), errors.Is(afterErr, os.ErrNotExist))
@@ -225,10 +241,10 @@ func (c *compareDump) assertLoadYAMLFiles(beforeFilename, afterFilename string,
225241

226242
beforeBytes, err := os.ReadFile(beforeFilename)
227243
assert.NoError(c.t, err)
228-
assert.NoError(c.t, yaml.Unmarshal(beforeBytes, before))
244+
assert.NoError(c.t, json.Unmarshal(beforeBytes, before))
229245
afterBytes, err := os.ReadFile(afterFilename)
230246
assert.NoError(c.t, err)
231-
assert.NoError(c.t, yaml.Unmarshal(afterBytes, after))
247+
assert.NoError(c.t, json.Unmarshal(afterBytes, after))
232248
}
233249

234250
func (c *compareDump) assertLoadFiles(beforeFilename, afterFilename string, t reflect.Type) (before, after reflect.Value) {
@@ -251,13 +267,14 @@ func (c *compareDump) assertLoadFiles(beforeFilename, afterFilename string, t re
251267
beforePtr = reflect.New(t)
252268
afterPtr = reflect.New(t)
253269
}
254-
c.assertLoadYAMLFiles(beforeFilename, afterFilename, beforePtr.Interface(), afterPtr.Interface())
270+
c.assertLoadJSONFiles(beforeFilename, afterFilename, beforePtr.Interface(), afterPtr.Interface())
255271
return beforePtr.Elem(), afterPtr.Elem()
256272
}
257273

258274
func (c *compareDump) assertEqual(filename string, kind interface{}, fields compareFields) (i interface{}) {
259275
beforeFilename := filepath.Join(c.dirBefore, filename)
260276
afterFilename := filepath.Join(c.dirAfter, filename)
277+
fmt.Println("assertEqual ", beforeFilename, afterFilename)
261278

262279
typeOf := reflect.TypeOf(kind)
263280
before, after := c.assertLoadFiles(beforeFilename, afterFilename, typeOf)
@@ -300,29 +317,34 @@ func (c *compareDump) assertEqualValues(before, after reflect.Value, fields comp
300317
// Transform these strings before comparing them
301318
//
302319
bs, ok := bi.(string)
303-
assert.True(c.t, ok)
320+
assert.True(c.t, ok, field.Name)
304321
as, ok := ai.(string)
305-
assert.True(c.t, ok)
306-
assert.EqualValues(c.t, compare.transform(bs), compare.transform(as))
322+
assert.True(c.t, ok, field.Name)
323+
assert.EqualValues(c.t, compare.transform(bs), compare.transform(as), field.Name)
307324
continue
308325
}
309326
if compare.before != nil && compare.after != nil {
310327
//
311328
// The fields are expected to have different values
312329
//
313-
assert.EqualValues(c.t, compare.before, bi)
314-
assert.EqualValues(c.t, compare.after, ai)
330+
assert.EqualValues(c.t, compare.before, bi, field.Name)
331+
assert.EqualValues(c.t, compare.after, ai, field.Name)
315332
continue
316333
}
317334
if compare.nested != nil {
318335
//
319-
// The fields are a struct, recurse
336+
// The fields are a struct/slice, recurse
320337
//
321-
c.assertEqualValues(bf, af, *compare.nested)
338+
fmt.Println("nested ", field.Name)
339+
if reflect.TypeOf(bi).Kind() == reflect.Slice {
340+
c.assertEqualSlices(bf, af, *compare.nested)
341+
} else {
342+
c.assertEqualValues(bf, af, *compare.nested)
343+
}
322344
continue
323345
}
324346
}
325-
assert.EqualValues(c.t, bi, ai)
347+
assert.EqualValues(c.t, bi, ai, field.Name)
326348
}
327349
return after.Interface()
328350
}

0 commit comments

Comments
 (0)