1
- import React from "dom-chef" ;
2
1
import browser from "webextension-polyfill" ;
3
2
import alpha from "color-alpha" ;
4
3
import Drop from "tether-drop" ;
@@ -27,15 +26,14 @@ import {
27
26
import { colors } from "../common/constants" ;
28
27
import { createDropdown } from "./utils/dropdown" ;
29
28
import {
30
- getMetadata ,
31
29
getComponents ,
32
30
getCommitReport ,
33
31
getFlags ,
34
32
getBranchReport ,
35
33
} from "../common/fetchers" ;
36
34
import { print } from "src/utils" ;
35
+ import Sentry from "../../common/sentry" ;
37
36
import { isFileUrl } from "../common/utils" ;
38
- import Sentry from '../../common/sentry' ;
39
37
40
38
const globals : {
41
39
coverageReport ?: FileCoverageReport ;
@@ -47,7 +45,7 @@ const globals: {
47
45
prompt ?: HTMLElement ;
48
46
} = { } ;
49
47
50
- init ( )
48
+ init ( ) ;
51
49
52
50
function init ( ) : Promise < void > {
53
51
// this event discovered by "reverse-engineering GitHub"
@@ -63,21 +61,60 @@ function init(): Promise<void> {
63
61
64
62
async function main ( ) : Promise < void > {
65
63
try {
66
- if ( ! isFileUrl ( document . URL ) ) {
64
+ const urlMetadata = getMetadataFromURL ( ) ;
65
+ if ( ! urlMetadata ) {
67
66
print ( "file not detected at current URL" ) ;
68
67
return ;
69
68
}
69
+ globals . coverageButton = createCoverageButton ( ) ;
70
+ process ( urlMetadata ) ;
71
+ } catch ( e ) {
72
+ Sentry . captureException ( e ) ;
73
+ throw e ;
74
+ }
75
+ }
70
76
71
- let metadata : FileMetadata ;
72
- metadata = await getMetadata ( document . URL ) ;
77
+ function getMetadataFromURL ( ) : FileMetadata | null {
78
+ const regexp =
79
+ / \/ (?< owner > .+ ?) \/ (?< repo > .+ ?) \/ b l o b \/ (?< branch > .+ ?) \/ (?< path > .+ ?) $ / ;
80
+ const matches = regexp . exec ( window . location . pathname ) ;
81
+ const groups = matches ?. groups ;
82
+ if ( ! groups ) {
83
+ return null ;
84
+ }
73
85
74
- globals . coverageButton = createCoverageButton ( ) ;
86
+ const branch = groups . branch ;
87
+ const commitMatch = branch . match ( / [ \d a - f ] + / ) ;
75
88
76
- process ( metadata )
77
- } catch ( e ) {
78
- Sentry . captureException ( e )
79
- throw e
89
+ // branch could be a commit sha
90
+ if (
91
+ commitMatch &&
92
+ commitMatch [ 0 ] . length == branch . length &&
93
+ ( groups . branch . length === 40 || branch . length === 7 )
94
+ ) {
95
+ // branch is actually a commit sha
96
+ let commit = branch ;
97
+
98
+ // if it's a short sha, we need to get the full sha
99
+ if ( commit . length === 7 ) {
100
+ const commitLink = document . querySelector (
101
+ `[href^="/${ groups . owner } /${ groups . repo } /tree/${ commit } "]`
102
+ ) ;
103
+ if ( ! commitLink )
104
+ throw new Error ( "Could not find commit link from short sha" ) ;
105
+ const longSha = commitLink
106
+ . getAttribute ( "href" )
107
+ ?. match ( / [ \d a - f ] { 40 } / ) ?. [ 0 ] ;
108
+ if ( ! longSha ) throw new Error ( "Could not get long sha from commit link" ) ;
109
+ commit = longSha ;
110
+ }
111
+
112
+ return {
113
+ ...groups ,
114
+ commit,
115
+ } ;
80
116
}
117
+ return groups ;
81
118
}
82
119
83
120
async function process ( metadata : FileMetadata ) : Promise < void > {
@@ -111,17 +148,16 @@ async function process(metadata: FileMetadata): Promise<void> {
111
148
previousElement : globals . coverageButton ! ,
112
149
selectedOptions : selectedFlags ,
113
150
onClick : handleFlagClick ,
114
- } )
115
- . then ( ( { button, list } ) => {
116
- globals . flagsButton = button ;
117
- globals . flagsDrop = new Drop ( {
118
- target : button ,
119
- content : list ,
120
- classes : "drop-theme-arrows codecov-z1 codecov-bg-white" ,
121
- position : "bottom right" ,
122
- openOn : "click" ,
123
- } ) ;
124
- } )
151
+ } ) . then ( ( { button, list } ) => {
152
+ globals . flagsButton = button ;
153
+ globals . flagsDrop = new Drop ( {
154
+ target : button ,
155
+ content : list ,
156
+ classes : "drop-theme-arrows codecov-z1 codecov-bg-white" ,
157
+ position : "bottom right" ,
158
+ openOn : "click" ,
159
+ } ) ;
160
+ } ) ;
125
161
}
126
162
127
163
const components = await getComponents ( metadata ) ;
@@ -134,7 +170,7 @@ async function process(metadata: FileMetadata): Promise<void> {
134
170
return [ ] ;
135
171
} ) ;
136
172
137
- // TODO: allow setting selected flags for different files at the same time
173
+ // TODO: allow setting selected components for different files at the same time
138
174
if (
139
175
selectedComponents . length > 0 &&
140
176
_ . intersection ( components , selectedComponents ) . length === 0
@@ -151,35 +187,45 @@ async function process(metadata: FileMetadata): Promise<void> {
151
187
previousElement : globals . coverageButton ! ,
152
188
onClick : handleComponentClick ,
153
189
selectedOptions : selectedComponents ,
154
- } )
155
- . then ( ( { button, list } ) => {
156
- globals . componentsButton = button ;
157
- globals . componentsDrop = new Drop ( {
158
- target : button ,
159
- content : list ,
160
- classes : "drop-theme-arrows codecov-z1 codecov-bg-white" ,
161
- position : "bottom right" ,
162
- openOn : "click" ,
163
- } ) ;
164
- } )
190
+ } ) . then ( ( { button, list } ) => {
191
+ globals . componentsButton = button ;
192
+ globals . componentsDrop = new Drop ( {
193
+ target : button ,
194
+ content : list ,
195
+ classes : "drop-theme-arrows codecov-z1 codecov-bg-white" ,
196
+ position : "bottom right" ,
197
+ openOn : "click" ,
198
+ } ) ;
199
+ } ) ;
165
200
}
166
201
202
+ // If commit sha is defined use that, otherwise just branch name
203
+ const getReportFn = metadata . commit ? getCommitReport : getBranchReport ;
204
+
167
205
let coverageReportResponses : Array < FileCoverageReportResponse > ;
168
206
try {
169
- if ( selectedFlags ?. length > 0 ) {
207
+ if ( selectedFlags ?. length > 0 && selectedComponents ?. length > 0 ) {
208
+ coverageReportResponses = await Promise . all (
209
+ selectedFlags . flatMap ( ( flag ) =>
210
+ selectedComponents . map ( ( component ) =>
211
+ getReportFn ( metadata , flag , component )
212
+ )
213
+ )
214
+ ) ;
215
+ } else if ( selectedFlags ?. length > 0 ) {
170
216
coverageReportResponses = await Promise . all (
171
- selectedFlags . map ( ( flag ) => getCommitReport ( metadata , flag , undefined ) )
217
+ selectedFlags . map ( ( flag ) => getReportFn ( metadata , flag , undefined ) )
172
218
) ;
173
219
} else if ( selectedComponents ?. length > 0 ) {
174
220
coverageReportResponses = await Promise . all (
175
221
selectedComponents . map ( ( component ) =>
176
- getCommitReport ( metadata , undefined , component )
222
+ getReportFn ( metadata , undefined , component )
177
223
)
178
224
) ;
179
225
} else {
180
- coverageReportResponses = await Promise . all ( [
181
- await getCommitReport ( metadata , undefined , undefined ) ,
182
- ] ) ;
226
+ coverageReportResponses = [
227
+ await getReportFn ( metadata , undefined , undefined ) ,
228
+ ] ;
183
229
}
184
230
} catch ( e ) {
185
231
updateButton ( `Coverage: ⚠` ) ;
@@ -220,7 +266,6 @@ async function process(metadata: FileMetadata): Promise<void> {
220
266
if ( _ . isEmpty ( coverageReport ) ) {
221
267
updateButton ( `Coverage: N/A` ) ;
222
268
globals . coverageReport = { } ;
223
- await promptPastReport ( metadata ) ;
224
269
return ;
225
270
}
226
271
@@ -232,40 +277,6 @@ async function process(metadata: FileMetadata): Promise<void> {
232
277
animateAndAnnotateLines ( noVirtLineSelector , annotateLine ) ;
233
278
}
234
279
235
- async function promptPastReport ( metadata : FileMetadata ) : Promise < void > {
236
- if ( ! metadata . branch ) {
237
- return ;
238
- }
239
- const response = await getBranchReport ( metadata ) ;
240
- const regexp = / a p p .c o d e c o v .i o \/ g i t h u b \/ .* \/ .* \/ c o m m i t \/ (?< commit > .* ) \/ b l o b / ;
241
- const matches = regexp . exec ( response . commit_file_url ) ;
242
- const commit = matches ?. groups ?. commit ;
243
- if ( ! commit ) {
244
- throw new Error ( "Could not parse commit hash from response for past coverage report" )
245
- }
246
- const link = document . URL . replace (
247
- `blob/${ metadata . branch } ` ,
248
- `blob/${ commit } `
249
- ) ;
250
- globals . prompt = createPrompt (
251
- < span >
252
- Coverage report not available for branch HEAD (
253
- { metadata . commit . substr ( 0 , 7 ) } ), most recent coverage report for this
254
- branch available at commit < a href = { link } > { commit . substr ( 0 , 7 ) } </ a >
255
- </ span >
256
- ) ;
257
- }
258
-
259
- function createPrompt ( child : any ) {
260
- const ref = document . querySelector ( '[data-testid="latest-commit"]' )
261
- ?. parentElement ?. parentElement ;
262
- if ( ! ref ) {
263
- throw new Error ( "Could not find reference element to render prompt" )
264
- }
265
- const prompt = < div className = "codecov-mb2 codecov-mx1" > { child } </ div > ;
266
- return ref . insertAdjacentElement ( "afterend" , prompt ) as HTMLElement ;
267
- }
268
-
269
280
function createCoverageButton ( ) {
270
281
const rawButton = document . querySelector ( '[data-testid="raw-button"]' ) ;
271
282
if ( ! rawButton ) {
0 commit comments