mirror of
https://github.com/pcottle/learnGitBranching.git
synced 2025-07-12 23:54:27 +02:00
Git Tag: Initial support for tagging
Branching in git even more useful if using tags. Simulate relase branches, maintenance branches and so on is therefore really useful in this tool. Now, rudimentary tagging is implemented, where tags can be attached to the commits, and referenced by for exmapmle git checkout Signed-off-by: Max Sikström <msikstrom@op5.com>
This commit is contained in:
parent
fa7b918be9
commit
74342e2028
13 changed files with 2009 additions and 29 deletions
|
@ -557,6 +557,24 @@ var commandConfig = {
|
|||
destination: tracking
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
tag: {
|
||||
regex: /^git +tag($|\s)/,
|
||||
execute: function(engine, command) {
|
||||
var generalArgs = command.getGeneralArgs();
|
||||
|
||||
|
||||
if (generalArgs.length === 0) {
|
||||
var tags = engine.getTags();
|
||||
engine.printTags(tags);
|
||||
return;
|
||||
}
|
||||
|
||||
command.twoArgsImpliedHead(generalArgs);
|
||||
engine.tag(generalArgs[0], generalArgs[1]);
|
||||
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -35,6 +35,7 @@ function GitEngine(options) {
|
|||
this.localRepo = null;
|
||||
|
||||
this.branchCollection = options.branches;
|
||||
this.tagCollection = options.tags;
|
||||
this.commitCollection = options.collection;
|
||||
this.gitVisuals = options.gitVisuals;
|
||||
|
||||
|
@ -207,6 +208,7 @@ GitEngine.prototype.exportTree = function() {
|
|||
_.each(this.branchCollection.toJSON(), function(branch) {
|
||||
branch.target = branch.target.get('id');
|
||||
branch.visBranch = undefined;
|
||||
branch.visTag = undefined;
|
||||
|
||||
totalExport.branches[branch.id] = branch;
|
||||
});
|
||||
|
@ -228,8 +230,7 @@ GitEngine.prototype.exportTree = function() {
|
|||
}, this);
|
||||
|
||||
var HEAD = this.HEAD.toJSON();
|
||||
HEAD.visBranch = undefined;
|
||||
HEAD.lastTarget = HEAD.lastLastTarget = HEAD.visBranch = undefined;
|
||||
HEAD.lastTarget = HEAD.lastLastTarget = HEAD.visBranch = HEAD.visTag =undefined;
|
||||
HEAD.target = HEAD.target.get('id');
|
||||
totalExport.HEAD = HEAD;
|
||||
|
||||
|
@ -291,6 +292,12 @@ GitEngine.prototype.instantiateFromTree = function(tree) {
|
|||
this.branchCollection.add(branch, {silent: true});
|
||||
}, this);
|
||||
|
||||
_.each(tree.tags, function(tagJSON) {
|
||||
var tag = this.getOrMakeRecursive(tree, createdSoFar, tagJSON.id);
|
||||
|
||||
this.tagCollection.add(tag, {silent: true});
|
||||
}, this);
|
||||
|
||||
var HEAD = this.getOrMakeRecursive(tree, createdSoFar, tree.HEAD.id);
|
||||
this.HEAD = HEAD;
|
||||
|
||||
|
@ -302,8 +309,11 @@ GitEngine.prototype.instantiateFromTree = function(tree) {
|
|||
|
||||
this.gitVisuals.gitReady = false;
|
||||
this.branchCollection.each(function(branch) {
|
||||
this.gitVisuals.addBranch(branch);
|
||||
}, this);
|
||||
this.gitVisuals.addBranch(branch);
|
||||
}, this);
|
||||
this.tagCollection.each(function(tag) {
|
||||
this.gitVisuals.addTag(tag);
|
||||
}, this);
|
||||
|
||||
if (tree.originTree) {
|
||||
var treeString = JSON.stringify(tree.originTree);
|
||||
|
@ -438,6 +448,19 @@ GitEngine.prototype.getOrMakeRecursive = function(tree, createdSoFar, objID) {
|
|||
return branch;
|
||||
}
|
||||
|
||||
if (type == 'tag') {
|
||||
var tagJSON = tree.tags[objID];
|
||||
|
||||
var tag = new Tag(_.extend(
|
||||
tree.tags[objID],
|
||||
{
|
||||
target: this.getOrMakeRecursive(tree, createdSoFar, tagJSON.target)
|
||||
}
|
||||
));
|
||||
createdSoFar[objID] = tag;
|
||||
return tag;
|
||||
}
|
||||
|
||||
if (type == 'commit') {
|
||||
// for commits, we need to grab all the parents
|
||||
var commitJSON = tree.commits[objID];
|
||||
|
@ -485,6 +508,7 @@ GitEngine.prototype.reloadGraphics = function() {
|
|||
|
||||
GitEngine.prototype.removeAll = function() {
|
||||
this.branchCollection.reset();
|
||||
this.tagCollection.reset();
|
||||
this.commitCollection.reset();
|
||||
this.refs = {};
|
||||
this.HEAD = null;
|
||||
|
@ -551,6 +575,20 @@ GitEngine.prototype.validateAndMakeBranch = function(id, target) {
|
|||
this.makeBranch(id, target);
|
||||
};
|
||||
|
||||
GitEngine.prototype.validateAndMakeTag = function(id, target) {
|
||||
id = this.validateBranchName(id);
|
||||
if (this.refs[id]) {
|
||||
throw new GitError({
|
||||
msg: intl.str(
|
||||
'bad-tag-name',
|
||||
{ tag: name }
|
||||
)
|
||||
});
|
||||
}
|
||||
|
||||
this.makeTag(id, target);
|
||||
};
|
||||
|
||||
GitEngine.prototype.makeBranch = function(id, target) {
|
||||
if (this.refs[id]) {
|
||||
throw new Error('woah already have that');
|
||||
|
@ -565,10 +603,37 @@ GitEngine.prototype.makeBranch = function(id, target) {
|
|||
return branch;
|
||||
};
|
||||
|
||||
GitEngine.prototype.makeTag = function(id, target) {
|
||||
if (this.refs[id]) {
|
||||
throw new Error('woah already have that');
|
||||
}
|
||||
|
||||
var tag = new Tag({
|
||||
target: target,
|
||||
id: id
|
||||
});
|
||||
this.tagCollection.add(tag);
|
||||
this.refs[tag.get('id')] = tag;
|
||||
return tag;
|
||||
};
|
||||
|
||||
GitEngine.prototype.getHead = function() {
|
||||
return _.clone(this.HEAD);
|
||||
};
|
||||
|
||||
GitEngine.prototype.getTags = function() {
|
||||
var toReturn = [];
|
||||
this.tagCollection.each(function(tag) {
|
||||
toReturn.push({
|
||||
id: tag.get('id'),
|
||||
target: tag.get('target'),
|
||||
remote: tag.getIsRemote(),
|
||||
obj: tag
|
||||
});
|
||||
}, this);
|
||||
return toReturn;
|
||||
};
|
||||
|
||||
GitEngine.prototype.getBranches = function() {
|
||||
var toReturn = [];
|
||||
this.branchCollection.each(function(branch) {
|
||||
|
@ -619,6 +684,17 @@ GitEngine.prototype.printBranches = function(branches) {
|
|||
});
|
||||
};
|
||||
|
||||
GitEngine.prototype.printTags = function(tags) {
|
||||
var result = '';
|
||||
_.each(tags, function(tag) {
|
||||
console.log(tag);
|
||||
result += tag.id + '\n';
|
||||
});
|
||||
throw new CommandResult({
|
||||
msg: result
|
||||
});
|
||||
};
|
||||
|
||||
GitEngine.prototype.printRemotes = function(options) {
|
||||
var result = '';
|
||||
if (options.verbose) {
|
||||
|
@ -2063,12 +2139,15 @@ GitEngine.prototype.checkout = function(idOrTarget) {
|
|||
target = this.getCommitFromRef(target.get('id'));
|
||||
}
|
||||
|
||||
if (type !== 'branch' && type !== 'commit') {
|
||||
if (type !== 'branch' && type !== 'tag' && type !== 'commit') {
|
||||
throw new GitError({
|
||||
msg: intl.str('git-error-options')
|
||||
});
|
||||
}
|
||||
|
||||
if (type === 'tag') {
|
||||
target = target.get('target');
|
||||
}
|
||||
|
||||
this.HEAD.set('target', target);
|
||||
};
|
||||
|
||||
|
@ -2102,6 +2181,11 @@ GitEngine.prototype.branch = function(name, ref) {
|
|||
this.validateAndMakeBranch(name, target);
|
||||
};
|
||||
|
||||
GitEngine.prototype.tag = function(name, ref) {
|
||||
var target = this.getCommitFromRef(ref);
|
||||
this.validateAndMakeTag(name, target);
|
||||
};
|
||||
|
||||
GitEngine.prototype.deleteBranch = function(name) {
|
||||
// trying to delete, lets check our refs
|
||||
var target = this.resolveID(name);
|
||||
|
@ -2603,8 +2687,20 @@ var Commit = Backbone.Model.extend({
|
|||
}
|
||||
});
|
||||
|
||||
var Tag = Ref.extend({
|
||||
defaults: {
|
||||
visTag: null
|
||||
},
|
||||
|
||||
initialize: function() {
|
||||
Ref.prototype.initialize.call(this);
|
||||
this.set('type', 'tag');
|
||||
}
|
||||
});
|
||||
|
||||
exports.GitEngine = GitEngine;
|
||||
exports.Commit = Commit;
|
||||
exports.Branch = Branch;
|
||||
exports.Tag = Tag;
|
||||
exports.Ref = Ref;
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ var Backbone = (!require('../util').isBrowser()) ? Backbone = require('backbone'
|
|||
|
||||
var Commit = require('../git').Commit;
|
||||
var Branch = require('../git').Branch;
|
||||
var Tag = require('../git').Tag;
|
||||
|
||||
var Command = require('../models/commandModel').Command;
|
||||
var CommandEntry = require('../models/commandModel').CommandEntry;
|
||||
|
@ -22,6 +23,10 @@ var BranchCollection = Backbone.Collection.extend({
|
|||
model: Branch
|
||||
});
|
||||
|
||||
var TagCollection = Backbone.Collection.extend({
|
||||
model: Tag
|
||||
});
|
||||
|
||||
var CommandEntryCollection = Backbone.Collection.extend({
|
||||
model: CommandEntry,
|
||||
localStorage: (Backbone.LocalStorage) ? new Backbone.LocalStorage('CommandEntries') : null
|
||||
|
@ -125,6 +130,7 @@ var CommandBuffer = Backbone.Model.extend({
|
|||
exports.CommitCollection = CommitCollection;
|
||||
exports.CommandCollection = CommandCollection;
|
||||
exports.BranchCollection = BranchCollection;
|
||||
exports.TagCollection = TagCollection;
|
||||
exports.CommandEntryCollection = CommandEntryCollection;
|
||||
exports.CommandBuffer = CommandBuffer;
|
||||
|
||||
|
|
|
@ -33,6 +33,7 @@ var GRAPHICS = {
|
|||
originDash: '- ',
|
||||
|
||||
multiBranchY: 20,
|
||||
multiTagY: 15,
|
||||
upstreamHeadOpacity: 0.5,
|
||||
upstreamNoneOpacity: 0.2,
|
||||
edgeUpstreamHeadOpacity: 0.4,
|
||||
|
@ -45,6 +46,10 @@ var GRAPHICS = {
|
|||
defaultNodeStrokeWidth: 2,
|
||||
defaultNodeStroke: '#FFF',
|
||||
|
||||
tagFill: 'hsb(0,0,0.9)',
|
||||
tagStroke: '#FFF',
|
||||
tagStrokeWidth: '2',
|
||||
|
||||
orphanNodeFill: 'hsb(0.5,0.8,0.7)'
|
||||
};
|
||||
|
||||
|
|
|
@ -8,10 +8,13 @@ var GLOBAL = require('../util/constants').GLOBAL;
|
|||
var Collections = require('../models/collections');
|
||||
var CommitCollection = Collections.CommitCollection;
|
||||
var BranchCollection = Collections.BranchCollection;
|
||||
var TagCollection = Collections.TagCollection;
|
||||
|
||||
var VisNode = require('../visuals/visNode').VisNode;
|
||||
var VisBranch = require('../visuals/visBranch').VisBranch;
|
||||
var VisBranchCollection = require('../visuals/visBranch').VisBranchCollection;
|
||||
var VisTag = require('../visuals/visTag').VisTag;
|
||||
var VisTagCollection = require('../visuals/visTag').VisTagCollection;
|
||||
var VisEdge = require('../visuals/visEdge').VisEdge;
|
||||
var VisEdgeCollection = require('../visuals/visEdge').VisEdgeCollection;
|
||||
|
||||
|
@ -21,14 +24,17 @@ function GitVisuals(options) {
|
|||
this.visualization = options.visualization;
|
||||
this.commitCollection = options.commitCollection;
|
||||
this.branchCollection = options.branchCollection;
|
||||
this.tagCollection = options.tagCollection;
|
||||
this.visNodeMap = {};
|
||||
|
||||
this.visEdgeCollection = new VisEdgeCollection();
|
||||
this.visBranchCollection = new VisBranchCollection();
|
||||
this.visTagCollection = new VisTagCollection();
|
||||
this.commitMap = {};
|
||||
|
||||
this.rootCommit = null;
|
||||
this.branchStackMap = null;
|
||||
this.tagStackMap = null;
|
||||
this.upstreamBranchSet = null;
|
||||
this.upstreamHeadSet = null;
|
||||
|
||||
|
@ -37,6 +43,10 @@ function GitVisuals(options) {
|
|||
|
||||
this.branchCollection.on('add', this.addBranchFromEvent, this);
|
||||
this.branchCollection.on('remove', this.removeBranch, this);
|
||||
|
||||
this.tagCollection.on('add', this.addTagFromEvent, this);
|
||||
this.tagCollection.on('remove', this.removeTag, this);
|
||||
|
||||
this.deferred = [];
|
||||
|
||||
this.flipFraction = 0.65;
|
||||
|
@ -69,12 +79,18 @@ GitVisuals.prototype.resetAll = function() {
|
|||
visBranch.remove();
|
||||
}, this);
|
||||
|
||||
var tags = this.visTagCollection.toArray();
|
||||
_.each(tags, function(visTag) {
|
||||
visTag.remove();
|
||||
}, this);
|
||||
|
||||
_.each(this.visNodeMap, function(visNode) {
|
||||
visNode.remove();
|
||||
}, this);
|
||||
|
||||
this.visEdgeCollection.reset();
|
||||
this.visBranchCollection.reset();
|
||||
this.visTagsCollection.reset();
|
||||
|
||||
this.visNodeMap = {};
|
||||
this.rootCommit = null;
|
||||
|
@ -178,6 +194,7 @@ GitVisuals.prototype.animateAllAttrKeys = function(keys, attr, speed, easing) {
|
|||
|
||||
this.visBranchCollection.each(animate);
|
||||
this.visEdgeCollection.each(animate);
|
||||
this.visTagCollection.each(animate);
|
||||
_.each(this.visNodeMap, animate);
|
||||
|
||||
var time = (speed !== undefined) ? speed : GRAPHICS.defaultAnimationTime;
|
||||
|
@ -334,6 +351,7 @@ GitVisuals.prototype.animateAllFromAttrToAttr = function(fromSnapshot, toSnapsho
|
|||
|
||||
this.visBranchCollection.each(animate);
|
||||
this.visEdgeCollection.each(animate);
|
||||
this.visTagCollection.each(animate);
|
||||
_.each(this.visNodeMap, animate);
|
||||
};
|
||||
|
||||
|
@ -370,6 +388,10 @@ GitVisuals.prototype.genSnapshot = function() {
|
|||
snapshot[visEdge.getID()] = visEdge.getAttributes();
|
||||
}, this);
|
||||
|
||||
this.visTagCollection.each(function(visTag) {
|
||||
snapshot[visTag.getID()] = visTag.getAttributes();
|
||||
}, this);
|
||||
|
||||
return snapshot;
|
||||
};
|
||||
|
||||
|
@ -411,6 +433,7 @@ GitVisuals.prototype.calcTreeCoords = function() {
|
|||
|
||||
this.calcUpstreamSets();
|
||||
this.calcBranchStacks();
|
||||
this.calcTagStacks();
|
||||
|
||||
this.calcDepth();
|
||||
this.calcWidth();
|
||||
|
@ -420,6 +443,9 @@ GitVisuals.prototype.calcGraphicsCoords = function() {
|
|||
this.visBranchCollection.each(function(visBranch) {
|
||||
visBranch.updateName();
|
||||
});
|
||||
this.visTagCollection.each(function(visTag) {
|
||||
visTag.updateName();
|
||||
});
|
||||
};
|
||||
|
||||
GitVisuals.prototype.calcUpstreamSets = function() {
|
||||
|
@ -496,6 +522,23 @@ GitVisuals.prototype.calcBranchStacks = function() {
|
|||
this.branchStackMap = map;
|
||||
};
|
||||
|
||||
GitVisuals.prototype.calcTagStacks = function() {
|
||||
var tags = this.gitEngine.getTags();
|
||||
var map = {};
|
||||
_.each(tags, function(tag) {
|
||||
var thisId = tag.target.get('id');
|
||||
|
||||
map[thisId] = map[thisId] || [];
|
||||
map[thisId].push(tag);
|
||||
map[thisId].sort(function(a, b) {
|
||||
var aId = a.obj.get('id');
|
||||
var bId = b.obj.get('id');
|
||||
return aId.localeCompare(bId);
|
||||
});
|
||||
});
|
||||
this.tagStackMap = map;
|
||||
};
|
||||
|
||||
GitVisuals.prototype.calcWidth = function() {
|
||||
this.maxWidthRecursive(this.rootCommit);
|
||||
|
||||
|
@ -626,10 +669,44 @@ GitVisuals.prototype.addBranch = function(branch) {
|
|||
}
|
||||
};
|
||||
|
||||
GitVisuals.prototype.addTagFromEvent = function(tag, collection, index) {
|
||||
var action = _.bind(function() {
|
||||
this.addTag(tag);
|
||||
}, this);
|
||||
|
||||
if (!this.gitEngine || !this.gitReady) {
|
||||
this.defer(action);
|
||||
} else {
|
||||
action();
|
||||
}
|
||||
};
|
||||
|
||||
GitVisuals.prototype.addTag = function(tag) {
|
||||
var visTag = new VisTag({
|
||||
tag: tag,
|
||||
gitVisuals: this,
|
||||
gitEngine: this.gitEngine
|
||||
});
|
||||
|
||||
this.visTagCollection.add(visTag);
|
||||
if (this.gitReady) {
|
||||
visTag.genGraphics(this.paper);
|
||||
} else {
|
||||
this.defer(_.bind(function() {
|
||||
visTag.genGraphics(this.paper);
|
||||
}, this));
|
||||
}
|
||||
};
|
||||
|
||||
GitVisuals.prototype.removeVisBranch = function(visBranch) {
|
||||
this.visBranchCollection.remove(visBranch);
|
||||
};
|
||||
|
||||
GitVisuals.prototype.removeVisTag = function(visTag) {
|
||||
this.visTagCollection.remove(visTag);
|
||||
};
|
||||
|
||||
|
||||
GitVisuals.prototype.removeVisNode = function(visNode) {
|
||||
delete this.visNodeMap[visNode.getID()];
|
||||
};
|
||||
|
@ -642,6 +719,9 @@ GitVisuals.prototype.animateRefs = function(speed) {
|
|||
this.visBranchCollection.each(function(visBranch) {
|
||||
visBranch.animateUpdatedPos(speed);
|
||||
}, this);
|
||||
this.visTagCollection.each(function(visTag) {
|
||||
visTag.animateUpdatedPos(speed);
|
||||
}, this);
|
||||
};
|
||||
|
||||
GitVisuals.prototype.animateEdges = function(speed) {
|
||||
|
@ -756,6 +836,7 @@ GitVisuals.prototype.addEdge = function(idTail, idHead) {
|
|||
GitVisuals.prototype.zIndexReflow = function() {
|
||||
this.visNodesFront();
|
||||
this.visBranchesFront();
|
||||
this.visTagsFront();
|
||||
};
|
||||
|
||||
GitVisuals.prototype.visNodesFront = function() {
|
||||
|
@ -775,6 +856,17 @@ GitVisuals.prototype.visBranchesFront = function() {
|
|||
});
|
||||
};
|
||||
|
||||
GitVisuals.prototype.visTagsFront = function() {
|
||||
this.visTagCollection.each(function(vTag) {
|
||||
vTag.nonTextToFront();
|
||||
vTag.textToFront();
|
||||
});
|
||||
|
||||
this.visTagCollection.each(function(vTag) {
|
||||
vTag.textToFrontIfInStack();
|
||||
});
|
||||
};
|
||||
|
||||
GitVisuals.prototype.drawTreeFromReload = function() {
|
||||
this.gitReady = true;
|
||||
// gen all the graphics we need
|
||||
|
@ -799,6 +891,10 @@ GitVisuals.prototype.drawTreeFirstTime = function() {
|
|||
visBranch.genGraphics(this.paper);
|
||||
}, this);
|
||||
|
||||
this.visTagCollection.each(function(visTag) {
|
||||
visTag.genGraphics(this.paper);
|
||||
}, this);
|
||||
|
||||
this.zIndexReflow();
|
||||
};
|
||||
|
||||
|
|
|
@ -130,6 +130,7 @@ var VisEdge = VisBase.extend({
|
|||
var stat = this.gitVisuals.getCommitUpstreamStatus(this.get('tail'));
|
||||
var map = {
|
||||
'branch': 1,
|
||||
'tag': 1,
|
||||
'head': GRAPHICS.edgeUpstreamHeadOpacity,
|
||||
'none': GRAPHICS.edgeUpstreamNoneOpacity
|
||||
};
|
||||
|
|
|
@ -74,6 +74,7 @@ var VisNode = VisBase.extend({
|
|||
var stat = this.gitVisuals.getCommitUpstreamStatus(this.get('commit'));
|
||||
var map = {
|
||||
branch: 1,
|
||||
tag: 1,
|
||||
head: 0.3,
|
||||
none: 0.1
|
||||
};
|
||||
|
@ -89,6 +90,7 @@ var VisNode = VisBase.extend({
|
|||
getOpacity: function() {
|
||||
var map = {
|
||||
'branch': 1,
|
||||
'tag' : 1,
|
||||
'head': GRAPHICS.upstreamHeadOpacity,
|
||||
'none': GRAPHICS.upstreamNoneOpacity
|
||||
};
|
||||
|
|
429
src/js/visuals/visTag.js
Normal file
429
src/js/visuals/visTag.js
Normal file
|
@ -0,0 +1,429 @@
|
|||
var _ = require('underscore');
|
||||
var Backbone = require('backbone');
|
||||
var GRAPHICS = require('../util/constants').GRAPHICS;
|
||||
|
||||
var VisBase = require('../visuals/visBase').VisBase;
|
||||
var TreeCompare = require('../git/treeCompare').TreeCompare;
|
||||
|
||||
var randomHueString = function() {
|
||||
var hue = Math.random();
|
||||
var str = 'hsb(' + String(hue) + ',0.7,1)';
|
||||
return str;
|
||||
};
|
||||
|
||||
var VisTag = VisBase.extend({
|
||||
defaults: {
|
||||
pos: null,
|
||||
text: null,
|
||||
rect: null,
|
||||
isHead: false,
|
||||
|
||||
fill: GRAPHICS.tagFill,
|
||||
stroke: GRAPHICS.tagStroke,
|
||||
'stroke-width': GRAPHICS.tagStrokeWidth,
|
||||
|
||||
offsetX: GRAPHICS.nodeRadius,
|
||||
offsetY: GRAPHICS.nodeRadius,
|
||||
|
||||
vPad: 2,
|
||||
hPad: 2,
|
||||
|
||||
animationSpeed: GRAPHICS.defaultAnimationTime,
|
||||
animationEasing: GRAPHICS.defaultEasing
|
||||
},
|
||||
|
||||
validateAtInit: function() {
|
||||
if (!this.get('tag')) {
|
||||
throw new Error('need a Tag!');
|
||||
}
|
||||
},
|
||||
|
||||
getID: function() {
|
||||
return this.get('tag').get('id');
|
||||
},
|
||||
|
||||
initialize: function() {
|
||||
this.validateAtInit();
|
||||
|
||||
// shorthand notation for the main objects
|
||||
this.gitVisuals = this.get('gitVisuals');
|
||||
this.gitEngine = this.get('gitEngine');
|
||||
if (!this.gitEngine) {
|
||||
throw new Error('asd wtf');
|
||||
}
|
||||
|
||||
this.get('tag').set('visTag', this);
|
||||
},
|
||||
|
||||
getCommitPosition: function() {
|
||||
var commit = this.gitEngine.getCommitFromRef(this.get('tag'));
|
||||
var visNode = commit.get('visNode');
|
||||
|
||||
return visNode.getScreenCoords();
|
||||
},
|
||||
|
||||
getDashArray: function() {
|
||||
if (!this.get('gitVisuals').getIsGoalVis()) {
|
||||
return '';
|
||||
}
|
||||
return (this.getIsLevelTagCompared()) ? '' : '--';
|
||||
},
|
||||
|
||||
getIsGoalAndNotCompared: function() {
|
||||
if (!this.get('gitVisuals').getIsGoalVis()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return !this.getIsLevelTagCompared();
|
||||
},
|
||||
|
||||
/**
|
||||
* returns true if we are a Tag that is not being
|
||||
* compared in the goal (used in a goal visualization context
|
||||
*/
|
||||
getIsLevelTagCompared: function() {
|
||||
if (this.getIsMaster()) {
|
||||
return true; // master always compared
|
||||
}
|
||||
// we are not master, so return true if its not just master being compared
|
||||
var levelBlob = this.get('gitVisuals').getLevelBlob();
|
||||
return !TreeCompare.onlyMasterCompared(levelBlob);
|
||||
},
|
||||
|
||||
getIsMaster: function() {
|
||||
return this.get('tag').get('id') == 'master';
|
||||
},
|
||||
|
||||
getArrowTransform: function() {
|
||||
return 't2,20R-35';
|
||||
},
|
||||
|
||||
getTagStackIndex: function() {
|
||||
if (this.get('isHead')) {
|
||||
// head is never stacked with other Tages
|
||||
return 0;
|
||||
}
|
||||
|
||||
var myArray = this.getTagStackArray();
|
||||
var index = -1;
|
||||
_.each(myArray, function(Tag, i) {
|
||||
if (Tag.obj == this.get('tag')) {
|
||||
index = i;
|
||||
}
|
||||
}, this);
|
||||
return index;
|
||||
},
|
||||
|
||||
getTagStackLength: function() {
|
||||
if (this.get('isHead')) {
|
||||
// head is always by itself
|
||||
return 1;
|
||||
}
|
||||
|
||||
return this.getTagStackArray().length;
|
||||
},
|
||||
|
||||
isTagStackEmpty: function() {
|
||||
// useful function for head when computing flip logic
|
||||
var arr = this.gitVisuals.tagStackMap[this.getCommitID()];
|
||||
return (arr) ?
|
||||
arr.length === 0 :
|
||||
true;
|
||||
},
|
||||
|
||||
getCommitID: function() {
|
||||
var target = this.get('tag').get('target');
|
||||
if (target.get('type') === 'tag') {
|
||||
// for HEAD
|
||||
target = target.get('target');
|
||||
}
|
||||
return target.get('id');
|
||||
},
|
||||
|
||||
getTagStackArray: function() {
|
||||
var arr = this.gitVisuals.tagStackMap[this.getCommitID()];
|
||||
if (arr === undefined) {
|
||||
// this only occurs when we are generating graphics inside of
|
||||
// a new Tag instantiation, so we need to force the update
|
||||
this.gitVisuals.calcTagStacks();
|
||||
return this.getTagStackArray();
|
||||
}
|
||||
return arr;
|
||||
},
|
||||
|
||||
getTextPosition: function() {
|
||||
var pos = this.getCommitPosition();
|
||||
|
||||
// then order yourself accordingly. we use alphabetical sorting
|
||||
// so everything is independent
|
||||
var myPos = this.getTagStackIndex();
|
||||
|
||||
return {
|
||||
x: pos.x + this.get('offsetX'),
|
||||
y: pos.y + myPos * GRAPHICS.multiTagY + this.get('offsetY')
|
||||
};
|
||||
},
|
||||
|
||||
getRectPosition: function() {
|
||||
var pos = this.getTextPosition();
|
||||
|
||||
// first get text width and height
|
||||
var textSize = this.getTextSize();
|
||||
return {
|
||||
x: pos.x - this.get('hPad'),
|
||||
y: pos.y - 0.5 * textSize.h - this.get('vPad')
|
||||
};
|
||||
},
|
||||
|
||||
getTextSize: function() {
|
||||
var getTextWidth = function(visTag) {
|
||||
var textNode = (visTag.get('text')) ? visTag.get('text').node : null;
|
||||
return (textNode === null) ? 0 : textNode.clientWidth;
|
||||
};
|
||||
|
||||
var firefoxFix = function(obj) {
|
||||
if (!obj.w) { obj.w = 75; }
|
||||
if (!obj.h) { obj.h = 20; }
|
||||
return obj;
|
||||
};
|
||||
|
||||
var textNode = this.get('text').node;
|
||||
|
||||
var maxWidth = 0;
|
||||
_.each(this.getTagStackArray(), function(Tag) {
|
||||
maxWidth = Math.max(maxWidth, getTextWidth(
|
||||
Tag.obj.get('visTag')
|
||||
));
|
||||
});
|
||||
|
||||
return firefoxFix({
|
||||
w: maxWidth,
|
||||
h: textNode.clientHeight
|
||||
});
|
||||
},
|
||||
|
||||
getSingleRectSize: function() {
|
||||
var textSize = this.getTextSize();
|
||||
var vPad = this.get('vPad');
|
||||
var hPad = this.get('hPad');
|
||||
return {
|
||||
w: textSize.w + vPad * 2,
|
||||
h: textSize.h + hPad * 2
|
||||
};
|
||||
},
|
||||
|
||||
getRectSize: function() {
|
||||
var textSize = this.getTextSize();
|
||||
// enforce padding
|
||||
var vPad = this.get('vPad');
|
||||
var hPad = this.get('hPad');
|
||||
|
||||
// number of other Tag names we are housing
|
||||
var totalNum = this.getTagStackLength();
|
||||
return {
|
||||
w: textSize.w + vPad * 2,
|
||||
h: textSize.h * totalNum + hPad * 2
|
||||
};
|
||||
},
|
||||
|
||||
getIsRemote: function() {
|
||||
return this.get('tag').getIsRemote();
|
||||
},
|
||||
|
||||
getName: function() {
|
||||
var name = this.get('tag').getName();
|
||||
var selected = this.get('tag') === this.gitEngine.HEAD.get('target');
|
||||
var isRemote = this.getIsRemote();
|
||||
var isHg = this.gitEngine.getIsHg();
|
||||
|
||||
if (name === 'HEAD' && isHg) {
|
||||
name = '.';
|
||||
}
|
||||
|
||||
var after = (selected && !this.getIsInOrigin() && !isRemote) ? '*' : '';
|
||||
return name + after;
|
||||
},
|
||||
|
||||
nonTextToFront: function() {
|
||||
this.get('rect').toFront();
|
||||
},
|
||||
|
||||
textToFront: function() {
|
||||
this.get('text').toFront();
|
||||
},
|
||||
|
||||
textToFrontIfInStack: function() {
|
||||
if (this.getTagStackIndex() !== 0) {
|
||||
this.get('text').toFront();
|
||||
}
|
||||
},
|
||||
|
||||
remove: function() {
|
||||
this.removeKeys(['text', 'rect']);
|
||||
// also need to remove from this.gitVisuals
|
||||
this.gitVisuals.removeVisTag(this);
|
||||
},
|
||||
|
||||
handleModeChange: function() {
|
||||
|
||||
},
|
||||
|
||||
genGraphics: function(paper) {
|
||||
var textPos = this.getTextPosition();
|
||||
var name = this.getName();
|
||||
|
||||
// when from a reload, we dont need to generate the text
|
||||
var text = paper.text(textPos.x, textPos.y, String(name));
|
||||
text.attr({
|
||||
'font-size': 14,
|
||||
'font-family': 'Monaco, Courier, font-monospace',
|
||||
opacity: this.getTextOpacity(),
|
||||
'text-anchor': 'start'
|
||||
});
|
||||
this.set('text', text);
|
||||
var attr = this.getAttributes();
|
||||
|
||||
var rectPos = this.getRectPosition();
|
||||
var sizeOfRect = this.getRectSize();
|
||||
var rect = paper
|
||||
.rect(rectPos.x, rectPos.y, sizeOfRect.w, sizeOfRect.h, 8)
|
||||
.attr(attr.rect);
|
||||
this.set('rect', rect);
|
||||
|
||||
// set CSS
|
||||
var keys = ['text', 'rect'];
|
||||
_.each(keys, function(key) {
|
||||
$(this.get(key).node).css(attr.css);
|
||||
}, this);
|
||||
|
||||
this.attachClickHandlers();
|
||||
rect.toFront();
|
||||
text.toFront();
|
||||
},
|
||||
|
||||
attachClickHandlers: function() {
|
||||
if (this.get('gitVisuals').options.noClick) {
|
||||
return;
|
||||
}
|
||||
var objs = [
|
||||
this.get('rect'),
|
||||
this.get('text')
|
||||
];
|
||||
|
||||
_.each(objs, function(rObj) {
|
||||
rObj.click(_.bind(this.onClick ,this));
|
||||
}, this);
|
||||
},
|
||||
|
||||
shouldDisableClick: function() {
|
||||
return this.get('isHead') && !this.gitEngine.getDetachedHead();
|
||||
},
|
||||
|
||||
onClick: function() {
|
||||
if (this.shouldDisableClick()) {
|
||||
return;
|
||||
}
|
||||
|
||||
var commandStr = 'git checkout ' + this.get('tag').get('id');
|
||||
var Main = require('../app');
|
||||
Main.getEventBaton().trigger('commandSubmitted', commandStr);
|
||||
},
|
||||
|
||||
updateName: function() {
|
||||
this.get('text').attr({
|
||||
text: this.getName()
|
||||
});
|
||||
},
|
||||
|
||||
getNonTextOpacity: function() {
|
||||
if (this.get('isHead')) {
|
||||
return this.gitEngine.getDetachedHead() ? 1 : 0;
|
||||
}
|
||||
if (this.getTagStackIndex() !== 0) {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
},
|
||||
|
||||
getTextOpacity: function() {
|
||||
if (this.get('isHead')) {
|
||||
return this.gitEngine.getDetachedHead() ? 1 : 0;
|
||||
}
|
||||
|
||||
if (this.getIsGoalAndNotCompared()) {
|
||||
return (this.getTagStackIndex() === 0) ? 0.7 : 0.3;
|
||||
}
|
||||
|
||||
return 1;
|
||||
},
|
||||
|
||||
getStrokeWidth: function() {
|
||||
if (this.getIsGoalAndNotCompared()) {
|
||||
return this.get('stroke-width') / 5.0;
|
||||
}
|
||||
|
||||
return this.get('stroke-width');
|
||||
},
|
||||
|
||||
getAttributes: function() {
|
||||
var textOpacity = this.getTextOpacity();
|
||||
this.updateName();
|
||||
|
||||
var textPos = this.getTextPosition();
|
||||
var rectPos = this.getRectPosition();
|
||||
var rectSize = this.getRectSize();
|
||||
|
||||
var dashArray = this.getDashArray();
|
||||
var cursorStyle = (this.shouldDisableClick()) ?
|
||||
'auto' :
|
||||
'pointer';
|
||||
|
||||
return {
|
||||
css: {
|
||||
cursor: cursorStyle
|
||||
},
|
||||
text: {
|
||||
x: textPos.x,
|
||||
y: textPos.y,
|
||||
opacity: textOpacity
|
||||
},
|
||||
rect: {
|
||||
x: rectPos.x,
|
||||
y: rectPos.y,
|
||||
width: rectSize.w,
|
||||
height: rectSize.h,
|
||||
opacity: this.getNonTextOpacity(),
|
||||
fill: this.get('fill'),
|
||||
stroke: this.get('stroke'),
|
||||
'stroke-dasharray': dashArray,
|
||||
'stroke-width': this.getStrokeWidth()
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
animateUpdatedPos: function(speed, easing) {
|
||||
var attr = this.getAttributes();
|
||||
this.animateToAttr(attr, speed, easing);
|
||||
},
|
||||
|
||||
animateFromAttrToAttr: function(fromAttr, toAttr, speed, easing) {
|
||||
// an animation of 0 is essentially setting the attribute directly
|
||||
this.animateToAttr(fromAttr, 0);
|
||||
this.animateToAttr(toAttr, speed, easing);
|
||||
},
|
||||
|
||||
setAttr: function(attr, instant, speed, easing) {
|
||||
var keys = ['text', 'rect'];
|
||||
this.setAttrBase(keys, attr, instant, speed, easing);
|
||||
}
|
||||
});
|
||||
|
||||
var VisTagCollection = Backbone.Collection.extend({
|
||||
model: VisTag
|
||||
});
|
||||
|
||||
exports.VisTagCollection = VisTagCollection;
|
||||
exports.VisTag = VisTag;
|
||||
exports.randomHueString = randomHueString;
|
||||
|
|
@ -5,6 +5,7 @@ var Backbone = (!require('../util').isBrowser()) ? Backbone = require('backbone'
|
|||
var Collections = require('../models/collections');
|
||||
var CommitCollection = Collections.CommitCollection;
|
||||
var BranchCollection = Collections.BranchCollection;
|
||||
var TagCollection = Collections.TagCollection;
|
||||
var EventBaton = require('../util/eventBaton').EventBaton;
|
||||
|
||||
var GitVisuals = require('../visuals').GitVisuals;
|
||||
|
@ -43,10 +44,12 @@ var Visualization = Backbone.View.extend({
|
|||
|
||||
this.commitCollection = new CommitCollection();
|
||||
this.branchCollection = new BranchCollection();
|
||||
this.tagCollection = new TagCollection();
|
||||
|
||||
this.gitVisuals = new GitVisuals({
|
||||
commitCollection: this.commitCollection,
|
||||
branchCollection: this.branchCollection,
|
||||
tagCollection: this.tagCollection,
|
||||
paper: this.paper,
|
||||
noClick: this.options.noClick,
|
||||
isGoalVis: this.options.isGoalVis,
|
||||
|
@ -58,6 +61,7 @@ var Visualization = Backbone.View.extend({
|
|||
this.gitEngine = new GitEngine({
|
||||
collection: this.commitCollection,
|
||||
branches: this.branchCollection,
|
||||
tags: this.tagCollection,
|
||||
gitVisuals: this.gitVisuals,
|
||||
eventBaton: this.eventBaton
|
||||
});
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue