UNPKG

mermaid

Version:

Markdownish syntax for generating flowcharts, sequence diagrams, class diagrams, gantt charts and git graphs.

210 lines (190 loc) 5.61 kB
import _ from 'lodash' const Logger = require('../../logger') const log = Logger.Log var commits = {} var head = null var branches = { 'master': head } var curBranch = 'master' var direction = 'LR' var seq = 0 function getRandomInt (min, max) { return Math.floor(Math.random() * (max - min)) + min } function getId () { var pool = '0123456789abcdef' var id = '' for (var i = 0; i < 7; i++) { id += pool[getRandomInt(0, 16)] } return id } function isfastforwardable (currentCommit, otherCommit) { log.debug('Entering isfastforwardable:', currentCommit.id, otherCommit.id) while (currentCommit.seq <= otherCommit.seq && currentCommit !== otherCommit) { // only if other branch has more commits if (otherCommit.parent == null) break if (Array.isArray(otherCommit.parent)) { log.debug('In merge commit:', otherCommit.parent) return isfastforwardable(currentCommit, commits[otherCommit.parent[0]]) || isfastforwardable(currentCommit, commits[otherCommit.parent[1]]) } else { otherCommit = commits[otherCommit.parent] } } log.debug(currentCommit.id, otherCommit.id) return currentCommit.id === otherCommit.id } function isReachableFrom (currentCommit, otherCommit) { var currentSeq = currentCommit.seq var otherSeq = otherCommit.seq if (currentSeq > otherSeq) return isfastforwardable(otherCommit, currentCommit) return false } exports.setDirection = function (dir) { direction = dir } var options = {} exports.setOptions = function (rawOptString) { log.debug('options str', rawOptString) rawOptString = rawOptString && rawOptString.trim() rawOptString = rawOptString || '{}' try { options = JSON.parse(rawOptString) } catch (e) { log.error('error while parsing gitGraph options', e.message) } } exports.getOptions = function () { return options } exports.commit = function (msg) { var commit = { id: getId(), message: msg, seq: seq++, parent: head == null ? null : head.id } head = commit commits[commit.id] = commit branches[curBranch] = commit.id log.debug('in pushCommit ' + commit.id) } exports.branch = function (name) { branches[name] = head != null ? head.id : null log.debug('in createBranch') } exports.merge = function (otherBranch) { var currentCommit = commits[branches[curBranch]] var otherCommit = commits[branches[otherBranch]] if (isReachableFrom(currentCommit, otherCommit)) { log.debug('Already merged') return } if (isfastforwardable(currentCommit, otherCommit)) { branches[curBranch] = branches[otherBranch] head = commits[branches[curBranch]] } else { // create merge commit var commit = { id: getId(), message: 'merged branch ' + otherBranch + ' into ' + curBranch, seq: seq++, parent: [head == null ? null : head.id, branches[otherBranch]] } head = commit commits[commit.id] = commit branches[curBranch] = commit.id } log.debug(branches) log.debug('in mergeBranch') } exports.checkout = function (branch) { log.debug('in checkout') curBranch = branch var id = branches[curBranch] head = commits[id] } exports.reset = function (commitRef) { log.debug('in reset', commitRef) var ref = commitRef.split(':')[0] var parentCount = parseInt(commitRef.split(':')[1]) var commit = ref === 'HEAD' ? head : commits[branches[ref]] log.debug(commit, parentCount) while (parentCount > 0) { commit = commits[commit.parent] parentCount-- if (!commit) { var err = 'Critical error - unique parent commit not found during reset' log.error(err) throw err } } head = commit branches[curBranch] = commit.id } function upsert (arr, key, newval) { const index = arr.indexOf(key) if (index === -1) { arr.push(newval) } else { arr.splice(index, 1, newval) } } function prettyPrintCommitHistory (commitArr) { var commit = _.maxBy(commitArr, 'seq') var line = '' commitArr.forEach(function (c) { if (c === commit) { line += '\t*' } else { line += '\t|' } }) var label = [line, commit.id, commit.seq] _.each(branches, function (value, key) { if (value === commit.id) label.push(key) }) log.debug(label.join(' ')) if (Array.isArray(commit.parent)) { var newCommit = commits[commit.parent[0]] upsert(commitArr, commit, newCommit) commitArr.push(commits[commit.parent[1]]) } else if (commit.parent == null) { return } else { var nextCommit = commits[commit.parent] upsert(commitArr, commit, nextCommit) } commitArr = _.uniqBy(commitArr, 'id') prettyPrintCommitHistory(commitArr) } exports.prettyPrint = function () { log.debug(commits) var node = exports.getCommitsArray()[0] prettyPrintCommitHistory([node]) } exports.clear = function () { commits = {} head = null branches = { 'master': head } curBranch = 'master' seq = 0 } exports.getBranchesAsObjArray = function () { const branchArr = _.map(branches, function (value, key) { return { 'name': key, 'commit': commits[value] } }) return branchArr } exports.getBranches = function () { return branches } exports.getCommits = function () { return commits } exports.getCommitsArray = function () { var commitArr = Object.keys(commits).map(function (key) { return commits[key] }) commitArr.forEach(function (o) { log.debug(o.id) }) return _.orderBy(commitArr, ['seq'], ['desc']) } exports.getCurrentBranch = function () { return curBranch } exports.getDirection = function () { return direction } exports.getHead = function () { return head }