1 | "use strict";
|
2 | var immutable_1 = require("immutable");
|
3 | var log = require('debug')('redux-dag-history:DagGraph');
|
4 | var treeify = require('treeify');
|
5 | var DagGraph = (function () {
|
6 | function DagGraph(graph) {
|
7 | this.graph = graph;
|
8 | if (!graph) {
|
9 | throw new Error('\'graph\' parameter must be defined');
|
10 | }
|
11 | if (!graph.getIn) {
|
12 | throw new Error('\'graph\' must be an immutablejs instance');
|
13 | }
|
14 | }
|
15 | DagGraph.prototype.print = function () {
|
16 | var _this = this;
|
17 | var graph = this.graph.toJS();
|
18 | var root = null;
|
19 | var states = {};
|
20 | var getOrCreateState = function (stateId) {
|
21 | var result = states[stateId];
|
22 | if (!result) {
|
23 | result = {
|
24 | id: stateId,
|
25 | name: _this.stateName(stateId),
|
26 | children: [],
|
27 | };
|
28 | states[stateId] = result;
|
29 | }
|
30 | return result;
|
31 | };
|
32 | Object.keys(graph.states || {}).forEach(function (stateId) {
|
33 | var parentId = graph.states[stateId].parent;
|
34 | var state = getOrCreateState(stateId);
|
35 | if (!parentId) {
|
36 | root = state;
|
37 | }
|
38 | getOrCreateState(parentId).children.push(state);
|
39 | states[stateId] = state;
|
40 | });
|
41 | var tree = {
|
42 | current: graph.current,
|
43 | branches: graph.branches,
|
44 | dag: root,
|
45 | };
|
46 | var result = treeify.asTree(tree, true);
|
47 | return result;
|
48 | };
|
49 | Object.defineProperty(DagGraph.prototype, "currentStateId", {
|
50 | get: function () {
|
51 | return this.graph.getIn(['current', 'state']);
|
52 | },
|
53 | enumerable: true,
|
54 | configurable: true
|
55 | });
|
56 | DagGraph.prototype.branchStartDepth = function (branch) {
|
57 | return this.stateDepth(this.firstOn(branch));
|
58 | };
|
59 | DagGraph.prototype.branchEndDepth = function (branch) {
|
60 | return this.stateDepth(this.latestOn(branch));
|
61 | };
|
62 | DagGraph.prototype.stateDepth = function (commit) {
|
63 | return this.commitPath(commit).length - 1;
|
64 | };
|
65 | DagGraph.prototype.depthIndexOf = function (branch, commit) {
|
66 | var commits = this.branchCommitPath(branch);
|
67 | var foundIndex = commits.indexOf(commit);
|
68 | if (foundIndex === -1) {
|
69 | return undefined;
|
70 | }
|
71 | else {
|
72 | var start = this.branchStartDepth(branch);
|
73 | return start + foundIndex;
|
74 | }
|
75 | };
|
76 | Object.defineProperty(DagGraph.prototype, "maxDepth", {
|
77 | get: function () {
|
78 | var _this = this;
|
79 | var branches = this.branches;
|
80 | var branchDepths = branches.map(function (b) { return _this.branchEndDepth(b); });
|
81 | var max = -1;
|
82 | branchDepths.forEach(function (d) {
|
83 | if (d > max) {
|
84 | max = d;
|
85 | }
|
86 | });
|
87 | return max;
|
88 | },
|
89 | enumerable: true,
|
90 | configurable: true
|
91 | });
|
92 | DagGraph.prototype.setCurrentStateId = function (stateId) {
|
93 | this.graph = this.graph.setIn(['current', 'state'], stateId);
|
94 | return this;
|
95 | };
|
96 | Object.defineProperty(DagGraph.prototype, "currentBranch", {
|
97 | get: function () {
|
98 | return this.graph.getIn(['current', 'branch']);
|
99 | },
|
100 | enumerable: true,
|
101 | configurable: true
|
102 | });
|
103 | DagGraph.prototype.setCurrentBranch = function (branchId) {
|
104 | this.graph = this.graph.setIn(['current', 'branch'], branchId);
|
105 | return this;
|
106 | };
|
107 | DagGraph.prototype.latestOn = function (branch) {
|
108 | return this.graph.getIn(['branches', "" + branch, 'latest']);
|
109 | };
|
110 | DagGraph.prototype.committedOn = function (branch) {
|
111 | return this.graph.getIn(['branches', "" + branch, 'committed']);
|
112 | };
|
113 | DagGraph.prototype.setLatest = function (branch, commit) {
|
114 | this.graph = this.graph.setIn(['branches', "" + branch, 'latest'], commit);
|
115 | return this;
|
116 | };
|
117 | DagGraph.prototype.setCommitted = function (branch, commit) {
|
118 | this.graph = this.graph.setIn(['branches', "" + branch, 'committed'], commit);
|
119 | return this;
|
120 | };
|
121 | DagGraph.prototype.markStateForBranch = function (commit, branch) {
|
122 | this.graph = this.graph.setIn(['states', "" + commit, 'branch'], branch);
|
123 | return this;
|
124 | };
|
125 | DagGraph.prototype.setFirst = function (branch, commit) {
|
126 | this.graph = this.graph.setIn(['branches', "" + branch, 'first'], commit);
|
127 | return this;
|
128 | };
|
129 | DagGraph.prototype.firstOn = function (branch) {
|
130 | return this.graph.getIn(['branches', "" + branch, 'first']);
|
131 | };
|
132 | DagGraph.prototype.renameState = function (commit, name) {
|
133 | this.graph = this.graph.setIn(['states', "" + commit, 'name'], name);
|
134 | return this;
|
135 | };
|
136 | DagGraph.prototype.stateName = function (commit) {
|
137 | return this.graph.getIn(['states', "" + commit, 'name']);
|
138 | };
|
139 | DagGraph.prototype.getBranchName = function (branch) {
|
140 | return this.graph.getIn(['branches', "" + branch, 'name']);
|
141 | };
|
142 | DagGraph.prototype.setBranchName = function (branch, name) {
|
143 | this.graph = this.graph.setIn(['branches', "" + branch, 'name'], name);
|
144 | return this;
|
145 | };
|
146 | DagGraph.prototype.getState = function (commit) {
|
147 | return this.graph.getIn(['states', "" + commit, 'state']);
|
148 | };
|
149 | DagGraph.prototype.insertState = function (commit, parent, state, name) {
|
150 | log('Inserting new commit', commit);
|
151 | var newState = immutable_1.fromJS({
|
152 | name: name,
|
153 | parent: parent,
|
154 | }).set('state', state);
|
155 | if (this.graph.getIn(['states', "" + commit])) {
|
156 | log('Commit %s is already present', this.getState(commit));
|
157 | }
|
158 | this.graph = this.graph.setIn(['states', "" + commit], newState);
|
159 | return this;
|
160 | };
|
161 | DagGraph.prototype.childrenOf = function (commit) {
|
162 | var states = this.graph.get('states');
|
163 | return states.toSeq()
|
164 | .filter(function (state) { return state.get('parent') === commit; })
|
165 | .map(function (state, key) { return key; })
|
166 | .toList().toJS();
|
167 | };
|
168 | DagGraph.prototype.parentOf = function (commit) {
|
169 | return this.graph.getIn(['states', "" + commit, 'parent']);
|
170 | };
|
171 | DagGraph.prototype.alternateParentsOf = function (commit) {
|
172 | var result = this.graph.getIn(['states', "" + commit, 'alternateParents']);
|
173 | return result ? result.toJS() : [];
|
174 | };
|
175 | DagGraph.prototype.shallowestParentOf = function (commit) {
|
176 | var _this = this;
|
177 | var allParents = [
|
178 | this.parentOf(commit)
|
179 | ].concat(this.alternateParentsOf(commit));
|
180 | var result = undefined;
|
181 | var minDepth = undefined;
|
182 | allParents.forEach(function (t) {
|
183 | var depth = _this.depthIndexOf(_this.branchOf(t), t);
|
184 | if (minDepth === undefined || depth < minDepth) {
|
185 | minDepth = depth;
|
186 | result = t;
|
187 | }
|
188 | });
|
189 | return result;
|
190 | };
|
191 | DagGraph.prototype.replaceState = function (commit, state) {
|
192 | this.graph = this.graph.setIn(['states', "" + commit, 'state'], state);
|
193 | return this;
|
194 | };
|
195 | DagGraph.prototype.commitPath = function (commit) {
|
196 | if (commit === undefined) {
|
197 | return [];
|
198 | }
|
199 | var path = [commit];
|
200 | var current = commit;
|
201 | do {
|
202 | var parent_1 = this.parentOf(current);
|
203 | if (parent_1) {
|
204 | path.unshift(parent_1);
|
205 | }
|
206 | current = parent_1;
|
207 | } while (current);
|
208 | return path;
|
209 | };
|
210 | DagGraph.prototype.shortestCommitPath = function (commit) {
|
211 | if (commit === undefined) {
|
212 | return [];
|
213 | }
|
214 | var path = [commit];
|
215 | var current = commit;
|
216 | do {
|
217 | var parent_2 = this.shallowestParentOf(current);
|
218 | if (parent_2) {
|
219 | path.unshift(parent_2);
|
220 | }
|
221 | current = parent_2;
|
222 | } while (current);
|
223 | return path;
|
224 | };
|
225 | DagGraph.prototype.branchCommitPath = function (branch) {
|
226 | if (branch === undefined) {
|
227 | return [];
|
228 | }
|
229 | var latest = this.latestOn(branch);
|
230 | var path = this.commitPath(latest);
|
231 | var firstCommitOnBranch = this.firstOn(branch);
|
232 | return path.slice(path.indexOf(firstCommitOnBranch));
|
233 | };
|
234 | DagGraph.prototype.setParent = function (commit, parent) {
|
235 | this.graph = this.graph.setIn(['states', "" + commit, 'parent'], parent);
|
236 | };
|
237 | DagGraph.prototype.setAlternateParent = function (commit, parent) {
|
238 | if (this.parentOf(commit) !== parent) {
|
239 | return;
|
240 | }
|
241 | var path = ['states', "" + commit, 'alternateParents'];
|
242 | var parentList = this.graph.getIn(path) ||
|
243 | immutable_1.List();
|
244 | if (!parentList.contains(parent)) {
|
245 | this.graph = this.graph.setIn(path, parentList.push(parent));
|
246 | }
|
247 | };
|
248 | Object.defineProperty(DagGraph.prototype, "branches", {
|
249 | get: function () {
|
250 | var branches = this.graph.get('branches');
|
251 | return Array.from(branches.keys());
|
252 | },
|
253 | enumerable: true,
|
254 | configurable: true
|
255 | });
|
256 | DagGraph.prototype.branchOf = function (commit) {
|
257 | return this.graph.getIn(['states', "" + commit, 'branch']);
|
258 | };
|
259 | DagGraph.prototype.branchesOf = function (commit) {
|
260 | var _this = this;
|
261 | if (!commit) {
|
262 | throw new Error('commit must be defined');
|
263 | }
|
264 | var children = this.childrenOf(commit);
|
265 | if (children.length === 0) {
|
266 | var branches = [];
|
267 | for (var _i = 0, _a = this.branches; _i < _a.length; _i++) {
|
268 | var branch = _a[_i];
|
269 | if (this.latestOn(branch) === commit) {
|
270 | branches.push(branch);
|
271 | }
|
272 | }
|
273 | return branches;
|
274 | }
|
275 | else {
|
276 | var result_1 = [];
|
277 | var childrenBranches = children.map(function (child) { return _this.branchesOf(child); });
|
278 | childrenBranches.forEach(function (cb) { return result_1 = result_1.concat.apply(result_1, cb); });
|
279 | return result_1;
|
280 | }
|
281 | };
|
282 | DagGraph.prototype.remove = function (commit) {
|
283 | this.graph = this.graph.deleteIn(['states', "" + commit]);
|
284 | };
|
285 | DagGraph.prototype.squashCurrentBranch = function () {
|
286 | var _this = this;
|
287 | var toSquash = [];
|
288 | var branch = this.branchOf(this.currentStateId);
|
289 | var current = this.parentOf(this.currentStateId);
|
290 | var keepSquashing = true;
|
291 | do {
|
292 | if (current && this.branchOf(current) === branch) {
|
293 | toSquash.push(current);
|
294 | current = this.parentOf(current);
|
295 | }
|
296 | else {
|
297 | keepSquashing = false;
|
298 | }
|
299 | } while (keepSquashing);
|
300 | log('squashing %s states on branch %s => ', toSquash.length, branch, current, toSquash);
|
301 | if (toSquash.length > 0) {
|
302 | toSquash.forEach(function (c) { return _this.remove(c); });
|
303 | this.setParent(this.currentStateId, current);
|
304 | }
|
305 | return this;
|
306 | };
|
307 | return DagGraph;
|
308 | }());
|
309 | Object.defineProperty(exports, "__esModule", { value: true });
|
310 | exports.default = DagGraph;
|