Git sync commit on Windows always shows all objects as unversioned (#2215)

This commit is contained in:
Opender Singh
2020-05-29 06:44:17 +12:00
committed by GitHub
parent bbc3103fe6
commit 040641f5fc
8 changed files with 225 additions and 141 deletions

View File

@@ -5,7 +5,14 @@ import path from 'path';
jest.mock('path');
describe.each(['win32', 'posix'])('Git-VCS using path.%s', type => {
beforeAll(() => path.__mockPath(type));
let fooTxt = '';
let barTxt = '';
beforeAll(() => {
path.__mockPath(type);
fooTxt = path.join(GIT_INSOMNIA_DIR, 'foo.txt');
barTxt = path.join(GIT_INSOMNIA_DIR, 'bar.txt');
});
afterAll(() => jest.restoreAllMocks());
beforeEach(setupDateMocks);
@@ -21,7 +28,8 @@ describe.each(['win32', 'posix'])('Git-VCS using path.%s', type => {
const files1 = await vcs.listFiles();
expect(files1).toEqual([]);
await fs.promises.writeFile('/foo.txt', 'bar');
// File does not exist in git index
await fs.promises.writeFile('foo.txt', 'bar');
const files2 = await vcs.listFiles();
expect(files2).toEqual([]);
});
@@ -29,8 +37,8 @@ describe.each(['win32', 'posix'])('Git-VCS using path.%s', type => {
it('stage and unstage file', async () => {
const fs = MemPlugin.createPlugin();
await fs.promises.mkdir(GIT_INSOMNIA_DIR);
await fs.promises.writeFile(`${GIT_INSOMNIA_DIR}/foo.txt`, 'foo');
await fs.promises.writeFile(`${GIT_INSOMNIA_DIR}/bar.txt`, 'bar');
await fs.promises.writeFile(fooTxt, 'foo');
await fs.promises.writeFile(barTxt, 'bar');
// Files outside namespace should be ignored
await fs.promises.writeFile('/other.txt', 'other');
@@ -39,16 +47,16 @@ describe.each(['win32', 'posix'])('Git-VCS using path.%s', type => {
await vcs.init(GIT_CLONE_DIR, fs);
await vcs.setAuthor('Karen Brown', 'karen@example.com');
expect(await vcs.status(`${GIT_INSOMNIA_DIR}/bar.txt`)).toBe('*added');
expect(await vcs.status(`${GIT_INSOMNIA_DIR}/foo.txt`)).toBe('*added');
expect(await vcs.status(barTxt)).toBe('*added');
expect(await vcs.status(fooTxt)).toBe('*added');
await vcs.add(`${GIT_INSOMNIA_DIR}/foo.txt`);
expect(await vcs.status(`${GIT_INSOMNIA_DIR}/bar.txt`)).toBe('*added');
expect(await vcs.status(`${GIT_INSOMNIA_DIR}/foo.txt`)).toBe('added');
await vcs.add(fooTxt);
expect(await vcs.status(barTxt)).toBe('*added');
expect(await vcs.status(fooTxt)).toBe('added');
await vcs.remove(`${GIT_INSOMNIA_DIR}/foo.txt`);
expect(await vcs.status(`${GIT_INSOMNIA_DIR}/bar.txt`)).toBe('*added');
expect(await vcs.status(`${GIT_INSOMNIA_DIR}/foo.txt`)).toBe('*added');
await vcs.remove(fooTxt);
expect(await vcs.status(barTxt)).toBe('*added');
expect(await vcs.status(fooTxt)).toBe('*added');
});
it('Returns empty log without first commit', async () => {
@@ -62,20 +70,20 @@ describe.each(['win32', 'posix'])('Git-VCS using path.%s', type => {
it('commit file', async () => {
const fs = MemPlugin.createPlugin();
await fs.promises.mkdir(`${GIT_INSOMNIA_DIR}`);
await fs.promises.writeFile(`${GIT_INSOMNIA_DIR}/foo.txt`, 'foo');
await fs.promises.writeFile(`${GIT_INSOMNIA_DIR}/bar.txt`, 'bar');
await fs.promises.mkdir(GIT_INSOMNIA_DIR);
await fs.promises.writeFile(fooTxt, 'foo');
await fs.promises.writeFile(barTxt, 'bar');
await fs.promises.writeFile('/other.txt', 'should be ignored');
await fs.promises.writeFile('other.txt', 'should be ignored');
const vcs = new GitVCS();
await vcs.init(GIT_CLONE_DIR, fs);
await vcs.setAuthor('Karen Brown', 'karen@example.com');
await vcs.add(`${GIT_INSOMNIA_DIR}/foo.txt`);
await vcs.add(fooTxt);
await vcs.commit('First commit!');
expect(await vcs.status(`${GIT_INSOMNIA_DIR}/bar.txt`)).toBe('*added');
expect(await vcs.status(`${GIT_INSOMNIA_DIR}/foo.txt`)).toBe('unmodified');
expect(await vcs.status(barTxt)).toBe('*added');
expect(await vcs.status(fooTxt)).toBe('unmodified');
expect(await vcs.log()).toEqual([
{
@@ -98,36 +106,36 @@ describe.each(['win32', 'posix'])('Git-VCS using path.%s', type => {
},
]);
await fs.promises.unlink(`${GIT_INSOMNIA_DIR}/foo.txt`);
expect(await vcs.status(`${GIT_INSOMNIA_DIR}/bar.txt`)).toBe('*added');
expect(await vcs.status(`${GIT_INSOMNIA_DIR}/foo.txt`)).toBe('*deleted');
await fs.promises.unlink(fooTxt);
expect(await vcs.status(barTxt)).toBe('*added');
expect(await vcs.status(fooTxt)).toBe('*deleted');
await vcs.remove(`${GIT_INSOMNIA_DIR}/foo.txt`);
expect(await vcs.status(`${GIT_INSOMNIA_DIR}/bar.txt`)).toBe('*added');
expect(await vcs.status(`${GIT_INSOMNIA_DIR}/foo.txt`)).toBe('deleted');
await vcs.remove(fooTxt);
expect(await vcs.status(barTxt)).toBe('*added');
expect(await vcs.status(fooTxt)).toBe('deleted');
await vcs.remove(`${GIT_INSOMNIA_DIR}/foo.txt`);
expect(await vcs.status(`${GIT_INSOMNIA_DIR}/bar.txt`)).toBe('*added');
expect(await vcs.status(`${GIT_INSOMNIA_DIR}/foo.txt`)).toBe('deleted');
await vcs.remove(fooTxt);
expect(await vcs.status(barTxt)).toBe('*added');
expect(await vcs.status(fooTxt)).toBe('deleted');
});
it('create branch', async () => {
const fs = MemPlugin.createPlugin();
await fs.promises.mkdir(`${GIT_INSOMNIA_DIR}`);
await fs.promises.writeFile(`${GIT_INSOMNIA_DIR}/foo.txt`, 'foo');
await fs.promises.writeFile(`${GIT_INSOMNIA_DIR}/bar.txt`, 'bar');
await fs.promises.mkdir(GIT_INSOMNIA_DIR);
await fs.promises.writeFile(fooTxt, 'foo');
await fs.promises.writeFile(barTxt, 'bar');
const vcs = new GitVCS();
await vcs.init(GIT_CLONE_DIR, fs);
await vcs.setAuthor('Karen Brown', 'karen@example.com');
await vcs.add(`${GIT_INSOMNIA_DIR}/foo.txt`);
await vcs.add(fooTxt);
await vcs.commit('First commit!');
expect((await vcs.log()).length).toBe(1);
await vcs.checkout('new-branch');
expect((await vcs.log()).length).toBe(1);
await vcs.add(`${GIT_INSOMNIA_DIR}/bar.txt`);
await vcs.add(barTxt);
await vcs.commit('Second commit!');
expect((await vcs.log()).length).toBe(2);
@@ -139,26 +147,27 @@ describe.each(['win32', 'posix'])('Git-VCS using path.%s', type => {
describe('readObjectFromTree()', () => {
it('reads an object from tree', async () => {
const fs = MemPlugin.createPlugin();
await fs.promises.mkdir(`${GIT_INSOMNIA_DIR}`);
await fs.promises.mkdir(`${GIT_INSOMNIA_DIR}/dir`);
await fs.promises.writeFile(`${GIT_INSOMNIA_DIR}/dir/foo.txt`, 'foo');
const dir = path.join(GIT_INSOMNIA_DIR, 'dir');
const dirFooTxt = path.join(dir, 'foo.txt');
await fs.promises.mkdir(GIT_INSOMNIA_DIR);
await fs.promises.mkdir(dir);
await fs.promises.writeFile(dirFooTxt, 'foo');
const vcs = new GitVCS();
await vcs.init(GIT_CLONE_DIR, fs);
await vcs.setAuthor('Karen Brown', 'karen@example.com');
await vcs.add(`${GIT_INSOMNIA_DIR}/dir/foo.txt`);
await vcs.add(dirFooTxt);
await vcs.commit('First');
await fs.promises.writeFile(`${GIT_INSOMNIA_DIR}/dir/foo.txt`, 'foo bar');
await vcs.add(`${GIT_INSOMNIA_DIR}/dir/foo.txt`);
await fs.promises.writeFile(dirFooTxt, 'foo bar');
await vcs.add(dirFooTxt);
await vcs.commit('Second');
const log = await vcs.log();
expect(await vcs.readObjFromTree(log[0].tree, `${GIT_INSOMNIA_DIR}/dir/foo.txt`)).toBe(
'foo bar',
);
expect(await vcs.readObjFromTree(log[1].tree, `${GIT_INSOMNIA_DIR}/dir/foo.txt`)).toBe('foo');
expect(await vcs.readObjFromTree(log[0].tree, dirFooTxt)).toBe('foo bar');
expect(await vcs.readObjFromTree(log[1].tree, dirFooTxt)).toBe('foo');
// Some extra checks
expect(await vcs.readObjFromTree(log[1].tree, 'missing')).toBe(null);

View File

@@ -9,68 +9,72 @@ describe.each(['win32', 'posix'])('Memlugin using path.%s', type => {
afterAll(() => jest.restoreAllMocks());
beforeEach(setupDateMocks);
const fooTxt = 'foo.txt';
const barTxt = 'bar.txt';
describe('readfile()', () => {
it('fails to read', async () => {
const p = new MemPlugin();
await assertAsyncError(p.readFile('/foo.txt'), 'ENOENT');
await assertAsyncError(p.readFile(fooTxt), 'ENOENT');
});
it('reads a file', async () => {
const p = new MemPlugin();
await p.writeFile('/foo.txt', 'Hello World!');
expect((await p.readFile('/foo.txt')).toString()).toBe('Hello World!');
await p.writeFile(fooTxt, 'Hello World!');
expect((await p.readFile(fooTxt)).toString()).toBe('Hello World!');
});
});
describe('writeFile()', () => {
it('fails to write over directory', async () => {
const p = new MemPlugin();
const dirName = 'foo';
await p.mkdir('/foo');
await assertAsyncError(p.writeFile('/foo', 'Hello World 2!'), 'EISDIR');
await p.mkdir(dirName);
await assertAsyncError(p.writeFile(dirName, 'Hello World 2!'), 'EISDIR');
});
it('overwrites file', async () => {
const p = new MemPlugin();
await p.writeFile('/foo.txt', 'Hello World!');
await p.writeFile('/foo.txt', 'Hello World 2!');
expect((await p.readFile('/foo.txt')).toString()).toBe('Hello World 2!');
await p.writeFile(fooTxt, 'Hello World!');
await p.writeFile(fooTxt, 'Hello World 2!');
expect((await p.readFile(fooTxt)).toString()).toBe('Hello World 2!');
});
it('flag "a" file', async () => {
const p = new MemPlugin();
await p.writeFile('/foo.txt', 'Hello World!', { flag: 'a' });
await p.writeFile('/foo.txt', 'xxx', { flag: 'a' });
expect((await p.readFile('/foo.txt')).toString()).toBe('Hello World!xxx');
await p.writeFile(fooTxt, 'Hello World!', { flag: 'a' });
await p.writeFile(fooTxt, 'xxx', { flag: 'a' });
expect((await p.readFile(fooTxt)).toString()).toBe('Hello World!xxx');
});
it('flags "ax" and "wx" fail if path exists', async () => {
const p = new MemPlugin();
await p.writeFile('/foo.txt', 'Hello World!');
await assertAsyncError(p.writeFile('/foo.txt', 'aaa', { flag: 'ax' }), 'EEXIST');
await assertAsyncError(p.writeFile('/foo.txt', 'aaa', { flag: 'wx' }), 'EEXIST');
await p.writeFile(fooTxt, 'Hello World!');
await assertAsyncError(p.writeFile(fooTxt, 'aaa', { flag: 'ax' }), 'EEXIST');
await assertAsyncError(p.writeFile(fooTxt, 'aaa', { flag: 'wx' }), 'EEXIST');
});
it('fails if flag "r"', async () => {
const p = new MemPlugin();
await assertAsyncError(p.writeFile('/foo.txt', 'aaa', { flag: 'r' }), 'EBADF');
await assertAsyncError(p.writeFile(fooTxt, 'aaa', { flag: 'r' }), 'EBADF');
});
it('fails if dir missing', async () => {
const p = new MemPlugin();
await assertAsyncError(p.writeFile('/foo.txt', 'aaa', { flag: 'r' }), 'EBADF');
await assertAsyncError(p.writeFile(fooTxt, 'aaa', { flag: 'r' }), 'EBADF');
});
it('works with flags', async () => {
const p = new MemPlugin();
await p.writeFile('/foo.txt', 'Hello World!', { flag: 'a' });
await p.writeFile('/foo.txt', 'xxx', { flag: 'a' });
expect((await p.readFile('/foo.txt')).toString()).toBe('Hello World!xxx');
await p.writeFile(fooTxt, 'Hello World!', { flag: 'a' });
await p.writeFile(fooTxt, 'xxx', { flag: 'a' });
expect((await p.readFile(fooTxt)).toString()).toBe('Hello World!xxx');
});
});
@@ -78,15 +82,15 @@ describe.each(['win32', 'posix'])('Memlugin using path.%s', type => {
it('unlinks file', async () => {
const p = new MemPlugin();
await p.writeFile('/foo.txt', 'xxx');
await p.unlink('/foo.txt');
await assertAsyncError(p.readFile('/foo.txt'), 'ENOENT');
await p.writeFile(fooTxt, 'xxx');
await p.unlink(fooTxt);
await assertAsyncError(p.readFile(fooTxt), 'ENOENT');
});
it('fails to unlinks missing file', async () => {
const p = new MemPlugin();
await assertAsyncError(p.unlink('/not/exist.txt'), 'ENOENT');
await assertAsyncError(p.unlink(path.join('not', 'exist.txt')), 'ENOENT');
});
});
@@ -98,81 +102,90 @@ describe.each(['win32', 'posix'])('Memlugin using path.%s', type => {
expect(await p.readdir(GIT_CLONE_DIR)).toEqual([]);
// Write a file and list it again
await p.writeFile('/foo.txt', 'Hello World!');
await p.writeFile('/bar.txt', 'Bar!');
await p.writeFile(fooTxt, 'Hello World!');
await p.writeFile(barTxt, 'Bar!');
expect(await p.readdir(GIT_CLONE_DIR)).toEqual(['bar.txt', 'foo.txt']);
});
it('errors on file', async () => {
const p = new MemPlugin();
await p.writeFile('/foo.txt', 'Bar!');
await assertAsyncError(p.readdir('/foo.txt'), 'ENOTDIR');
await p.writeFile(fooTxt, 'Bar!');
await assertAsyncError(p.readdir(fooTxt), 'ENOTDIR');
});
it('errors on missing directory', async () => {
const p = new MemPlugin();
await assertAsyncError(p.readdir('/invalid'), 'ENOENT');
await assertAsyncError(p.readdir(path.join('/', 'invalid')), 'ENOENT');
});
});
describe('mkdir()', () => {
const fooDir = 'foo';
const fooBarDir = path.join(fooDir, 'bar');
const cloneFooDir = path.join(GIT_CLONE_DIR, 'foo');
const cloneFooBarDir = path.join(GIT_CLONE_DIR, 'foo', 'bar');
const cloneFooBarBazDir = path.join(GIT_CLONE_DIR, 'foo', 'bar', 'baz');
it('creates directory', async () => {
const p = new MemPlugin();
await p.mkdir('/foo');
await p.mkdir('/foo/bar');
await p.mkdir(fooDir);
await p.mkdir(fooBarDir);
expect(await p.readdir(GIT_CLONE_DIR)).toEqual(['foo']);
expect(await p.readdir(`${GIT_CLONE_DIR}/foo`)).toEqual(['bar']);
expect(await p.readdir(cloneFooDir)).toEqual(['bar']);
});
it('creates directory non-recursively', async () => {
const p = new MemPlugin();
await p.mkdir(`${GIT_CLONE_DIR}/foo`, { recursive: true });
await p.mkdir(`${GIT_CLONE_DIR}/foo/bar`);
expect(await p.readdir(`${GIT_CLONE_DIR}/foo/bar`)).toEqual([]);
await p.mkdir(cloneFooDir, { recursive: true });
await p.mkdir(cloneFooBarDir);
expect(await p.readdir(cloneFooBarDir)).toEqual([]);
});
it('creates directory recursively', async () => {
const p = new MemPlugin();
await p.mkdir(`${GIT_CLONE_DIR}/foo/bar/baz`, { recursive: true });
expect(await p.readdir(`${GIT_CLONE_DIR}/foo/bar/baz`)).toEqual([]);
await p.mkdir(cloneFooBarBazDir, { recursive: true });
expect(await p.readdir(cloneFooBarBazDir)).toEqual([]);
});
it('fails to create if no parent', async () => {
const p = new MemPlugin();
await assertAsyncError(p.mkdir(`${GIT_CLONE_DIR}/foo/bar/baz`), 'ENOENT');
await assertAsyncError(p.mkdir(cloneFooBarBazDir), 'ENOENT');
});
});
describe('rmdir()', () => {
const abDir = path.join('a', 'b');
const abcDir = path.join('a', 'b', 'c');
it('removes a dir', async () => {
const p = new MemPlugin();
await p.mkdir('/a/b/c', { recursive: true });
expect(await p.readdir('/a/b')).toEqual(['c']);
await p.rmdir('/a/b/c');
expect(await p.readdir('/a/b')).toEqual([]);
await p.mkdir(abcDir, { recursive: true });
expect(await p.readdir(abDir)).toEqual(['c']);
await p.rmdir(abcDir);
expect(await p.readdir(abDir)).toEqual([]);
});
it('fails on non-empty dir', async () => {
const p = new MemPlugin();
await p.mkdir('/a/b/c', { recursive: true });
await p.writeFile('/a/b/c/foo.txt', 'xxx');
await p.mkdir(abcDir, { recursive: true });
await p.writeFile(path.join(abcDir, 'foo.txt'), 'xxx');
await assertAsyncError(p.rmdir('/a/b'), 'ENOTEMPTY');
await assertAsyncError(p.rmdir('/a/b/c'), 'ENOTEMPTY');
await assertAsyncError(p.rmdir(abDir), 'ENOTEMPTY');
await assertAsyncError(p.rmdir(abcDir), 'ENOTEMPTY');
});
it('fails on file', async () => {
const p = new MemPlugin();
await p.writeFile('/foo.txt', 'xxx');
await assertAsyncError(p.rmdir('/foo.txt'), 'ENOTDIR');
await p.writeFile(fooTxt, 'xxx');
await assertAsyncError(p.rmdir(fooTxt), 'ENOTDIR');
});
});
@@ -202,8 +215,8 @@ describe.each(['win32', 'posix'])('Memlugin using path.%s', type => {
it('stats file', async () => {
const p = new MemPlugin();
await p.writeFile('/foo.txt', 'xxx');
const stat = await p.stat('/foo.txt');
await p.writeFile(fooTxt, 'xxx');
const stat = await p.stat(fooTxt);
expect(stat).toEqual({
ctimeMs: 1000000000001,
@@ -224,7 +237,7 @@ describe.each(['win32', 'posix'])('Memlugin using path.%s', type => {
it('fails to stat missing', async () => {
const p = new MemPlugin();
await assertAsyncError(p.stat('/bar.txt'), 'ENOENT');
await assertAsyncError(p.stat(barTxt), 'ENOENT');
});
});
});

View File

@@ -30,56 +30,62 @@ describe.each(['win32', 'posix'])('NeDBPlugin using path.%s', type => {
describe('readdir()', () => {
it('reads model IDs from model type folders', async () => {
const pNeDB = new NeDBPlugin('wrk_1');
const reqDir = path.join(GIT_INSOMNIA_DIR, models.request.type);
const wrkDir = path.join(GIT_INSOMNIA_DIR, models.workspace.type);
expect(await pNeDB.readdir(GIT_CLONE_DIR)).toEqual([GIT_INSOMNIA_DIR_NAME]);
expect(await pNeDB.readdir(GIT_INSOMNIA_DIR)).toEqual([
'ApiSpec',
'Environment',
'Request',
'RequestGroup',
'Workspace',
models.apiSpec.type,
models.environment.type,
models.request.type,
models.requestGroup.type,
models.workspace.type,
]);
expect(await pNeDB.readdir(`${GIT_INSOMNIA_DIR}/Request`)).toEqual([
'req_1.yml',
'req_2.yml',
]);
expect(await pNeDB.readdir(`${GIT_INSOMNIA_DIR}/Workspace`)).toEqual(['wrk_1.yml']);
expect(await pNeDB.readdir(reqDir)).toEqual(['req_1.yml', 'req_2.yml']);
expect(await pNeDB.readdir(wrkDir)).toEqual(['wrk_1.yml']);
});
});
describe('readFile()', () => {
it('reads file from model/id folders', async () => {
const wrk1Yml = path.join(GIT_INSOMNIA_DIR, models.workspace.type, 'wrk_1.yml');
const req1Yml = path.join(GIT_INSOMNIA_DIR, models.request.type, 'req_1.yml');
const reqXYml = path.join(GIT_INSOMNIA_DIR, models.request.type, 'req_x.yml');
const pNeDB = new NeDBPlugin('wrk_1');
expect(
YAML.parse(await pNeDB.readFile(`${GIT_INSOMNIA_DIR}/Workspace/wrk_1.yml`, 'utf8')),
).toEqual(expect.objectContaining({ _id: 'wrk_1', parentId: null }));
expect(YAML.parse(await pNeDB.readFile(wrk1Yml, 'utf8'))).toEqual(
expect.objectContaining({ _id: 'wrk_1', parentId: null }),
);
expect(
YAML.parse(await pNeDB.readFile(`${GIT_INSOMNIA_DIR}/Request/req_1.yml`, 'utf8')),
).toEqual(expect.objectContaining({ _id: 'req_1', parentId: 'wrk_1' }));
expect(YAML.parse(await pNeDB.readFile(req1Yml, 'utf8'))).toEqual(
expect.objectContaining({ _id: 'req_1', parentId: 'wrk_1' }),
);
await assertAsyncError(pNeDB.readFile(`${GIT_INSOMNIA_DIR}/Request/req_x.yml`));
await assertAsyncError(pNeDB.readFile(reqXYml));
});
});
describe('stat()', () => {
it('stats a dir', async () => {
// Assemble
const reqDir = path.join(GIT_INSOMNIA_DIR, models.request.type);
const wrkDir = path.join(GIT_INSOMNIA_DIR, models.workspace.type);
const dirType = expect.objectContaining({ type: 'dir' });
const fileType = expect.objectContaining({ type: 'file' });
// Act
const pNeDB = new NeDBPlugin('wrk_1');
expect(await pNeDB.stat(GIT_CLONE_DIR)).toEqual(expect.objectContaining({ type: 'dir' }));
expect(await pNeDB.stat(`${GIT_INSOMNIA_DIR}`)).toEqual(
expect.objectContaining({ type: 'dir' }),
);
expect(await pNeDB.stat(`${GIT_INSOMNIA_DIR}/Workspace/wrk_1.yml`)).toEqual(
expect.objectContaining({ type: 'file' }),
);
expect(await pNeDB.stat(`${GIT_INSOMNIA_DIR}/Request`)).toEqual(
expect.objectContaining({ type: 'dir' }),
);
expect(await pNeDB.stat(`${GIT_INSOMNIA_DIR}/Request/req_2.yml`)).toEqual(
expect.objectContaining({ type: 'file' }),
);
// Assert
expect(await pNeDB.stat(GIT_CLONE_DIR)).toEqual(dirType);
expect(await pNeDB.stat(GIT_INSOMNIA_DIR)).toEqual(dirType);
expect(await pNeDB.stat(reqDir)).toEqual(dirType);
expect(await pNeDB.stat(path.join(wrkDir, 'wrk_1.yml'))).toEqual(fileType);
expect(await pNeDB.stat(path.join(reqDir, 'req_2.yml'))).toEqual(fileType);
});
});
@@ -90,8 +96,8 @@ describe.each(['win32', 'posix'])('NeDBPlugin using path.%s', type => {
const workspaceId = 'wrk_1';
const pNeDB = new NeDBPlugin(workspaceId);
const env = { _id: 'env_1', type: 'Environment', parentId: workspaceId };
const filePath = `anotherDir/${env.type}/${env._id}.yml`;
const env = { _id: 'env_1', type: models.environment.type, parentId: workspaceId };
const filePath = path.join('anotherDir', env.type, `${env._id}.yml`);
// Act
await pNeDB.writeFile(filePath, YAML.stringify(env));
@@ -109,8 +115,8 @@ describe.each(['win32', 'posix'])('NeDBPlugin using path.%s', type => {
const pNeDB = new NeDBPlugin(workspaceId);
const upsertSpy = jest.spyOn(db, 'upsert');
const env = { _id: 'env_1', type: 'Environment', parentId: workspaceId };
const filePath = `${GIT_INSOMNIA_DIR}/${env.type}/${env._id}.yml`;
const env = { _id: 'env_1', type: models.environment.type, parentId: workspaceId };
const filePath = path.join(GIT_INSOMNIA_DIR, env.type, `${env._id}.yml`);
// Act
await pNeDB.writeFile(filePath, YAML.stringify(env));
@@ -128,8 +134,8 @@ describe.each(['win32', 'posix'])('NeDBPlugin using path.%s', type => {
const workspaceId = 'wrk_1';
const pNeDB = new NeDBPlugin(workspaceId);
const env = { _id: 'env_1', type: 'Environment', parentId: workspaceId };
const filePath = `${GIT_INSOMNIA_DIR}/${env.type}/env_2.yml`;
const env = { _id: 'env_1', type: models.environment.type, parentId: workspaceId };
const filePath = path.join(GIT_INSOMNIA_DIR, env.type, `env_2.yml`);
// Act
const promiseResult = pNeDB.writeFile(filePath, YAML.stringify(env));
@@ -145,8 +151,8 @@ describe.each(['win32', 'posix'])('NeDBPlugin using path.%s', type => {
const workspaceId = 'wrk_1';
const pNeDB = new NeDBPlugin(workspaceId);
const env = { _id: 'env_1', type: 'Environment', parentId: workspaceId };
const filePath = `${GIT_INSOMNIA_DIR}/Request/${env._id}.yml`;
const env = { _id: 'env_1', type: models.environment.type, parentId: workspaceId };
const filePath = path.join(GIT_INSOMNIA_DIR, models.request.type, `${env._id}.yml`);
// Act
const promiseResult = pNeDB.writeFile(filePath, YAML.stringify(env));
@@ -165,7 +171,6 @@ describe.each(['win32', 'posix'])('NeDBPlugin using path.%s', type => {
const promiseResult = pNeDB.mkdir('', '');
// Assert
await expect(promiseResult).rejects.toThrowError('NeDBPlugin is not writable');
});
});

View File

@@ -0,0 +1,29 @@
// @flow
import path from 'path';
import { convertToOsSep, convertToPosixSep } from '../path-sep';
jest.mock('path');
describe('convertToPosixSep()', () => {
it('should handle empty string', () => {
expect(convertToPosixSep('')).toBe('');
});
it.each(['win32', 'posix'])('should convert separator from %s to posix', type => {
const input = path[type].join('a', 'b', 'c');
const posix = path.posix.join('a', 'b', 'c');
expect(convertToPosixSep(input)).toBe(posix);
});
});
describe.each(['win32', 'posix'])('convertToOsSep() where os is %s', osType => {
beforeAll(() => path.__mockPath(osType));
afterAll(() => jest.restoreAllMocks());
it.each(['win32', 'posix'])(`should convert separators from %s to ${osType}`, inputType => {
const input = path[inputType].join('a', 'b', 'c');
const output = path[osType].join('a', 'b', 'c');
expect(convertToOsSep(input)).toBe(output);
});
});

View File

@@ -2,6 +2,7 @@
import * as git from 'isomorphic-git';
import { trackEvent } from '../../common/analytics';
import { httpPlugin } from './http';
import { convertToOsSep, convertToPosixSep } from './path-sep';
import path from 'path';
export type GitAuthor = {|
@@ -97,7 +98,8 @@ export default class GitVCS {
async listFiles(): Promise<Array<string>> {
console.log('[git] List files');
return git.listFiles({ ...this._baseOpts });
const files = await git.listFiles({ ...this._baseOpts });
return files.map(convertToOsSep);
}
async getBranch(): Promise<string> {
@@ -129,15 +131,23 @@ export default class GitVCS {
}
async status(filepath: string) {
return git.status({ ...this._baseOpts, filepath });
return git.status({
...this._baseOpts,
filepath: convertToPosixSep(filepath),
});
}
async add(relPath: string): Promise<void> {
relPath = convertToPosixSep(relPath);
console.log(`[git] Add ${relPath}`);
return git.add({ ...this._baseOpts, filepath: relPath });
return git.add({
...this._baseOpts,
filepath: relPath,
});
}
async remove(relPath: string): Promise<void> {
relPath = convertToPosixSep(relPath);
console.log(`[git] Remove relPath=${relPath}`);
return git.remove({ ...this._baseOpts, filepath: relPath });
}
@@ -312,7 +322,7 @@ export default class GitVCS {
const obj = await git.readObject({
...this._baseOpts,
oid: treeOid,
filepath: objPath,
filepath: convertToPosixSep(objPath),
encoding: 'utf8',
});

View File

@@ -172,7 +172,7 @@ export default class NeDBPlugin {
type: 'file',
mode: 0o777,
size: fileBuff.length,
ino: doc._id,
ino: doc._id, // should be number instead of string https://nodejs.org/api/fs.html#fs_stats_ino I think flow should have detected this
mtimeMs: doc.modified,
});
} else {

View File

@@ -0,0 +1,19 @@
// @flow
import path from 'path';
const win32SepRegex = /\\/g;
const posixSepRegex = /\//g;
export function convertToPosixSep(filePath: string) {
return filePath.replace(win32SepRegex, path.posix.sep);
}
export function convertToOsSep(filePath: string) {
// is windows, so convert posix sep to windows sep
if (path.sep === path.win32.sep) {
return filePath.replace(posixSepRegex, path.win32.sep);
}
// is posix, so convert win32 sep to posix sep
return filePath.replace(win32SepRegex, path.posix.sep);
}

View File

@@ -170,10 +170,9 @@ class GitStagingModal extends React.PureComponent<Props, State> {
this.statusNames = {};
for (const doc of docs) {
this.statusNames[path.join(GIT_INSOMNIA_DIR_NAME, doc.type, `${doc._id}.json`)] =
(doc: any).name || '';
this.statusNames[path.join(GIT_INSOMNIA_DIR_NAME, doc.type, `${doc._id}.yml`)] =
(doc: any).name || '';
const name = (doc.type === models.apiSpec.type && doc.fileName) || doc.name || '';
this.statusNames[path.join(GIT_INSOMNIA_DIR_NAME, doc.type, `${doc._id}.json`)] = name;
this.statusNames[path.join(GIT_INSOMNIA_DIR_NAME, doc.type, `${doc._id}.yml`)] = name;
}
// Create status items