Skip to content

Commit 86442ad

Browse files
committed
in progress changes for go-gitea#7405, added ability to add cross-repo dependencies
1 parent 76408d5 commit 86442ad

26 files changed

+244
-62
lines changed

models/issue.go

+48-12
Original file line numberDiff line numberDiff line change
@@ -1747,8 +1747,8 @@ func GetRepoIssueStats(repoID, uid int64, filterMode int, isPull bool) (numOpen
17471747
}
17481748

17491749
// SearchIssueIDsByKeyword search issues on database
1750-
func SearchIssueIDsByKeyword(kw string, repoID int64, limit, start int) (int64, []int64, error) {
1751-
var repoCond = builder.Eq{"repo_id": repoID}
1750+
func SearchIssueIDsByKeyword(kw string, repoIDs []int64, limit, start int) (int64, []int64, error) {
1751+
var repoCond = builder.In("repo_id", repoIDs)
17521752
var subQuery = builder.Select("id").From("issue").Where(repoCond)
17531753
var cond = builder.And(
17541754
repoCond,
@@ -1820,33 +1820,69 @@ func UpdateIssueDeadline(issue *Issue, deadlineUnix util.TimeStamp, doer *User)
18201820
return sess.Commit()
18211821
}
18221822

1823+
// DependencyInfo represents high level information about an issue which is a dependency of another issue.
1824+
type DependencyInfo struct {
1825+
ID int64 `xorm:"id"`
1826+
RepoID int64 `xorm:"repo_id"`
1827+
Index int64 `xorm:"index"`
1828+
IsClosed bool `xorm:"is_closed"`
1829+
Title string `xorm:"name"`
1830+
RepoLink string `xorm:"-"`
1831+
}
1832+
18231833
// Get Blocked By Dependencies, aka all issues this issue is blocked by.
1824-
func (issue *Issue) getBlockedByDependencies(e Engine) (issueDeps []*Issue, err error) {
1825-
return issueDeps, e.
1826-
Table("issue_dependency").
1827-
Select("issue.*").
1834+
func (issue *Issue) getBlockedByDependencies(e Engine) (issueDeps []*DependencyInfo, err error) {
1835+
err = e.Table("issue_dependency").
1836+
Select("issue.id, issue.repo_id, issue.index, issue.is_closed, issue.name").
18281837
Join("INNER", "issue", "issue.id = issue_dependency.dependency_id").
18291838
Where("issue_id = ?", issue.ID).
18301839
Find(&issueDeps)
1840+
1841+
if err != nil {
1842+
return nil, err
1843+
}
1844+
1845+
for i := 0; i < len(issueDeps); i++ {
1846+
repo, err := GetRepositoryByID(issueDeps[i].RepoID)
1847+
if err != nil {
1848+
return nil, err
1849+
}
1850+
issueDeps[i].RepoLink = repo.Link()
1851+
}
1852+
1853+
return issueDeps, nil
18311854
}
18321855

18331856
// Get Blocking Dependencies, aka all issues this issue blocks.
1834-
func (issue *Issue) getBlockingDependencies(e Engine) (issueDeps []*Issue, err error) {
1835-
return issueDeps, e.
1836-
Table("issue_dependency").
1837-
Select("issue.*").
1857+
func (issue *Issue) getBlockingDependencies(e Engine) (issueDeps []*DependencyInfo, err error) {
1858+
err = e.Table("issue_dependency").
1859+
Select("issue.id, issue.repo_id, issue.index, issue.is_closed, issue.name").
18381860
Join("INNER", "issue", "issue.id = issue_dependency.issue_id").
18391861
Where("dependency_id = ?", issue.ID).
18401862
Find(&issueDeps)
1863+
1864+
if err != nil {
1865+
return nil, err
1866+
}
1867+
1868+
for i := 0; i < len(issueDeps); i++ {
1869+
repo, err := GetRepositoryByID(issueDeps[i].RepoID)
1870+
if err != nil {
1871+
return nil, err
1872+
}
1873+
issueDeps[i].RepoLink = repo.Link()
1874+
}
1875+
1876+
return issueDeps, nil
18411877
}
18421878

18431879
// BlockedByDependencies finds all Dependencies an issue is blocked by
1844-
func (issue *Issue) BlockedByDependencies() ([]*Issue, error) {
1880+
func (issue *Issue) BlockedByDependencies() ([]*DependencyInfo, error) {
18451881
return issue.getBlockedByDependencies(x)
18461882
}
18471883

18481884
// BlockingDependencies returns all blocking dependencies, aka all other issues a given issue blocks
1849-
func (issue *Issue) BlockingDependencies() ([]*Issue, error) {
1885+
func (issue *Issue) BlockingDependencies() ([]*DependencyInfo, error) {
18501886
return issue.getBlockingDependencies(x)
18511887
}
18521888

models/issue_label.go

+13
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,19 @@ func GetLabelIDsInRepoByNames(repoID int64, labelNames []string) ([]int64, error
217217
Find(&labelIDs)
218218
}
219219

220+
// GetLabelIDsInReposByNames returns a list of labelIDs by names in one of the given
221+
// repositories.
222+
// it silently ignores label names that do not belong to the repository.
223+
func GetLabelIDsInReposByNames(repoIDs []int64, labelNames []string) ([]int64, error) {
224+
labelIDs := make([]int64, 0, len(labelNames))
225+
return labelIDs, x.Table("label").
226+
In("repo_id", repoIDs).
227+
In("name", labelNames).
228+
Asc("name").
229+
Cols("id").
230+
Find(&labelIDs)
231+
}
232+
220233
// GetLabelInRepoByID returns a label by ID in given repository.
221234
func GetLabelInRepoByID(repoID, labelID int64) (*Label, error) {
222235
return getLabelInRepoByID(x, repoID, labelID)

models/issue_test.go

+4-5
Original file line numberDiff line numberDiff line change
@@ -298,24 +298,23 @@ func TestIssue_loadTotalTimes(t *testing.T) {
298298

299299
func TestIssue_SearchIssueIDsByKeyword(t *testing.T) {
300300
assert.NoError(t, PrepareTestDatabase())
301-
302-
total, ids, err := SearchIssueIDsByKeyword("issue2", 1, 10, 0)
301+
total, ids, err := SearchIssueIDsByKeyword("issue2", []int64{1}, 10, 0)
303302
assert.NoError(t, err)
304303
assert.EqualValues(t, 1, total)
305304
assert.EqualValues(t, []int64{2}, ids)
306305

307-
total, ids, err = SearchIssueIDsByKeyword("first", 1, 10, 0)
306+
total, ids, err = SearchIssueIDsByKeyword("first", []int64{1}, 10, 0)
308307
assert.NoError(t, err)
309308
assert.EqualValues(t, 1, total)
310309
assert.EqualValues(t, []int64{1}, ids)
311310

312-
total, ids, err = SearchIssueIDsByKeyword("for", 1, 10, 0)
311+
total, ids, err = SearchIssueIDsByKeyword("for", []int64{1}, 10, 0)
313312
assert.NoError(t, err)
314313
assert.EqualValues(t, 4, total)
315314
assert.EqualValues(t, []int64{1, 2, 3, 5}, ids)
316315

317316
// issue1's comment id 2
318-
total, ids, err = SearchIssueIDsByKeyword("good", 1, 10, 0)
317+
total, ids, err = SearchIssueIDsByKeyword("good", []int64{1}, 10, 0)
319318
assert.NoError(t, err)
320319
assert.EqualValues(t, 1, total)
321320
assert.EqualValues(t, []int64{1}, ids)

modules/indexer/issues/bleve.go

+12-4
Original file line numberDiff line numberDiff line change
@@ -218,9 +218,18 @@ func (b *BleveIndexer) Delete(ids ...int64) error {
218218

219219
// Search searches for issues by given conditions.
220220
// Returns the matching issue IDs
221-
func (b *BleveIndexer) Search(keyword string, repoID int64, limit, start int) (*SearchResult, error) {
221+
func (b *BleveIndexer) Search(keyword string, repoIDs []int64, limit, start int) (*SearchResult, error) {
222+
var repoQueriesP []*query.NumericRangeQuery
223+
for _, repoID := range repoIDs {
224+
repoQueriesP = append(repoQueriesP, numericEqualityQuery(repoID, "RepoID"))
225+
}
226+
repoQueries := make([]query.Query, len(repoQueriesP))
227+
for i, v := range repoQueriesP {
228+
repoQueries[i] = query.Query(v)
229+
}
230+
222231
indexerQuery := bleve.NewConjunctionQuery(
223-
numericEqualityQuery(repoID, "RepoID"),
232+
bleve.NewDisjunctionQuery(repoQueries...),
224233
bleve.NewDisjunctionQuery(
225234
newMatchPhraseQuery(keyword, "Title", issueIndexerAnalyzer),
226235
newMatchPhraseQuery(keyword, "Content", issueIndexerAnalyzer),
@@ -242,8 +251,7 @@ func (b *BleveIndexer) Search(keyword string, repoID int64, limit, start int) (*
242251
return nil, err
243252
}
244253
ret.Hits = append(ret.Hits, Match{
245-
ID: id,
246-
RepoID: repoID,
254+
ID: id,
247255
})
248256
}
249257
return &ret, nil

modules/indexer/issues/bleve_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ func TestBleveIndexAndSearch(t *testing.T) {
7676
)
7777

7878
for _, kw := range keywords {
79-
res, err := indexer.Search(kw.Keyword, 2, 10, 0)
79+
res, err := indexer.Search(kw.Keyword, []int64{2}, 10, 0)
8080
assert.NoError(t, err)
8181

8282
var ids = make([]int64, 0, len(res.Hits))

modules/indexer/issues/db.go

+3-4
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@ func (db *DBIndexer) Delete(ids ...int64) error {
2626
}
2727

2828
// Search dummy function
29-
func (db *DBIndexer) Search(kw string, repoID int64, limit, start int) (*SearchResult, error) {
30-
total, ids, err := models.SearchIssueIDsByKeyword(kw, repoID, limit, start)
29+
func (db *DBIndexer) Search(kw string, repoIDs []int64, limit, start int) (*SearchResult, error) {
30+
total, ids, err := models.SearchIssueIDsByKeyword(kw, repoIDs, limit, start)
3131
if err != nil {
3232
return nil, err
3333
}
@@ -37,8 +37,7 @@ func (db *DBIndexer) Search(kw string, repoID int64, limit, start int) (*SearchR
3737
}
3838
for _, id := range ids {
3939
result.Hits = append(result.Hits, Match{
40-
ID: id,
41-
RepoID: repoID,
40+
ID: id,
4241
})
4342
}
4443
return &result, nil

modules/indexer/issues/indexer.go

+5-6
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,8 @@ type IndexerData struct {
2626

2727
// Match represents on search result
2828
type Match struct {
29-
ID int64 `json:"id"`
30-
RepoID int64 `json:"repo_id"`
31-
Score float64 `json:"score"`
29+
ID int64 `json:"id"`
30+
Score float64 `json:"score"`
3231
}
3332

3433
// SearchResult represents search results
@@ -42,7 +41,7 @@ type Indexer interface {
4241
Init() (bool, error)
4342
Index(issue []*IndexerData) error
4443
Delete(ids ...int64) error
45-
Search(kw string, repoID int64, limit, start int) (*SearchResult, error)
44+
Search(kw string, repoIDs []int64, limit, start int) (*SearchResult, error)
4645
}
4746

4847
var (
@@ -195,9 +194,9 @@ func DeleteRepoIssueIndexer(repo *models.Repository) {
195194
}
196195

197196
// SearchIssuesByKeyword search issue ids by keywords and repo id
198-
func SearchIssuesByKeyword(repoID int64, keyword string) ([]int64, error) {
197+
func SearchIssuesByKeyword(repoIDs []int64, keyword string) ([]int64, error) {
199198
var issueIDs []int64
200-
res, err := issueIndexer.Search(keyword, repoID, 1000, 0)
199+
res, err := issueIndexer.Search(keyword, repoIDs, 1000, 0)
201200
if err != nil {
202201
return nil, err
203202
}

modules/indexer/issues/indexer_test.go

+8-8
Original file line numberDiff line numberDiff line change
@@ -38,19 +38,19 @@ func TestBleveSearchIssues(t *testing.T) {
3838

3939
time.Sleep(5 * time.Second)
4040

41-
ids, err := SearchIssuesByKeyword(1, "issue2")
41+
ids, err := SearchIssuesByKeyword([]int64{1}, "issue2")
4242
assert.NoError(t, err)
4343
assert.EqualValues(t, []int64{2}, ids)
4444

45-
ids, err = SearchIssuesByKeyword(1, "first")
45+
ids, err = SearchIssuesByKeyword([]int64{1}, "first")
4646
assert.NoError(t, err)
4747
assert.EqualValues(t, []int64{1}, ids)
4848

49-
ids, err = SearchIssuesByKeyword(1, "for")
49+
ids, err = SearchIssuesByKeyword([]int64{1}, "for")
5050
assert.NoError(t, err)
5151
assert.EqualValues(t, []int64{1, 2, 3, 5}, ids)
5252

53-
ids, err = SearchIssuesByKeyword(1, "good")
53+
ids, err = SearchIssuesByKeyword([]int64{1}, "good")
5454
assert.NoError(t, err)
5555
assert.EqualValues(t, []int64{1}, ids)
5656
}
@@ -63,19 +63,19 @@ func TestDBSearchIssues(t *testing.T) {
6363
fatalTestError("Error InitIssueIndexer: %v\n", err)
6464
}
6565

66-
ids, err := SearchIssuesByKeyword(1, "issue2")
66+
ids, err := SearchIssuesByKeyword([]int64{1}, "issue2")
6767
assert.NoError(t, err)
6868
assert.EqualValues(t, []int64{2}, ids)
6969

70-
ids, err = SearchIssuesByKeyword(1, "first")
70+
ids, err = SearchIssuesByKeyword([]int64{1}, "first")
7171
assert.NoError(t, err)
7272
assert.EqualValues(t, []int64{1}, ids)
7373

74-
ids, err = SearchIssuesByKeyword(1, "for")
74+
ids, err = SearchIssuesByKeyword([]int64{1}, "for")
7575
assert.NoError(t, err)
7676
assert.EqualValues(t, []int64{1, 2, 3, 5}, ids)
7777

78-
ids, err = SearchIssuesByKeyword(1, "good")
78+
ids, err = SearchIssuesByKeyword([]int64{1}, "good")
7979
assert.NoError(t, err)
8080
assert.EqualValues(t, []int64{1}, ids)
8181
}

options/locale/locale_cs-CZ.ini

-1
Original file line numberDiff line numberDiff line change
@@ -909,7 +909,6 @@ issues.dependency.add_error_dep_issue_not_exist=Související úkol neexistuje.
909909
issues.dependency.add_error_dep_not_exist=Závislost neexistuje.
910910
issues.dependency.add_error_dep_exists=Závislost již existuje.
911911
issues.dependency.add_error_cannot_create_circular=Nemůžete vytvořit závislost dvou úkolů, které se vzájemně blokují.
912-
issues.dependency.add_error_dep_not_same_repo=Oba úkoly musí být ve stejném repozitáři.
913912
issues.review.self.approval=Nemůžete schválit svůj požadavek na natažení.
914913
issues.review.self.rejection=Nemůžete požadovat změny ve svém vlastním požadavku na natažení.
915914
issues.review.approve=schválil tyto změny %s

options/locale/locale_de-DE.ini

-1
Original file line numberDiff line numberDiff line change
@@ -932,7 +932,6 @@ issues.dependency.add_error_dep_issue_not_exist=Abhängiges Issue existiert nich
932932
issues.dependency.add_error_dep_not_exist=Abhängigkeit existiert nicht.
933933
issues.dependency.add_error_dep_exists=Abhängigkeit existiert bereits.
934934
issues.dependency.add_error_cannot_create_circular=Du kannst keine Abhängigkeit erstellen, bei welcher sich zwei Issues gegenseitig blockieren.
935-
issues.dependency.add_error_dep_not_same_repo=Beide Issues müssen sich im selben Repository befinden.
936935
issues.review.self.approval=Du kannst keine Änderungen an deinem eigenen Pull-Request genehmigen.
937936
issues.review.self.rejection=Du kannst keine Änderungen an deinem eigenen Pull-Request anfragen.
938937
issues.review.approve=hat die Änderungen %s genehmigt

options/locale/locale_en-US.ini

-1
Original file line numberDiff line numberDiff line change
@@ -933,7 +933,6 @@ issues.dependency.add_error_dep_issue_not_exist = Dependent issue does not exist
933933
issues.dependency.add_error_dep_not_exist = Dependency does not exist.
934934
issues.dependency.add_error_dep_exists = Dependency already exists.
935935
issues.dependency.add_error_cannot_create_circular = You cannot create a dependency with two issues blocking each other.
936-
issues.dependency.add_error_dep_not_same_repo = Both issues must be in the same repository.
937936
issues.review.self.approval = You cannot approve your own pull request.
938937
issues.review.self.rejection = You cannot request changes on your own pull request.
939938
issues.review.approve = "approved these changes %s"

options/locale/locale_es-ES.ini

-1
Original file line numberDiff line numberDiff line change
@@ -932,7 +932,6 @@ issues.dependency.add_error_dep_issue_not_exist=Incidencia dependiente no existe
932932
issues.dependency.add_error_dep_not_exist=La dependencia no existe.
933933
issues.dependency.add_error_dep_exists=La dependencia ya existe.
934934
issues.dependency.add_error_cannot_create_circular=No puede crear una depenciena con dos issues que se estan bloqueando mutuamente.
935-
issues.dependency.add_error_dep_not_same_repo=Ambas incidencias deben estar en el mismo repositorio.
936935
issues.review.self.approval=No puede aprobar su propio pull request.
937936
issues.review.self.rejection=No puede sugerir cambios en su propio pull request.
938937
issues.review.approve=aprobado estos cambios %s

options/locale/locale_fr-FR.ini

-1
Original file line numberDiff line numberDiff line change
@@ -932,7 +932,6 @@ issues.dependency.add_error_dep_issue_not_exist=Le ticket dépendant n'existe pa
932932
issues.dependency.add_error_dep_not_exist=La dépendance n'existe pas.
933933
issues.dependency.add_error_dep_exists=La dépendance existe déjà.
934934
issues.dependency.add_error_cannot_create_circular=Vous ne pouvez pas créer une dépendance avec deux tickets qui se bloquent l'un l'autre.
935-
issues.dependency.add_error_dep_not_same_repo=Les deux tickets doivent être dans le même dépôt.
936935
issues.review.self.approval=Vous ne pouvez approuver vos propres demandes d'ajout.
937936
issues.review.self.rejection=Vous ne pouvez demander de changements sur vos propres demandes de changement.
938937
issues.review.approve=ces changements ont été approuvés %s

options/locale/locale_ja-JP.ini

-1
Original file line numberDiff line numberDiff line change
@@ -932,7 +932,6 @@ issues.dependency.add_error_dep_issue_not_exist=依存先の課題が存在し
932932
issues.dependency.add_error_dep_not_exist=依存関係が存在していません。
933933
issues.dependency.add_error_dep_exists=依存関係は既に設定済みです。
934934
issues.dependency.add_error_cannot_create_circular=2つの課題が互いにブロックする依存関係は作成できません。
935-
issues.dependency.add_error_dep_not_same_repo=両方とも同じリポジトリの課題にする必要があります。
936935
issues.review.self.approval=自分のプルリクエストを承認することはできません。
937936
issues.review.self.rejection=自分のプルリクエストに対して修正を要求することはできません。
938937
issues.review.approve=が変更を承認 %s

options/locale/locale_lv-LV.ini

-1
Original file line numberDiff line numberDiff line change
@@ -931,7 +931,6 @@ issues.dependency.add_error_dep_issue_not_exist=Atkarīgā problēma neeksistē.
931931
issues.dependency.add_error_dep_not_exist=Atkarība neeksistē.
932932
issues.dependency.add_error_dep_exists=Atkarība jau ir pievienota.
933933
issues.dependency.add_error_cannot_create_circular=Nav iespējams veidot atkarību, kur divas problēmas bloķētu viena otru.
934-
issues.dependency.add_error_dep_not_same_repo=Abām problēmām ir jābūt no viena repozitorija.
935934
issues.review.self.approval=Nevar apstiprināt savu izmaiņu pieprasījumi.
936935
issues.review.self.rejection=Nevar pieprasīt izmaiņas savam izmaiņu pieprasījumam.
937936
issues.review.approve=apstiprināja izmaiņas %s

options/locale/locale_pt-BR.ini

-1
Original file line numberDiff line numberDiff line change
@@ -932,7 +932,6 @@ issues.dependency.add_error_dep_issue_not_exist=Issue dependente não existe.
932932
issues.dependency.add_error_dep_not_exist=Dependência não existe.
933933
issues.dependency.add_error_dep_exists=Dependência já existe.
934934
issues.dependency.add_error_cannot_create_circular=Você não pode criar uma dependência com duas issues bloqueando uma a outra.
935-
issues.dependency.add_error_dep_not_same_repo=Ambas as issues devem estar no mesmo repositório.
936935
issues.review.self.approval=Você não pode aprovar o seu próprio pull request.
937936
issues.review.self.rejection=Você não pode solicitar alterações em seu próprio pull request.
938937
issues.review.approve=aprovou estas alterações %s

options/locale/locale_ru-RU.ini

-1
Original file line numberDiff line numberDiff line change
@@ -900,7 +900,6 @@ issues.dependency.add_error_dep_issue_not_exist=Зависимая задача
900900
issues.dependency.add_error_dep_not_exist=Зависимости не существует.
901901
issues.dependency.add_error_dep_exists=Зависимость уже существует.
902902
issues.dependency.add_error_cannot_create_circular=Вы не можете создать зависимость с двумя задачами, блокирующими друг друга.
903-
issues.dependency.add_error_dep_not_same_repo=Обе задачи должны находиться в одном репозитории.
904903
issues.review.self.approval=Вы не можете одобрить собственный Pull Request.
905904
issues.review.self.rejection=Невозможно запрашивать изменения своего Pull Request'а.
906905
issues.review.approve=одобрил(а) эти изменения %s

options/locale/locale_uk-UA.ini

-1
Original file line numberDiff line numberDiff line change
@@ -802,7 +802,6 @@ issues.dependency.add_error_dep_issue_not_exist=Залежність для пр
802802
issues.dependency.add_error_dep_not_exist=Залежність не існує.
803803
issues.dependency.add_error_dep_exists=Залежність уже існує.
804804
issues.dependency.add_error_cannot_create_circular=Ви не можете створити залежність з двома проблемами, які блокують одна одну.
805-
issues.dependency.add_error_dep_not_same_repo=Обидві проблеми повинні бути в одному репозиторії.
806805
issues.review.self.approval=Ви не можете схвалити власний пулл-реквест.
807806
issues.review.self.rejection=Ви не можете надіслати запит на зміну на власний пулл-реквест.
808807
issues.review.approve=зміни затверджено %s

options/locale/locale_zh-CN.ini

-1
Original file line numberDiff line numberDiff line change
@@ -932,7 +932,6 @@ issues.dependency.add_error_dep_issue_not_exist=依赖项不存在。
932932
issues.dependency.add_error_dep_not_exist=依赖项不存在。
933933
issues.dependency.add_error_dep_exists=依赖项已存在。
934934
issues.dependency.add_error_cannot_create_circular=您不能创建依赖, 使得两个工单相互阻止。
935-
issues.dependency.add_error_dep_not_same_repo=这两个工单必须在同一仓库。
936935
issues.review.self.approval=您不能批准您自己的合并请求。
937936
issues.review.self.rejection=您不能请求对您自己的合并请求进行更改。
938937
issues.review.approve=已于 %s 批准这些更改

public/js/index.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -3077,7 +3077,7 @@ function initIssueList() {
30773077
$('#new-dependency-drop-list')
30783078
.dropdown({
30793079
apiSettings: {
3080-
url: suburl + '/api/v1/repos/' + repolink + '/issues?q={query}',
3080+
url: suburl + '/api/v1/repos/issues/search?q={query}',
30813081
onResponse: function(response) {
30823082
const filteredResponse = {'success': true, 'results': []};
30833083
const currIssueId = $('#new-dependency-drop-list').data('issue-id');

routers/api/v1/api.go

+2
Original file line numberDiff line numberDiff line change
@@ -602,6 +602,8 @@ func RegisterRoutes(m *macaron.Macaron) {
602602
m.Get("/search", repo.Search)
603603
})
604604

605+
m.Get("/repos/issues/search", repo.SearchIssues)
606+
605607
m.Combo("/repositories/:id", reqToken()).Get(repo.GetByID)
606608

607609
m.Group("/repos", func() {

0 commit comments

Comments
 (0)