2017-02-27 03:45:03 +03: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"
2021-09-19 14:49:59 +03:00
"code.gitea.io/gitea/models/db"
2021-11-28 14:58:28 +03:00
"code.gitea.io/gitea/models/perm"
2021-12-10 04:27:50 +03:00
repo_model "code.gitea.io/gitea/models/repo"
2021-11-24 12:49:20 +03:00
user_model "code.gitea.io/gitea/models/user"
2019-02-18 19:00:27 +03:00
"code.gitea.io/gitea/modules/structs"
2017-10-27 00:16:13 +03:00
"code.gitea.io/gitea/modules/util"
2019-06-23 18:22:43 +03:00
"xorm.io/builder"
2017-02-27 03:45:03 +03:00
)
2017-12-31 17:45:46 +03:00
// RepositoryListDefaultPageSize is the default number of repositories
// to load in memory when running administrative tasks on all (or almost
// all) of them.
// The number should be low enough to avoid filling up all RAM with
// repository data...
const RepositoryListDefaultPageSize = 64
2017-02-27 03:45:03 +03:00
// RepositoryList contains a list of repositories
2021-12-10 04:27:50 +03:00
type RepositoryList [ ] * repo_model . Repository
2017-02-27 03:45:03 +03:00
2017-12-04 07:39:01 +03:00
func ( repos RepositoryList ) Len ( ) int {
return len ( repos )
}
func ( repos RepositoryList ) Less ( i , j int ) bool {
return repos [ i ] . FullName ( ) < repos [ j ] . FullName ( )
}
func ( repos RepositoryList ) Swap ( i , j int ) {
repos [ i ] , repos [ j ] = repos [ j ] , repos [ i ]
}
2017-08-03 08:09:16 +03:00
// RepositoryListOfMap make list from values of map
2021-12-10 04:27:50 +03:00
func RepositoryListOfMap ( repoMap map [ int64 ] * repo_model . Repository ) RepositoryList {
2017-08-03 08:09:16 +03:00
return RepositoryList ( valuesRepository ( repoMap ) )
}
2021-09-19 14:49:59 +03:00
func ( repos RepositoryList ) loadAttributes ( e db . Engine ) error {
2017-02-27 03:45:03 +03:00
if len ( repos ) == 0 {
return nil
}
2017-03-11 11:50:12 +03:00
set := make ( map [ int64 ] struct { } )
2020-02-11 12:34:17 +03:00
repoIDs := make ( [ ] int64 , len ( repos ) )
2017-02-27 03:45:03 +03:00
for i := range repos {
2017-03-11 11:50:12 +03:00
set [ repos [ i ] . OwnerID ] = struct { } { }
2020-02-11 12:34:17 +03:00
repoIDs [ i ] = repos [ i ] . ID
2017-02-27 03:45:03 +03:00
}
2020-02-11 12:34:17 +03:00
// Load owners.
2021-11-24 12:49:20 +03:00
users := make ( map [ int64 ] * user_model . User , len ( set ) )
2017-02-27 03:45:03 +03:00
if err := e .
Where ( "id > 0" ) .
2017-03-11 11:50:12 +03:00
In ( "id" , keysInt64 ( set ) ) .
2017-02-27 03:45:03 +03:00
Find ( & users ) ; err != nil {
return fmt . Errorf ( "find users: %v" , err )
}
for i := range repos {
2017-03-11 11:50:12 +03:00
repos [ i ] . Owner = users [ repos [ i ] . OwnerID ]
2017-02-27 03:45:03 +03:00
}
2020-02-11 12:34:17 +03:00
// Load primary language.
2021-12-10 04:27:50 +03:00
stats := make ( repo_model . LanguageStatList , 0 , len ( repos ) )
2020-02-11 12:34:17 +03:00
if err := e .
Where ( "`is_primary` = ? AND `language` != ?" , true , "other" ) .
In ( "`repo_id`" , repoIDs ) .
Find ( & stats ) ; err != nil {
return fmt . Errorf ( "find primary languages: %v" , err )
}
2021-12-10 04:27:50 +03:00
stats . LoadAttributes ( )
2020-02-11 12:34:17 +03:00
for i := range repos {
for _ , st := range stats {
if st . RepoID == repos [ i ] . ID {
repos [ i ] . PrimaryLanguage = st
break
}
}
}
2017-02-27 03:45:03 +03:00
return nil
}
// LoadAttributes loads the attributes for the given RepositoryList
func ( repos RepositoryList ) LoadAttributes ( ) error {
2021-09-23 18:45:36 +03:00
return repos . loadAttributes ( db . GetEngine ( db . DefaultContext ) )
2017-02-27 03:45:03 +03:00
}
// SearchRepoOptions holds the search options
type SearchRepoOptions struct {
2021-09-24 14:32:56 +03:00
db . ListOptions
2021-11-24 12:49:20 +03:00
Actor * user_model . User
2019-11-11 18:15:29 +03:00
Keyword string
OwnerID int64
PriorityOwnerID int64
2020-12-27 22:58:03 +03:00
TeamID int64
2021-11-24 12:49:20 +03:00
OrderBy db . SearchOrderBy
2019-11-11 18:15:29 +03:00
Private bool // Include private repositories in results
StarredByID int64
2021-04-15 19:53:57 +03:00
WatchedByID int64
2020-01-05 21:48:47 +03:00
AllPublic bool // Include also all public repositories of users and public organisations
AllLimited bool // Include also all public repositories of limited organisations
2020-05-21 04:15:30 +03:00
// None -> include public and private
// True -> include just private
2021-07-08 14:38:13 +03:00
// False -> include just public
2020-05-21 04:15:30 +03:00
IsPrivate util . OptionalBool
2017-10-27 00:16:13 +03:00
// None -> include collaborative AND non-collaborative
// True -> include just collaborative
2021-07-08 14:38:13 +03:00
// False -> include just non-collaborative
2017-10-27 00:16:13 +03:00
Collaborate util . OptionalBool
// None -> include forks AND non-forks
// True -> include just forks
// False -> include just non-forks
Fork util . OptionalBool
2019-11-11 18:15:29 +03:00
// None -> include templates AND non-templates
// True -> include just templates
// False -> include just non-templates
Template util . OptionalBool
2017-10-27 00:16:13 +03:00
// None -> include mirrors AND non-mirrors
// True -> include just mirrors
// False -> include just non-mirrors
Mirror util . OptionalBool
2020-05-16 23:07:01 +03:00
// None -> include archived AND non-archived
// True -> include just archived
// False -> include just non-archived
Archived util . OptionalBool
2018-09-13 05:33:48 +03:00
// only search topic name
TopicOnly bool
2019-08-25 20:06:36 +03:00
// include description in keyword search
IncludeDescription bool
2020-03-31 10:47:00 +03:00
// None -> include has milestones AND has no milestone
// True -> include just has milestones
// False -> include just has no milestone
HasMilestones util . OptionalBool
2020-09-25 07:09:23 +03:00
// LowerNames represents valid lower names to restrict to
LowerNames [ ] string
2017-02-27 03:45:03 +03:00
}
2020-03-29 08:27:06 +03:00
// SearchRepositoryCondition creates a query condition according search repository options
func SearchRepositoryCondition ( opts * SearchRepoOptions ) builder . Cond {
2021-03-14 21:52:12 +03:00
cond := builder . NewCond ( )
2017-08-24 17:01:03 +03:00
2019-05-15 18:24:39 +03:00
if opts . Private {
2020-01-13 20:33:46 +03:00
if opts . Actor != nil && ! opts . Actor . IsAdmin && opts . Actor . ID != opts . OwnerID {
2019-05-15 18:24:39 +03:00
// OK we're in the context of a User
2020-01-13 20:33:46 +03:00
cond = cond . And ( accessibleRepositoryCondition ( opts . Actor ) )
2019-05-15 18:24:39 +03:00
}
} else {
2021-07-27 01:02:35 +03:00
// Not looking at private organisations and users
2020-05-16 23:07:01 +03:00
// We should be able to see all non-private repositories that
// isn't in a private or limited organisation.
cond = cond . And (
builder . Eq { "is_private" : false } ,
builder . NotIn ( "owner_id" , builder . Select ( "id" ) . From ( "`user`" ) . Where (
2021-07-27 01:02:35 +03:00
builder . Or ( builder . Eq { "visibility" : structs . VisibleTypeLimited } , builder . Eq { "visibility" : structs . VisibleTypePrivate } ) ,
) ) )
2020-05-16 23:07:01 +03:00
}
2020-05-21 04:15:30 +03:00
if opts . IsPrivate != util . OptionalBoolNone {
cond = cond . And ( builder . Eq { "is_private" : opts . IsPrivate . IsTrue ( ) } )
2017-10-17 18:20:22 +03:00
}
2017-08-24 17:01:03 +03:00
2019-11-11 18:15:29 +03:00
if opts . Template != util . OptionalBoolNone {
cond = cond . And ( builder . Eq { "is_template" : opts . Template == util . OptionalBoolTrue } )
}
2019-05-15 18:24:39 +03:00
// Restrict to starred repositories
if opts . StarredByID > 0 {
cond = cond . And ( builder . In ( "id" , builder . Select ( "repo_id" ) . From ( "star" ) . Where ( builder . Eq { "uid" : opts . StarredByID } ) ) )
}
2021-04-15 19:53:57 +03:00
// Restrict to watched repositories
if opts . WatchedByID > 0 {
cond = cond . And ( builder . In ( "id" , builder . Select ( "repo_id" ) . From ( "watch" ) . Where ( builder . Eq { "user_id" : opts . WatchedByID } ) ) )
}
2019-05-15 18:24:39 +03:00
// Restrict repositories to those the OwnerID owns or contributes to as per opts.Collaborate
2017-10-17 18:20:22 +03:00
if opts . OwnerID > 0 {
2021-03-14 21:52:12 +03:00
accessCond := builder . NewCond ( )
2019-05-15 18:24:39 +03:00
if opts . Collaborate != util . OptionalBoolTrue {
accessCond = builder . Eq { "owner_id" : opts . OwnerID }
}
2017-08-24 17:01:03 +03:00
2019-05-15 18:24:39 +03:00
if opts . Collaborate != util . OptionalBoolFalse {
2020-05-18 02:27:54 +03:00
// A Collaboration is:
2019-05-15 18:24:39 +03:00
collaborateCond := builder . And (
2020-05-18 02:27:54 +03:00
// 1. Repository we don't own
builder . Neq { "owner_id" : opts . OwnerID } ,
// 2. But we can see because of:
2019-05-15 18:24:39 +03:00
builder . Or (
2020-05-18 02:27:54 +03:00
// A. We have access
builder . In ( "`repository`.id" ,
builder . Select ( "`access`.repo_id" ) .
From ( "access" ) .
Where ( builder . Eq { "`access`.user_id" : opts . OwnerID } ) ) ,
// B. We are in a team for
builder . In ( "`repository`.id" , builder . Select ( "`team_repo`.repo_id" ) .
2019-05-15 18:24:39 +03:00
From ( "team_repo" ) .
Where ( builder . Eq { "`team_user`.uid" : opts . OwnerID } ) .
2020-05-18 02:27:54 +03:00
Join ( "INNER" , "team_user" , "`team_user`.team_id = `team_repo`.team_id" ) ) ,
// C. Public repositories in private organizations that we are member of
builder . And (
builder . Eq { "`repository`.is_private" : false } ,
builder . In ( "`repository`.owner_id" ,
builder . Select ( "`org_user`.org_id" ) .
From ( "org_user" ) .
Join ( "INNER" , "`user`" , "`user`.id = `org_user`.org_id" ) .
Where ( builder . Eq {
"`org_user`.uid" : opts . OwnerID ,
2021-11-24 12:49:20 +03:00
"`user`.type" : user_model . UserTypeOrganization ,
2020-05-18 02:27:54 +03:00
"`user`.visibility" : structs . VisibleTypePrivate ,
} ) ) ) ) ,
)
2019-05-15 18:24:39 +03:00
if ! opts . Private {
collaborateCond = collaborateCond . And ( builder . Expr ( "owner_id NOT IN (SELECT org_id FROM org_user WHERE org_user.uid = ? AND org_user.is_public = ?)" , opts . OwnerID , false ) )
2017-08-24 17:01:03 +03:00
}
2019-05-15 18:24:39 +03:00
accessCond = accessCond . Or ( collaborateCond )
}
2017-10-27 00:16:13 +03:00
2019-05-15 18:24:39 +03:00
if opts . AllPublic {
2020-01-05 21:48:47 +03:00
accessCond = accessCond . Or ( builder . Eq { "is_private" : false } . And ( builder . In ( "owner_id" , builder . Select ( "`user`.id" ) . From ( "`user`" ) . Where ( builder . Eq { "`user`.visibility" : structs . VisibleTypePublic } ) ) ) )
}
if opts . AllLimited {
accessCond = accessCond . Or ( builder . Eq { "is_private" : false } . And ( builder . In ( "owner_id" , builder . Select ( "`user`.id" ) . From ( "`user`" ) . Where ( builder . Eq { "`user`.visibility" : structs . VisibleTypeLimited } ) ) ) )
2017-10-17 18:20:22 +03:00
}
2019-05-15 18:24:39 +03:00
cond = cond . And ( accessCond )
2017-02-27 03:45:03 +03:00
}
2020-12-27 22:58:03 +03:00
if opts . TeamID > 0 {
cond = cond . And ( builder . In ( "`repository`.id" , builder . Select ( "`team_repo`.repo_id" ) . From ( "team_repo" ) . Where ( builder . Eq { "`team_repo`.team_id" : opts . TeamID } ) ) )
}
2017-10-10 23:37:18 +03:00
if opts . Keyword != "" {
2018-10-18 06:14:28 +03:00
// separate keyword
2021-03-14 21:52:12 +03:00
subQueryCond := builder . NewCond ( )
2018-10-18 06:14:28 +03:00
for _ , v := range strings . Split ( opts . Keyword , "," ) {
2019-08-23 05:37:35 +03:00
if opts . TopicOnly {
subQueryCond = subQueryCond . Or ( builder . Eq { "topic.name" : strings . ToLower ( v ) } )
} else {
subQueryCond = subQueryCond . Or ( builder . Like { "topic.name" , strings . ToLower ( v ) } )
}
2018-10-31 00:48:37 +03:00
}
subQuery := builder . Select ( "repo_topic.repo_id" ) . From ( "repo_topic" ) .
Join ( "INNER" , "topic" , "topic.id = repo_topic.topic_id" ) .
Where ( subQueryCond ) .
GroupBy ( "repo_topic.repo_id" )
2021-03-14 21:52:12 +03:00
keywordCond := builder . In ( "id" , subQuery )
2018-10-31 00:48:37 +03:00
if ! opts . TopicOnly {
2021-03-14 21:52:12 +03:00
likes := builder . NewCond ( )
2018-10-31 00:48:37 +03:00
for _ , v := range strings . Split ( opts . Keyword , "," ) {
likes = likes . Or ( builder . Like { "lower_name" , strings . ToLower ( v ) } )
2019-08-25 20:06:36 +03:00
if opts . IncludeDescription {
likes = likes . Or ( builder . Like { "LOWER(description)" , strings . ToLower ( v ) } )
}
2018-10-18 06:14:28 +03:00
}
2018-10-31 00:48:37 +03:00
keywordCond = keywordCond . Or ( likes )
2018-09-13 05:33:48 +03:00
}
cond = cond . And ( keywordCond )
2017-10-10 23:37:18 +03:00
}
2017-10-27 00:16:13 +03:00
if opts . Fork != util . OptionalBoolNone {
cond = cond . And ( builder . Eq { "is_fork" : opts . Fork == util . OptionalBoolTrue } )
}
if opts . Mirror != util . OptionalBoolNone {
cond = cond . And ( builder . Eq { "is_mirror" : opts . Mirror == util . OptionalBoolTrue } )
}
2020-01-13 20:33:46 +03:00
if opts . Actor != nil && opts . Actor . IsRestricted {
cond = cond . And ( accessibleRepositoryCondition ( opts . Actor ) )
}
2020-03-31 10:47:00 +03:00
2020-05-16 23:07:01 +03:00
if opts . Archived != util . OptionalBoolNone {
cond = cond . And ( builder . Eq { "is_archived" : opts . Archived == util . OptionalBoolTrue } )
}
2020-03-31 10:47:00 +03:00
switch opts . HasMilestones {
case util . OptionalBoolTrue :
cond = cond . And ( builder . Gt { "num_milestones" : 0 } )
case util . OptionalBoolFalse :
cond = cond . And ( builder . Eq { "num_milestones" : 0 } . Or ( builder . IsNull { "num_milestones" } ) )
}
2020-03-29 08:27:06 +03:00
return cond
}
// SearchRepository returns repositories based on search options,
// it returns results in given range and number of total results.
func SearchRepository ( opts * SearchRepoOptions ) ( RepositoryList , int64 , error ) {
cond := SearchRepositoryCondition ( opts )
2020-03-31 10:47:00 +03:00
return SearchRepositoryByCondition ( opts , cond , true )
}
2020-03-29 08:27:06 +03:00
2020-03-31 10:47:00 +03:00
// SearchRepositoryByCondition search repositories by condition
func SearchRepositoryByCondition ( opts * SearchRepoOptions , cond builder . Cond , loadAttributes bool ) ( RepositoryList , int64 , error ) {
2021-03-29 20:12:21 +03:00
sess , count , err := searchRepositoryByCondition ( opts , cond )
if err != nil {
return nil , 0 , err
}
defaultSize := 50
if opts . PageSize > 0 {
defaultSize = opts . PageSize
}
repos := make ( RepositoryList , 0 , defaultSize )
if err := sess . Find ( & repos ) ; err != nil {
return nil , 0 , fmt . Errorf ( "Repo: %v" , err )
}
if opts . PageSize <= 0 {
count = int64 ( len ( repos ) )
}
if loadAttributes {
if err := repos . loadAttributes ( sess ) ; err != nil {
return nil , 0 , fmt . Errorf ( "LoadAttributes: %v" , err )
}
}
return repos , count , nil
}
2021-11-21 18:41:00 +03:00
func searchRepositoryByCondition ( opts * SearchRepoOptions , cond builder . Cond ) ( db . Engine , int64 , error ) {
2020-03-29 08:27:06 +03:00
if opts . Page <= 0 {
opts . Page = 1
}
2020-01-13 20:33:46 +03:00
2017-02-27 03:45:03 +03:00
if len ( opts . OrderBy ) == 0 {
2021-11-24 12:49:20 +03:00
opts . OrderBy = db . SearchOrderByAlphabetically
2017-02-27 03:45:03 +03:00
}
2019-11-11 18:15:29 +03:00
if opts . PriorityOwnerID > 0 {
2021-11-24 12:49:20 +03:00
opts . OrderBy = db . SearchOrderBy ( fmt . Sprintf ( "CASE WHEN owner_id = %d THEN 0 ELSE owner_id END, %s" , opts . PriorityOwnerID , opts . OrderBy ) )
2019-11-11 18:15:29 +03:00
}
2021-11-21 18:41:00 +03:00
sess := db . GetEngine ( db . DefaultContext )
2017-08-23 04:30:54 +03:00
2021-03-29 20:12:21 +03:00
var count int64
if opts . PageSize > 0 {
var err error
count , err = sess .
Where ( cond ) .
2021-12-10 04:27:50 +03:00
Count ( new ( repo_model . Repository ) )
2021-03-29 20:12:21 +03:00
if err != nil {
return nil , 0 , fmt . Errorf ( "Count: %v" , err )
}
2017-10-17 18:20:22 +03:00
}
2021-11-21 18:41:00 +03:00
sess = sess . Where ( cond ) . OrderBy ( opts . OrderBy . String ( ) )
2020-03-31 10:47:00 +03:00
if opts . PageSize > 0 {
2021-11-21 18:41:00 +03:00
sess = sess . Limit ( opts . PageSize , ( opts . Page - 1 ) * opts . PageSize )
2020-03-31 10:47:00 +03:00
}
2021-03-29 20:12:21 +03:00
return sess , count , nil
2017-02-27 03:45:03 +03:00
}
2018-03-16 17:04:33 +03:00
2019-10-28 21:31:55 +03:00
// accessibleRepositoryCondition takes a user a returns a condition for checking if a repository is accessible
2021-11-24 12:49:20 +03:00
func accessibleRepositoryCondition ( user * user_model . User ) builder . Cond {
2021-03-14 21:52:12 +03:00
cond := builder . NewCond ( )
2020-01-13 20:33:46 +03:00
2020-01-28 14:39:37 +03:00
if user == nil || ! user . IsRestricted || user . ID <= 0 {
2020-01-13 20:33:46 +03:00
orgVisibilityLimit := [ ] structs . VisibleType { structs . VisibleTypePrivate }
2020-01-28 14:39:37 +03:00
if user == nil || user . ID <= 0 {
2020-01-13 20:33:46 +03:00
orgVisibilityLimit = append ( orgVisibilityLimit , structs . VisibleTypeLimited )
}
2019-10-28 21:31:55 +03:00
// 1. Be able to see all non-private repositories that either:
2020-01-13 20:33:46 +03:00
cond = cond . Or ( builder . And (
2019-10-28 21:31:55 +03:00
builder . Eq { "`repository`.is_private" : false } ,
2020-03-29 17:31:10 +03:00
// 2. Aren't in an private organisation or limited organisation if we're not logged in
builder . NotIn ( "`repository`.owner_id" , builder . Select ( "id" ) . From ( "`user`" ) . Where (
builder . And (
2021-11-24 12:49:20 +03:00
builder . Eq { "type" : user_model . UserTypeOrganization } ,
2020-03-29 17:31:10 +03:00
builder . In ( "visibility" , orgVisibilityLimit ) ) ,
) ) ) )
2020-01-13 20:33:46 +03:00
}
if user != nil {
2020-05-17 11:22:17 +03:00
cond = cond . Or (
// 2. Be able to see all repositories that we have access to
2019-11-11 18:15:29 +03:00
builder . In ( "`repository`.id" , builder . Select ( "repo_id" ) .
From ( "`access`" ) .
Where ( builder . And (
2020-01-13 20:33:46 +03:00
builder . Eq { "user_id" : user . ID } ,
2021-11-28 14:58:28 +03:00
builder . Gt { "mode" : int ( perm . AccessModeNone ) } ) ) ) ,
2020-05-17 11:22:17 +03:00
// 3. Repositories that we directly own
builder . Eq { "`repository`.owner_id" : user . ID } ,
// 4. Be able to see all repositories that we are in a team
builder . In ( "`repository`.id" , builder . Select ( "`team_repo`.repo_id" ) .
From ( "team_repo" ) .
Where ( builder . Eq { "`team_user`.uid" : user . ID } ) .
Join ( "INNER" , "team_user" , "`team_user`.team_id = `team_repo`.team_id" ) ) ,
// 5. Be able to see all public repos in private organizations that we are an org_user of
builder . And ( builder . Eq { "`repository`.is_private" : false } ,
builder . In ( "`repository`.owner_id" ,
builder . Select ( "`org_user`.org_id" ) .
From ( "org_user" ) .
Where ( builder . Eq { "`org_user`.uid" : user . ID } ) ) ) )
2020-01-13 20:33:46 +03:00
}
return cond
2019-10-28 21:31:55 +03:00
}
2019-08-25 20:06:36 +03: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 ) ( RepositoryList , int64 , error ) {
opts . IncludeDescription = false
return SearchRepository ( opts )
}
2021-03-29 20:12:21 +03:00
// SearchRepositoryIDs takes keyword and part of repository name to search,
// it returns results in given range and number of total results.
func SearchRepositoryIDs ( opts * SearchRepoOptions ) ( [ ] int64 , int64 , error ) {
opts . IncludeDescription = false
cond := SearchRepositoryCondition ( opts )
sess , count , err := searchRepositoryByCondition ( opts , cond )
if err != nil {
return nil , 0 , err
}
defaultSize := 50
if opts . PageSize > 0 {
defaultSize = opts . PageSize
}
ids := make ( [ ] int64 , 0 , defaultSize )
err = sess . Select ( "id" ) . Table ( "repository" ) . Find ( & ids )
if opts . PageSize <= 0 {
count = int64 ( len ( ids ) )
}
return ids , count , err
}
2020-01-13 20:33:46 +03:00
// AccessibleRepoIDsQuery queries accessible repository ids. Usable as a subquery wherever repo ids need to be filtered.
2021-11-24 12:49:20 +03:00
func AccessibleRepoIDsQuery ( user * user_model . User ) * builder . Builder {
2020-01-28 14:39:37 +03:00
// NB: Please note this code needs to still work if user is nil
2020-01-13 20:33:46 +03:00
return builder . Select ( "id" ) . From ( "repository" ) . Where ( accessibleRepositoryCondition ( user ) )
}
2018-03-16 17:04:33 +03:00
2020-01-13 20:33:46 +03:00
// FindUserAccessibleRepoIDs find all accessible repositories' ID by user's id
2021-11-24 12:49:20 +03:00
func FindUserAccessibleRepoIDs ( user * user_model . User ) ( [ ] int64 , error ) {
2018-03-16 17:04:33 +03:00
repoIDs := make ( [ ] int64 , 0 , 10 )
2021-09-23 18:45:36 +03:00
if err := db . GetEngine ( db . DefaultContext ) .
2018-03-16 17:04:33 +03:00
Table ( "repository" ) .
Cols ( "id" ) .
2020-01-13 20:33:46 +03:00
Where ( accessibleRepositoryCondition ( user ) ) .
2018-03-16 17:04:33 +03:00
Find ( & repoIDs ) ; err != nil {
return nil , fmt . Errorf ( "FindUserAccesibleRepoIDs: %v" , err )
}
return repoIDs , nil
}
2021-12-10 04:27:50 +03:00
// GetUserRepositories returns a list of repositories of given user.
func GetUserRepositories ( opts * SearchRepoOptions ) ( [ ] * repo_model . Repository , int64 , error ) {
if len ( opts . OrderBy ) == 0 {
opts . OrderBy = "updated_unix DESC"
}
cond := builder . NewCond ( )
cond = cond . And ( builder . Eq { "owner_id" : opts . Actor . ID } )
if ! opts . Private {
cond = cond . And ( builder . Eq { "is_private" : false } )
}
if opts . LowerNames != nil && len ( opts . LowerNames ) > 0 {
cond = cond . And ( builder . In ( "lower_name" , opts . LowerNames ) )
}
sess := db . GetEngine ( db . DefaultContext )
count , err := sess . Where ( cond ) . Count ( new ( repo_model . Repository ) )
if err != nil {
return nil , 0 , fmt . Errorf ( "Count: %v" , err )
}
sess = sess . Where ( cond ) . OrderBy ( opts . OrderBy . String ( ) )
repos := make ( [ ] * repo_model . Repository , 0 , opts . PageSize )
return repos , count , db . SetSessionPagination ( sess , opts ) . Find ( & repos )
}