mermaid/src/diagrams/git/gitGraphAst.js

244 lines
6.0 KiB
JavaScript
Raw Normal View History

2019-09-12 12:56:54 -07:00
import _ from 'lodash';
2017-09-05 21:19:53 +08:00
2019-09-12 12:56:54 -07:00
import { logger } from '../../logger';
2016-03-28 13:17:31 +05:30
2019-09-12 12:56:54 -07:00
let commits = {};
let head = null;
let branches = { master: head };
let curBranch = 'master';
let direction = 'LR';
let seq = 0;
2019-09-12 12:56:54 -07:00
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min)) + min;
2016-03-29 20:55:22 +05:30
}
2016-04-28 11:27:24 +05:30
2019-09-12 12:56:54 -07:00
function getId() {
const pool = '0123456789abcdef';
let id = '';
2017-09-14 20:53:36 +08:00
for (let i = 0; i < 7; i++) {
2019-09-12 12:56:54 -07:00
id += pool[getRandomInt(0, 16)];
2017-04-11 22:14:25 +08:00
}
2019-09-12 12:56:54 -07:00
return id;
}
2019-09-12 12:56:54 -07:00
function isfastforwardable(currentCommit, otherCommit) {
logger.debug('Entering isfastforwardable:', currentCommit.id, otherCommit.id);
2017-04-13 20:16:38 +08:00
while (currentCommit.seq <= otherCommit.seq && currentCommit !== otherCommit) {
2017-04-16 23:48:36 +08:00
// only if other branch has more commits
2019-09-12 12:56:54 -07:00
if (otherCommit.parent == null) break;
2017-04-11 22:14:25 +08:00
if (Array.isArray(otherCommit.parent)) {
2019-09-12 12:56:54 -07:00
logger.debug('In merge commit:', otherCommit.parent);
return (
isfastforwardable(currentCommit, commits[otherCommit.parent[0]]) ||
2017-04-16 23:48:36 +08:00
isfastforwardable(currentCommit, commits[otherCommit.parent[1]])
2019-09-12 12:56:54 -07:00
);
2016-03-27 17:53:01 +05:30
} else {
2019-09-12 12:56:54 -07:00
otherCommit = commits[otherCommit.parent];
2016-03-27 16:13:07 +05:30
}
2017-04-11 22:14:25 +08:00
}
2019-09-12 12:56:54 -07:00
logger.debug(currentCommit.id, otherCommit.id);
return currentCommit.id === otherCommit.id;
2017-04-11 22:14:25 +08:00
}
2019-09-12 12:56:54 -07:00
function isReachableFrom(currentCommit, otherCommit) {
const currentSeq = currentCommit.seq;
const otherSeq = otherCommit.seq;
if (currentSeq > otherSeq) return isfastforwardable(otherCommit, currentCommit);
return false;
2017-04-11 22:14:25 +08:00
}
2019-09-12 12:56:54 -07:00
export const setDirection = function(dir) {
direction = dir;
};
let options = {};
export const setOptions = function(rawOptString) {
logger.debug('options str', rawOptString);
rawOptString = rawOptString && rawOptString.trim();
rawOptString = rawOptString || '{}';
2017-04-11 22:14:25 +08:00
try {
2019-09-12 12:56:54 -07:00
options = JSON.parse(rawOptString);
2017-04-11 22:14:25 +08:00
} catch (e) {
2019-09-12 12:56:54 -07:00
logger.error('error while parsing gitGraph options', e.message);
2017-04-11 22:14:25 +08:00
}
2019-09-12 12:56:54 -07:00
};
2017-04-11 22:14:25 +08:00
2019-09-12 12:56:54 -07:00
export const getOptions = function() {
return options;
};
2017-04-11 22:14:25 +08:00
2019-09-12 12:56:54 -07:00
export const commit = function(msg) {
2017-09-14 20:53:36 +08:00
const commit = {
2017-04-16 23:48:36 +08:00
id: getId(),
2017-04-11 22:14:25 +08:00
message: msg,
seq: seq++,
2017-04-16 23:48:36 +08:00
parent: head == null ? null : head.id
2019-09-12 12:56:54 -07:00
};
head = commit;
commits[commit.id] = commit;
branches[curBranch] = commit.id;
logger.debug('in pushCommit ' + commit.id);
};
export const branch = function(name) {
branches[name] = head != null ? head.id : null;
logger.debug('in createBranch');
};
export const merge = function(otherBranch) {
const currentCommit = commits[branches[curBranch]];
const otherCommit = commits[branches[otherBranch]];
2017-04-11 22:14:25 +08:00
if (isReachableFrom(currentCommit, otherCommit)) {
2019-09-12 12:56:54 -07:00
logger.debug('Already merged');
return;
2017-04-11 22:14:25 +08:00
}
if (isfastforwardable(currentCommit, otherCommit)) {
2019-09-12 12:56:54 -07:00
branches[curBranch] = branches[otherBranch];
head = commits[branches[curBranch]];
2017-04-11 22:14:25 +08:00
} else {
2017-04-16 23:48:36 +08:00
// create merge commit
2017-09-14 20:53:36 +08:00
const commit = {
2017-04-11 22:14:25 +08:00
id: getId(),
message: 'merged branch ' + otherBranch + ' into ' + curBranch,
seq: seq++,
parent: [head == null ? null : head.id, branches[otherBranch]]
2019-09-12 12:56:54 -07:00
};
head = commit;
commits[commit.id] = commit;
branches[curBranch] = commit.id;
2017-04-11 22:14:25 +08:00
}
2019-09-12 12:56:54 -07:00
logger.debug(branches);
logger.debug('in mergeBranch');
};
export const checkout = function(branch) {
logger.debug('in checkout');
curBranch = branch;
const id = branches[curBranch];
head = commits[id];
};
export const reset = function(commitRef) {
logger.debug('in reset', commitRef);
const ref = commitRef.split(':')[0];
let parentCount = parseInt(commitRef.split(':')[1]);
let commit = ref === 'HEAD' ? head : commits[branches[ref]];
logger.debug(commit, parentCount);
2017-04-11 22:14:25 +08:00
while (parentCount > 0) {
2019-09-12 12:56:54 -07:00
commit = commits[commit.parent];
parentCount--;
2017-04-11 22:14:25 +08:00
if (!commit) {
2019-09-12 12:56:54 -07:00
const err = 'Critical error - unique parent commit not found during reset';
logger.error(err);
throw err;
2016-03-28 13:18:11 +05:30
}
2017-04-11 22:14:25 +08:00
}
2019-09-12 12:56:54 -07:00
head = commit;
branches[curBranch] = commit.id;
};
2017-04-11 22:14:25 +08:00
2019-09-12 12:56:54 -07:00
function upsert(arr, key, newval) {
const index = arr.indexOf(key);
2017-04-19 20:17:57 +08:00
if (index === -1) {
2019-09-12 12:56:54 -07:00
arr.push(newval);
2017-04-19 20:17:57 +08:00
} else {
2019-09-12 12:56:54 -07:00
arr.splice(index, 1, newval);
2017-04-11 22:14:25 +08:00
}
}
2019-09-12 12:56:54 -07:00
function prettyPrintCommitHistory(commitArr) {
const commit = _.maxBy(commitArr, 'seq');
let line = '';
commitArr.forEach(function(c) {
2017-04-13 20:16:38 +08:00
if (c === commit) {
2019-09-12 12:56:54 -07:00
line += '\t*';
2016-03-28 13:18:11 +05:30
} else {
2019-09-12 12:56:54 -07:00
line += '\t|';
2016-03-28 13:18:11 +05:30
}
2019-09-12 12:56:54 -07:00
});
const label = [line, commit.id, commit.seq];
for (let branch in branches) {
2019-09-12 12:56:54 -07:00
if (branches[branch] === commit.id) label.push(branch);
}
2019-09-12 12:56:54 -07:00
logger.debug(label.join(' '));
2017-04-11 22:14:25 +08:00
if (Array.isArray(commit.parent)) {
2019-09-12 12:56:54 -07:00
const newCommit = commits[commit.parent[0]];
upsert(commitArr, commit, newCommit);
commitArr.push(commits[commit.parent[1]]);
2017-04-11 22:14:25 +08:00
} else if (commit.parent == null) {
2019-09-12 12:56:54 -07:00
return;
2017-04-11 22:14:25 +08:00
} else {
2019-09-12 12:56:54 -07:00
const nextCommit = commits[commit.parent];
upsert(commitArr, commit, nextCommit);
2017-04-11 22:14:25 +08:00
}
2019-09-12 12:56:54 -07:00
commitArr = _.uniqBy(commitArr, 'id');
prettyPrintCommitHistory(commitArr);
}
export const prettyPrint = function() {
logger.debug(commits);
const node = getCommitsArray()[0];
prettyPrintCommitHistory([node]);
};
export const clear = function() {
commits = {};
head = null;
branches = { master: head };
curBranch = 'master';
seq = 0;
};
export const getBranchesAsObjArray = function() {
const branchArr = [];
for (let branch in branches) {
2019-09-12 12:56:54 -07:00
branchArr.push({ name: branch, commit: commits[branches[branch]] });
}
2019-09-12 12:56:54 -07:00
return branchArr;
};
export const getBranches = function() {
return branches;
};
export const getCommits = function() {
return commits;
};
export const getCommitsArray = function() {
const commitArr = Object.keys(commits).map(function(key) {
return commits[key];
});
commitArr.forEach(function(o) {
logger.debug(o.id);
});
return _.orderBy(commitArr, ['seq'], ['desc']);
};
export const getCurrentBranch = function() {
return curBranch;
};
export const getDirection = function() {
return direction;
};
export const getHead = function() {
return head;
};
2017-09-10 21:51:48 +08:00
export default {
setDirection,
setOptions,
getOptions,
commit,
branch,
merge,
checkout,
reset,
prettyPrint,
clear,
getBranchesAsObjArray,
getBranches,
getCommits,
getCommitsArray,
getCurrentBranch,
getDirection,
getHead
2019-09-12 12:56:54 -07:00
};