Skip to content

Commit 66b6917

Browse files
author
Otto
committed
Merge pull request '[v9.0/forgejo] fix: issue labels are not set after deleting one label' (go-gitea#5844) from bp-v9.0/forgejo-db899c1-f06bdb0 into v9.0/forgejo
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/5844 Reviewed-by: Otto <[email protected]>
2 parents ed2d5f6 + 397b3cf commit 66b6917

File tree

2 files changed

+124
-15
lines changed

2 files changed

+124
-15
lines changed

models/issues/issue_label.go

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -111,9 +111,7 @@ func NewIssueLabel(ctx context.Context, issue *Issue, label *Label, doer *user_m
111111
return err
112112
}
113113

114-
issue.isLabelsLoaded = false
115-
issue.Labels = nil
116-
if err = issue.LoadLabels(ctx); err != nil {
114+
if err = issue.ReloadLabels(ctx); err != nil {
117115
return err
118116
}
119117

@@ -161,10 +159,7 @@ func NewIssueLabels(ctx context.Context, issue *Issue, labels []*Label, doer *us
161159
return err
162160
}
163161

164-
// reload all labels
165-
issue.isLabelsLoaded = false
166-
issue.Labels = nil
167-
if err = issue.LoadLabels(ctx); err != nil {
162+
if err = issue.ReloadLabels(ctx); err != nil {
168163
return err
169164
}
170165

@@ -205,8 +200,7 @@ func DeleteIssueLabel(ctx context.Context, issue *Issue, label *Label, doer *use
205200
return err
206201
}
207202

208-
issue.Labels = nil
209-
return issue.LoadLabels(ctx)
203+
return issue.ReloadLabels(ctx)
210204
}
211205

212206
// DeleteLabelsByRepoID deletes labels of some repository
@@ -326,14 +320,23 @@ func FixIssueLabelWithOutsideLabels(ctx context.Context) (int64, error) {
326320
return res.RowsAffected()
327321
}
328322

329-
// LoadLabels loads labels
323+
// LoadLabels only if they are not already set
330324
func (issue *Issue) LoadLabels(ctx context.Context) (err error) {
331-
if !issue.isLabelsLoaded && issue.Labels == nil && issue.ID != 0 {
325+
if !issue.isLabelsLoaded && issue.Labels == nil {
326+
if err := issue.ReloadLabels(ctx); err != nil {
327+
return err
328+
}
329+
issue.isLabelsLoaded = true
330+
}
331+
return nil
332+
}
333+
334+
func (issue *Issue) ReloadLabels(ctx context.Context) (err error) {
335+
if issue.ID != 0 {
332336
issue.Labels, err = GetLabelsByIssueID(ctx, issue.ID)
333337
if err != nil {
334338
return fmt.Errorf("getLabelsByIssueID [%d]: %w", issue.ID, err)
335339
}
336-
issue.isLabelsLoaded = true
337340
}
338341
return nil
339342
}
@@ -496,9 +499,7 @@ func ReplaceIssueLabels(ctx context.Context, issue *Issue, labels []*Label, doer
496499
}
497500
}
498501

499-
issue.isLabelsLoaded = false
500-
issue.Labels = nil
501-
if err = issue.LoadLabels(ctx); err != nil {
502+
if err = issue.ReloadLabels(ctx); err != nil {
502503
return err
503504
}
504505

models/issues/issue_label_test.go

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,114 @@ import (
1515
"github.com/stretchr/testify/require"
1616
)
1717

18+
func TestIssueNewIssueLabels(t *testing.T) {
19+
require.NoError(t, unittest.PrepareTestDatabase())
20+
21+
issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 2})
22+
label1 := unittest.AssertExistsAndLoadBean(t, &issues_model.Label{ID: 1})
23+
label2 := unittest.AssertExistsAndLoadBean(t, &issues_model.Label{ID: 4})
24+
doer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
25+
26+
label3 := &issues_model.Label{RepoID: 1, Name: "label3", Color: "#123"}
27+
require.NoError(t, issues_model.NewLabel(db.DefaultContext, label3))
28+
29+
// label1 is already set, do nothing
30+
// label3 is new, add it
31+
require.NoError(t, issues_model.NewIssueLabels(db.DefaultContext, issue, []*issues_model.Label{label1, label3}, doer))
32+
33+
assert.Len(t, issue.Labels, 3)
34+
// check that the pre-existing label1 is still present
35+
assert.Equal(t, label1.ID, issue.Labels[0].ID)
36+
// check that new label3 was added
37+
assert.Equal(t, label3.ID, issue.Labels[1].ID)
38+
// check that pre-existing label2 was not removed
39+
assert.Equal(t, label2.ID, issue.Labels[2].ID)
40+
}
41+
42+
func TestIssueNewIssueLabel(t *testing.T) {
43+
require.NoError(t, unittest.PrepareTestDatabase())
44+
45+
issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 3})
46+
doer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
47+
48+
label := &issues_model.Label{RepoID: 1, Name: "label3", Color: "#123"}
49+
require.NoError(t, issues_model.NewLabel(db.DefaultContext, label))
50+
51+
require.NoError(t, issues_model.NewIssueLabel(db.DefaultContext, issue, label, doer))
52+
53+
assert.Len(t, issue.Labels, 1)
54+
assert.Equal(t, label.ID, issue.Labels[0].ID)
55+
}
56+
57+
func TestIssueReplaceIssueLabels(t *testing.T) {
58+
require.NoError(t, unittest.PrepareTestDatabase())
59+
60+
issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 2})
61+
label1 := unittest.AssertExistsAndLoadBean(t, &issues_model.Label{ID: 1})
62+
label2 := unittest.AssertExistsAndLoadBean(t, &issues_model.Label{ID: 4})
63+
doer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
64+
65+
label3 := &issues_model.Label{RepoID: 1, Name: "label3", Color: "#123"}
66+
require.NoError(t, issues_model.NewLabel(db.DefaultContext, label3))
67+
68+
issue.LoadLabels(db.DefaultContext)
69+
assert.Len(t, issue.Labels, 2)
70+
assert.Equal(t, label1.ID, issue.Labels[0].ID)
71+
assert.Equal(t, label2.ID, issue.Labels[1].ID)
72+
73+
// label1 is already set, do nothing
74+
// label3 is new, add it
75+
// label2 is not in the list but already set, remove it
76+
require.NoError(t, issues_model.ReplaceIssueLabels(db.DefaultContext, issue, []*issues_model.Label{label1, label3}, doer))
77+
78+
assert.Len(t, issue.Labels, 2)
79+
assert.Equal(t, label1.ID, issue.Labels[0].ID)
80+
assert.Equal(t, label3.ID, issue.Labels[1].ID)
81+
}
82+
83+
func TestIssueDeleteIssueLabel(t *testing.T) {
84+
require.NoError(t, unittest.PrepareTestDatabase())
85+
86+
issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 2})
87+
label1 := unittest.AssertExistsAndLoadBean(t, &issues_model.Label{ID: 1})
88+
label2 := unittest.AssertExistsAndLoadBean(t, &issues_model.Label{ID: 4})
89+
doer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2})
90+
91+
issue.LoadLabels(db.DefaultContext)
92+
assert.Len(t, issue.Labels, 2)
93+
assert.Equal(t, label1.ID, issue.Labels[0].ID)
94+
assert.Equal(t, label2.ID, issue.Labels[1].ID)
95+
96+
require.NoError(t, issues_model.DeleteIssueLabel(db.DefaultContext, issue, label2, doer))
97+
98+
assert.Len(t, issue.Labels, 1)
99+
assert.Equal(t, label1.ID, issue.Labels[0].ID)
100+
}
101+
102+
func TestIssueLoadLabels(t *testing.T) {
103+
require.NoError(t, unittest.PrepareTestDatabase())
104+
105+
issue := unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 2})
106+
label1 := unittest.AssertExistsAndLoadBean(t, &issues_model.Label{ID: 1})
107+
label2 := unittest.AssertExistsAndLoadBean(t, &issues_model.Label{ID: 4})
108+
109+
assert.Empty(t, issue.Labels)
110+
issue.LoadLabels(db.DefaultContext)
111+
assert.Len(t, issue.Labels, 2)
112+
assert.Equal(t, label1.ID, issue.Labels[0].ID)
113+
assert.Equal(t, label2.ID, issue.Labels[1].ID)
114+
115+
unittest.AssertSuccessfulDelete(t, &issues_model.IssueLabel{IssueID: issue.ID, LabelID: label2.ID})
116+
117+
// the database change is not noticed because the labels are cached
118+
issue.LoadLabels(db.DefaultContext)
119+
assert.Len(t, issue.Labels, 2)
120+
121+
issue.ReloadLabels(db.DefaultContext)
122+
assert.Len(t, issue.Labels, 1)
123+
assert.Equal(t, label1.ID, issue.Labels[0].ID)
124+
}
125+
18126
func TestNewIssueLabelsScope(t *testing.T) {
19127
require.NoError(t, unittest.PrepareTestDatabase())
20128

0 commit comments

Comments
 (0)