-
-
Notifications
You must be signed in to change notification settings - Fork 5.9k
Description
I'd like to implement labels on an organization level.
I think it should be pretty straight forward to add an org_id
column to the label
table and have it mostly work minus all interface updates/additions.
The way labels were implemented has them pretty coupled to repositories in code and language (compared to Webhooks, which seem to have been implemented without that limitation in mind and exist across repos and organizations ).
Many label functions currently are of the form GetLabelsByRepoID
, getLabelInRepoByName
, etc... and most of them rely on having a RepoID
passed through.
Just want to get feedback if it is worth refactoring/renaming the following functions to take both a repoID and orgID (one always being nil
) where appropriate since most of them would work the same otherwise and we would just want to do a lookup based on repoID
OR orgID
going forward:
Lines 155 to 308 in 877df0f
// getLabelInRepoByName returns a label by Name in given repository. | |
// If pass repoID as 0, then ORM will ignore limitation of repository | |
// and can return arbitrary label with any valid ID. | |
func getLabelInRepoByName(e Engine, repoID int64, labelName string) (*Label, error) { | |
if len(labelName) == 0 { | |
return nil, ErrLabelNotExist{0, repoID} | |
} | |
l := &Label{ | |
Name: labelName, | |
RepoID: repoID, | |
} | |
has, err := e.Get(l) | |
if err != nil { | |
return nil, err | |
} else if !has { | |
return nil, ErrLabelNotExist{0, l.RepoID} | |
} | |
return l, nil | |
} | |
// getLabelInRepoByID returns a label by ID in given repository. | |
// If pass repoID as 0, then ORM will ignore limitation of repository | |
// and can return arbitrary label with any valid ID. | |
func getLabelInRepoByID(e Engine, repoID, labelID int64) (*Label, error) { | |
if labelID <= 0 { | |
return nil, ErrLabelNotExist{labelID, repoID} | |
} | |
l := &Label{ | |
ID: labelID, | |
RepoID: repoID, | |
} | |
has, err := e.Get(l) | |
if err != nil { | |
return nil, err | |
} else if !has { | |
return nil, ErrLabelNotExist{l.ID, l.RepoID} | |
} | |
return l, nil | |
} | |
// GetLabelByID returns a label by given ID. | |
func GetLabelByID(id int64) (*Label, error) { | |
return getLabelInRepoByID(x, 0, id) | |
} | |
// GetLabelInRepoByName returns a label by name in given repository. | |
func GetLabelInRepoByName(repoID int64, labelName string) (*Label, error) { | |
return getLabelInRepoByName(x, repoID, labelName) | |
} | |
// GetLabelIDsInRepoByNames returns a list of labelIDs by names in a given | |
// repository. | |
// it silently ignores label names that do not belong to the repository. | |
func GetLabelIDsInRepoByNames(repoID int64, labelNames []string) ([]int64, error) { | |
labelIDs := make([]int64, 0, len(labelNames)) | |
return labelIDs, x.Table("label"). | |
Where("repo_id = ?", repoID). | |
In("name", labelNames). | |
Asc("name"). | |
Cols("id"). | |
Find(&labelIDs) | |
} | |
// GetLabelInRepoByID returns a label by ID in given repository. | |
func GetLabelInRepoByID(repoID, labelID int64) (*Label, error) { | |
return getLabelInRepoByID(x, repoID, labelID) | |
} | |
// GetLabelsInRepoByIDs returns a list of labels by IDs in given repository, | |
// it silently ignores label IDs that do not belong to the repository. | |
func GetLabelsInRepoByIDs(repoID int64, labelIDs []int64) ([]*Label, error) { | |
labels := make([]*Label, 0, len(labelIDs)) | |
return labels, x. | |
Where("repo_id = ?", repoID). | |
In("id", labelIDs). | |
Asc("name"). | |
Find(&labels) | |
} | |
// GetLabelsByRepoID returns all labels that belong to given repository by ID. | |
func GetLabelsByRepoID(repoID int64, sortType string) ([]*Label, error) { | |
labels := make([]*Label, 0, 10) | |
sess := x.Where("repo_id = ?", repoID) | |
switch sortType { | |
case "reversealphabetically": | |
sess.Desc("name") | |
case "leastissues": | |
sess.Asc("num_issues") | |
case "mostissues": | |
sess.Desc("num_issues") | |
default: | |
sess.Asc("name") | |
} | |
return labels, sess.Find(&labels) | |
} | |
func getLabelsByIssueID(e Engine, issueID int64) ([]*Label, error) { | |
var labels []*Label | |
return labels, e.Where("issue_label.issue_id = ?", issueID). | |
Join("LEFT", "issue_label", "issue_label.label_id = label.id"). | |
Asc("label.name"). | |
Find(&labels) | |
} | |
// GetLabelsByIssueID returns all labels that belong to given issue by ID. | |
func GetLabelsByIssueID(issueID int64) ([]*Label, error) { | |
return getLabelsByIssueID(x, issueID) | |
} | |
func updateLabel(e Engine, l *Label) error { | |
_, err := e.ID(l.ID).AllCols().Update(l) | |
return err | |
} | |
// UpdateLabel updates label information. | |
func UpdateLabel(l *Label) error { | |
return updateLabel(x, l) | |
} | |
// DeleteLabel delete a label of given repository. | |
func DeleteLabel(repoID, labelID int64) error { | |
_, err := GetLabelInRepoByID(repoID, labelID) | |
if err != nil { | |
if IsErrLabelNotExist(err) { | |
return nil | |
} | |
return err | |
} | |
sess := x.NewSession() | |
defer sess.Close() | |
if err = sess.Begin(); err != nil { | |
return err | |
} | |
if _, err = sess.ID(labelID).Delete(new(Label)); err != nil { | |
return err | |
} else if _, err = sess. | |
Where("label_id = ?", labelID). | |
Delete(new(IssueLabel)); err != nil { | |
return err | |
} | |
// Clear label id in comment table | |
if _, err = sess.Where("label_id = ?", labelID).Cols("label_id").Update(&Comment{}); err != nil { | |
return err | |
} | |
return sess.Commit() | |
} |
Or if it is preferred to just have some code duplication and copy the existing functions and replacing repoID
with orgID
(it isn't too much here).
Duplicating them doesn't feel right, but hesitant to touch things that are working otherwise and just wanted some feedback as to which is preferred. The current API would remain the same for repo labels regardless so it would just be a refractor and not breaking change.