API: Return primary language and repository language stats API URL (#18396)

This commit is contained in:
Lauris BH 2022-01-25 08:33:40 +02:00 committed by GitHub
parent 9628a76ce6
commit 6392f4691a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 55 additions and 2 deletions

View File

@ -222,6 +222,30 @@ func (repo *Repository) MustOwner() *user_model.User {
return repo.mustOwner(db.DefaultContext) return repo.mustOwner(db.DefaultContext)
} }
// LoadAttributes loads attributes of the repository.
func (repo *Repository) LoadAttributes(ctx context.Context) error {
// Load owner
if err := repo.GetOwner(ctx); err != nil {
return fmt.Errorf("load owner: %w", err)
}
// Load primary language
stats := make(LanguageStatList, 0, 1)
if err := db.GetEngine(ctx).
Where("`repo_id` = ? AND `is_primary` = ? AND `language` != ?", repo.ID, true, "other").
Find(&stats); err != nil {
return fmt.Errorf("find primary languages: %w", err)
}
stats.LoadAttributes()
for _, st := range stats {
if st.RepoID == repo.ID {
repo.PrimaryLanguage = st
break
}
}
return nil
}
// FullName returns the repository full name // FullName returns the repository full name
func (repo *Repository) FullName() string { func (repo *Repository) FullName() string {
return repo.OwnerName + "/" + repo.Name return repo.OwnerName + "/" + repo.Name

View File

@ -623,7 +623,7 @@ func FindUserAccessibleRepoIDs(user *user_model.User) ([]int64, error) {
} }
// GetUserRepositories returns a list of repositories of given user. // GetUserRepositories returns a list of repositories of given user.
func GetUserRepositories(opts *SearchRepoOptions) ([]*repo_model.Repository, int64, error) { func GetUserRepositories(opts *SearchRepoOptions) (RepositoryList, int64, error) {
if len(opts.OrderBy) == 0 { if len(opts.OrderBy) == 0 {
opts.OrderBy = "updated_unix DESC" opts.OrderBy = "updated_unix DESC"
} }
@ -646,6 +646,6 @@ func GetUserRepositories(opts *SearchRepoOptions) ([]*repo_model.Repository, int
} }
sess = sess.Where(cond).OrderBy(opts.OrderBy.String()) sess = sess.Where(cond).OrderBy(opts.OrderBy.String())
repos := make([]*repo_model.Repository, 0, opts.PageSize) repos := make(RepositoryList, 0, opts.PageSize)
return repos, count, db.SetSessionPagination(sess, opts).Find(&repos) return repos, count, db.SetSessionPagination(sess, opts).Find(&repos)
} }

View File

@ -125,6 +125,13 @@ func innerToRepo(repo *repo_model.Repository, mode perm.AccessMode, isParent boo
} }
} }
var language string
if repo.PrimaryLanguage != nil {
language = repo.PrimaryLanguage.Language
}
repoAPIURL := repo.APIURL()
return &api.Repository{ return &api.Repository{
ID: repo.ID, ID: repo.ID,
Owner: ToUserWithAccessMode(repo.Owner, mode), Owner: ToUserWithAccessMode(repo.Owner, mode),
@ -144,6 +151,8 @@ func innerToRepo(repo *repo_model.Repository, mode perm.AccessMode, isParent boo
CloneURL: cloneLink.HTTPS, CloneURL: cloneLink.HTTPS,
OriginalURL: repo.SanitizedOriginalURL(), OriginalURL: repo.SanitizedOriginalURL(),
Website: repo.Website, Website: repo.Website,
Language: language,
LanguagesURL: repoAPIURL + "/languages",
Stars: repo.NumStars, Stars: repo.NumStars,
Forks: repo.NumForks, Forks: repo.NumForks,
Watchers: repo.NumWatches, Watchers: repo.NumWatches,

View File

@ -59,6 +59,8 @@ type Repository struct {
Parent *Repository `json:"parent"` Parent *Repository `json:"parent"`
Mirror bool `json:"mirror"` Mirror bool `json:"mirror"`
Size int `json:"size"` Size int `json:"size"`
Language string `json:"language"`
LanguagesURL string `json:"languages_url"`
HTMLURL string `json:"html_url"` HTMLURL string `json:"html_url"`
SSHURL string `json:"ssh_url"` SSHURL string `json:"ssh_url"`
CloneURL string `json:"clone_url"` CloneURL string `json:"clone_url"`

View File

@ -533,6 +533,11 @@ func Get(ctx *context.APIContext) {
// "200": // "200":
// "$ref": "#/responses/Repository" // "$ref": "#/responses/Repository"
if err := ctx.Repo.Repository.LoadAttributes(ctx); err != nil {
ctx.Error(http.StatusInternalServerError, "Repository.LoadAttributes", err)
return
}
ctx.JSON(http.StatusOK, convert.ToRepo(ctx.Repo.Repository, ctx.Repo.AccessMode)) ctx.JSON(http.StatusOK, convert.ToRepo(ctx.Repo.Repository, ctx.Repo.AccessMode))
} }

View File

@ -32,6 +32,11 @@ func listUserRepos(ctx *context.APIContext, u *user_model.User, private bool) {
return return
} }
if err := repos.LoadAttributes(); err != nil {
ctx.Error(http.StatusInternalServerError, "RepositoryList.LoadAttributes", err)
return
}
apiRepos := make([]*api.Repository, 0, len(repos)) apiRepos := make([]*api.Repository, 0, len(repos))
for i := range repos { for i := range repos {
access, err := models.AccessLevel(ctx.User, repos[i]) access, err := models.AccessLevel(ctx.User, repos[i])

View File

@ -17188,6 +17188,14 @@
"internal_tracker": { "internal_tracker": {
"$ref": "#/definitions/InternalTracker" "$ref": "#/definitions/InternalTracker"
}, },
"language": {
"type": "string",
"x-go-name": "Language"
},
"languages_url": {
"type": "string",
"x-go-name": "LanguagesURL"
},
"mirror": { "mirror": {
"type": "boolean", "type": "boolean",
"x-go-name": "Mirror" "x-go-name": "Mirror"