fixed the rest of the concerns, refactored portions of the gitGraphParser test to handle async actions

This commit is contained in:
Austin Fulbright
2024-08-05 13:53:51 -04:00
parent 9ed38ccf3a
commit 2a38d46fd9
4 changed files with 378 additions and 447 deletions

View File

@@ -44,7 +44,6 @@ function getID() {
return random({ length: 7 }); return random({ length: 7 });
} }
/** /**
* @param list - list of items * @param list - list of items
* @param fn - function to get the key * @param fn - function to get the key
@@ -88,7 +87,7 @@ export const commit = function (msg: string, id: string, type: number, tags?: st
msg = common.sanitizeText(msg, config); msg = common.sanitizeText(msg, config);
tags = tags?.map((tag) => common.sanitizeText(tag, config)); tags = tags?.map((tag) => common.sanitizeText(tag, config));
const newCommit: Commit = { const newCommit: Commit = {
id: id ? id : state.records.seq + '-' + getId(), id: id ? id : state.records.seq + '-' + getID(),
message: msg, message: msg,
seq: state.records.seq++, seq: state.records.seq++,
type: type ?? commitType.NORMAL, type: type ?? commitType.NORMAL,
@@ -123,9 +122,10 @@ export const merge = (
overrideType?: number, overrideType?: number,
customTags?: string[] customTags?: string[]
): void => { ): void => {
otherBranch = common.sanitizeText(otherBranch, getConfig()); const config = getConfig();
otherBranch = common.sanitizeText(otherBranch, config);
if (customId) { if (customId) {
customId = common.sanitizeText(customId, getConfig()); customId = common.sanitizeText(customId, config);
} }
const currentBranchCheck: string | null | undefined = state.records.branches.get( const currentBranchCheck: string | null | undefined = state.records.branches.get(
state.records.currBranch state.records.currBranch
@@ -150,7 +150,8 @@ export const merge = (
expected: ['branch abc'], expected: ['branch abc'],
}; };
throw error; throw error;
} else if (currentCommit === undefined || !currentCommit) { }
if (currentCommit === undefined || !currentCommit) {
const error: any = new Error( const error: any = new Error(
`Incorrect usage of "merge". Current branch (${state.records.currBranch})has no commits` `Incorrect usage of "merge". Current branch (${state.records.currBranch})has no commits`
); );
@@ -162,7 +163,8 @@ export const merge = (
expected: ['commit'], expected: ['commit'],
}; };
throw error; throw error;
} else if (!state.records.branches.has(otherBranch)) { }
if (!state.records.branches.has(otherBranch)) {
const error: any = new Error( const error: any = new Error(
'Incorrect usage of "merge". Branch to be merged (' + otherBranch + ') does not exist' 'Incorrect usage of "merge". Branch to be merged (' + otherBranch + ') does not exist'
); );
@@ -174,7 +176,8 @@ export const merge = (
expected: [`branch ${otherBranch}`], expected: [`branch ${otherBranch}`],
}; };
throw error; throw error;
} else if (otherCommit === undefined || !otherCommit) { }
if (otherCommit === undefined || !otherCommit) {
const error: any = new Error( const error: any = new Error(
'Incorrect usage of "merge". Branch to be merged (' + otherBranch + ') has no commits' 'Incorrect usage of "merge". Branch to be merged (' + otherBranch + ') has no commits'
); );
@@ -186,7 +189,8 @@ export const merge = (
expected: ['"commit"'], expected: ['"commit"'],
}; };
throw error; throw error;
} else if (currentCommit === otherCommit) { }
if (currentCommit === otherCommit) {
const error: any = new Error('Incorrect usage of "merge". Both branches have same head'); const error: any = new Error('Incorrect usage of "merge". Both branches have same head');
error.hash = { error.hash = {
text: `merge ${otherBranch}`, text: `merge ${otherBranch}`,
@@ -196,7 +200,8 @@ export const merge = (
expected: ['branch abc'], expected: ['branch abc'],
}; };
throw error; throw error;
} else if (customId && state.records.commits.has(customId)) { }
if (customId && state.records.commits.has(customId)) {
const error: any = new Error( const error: any = new Error(
'Incorrect usage of "merge". Commit with id:' + 'Incorrect usage of "merge". Commit with id:' +
customId + customId +
@@ -218,7 +223,7 @@ export const merge = (
const verifiedBranch: string = otherBranchCheck ? otherBranchCheck : ''; //figure out a cleaner way to do this const verifiedBranch: string = otherBranchCheck ? otherBranchCheck : ''; //figure out a cleaner way to do this
const commit: Commit = { const commit: Commit = {
id: customId ? customId : state.records.seq + '-' + getId(), id: customId ? customId : state.records.seq + '-' + getID(),
message: `merged branch ${otherBranch} into ${state.records.currBranch}`, message: `merged branch ${otherBranch} into ${state.records.currBranch}`,
seq: state.records.seq++, seq: state.records.seq++,
parents: [state.records.head == null ? null : state.records.head.id, verifiedBranch], parents: [state.records.head == null ? null : state.records.head.id, verifiedBranch],
@@ -242,12 +247,13 @@ export const cherryPick = function (
parentCommitId: string parentCommitId: string
) { ) {
log.debug('Entering cherryPick:', sourceId, targetId, tags); log.debug('Entering cherryPick:', sourceId, targetId, tags);
sourceId = common.sanitizeText(sourceId, getConfig());
targetId = common.sanitizeText(targetId, getConfig());
const config = getConfig(); const config = getConfig();
sourceId = common.sanitizeText(sourceId, config);
targetId = common.sanitizeText(targetId, config);
tags = tags?.map((tag) => common.sanitizeText(tag, config)); tags = tags?.map((tag) => common.sanitizeText(tag, config));
parentCommitId = common.sanitizeText(parentCommitId, getConfig()); parentCommitId = common.sanitizeText(parentCommitId, config);
if (!sourceId || !state.records.commits.has(sourceId)) { if (!sourceId || !state.records.commits.has(sourceId)) {
const error: any = new Error( const error: any = new Error(
@@ -293,8 +299,6 @@ export const cherryPick = function (
error.hash = { error.hash = {
text: `cherryPick ${sourceId} ${targetId}`, text: `cherryPick ${sourceId} ${targetId}`,
token: `cherryPick ${sourceId} ${targetId}`, token: `cherryPick ${sourceId} ${targetId}`,
line: '1',
loc: { first_line: 1, last_line: 1, first_column: 1, last_column: 1 },
expected: ['cherry-pick abc'], expected: ['cherry-pick abc'],
}; };
throw error; throw error;
@@ -307,8 +311,6 @@ export const cherryPick = function (
error.hash = { error.hash = {
text: `cherryPick ${sourceId} ${targetId}`, text: `cherryPick ${sourceId} ${targetId}`,
token: `cherryPick ${sourceId} ${targetId}`, token: `cherryPick ${sourceId} ${targetId}`,
line: '1',
loc: { first_line: 1, last_line: 1, first_column: 1, last_column: 1 },
expected: ['cherry-pick abc'], expected: ['cherry-pick abc'],
}; };
throw error; throw error;
@@ -323,13 +325,12 @@ export const cherryPick = function (
text: `cherryPick ${sourceId} ${targetId}`, text: `cherryPick ${sourceId} ${targetId}`,
token: `cherryPick ${sourceId} ${targetId}`, token: `cherryPick ${sourceId} ${targetId}`,
line: '1', line: '1',
loc: { first_line: 1, last_line: 1, first_column: 1, last_column: 1 },
expected: ['cherry-pick abc'], expected: ['cherry-pick abc'],
}; };
throw error; throw error;
} }
const commit = { const commit = {
id: state.records.seq + '-' + getId(), id: state.records.seq + '-' + getID(),
message: `cherry-picked ${sourceCommit?.message} into ${state.records.currBranch}`, message: `cherry-picked ${sourceCommit?.message} into ${state.records.currBranch}`,
seq: state.records.seq++, seq: state.records.seq++,
parents: [state.records.head == null ? null : state.records.head.id, sourceCommit.id], parents: [state.records.head == null ? null : state.records.head.id, sourceCommit.id],
@@ -365,8 +366,6 @@ export const checkout = function (branch: string) {
expected: [`branch ${branch}`], expected: [`branch ${branch}`],
}; };
throw error; throw error;
//branches[branch] = head != null ? head.id : null;
//log.debug('in createBranch');
} else { } else {
state.records.currBranch = branch; state.records.currBranch = branch;
const id = state.records.branches.get(state.records.currBranch); const id = state.records.branches.get(state.records.currBranch);
@@ -378,25 +377,6 @@ export const checkout = function (branch: string) {
} }
}; };
// export const reset = function (commitRef) {
// log.debug('in reset', commitRef);
// const ref = commitRef.split(':')[0];
// let parentCount = parseInt(commitRef.split(':')[1]);
// let commit = ref === 'HEAD' ? head : commits.get(branches.get(ref));
// log.debug(commit, parentCount);
// while (parentCount > 0) {
// commit = commits.get(commit.parent);
// parentCount--;
// if (!commit) {
// const err = 'Critical error - unique parent commit not found during reset';
// log.error(err);
// throw err;
// }
// }
// head = commit;
// branches[curBranch] = commit.id;
// };
/** /**
* @param arr - array * @param arr - array
* @param key - key * @param key - key

View File

@@ -1,129 +1,92 @@
import gitGraphAst from './gitGraphAst.js'; import db from './gitGraphAst.js';
import { parser } from './parser/gitGraph.jison'; import { parser } from './gitGraphParser.js';
describe('when parsing a gitGraph', function () { describe('when parsing a gitGraph', function () {
beforeEach(function () { beforeEach(function () {
parser.yy = gitGraphAst; db.clear();
parser.yy.clear();
}); });
it('should handle a gitGraph definition', function () {
const str = 'gitGraph:\n' + 'commit\n';
parser.parse(str); it('should handle a gitGraph definition', async () => {
const commits = parser.yy.getCommits(); const str = `gitGraph:\n commit\n`;
await parser.parse(str);
const commits = db.getCommits();
expect(commits.size).toBe(1); expect(commits.size).toBe(1);
expect(parser.yy.getCurrentBranch()).toBe('main'); expect(db.getCurrentBranch()).toBe('main');
expect(parser.yy.getDirection()).toBe('LR'); expect(db.getDirection()).toBe('LR');
expect(parser.yy.getBranches().size).toBe(1); expect(db.getBranches().size).toBe(1);
}); });
it('should handle a gitGraph definition with empty options', function () { it('should handle set direction top to bottom', async () => {
const str = 'gitGraph:\n' + 'options\n' + ' end\n' + 'commit\n';
parser.parse(str);
const commits = parser.yy.getCommits();
expect(parser.yy.getOptions()).toEqual({});
expect(commits.size).toBe(1);
expect(parser.yy.getCurrentBranch()).toBe('main');
expect(parser.yy.getDirection()).toBe('LR');
expect(parser.yy.getBranches().size).toBe(1);
});
it('should handle a gitGraph definition with valid options', function () {
const str = 'gitGraph:\n' + 'options\n' + '{"key": "value"}\n' + 'end\n' + 'commit\n';
parser.parse(str);
const commits = parser.yy.getCommits();
expect(parser.yy.getOptions().key).toBe('value');
expect(commits.size).toBe(1);
expect(parser.yy.getCurrentBranch()).toBe('main');
expect(parser.yy.getDirection()).toBe('LR');
expect(parser.yy.getBranches().size).toBe(1);
});
it('should not fail on a gitGraph with malformed json', function () {
const str = 'gitGraph:\n' + 'options\n' + '{"key": "value"\n' + 'end\n' + 'commit\n';
parser.parse(str);
const commits = parser.yy.getCommits();
expect(commits.size).toBe(1);
expect(parser.yy.getCurrentBranch()).toBe('main');
expect(parser.yy.getDirection()).toBe('LR');
expect(parser.yy.getBranches().size).toBe(1);
});
it('should handle set direction top to bottom', function () {
const str = 'gitGraph TB:\n' + 'commit\n'; const str = 'gitGraph TB:\n' + 'commit\n';
parser.parse(str); await parser.parse(str);
const commits = parser.yy.getCommits(); const commits = db.getCommits();
expect(commits.size).toBe(1); expect(commits.size).toBe(1);
expect(parser.yy.getCurrentBranch()).toBe('main'); expect(db.getCurrentBranch()).toBe('main');
expect(parser.yy.getDirection()).toBe('TB'); expect(db.getDirection()).toBe('TB');
expect(parser.yy.getBranches().size).toBe(1); expect(db.getBranches().size).toBe(1);
}); });
it('should handle set direction bottom to top', function () { it('should handle set direction bottom to top', async () => {
const str = 'gitGraph BT:\n' + 'commit\n'; const str = 'gitGraph BT:\n' + 'commit\n';
parser.parse(str); await parser.parse(str);
const commits = parser.yy.getCommits(); const commits = db.getCommits();
expect(commits.size).toBe(1); expect(commits.size).toBe(1);
expect(parser.yy.getCurrentBranch()).toBe('main'); expect(db.getCurrentBranch()).toBe('main');
expect(parser.yy.getDirection()).toBe('BT'); expect(db.getDirection()).toBe('BT');
expect(parser.yy.getBranches().size).toBe(1); expect(db.getBranches().size).toBe(1);
}); });
it('should checkout a branch', function () { it('should checkout a branch', async () => {
const str = 'gitGraph:\n' + 'branch new\n' + 'checkout new\n'; const str = 'gitGraph:\n' + 'branch new\n' + 'checkout new\n';
parser.parse(str); await parser.parse(str);
const commits = parser.yy.getCommits(); const commits = db.getCommits();
expect(commits.size).toBe(0); expect(commits.size).toBe(0);
expect(parser.yy.getCurrentBranch()).toBe('new'); expect(db.getCurrentBranch()).toBe('new');
}); });
it('should switch a branch', function () { it('should switch a branch', async () => {
const str = 'gitGraph:\n' + 'branch new\n' + 'switch new\n'; const str = 'gitGraph:\n' + 'branch new\n' + 'switch new\n';
parser.parse(str); await parser.parse(str);
const commits = parser.yy.getCommits(); const commits = db.getCommits();
expect(commits.size).toBe(0); expect(commits.size).toBe(0);
expect(parser.yy.getCurrentBranch()).toBe('new'); expect(db.getCurrentBranch()).toBe('new');
}); });
it('should add commits to checked out branch', function () { it('should add commits to checked out branch', async () => {
const str = 'gitGraph:\n' + 'branch new\n' + 'checkout new\n' + 'commit\n' + 'commit\n'; const str = 'gitGraph:\n' + 'branch new\n' + 'checkout new\n' + 'commit\n' + 'commit\n';
parser.parse(str); await parser.parse(str);
const commits = parser.yy.getCommits(); const commits = db.getCommits();
expect(commits.size).toBe(2); expect(commits.size).toBe(2);
expect(parser.yy.getCurrentBranch()).toBe('new'); expect(db.getCurrentBranch()).toBe('new');
const branchCommit = parser.yy.getBranches().get('new'); const branchCommit = db.getBranches().get('new');
expect(branchCommit).not.toBeNull(); expect(branchCommit).not.toBeNull();
expect(commits.get(branchCommit).parent).not.toBeNull(); expect(commits.get(branchCommit).parent).not.toBeNull();
}); });
it('should handle commit with args', function () { it('should handle commit with args', async () => {
const str = 'gitGraph:\n' + 'commit "a commit"\n'; const str = 'gitGraph:\n' + 'commit "a commit"\n';
parser.parse(str); await parser.parse(str);
const commits = parser.yy.getCommits(); const commits = db.getCommits();
expect(commits.size).toBe(1); expect(commits.size).toBe(1);
const key = commits.keys().next().value; const key = commits.keys().next().value;
expect(commits.get(key).message).toBe('a commit'); expect(commits.get(key).message).toBe('a commit');
expect(parser.yy.getCurrentBranch()).toBe('main'); expect(db.getCurrentBranch()).toBe('main');
}); });
// Reset has been commented out in JISON it.skip('should reset a branch', async () => {
it.skip('should reset a branch', function () {
const str = const str =
'gitGraph:\n' + 'gitGraph:\n' +
'commit\n' + 'commit\n' +
@@ -133,16 +96,16 @@ describe('when parsing a gitGraph', function () {
'commit\n' + 'commit\n' +
'reset main\n'; 'reset main\n';
parser.parse(str); await parser.parse(str);
const commits = parser.yy.getCommits(); const commits = db.getCommits();
expect(commits.size).toBe(3); expect(commits.size).toBe(3);
expect(parser.yy.getCurrentBranch()).toBe('newbranch'); expect(db.getCurrentBranch()).toBe('newbranch');
expect(parser.yy.getBranches().get('newbranch')).toEqual(parser.yy.getBranches().get('main')); expect(db.getBranches().get('newbranch')).toEqual(db.getBranches().get('main'));
expect(parser.yy.getHead().id).toEqual(parser.yy.getBranches().get('newbranch')); expect(db.getHead().id).toEqual(db.getBranches().get('newbranch'));
}); });
it.skip('reset can take an argument', function () { it.skip('reset can take an argument', async () => {
const str = const str =
'gitGraph:\n' + 'gitGraph:\n' +
'commit\n' + 'commit\n' +
@@ -152,16 +115,16 @@ describe('when parsing a gitGraph', function () {
'commit\n' + 'commit\n' +
'reset main^\n'; 'reset main^\n';
parser.parse(str); await parser.parse(str);
const commits = parser.yy.getCommits(); const commits = db.getCommits();
expect(commits.size).toBe(3); expect(commits.size).toBe(3);
expect(parser.yy.getCurrentBranch()).toBe('newbranch'); expect(db.getCurrentBranch()).toBe('newbranch');
const main = commits.get(parser.yy.getBranches().get('main')); const main = commits.get(db.getBranches().get('main'));
expect(parser.yy.getHead().id).toEqual(main.parent); expect(db.getHead().id).toEqual(main.parent);
}); });
it.skip('should handle fast forwardable merges', function () { it.skip('should handle fast forwardable merges', async () => {
const str = const str =
'gitGraph:\n' + 'gitGraph:\n' +
'commit\n' + 'commit\n' +
@@ -172,16 +135,16 @@ describe('when parsing a gitGraph', function () {
'checkout main\n' + 'checkout main\n' +
'merge newbranch\n'; 'merge newbranch\n';
parser.parse(str); await parser.parse(str);
const commits = parser.yy.getCommits(); const commits = db.getCommits();
expect(commits.size).toBe(4); expect(commits.size).toBe(4);
expect(parser.yy.getCurrentBranch()).toBe('main'); expect(db.getCurrentBranch()).toBe('main');
expect(parser.yy.getBranches().get('newbranch')).toEqual(parser.yy.getBranches().get('main')); expect(db.getBranches().get('newbranch')).toEqual(db.getBranches().get('main'));
expect(parser.yy.getHead().id).toEqual(parser.yy.getBranches().get('newbranch')); expect(db.getHead().id).toEqual(db.getBranches().get('newbranch'));
}); });
it('should handle cases when merge is a noop', function () { it('should handle cases when merge is a noop', async () => {
const str = const str =
'gitGraph:\n' + 'gitGraph:\n' +
'commit\n' + 'commit\n' +
@@ -191,18 +154,16 @@ describe('when parsing a gitGraph', function () {
'commit\n' + 'commit\n' +
'merge main\n'; 'merge main\n';
parser.parse(str); await parser.parse(str);
const commits = parser.yy.getCommits(); const commits = db.getCommits();
expect(commits.size).toBe(4); expect(commits.size).toBe(4);
expect(parser.yy.getCurrentBranch()).toBe('newbranch'); expect(db.getCurrentBranch()).toBe('newbranch');
expect(parser.yy.getBranches().get('newbranch')).not.toEqual( expect(db.getBranches().get('newbranch')).not.toEqual(db.getBranches().get('main'));
parser.yy.getBranches().get('main') expect(db.getHead().id).toEqual(db.getBranches().get('newbranch'));
);
expect(parser.yy.getHead().id).toEqual(parser.yy.getBranches().get('newbranch'));
}); });
it('should handle merge with 2 parents', function () { it('should handle merge with 2 parents', async () => {
const str = const str =
'gitGraph:\n' + 'gitGraph:\n' +
'commit\n' + 'commit\n' +
@@ -214,18 +175,16 @@ describe('when parsing a gitGraph', function () {
'commit\n' + 'commit\n' +
'merge newbranch\n'; 'merge newbranch\n';
parser.parse(str); await parser.parse(str);
const commits = parser.yy.getCommits(); const commits = db.getCommits();
expect(commits.size).toBe(5); expect(commits.size).toBe(5);
expect(parser.yy.getCurrentBranch()).toBe('main'); expect(db.getCurrentBranch()).toBe('main');
expect(parser.yy.getBranches().get('newbranch')).not.toEqual( expect(db.getBranches().get('newbranch')).not.toEqual(db.getBranches().get('main'));
parser.yy.getBranches().get('main') expect(db.getHead().id).toEqual(db.getBranches().get('main'));
);
expect(parser.yy.getHead().id).toEqual(parser.yy.getBranches().get('main'));
}); });
it.skip('should handle ff merge when history walk has two parents (merge commit)', function () { it.skip('should handle ff merge when history walk has two parents (merge commit)', async () => {
const str = const str =
'gitGraph:\n' + 'gitGraph:\n' +
'commit\n' + 'commit\n' +
@@ -240,18 +199,18 @@ describe('when parsing a gitGraph', function () {
'checkout newbranch\n' + 'checkout newbranch\n' +
'merge main\n'; 'merge main\n';
parser.parse(str); await parser.parse(str);
const commits = parser.yy.getCommits(); const commits = db.getCommits();
expect(commits.size).toBe(7); expect(commits.size).toBe(7);
expect(parser.yy.getCurrentBranch()).toBe('newbranch'); expect(db.getCurrentBranch()).toBe('newbranch');
expect(parser.yy.getBranches().get('newbranch')).toEqual(parser.yy.getBranches().get('main')); expect(db.getBranches().get('newbranch')).toEqual(db.getBranches().get('main'));
expect(parser.yy.getHead().id).toEqual(parser.yy.getBranches().get('main')); expect(db.getHead().id).toEqual(db.getBranches().get('main'));
parser.yy.prettyPrint(); db.prettyPrint();
}); });
it('should generate an array of known branches', function () { it('should generate an array of known branches', async () => {
const str = const str =
'gitGraph:\n' + 'gitGraph:\n' +
'commit\n' + 'commit\n' +
@@ -261,8 +220,8 @@ describe('when parsing a gitGraph', function () {
'commit\n' + 'commit\n' +
'branch b2\n'; 'branch b2\n';
parser.parse(str); await parser.parse(str);
const branches = gitGraphAst.getBranchesAsObjArray(); const branches = db.getBranchesAsObjArray();
expect(branches).toHaveLength(3); expect(branches).toHaveLength(3);
expect(branches[0]).toHaveProperty('name', 'main'); expect(branches[0]).toHaveProperty('name', 'main');

File diff suppressed because it is too large Load Diff

View File

@@ -26,7 +26,7 @@ hidden terminal SINGLE_LINE_COMMENT: /[\t ]*%%[^\n\r]*/;
entry GitGraph: entry GitGraph:
NEWLINE* NEWLINE*
'gitGraph' Direction? ':'? ('gitGraph' | 'gitGraph' ':' | 'gitGraph:' | ('gitGraph' Direction ':'))
NEWLINE* NEWLINE*
( (
NEWLINE* NEWLINE*