Skip to content

Commit c2eee3e

Browse files
committed
feat: replace simple-git with octokit to load fiddle
1 parent caa1f8d commit c2eee3e

File tree

7 files changed

+112
-41
lines changed

7 files changed

+112
-41
lines changed

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,14 @@
3030
},
3131
"dependencies": {
3232
"@electron/get": "^2.0.0",
33+
"@octokit/rest": "^19.0.4",
3334
"debug": "^4.3.3",
3435
"env-paths": "^2.2.1",
3536
"extract-zip": "^2.0.1",
3637
"fs-extra": "^10.0.0",
3738
"getos": "^3.2.1",
3839
"node-fetch": "^2.6.1",
39-
"semver": "^7.3.5",
40-
"simple-git": "^2.48.0"
40+
"semver": "^7.3.5"
4141
},
4242
"devDependencies": {
4343
"@continuous-auth/semantic-release-npm": "^3.0.0",

src/fiddle.ts

Lines changed: 70 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
import * as fs from 'fs-extra';
22
import * as path from 'path';
33
import debug from 'debug';
4-
import simpleGit from 'simple-git';
4+
import fetch from 'node-fetch';
55
import { createHash } from 'crypto';
66

77
import { DefaultPaths } from './paths';
8+
import { getOctokit } from './utils/octokit';
89

910
function hashString(str: string): string {
1011
const md5sum = createHash('md5');
@@ -32,10 +33,43 @@ export class Fiddle {
3233
export type FiddleSource = Fiddle | string | Iterable<[string, string]>;
3334

3435
export class FiddleFactory {
36+
private readonly VALID_FILES: Array<string> = [
37+
'main.js',
38+
'renderer.js',
39+
'index.html',
40+
'preload.js',
41+
'styles.css',
42+
];
43+
// Thanks to https://serverfault.com/a/917253
44+
private readonly GITHUB_URL_REGEX = new RegExp(
45+
'^(https|git)(://|@)([^/:]+)[/:]([^/:]+)/(.+).git$',
46+
);
47+
3548
constructor(private readonly fiddles: string = DefaultPaths.fiddles) {}
3649

37-
public async fromGist(gistId: string): Promise<Fiddle> {
38-
return this.fromRepo(`https://gist.github.com/${gistId}.git`);
50+
public async fromGist(gistId: string) {
51+
// stores in format [filename, content]
52+
const gistContents: [string, string][] = [];
53+
const octokit = getOctokit(process.env.FIDDLE_CORE_GITHUB_TOKEN);
54+
const gist = await octokit.gists.get({ gist_id: gistId });
55+
56+
if (gist.data.files === undefined) {
57+
return;
58+
}
59+
60+
for (const [, data] of Object.entries(gist.data.files)) {
61+
const fileName = data?.filename;
62+
const content = data?.content;
63+
64+
if (fileName === undefined || content === undefined) {
65+
continue;
66+
}
67+
if (this.VALID_FILES.includes(fileName)) {
68+
gistContents.push([fileName, content]);
69+
}
70+
}
71+
72+
return this.fromEntries(gistContents);
3973
}
4074

4175
public async fromFolder(source: string): Promise<Fiddle> {
@@ -55,23 +89,43 @@ export class FiddleFactory {
5589
return new Fiddle(path.join(folder, 'main.js'), source);
5690
}
5791

58-
public async fromRepo(url: string, checkout = 'master'): Promise<Fiddle> {
92+
public async fromRepo(url: string) {
5993
const d = debug('fiddle-core:FiddleFactory:fromRepo');
60-
const folder = path.join(this.fiddles, hashString(url));
61-
d({ url, checkout, folder });
62-
63-
// get the repo
64-
if (!fs.existsSync(folder)) {
65-
d(`cloning "${url}" into "${folder}"`);
66-
const git = simpleGit();
67-
await git.clone(url, folder, { '--depth': 1 });
94+
const match = this.GITHUB_URL_REGEX.exec(url);
95+
if (match === null) {
96+
throw new Error(`Invalid github URL`);
97+
}
98+
// This has to be done because octokit expects an owner and repo
99+
// params to be passed instead of just HTTPs/SSH git link.
100+
const owner = match[4];
101+
const repo = match[5];
102+
const repoContents: [string, string][] = [];
103+
104+
d({ url, owner, repo });
105+
const octokit = getOctokit(process.env.FIDDLE_CORE_GITHUB_TOKEN);
106+
const folder = await octokit.repos.getContent({
107+
owner,
108+
repo,
109+
path: '.', // Look for in the base directory only
110+
});
111+
112+
if (!Array.isArray(folder.data)) {
113+
return;
68114
}
69115

70-
const git = simpleGit(folder);
71-
await git.checkout(checkout);
72-
await git.pull('origin', checkout);
116+
for (const file of folder.data) {
117+
if (!this.VALID_FILES.includes(file.name)) {
118+
continue;
119+
}
120+
121+
if (file.download_url) {
122+
const resp = await fetch(file.download_url);
123+
const content = await resp.text();
124+
repoContents.push([file.name, content]);
125+
}
126+
}
73127

74-
return new Fiddle(path.join(folder, 'main.js'), url);
128+
return this.fromEntries(repoContents);
75129
}
76130

77131
public async fromEntries(src: Iterable<[string, string]>): Promise<Fiddle> {

src/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import {
1919
compareVersions,
2020
} from './versions';
2121
import { runFromCommandLine } from './command-line';
22+
import { setGithubToken, removeGithubToken } from './utils/env';
2223

2324
export {
2425
BaseVersions,
@@ -41,6 +42,8 @@ export {
4142
TestResult,
4243
Versions,
4344
compareVersions,
45+
setGithubToken,
46+
removeGithubToken,
4447
runFromCommandLine,
4548
};
4649

src/utils/env.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
export function setGithubToken(githubToken: string) {
2+
process.env.FIDDLE_CORE_GITHUB_TOKEN = githubToken;
3+
}
4+
5+
export function removeGithubToken() {
6+
delete process.env.FIDDLE_CORE_GITHUB_TOKEN;
7+
}

src/utils/octokit.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { Octokit } from '@octokit/rest';
2+
3+
let _octo: Octokit;
4+
/**
5+
* Returns a loaded Octokit. If state is passed and authentication
6+
* is available, we'll token-authenticate.
7+
* @returns {Octokit}
8+
*/
9+
export function getOctokit(token?: string): Octokit {
10+
// It's possible to load Gists without being authenticated,
11+
// but we get better rate limits when authenticated.
12+
_octo =
13+
_octo || token
14+
? new Octokit({
15+
auth: token,
16+
})
17+
: new Octokit();
18+
19+
return _octo;
20+
}

tests/fiddle.test.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,15 @@ describe('FiddleFactory', () => {
9393
expect(fiddle).toBe(fiddleIn);
9494
});
9595

96-
it.todo('reads fiddles from git repositories');
96+
it('reads fiddles from git repositories', async () => {
97+
const repo = 'https://github.com/electron/electron-quick-start.git';
98+
const fiddle = await fiddleFactory.create(repo);
99+
expect(fiddle).toBeTruthy();
100+
expect(fs.existsSync(fiddle!.mainPath)).toBe(true);
101+
expect(path.basename(fiddle!.mainPath)).toBe('main.js');
102+
expect(path.dirname(path.dirname(fiddle!.mainPath))).toBe(fiddleDir);
103+
});
104+
97105
it.todo('refreshes the cache if given a previously-cached git repository');
98106

99107
it('returns undefined for unknown input', async () => {

yarn.lock

Lines changed: 1 addition & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -789,18 +789,6 @@
789789
"@types/yargs" "^16.0.0"
790790
chalk "^4.0.0"
791791

792-
"@kwsites/file-exists@^1.1.1":
793-
version "1.1.1"
794-
resolved "https://registry.yarnpkg.com/@kwsites/file-exists/-/file-exists-1.1.1.tgz#ad1efcac13e1987d8dbaf235ef3be5b0d96faa99"
795-
integrity sha512-m9/5YGR18lIwxSFDwfE3oA7bWuq9kdau6ugN4H2rJeyhFQZcG9AgSHkQtSD15a8WvTgfz9aikZMrKPHvbpqFiw==
796-
dependencies:
797-
debug "^4.1.1"
798-
799-
"@kwsites/promise-deferred@^1.1.1":
800-
version "1.1.1"
801-
resolved "https://registry.yarnpkg.com/@kwsites/promise-deferred/-/promise-deferred-1.1.1.tgz#8ace5259254426ccef57f3175bc64ed7095ed919"
802-
integrity sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw==
803-
804792
"@microsoft/[email protected]":
805793
version "7.15.3"
806794
resolved "https://registry.yarnpkg.com/@microsoft/api-extractor-model/-/api-extractor-model-7.15.3.tgz#cf76deeeb2733d974da678f530c2dbaceb18a065"
@@ -1119,7 +1107,7 @@
11191107
node-fetch "^2.6.7"
11201108
universal-user-agent "^6.0.0"
11211109

1122-
"@octokit/rest@^19.0.0":
1110+
"@octokit/rest@^19.0.0", "@octokit/rest@^19.0.4":
11231111
version "19.0.4"
11241112
resolved "https://registry.yarnpkg.com/@octokit/rest/-/rest-19.0.4.tgz#fd8bed1cefffa486e9ae46a9dc608ce81bcfcbdd"
11251113
integrity sha512-LwG668+6lE8zlSYOfwPj4FxWdv/qFXYBpv79TWIQEpBLKA9D/IMcWsF/U9RGpA3YqMVDiTxpgVpEW3zTFfPFTA==
@@ -6101,15 +6089,6 @@ signale@^1.2.1:
61016089
figures "^2.0.0"
61026090
pkg-conf "^2.1.0"
61036091

6104-
simple-git@^2.48.0:
6105-
version "2.48.0"
6106-
resolved "https://registry.yarnpkg.com/simple-git/-/simple-git-2.48.0.tgz#87c262dba8f84d7b96bb3a713e9e34701c1f6e3b"
6107-
integrity sha512-z4qtrRuaAFJS4PUd0g+xy7aN4y+RvEt/QTJpR184lhJguBA1S/LsVlvE/CM95RsYMOFJG3NGGDjqFCzKU19S/A==
6108-
dependencies:
6109-
"@kwsites/file-exists" "^1.1.1"
6110-
"@kwsites/promise-deferred" "^1.1.1"
6111-
debug "^4.3.2"
6112-
61136092
sisteransi@^1.0.5:
61146093
version "1.0.5"
61156094
resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed"

0 commit comments

Comments
 (0)