1
1
import { Api , giteaApi , HttpResponse , Repository as GiteaRepository } from 'gitea-js' ;
2
- import { GiteaConfig } from "@sourcebot/schemas/v2/index.type"
3
- import { excludeArchivedRepos , excludeForkedRepos , excludeReposByName , getTokenFromConfig , marshalBool , measure } from './utils.js' ;
4
- import { AppContext , GitRepository } from './types.js' ;
2
+ import { GiteaConnectionConfig } from '@sourcebot/schemas/v3/gitea.type' ;
3
+ import { getTokenFromConfig , measure } from './utils.js' ;
5
4
import fetch from 'cross-fetch' ;
6
5
import { createLogger } from './logger.js' ;
7
- import path from 'path' ;
8
6
import micromatch from 'micromatch' ;
7
+ import { PrismaClient } from '@sourcebot/db' ;
9
8
10
9
const logger = createLogger ( 'Gitea' ) ;
11
10
12
- export const getGiteaReposFromConfig = async ( config : GiteaConfig , orgId : number , ctx : AppContext ) => {
11
+ export const getGiteaReposFromConfig = async ( config : GiteaConnectionConfig , orgId : number , db : PrismaClient ) => {
13
12
// TODO: pass in DB here to fetch secret properly
14
- const token = config . token ? await getTokenFromConfig ( config . token , orgId ) : undefined ;
13
+ const token = config . token ? await getTokenFromConfig ( config . token , orgId , db ) : undefined ;
15
14
16
15
const api = giteaApi ( config . url ?? 'https://gitea.com' , {
17
16
token,
@@ -34,94 +33,107 @@ export const getGiteaReposFromConfig = async (config: GiteaConfig, orgId: number
34
33
const _repos = await getReposOwnedByUsers ( config . users , api ) ;
35
34
allRepos = allRepos . concat ( _repos ) ;
36
35
}
37
-
38
- let repos : GitRepository [ ] = allRepos
39
- . map ( ( repo ) => {
40
- const hostname = config . url ? new URL ( config . url ) . hostname : 'gitea.com' ;
41
- const repoId = `${ hostname } /${ repo . full_name ! } ` ;
42
- const repoPath = path . resolve ( path . join ( ctx . reposPath , `${ repoId } .git` ) ) ;
43
-
44
- const cloneUrl = new URL ( repo . clone_url ! ) ;
45
- if ( token ) {
46
- cloneUrl . username = token ;
47
- }
48
-
49
- return {
50
- vcs : 'git' ,
51
- codeHost : 'gitea' ,
52
- name : repo . full_name ! ,
53
- id : repoId ,
54
- cloneUrl : cloneUrl . toString ( ) ,
55
- path : repoPath ,
56
- isStale : false ,
57
- isFork : repo . fork ! ,
58
- isArchived : ! ! repo . archived ,
59
- gitConfigMetadata : {
60
- 'zoekt.web-url-type' : 'gitea' ,
61
- 'zoekt.web-url' : repo . html_url ! ,
62
- 'zoekt.name' : repoId ,
63
- 'zoekt.archived' : marshalBool ( repo . archived ) ,
64
- 'zoekt.fork' : marshalBool ( repo . fork ! ) ,
65
- 'zoekt.public' : marshalBool ( repo . internal === false && repo . private === false ) ,
66
- } ,
67
- branches : [ ] ,
68
- tags : [ ]
69
- } satisfies GitRepository ;
70
- } ) ;
71
36
72
- if ( config . exclude ) {
73
- if ( ! ! config . exclude . forks ) {
74
- repos = excludeForkedRepos ( repos , logger ) ;
75
- }
76
-
77
- if ( ! ! config . exclude . archived ) {
78
- repos = excludeArchivedRepos ( repos , logger ) ;
79
- }
80
-
81
- if ( config . exclude . repos ) {
82
- repos = excludeReposByName ( repos , config . exclude . repos , logger ) ;
37
+ allRepos = allRepos . filter ( repo => repo . full_name !== undefined ) ;
38
+ allRepos = allRepos . filter ( repo => {
39
+ if ( repo . full_name === undefined ) {
40
+ logger . warn ( `Repository with undefined full_name found: orgId=${ orgId } , repoId=${ repo . id } ` ) ;
41
+ return false ;
83
42
}
84
- }
85
-
86
- logger . debug ( `Found ${ repos . length } total repositories.` ) ;
43
+ return true ;
44
+ } ) ;
87
45
46
+
88
47
if ( config . revisions ) {
89
48
if ( config . revisions . branches ) {
90
49
const branchGlobs = config . revisions . branches ;
91
- repos = await Promise . all (
92
- repos . map ( async ( repo ) => {
93
- const [ owner , name ] = repo . name . split ( '/' ) ;
50
+ allRepos = await Promise . all (
51
+ allRepos . map ( async ( repo ) => {
52
+ const [ owner , name ] = repo . full_name ! . split ( '/' ) ;
94
53
let branches = ( await getBranchesForRepo ( owner , name , api ) ) . map ( branch => branch . name ! ) ;
95
54
branches = micromatch . match ( branches , branchGlobs ) ;
96
-
55
+
97
56
return {
98
57
...repo ,
99
58
branches,
100
59
} ;
101
60
} )
102
61
)
103
62
}
104
-
63
+
105
64
if ( config . revisions . tags ) {
106
65
const tagGlobs = config . revisions . tags ;
107
- repos = await Promise . all (
108
- repos . map ( async ( repo ) => {
109
- const [ owner , name ] = repo . name . split ( '/' ) ;
66
+ allRepos = await Promise . all (
67
+ allRepos . map ( async ( allRepos ) => {
68
+ const [ owner , name ] = allRepos . name ! . split ( '/' ) ;
110
69
let tags = ( await getTagsForRepo ( owner , name , api ) ) . map ( tag => tag . name ! ) ;
111
70
tags = micromatch . match ( tags , tagGlobs ) ;
112
-
71
+
113
72
return {
114
- ...repo ,
73
+ ...allRepos ,
115
74
tags,
116
75
} ;
117
76
} )
118
77
)
119
78
}
120
79
}
80
+
81
+ let repos = allRepos
82
+ . filter ( ( repo ) => {
83
+ const isExcluded = shouldExcludeRepo ( {
84
+ repo,
85
+ exclude : config . exclude ,
86
+ } ) ;
87
+
88
+ return ! isExcluded ;
89
+ } ) ;
121
90
91
+ logger . debug ( `Found ${ repos . length } total repositories.` ) ;
122
92
return repos ;
123
93
}
124
94
95
+ const shouldExcludeRepo = ( {
96
+ repo,
97
+ exclude
98
+ } : {
99
+ repo : GiteaRepository ,
100
+ exclude ?: {
101
+ forks ?: boolean ,
102
+ archived ?: boolean ,
103
+ repos ?: string [ ] ,
104
+ }
105
+ } ) => {
106
+ let reason = '' ;
107
+ const repoName = repo . full_name ! ;
108
+
109
+ const shouldExclude = ( ( ) => {
110
+ if ( ! ! exclude ?. forks && repo . fork ) {
111
+ reason = `\`exclude.forks\` is true` ;
112
+ return true ;
113
+ }
114
+
115
+ if ( ! ! exclude ?. archived && ! ! repo . archived ) {
116
+ reason = `\`exclude.archived\` is true` ;
117
+ return true ;
118
+ }
119
+
120
+ if ( exclude ?. repos ) {
121
+ if ( micromatch . isMatch ( repoName , exclude . repos ) ) {
122
+ reason = `\`exclude.repos\` contains ${ repoName } ` ;
123
+ return true ;
124
+ }
125
+ }
126
+
127
+ return false ;
128
+ } ) ( ) ;
129
+
130
+ if ( shouldExclude ) {
131
+ logger . debug ( `Excluding repo ${ repoName } . Reason: ${ reason } ` ) ;
132
+ }
133
+
134
+ return shouldExclude ;
135
+ }
136
+
125
137
const getTagsForRepo = async < T > ( owner : string , repo : string , api : Api < T > ) => {
126
138
try {
127
139
logger . debug ( `Fetching tags for repo ${ owner } /${ repo } ...` ) ;
0 commit comments