Skip to content

Commit

Permalink
test: add "git export" tests, polishing up the export code itself
Browse files Browse the repository at this point in the history
  • Loading branch information
senyai committed Apr 29, 2024
1 parent 4f298c7 commit 3622dfd
Show file tree
Hide file tree
Showing 4 changed files with 601 additions and 52 deletions.
110 changes: 58 additions & 52 deletions src/gitExport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ import {
Uri,
window,
} from 'vscode';
import { Octokit } from '@octokit/rest';
import { Repository } from './repository';
import { Distinct } from './openedRepository';
import { mkdir } from 'fs/promises';
import { Octokit } from '@octokit/rest';
import { RequestError } from '@octokit/request-error';
import type { Repository } from './repository';
import type { Distinct } from './openedRepository';

const GITHUB_AUTH_PROVIDER_ID = 'github';
// https://fossil-scm.org/home/doc/trunk/www/mirrortogithub.md says
Expand All @@ -32,38 +32,36 @@ export class Credentials {
disposables.push(
authentication.onDidChangeSessions(async e => {
if (e.provider.id === GITHUB_AUTH_PROVIDER_ID) {
this.octokit = await this.tryCreateOctokit();
await this.tryCreateOctokit();
}
})
);
}
if (!this.octokit) {
this.octokit = await this.tryCreateOctokit();
await this.tryCreateOctokit();
}
}

private async tryCreateOctokit(
/** @internal */ async tryCreateOctokit(
createIfNone: boolean = false
): Promise<Octokit | undefined> {
const session = (this.session = await authentication.getSession(
const session = await authentication.getSession(
GITHUB_AUTH_PROVIDER_ID,
SCOPES,
{ createIfNone }
));

return session
? new Octokit({
auth: session.accessToken,
})
: undefined;
);
if (session) {
this.octokit = new Octokit({
auth: session.accessToken,
});
this.session = session;
return this.octokit;
}
return;
}

async getOctokit(): Promise<Octokit> {
if (this.octokit) {
return this.octokit;
}
this.octokit = await this.tryCreateOctokit(true);
return this.octokit!;
return this.octokit ?? (await this.tryCreateOctokit(true))!;
}
}

Expand Down Expand Up @@ -93,25 +91,20 @@ export async function inputExportOptions(
disposables: Disposable[]
): Promise<GitExportOptions | undefined> {
// ask: exportParentPath (hardest part, no explicit vscode API for this)
let exportParentPath = await window.showSaveDialog({
title:
'Parent path for intermediate git repository ' +
'outside of fossil repository',
saveLabel: 'Select',
filters: {
Directories: [], // trying to select only directories
},
});
const exportParentPath = (
await window.showOpenDialog({
title:
'Parent path for intermediate git repository ' +
'outside of fossil repository',
openLabel: 'Select',
canSelectFiles: false,
canSelectFolders: true,
})
)?.at(0);

if (!exportParentPath) {
return;
}
if (exportParentPath.path.endsWith('.undefined')) {
// somewhat vscode bug
exportParentPath = exportParentPath.with({
path: exportParentPath.path.slice(0, -10),
});
}

// ask: repository name
const config = await repository.config(
Expand All @@ -123,6 +116,8 @@ export async function inputExportOptions(
prompt: 'The name of the new repository',
ignoreFocusOut: true,
value: config.get('short-project-name') || config.get('project-name'),
validateInput: text =>
/^\w+$/.test(text) ? '' : 'Must be a single word',
});
if (!name) {
return;
Expand Down Expand Up @@ -166,6 +161,16 @@ export async function inputExportOptions(
// github option was chosen
// so, we must authenticate
await credentials.initialize(disposables);
const session = credentials.session;
if (!session) {
await window.showErrorMessage(
`No github session available, fossil won't export ${(
credentials as any
).octokit!}`
);
return;
}

const octokit = await credentials.getOctokit();
const userInfo = await octokit.users.getAuthenticated();
const orgs = await octokit.orgs.listForAuthenticatedUser();
Expand Down Expand Up @@ -207,12 +212,12 @@ export async function inputExportOptions(
}

// ask: privacy
const publicItem: QuickPickItem = {
label: '$(globe) Public',
};
const privateItem: QuickPickItem = {
label: '$(lock) Private',
};
const publicItem: QuickPickItem = {
label: '$(globe) Public',
};
const selectedPrivacy = await window.showQuickPick(
[privateItem, publicItem],
{
Expand Down Expand Up @@ -268,7 +273,6 @@ export async function inputExportOptions(
}
}
// add token to url
const session = credentials.session!;
const remoteUri = Uri.parse(response.data.html_url) as AutoPushURISafe;
const remoteUriWithToken = remoteUri.with({
authority: `${session.account.label}:${session.accessToken}@${remoteUri.authority}`,
Expand All @@ -283,10 +287,10 @@ export async function exportGit(
): Promise<void> {
await window.withProgress(
{
title: `Creating $(github) repository ${options.url}`,
title: `Exporting git repository ${options.url}`,
location: ProgressLocation.Notification,
},
async (progress): Promise<any> => {
async (progress): Promise<void> => {
progress.report({
message: `Setting up fossil with ${options.url}`,
increment: 33,
Expand All @@ -295,29 +299,31 @@ export async function exportGit(
name: 'Fossil git export',
cwd: repository.root,
});
const terminalIsClosed = new Promise<void>(ready => {
const dis = window.onDidCloseTerminal(closedTerminal => {
if (closedTerminal === terminal) {
dis.dispose();
ready();
}
});
});
await mkdir(options.path, { recursive: true, mode: 0o700 });
terminal.sendText(
// space at the start to skip history
` fossil git export ${
options.path
} --mainbranch main --autopush ${options.urlUnsafe.toString()}`
);
terminal.show();
progress.report({
message:
'$(terminal) running export (manually close the terminal to finish)',
'Running export (manually close the terminal to finish)',
increment: 66,
});
await new Promise<void>(ready => {
const dis = window.onDidCloseTerminal(closedTerminal => {
if (closedTerminal === terminal) {
progress.report({
message: 'done',
increment: 100,
});
ready();
dis.dispose();
}
});
await terminalIsClosed;
progress.report({
message: 'done',
increment: 100,
});
}
);
Expand Down
5 changes: 5 additions & 0 deletions src/test/suite/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ import { OpenedRepository, ResourceStatus } from '../../openedRepository';
import { FossilResourceGroup } from '../../resourceGroups';
import { delay } from '../../util';

export type SinonStubT<T extends (...args: any) => any> = sinon.SinonStub<
Parameters<T>,
ReturnType<T>
>;

export async function cleanRoot(): Promise<void> {
/* c8 ignore next 5 */
if (!vscode.workspace.workspaceFolders) {
Expand Down
2 changes: 2 additions & 0 deletions src/test/suite/extension.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { PatchSuite, StageSuite, StashSuite, UpdateSuite } from './stateSuite';
import { RenameSuite } from './renameSuite';
import { BranchSuite } from './branchSuite';
import { RevertSuite } from './revertSuite';
import { GetExportSuite as GitExportSuite } from './gitExportSuite';

suite('Fossil.OpenedRepo', function (this: Suite) {
this.ctx.sandbox = sinon.createSandbox();
Expand Down Expand Up @@ -46,6 +47,7 @@ suite('Fossil.OpenedRepo', function (this: Suite) {
suite('FileSystem', FileSystemSuite);
suite('Diff', DiffSuite);
suite('Quality of Life', QualityOfLifeSuite);
suite('Git Export', GitExportSuite);

afterEach(() => {
this.ctx.sandbox.restore();
Expand Down
Loading

0 comments on commit 3622dfd

Please sign in to comment.