@mieweb/wikigdrive
Version:
Google Drive to MarkDown synchronization
415 lines (336 loc) • 15 kB
text/typescript
import fs from 'node:fs';
import path from 'node:path';
import {execSync} from 'node:child_process';
import winston from 'winston';
// eslint-disable-next-line import/no-unresolved
import {assertStrictEquals} from 'asserts';
import {GitScanner} from '../../src/git/GitScanner.ts';
import {createTmpDir} from '../utils.ts';
import {instrumentLogger} from '../../src/utils/logger/logger.ts';
const COMMITER1 = {
name: 'John', email: 'john@example.tld'
};
const COMMITER2 = {
name: 'Bob', email: 'bob@example.tld'
};
const logger = winston.createLogger({
level: 'debug',
defaultMeta: {},
transports: [
new winston.transports.Console()
]
});
instrumentLogger(logger);
Deno.test('test clone', async () => {
// t.timeout(5000);
const localRepoDir: string = createTmpDir();
const githubRepoDir: string = createTmpDir();
const secondRepoDir: string = createTmpDir();
execSync(`git init -b main --bare ${githubRepoDir}`);
try {
const scannerLocal = new GitScanner(logger, localRepoDir, COMMITER1.email);
await scannerLocal.initialize();
fs.writeFileSync(path.join(localRepoDir, 'file1.txt'), 'Initial content');
{
const changes = await scannerLocal.changes();
assertStrictEquals(2, (await scannerLocal.changes()).length);
await scannerLocal.commit('First commit', changes.map(change => change.path), COMMITER1);
}
{
const changes = await scannerLocal.changes();
assertStrictEquals(0, changes.length);
}
await scannerLocal.setRemoteUrl(githubRepoDir);
await scannerLocal.pushBranch('main');
////
const scannerSecond = new GitScanner(logger, secondRepoDir, COMMITER2.email);
await scannerSecond.initialize();
fs.unlinkSync(secondRepoDir + '/.gitignore');
await scannerSecond.setRemoteUrl(githubRepoDir);
await scannerSecond.pullBranch('main');
{
const files = fs.readdirSync(scannerSecond.rootPath);
assertStrictEquals(3, files.length);
assertStrictEquals(true, files.includes('.git'));
assertStrictEquals(true, files.includes('.gitignore'));
assertStrictEquals(true, files.includes('file1.txt'));
}
const headCommit = await scannerLocal.getBranchCommit('HEAD');
const masterCommit = await scannerLocal.getBranchCommit('main');
const remoteCommit = await scannerLocal.getBranchCommit('refs/remotes/origin/main');
assertStrictEquals(headCommit, masterCommit);
assertStrictEquals(headCommit, remoteCommit);
} finally {
fs.rmSync(localRepoDir, { recursive: true, force: true });
fs.rmSync(githubRepoDir, { recursive: true, force: true });
fs.rmSync(secondRepoDir, { recursive: true, force: true });
}
});
Deno.test('test fast forward', async () => {
// t.timeout(5000);
const localRepoDir: string = createTmpDir();
const githubRepoDir: string = createTmpDir();
const secondRepoDir: string = createTmpDir();
execSync(`git init -b main --bare ${githubRepoDir}`);
try {
const scannerLocal = new GitScanner(logger, localRepoDir, COMMITER1.email);
await scannerLocal.initialize();
{
fs.writeFileSync(path.join(localRepoDir, 'file1.txt'), 'Initial content');
const changes = await scannerLocal.changes();
assertStrictEquals(2, (await scannerLocal.changes()).length);
await scannerLocal.commit('First commit', changes.map(change => change.path), COMMITER1);
}
{
const changes = await scannerLocal.changes();
assertStrictEquals(0, changes.length);
}
await scannerLocal.setRemoteUrl(githubRepoDir);
await scannerLocal.pushBranch('main');
////
const scannerSecond = new GitScanner(logger, secondRepoDir, COMMITER2.email);
await scannerSecond.initialize();
fs.unlinkSync(secondRepoDir + '/.gitignore');
await scannerSecond.setRemoteUrl(githubRepoDir);
await scannerSecond.pullBranch('main');
{
fs.writeFileSync(path.join(secondRepoDir, 'file1.txt'), 'Change on second repo');
const changes = await scannerSecond.changes();
assertStrictEquals(1, (await scannerSecond.changes()).length);
await scannerSecond.commit('Change on second repo', changes.map(change => change.path), COMMITER2);
await scannerSecond.pushBranch('main');
}
await scannerLocal.pullBranch('main');
{
// const history = await scannerLocal.history('');
// const files = fs.readdirSync(scannerLocal.rootPath);
/*
assertStrictEquals(3, files.length);
assertStrictEquals(true, files.includes('.git'));
assertStrictEquals(true, files.includes('.gitignore'));
assertStrictEquals(true, files.includes('file1.txt'));
*/
}
const headCommit = await scannerLocal.getBranchCommit('HEAD');
const masterCommit = await scannerLocal.getBranchCommit('main');
const remoteCommit = await scannerLocal.getBranchCommit('refs/remotes/origin/main');
assertStrictEquals(headCommit, masterCommit);
assertStrictEquals(headCommit, remoteCommit);
} finally {
fs.rmSync(localRepoDir, { recursive: true, force: true });
fs.rmSync(githubRepoDir, { recursive: true, force: true });
fs.rmSync(secondRepoDir, { recursive: true, force: true });
}
});
Deno.test('test local fast forward', async () => {
// t.timeout(5000);
const localRepoDir: string = createTmpDir();
const githubRepoDir: string = createTmpDir();
const secondRepoDir: string = createTmpDir();
execSync(`git init -b main --bare ${githubRepoDir}`);
try {
const scannerLocal = new GitScanner(logger, localRepoDir, COMMITER1.email);
await scannerLocal.initialize();
{
fs.writeFileSync(path.join(localRepoDir, 'file1.txt'), 'Initial content');
const changes = await scannerLocal.changes();
assertStrictEquals(2, (await scannerLocal.changes()).length);
await scannerLocal.commit('First commit', changes.map(change => change.path), COMMITER1);
}
{
const changes = await scannerLocal.changes();
assertStrictEquals(0, changes.length);
}
await scannerLocal.setRemoteUrl(githubRepoDir);
await scannerLocal.pushBranch('main');
const scannerSecond = new GitScanner(logger, secondRepoDir, COMMITER2.email);
await scannerSecond.initialize();
fs.unlinkSync(secondRepoDir + '/.gitignore');
await scannerSecond.setRemoteUrl(githubRepoDir);
await scannerSecond.pullBranch('main');
{
fs.writeFileSync(path.join(localRepoDir, 'file1.txt'), 'Change on local repo');
const changes = await scannerLocal.changes();
assertStrictEquals(1, (await scannerLocal.changes()).length);
await scannerLocal.commit('Change on local repo', changes.map(change => change.path), COMMITER1);
await scannerLocal.pushBranch('main');
}
await scannerSecond.pullBranch('main');
{
// const history = await scannerSecond.history('');
// const files = fs.readdirSync(scannerSecond.rootPath);
/*
assertStrictEquals(3, files.length);
assertStrictEquals(true, files.includes('.git'));
assertStrictEquals(true, files.includes('.gitignore'));
assertStrictEquals(true, files.includes('file1.txt'));
*/
}
const headCommit = await scannerSecond.getBranchCommit('HEAD');
const masterCommit = await scannerSecond.getBranchCommit('main');
const remoteCommit = await scannerSecond.getBranchCommit('refs/remotes/origin/main');
assertStrictEquals(headCommit, masterCommit);
assertStrictEquals(headCommit, remoteCommit);
} finally {
fs.rmSync(localRepoDir, { recursive: true, force: true });
fs.rmSync(githubRepoDir, { recursive: true, force: true });
fs.rmSync(secondRepoDir, { recursive: true, force: true });
}
});
Deno.test('test non conflict', async () => {
// t.timeout(5000);
const localRepoDir: string = createTmpDir();
const githubRepoDir: string = createTmpDir();
const secondRepoDir: string = createTmpDir();
execSync(`git init -b main --bare ${githubRepoDir}`);
try {
const scannerLocal = new GitScanner(logger, localRepoDir, COMMITER1.email);
await scannerLocal.initialize();
{
fs.writeFileSync(path.join(localRepoDir, 'file1.txt'), 'Initial content');
const changes = await scannerLocal.changes();
assertStrictEquals(2, (await scannerLocal.changes()).length);
await scannerLocal.commit('First commit', changes.map(change => change.path), COMMITER1);
}
{
const changes = await scannerLocal.changes();
assertStrictEquals(0, changes.length);
}
await scannerLocal.setRemoteUrl(githubRepoDir);
await scannerLocal.pushBranch('main');
////
const scannerSecond = new GitScanner(logger, secondRepoDir, COMMITER2.email);
await scannerSecond.initialize();
fs.unlinkSync(secondRepoDir + '/.gitignore');
await scannerSecond.setRemoteUrl(githubRepoDir);
await scannerSecond.pullBranch('main');
{
fs.writeFileSync(path.join(secondRepoDir, 'file2.txt'), 'Change on second repo');
const changes = await scannerSecond.changes();
assertStrictEquals(1, (await scannerSecond.changes()).length);
await scannerSecond.commit('Change on second repo', changes.map(change => change.path), COMMITER2);
logger.info('Push second');
await scannerSecond.pushBranch('main');
logger.info('Pushed second');
}
{
const history = await scannerSecond.history('');
assertStrictEquals(2, history.length);
const files = fs.readdirSync(scannerSecond.rootPath);
assertStrictEquals(4, files.length);
assertStrictEquals(true, files.includes('.git'));
assertStrictEquals(true, files.includes('.gitignore'));
assertStrictEquals(true, files.includes('file1.txt'));
assertStrictEquals(true, files.includes('file2.txt'));
}
{
fs.writeFileSync(path.join(localRepoDir, 'file1.txt'), 'Change on local repo');
const changes = await scannerLocal.changes();
assertStrictEquals(1, (await scannerLocal.changes()).length);
await scannerLocal.commit('Change on local repo', changes.map(change => change.path), COMMITER1);
logger.info('Push local');
await scannerLocal.pushBranch('main');
logger.info('Pushed local');
}
await scannerSecond.pullBranch('main');
{
const history = await scannerSecond.history('');
assertStrictEquals(3, history.length);
const files = fs.readdirSync(scannerSecond.rootPath);
assertStrictEquals(4, files.length);
assertStrictEquals(true, files.includes('.git'));
assertStrictEquals(true, files.includes('.gitignore'));
assertStrictEquals(true, files.includes('file1.txt'));
assertStrictEquals(true, files.includes('file2.txt'));
}
const headCommit = await scannerSecond.getBranchCommit('HEAD');
const masterCommit = await scannerSecond.getBranchCommit('main');
const remoteCommit = await scannerSecond.getBranchCommit('refs/remotes/origin/main');
assertStrictEquals(headCommit, masterCommit);
assertStrictEquals(headCommit, remoteCommit);
} finally {
// fs.rmSync(localRepoDir, { recursive: true, force: true });
// fs.rmSync(githubRepoDir, { recursive: true, force: true });
// fs.rmSync(secondRepoDir, { recursive: true, force: true });
}
});
Deno.test('test conflict', async () => {
// t.timeout(5000);
const localRepoDir: string = createTmpDir();
const githubRepoDir: string = createTmpDir();
const secondRepoDir: string = createTmpDir();
execSync(`git init -b main --bare ${githubRepoDir}`);
try {
const scannerLocal = new GitScanner(logger, localRepoDir, COMMITER1.email);
await scannerLocal.initialize();
{
fs.writeFileSync(path.join(localRepoDir, 'file1.txt'), 'Initial content');
const changes = await scannerLocal.changes();
assertStrictEquals(2, (await scannerLocal.changes()).length);
await scannerLocal.commit('First commit', changes.map(change => change.path), COMMITER1);
}
{
const changes = await scannerLocal.changes();
assertStrictEquals(0, changes.length);
}
await scannerLocal.setRemoteUrl(githubRepoDir);
await scannerLocal.pushBranch('main');
////
const scannerSecond = new GitScanner(logger, secondRepoDir, COMMITER2.email);
await scannerSecond.initialize();
fs.unlinkSync(secondRepoDir + '/.gitignore');
await scannerSecond.setRemoteUrl(githubRepoDir);
await scannerSecond.pullBranch('main');
{
fs.writeFileSync(path.join(secondRepoDir, 'file1.txt'), 'Change on second repo');
const changes = await scannerSecond.changes();
assertStrictEquals(1, (await scannerSecond.changes()).length);
await scannerSecond.commit('Change on second repo', changes.map(change => change.path), COMMITER2);
await scannerSecond.pushBranch('main');
}
{
fs.writeFileSync(path.join(localRepoDir, 'file1.txt'), 'Change on local repo');
const changes = await scannerLocal.changes();
assertStrictEquals(1, (await scannerLocal.changes()).length);
await scannerLocal.commit('Change on local repo', changes.map(change => change.path), COMMITER1);
try {
await scannerLocal.pushBranch('main');
assertStrictEquals(true, false, 'Should fail because of conflict');
} catch (err) {
if (err.message.indexOf('conflict') === -1) {
console.error(err);
t.fail(err);
}
assertStrictEquals(true, err.message.indexOf('conflict') > -1);
}
}
await scannerLocal.resetToRemote('main');
await scannerLocal.pushBranch('main');
{
const headCommit = await scannerLocal.getBranchCommit('HEAD');
const masterCommit = await scannerLocal.getBranchCommit('main');
const remoteCommit = await scannerLocal.getBranchCommit('refs/remotes/origin/main');
assertStrictEquals(headCommit, masterCommit);
assertStrictEquals(headCommit, remoteCommit);
}
{
const history = await scannerLocal.history('');
assertStrictEquals(2, history.length);
assertStrictEquals('Change on second repo', history[0].message);
const files = fs.readdirSync(scannerLocal.rootPath);
assertStrictEquals(3, files.length);
assertStrictEquals(true, files.includes('.git'));
assertStrictEquals(true, files.includes('.gitignore'));
assertStrictEquals(true, files.includes('file1.txt'));
}
const headCommit = await scannerSecond.getBranchCommit('HEAD');
const masterCommit = await scannerSecond.getBranchCommit('main');
const remoteCommit = await scannerSecond.getBranchCommit('refs/remotes/origin/main');
assertStrictEquals(headCommit, masterCommit);
assertStrictEquals(headCommit, remoteCommit);
} finally {
fs.rmSync(localRepoDir, { recursive: true, force: true });
fs.rmSync(githubRepoDir, { recursive: true, force: true });
fs.rmSync(secondRepoDir, { recursive: true, force: true });
}
});