From 0876ba26ec9c09b14b6f3d6ebb149b40054062ef Mon Sep 17 00:00:00 2001 From: Mario Schlicht <196292603+mschlicht-tt@users.noreply.github.com> Date: Mon, 17 Nov 2025 16:33:11 +0100 Subject: [PATCH 1/2] Support for Bitbucket - Rework of host configuration to improve workflow, support different token types, and add better validation feedback - Better error messages for all SCM adapters - minor improvements for UI (e.g. place holder panel on options page if no host configured) --- README.md | 27 +- docs/DeveloperGuide.md | 28 +- docs/images/chrome/add_host_dialog.png | Bin 0 -> 22042 bytes docs/images/chrome/configuration.png | Bin 80310 -> 30873 bytes docs/images/chrome/dialog.png | Bin 28900 -> 30574 bytes docs/images/chrome/dialog_download.png | Bin 40500 -> 17330 bytes src/HostDialog.ts | 396 +++++++++++++ src/options.ts | 551 ++++++++++++------ src/popup.ts | 18 +- src/scm.ts | 749 ------------------------- src/scm/base.ts | 294 ++++++++++ src/scm/bitbucket.ts | 285 ++++++++++ src/scm/github.ts | 210 +++++++ src/scm/gitlab.ts | 281 ++++++++++ src/scm/index.ts | 9 + src/serviceWorker.ts | 105 +++- src/types.ts | 22 +- src/utils.ts | 10 + static/icons/bitbucket.svg | 5 + static/manifest.json | 2 +- static/options.html | 147 ++++- static/popup.html | 8 +- styles/common.scss | 11 +- styles/options.scss | 199 ++++++- styles/popup.scss | 24 + test/scm.download.test.ts | 15 +- test/scm.fetch-logic.test.ts | 157 +++++- test/scm.gitlab-internals.test.ts | 2 +- test/scm.mapping.test.ts | 113 +++- test/scm.methods.test.ts | 24 +- test/scm.pagination.test.ts | 304 ++++++++++ test/scm.test.ts | 9 - test/scm.url.detection.test.ts | 45 +- test/utils.ts | 20 +- 34 files changed, 3031 insertions(+), 1039 deletions(-) create mode 100644 docs/images/chrome/add_host_dialog.png create mode 100644 src/HostDialog.ts delete mode 100644 src/scm.ts create mode 100644 src/scm/base.ts create mode 100644 src/scm/bitbucket.ts create mode 100644 src/scm/github.ts create mode 100644 src/scm/gitlab.ts create mode 100644 src/scm/index.ts create mode 100644 src/utils.ts create mode 100644 static/icons/bitbucket.svg create mode 100644 test/scm.pagination.test.ts delete mode 100644 test/scm.test.ts diff --git a/README.md b/README.md index bcf604d..c6dc160 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,7 @@ Supported SCM platforms: - GitHub - GitLab +- Bitbucket Cloud Supported entry points @@ -81,7 +82,7 @@ You are good to go! You can also pin the extension to the toolbar for easy acces - Open a commit or merge request on your SCM platform. Open the extension popup dialog - Select the correct platform type and add the host -- Go to the options e.g., via click on the cog-wheel icon +- You will be redirected to the options page, where the configuration dialog opens up - Now enter your API token - ⚠️Don\'t give the token all permissions, use fine-grained personal access tokens (if possible) ⚠️ @@ -100,9 +101,25 @@ You are good to go! You can also pin the extension to the toolbar for easy acces 3. Select `Personal access tokens` - `Fine-grained tokens` 4. Select `Generate new token` 5. Set `Repository access` as desired. If you give access to non-public repositories, make sure to grant `Repository permissions` for `Content` (read-only) and `Pull requests` (read-only) - - GitLab 1. Go to `Settings` - `Access tokens` in the relevant group or repository 2. Select `Add new token` 3. Set **Scope** to `read_api`, select a **Role** that is allowed to access code and changes + - GitLab + 1. Go to `Settings` - `Access tokens` in the relevant group or repository + 2. Select `Add new token` + 3. Set **Scope** to `read_api`, select a **Role** that is allowed to access code and changes + - Bitbucket Cloud + - Personal access tokens + 1. Log in to https://id.atlassian.com/manage-profile/security/api-tokens. + 2. Select **Create API token with scopes**. + 3. Select **`read:repository:bitbucket`** and **`read:pullrequest:bitbucket`** scopes. + >*When using a Bitbucket personal access token, you must also provide the email address that belongs to the token in the extension’s configuration dialog.* + - Workspace/Project/Repository access tokens + 1. At https://bitbucket.org, navigate to the workspace, project or repository that you want the token to have access to. + 2. Open the corresponding **workspace**, **project** or **repository settings**. + 3. On the sidebar, under **Security**, select **Access tokens**. + 4. Select **Create access tokens**. + 5. Select **`repository`** and **`pullrequest`** permissions. - Configuration + Add host dialog + Configuration - Save the settings - Go back to the commit page and open the popup again @@ -110,12 +127,12 @@ You are good to go! You can also pin the extension to the toolbar for easy acces - Files that cannot be diffed with the ecu.test Diff-Viewer can still be opened individually for both the old and new versions - Click on a file and click on "Show new" or "Show old" - Configuration Download + Configuration Download - Files supported by the ecu.test Diff-Viewer will open directly in the viewer - Click on a file and click on "Show diff" - Configuration + Configuration - ecu.test Diff-Viewer will be opened diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 589a970..29fb02c 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -51,7 +51,7 @@ Open the ecu.test diff project in your IDE of choice and run the following termi If you want to build the ecu.test diff extension locally for development purposes or for production use, you have access to different scripts: -**Note:** All of these scripts can be found and modified within the './package.json' of the project. +**Note:** All of these scripts can be found and modified within the `./package.json` of the project. **Firefox:** @@ -76,18 +76,9 @@ For integration and testing into your browser, you have to note some differences In **Chrome/Edge** you can select the `./dist` folder inside you browser windows for importing the extension. -In **Firefox**, you can test the extension only in debug-mode. -You have to klick on 'debug add-ons' and can afterward select a .zip file for the import. -You can create the .zip file on your own or use the tool web-ext (from mozilla). - -``` -npm install web-ext -cd ./dist -web-ext build -``` - -This tooling also provides help in the [signing process](https://extensionworkshop.com/documentation/develop/extensions-and-the-add-on-id/) -which is required for the use of add-ons without a debug-mode in firefox. +In **Firefox**, you can test the extension only in debug-mode on the [debugging page](about:debugging#/runtime/this-firefox) (click on 'debug add-ons' when managing addons). +You have to . The [debugging page](about:debugging#/runtime/this-firefox) opens. +Select a typical file in `./dist` folder, e.g. `./dist/manifest.json`. ## Testing / Linting / Code formatting @@ -100,7 +91,7 @@ Select the files you want to format and run the following command: ```bash # check all files -npm prettier:check +npm run prettier:check # fix findings for all files npm run prettier:write . @@ -192,6 +183,15 @@ See the following store-specific information, to handle release specification in - a mozilla developer account is required - any secrets that are necessary for the publication process are set as `Actions secret` - any additional information, see [Submitting an add-on](https://extensionworkshop.com/documentation/publish/submitting-an-add-on/) + - _Note_: + - The tool `web-ext` (from mozilla) will help you in the [signing process](https://extensionworkshop.com/documentation/develop/extensions-and-the-add-on-id/) which is required for the use of add-ons without a debug-mode in firefox. + + For example, install it globally. + ``` + npm install web-ext -g + cd ./dist + web-ext build + ``` - after publishing the application, a review is usually pending and will be published afterward - _Note_: - the add-on may be subject to additional review. diff --git a/docs/images/chrome/add_host_dialog.png b/docs/images/chrome/add_host_dialog.png new file mode 100644 index 0000000000000000000000000000000000000000..96b4c904ac106f061892f1ff829f2af169b19951 GIT binary patch literal 22042 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 B@ZJCb literal 0 HcmV?d00001 diff --git a/docs/images/chrome/configuration.png b/docs/images/chrome/configuration.png index 606d5144b4bbb1a97eca92ce33fa7db8662be5d1..808db6273dde3e38b2a9374eca7ff1e83fe0e7b2 100644 GIT binary patch literal 30873 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
    X*xn1G!IF_~`Y@*GSWwD~omIaa ziy?sr{SJL-6&uu(SC$<8+%oS6a#{ab&{WgsxGZ<+GWERrp8BOem{s`jh4ZK1Tka%D^GQkjqcVCoLDs}` z3Bbv(1-LkFF=a9TlX*if=M?Vsw<6}O0f@o2tXtx9CE($)EqwLNqxl#Mog)JHSF}da zKGx+Yu{okKk|;}ef9DPji`BAu6~NQchBYp!TuMCZ~Ye%e`3cY`rV%HsJ%1> zZPvcJz|F%fpoWbi&(EG}=%->kQut9d&axp+FDdYWgkSes1;OOwd-{v2D= zb7+RX&F@sQ5AfCF%(L?}6k>(a7glqAoZj}Y&cd1l7G$)ALWXpH{C%YQ>0lw?M8yD$W*pIZaaoaTK1EX% zrjt3fSN)Gr7w47|ah@^j6}2TVvrI3wr@sK^eGSFkW<(e2XULK4)*Pc7u2ZfzFf}o1 zN6>1y_iM~GQGeU{MrQyS`Nu%*a?wbIQo-Ox@DKg7LmiYlm`LP=Mj|z2GiNeEtW(He zPDMi~tv`_8*}H3b=lO=uA?HC`$@X0smRP4X7_f-DM{y6M-Yr2jT)qO89>u@X@gFgI z67&JbE`naJ=L@sjLCu;RIPeM!8Q1!LXRJngH$!o^&4pL587o0hS67UtP?{^2YBQ<7 zFa#h8h;SF?NaO}BC8Qed4{V5AJWWV$t>h{w8Al+>BpNix2a5bybH@oFz+|4ijG(h* zJ-2qlYV{1>q2&ISMwy)0eK3j8L**{}=?kcxW7#RkA1y7YySJ=?O6*-14idV4K)78QQ42!D`QiTK>r) zjvdVk1QdT`d9T(14{^mvbIF9>oaAr&$=hOP{eMfluf9r);rKFnnUGAc$^JApVEy5V zTow3A3VdTY|9oRW#7V_XBdvIyQg&eP+?-HQL=u5nK@M!j$*czoMmw3;6eQ^7jX@;o zTlQHVq6^c-5ZuF$oVHSqx&p_Hl|ID>!gdOmpCxxyCEAV_r^)lDYu{ z?9*T7k(m8n7^1Y99vD0aEzJ+YPObnS_4?)?A2s;~Z9o!jg8`$X8lm{Dj9kI@9k2;^ zq0Rbj699BVmB#ng`-;5oY|LgW{WNXq;{iE?mp=hhkzC2saE=xATaW}g-IL?@^J&tU zmDXxZg%@67$FW%#ZoH)OX=2v8zV5#4Xjx9%_eFZar;jBn0YKNo{~le}|3TMBSFN=c zLI1V&1P~km+@x7=Rhi(_VkrM^gCZ_T@SfZRytVa4*Q+KALv=QqRm0vh*$5oxMAuAv zq{T|y=imWfF*=>;;6bzn?<@;gM`}G-BT@Xrs{bLpvxJ8v`M0$B`4YBtoqAMM7X6dw ze)u0x7(;%usfHFq@=3nuloySff$a+2(0AGEew2nia7idwYv_!DK{h_j|K2uz)C?>8 z+g6e^t(Y0hce(}?%>vVjdO3ce2*f5M@aE%*#Scq+j5bSj7B$?b_i)ok%{DMaONW7O z%uA&YmRXSPg+vw!yp9QLbu@Aw-_R;QqF$P9(s^2B8QB0-o8>Vc5xC{}3`dv`*I==h z!`E+_!&psJ?;AmHZZnuKHiwj(6J!I%cjxJ6tbs*PP$a8@^4rCLO`DF0+D~&-!N27y z@||8a4W?RN>v1zvkcF9#StQkBCk{G7~lVnm&r# z=h&>CR|GM7E=w2dxP2z9MomBX5Kd-4+cnbutFhq-8|R0Y5{hinSWjTOoVe(Z6ZTN* z66c4{-^H|TFpn&Ic6>T4-e^%9aA)t;$nH5EsPVFVoP==b@Y6M?cm4j0b|dGR!c6q< zGRDA*4XfHs&Ty$^6`V99-}N4yA1Gc0V3B1-7t43t>Pc zF9)vIYY>?E26r=DP8N(_+mKCf|Bpty|8)W~+I;-~)Hn_7zNMtB+~a*+FMPDfD31jS zA7In2DkAhN;U&qANuJ26<$MzE?WVdZI8k@~B7MmomWat1`aqH-n&Go^j3aWDL<(E` zRp~wyoPiKaf}H5z03fjZV~-3wjgnxgmcae%(e}?H)7Qh@KTgi`(YDPRdk52Z6j?I|Z5W#(q;{1x+iO@O?SEp;lNshHqOit#;_nVeggv z=N}Tw5?%lPX^qxGzomdWQ{?r}1)^657Jd^~2TWR&VSFe8w!_7EA*(D?ETtdtzW@O| B2;Kky literal 28900 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
    <gRCy5 zf4}!cF*1N0mcrxAn%lRPER5J2p|R`U^!dh`7zZO>qhZf^2+?6EiKQWRF*|B8YlenD zT(26RHh3?((;0J)FkJ3W8Ui=?`du6ZX3q#ehK+s<7KQZYV#D}%$RGS%3vA2h|8_Pd z8O{eu6EtjSzMR`HvT_ov7W|Ed7>BZ|Z67CrzjX8N)1L{0sL2#|#B6U4+n-4hJvolx zld$B@SA%-;xaxSw%`(!D2p><~tRdKE5+snPAdS^;7re!GfpWpZr!~F-5sAa3|OF4 zsymQSUiJkho>}mUZaG^7LY;~_4QWg}Zy?Xx9vNT$47$~A=XQP%Tt+H$CEN7bVW?!7 zC*f!L)Grk~7-v)#20KSXC0J%5l;ZaY^{0A5GMW0&A9OtXH6%# z8jPFK_!GlQS2zA2F$3fQPF}j&?HaD#sdn4p=;^8cUQ_Ijt72JXjG9LBTiWa6^TW4M^;4SW2g(=rFV&Q)f6jYC zimd8N8sM;+?fQ7OSu{xf4z%fYT4DC(P!FU>EhOp}9UefLKuNiJB>jCz z-?aH9$WXB;4M|zjCT^oFUL z>9;7plFi^PzglppMpEYo`CZyZEZ!h+$;1z%O31s_F0(6UuX@_wr0mgrH`Jd~)!zq& zQ0sbG(c&S@F6!(EZbX8d#F4j(77O5d0k84y#-+pZ4Y%8T=Bw~_bmv5#s`K!d?Xn@XPgQ#op4xTRa!@A#~ zlk-g060P_Xse{Cl2jNo3p;B8hpprRTV&VO(hiDg;##6JyJ@6+>nI`+D8m(&UddRTB z^%mrLz=m#eqWIq4I8qo40`}>+3}s!B(&_FDA1k+vJ@b)yL4@8f4~y;>Rf{87B#MGQ zP~UVzw>mDMyA0lt-md5NTFMl1f6*s*Jg>WQ1F43%3&nBs)Ctr${{Z;(ASGfMA&p3k z!VuBQF7TbS@n(p-81QvgXkBya=+51(7`mQr@G5<-ZEs>`h{}ICt!7?C05P#hmiV~A zhEz7!O2*-�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 Rv@#(;N=#0)SXkfpzX3Wqw`BkT diff --git a/docs/images/chrome/dialog_download.png b/docs/images/chrome/dialog_download.png index 47b1deb545dbb0287dcf366a071226f2deca21ca..dee421641afa01222c785bd513d8cd8c58685076 100644 GIT binary patch literal 17330 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 literal 40500 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 a;CsSHb_DU!y~; + private messageSpan: HTMLElement; + + constructor() { + this.dialog = document.getElementById('hostDialog') as HTMLDialogElement; + this.title = document.getElementById('hostDialogTitle')!; + this.scmSelect = this.dialog.querySelector('#dlg-scm') as HTMLSelectElement; + this.scmIcon = this.dialog.querySelector( + '#dlg-scm-icon', + ) as HTMLImageElement; + this.hostInput = this.dialog.querySelector('#dlg-host') as HTMLInputElement; + this.emailInput = this.dialog.querySelector( + '#dlg-email', + ) as HTMLInputElement; + this.tokenInput = this.dialog.querySelector( + '#dlg-token', + ) as HTMLInputElement; + this.tokenToggle = this.dialog.querySelector( + '#dlg-token-toggle', + ) as HTMLElement; + this.saveButton = this.dialog.querySelector( + '#dlg-btn-save', + ) as HTMLButtonElement; + this.cancelButton = this.dialog.querySelector( + '#dlg-btn-cancel', + ) as HTMLButtonElement; + this.bitbucketAuth = this.dialog.querySelector( + '#dlg-bitbucket-auth', + ) as HTMLDivElement; + this.emailRow = this.dialog.querySelector( + '#dlg-email-row', + ) as HTMLDivElement; + this.authRadios = this.dialog.querySelectorAll( + 'input[name="dlg-bitbucket-auth-type"]', + ); + this.messageSpan = this.dialog.querySelector('#dlg-message')!; + } + + private setValid( + input: HTMLElement, + value: boolean | null = true, + tooltip = '', + ) { + if (value === null) { + input.classList.remove('valid', 'invalid'); + } else { + input.classList.add(value ? 'valid' : 'invalid'); + input.classList.remove(value ? 'invalid' : 'valid'); + } + input.title = tooltip; + } + + private setError(input: HTMLElement, message: string | null) { + const err = input.parentElement?.querySelector('.error') as HTMLElement; + if (message) { + this.setValid(input, false); + err.textContent = message; + err.style.visibility = 'visible'; + } else { + err.textContent = ''; + err.style.visibility = 'hidden'; + } + } + + private clearError(input: HTMLElement) { + this.setValid(input, null); + const err = input.parentElement?.querySelector('.error') as HTMLElement; + if (err) { + err.textContent = ''; + err.style.visibility = 'hidden'; + } + } + + private attachLiveClear() { + [this.hostInput, this.tokenInput, this.emailInput].forEach((input) => { + input.addEventListener('input', () => this.clearError(input)); + }); + } + + private getAuthType(): AuthType { + const selectedAuth = Array.from(this.authRadios).find( + (r) => r.checked, + )?.value; + return selectedAuth === 'basic' ? AuthType.Basic : AuthType.Bearer; + } + + private validateField(input: HTMLInputElement): boolean { + if (input.id === 'dlg-host') { + const host = normalizeHost(input.value.trim()); + const scm = this.scmSelect.value as Scm; + if (!host) { + this.setError(input, 'Please enter a host.'); + return false; + } + if (scm === 'bitbucket') { + if ( + !BITBUCKET_BASIC_REGEX.test(host) && + !BITBUCKET_BEARER_REGEX.test(host) + ) { + this.setError(input, 'Invalid host name.'); + return false; + } + const authType = this.getAuthType(); + if (authType === AuthType.Basic) { + // only allow bitbucket.org + if (!BITBUCKET_BASIC_REGEX.test(host)) { + this.setError( + input, + 'For personal access tokens, please use bitbucket.org as host.', + ); + return false; + } + } else { + // require workspace or repository + if (!BITBUCKET_BEARER_REGEX.test(host)) { + this.setError( + input, + 'Please specify a valid workspace or repository.', + ); + return false; + } + } + this.setError(input, null); + this.setValid(input, null); + return true; + } + if (IP_REGEX.test(host)) { + this.setValid(input, null); + return true; + } + if (!HOSTNAME_REGEX.test(host)) { + this.setError(input, 'Invalid host name.'); + return false; + } + this.setValid(input, null); + return true; + } + if (input.id === 'dlg-token') { + const token = input.value.trim(); + if (!token) { + this.setError(input, 'Please enter a token.'); + return false; + } + this.setValid(input, null); + return true; + } + if (input.id === 'dlg-email') { + const email = input.value.trim(); + const scm = this.scmSelect.value as Scm; + const authType = this.getAuthType(); + if (scm !== 'bitbucket' || authType !== AuthType.Basic) { + this.clearError(input); + return true; + } + if (!email) { + this.setError(input, 'Please enter your email address.'); + return false; + } + const simpleEmailRegex = /.+@.+\..+/; + if (!simpleEmailRegex.test(email)) { + this.setError(input, 'Please enter a valid email address.'); + return false; + } + this.setError(input, null); + return true; + } + this.setValid(input, null); + return true; + } + + private validateDialog(): boolean { + const fields: HTMLInputElement[] = [ + this.hostInput, + this.tokenInput, + this.emailInput, + ]; + let allValid = true; + for (const field of fields) { + const ok = this.validateField(field); + if (!ok) allValid = false; + } + return allValid; + } + + private updateDialogVisibility() { + const isBitbucket = this.scmSelect.value === 'bitbucket'; + const dlgHostHint = document.getElementById('dlg-host-hint'); + if (!isBitbucket) { + this.bitbucketAuth.classList.add('hidden'); + this.emailRow.classList.add('hidden'); + dlgHostHint.style.display = 'none'; + return; + } + this.bitbucketAuth.classList.remove('hidden'); + dlgHostHint.style.display = 'block'; + const selectedAuth = Array.from(this.authRadios).find( + (r) => r.checked, + )?.value; + if (selectedAuth === AuthType.Basic) { + this.emailRow.classList.remove('hidden'); + } else { + this.emailRow.classList.add('hidden'); + } + } + + private updateControls() { + const linkWrapper = document.getElementById('dlg-token-learnmore')!; + const link = linkWrapper.querySelector('a')!; + const scm = this.scmSelect.value as Scm; + let url = '#'; + let placeholder = ''; + if (scm === 'github') { + url = TOKEN_DOC_URLS.github; + placeholder = 'e.g. github.com'; + } else if (scm === 'gitlab') { + url = TOKEN_DOC_URLS.gitlab; + placeholder = 'e.g. gitlab.com'; + } else if (scm === 'bitbucket') { + url = TOKEN_DOC_URLS.bitbucket; + placeholder = 'e.g. bitbucket.org'; + } + link.href = url; + this.hostInput.placeholder = placeholder; + } + + private buildScmHost(): ScmHost { + const scm = this.scmSelect.value as Scm; + const host = normalizeHost(this.hostInput.value.trim()); + let token = this.tokenInput.value.trim(); + const email = this.emailInput.value.trim(); + const authType = this.getAuthType(); + if (scm === 'bitbucket' && authType === AuthType.Basic) { + token = `${email}:${token}`; + } + return { + scm, + host, + token, + authType: scm === 'bitbucket' ? authType : undefined, + }; + } + + private async checkHostConnection(scmHost: ScmHost): Promise { + const ok = (await browser.runtime.sendMessage({ + action: Action.checkConnection, + option: { scmHost }, + } as ServiceWorkerRequest)) as boolean; + this.setError( + this.tokenInput, + ok ? '' : 'Authentication failed for this host.', + ); + return ok; + } + + public open(prefill?: ScmHost, editRowId?: string, edit = false) { + this.reset(); + if (prefill) { + this.title.textContent = edit ? 'Edit host' : 'Add host'; + this.scmSelect.value = prefill.scm; + this.scmIcon.src = `icons/${prefill.scm}.svg`; + this.hostInput.value = prefill.host; + let tokenValue = prefill.token ?? ''; + let emailValue = ''; + if (prefill.scm === 'bitbucket') { + const authType = prefill.authType || AuthType.Basic; + this.authRadios.forEach((radio) => { + radio.checked = radio.value === authType; + }); + + if (authType === AuthType.Basic) { + if (tokenValue.includes(':')) { + const [emailPart, ...rest] = tokenValue.split(':'); + emailValue = emailPart; + tokenValue = rest.join(':'); + } else { + emailValue = ''; + } + } + } + this.tokenInput.value = tokenValue; + this.emailInput.value = emailValue; + (this.saveButton as HTMLButtonElement).dataset.editRow = editRowId ?? ''; + } else { + this.title.textContent = 'Add host'; + delete (this.saveButton as HTMLButtonElement).dataset.editRow; + } + this.updateDialogVisibility(); + this.updateControls(); + this.dialog.showModal(); + } + + private reset() { + this.scmSelect.value = 'github'; + this.scmIcon.src = `icons/github.svg`; + this.hostInput.value = ''; + this.emailInput.value = ''; + this.tokenInput.value = ''; + this.authRadios.forEach((radio) => { + radio.checked = radio.value === AuthType.Basic; + }); + this.updateDialogVisibility(); + [this.scmSelect, this.hostInput, this.emailInput, this.tokenInput].forEach( + (elem) => { + this.clearError(elem); + }, + ); + } + + private async onDialogSave( + event: Event, + onSaveCallback: (host: ScmHost, editRowId?: string) => Promise, + ) { + event.preventDefault(); + if (!this.validateDialog()) return; + const scmHost = this.buildScmHost(); + const ok = await this.checkHostConnection(scmHost); + if (!ok) return; + const editRowId = (this.saveButton as HTMLButtonElement).dataset.editRow as + | string + | undefined; + await onSaveCallback(scmHost, editRowId); + this.dialog.close(); + } + + public registerEvents( + onSaveCallback: (host: ScmHost, editRowId?: string) => Promise, + ) { + this.cancelButton.addEventListener('click', () => this.dialog.close()); + this.tokenToggle.addEventListener('click', () => { + if (this.tokenInput.type === 'password') { + this.tokenInput.type = 'text'; + this.tokenToggle.textContent = 'visibility_off'; + } else { + this.tokenInput.type = 'password'; + this.tokenToggle.textContent = 'visibility'; + } + }); + this.scmSelect.addEventListener('change', () => { + this.scmIcon.src = `icons/${this.scmSelect.value}.svg`; + this.updateDialogVisibility(); + this.updateControls(); + }); + this.authRadios.forEach((radio) => { + radio.addEventListener('change', () => { + this.updateDialogVisibility(); + this.clearError(this.hostInput); + }); + }); + this.attachLiveClear(); + this.hostInput.addEventListener('blur', () => + this.validateField(this.hostInput), + ); + this.tokenInput.addEventListener('blur', () => + this.validateField(this.tokenInput), + ); + this.emailInput.addEventListener('blur', () => + this.validateField(this.emailInput), + ); + this.saveButton.addEventListener('click', (event) => + this.onDialogSave(event, onSaveCallback), + ); + } +} diff --git a/src/options.ts b/src/options.ts index 152a003..a2fe5f8 100644 --- a/src/options.ts +++ b/src/options.ts @@ -1,6 +1,8 @@ import '../styles/options.scss'; import browser from 'webextension-polyfill'; -import { Action, ScmHost, ServiceWorkerRequest } from './types'; +import { Action, AuthType, ScmHost, ServiceWorkerRequest } from './types'; +import { HostDialog } from './HostDialog'; +import { normalizeHost } from './utils'; const IP_REGEX = /^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$/; @@ -8,240 +10,435 @@ const IP_REGEX = const HOSTNAME_REGEX = /^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9-]*[A-Za-z0-9])$/; -function setMessage(type: 'success' | 'error', message: string) { - const elem = document.getElementById('message'); +const BITBUCKET_BEARER_REGEX = + /^bitbucket\.org\/[A-Za-z0-9._-]+(?:\/[A-Za-z0-9._-]+)?$/i; +const BITBUCKET_BASIC_REGEX = /^bitbucket\.org$/i; + +type Scm = 'github' | 'gitlab' | 'bitbucket'; + +const SCM_DISPLAY_NAME: Record = { + github: 'Github', + gitlab: 'Gitlab', + bitbucket: 'Bitbucket Cloud', +}; +function setMessage( + type: 'success' | 'error', + message: string, + dialog: boolean = false, +) { + const elem = document.getElementById(dialog ? 'dlg-message' : 'message'); elem.textContent = message; elem.classList.add(type); elem.classList.remove(type == 'success' ? 'error' : 'success'); } -function setValid( - idOrElem: string | HTMLElement, - value: boolean | null = true, - tooltip = '', -) { - const elem = - typeof idOrElem == 'string' ? document.getElementById(idOrElem) : idOrElem; - if (value === null) { - elem.classList.remove('valid', 'invalid'); - } else { - elem.classList.add(value ? 'valid' : 'invalid'); - elem.classList.remove(value ? 'invalid' : 'valid'); - } - elem.title = tooltip; -} - let rowIdCounter = 0; -function getHostTableRowElement( - rowId: string, - elemId: string, -): HTMLElement | null { - return document.getElementById(rowId).querySelector(`[id=${elemId}]`); +function getHostsTableBody(): HTMLTableSectionElement { + return document.getElementById('hosts').querySelector('tbody'); } -async function checkHost(scmHost: ScmHost, rowId: string): Promise { - const hostElem = getHostTableRowElement(rowId, 'host'); - const tokenElem = getHostTableRowElement(rowId, 'token'); - setValid(hostElem, null); - setValid(tokenElem, null); - - let valid = true; - if ( - !IP_REGEX.test(scmHost.host.trim()) && - !HOSTNAME_REGEX.test(scmHost.host.trim()) - ) { - valid = false; - setValid(hostElem, false, 'Not a valid host name. Example: "github.com"'); - } else { - setValid(hostElem); - } - if (!scmHost.token.trim()) { - valid = false; - setValid(tokenElem, false, 'Please enter a token.'); - } +function getHostRows(): HTMLTableRowElement[] { + return Array.from(getHostsTableBody().children) as HTMLTableRowElement[]; +} - if (valid) { - valid = await browser.runtime.sendMessage({ - action: Action.checkConnection, - option: { - scmHost, - }, - } as ServiceWorkerRequest); +function getRowScmHost(row: HTMLTableRowElement): ScmHost { + const scm = row.dataset.scm as Scm; + const token = row.dataset.token ?? ''; + const hostSpan = row.querySelector('.host-text') as HTMLElement | null; + const host = hostSpan?.textContent ?? ''; + const authTypeRaw = row.dataset.authType; + const authType = + scm === 'bitbucket' && + (authTypeRaw === AuthType.Basic || authTypeRaw === AuthType.Bearer) + ? authTypeRaw + : undefined; - setValid(tokenElem, valid, valid ? null : 'Authentification failed!'); - } - return valid; + return { scm, host, token, authType }; } -function getHostsTableBody(): HTMLTableSectionElement { - return document.getElementById('hosts').querySelector('tbody'); -} -function onAddHost(): void { - const body = getHostsTableBody(); - createHostRow(body, { - host: '', - scm: 'github', - token: null, - }); -} -function onRemoveHost(rowId: string): void { - document.getElementById(rowId).remove(); +function getBitbucketScopeLevel(host: string): number { + const parts = host.split('/').filter(Boolean); + if (parts.length <= 1) return 0; + if (parts.length === 2) return 1; + return 2; } -function buildScmHosts(): ScmHost[] { - const rows = getHostsTableBody().childNodes; - const data: ScmHost[] = []; - rows.forEach((row: HTMLTableRowElement) => { - data.push({ - scm: (row.childNodes[0].childNodes[1] as HTMLInputElement).value as - | 'github' - | 'gitlab', - host: (row.childNodes[1].childNodes[0] as HTMLInputElement).value, - token: (row.childNodes[2].childNodes[0] as HTMLInputElement).value, - }); - }); - return data; +function hostPriorityKey(h: ScmHost): { + scmOrder: number; + scopeLevel: number; + hostLen: number; + host: string; +} { + const scm = h.scm as Scm; + const normHost = normalizeHost(h.host); + + // keep platforms grouped + const scmOrderMap: Record = { + bitbucket: 0, + github: 1, + gitlab: 2, + }; + + const scopeLevel = scm === 'bitbucket' ? getBitbucketScopeLevel(normHost) : 0; + + return { + scmOrder: scmOrderMap[scm], + scopeLevel, + hostLen: normHost.length, + host: normHost, + }; } -async function onCheckHosts(): Promise { - const data = buildScmHosts(); - data.forEach((scmHost, index) => { - const hostRow = getHostsTableBody().childNodes[ - index - ] as HTMLTableRowElement; - checkHost(scmHost, hostRow.id); + +function sortHostsByPriority(hosts: ScmHost[]): ScmHost[] { + return [...hosts].sort((a, b) => { + const ka = hostPriorityKey(a); + const kb = hostPriorityKey(b); + + if (ka.scmOrder !== kb.scmOrder) return ka.scmOrder - kb.scmOrder; + if (ka.scopeLevel !== kb.scopeLevel) return kb.scopeLevel - ka.scopeLevel; + if (ka.hostLen !== kb.hostLen) return kb.hostLen - ka.hostLen; + return ka.host.localeCompare(kb.host); }); } -// Function to save options -async function onSave(): Promise { - await browser.runtime.sendMessage({ - action: Action.saveHosts, - option: { hosts: buildScmHosts() }, - } as ServiceWorkerRequest); - - setMessage('success', 'Options saved!'); - setTimeout(() => setMessage('success', ''), 2000); +function renderHosts(hosts: ScmHost[]) { + const body = getHostsTableBody(); + const table = document.getElementById('hosts'); + const placeholder = document.getElementById('hosts-empty-placeholder'); + body.innerHTML = ''; + rowIdCounter = 0; + if (hosts.length === 0) { + table.style.display = 'none'; + if (placeholder) placeholder.style.display = ''; + } else { + table.style.display = ''; + if (placeholder) placeholder.style.display = 'none'; + hosts.forEach((h) => createHostRow(body, h)); + } } -function createHostRow(body: HTMLTableSectionElement, hostInfo: ScmHost) { +function createHostRow( + body: HTMLTableSectionElement, + hostInfo: ScmHost, +): HTMLTableRowElement { const row = body.insertRow(); const rowId = 'hostrow_' + rowIdCounter.toString(); row.id = rowId; rowIdCounter += 1; - // scm platform + const platformCell = row.insertCell(); const img = document.createElement('img'); - if (hostInfo.scm) img.src = `icons/${hostInfo.scm}.svg`; + img.src = `icons/${hostInfo.scm}.svg`; img.width = 16; img.style.paddingRight = '2px'; img.style.verticalAlign = 'middle'; - const scmSelection = document.createElement('select'); - scmSelection.id = `scm`; - scmSelection.addEventListener('input', () => { - img.src = `icons/${scmSelection.value}.svg`; - }); - const option1 = document.createElement('option'); - option1.value = 'github'; - option1.text = 'Github'; - const option2 = document.createElement('option'); - option2.value = 'gitlab'; - option2.text = 'Gitlab'; - - scmSelection.append(option1, option2); - const imgCell = row.insertCell(); - imgCell.append(img, scmSelection); - scmSelection.value = hostInfo.scm; - imgCell.style.whiteSpace = 'nowrap'; - - // host + const label = document.createElement('span'); + label.textContent = + SCM_DISPLAY_NAME[hostInfo.scm as keyof typeof SCM_DISPLAY_NAME]; + label.style.marginLeft = '4px'; + platformCell.append(img, label); + platformCell.style.whiteSpace = 'nowrap'; + const hostCell = row.insertCell(); - const hostInput = document.createElement('input'); - hostInput.type = 'text'; - hostInput.classList.add('hostinput'); - hostInput.id = `host`; - hostInput.value = hostInfo.host; - hostCell.append(hostInput); - - // token - const tokenCell = row.insertCell(); - tokenCell.style.whiteSpace = 'nowrap'; - const tokenInput = document.createElement('input'); - tokenInput.type = 'password'; - tokenInput.classList.add('tokeninput'); - tokenInput.id = `token`; - - tokenInput.value = hostInfo.token; - - const imgShowPw = document.createElement('span'); - imgShowPw.classList.add('material-symbols-outlined', 'clickable'); - imgShowPw.style.verticalAlign = 'text-top'; - imgShowPw.textContent = 'visibility'; - - imgShowPw.style.paddingLeft = '4px'; - imgShowPw.addEventListener('click', () => { - if (imgShowPw.textContent === 'visibility') { - imgShowPw.textContent = 'visibility_off'; - tokenInput.type = 'text'; - } else { - imgShowPw.textContent = 'visibility'; - tokenInput.type = 'password'; - } - }); - tokenCell.append(tokenInput, imgShowPw); + const hostSpan = document.createElement('span'); + hostSpan.classList.add('host-text'); + hostSpan.textContent = hostInfo.host; + hostCell.append(hostSpan); - // actions const actionCell = row.insertCell(); - const delImg = document.createElement('span'); - delImg.classList.add('material-symbols-outlined', 'clickable'); - delImg.style.verticalAlign = 'text-top'; - delImg.textContent = 'delete'; - delImg.addEventListener('click', () => onRemoveHost(rowId)); - actionCell.append(delImg); + const editIcon = document.createElement('span'); + editIcon.classList.add('material-symbols-outlined', 'clickable'); + editIcon.style.verticalAlign = 'text-top'; + editIcon.textContent = 'edit'; + editIcon.title = 'Edit'; + editIcon.addEventListener('click', () => { + const row = document.getElementById(rowId) as HTMLTableRowElement | null; + if (!row) return; + hostDialog.open(getRowScmHost(row), rowId, true); + }); + + actionCell.append(editIcon); + const delIcon = document.createElement('span'); + delIcon.classList.add('material-symbols-outlined', 'clickable'); + delIcon.style.verticalAlign = 'text-top'; + delIcon.textContent = 'delete'; + delIcon.title = 'Remove'; + delIcon.addEventListener('click', () => onRemoveHost(rowId)); + actionCell.append(delIcon); + + row.dataset.token = hostInfo.token ?? ''; + row.dataset.scm = hostInfo.scm; + row.dataset.authType = + hostInfo.scm === 'bitbucket' && hostInfo.authType ? hostInfo.authType : ''; - row.append(imgCell, hostCell, tokenCell, actionCell); + return row; +} + +function buildScmHosts(): ScmHost[] { + return getHostRows().map(getRowScmHost); } async function updateHosts() { const hosts: ScmHost[] = await browser.runtime.sendMessage({ action: Action.getHosts, } as ServiceWorkerRequest); + renderHosts(sortHostsByPriority(hosts)); +} + +// Function to save settings +async function onSave(): Promise { + const sorted = sortHostsByPriority(buildScmHosts()); + await browser.runtime.sendMessage({ + action: Action.saveHosts, + option: { hosts: sorted }, + } as ServiceWorkerRequest); - const body = getHostsTableBody(); - body.innerHTML = ''; - hosts.forEach((scmHost) => { - createHostRow(body, scmHost); + setMessage('success', 'Settings saved!'); + setTimeout(() => setMessage('success', ''), 2000); +} + +async function onRemoveHost(rowId: string): Promise { + const row = document.getElementById(rowId); + if (!row) return; + const confirmed = window.confirm( + 'Are you sure you want to remove this host?', + ); + + if (!confirmed) return; + row.remove(); + await onSave(); + await updateHosts(); +} + +type FieldErrorMap = Partial>; + +interface ValidationResult { + valid: boolean; + reason?: string; + fieldErrors?: FieldErrorMap; +} + +async function validateHostRow( + row: HTMLTableRowElement, +): Promise { + const scmHost = getRowScmHost(row); + row.classList.remove('valid-host', 'invalid-host'); + + const rawHost = scmHost.host ?? ''; + const normHost = normalizeHost(rawHost); + const token = (scmHost.token ?? '').trim(); + + const fieldErrors: FieldErrorMap = {}; + let valid = true; + let reason: string | undefined; + + if (!normHost) { + valid = false; + reason = 'Host is missing.'; + fieldErrors.host = reason; + } else if (scmHost.scm === 'bitbucket') { + if ( + !BITBUCKET_BASIC_REGEX.test(normHost) && + !BITBUCKET_BEARER_REGEX.test(normHost) + ) { + valid = false; + reason = 'Invalid host format.'; + fieldErrors.host = reason; + } + } else { + if (!IP_REGEX.test(normHost) && !HOSTNAME_REGEX.test(normHost)) { + valid = false; + reason = 'Invalid host format.'; + fieldErrors.host = reason; + } + } + + if (!token) { + valid = false; + reason = 'Access token is missing.'; + fieldErrors.token = reason; + } + + if (valid) { + try { + const ok = (await browser.runtime.sendMessage({ + action: Action.checkConnection, + option: { scmHost: { ...scmHost, host: normHost } }, + } as ServiceWorkerRequest)) as boolean; + + if (!ok) { + valid = false; + reason = 'Authentication failed.'; + fieldErrors.token = reason; + } + } catch (e) { + valid = false; + reason = 'Connection error.'; + fieldErrors.token = reason; + console.error('Error while checking host', scmHost.host, e); + } + } + row.classList.add(valid ? 'valid-host' : 'invalid-host'); + row.title = reason ?? ''; + + delete row.dataset.hostError; + delete row.dataset.tokenError; + + if (fieldErrors.host) row.dataset.hostError = fieldErrors.host; + if (fieldErrors.token) row.dataset.tokenError = fieldErrors.token; + + return { valid, reason, fieldErrors }; +} + +async function onCheckHosts(): Promise { + const rows = getHostRows(); + if (rows.length === 0) { + setMessage('error', 'There are no configured hosts.'); + return; + } + + rows.forEach((row) => { + row.classList.remove('valid-host', 'invalid-host'); + row.title = ''; }); + + const results = await Promise.all( + rows.map(async (row) => { + const result = await validateHostRow(row); + const hostText = getRowScmHost(row).host || '(unknown)'; + return { row, host: hostText, ...result }; + }), + ); + + const failures = results.filter((r) => !r.valid); + if (failures.length === 0) { + setMessage('success', 'All hosts passed validation.'); + return; + } else { + setMessage( + 'error', + 'Validation failed for one or more hosts. See the tooltips in the table for details.', + ); + } } -async function addPendingHosts() { - // detect whether a host was added - let hosts: ScmHost[] = await browser.runtime.sendMessage({ + +async function addPendingHosts(): Promise { + const allHosts: ScmHost[] = await browser.runtime.sendMessage({ action: Action.getHosts, } as ServiceWorkerRequest); - const visibleHosts = buildScmHosts().map((host) => host.host); - hosts = hosts.filter((scmHost) => !visibleHosts.includes(scmHost.host)); - if (hosts.length == 0) return; + + const visible = new Set(); + getHostRows().forEach((row) => { + const { scm, host } = getRowScmHost(row); + visible.add(`${scm}|${normalizeHost(host)}`); + }); + const body = getHostsTableBody(); - hosts.forEach((scmHost) => { - createHostRow(body, scmHost); + allHosts.forEach((h) => { + const key = `${h.scm}|${normalizeHost(h.host)}`; + if (!visible.has(key)) createHostRow(body, h); }); } + +type PendingHost = { + scm: Scm; + host: string; +}; + +async function openPendingHostDialog(): Promise { + const { pendingHost } = (await browser.storage.local.get('pendingHost')) as { + pendingHost?: PendingHost; + }; + + if (!pendingHost) return; + + try { + const targetScm = pendingHost.scm; + const targetHostNormalized = normalizeHost(pendingHost.host); + + const hosts: ScmHost[] = await browser.runtime.sendMessage({ + action: Action.getHosts, + } as ServiceWorkerRequest); + + const match = hosts.find( + (h) => + h.scm === targetScm && normalizeHost(h.host) === targetHostNormalized, + ); + + if (!match) return; + + await updateHosts(); + + const row = getHostRows().find((r) => { + const rh = getRowScmHost(r); + return ( + rh.scm === targetScm && normalizeHost(rh.host) === targetHostNormalized + ); + }); + + hostDialog.open(match, row?.id); + } finally { + await browser.storage.local.remove('pendingHost'); + } +} + +const hostDialog = new HostDialog(); + +hostDialog.registerEvents(async (scmHost, editRowId) => { + const body = getHostsTableBody(); + if (editRowId) { + const row = document.getElementById(editRowId) as HTMLTableRowElement; + if (!row) { + console.error('Edit row not found: ', editRowId); + return; + } + const platformCell = row.cells[0]; + const img = platformCell.querySelector('img') as HTMLImageElement; + const label = platformCell.querySelector('span:last-child') as HTMLElement; + img.src = `icons/${scmHost.scm}.svg`; + label.textContent = + SCM_DISPLAY_NAME[scmHost.scm as keyof typeof SCM_DISPLAY_NAME]; + const hostSpan = row.querySelector('.host-text') as HTMLElement; + hostSpan.textContent = scmHost.host; + row.dataset.token = scmHost.token ?? ''; + row.dataset.scm = scmHost.scm; + row.dataset.authType = + scmHost.scm === 'bitbucket' && scmHost.authType ? scmHost.authType : ''; + row.classList.remove('invalid-host'); + row.classList.add('valid-host'); + } else { + const row = createHostRow(body, scmHost); + row.classList.remove('invalid-host'); + row.classList.add('valid-host'); + } + await onSave(); + await updateHosts(); +}); + async function initUi() { - // Event listener for saveAccessTokenButton click - const saveAccessTokenButton = document.getElementById('saveOptions'); - saveAccessTokenButton.addEventListener('click', onSave); const addHostButton = document.getElementById('addhost'); - addHostButton.addEventListener('click', onAddHost); + addHostButton.addEventListener('click', () => hostDialog.open()); + + const addHostEmptyButton = document.getElementById('addhost-empty'); + if (addHostEmptyButton) { + addHostEmptyButton.addEventListener('click', () => hostDialog.open()); + } const checkHostButton = document.getElementById('checkhosts'); checkHostButton.addEventListener('click', onCheckHosts); document.addEventListener('visibilitychange', async () => { - if (!document.hidden) addPendingHosts(); + if (!document.hidden) { + await addPendingHosts(); + const { pendingHost } = await browser.storage.local.get('pendingHost'); + if (pendingHost) await openPendingHostDialog(); + } }); // init data - updateHosts(); + await updateHosts(); + await openPendingHostDialog(); } initUi(); diff --git a/src/popup.ts b/src/popup.ts index e82177d..1c58472 100644 --- a/src/popup.ts +++ b/src/popup.ts @@ -63,6 +63,12 @@ async function fetchModifiedFiles( function showAddHost(host: string) { showElement('addhost'); document.getElementById('addhost_host').textContent = host; + const scmSelect = document.getElementById('addhost_scm') as HTMLSelectElement; + let scm = 'github'; + if (host == 'bitbucket.org') { + scm = 'bitbucket'; + } + scmSelect.value = scm; } async function onAddHost() { const scmSelect = document.getElementById('addhost_scm') as HTMLSelectElement; @@ -71,7 +77,10 @@ async function onAddHost() { action: Action.addHost, option: { hostInfo: { scm: scmSelect.value, host } }, } as ServiceWorkerRequest); - initData(); + await browser.storage.local.set({ + pendingHost: { scm: scmSelect.value, host }, + }); + await browser.runtime.openOptionsPage(); } // Function to display total changes @@ -318,11 +327,14 @@ async function initData() { return; } showElement('addhost', false); - - displayModifiedFiles(await fetchModifiedFiles(hostInfo)); + showElement('loader', true); + const files = await fetchModifiedFiles(hostInfo); + displayModifiedFiles(files); } catch (error) { console.error(error); displayErrorMessage(error); + } finally { + showElement('loader', false); } } diff --git a/src/scm.ts b/src/scm.ts deleted file mode 100644 index 052dba9..0000000 --- a/src/scm.ts +++ /dev/null @@ -1,749 +0,0 @@ -import browser from 'webextension-polyfill'; -import { HostInfo, ModifiedFile, SUPPORTED_FILES } from './types.ts'; -import { Buffer } from 'buffer'; - -// types for responses objects of github and gitlab and generalized types for common usage -type CommitInfo = { - owner: string; - repo: string; - commitHash: string; -}; - -type PullInfo = { - owner: string; - repo: string; - pullNumber: string; -}; - -type GithubCommitInfo = { - files: GithubChangeFile[]; - parents: { sha: string }[]; - sha: string; -}; - -type GithubPullInfo = { - info: { base: { sha: string }; head: { sha: string } }; - files: GithubChangeFile[]; -}; - -type CommonChange = { - filename: string; - filenameOld: string; - new: boolean; - renamed: boolean; - deleted: boolean; - additions: number; - deletions: number; -}; - -type GithubChangeFile = { - additions: number; - deletions: number; - changes: number; - filename: string; - previous_filename?: string; - patch: string; - sha: string; - status: 'added' | 'renamed' | 'removed'; - blob_url: string; - raw_url: string; - content_url: string; -}; - -type GitlabChange = { - diff: string; - new_path: string; - old_path: string; - a_mode: string; - b_mode: string; - new_file: boolean; - renamed_file: boolean; - deleted_file: boolean; - generated_file: boolean | null; -}; - -export abstract class BaseScmAdapter { - hostInfo: HostInfo; - constructor(hostInfo: HostInfo) { - this.hostInfo = hostInfo; - } - protected abstract getApiUrl(): string; - - protected abstract createHeaders(token: string): { Authorization: string }; - - async test(token: string): Promise { - const url = this.getApiUrl(); - try { - const response = await fetch(url, { headers: this.createHeaders(token) }); - return response.ok; - } catch (error) { - console.error(error); - return false; - } - } - - protected isSupportedFile(filename: string): boolean { - const ext = filename.split('.').pop(); - return SUPPORTED_FILES.includes(ext); - } - - async fetchModifiedFiles( - url: string, - token: string, - ): Promise { - let parsedUrl: URL; - try { - parsedUrl = new URL(url); - // eslint-disable-next-line @typescript-eslint/no-unused-vars - } catch (error) { - throw new Error(`Not a valid URL: ${url}`); - } - - const commitInfo = this.testCommit(parsedUrl); - console.debug('test commit:', commitInfo); - if (commitInfo) { - return this.handleCommit(commitInfo, token); - } else { - const pullInfo = this.testPullRequest(parsedUrl); - console.debug('test pull request', pullInfo); - if (pullInfo !== null) { - return this.handlePullRequest(pullInfo, token); - } else { - throw new Error('Not a GitHub commit or pull request page.'); - } - } - } - - protected abstract testCommit(url: URL): CommitInfo | null; - protected abstract testPullRequest(url: URL): PullInfo | null; - protected abstract handleCommit( - commitInfo: CommitInfo, - token: string, - ): Promise; - protected abstract handlePullRequest( - pullInfo: PullInfo, - token: string, - ): Promise; - - private async downloadDummy(filename: string, suffix: string) { - const [basename, fileExtension] = filename - .split('/') - .slice(-1)[0] - .split('.'); - const downloadName = `diff/${basename}/${ - basename + suffix - }.${fileExtension}`; - const mimeType = `text/${ - fileExtension === 'txt' ? 'plain' : fileExtension - }`; - const downloadUrl = `data:${mimeType};charset=utf-8,`; - return this.doDownload(downloadUrl, downloadName); - } - - private async doDownload( - downloadUrl: string, - downloadName: string, - ): Promise { - const downloadId = await browser.downloads.download({ - url: downloadUrl, - filename: downloadName, - conflictAction: 'overwrite', - }); - - if (downloadId === undefined) throw new Error('Failed to start download'); - - return new Promise((resolve, reject) => { - browser.downloads.onChanged.addListener( - async function onChanged(downloadDelta) { - if ( - downloadDelta.id === downloadId && - downloadDelta.state && - downloadDelta.state.current === 'complete' - ) { - const downloadItems = await browser.downloads.search({ - id: downloadId, - }); - - if (downloadItems.length > 0) { - resolve(downloadItems[0].filename); - } else { - reject(new Error('Failed to retrieve download item')); - } - browser.downloads.onChanged.removeListener(onChanged); - browser.downloads.erase({ id: downloadId }); - } - }, - ); - }); - } - - private calcShortHash(sha: string): string { - return sha.substring(0, 8); - } - - private async doDownloadFile( - url: string, - type: 'raw' | 'json', - filename: string, - suffix: string, - token: string, - sha: string, - ): Promise { - const [basename, fileExtension] = filename - .split('/') - .slice(-1)[0] - .split('.'); - const downloadName = `diff/${basename}/${ - basename + suffix - }.${fileExtension}`; - - const mimeType = `text/${ - fileExtension === 'txt' ? 'plain' : fileExtension - }`; - - console.debug(`Download file ${filename} from ${url} as ${downloadName}`); - const response = await fetch(url, { headers: this.createHeaders(token) }); - if (!response.ok) { - throw new Error( - `Failed to fetch file ${filename} for commit ${sha} via ${url}: ${response.statusText}`, - ); - } - let content: Buffer; - let downloadUrl: string; - - const supportsObjectURL = !!URL.createObjectURL; - - if (type == 'json') { - const fileData = await response.json(); - - content = Buffer.from(fileData.content, 'base64'); - downloadUrl = `data:${mimeType};base64,${fileData.content}`; - if (supportsObjectURL) { - const res = await fetch(downloadUrl); - downloadUrl = URL.createObjectURL(await res.blob()); - } - } else if (type == 'raw') { - if (supportsObjectURL) { - downloadUrl = URL.createObjectURL(await response.blob()); - } else { - content = Buffer.from(await (await response.blob()).arrayBuffer()); - downloadUrl = `data:${mimeType};base64,${encodeURIComponent( - content.toString('base64'), - )}`; - } - } else { - throw new Error(`Unknown download type: ${type}`); - } - - try { - return await this.doDownload(downloadUrl, downloadName); - } finally { - if (supportsObjectURL) URL.revokeObjectURL(downloadUrl); - } - } - - async downloadDiff(file: ModifiedFile, token: string) { - let oldFile = ''; - if (!file.new) { - oldFile = await this.doDownloadFile( - file.download.old, - file.download.type, - file.filename, - `.${this.calcShortHash(file.shaOld)}.old`, - token, - file.shaOld, - ); - } else { - oldFile = await this.downloadDummy( - file.filename, - `.${this.calcShortHash(file.shaOld)}.old`, - ); - } - - let newFile = ''; - if (!file.deleted) { - newFile = await this.doDownloadFile( - file.download.new, - file.download.type, - file.filename, - `.${this.calcShortHash(file.shaNew)}.new`, - token, - file.shaNew, - ); - } else { - newFile = await this.downloadDummy( - file.filename, - `.${this.calcShortHash(file.shaNew)}.new`, - ); - } - - const protocolUrl = encodeURI( - `tracetronic://diff?file1=${oldFile}&file2=${newFile}&cleanup=True`, - ); - await browser.tabs.update({ url: protocolUrl }); - } - - async downloadFile(file: ModifiedFile, what: 'old' | 'new', token: string) { - const sha = what == 'old' ? file.shaOld : file.shaNew; - const theFile = await this.doDownloadFile( - file.download[what], - file.download.type, - file.filename, - `.${this.calcShortHash(sha)}.${what}`, - token, - sha, - ); - const protocolUrl = encodeURI(`tracetronic:///${theFile}`); - await browser.tabs.update({ url: protocolUrl }); - } -} - -class Github extends BaseScmAdapter { - protected getApiUrl(): string { - let url = null; - - if (this.hostInfo.host == 'github.com') { - url = 'https://api.github.com'; - } else { - url = `https://${this.hostInfo.host}/api/v3`; - } - return url; - } - protected createHeaders(token: string) { - return { Authorization: `token ${token}` }; - } - - protected testCommit(url: URL): CommitInfo | null { - // e.g., https://github.com/Mscht/PackageDiffTest/commit/fc33321adcf0ff9d697f64d32a6dfe5f5a12903a - const result = /\/(.*?)\/(.*?)\/commit\/([a-z0-9]+)$/.exec(url.pathname); - - if (result) - return { owner: result[1], repo: result[2], commitHash: result[3] }; - return null; - } - - protected testPullRequest(url: URL): PullInfo | null { - // e.g., https://github.com/Mscht/PackageDiffTest/pull/1 - // or https://github.com/Mscht/PackageDiffTest/pull/1/files - const result = /\/(.*?)\/(.*?)\/pull\/(\d+)\/?/.exec(url.pathname); - if (result) - return { owner: result[1], repo: result[2], pullNumber: result[3] }; - return null; - } - - private async fetchPaginated( - url: string, - token: string, - perPage = 100, - ): Promise { - let page = 1; - const allItems: T[] = []; - let itemsOnPage: T[]; - - do { - const pageUrl = `${url}?per_page=${perPage}&page=${page}`; - const response = await fetch(pageUrl, { - headers: this.createHeaders(token), - }); - if (!response.ok) { - throw new Error( - `Failed to retrieve paginated data (page ${page}): ${response.statusText}`, - ); - } - itemsOnPage = await response.json(); - allItems.push(...itemsOnPage); - page++; - } while (itemsOnPage.length === perPage); - - return allItems; - } - - private async getCommitDetails( - commitInfo: CommitInfo, - token: string, - ): Promise { - const commitUrl = `${this.getApiUrl()}/repos/${commitInfo.owner}/${ - commitInfo.repo - }/commits/${commitInfo.commitHash}`; - - const response = await fetch(commitUrl, { - headers: this.createHeaders(token), - }); - - if (!response.ok) { - throw new Error( - `Failed to retrieve commit details: ${response.statusText}`, - ); - } - - return await response.json(); - } - - protected async handleCommit( - commitInfo: CommitInfo, - token: string, - ): Promise { - const commitData = await this.getCommitDetails(commitInfo, token); - - if (!commitData.files || !Array.isArray(commitData.files)) { - throw new Error('Unable to retrieve modified files from commitData.'); - } - - const baseApiUrl = `${this.getApiUrl()}/repos/${commitInfo.owner}/${ - commitInfo.repo - }`; - return commitData.files - .filter((f) => this.isSupportedFile(f.filename)) - .map((file) => { - const filenameOld = file.previous_filename ?? file.filename; - const shaOld = commitData.parents[0]?.sha; - return { - filename: file.filename, - filenameOld, - new: file.status == 'added', - renamed: file.status == 'renamed', - deleted: file.status == 'removed', - additions: file.additions, - deletions: file.deletions, - shaOld, - shaNew: commitData.sha, - download: { - type: 'json' as const, - old: shaOld - ? `${baseApiUrl}/contents/${filenameOld}?ref=${shaOld}` - : null, - new: `${baseApiUrl}/contents/${file.filename}?ref=${commitData.sha}`, - }, - }; - }); - } - - private async getPullDetails( - commitInfo: PullInfo, - token: string, - ): Promise { - const pullUrl = `${this.getApiUrl()}/repos/${commitInfo.owner}/${ - commitInfo.repo - }/pulls/${commitInfo.pullNumber}`; - - const response = await fetch(pullUrl, { - headers: this.createHeaders(token), - }); - - if (!response.ok) { - throw new Error( - `Failed to retrieve pull details: ${response.statusText}`, - ); - } - const info = await response.json(); - - const pullFilesUrl = `${this.getApiUrl()}/repos/${commitInfo.owner}/${ - commitInfo.repo - }/pulls/${commitInfo.pullNumber}/files`; - const allFiles: GithubChangeFile[] = - await this.fetchPaginated(pullFilesUrl, token); - - return { info, files: allFiles }; - } - - protected async handlePullRequest( - pullInfo: PullInfo, - token: string, - ): Promise { - const pullData = await this.getPullDetails(pullInfo, token); - const baseApiUrl = `${this.getApiUrl()}/repos/${pullInfo.owner}/${ - pullInfo.repo - }`; - - return pullData.files - .filter((f) => this.isSupportedFile(f.filename)) - .map((file) => { - const filenameOld = file.previous_filename ?? file.filename; - const shaOld = pullData.info.base.sha; - return { - filename: file.filename, - filenameOld, - new: file.status == 'added', - renamed: file.status == 'renamed', - deleted: file.status == 'removed', - additions: file.additions, - deletions: file.deletions, - shaOld, - shaNew: pullData.info.head.sha, - download: { - type: 'json' as const, - old: `${baseApiUrl}/contents/${filenameOld}?ref=${shaOld}`, - new: `${baseApiUrl}/contents/${file.filename}?ref=${pullData.info.head.sha}`, - }, - }; - }); - } -} - -class Gitlab extends BaseScmAdapter { - protected testCommit(url: URL): CommitInfo | null { - // https://myhost/mygroup/myproject/-/commit/7afcf8cd245c29bb424543cef583947230166ae4e - const result = /\/(.*?)\/(.*?)\/-\/commit\/([a-z0-9]+)$/.exec(url.pathname); - - if (result) - return { owner: result[1], repo: result[2], commitHash: result[3] }; - return null; - } - - protected testPullRequest(url: URL): PullInfo | null { - const result = /\/(.*?)\/(.*?)\/-\/merge_requests\/([0-9]+)\/?/.exec( - url.pathname, - ); - - if (result) - return { owner: result[1], repo: result[2], pullNumber: result[3] }; - return null; - } - - private parseStats(diff: string): { additions: number; deletions: number } { - let additions = 0; - let deletions = 0; - const result = diff.matchAll(/\r?\n([+-])/g); - [...result].forEach((entry) => { - if (entry[1] == '+') { - additions += 1; - } else { - deletions += 1; - } - }); - return { additions, deletions }; - } - - private processChanges(changes: GitlabChange[]): CommonChange[] { - return changes - .filter((change) => this.isSupportedFile(change.new_path)) - .map((change: GitlabChange) => { - const stats = this.parseStats(change.diff); - return { - filename: change.new_path, - filenameOld: change.old_path, - new: change.new_file, - renamed: change.renamed_file, - deleted: change.deleted_file, - ...stats, - }; - }); - } - - private async fetchPaginated( - url: string, - token: string, - perPage = 100, - ): Promise { - let page = 1; - let totalPages = 1; - const allItems: T[] = []; - - do { - const response = await fetch(`${url}?per_page=${perPage}&page=${page}`, { - headers: this.createHeaders(token), - }); - if (!response.ok) { - throw new Error( - `Failed to retrieve paginated data (page ${page}): [${response.status}] ${response.statusText}`, - ); - } - if (page === 1) { - const tp = response.headers.get('x-total-pages'); - totalPages = tp ? parseInt(tp, 10) : 1; - } - const batch: T[] = await response.json(); - allItems.push(...batch); - page++; - } while (page <= totalPages); - - return allItems; - } - - private async getCommitDetails( - commitInfo: CommitInfo, - token: string, - ): Promise<{ - sha: string; - parents: { sha: string }[]; - files: CommonChange[]; - }> { - const namespace = encodeURIComponent( - `${commitInfo.owner}/${commitInfo.repo}`, - ); - const commitUrl = `${this.getApiUrl()}/projects/${namespace}/repository/commits/${commitInfo.commitHash}`; - - const response = await fetch(commitUrl, { - headers: this.createHeaders(token), - }); - - if (!response.ok) { - throw new Error( - `Failed to retrieve commit details: [${response.status}] ${response.statusText}`, - ); - } - const commitData = await response.json(); - - const diffUrl = `${this.getApiUrl()}/projects/${namespace}/repository/commits/${commitInfo.commitHash}/diff`; - const allChanges: GitlabChange[] = await this.fetchPaginated( - diffUrl, - token, - ); - - const files = this.processChanges(allChanges); - const parents = commitData.parent_ids.map((id: string) => ({ sha: id })); - - return { - sha: commitInfo.commitHash, - parents, - files, - }; - } - - protected async handleCommit( - commitInfo: CommitInfo, - token: string, - ): Promise { - const commitData = await this.getCommitDetails(commitInfo, token); - - if (!commitData.files || !Array.isArray(commitData.files)) { - throw new Error('Unable to retrieve modified files from commitData.'); - } - - const namespace = encodeURIComponent( - `${commitInfo.owner}/${commitInfo.repo}`, - ); - const baseApiUrl = `${this.getApiUrl()}/projects/${namespace}/repository/files`; - - // commitData.parents[0] is probably empty if this is the first commit - const shaOld = commitData.parents[0]?.sha || commitData.sha; - const shaNew = commitData.sha; - const modifiedFiles = commitData.files.map((file) => { - return { - filename: file.filename, - filenameOld: file.filenameOld, - new: file.new, - deleted: file.deleted, - renamed: file.renamed, - additions: file.additions, - deletions: file.deletions, - shaOld, - shaNew, - download: { - type: 'raw' as const, - old: `${baseApiUrl}/${file.filenameOld.replace( - /\//g, - '%2f', - )}/raw?ref=${shaOld}`, - new: `${baseApiUrl}/${file.filename.replace(/\//g, '%2f')}/raw?ref=${ - shaNew - }`, - }, - }; - }); - - return modifiedFiles; - } - - private async getPullDetails( - pullInfo: PullInfo, - token: string, - ): Promise<{ - info: { - head: { sha: string }; - base: { sha: string }; - }; - files: CommonChange[]; - }> { - const namespace = encodeURIComponent(`${pullInfo.owner}/${pullInfo.repo}`); - const diffsUrl = `${this.getApiUrl()}/projects/${namespace}/merge_requests/${pullInfo.pullNumber}/diffs`; - const allChanges: GitlabChange[] = await this.fetchPaginated( - diffsUrl, - token, - ); - const files: CommonChange[] = this.processChanges(allChanges); - - const response = await fetch( - `${this.getApiUrl()}/projects/${namespace}/merge_requests/${pullInfo.pullNumber}`, - { headers: this.createHeaders(token) }, - ); - if (!response.ok) { - throw new Error( - `Failed to retrieve merge request details: [${response.status}] ${response.statusText}`, - ); - } - const pullData = await response.json(); - - return { - info: { - head: { sha: pullData.diff_refs.head_sha }, - base: { sha: pullData.diff_refs.base_sha }, - }, - files, - }; - } - - protected async handlePullRequest( - pullInfo: PullInfo, - token: string, - ): Promise { - const pullData = await this.getPullDetails(pullInfo, token); - const namespace = encodeURIComponent(`${pullInfo.owner}/${pullInfo.repo}`); - const baseApiUrl = `${this.getApiUrl()}/projects/${namespace}/repository/files`; - - // pullData.info.base.sha is probably not set if target branch has no commit yet - const shaOld = pullData.info.base.sha || pullData.info.head.sha; - const shaNew = pullData.info.head.sha; - const modifiedFiles = pullData.files.map((file) => { - return { - filename: file.filename, - filenameOld: file.filenameOld, - new: file.new, - deleted: file.deleted, - renamed: file.renamed, - additions: file.additions, - deletions: file.deletions, - shaOld, - shaNew, - download: { - type: 'raw' as const, - old: `${baseApiUrl}/${file.filenameOld.replace( - /\//g, - '%2f', - )}/raw?ref=${shaOld}`, - new: `${baseApiUrl}/${file.filename.replace(/\//g, '%2f')}/raw?ref=${ - shaNew - }`, - }, - }; - }); - - return modifiedFiles; - } - - protected createHeaders(token: string): { Authorization: string } { - return { Authorization: `Bearer ${token}` }; - } - - protected getApiUrl(): string { - return `https://${this.hostInfo.host}/api/v4`; - } - async test(token: string): Promise { - const url = this.getApiUrl() + '/metadata'; - try { - const response = await fetch(url, { headers: this.createHeaders(token) }); - - return ( - response.ok || - (response.status == 403 && - response.headers.get('x-gitlab-meta') != null) - ); - } catch (error) { - console.error(error); - return false; - } - } -} - -// export only the adapter lookup -export const scmAdapters = { github: Github, gitlab: Gitlab }; diff --git a/src/scm/base.ts b/src/scm/base.ts new file mode 100644 index 0000000..26b5e9a --- /dev/null +++ b/src/scm/base.ts @@ -0,0 +1,294 @@ +import browser from 'webextension-polyfill'; +import { HostInfo, ModifiedFile, SUPPORTED_FILES } from '../types.ts'; +import { Buffer } from 'buffer'; + +// types for responses objects of github and gitlab and generalized types for common usage +export type CommitInfo = { + owner: string; + repo: string; + commitHash: string; +}; + +export type PullInfo = { + owner: string; + repo: string; + pullNumber: string; +}; + +export type CommonChange = { + filename: string; + filenameOld: string; + new: boolean; + renamed: boolean; + deleted: boolean; + additions: number; + deletions: number; +}; + +export abstract class BaseScmAdapter { + hostInfo: HostInfo; + constructor(hostInfo: HostInfo) { + this.hostInfo = hostInfo; + } + protected abstract getApiUrl(): string; + + protected abstract createHeaders(token: string): { Authorization: string }; + + async test(token: string): Promise { + const url = this.getApiUrl(); + try { + const response = await fetch(url, { headers: this.createHeaders(token) }); + return response.ok; + } catch (error) { + console.error(error); + return false; + } + } + + protected getHttpErrorMessages(): Record { + return {}; + } + + protected buildHttpError(response: Response, context: string): Error { + const map = this.getHttpErrorMessages(); + const statusMessage = + map[response.status] ?? 'An unknown error occurred.'; + + return new Error(`Failed to retrieve ${context}. ${statusMessage}`); + } + + protected isSupportedFile(filename: string): boolean { + const ext = filename.split('.').pop(); + return SUPPORTED_FILES.includes(ext); + } + + async fetchModifiedFiles( + url: string, + token: string, + ): Promise { + let parsedUrl: URL; + try { + parsedUrl = new URL(url); + // eslint-disable-next-line @typescript-eslint/no-unused-vars + } catch (error) { + throw new Error(`Not a valid URL: ${url}`); + } + + const commitInfo = this.testCommit(parsedUrl); + console.debug('test commit:', commitInfo); + if (commitInfo) { + return this.handleCommit(commitInfo, token); + } else { + const pullInfo = this.testPullRequest(parsedUrl); + console.debug('test pull request', pullInfo); + if (pullInfo !== null) { + return this.handlePullRequest(pullInfo, token); + } else { + throw new Error('Not a commit or pull request page.'); + } + } + } + + protected abstract testCommit(url: URL): CommitInfo | null; + protected abstract testPullRequest(url: URL): PullInfo | null; + protected abstract handleCommit( + commitInfo: CommitInfo, + token: string, + ): Promise; + protected abstract handlePullRequest( + pullInfo: PullInfo, + token: string, + ): Promise; + + private async downloadDummy(filename: string, suffix: string) { + const [basename, fileExtension] = filename + .split('/') + .slice(-1)[0] + .split('.'); + const downloadName = `diff/${basename}/${ + basename + suffix + }.${fileExtension}`; + + const mimeType = `text/${ + fileExtension === 'txt' ? 'plain' : fileExtension + }`; + let downloadUrl: string; + if (typeof URL.createObjectURL === 'function') { + // firefox does not support data URL, use blob instead. + // Firefox applies the file extension based on download name. + const blob = new Blob([''], { type: 'text/plain' }); + downloadUrl = URL.createObjectURL(blob); + } else { + // chrome supports data URL. It applies the file extension based on data URL mime type. + downloadUrl = `data:${mimeType};charset=utf-8,`; + } + + try { + return await this.doDownload(downloadUrl, downloadName); + } finally { + if ( + typeof URL.createObjectURL === 'function' && + downloadUrl.startsWith('blob:') + ) { + URL.revokeObjectURL(downloadUrl); + } + } + } + + private async doDownload( + downloadUrl: string, + downloadName: string, + ): Promise { + const downloadId = await browser.downloads.download({ + url: downloadUrl, + filename: downloadName, + conflictAction: 'overwrite', + }); + + if (downloadId === undefined) throw new Error('Failed to start download'); + + return new Promise((resolve, reject) => { + browser.downloads.onChanged.addListener( + async function onChanged(downloadDelta) { + if ( + downloadDelta.id === downloadId && + downloadDelta.state && + downloadDelta.state.current === 'complete' + ) { + const downloadItems = await browser.downloads.search({ + id: downloadId, + }); + + if (downloadItems.length > 0) { + resolve(downloadItems[0].filename); + } else { + reject(new Error('Failed to retrieve download item')); + } + browser.downloads.onChanged.removeListener(onChanged); + browser.downloads.erase({ id: downloadId }); + } + }, + ); + }); + } + + private calcShortHash(sha: string): string { + return sha.substring(0, 8); + } + + private async doDownloadFile( + url: string, + type: 'raw' | 'json', + filename: string, + suffix: string, + token: string, + sha: string, + ): Promise { + const [basename, fileExtension] = filename + .split('/') + .slice(-1)[0] + .split('.'); + const downloadName = `diff/${basename}/${ + basename + suffix + }.${fileExtension}`; + + const mimeType = `text/${ + fileExtension === 'txt' ? 'plain' : fileExtension + }`; + + console.debug(`Download file ${filename} from ${url} as ${downloadName}`); + const response = await fetch(url, { headers: this.createHeaders(token) }); + if (!response.ok) { + throw new Error( + `Failed to fetch file ${filename} for commit ${sha} via ${url}: ${response.statusText}`, + ); + } + let content: Buffer; + let downloadUrl: string; + + const supportsObjectURL = !!URL.createObjectURL; + + if (type == 'json') { + const fileData = await response.json(); + + content = Buffer.from(fileData.content, 'base64'); + downloadUrl = `data:${mimeType};base64,${fileData.content}`; + if (supportsObjectURL) { + const res = await fetch(downloadUrl); + downloadUrl = URL.createObjectURL(await res.blob()); + } + } else if (type == 'raw') { + if (supportsObjectURL) { + downloadUrl = URL.createObjectURL(await response.blob()); + } else { + content = Buffer.from(await (await response.blob()).arrayBuffer()); + downloadUrl = `data:${mimeType};base64,${encodeURIComponent( + content.toString('base64'), + )}`; + } + } else { + throw new Error(`Unknown download type: ${type}`); + } + + try { + return await this.doDownload(downloadUrl, downloadName); + } finally { + if (supportsObjectURL) URL.revokeObjectURL(downloadUrl); + } + } + + async downloadDiff(file: ModifiedFile, token: string) { + let oldFile = ''; + if (!file.new) { + oldFile = await this.doDownloadFile( + file.download.old, + file.download.type, + file.filename, + `.${this.calcShortHash(file.shaOld)}.old`, + token, + file.shaOld, + ); + } else { + oldFile = await this.downloadDummy( + file.filename, + `.${this.calcShortHash(file.shaOld)}.old`, + ); + } + + let newFile = ''; + if (!file.deleted) { + newFile = await this.doDownloadFile( + file.download.new, + file.download.type, + file.filename, + `.${this.calcShortHash(file.shaNew)}.new`, + token, + file.shaNew, + ); + } else { + newFile = await this.downloadDummy( + file.filename, + `.${this.calcShortHash(file.shaNew)}.new`, + ); + } + + const protocolUrl = encodeURI( + `tracetronic://diff?file1=${oldFile}&file2=${newFile}&cleanup=True`, + ); + await browser.tabs.update({ url: protocolUrl }); + } + + async downloadFile(file: ModifiedFile, what: 'old' | 'new', token: string) { + const sha = what == 'old' ? file.shaOld : file.shaNew; + const theFile = await this.doDownloadFile( + file.download[what], + file.download.type, + file.filename, + `.${this.calcShortHash(sha)}.${what}`, + token, + sha, + ); + const protocolUrl = encodeURI(`tracetronic:///${theFile}`); + await browser.tabs.update({ url: protocolUrl }); + } +} diff --git a/src/scm/bitbucket.ts b/src/scm/bitbucket.ts new file mode 100644 index 0000000..9785fa7 --- /dev/null +++ b/src/scm/bitbucket.ts @@ -0,0 +1,285 @@ +import { AuthType, ModifiedFile } from '../types.ts'; +import { BaseScmAdapter, CommitInfo, CommonChange, PullInfo } from './base.ts'; + +type BitbucketChange = { + status: string; + lines_added: number; + lines_removed: number; + new: { path: string }; + old?: { path: string }; +}; + +export class Bitbucket extends BaseScmAdapter { + private authType: AuthType = AuthType.Basic; + + public setAuthType(type: AuthType): void { + this.authType = type; + } + + protected getApiUrl(): string { + const { hostname } = this.parseHostScope(); + if (hostname !== 'bitbucket.org') { + throw new Error('Bitbucket Cloud only supports bitbucket.org'); + } + return `https://api.${hostname}/2.0`; + } + + protected createHeaders(token: string): { Authorization: string } { + if (this.usesBearerAuth()) { + return { Authorization: `Bearer ${token}` }; + } + return { Authorization: `Basic ${btoa(token)}` }; + } + + private parseHostScope() { + const raw = this.hostInfo.host + .trim() + .replace(/^https?:\/\//, '') + .replace(/\/+$/, ''); + const [hostname, workspace, repo] = raw.split('/'); + return { hostname, workspace, repo }; + } + + private usesBearerAuth(): boolean { + return this.authType === AuthType.Bearer; + } + + async test(token: string): Promise { + const { workspace, repo } = this.parseHostScope(); + const baseUrl = this.getApiUrl(); + + try { + if (!this.usesBearerAuth()) { + if (workspace || repo) return false; + + const response = await fetch(`${baseUrl}/user`, { + headers: this.createHeaders(token), + }); + // 403 means the read:user scope is missing, still a valid token + return response.status === 200 || response.status === 403; + } + + if (!workspace) return false; + if (repo) { + const response = await fetch( + `${baseUrl}/repositories/${workspace}/${repo}`, + { + headers: this.createHeaders(token), + }, + ); + return response.status === 200; + } + + const response = await fetch(`${baseUrl}/repositories/${workspace}`, { + headers: this.createHeaders(token), + }); + return response.status === 200; + } catch (error) { + console.error(error); + return false; + } + } + + protected testCommit(url: URL): CommitInfo | null { + const result = /\/(.*?)\/(.*?)\/commits\/([a-z0-9]+)$/.exec(url.pathname); + + if (result) + return { owner: result[1], repo: result[2], commitHash: result[3] }; + return null; + } + + protected testPullRequest(url: URL): PullInfo | null { + const result = + /^\/([^/]+)\/([^/]+)\/pull-?requests?\/(\d+)(?:\/.*)?$/i.exec( + url.pathname, + ); + + if (result) + return { owner: result[1], repo: result[2], pullNumber: result[3] }; + return null; + } + + private processChanges(changes: BitbucketChange[]): CommonChange[] { + return changes + .filter((change) => this.isSupportedFile(change.new.path)) + .map((change) => { + const isAdded = change.status === 'added'; + const isRemoved = change.status === 'removed'; + const isRenamed = change.status === 'renamed'; + return { + filename: change.new.path, + filenameOld: + isRenamed && change.old ? change.old.path : change.new.path, + new: isAdded, + renamed: isRenamed, + deleted: isRemoved, + additions: change.lines_added, + deletions: change.lines_removed, + }; + }); + } + + protected override getHttpErrorMessages(): Record { + return { + 401: 'Unauthorized: Invalid or missing token.', + 403: 'Forbidden: Your credentials lack one or more required privilege scopes.', + 404: 'Not found: You may not have access to this repository.', + }; + } + + private async fetchPaginated(url: string, token: string): Promise { + let results: T[] = []; + let nextUrl: string | null = url; + while (nextUrl) { + const response = await fetch(nextUrl, { + headers: this.createHeaders(token), + }); + if (!response.ok) { + throw this.buildHttpError(response, 'paginated data'); + } + const data = await response.json(); + results = results.concat(data.values); + nextUrl = data.next || null; + } + return results; + } + + private async getCommitDetails( + commitInfo: CommitInfo, + token: string, + ): Promise<{ + sha: string; + parents: { sha: string }[]; + files: CommonChange[]; + }> { + const namespace = encodeURIComponent( + `${commitInfo.owner}/${commitInfo.repo}`, + ); + const commitUrl = `${this.getApiUrl()}/repositories/${namespace}/commit/${commitInfo.commitHash}`; + const response = await fetch(commitUrl, { + headers: this.createHeaders(token), + }); + + if (!response.ok) { + throw this.buildHttpError(response, 'commit details'); + } + const commitData = await response.json(); + + const diffUrl = `${this.getApiUrl()}/repositories/${namespace}/diffstat/${commitInfo.commitHash}`; + const allChanges: BitbucketChange[] = await this.fetchPaginated( + diffUrl, + token, + ); + + const files = this.processChanges(allChanges); + const parents = Array.isArray(commitData.parents) + ? commitData.parents.map(({ hash }: { hash: string }) => ({ sha: hash })) + : []; + return { + sha: commitInfo.commitHash, + parents, + files, + }; + } + + protected async handleCommit( + commitInfo: CommitInfo, + token: string, + ): Promise { + const commitData = await this.getCommitDetails(commitInfo, token); + + if (!commitData.files || !Array.isArray(commitData.files)) { + throw new Error('Unable to retrieve modified files from commitData.'); + } + + const namespace = encodeURIComponent( + `${commitInfo.owner}/${commitInfo.repo}`, + ); + const baseApiUrl = `${this.getApiUrl()}/repositories/${namespace}`; + + const shaOld = commitData.parents[0]?.sha || commitData.sha; + const shaNew = commitData.sha; + const modifiedFiles = commitData.files.map((file) => { + return { + filename: file.filename, + filenameOld: file.filenameOld, + new: file.new, + deleted: file.deleted, + renamed: file.renamed, + additions: file.additions, + deletions: file.deletions, + shaOld, + shaNew, + download: { + type: 'raw' as const, + old: `${baseApiUrl}/src/${shaOld}/${file.filenameOld.replace(/\//g, '%2f')}`, + new: `${baseApiUrl}/src/${shaNew}/${file.filename.replace(/\//g, '%2f')}`, + }, + }; + }); + + return modifiedFiles; + } + + private async getPullDetails( + pullInfo: PullInfo, + token: string, + ): Promise<{ + info: { head: { sha: string }; base: { sha: string } }; + files: CommonChange[]; + }> { + const namespace = encodeURIComponent(`${pullInfo.owner}/${pullInfo.repo}`); + const prUrl = `${this.getApiUrl()}/repositories/${namespace}/pullrequests/${pullInfo.pullNumber}`; + const response = await fetch(prUrl, { + headers: this.createHeaders(token), + }); + + if (!response.ok) { + throw this.buildHttpError(response, 'pull request details'); + } + const prData = await response.json(); + + const headSha = prData.source.commit.hash; + const baseSha = prData.destination.commit.hash; + + const diffStatUrl = `${this.getApiUrl()}/repositories/${namespace}/pullrequests/${pullInfo.pullNumber}/diffstat`; + const allChanges: BitbucketChange[] = await this.fetchPaginated( + diffStatUrl, + token, + ); + + const files = this.processChanges(allChanges); + return { info: { head: { sha: headSha }, base: { sha: baseSha } }, files }; + } + + protected async handlePullRequest( + pullInfo: PullInfo, + token: string, + ): Promise { + const pullData = await this.getPullDetails(pullInfo, token); + + const shaOld = pullData.info.base.sha || pullData.info.head.sha; + const shaNew = pullData.info.head.sha; + + const namespace = encodeURIComponent(`${pullInfo.owner}/${pullInfo.repo}`); + const baseApiUrl = `${this.getApiUrl()}/repositories/${namespace}`; + + const modifiedFiles = pullData.files.map((file) => ({ + filename: file.filename, + filenameOld: file.filenameOld, + new: file.new, + deleted: file.deleted, + renamed: file.renamed, + additions: file.additions, + deletions: file.deletions, + shaOld, + shaNew, + download: { + type: 'raw' as const, + old: `${baseApiUrl}/src/${shaOld}/${file.filenameOld.replace(/\//g, '%2f')}`, + new: `${baseApiUrl}/src/${shaNew}/${file.filename.replace(/\//g, '%2f')}`, + }, + })); + return modifiedFiles; + } +} diff --git a/src/scm/github.ts b/src/scm/github.ts new file mode 100644 index 0000000..21105d8 --- /dev/null +++ b/src/scm/github.ts @@ -0,0 +1,210 @@ +import { BaseScmAdapter, CommitInfo, PullInfo } from './base.ts'; +import { ModifiedFile } from '../types'; + +type GithubCommitInfo = { + files: GithubChangeFile[]; + parents: { sha: string }[]; + sha: string; +}; + +type GithubPullInfo = { + info: { base: { sha: string }; head: { sha: string } }; + files: GithubChangeFile[]; +}; + +type GithubChangeFile = { + additions: number; + deletions: number; + changes: number; + filename: string; + previous_filename?: string; + patch: string; + sha: string; + status: 'added' | 'renamed' | 'removed'; + blob_url: string; + raw_url: string; + content_url: string; +}; + +export class Github extends BaseScmAdapter { + protected getApiUrl(): string { + let url = null; + + if (this.hostInfo.host == 'github.com') { + url = 'https://api.github.com'; + } else { + url = `https://${this.hostInfo.host}/api/v3`; + } + return url; + } + protected createHeaders(token: string) { + return { Authorization: `token ${token}` }; + } + + protected testCommit(url: URL): CommitInfo | null { + // e.g., https://github.com/Mscht/PackageDiffTest/commit/fc33321adcf0ff9d697f64d32a6dfe5f5a12903a + const result = /\/(.*?)\/(.*?)\/commit\/([a-z0-9]+)$/.exec(url.pathname); + + if (result) + return { owner: result[1], repo: result[2], commitHash: result[3] }; + return null; + } + + protected testPullRequest(url: URL): PullInfo | null { + // e.g., https://github.com/Mscht/PackageDiffTest/pull/1 + // or https://github.com/Mscht/PackageDiffTest/pull/1/files + const result = /\/(.*?)\/(.*?)\/pull\/(\d+)\/?/.exec(url.pathname); + if (result) + return { owner: result[1], repo: result[2], pullNumber: result[3] }; + return null; + } + + protected override getHttpErrorMessages(): Record { + return { + 401: 'Unauthorized: Invalid or missing token.', + 403: 'Forbidden: If you use a fine-grained access token, make sure to give permissions "Content" and "Pull requests".', + 404: 'Not found: You may not have access to this repository.', + }; + } + + private async fetchPaginated( + url: string, + token: string, + perPage = 100, + ): Promise { + let page = 1; + const allItems: T[] = []; + let itemsOnPage: T[]; + + do { + const pageUrl = `${url}?per_page=${perPage}&page=${page}`; + const response = await fetch(pageUrl, { + headers: this.createHeaders(token), + }); + if (!response.ok) { + throw this.buildHttpError(response, `paginated data (page ${page})`); + } + itemsOnPage = await response.json(); + allItems.push(...itemsOnPage); + page++; + } while (itemsOnPage.length === perPage); + + return allItems; + } + + private async getCommitDetails( + commitInfo: CommitInfo, + token: string, + ): Promise { + const commitUrl = `${this.getApiUrl()}/repos/${commitInfo.owner}/${ + commitInfo.repo + }/commits/${commitInfo.commitHash}`; + + const response = await fetch(commitUrl, { + headers: this.createHeaders(token), + }); + + if (!response.ok) { + throw this.buildHttpError(response, 'commit details'); + } + return await response.json(); + } + + protected async handleCommit( + commitInfo: CommitInfo, + token: string, + ): Promise { + const commitData = await this.getCommitDetails(commitInfo, token); + + if (!commitData.files || !Array.isArray(commitData.files)) { + throw new Error('Unable to retrieve modified files from commitData.'); + } + + const baseApiUrl = `${this.getApiUrl()}/repos/${commitInfo.owner}/${ + commitInfo.repo + }`; + return commitData.files + .filter((f) => this.isSupportedFile(f.filename)) + .map((file) => { + const filenameOld = file.previous_filename ?? file.filename; + const shaOld = commitData.parents[0]?.sha; + return { + filename: file.filename, + filenameOld, + new: file.status == 'added', + renamed: file.status == 'renamed', + deleted: file.status == 'removed', + additions: file.additions, + deletions: file.deletions, + shaOld, + shaNew: commitData.sha, + download: { + type: 'json' as const, + old: shaOld + ? `${baseApiUrl}/contents/${filenameOld}?ref=${shaOld}` + : null, + new: `${baseApiUrl}/contents/${file.filename}?ref=${commitData.sha}`, + }, + }; + }); + } + + private async getPullDetails( + commitInfo: PullInfo, + token: string, + ): Promise { + const pullUrl = `${this.getApiUrl()}/repos/${commitInfo.owner}/${ + commitInfo.repo + }/pulls/${commitInfo.pullNumber}`; + + const response = await fetch(pullUrl, { + headers: this.createHeaders(token), + }); + + if (!response.ok) { + throw this.buildHttpError(response, 'pull request details'); + } + const info = await response.json(); + + const pullFilesUrl = `${this.getApiUrl()}/repos/${commitInfo.owner}/${ + commitInfo.repo + }/pulls/${commitInfo.pullNumber}/files`; + const allFiles: GithubChangeFile[] = + await this.fetchPaginated(pullFilesUrl, token); + + return { info, files: allFiles }; + } + + protected async handlePullRequest( + pullInfo: PullInfo, + token: string, + ): Promise { + const pullData = await this.getPullDetails(pullInfo, token); + const baseApiUrl = `${this.getApiUrl()}/repos/${pullInfo.owner}/${ + pullInfo.repo + }`; + + return pullData.files + .filter((f) => this.isSupportedFile(f.filename)) + .map((file) => { + const filenameOld = file.previous_filename ?? file.filename; + const shaOld = pullData.info.base.sha; + return { + filename: file.filename, + filenameOld, + new: file.status == 'added', + renamed: file.status == 'renamed', + deleted: file.status == 'removed', + additions: file.additions, + deletions: file.deletions, + shaOld, + shaNew: pullData.info.head.sha, + download: { + type: 'json' as const, + old: `${baseApiUrl}/contents/${filenameOld}?ref=${shaOld}`, + new: `${baseApiUrl}/contents/${file.filename}?ref=${pullData.info.head.sha}`, + }, + }; + }); + } +} diff --git a/src/scm/gitlab.ts b/src/scm/gitlab.ts new file mode 100644 index 0000000..7449e92 --- /dev/null +++ b/src/scm/gitlab.ts @@ -0,0 +1,281 @@ +import { BaseScmAdapter, CommitInfo, PullInfo, CommonChange } from './base.ts'; +import { ModifiedFile } from '../types'; + +type GitlabChange = { + diff: string; + new_path: string; + old_path: string; + a_mode: string; + b_mode: string; + new_file: boolean; + renamed_file: boolean; + deleted_file: boolean; + generated_file: boolean | null; +}; + +export class Gitlab extends BaseScmAdapter { + protected testCommit(url: URL): CommitInfo | null { + // https://myhost/mygroup/myproject/-/commit/7afcf8cd245c29bb424543cef583947230166ae4e + const result = /\/(.*?)\/(.*?)\/-\/commit\/([a-z0-9]+)$/.exec(url.pathname); + + if (result) + return { owner: result[1], repo: result[2], commitHash: result[3] }; + return null; + } + + protected testPullRequest(url: URL): PullInfo | null { + const result = /\/(.*?)\/(.*?)\/-\/merge_requests\/([0-9]+)\/?/.exec( + url.pathname, + ); + + if (result) + return { owner: result[1], repo: result[2], pullNumber: result[3] }; + return null; + } + + private parseStats(diff: string): { additions: number; deletions: number } { + let additions = 0; + let deletions = 0; + const result = diff.matchAll(/\r?\n([+-])/g); + [...result].forEach((entry) => { + if (entry[1] == '+') { + additions += 1; + } else { + deletions += 1; + } + }); + return { additions, deletions }; + } + + private processChanges(changes: GitlabChange[]): CommonChange[] { + return changes + .filter((change) => this.isSupportedFile(change.new_path)) + .map((change: GitlabChange) => { + const stats = this.parseStats(change.diff); + return { + filename: change.new_path, + filenameOld: change.old_path, + new: change.new_file, + renamed: change.renamed_file, + deleted: change.deleted_file, + ...stats, + }; + }); + } + + protected override getHttpErrorMessages(): Record { + return { + 401: 'Unauthorized: Invalid or missing token.', + 403: 'Forbidden: Insufficient scope. Make sure to give permission "read_api".', + 404: 'Not found: You may not have access to this repository.', + }; + } + + private async fetchPaginated( + url: string, + token: string, + perPage = 100, + ): Promise { + let page = 1; + let totalPages = 1; + const allItems: T[] = []; + + do { + const response = await fetch(`${url}?per_page=${perPage}&page=${page}`, { + headers: this.createHeaders(token), + }); + if (!response.ok) { + throw this.buildHttpError(response, `paginated data (page ${page})`); + } + if (page === 1) { + const tp = response.headers.get('x-total-pages'); + totalPages = tp ? parseInt(tp, 10) : 1; + } + const batch: T[] = await response.json(); + allItems.push(...batch); + page++; + } while (page <= totalPages); + + return allItems; + } + + private async getCommitDetails( + commitInfo: CommitInfo, + token: string, + ): Promise<{ + sha: string; + parents: { sha: string }[]; + files: CommonChange[]; + }> { + const namespace = encodeURIComponent( + `${commitInfo.owner}/${commitInfo.repo}`, + ); + const commitUrl = `${this.getApiUrl()}/projects/${namespace}/repository/commits/${commitInfo.commitHash}`; + + const response = await fetch(commitUrl, { + headers: this.createHeaders(token), + }); + + if (!response.ok) { + throw this.buildHttpError(response, 'commit details'); + } + const commitData = await response.json(); + + const diffUrl = `${this.getApiUrl()}/projects/${namespace}/repository/commits/${commitInfo.commitHash}/diff`; + const allChanges: GitlabChange[] = await this.fetchPaginated( + diffUrl, + token, + ); + + const files = this.processChanges(allChanges); + const parents = commitData.parent_ids.map((id: string) => ({ sha: id })); + + return { + sha: commitInfo.commitHash, + parents, + files, + }; + } + + protected async handleCommit( + commitInfo: CommitInfo, + token: string, + ): Promise { + const commitData = await this.getCommitDetails(commitInfo, token); + + if (!commitData.files || !Array.isArray(commitData.files)) { + throw new Error('Unable to retrieve modified files from commitData.'); + } + + const namespace = encodeURIComponent( + `${commitInfo.owner}/${commitInfo.repo}`, + ); + const baseApiUrl = `${this.getApiUrl()}/projects/${namespace}/repository/files`; + + // commitData.parents[0] is probably empty if this is the first commit + const shaOld = commitData.parents[0]?.sha || commitData.sha; + const shaNew = commitData.sha; + const modifiedFiles = commitData.files.map((file) => { + return { + filename: file.filename, + filenameOld: file.filenameOld, + new: file.new, + deleted: file.deleted, + renamed: file.renamed, + additions: file.additions, + deletions: file.deletions, + shaOld, + shaNew, + download: { + type: 'raw' as const, + old: `${baseApiUrl}/${file.filenameOld.replace( + /\//g, + '%2f', + )}/raw?ref=${shaOld}`, + new: `${baseApiUrl}/${file.filename.replace(/\//g, '%2f')}/raw?ref=${ + shaNew + }`, + }, + }; + }); + + return modifiedFiles; + } + + private async getPullDetails( + pullInfo: PullInfo, + token: string, + ): Promise<{ + info: { + head: { sha: string }; + base: { sha: string }; + }; + files: CommonChange[]; + }> { + const namespace = encodeURIComponent(`${pullInfo.owner}/${pullInfo.repo}`); + const diffsUrl = `${this.getApiUrl()}/projects/${namespace}/merge_requests/${pullInfo.pullNumber}/diffs`; + const allChanges: GitlabChange[] = await this.fetchPaginated( + diffsUrl, + token, + ); + const files: CommonChange[] = this.processChanges(allChanges); + + const response = await fetch( + `${this.getApiUrl()}/projects/${namespace}/merge_requests/${pullInfo.pullNumber}`, + { headers: this.createHeaders(token) }, + ); + if (!response.ok) { + throw this.buildHttpError(response, 'merge request details'); + } + const pullData = await response.json(); + + return { + info: { + head: { sha: pullData.diff_refs.head_sha }, + base: { sha: pullData.diff_refs.base_sha }, + }, + files, + }; + } + + protected async handlePullRequest( + pullInfo: PullInfo, + token: string, + ): Promise { + const pullData = await this.getPullDetails(pullInfo, token); + const namespace = encodeURIComponent(`${pullInfo.owner}/${pullInfo.repo}`); + const baseApiUrl = `${this.getApiUrl()}/projects/${namespace}/repository/files`; + + // pullData.info.base.sha is probably not set if target branch has no commit yet + const shaOld = pullData.info.base.sha || pullData.info.head.sha; + const shaNew = pullData.info.head.sha; + const modifiedFiles = pullData.files.map((file) => { + return { + filename: file.filename, + filenameOld: file.filenameOld, + new: file.new, + deleted: file.deleted, + renamed: file.renamed, + additions: file.additions, + deletions: file.deletions, + shaOld, + shaNew, + download: { + type: 'raw' as const, + old: `${baseApiUrl}/${file.filenameOld.replace( + /\//g, + '%2f', + )}/raw?ref=${shaOld}`, + new: `${baseApiUrl}/${file.filename.replace(/\//g, '%2f')}/raw?ref=${ + shaNew + }`, + }, + }; + }); + + return modifiedFiles; + } + + protected createHeaders(token: string): { Authorization: string } { + return { Authorization: `Bearer ${token}` }; + } + + protected getApiUrl(): string { + return `https://${this.hostInfo.host}/api/v4`; + } + async test(token: string): Promise { + const url = this.getApiUrl() + '/metadata'; + try { + const response = await fetch(url, { headers: this.createHeaders(token) }); + + return ( + response.ok || + (response.status == 403 && + response.headers.get('x-gitlab-meta') != null) + ); + } catch (error) { + console.error(error); + return false; + } + } +} diff --git a/src/scm/index.ts b/src/scm/index.ts new file mode 100644 index 0000000..61da230 --- /dev/null +++ b/src/scm/index.ts @@ -0,0 +1,9 @@ +import { Bitbucket } from './bitbucket.ts'; +import { Github } from './github.ts'; +import { Gitlab } from './gitlab.ts'; + +export const scmAdapters = { + github: Github, + gitlab: Gitlab, + bitbucket: Bitbucket, +}; diff --git a/src/serviceWorker.ts b/src/serviceWorker.ts index a9cc164..124a264 100644 --- a/src/serviceWorker.ts +++ b/src/serviceWorker.ts @@ -1,13 +1,14 @@ import browser from 'webextension-polyfill'; import { Action, + AuthType, ErrorType, HostInfo, ModifiedFile, ScmHost, ServiceWorkerRequest, } from './types'; -import { scmAdapters } from './scm'; +import { scmAdapters } from './scm/index'; browser.runtime.onMessage.addListener(async function ( request: ServiceWorkerRequest, @@ -52,12 +53,53 @@ async function checkTab(): Promise { const currentHost = url.host; const hostList = await getHosts(); - const entry = hostList.find((value) => value.host == currentHost); - if (entry) return { scm: entry.scm, host: currentHost }; + const entry = findScmHostForUrl(url, hostList); + if (entry) return { scm: entry.scm, host: entry.host }; return { scm: null, host: currentHost }; } +function normalizeHostKey(host: string): string { + return host + .trim() + .replace(/^https?:\/\//, '') + .replace(/\/+$/, '') + .toLowerCase(); +} + +function findScmHostForUrl(url: URL, hosts: ScmHost[]): ScmHost | undefined { + const hostname = url.hostname.toLowerCase(); + if (hostname === 'bitbucket.org') { + const path = url.pathname.replace(/^\/+|\/+$/g, ''); + const parts = path.split('/'); + + const candidates: string[] = []; + if (parts.length >= 2) { + candidates.push(`bitbucket.org/${parts[0]}/${parts[1]}`); + candidates.push(`bitbucket.org/${parts[0]}`); + } + + candidates.push('bitbucket.org'); + const normalizedHosts = hosts + .filter((h) => h.scm === 'bitbucket') + .map((h) => ({ host: h, key: normalizeHostKey(h.host) })); + + for (const candidate of candidates) { + const key = normalizeHostKey(candidate); + const match = normalizedHosts.find((x) => x.key === key); + if (match) return match.host; + } + return undefined; + } + + const key = normalizeHostKey(hostname); + const normalizedHosts = hosts.map((h) => ({ + host: h, + key: normalizeHostKey(h.host), + })); + return normalizedHosts.find((x) => x.key === key)?.host; +} + async function getHosts(): Promise { const dataString: Record = (await browser.storage.local.get('hosts')) as Record< @@ -87,37 +129,64 @@ async function addHost(hostInfo: HostInfo): Promise { return true; } -async function getToken(hostInfo: HostInfo): Promise { +function createAdapter(hostInfo: HostInfo, entry?: ScmHost) { + const AdapterClass = scmAdapters[hostInfo.scm!]; + const adapter = new AdapterClass(hostInfo); + + if (hostInfo.scm === 'bitbucket' && entry?.authType) { + (adapter as unknown as { setAuthType: (t: AuthType) => void }).setAuthType( + entry.authType, + ); + } + + return adapter; +} + +async function getHostEntry(hostInfo: HostInfo): Promise { const data = await getHosts(); - const entry = data.find((value) => value.host == hostInfo.host); - if (entry == null) throw new Error(ErrorType.HOST_NOT_FOUND); - return entry.token; + const targetKey = normalizeHostKey(hostInfo.host); + const entry = data.find( + (h) => normalizeHostKey(h.host) === targetKey && h.scm === hostInfo.scm, + ); + if (!entry) throw new Error(ErrorType.HOST_NOT_FOUND); + return entry; } async function checkConnection(scmHost: ScmHost): Promise { - return new scmAdapters[scmHost.scm](scmHost).test(scmHost.token); + if (scmHost.token == null) throw new Error(ErrorType.SCM_NOT_SET); + const hostInfo: HostInfo = { scm: scmHost.scm, host: scmHost.host }; + const adapter = createAdapter(hostInfo, scmHost); + return adapter.test(scmHost.token); } async function fetchModifiedFiles(hostInfo: HostInfo) { if (hostInfo.scm == null) throw new Error(ErrorType.SCM_NOT_SET); - const token = await getToken(hostInfo); - if (token == null) throw new Error(ErrorType.TOKEN_NOT_SET); + const entry = await getHostEntry(hostInfo); + if (entry.token == null) throw new Error(ErrorType.TOKEN_NOT_SET); - return await new scmAdapters[hostInfo.scm](hostInfo).fetchModifiedFiles( - (await getActiveTab()).url, - token, - ); + const adapter = createAdapter(hostInfo, entry); + return adapter.fetchModifiedFiles((await getActiveTab()).url, entry.token); } async function downloadDiff(file: ModifiedFile) { const hostInfo = await checkTab(); - const token = await getToken(hostInfo); - new scmAdapters[hostInfo.scm](hostInfo).downloadDiff(file, token); + if (hostInfo.scm == null) throw new Error(ErrorType.SCM_NOT_SET); + + const entry = await getHostEntry(hostInfo); + if (entry.token == null) throw new Error(ErrorType.TOKEN_NOT_SET); + + const adapter = createAdapter(hostInfo, entry); + return adapter.downloadDiff(file, entry.token); } async function downloadFile(file: ModifiedFile, what: 'old' | 'new') { const hostInfo = await checkTab(); - const token = await getToken(hostInfo); - new scmAdapters[hostInfo.scm](hostInfo).downloadFile(file, what, token); + if (hostInfo.scm == null) throw new Error(ErrorType.SCM_NOT_SET); + + const entry = await getHostEntry(hostInfo); + if (entry.token == null) throw new Error(ErrorType.TOKEN_NOT_SET); + + const adapter = createAdapter(hostInfo, entry); + return adapter.downloadFile(file, what, entry.token); } diff --git a/src/types.ts b/src/types.ts index f830f34..fc7b278 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,15 +1,31 @@ -export const SUPPORTED_DIFF_FILES = ['pkg', 'ta', 'prj', 'xam', 'ppd', 'mask', 'gcd', 'tcf', 'tbc']; +export const SUPPORTED_DIFF_FILES = [ + 'pkg', + 'ta', + 'prj', + 'xam', + 'ppd', + 'mask', + 'gcd', + 'tcf', + 'tbc', +]; export const SUPPORTED_FILES = [...SUPPORTED_DIFF_FILES, 'trf']; export type HostInfo = { - scm: 'gitlab' | 'github' | null; + scm: 'gitlab' | 'github' | 'bitbucket' | null; host: string; }; +export enum AuthType { + Basic = 'basic', + Bearer = 'bearer', +} + export type ScmHost = { - scm: 'gitlab' | 'github'; + scm: 'gitlab' | 'github' | 'bitbucket'; host: string; token: string | null; + authType?: AuthType; }; export enum ErrorType { diff --git a/src/utils.ts b/src/utils.ts new file mode 100644 index 0000000..c0f8642 --- /dev/null +++ b/src/utils.ts @@ -0,0 +1,10 @@ +/** + * Normalizes a host string by removing protocol, trailing slashes, and lowercasing. + */ +export function normalizeHost(host: string): string { + return host + .trim() + .replace(/^https?:\/\//, '') + .replace(/\/+$/, '') + .toLowerCase(); +} diff --git a/static/icons/bitbucket.svg b/static/icons/bitbucket.svg new file mode 100644 index 0000000..20fd044 --- /dev/null +++ b/static/icons/bitbucket.svg @@ -0,0 +1,5 @@ + \ No newline at end of file diff --git a/static/manifest.json b/static/manifest.json index b8c1063..acfef29 100644 --- a/static/manifest.json +++ b/static/manifest.json @@ -1,7 +1,7 @@ { "manifest_version": 3, "name": "Open with ecu.test diff", - "description": "Extension to open the ecu.test/trace.check diff viewer on GitHub/GitLab.", + "description": "Extension to open the ecu.test/trace.check diff viewer on GitHub/GitLab/Bitbucket Cloud.", "version": "1.1.0.0", "background": {}, "browser_specific_settings": { diff --git a/static/options.html b/static/options.html index 2638d57..608c8eb 100644 --- a/static/options.html +++ b/static/options.html @@ -20,17 +20,25 @@
    Hosts
    + - - - @@ -53,9 +60,141 @@
    Platform URLToken
    @@ -45,7 +53,6 @@ Check settings
    - + + +
    + diff --git a/static/popup.html b/static/popup.html index 83a14f9..bd71801 100644 --- a/static/popup.html +++ b/static/popup.html @@ -31,15 +31,15 @@ Enable the extension for the current host?
    Add as - +

    - -
    +
    Add host
    +
    +
    +