mermaid/src/diagrams/gitGraph/gitGraphAst.js

209 lines
5.6 KiB
JavaScript
Raw Normal View History

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