2017-02-27 08:45:03 +08:00
// Copyright 2017 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package models
import (
"fmt"
"strings"
"github.com/go-xorm/builder"
)
// RepositoryList contains a list of repositories
type RepositoryList [ ] * Repository
2017-08-02 22:09:16 -07:00
// RepositoryListOfMap make list from values of map
func RepositoryListOfMap ( repoMap map [ int64 ] * Repository ) RepositoryList {
return RepositoryList ( valuesRepository ( repoMap ) )
}
2017-02-27 08:45:03 +08:00
func ( repos RepositoryList ) loadAttributes ( e Engine ) error {
if len ( repos ) == 0 {
return nil
}
// Load owners.
2017-03-11 03:50:12 -05:00
set := make ( map [ int64 ] struct { } )
2017-02-27 08:45:03 +08:00
for i := range repos {
2017-03-11 03:50:12 -05:00
set [ repos [ i ] . OwnerID ] = struct { } { }
2017-02-27 08:45:03 +08:00
}
2017-03-11 03:50:12 -05:00
users := make ( map [ int64 ] * User , len ( set ) )
2017-02-27 08:45:03 +08:00
if err := e .
Where ( "id > 0" ) .
2017-03-11 03:50:12 -05:00
In ( "id" , keysInt64 ( set ) ) .
2017-02-27 08:45:03 +08:00
Find ( & users ) ; err != nil {
return fmt . Errorf ( "find users: %v" , err )
}
for i := range repos {
2017-03-11 03:50:12 -05:00
repos [ i ] . Owner = users [ repos [ i ] . OwnerID ]
2017-02-27 08:45:03 +08:00
}
return nil
}
// LoadAttributes loads the attributes for the given RepositoryList
func ( repos RepositoryList ) LoadAttributes ( ) error {
return repos . loadAttributes ( x )
}
// MirrorRepositoryList contains the mirror repositories
type MirrorRepositoryList [ ] * Repository
func ( repos MirrorRepositoryList ) loadAttributes ( e Engine ) error {
if len ( repos ) == 0 {
return nil
}
// Load mirrors.
repoIDs := make ( [ ] int64 , 0 , len ( repos ) )
for i := range repos {
if ! repos [ i ] . IsMirror {
continue
}
repoIDs = append ( repoIDs , repos [ i ] . ID )
}
mirrors := make ( [ ] * Mirror , 0 , len ( repoIDs ) )
if err := e .
Where ( "id > 0" ) .
In ( "repo_id" , repoIDs ) .
Find ( & mirrors ) ; err != nil {
return fmt . Errorf ( "find mirrors: %v" , err )
}
set := make ( map [ int64 ] * Mirror )
for i := range mirrors {
set [ mirrors [ i ] . RepoID ] = mirrors [ i ]
}
for i := range repos {
repos [ i ] . Mirror = set [ repos [ i ] . ID ]
}
return nil
}
// LoadAttributes loads the attributes for the given MirrorRepositoryList
func ( repos MirrorRepositoryList ) LoadAttributes ( ) error {
return repos . loadAttributes ( x )
}
// SearchRepoOptions holds the search options
2017-05-02 15:35:59 +02:00
// swagger:parameters repoSearch
2017-02-27 08:45:03 +08:00
type SearchRepoOptions struct {
2017-05-02 15:35:59 +02:00
// Keyword to search
//
// in: query
Keyword string ` json:"q" `
// Owner in we search search
//
// in: query
2017-08-23 03:30:54 +02:00
OwnerID int64 ` json:"uid" `
Searcher * User ` json:"-" ` //ID of the person who's seeking
OrderBy string ` json:"-" `
Private bool ` json:"-" ` // Include private repositories in results
Collaborate bool ` json:"-" ` // Include collaborative repositories
Starred bool ` json:"-" `
Page int ` json:"-" `
IsProfile bool ` json:"-" `
2017-05-02 15:35:59 +02:00
// Limit of result
//
// maximum: setting.ExplorePagingNum
// in: query
PageSize int ` json:"limit" ` // Can be smaller than or equal to setting.ExplorePagingNum
2017-02-27 08:45:03 +08:00
}
// SearchRepositoryByName takes keyword and part of repository name to search,
// it returns results in given range and number of total results.
func SearchRepositoryByName ( opts * SearchRepoOptions ) ( repos RepositoryList , count int64 , err error ) {
2017-08-23 03:30:54 +02:00
var cond = builder . NewCond ( )
2017-02-27 08:45:03 +08:00
if opts . Page <= 0 {
opts . Page = 1
}
2017-08-24 22:01:03 +08:00
var starJoin bool
2017-02-27 08:45:03 +08:00
if opts . Starred && opts . OwnerID > 0 {
cond = builder . Eq {
"star.uid" : opts . OwnerID ,
}
2017-08-24 22:01:03 +08:00
starJoin = true
2017-02-27 08:45:03 +08:00
}
2017-08-23 03:30:54 +02:00
opts . Keyword = strings . ToLower ( opts . Keyword )
if opts . Keyword != "" {
cond = cond . And ( builder . Like { "lower_name" , opts . Keyword } )
}
2017-02-27 08:45:03 +08:00
// Append conditions
if ! opts . Starred && opts . OwnerID > 0 {
2017-08-24 22:01:03 +08:00
var searcherReposCond builder . Cond = builder . Eq { "owner_id" : opts . OwnerID }
if opts . Searcher != nil {
var ownerIds [ ] int64
ownerIds = append ( ownerIds , opts . Searcher . ID )
err = opts . Searcher . GetOrganizations ( true )
if err != nil {
return nil , 0 , fmt . Errorf ( "Organization: %v" , err )
}
for _ , org := range opts . Searcher . Orgs {
ownerIds = append ( ownerIds , org . ID )
}
searcherReposCond = searcherReposCond . Or ( builder . In ( "owner_id" , ownerIds ) )
if opts . Collaborate {
searcherReposCond = searcherReposCond . Or ( builder . Expr ( "id IN (SELECT repo_id FROM `access` WHERE access.user_id = ? AND owner_id != ?)" ,
opts . Searcher . ID , opts . Searcher . ID ) )
}
}
cond = cond . And ( searcherReposCond )
2017-02-27 08:45:03 +08:00
}
2017-08-24 22:01:03 +08:00
2017-02-27 08:45:03 +08:00
if ! opts . Private {
cond = cond . And ( builder . Eq { "is_private" : false } )
}
if len ( opts . OrderBy ) == 0 {
opts . OrderBy = "name ASC"
}
2017-08-23 03:30:54 +02:00
sess := x . NewSession ( )
defer sess . Close ( )
2017-08-24 22:01:03 +08:00
if starJoin {
2017-08-23 03:30:54 +02:00
count , err = sess .
2017-02-27 08:45:03 +08:00
Join ( "INNER" , "star" , "star.repo_id = repository.id" ) .
Where ( cond ) .
Count ( new ( Repository ) )
if err != nil {
return nil , 0 , fmt . Errorf ( "Count: %v" , err )
}
2017-08-23 03:30:54 +02:00
sess . Join ( "INNER" , "star" , "star.repo_id = repository.id" )
2017-02-27 08:45:03 +08:00
} else {
2017-08-23 03:30:54 +02:00
count , err = sess .
2017-02-27 08:45:03 +08:00
Where ( cond ) .
Count ( new ( Repository ) )
if err != nil {
return nil , 0 , fmt . Errorf ( "Count: %v" , err )
}
}
2017-08-23 03:30:54 +02:00
repos = make ( [ ] * Repository , 0 , opts . PageSize )
2017-02-27 08:45:03 +08:00
if err = sess .
2017-08-23 03:30:54 +02:00
Where ( cond ) .
2017-02-27 08:45:03 +08:00
Limit ( opts . PageSize , ( opts . Page - 1 ) * opts . PageSize ) .
OrderBy ( opts . OrderBy ) .
Find ( & repos ) ; err != nil {
return nil , 0 , fmt . Errorf ( "Repo: %v" , err )
}
if ! opts . IsProfile {
2017-08-23 03:30:54 +02:00
if err = repos . loadAttributes ( sess ) ; err != nil {
2017-02-27 08:45:03 +08:00
return nil , 0 , fmt . Errorf ( "LoadAttributes: %v" , err )
}
}
return
}
// Repositories returns all repositories
func Repositories ( opts * SearchRepoOptions ) ( _ RepositoryList , count int64 , err error ) {
if len ( opts . OrderBy ) == 0 {
opts . OrderBy = "id ASC"
}
repos := make ( RepositoryList , 0 , opts . PageSize )
if err = x .
Limit ( opts . PageSize , ( opts . Page - 1 ) * opts . PageSize ) .
OrderBy ( opts . OrderBy ) .
Find ( & repos ) ; err != nil {
return nil , 0 , fmt . Errorf ( "Repo: %v" , err )
}
if err = repos . loadAttributes ( x ) ; err != nil {
return nil , 0 , fmt . Errorf ( "LoadAttributes: %v" , err )
}
count = countRepositories ( - 1 , opts . Private )
return repos , count , nil
}
// GetRecentUpdatedRepositories returns the list of repositories that are recently updated.
func GetRecentUpdatedRepositories ( opts * SearchRepoOptions ) ( repos RepositoryList , _ int64 , _ error ) {
var cond = builder . NewCond ( )
if len ( opts . OrderBy ) == 0 {
opts . OrderBy = "updated_unix DESC"
}
if ! opts . Private {
cond = builder . Eq {
"is_private" : false ,
}
}
if opts . Searcher != nil && ! opts . Searcher . IsAdmin {
var ownerIds [ ] int64
ownerIds = append ( ownerIds , opts . Searcher . ID )
err := opts . Searcher . GetOrganizations ( true )
if err != nil {
return nil , 0 , fmt . Errorf ( "Organization: %v" , err )
}
for _ , org := range opts . Searcher . Orgs {
ownerIds = append ( ownerIds , org . ID )
}
cond = cond . Or ( builder . In ( "owner_id" , ownerIds ) )
}
count , err := x . Where ( cond ) . Count ( new ( Repository ) )
if err != nil {
return nil , 0 , fmt . Errorf ( "Count: %v" , err )
}
if err = x . Where ( cond ) .
Limit ( opts . PageSize , ( opts . Page - 1 ) * opts . PageSize ) .
Limit ( opts . PageSize ) .
OrderBy ( opts . OrderBy ) .
Find ( & repos ) ; err != nil {
return nil , 0 , fmt . Errorf ( "Repo: %v" , err )
}
if err = repos . loadAttributes ( x ) ; err != nil {
return nil , 0 , fmt . Errorf ( "LoadAttributes: %v" , err )
}
return repos , count , nil
}