use of com.gitblit.models.TicketModel.Patchset in project gitblit by gitblit.
the class TicketIndexer method ticketToDoc.
/**
* Creates a Lucene document from a ticket.
*
* @param ticket
* @return a Lucene document
*/
private Document ticketToDoc(TicketModel ticket) {
Document doc = new Document();
// repository and document ids for Lucene querying
toDocField(doc, Lucene.rid, StringUtils.getSHA1(ticket.repository));
toDocField(doc, Lucene.did, StringUtils.getSHA1(ticket.repository + ticket.number));
toDocField(doc, Lucene.project, ticket.project);
toDocField(doc, Lucene.repository, ticket.repository);
toDocField(doc, Lucene.number, ticket.number);
toDocField(doc, Lucene.title, ticket.title);
toDocField(doc, Lucene.body, ticket.body);
toDocField(doc, Lucene.created, ticket.created);
toDocField(doc, Lucene.createdby, ticket.createdBy);
toDocField(doc, Lucene.updated, ticket.updated);
toDocField(doc, Lucene.updatedby, ticket.updatedBy);
toDocField(doc, Lucene.responsible, ticket.responsible);
toDocField(doc, Lucene.milestone, ticket.milestone);
toDocField(doc, Lucene.topic, ticket.topic);
toDocField(doc, Lucene.status, ticket.status.name());
toDocField(doc, Lucene.comments, ticket.getComments().size());
toDocField(doc, Lucene.type, ticket.type == null ? null : ticket.type.name());
toDocField(doc, Lucene.mergesha, ticket.mergeSha);
toDocField(doc, Lucene.mergeto, ticket.mergeTo);
toDocField(doc, Lucene.labels, StringUtils.flattenStrings(ticket.getLabels(), ";").toLowerCase());
toDocField(doc, Lucene.participants, StringUtils.flattenStrings(ticket.getParticipants(), ";").toLowerCase());
toDocField(doc, Lucene.watchedby, StringUtils.flattenStrings(ticket.getWatchers(), ";").toLowerCase());
toDocField(doc, Lucene.mentions, StringUtils.flattenStrings(ticket.getMentions(), ";").toLowerCase());
toDocField(doc, Lucene.votes, ticket.getVoters().size());
toDocField(doc, Lucene.priority, ticket.priority.getValue());
toDocField(doc, Lucene.severity, ticket.severity.getValue());
List<String> attachments = new ArrayList<String>();
for (Attachment attachment : ticket.getAttachments()) {
attachments.add(attachment.name.toLowerCase());
}
toDocField(doc, Lucene.attachments, StringUtils.flattenStrings(attachments, ";"));
List<Patchset> patches = ticket.getPatchsets();
if (!patches.isEmpty()) {
toDocField(doc, Lucene.patchsets, patches.size());
Patchset patchset = patches.get(patches.size() - 1);
String flat = patchset.number + ":" + patchset.rev + ":" + patchset.tip + ":" + patchset.base + ":" + patchset.commits;
doc.add(new org.apache.lucene.document.Field(Lucene.patchset.name(), flat, TextField.TYPE_STORED));
}
doc.add(new TextField(Lucene.content.name(), ticket.toIndexableString(), Store.NO));
return doc;
}
use of com.gitblit.models.TicketModel.Patchset in project gitblit by gitblit.
the class TicketPage method createMergePanel.
/**
* Adds a merge panel for the patchset to the markup container. The panel
* may just a message if the patchset can not be merged.
*
* @param c
* @param user
* @param repository
*/
protected Component createMergePanel(UserModel user, RepositoryModel repository) {
Patchset patchset = ticket.getCurrentPatchset();
if (patchset == null) {
// no patchset to merge
return new Label("mergePanel");
}
boolean allowMerge;
if (repository.requireApproval) {
// repository requires approval
allowMerge = ticket.isOpen() && ticket.isApproved(patchset);
} else {
// vetoes are binding
allowMerge = ticket.isOpen() && !ticket.isVetoed(patchset);
}
MergeStatus mergeStatus = JGitUtils.canMerge(getRepository(), patchset.tip, ticket.mergeTo, repository.mergeType);
if (allowMerge) {
if (MergeStatus.MERGEABLE == mergeStatus) {
// patchset can be cleanly merged to integration branch OR has already been merged
Fragment mergePanel = new Fragment("mergePanel", "mergeableFragment", this);
mergePanel.add(new Label("mergeTitle", MessageFormat.format(getString("gb.patchsetMergeable"), ticket.mergeTo)));
if (user.canPush(repository)) {
// user can merge locally
SimpleAjaxLink<String> mergeButton = new SimpleAjaxLink<String>("mergeButton", Model.of(getString("gb.merge"))) {
private static final long serialVersionUID = 1L;
@Override
public void onClick(AjaxRequestTarget target) {
// ensure the patchset is still current AND not vetoed
Patchset patchset = ticket.getCurrentPatchset();
final TicketModel refreshedTicket = app().tickets().getTicket(getRepositoryModel(), ticket.number);
if (patchset.equals(refreshedTicket.getCurrentPatchset())) {
// patchset is current, check for recent veto
if (!refreshedTicket.isVetoed(patchset)) {
// patchset is not vetoed
// execute the merge using the ticket service
app().tickets().exec(new Runnable() {
@Override
public void run() {
PatchsetReceivePack rp = new PatchsetReceivePack(app().gitblit(), getRepository(), getRepositoryModel(), GitBlitWebSession.get().getUser());
MergeStatus result = rp.merge(refreshedTicket);
if (MergeStatus.MERGED == result) {
// notify participants and watchers
rp.sendAll();
} else {
// merge failure
String msg = MessageFormat.format("Failed to merge ticket {0,number,0}: {1}", ticket.number, result.name());
logger.error(msg);
GitBlitWebSession.get().cacheErrorMessage(msg);
}
}
});
} else {
// vetoed patchset
String msg = MessageFormat.format("Can not merge ticket {0,number,0}, patchset {1,number,0} has been vetoed!", ticket.number, patchset.number);
GitBlitWebSession.get().cacheErrorMessage(msg);
logger.error(msg);
}
} else {
// not current patchset
String msg = MessageFormat.format("Can not merge ticket {0,number,0}, the patchset has been updated!", ticket.number);
GitBlitWebSession.get().cacheErrorMessage(msg);
logger.error(msg);
}
redirectTo(TicketsPage.class, getPageParameters());
}
};
mergePanel.add(mergeButton);
Component instructions = getMergeInstructions(user, repository, "mergeMore", "gb.patchsetMergeableMore");
mergePanel.add(instructions);
} else {
mergePanel.add(new Label("mergeButton").setVisible(false));
mergePanel.add(new Label("mergeMore").setVisible(false));
}
return mergePanel;
} else if (MergeStatus.ALREADY_MERGED == mergeStatus) {
// patchset already merged
Fragment mergePanel = new Fragment("mergePanel", "alreadyMergedFragment", this);
mergePanel.add(new Label("mergeTitle", MessageFormat.format(getString("gb.patchsetAlreadyMerged"), ticket.mergeTo)));
return mergePanel;
} else if (MergeStatus.MISSING_INTEGRATION_BRANCH == mergeStatus) {
// target/integration branch is missing
Fragment mergePanel = new Fragment("mergePanel", "notMergeableFragment", this);
mergePanel.add(new Label("mergeTitle", MessageFormat.format(getString("gb.patchsetNotMergeable"), ticket.mergeTo)));
mergePanel.add(new Label("mergeMore", MessageFormat.format(getString("gb.missingIntegrationBranchMore"), ticket.mergeTo)));
return mergePanel;
} else {
// patchset can not be cleanly merged
Fragment mergePanel = new Fragment("mergePanel", "notMergeableFragment", this);
mergePanel.add(new Label("mergeTitle", MessageFormat.format(getString("gb.patchsetNotMergeable"), ticket.mergeTo)));
if (user.canPush(repository)) {
// user can merge locally
Component instructions = getMergeInstructions(user, repository, "mergeMore", "gb.patchsetNotMergeableMore");
mergePanel.add(instructions);
} else {
mergePanel.add(new Label("mergeMore").setVisible(false));
}
return mergePanel;
}
} else {
// merge not allowed
if (MergeStatus.ALREADY_MERGED == mergeStatus) {
// patchset already merged
Fragment mergePanel = new Fragment("mergePanel", "alreadyMergedFragment", this);
mergePanel.add(new Label("mergeTitle", MessageFormat.format(getString("gb.patchsetAlreadyMerged"), ticket.mergeTo)));
return mergePanel;
} else if (ticket.isVetoed(patchset)) {
// patchset has been vetoed
Fragment mergePanel = new Fragment("mergePanel", "vetoedFragment", this);
mergePanel.add(new Label("mergeTitle", MessageFormat.format(getString("gb.patchsetNotMergeable"), ticket.mergeTo)));
return mergePanel;
} else if (repository.requireApproval) {
// patchset has been not been approved for merge
Fragment mergePanel = new Fragment("mergePanel", "notApprovedFragment", this);
mergePanel.add(new Label("mergeTitle", MessageFormat.format(getString("gb.patchsetNotApproved"), ticket.mergeTo)));
mergePanel.add(new Label("mergeMore", MessageFormat.format(getString("gb.patchsetNotApprovedMore"), ticket.mergeTo)));
return mergePanel;
} else {
// other case
return new Label("mergePanel");
}
}
}
use of com.gitblit.models.TicketModel.Patchset in project gitblit by gitblit.
the class TicketPage method createPatchsetPanel.
protected Fragment createPatchsetPanel(String wicketId, RepositoryModel repository, UserModel user) {
final Patchset currentPatchset = ticket.getCurrentPatchset();
List<Patchset> patchsets = new ArrayList<Patchset>(ticket.getPatchsetRevisions(currentPatchset.number));
patchsets.remove(currentPatchset);
Collections.reverse(patchsets);
Fragment panel = new Fragment(wicketId, "collapsiblePatchsetFragment", this);
// patchset header
String ps = "<b>" + currentPatchset.number + "</b>";
if (currentPatchset.rev == 1) {
panel.add(new Label("uploadedWhat", MessageFormat.format(getString("gb.uploadedPatchsetN"), ps)).setEscapeModelStrings(false));
} else {
String rev = "<b>" + currentPatchset.rev + "</b>";
panel.add(new Label("uploadedWhat", MessageFormat.format(getString("gb.uploadedPatchsetNRevisionN"), ps, rev)).setEscapeModelStrings(false));
}
panel.add(new LinkPanel("patchId", null, "rev " + currentPatchset.rev, CommitPage.class, WicketUtils.newObjectParameter(repositoryName, currentPatchset.tip), true));
// compare menu
panel.add(new LinkPanel("compareMergeBase", null, getString("gb.compareToMergeBase"), ComparePage.class, WicketUtils.newRangeParameter(repositoryName, currentPatchset.base, currentPatchset.tip), true));
ListDataProvider<Patchset> compareMenuDp = new ListDataProvider<Patchset>(patchsets);
DataView<Patchset> compareMenu = new DataView<Patchset>("comparePatch", compareMenuDp) {
private static final long serialVersionUID = 1L;
@Override
public void populateItem(final Item<Patchset> item) {
Patchset patchset = item.getModelObject();
LinkPanel link = new LinkPanel("compareLink", null, MessageFormat.format(getString("gb.compareToN"), patchset.number + "-" + patchset.rev), ComparePage.class, WicketUtils.newRangeParameter(getRepositoryModel().name, patchset.tip, currentPatchset.tip), true);
item.add(link);
}
};
panel.add(compareMenu);
// reviews
List<Change> reviews = ticket.getReviews(currentPatchset);
ListDataProvider<Change> reviewsDp = new ListDataProvider<Change>(reviews);
DataView<Change> reviewsView = new DataView<Change>("reviews", reviewsDp) {
private static final long serialVersionUID = 1L;
@Override
public void populateItem(final Item<Change> item) {
Change change = item.getModelObject();
final String username = change.author;
UserModel user = app().users().getUserModel(username);
if (user == null) {
item.add(new Label("reviewer", username));
} else {
item.add(new LinkPanel("reviewer", null, user.getDisplayName(), UserPage.class, WicketUtils.newUsernameParameter(username)));
}
// indicate review score
Review review = change.review;
Label scoreLabel = new Label("score");
String scoreClass = getScoreClass(review.score);
String tooltip = getScoreDescription(review.score);
WicketUtils.setCssClass(scoreLabel, scoreClass);
if (!StringUtils.isEmpty(tooltip)) {
WicketUtils.setHtmlTooltip(scoreLabel, tooltip);
}
item.add(scoreLabel);
}
};
panel.add(reviewsView);
if (ticket.isOpen() && user.canReviewPatchset(repository) && app().tickets().isAcceptingTicketUpdates(repository)) {
// can only review open tickets
Review myReview = null;
for (Change change : ticket.getReviews(currentPatchset)) {
if (change.author.equals(user.username)) {
myReview = change.review;
}
}
// user can review, add review controls
Fragment reviewControls = new Fragment("reviewControls", "reviewControlsFragment", this);
// show "approve" button if no review OR not current score
if (user.canApprovePatchset(repository) && (myReview == null || Score.approved != myReview.score)) {
reviewControls.add(createReviewLink("approveLink", Score.approved));
} else {
reviewControls.add(new Label("approveLink").setVisible(false));
}
// show "looks good" button if no review OR not current score
if (myReview == null || Score.looks_good != myReview.score) {
reviewControls.add(createReviewLink("looksGoodLink", Score.looks_good));
} else {
reviewControls.add(new Label("looksGoodLink").setVisible(false));
}
// show "needs improvement" button if no review OR not current score
if (myReview == null || Score.needs_improvement != myReview.score) {
reviewControls.add(createReviewLink("needsImprovementLink", Score.needs_improvement));
} else {
reviewControls.add(new Label("needsImprovementLink").setVisible(false));
}
// show "veto" button if no review OR not current score
if (user.canVetoPatchset(repository) && (myReview == null || Score.vetoed != myReview.score)) {
reviewControls.add(createReviewLink("vetoLink", Score.vetoed));
} else {
reviewControls.add(new Label("vetoLink").setVisible(false));
}
panel.add(reviewControls);
} else {
// user can not review
panel.add(new Label("reviewControls").setVisible(false));
}
String insertions = MessageFormat.format("<span style=\"color:darkGreen;font-weight:bold;\">+{0}</span>", ticket.insertions);
String deletions = MessageFormat.format("<span style=\"color:darkRed;font-weight:bold;\">-{0}</span>", ticket.deletions);
panel.add(new Label("patchsetStat", MessageFormat.format(StringUtils.escapeForHtml(getString("gb.diffStat"), false), insertions, deletions)).setEscapeModelStrings(false));
// changed paths list
List<PathChangeModel> paths = JGitUtils.getFilesInRange(getRepository(), currentPatchset.base, currentPatchset.tip);
ListDataProvider<PathChangeModel> pathsDp = new ListDataProvider<PathChangeModel>(paths);
DataView<PathChangeModel> pathsView = new DataView<PathChangeModel>("changedPath", pathsDp) {
private static final long serialVersionUID = 1L;
int counter;
@Override
public void populateItem(final Item<PathChangeModel> item) {
final PathChangeModel entry = item.getModelObject();
Label changeType = new Label("changeType", "");
WicketUtils.setChangeTypeCssClass(changeType, entry.changeType);
setChangeTypeTooltip(changeType, entry.changeType);
item.add(changeType);
boolean hasSubmodule = false;
String submodulePath = null;
if (entry.isTree()) {
// tree
item.add(new LinkPanel("pathName", null, entry.path, TreePage.class, WicketUtils.newPathParameter(repositoryName, currentPatchset.tip, entry.path), true));
item.add(new Label("diffStat").setVisible(false));
} else if (entry.isSubmodule()) {
// submodule
String submoduleId = entry.objectId;
SubmoduleModel submodule = getSubmodule(entry.path);
submodulePath = submodule.gitblitPath;
hasSubmodule = submodule.hasSubmodule;
item.add(new LinkPanel("pathName", "list", entry.path + " @ " + getShortObjectId(submoduleId), TreePage.class, WicketUtils.newPathParameter(submodulePath, submoduleId, ""), true).setEnabled(hasSubmodule));
item.add(new Label("diffStat").setVisible(false));
} else {
// blob
String displayPath = entry.path;
String path = entry.path;
if (entry.isSymlink()) {
RevCommit commit = JGitUtils.getCommit(getRepository(), PatchsetCommand.getTicketBranch(ticket.number));
path = JGitUtils.getStringContent(getRepository(), commit.getTree(), path);
displayPath = entry.path + " -> " + path;
}
if (entry.changeType.equals(ChangeType.ADD)) {
// add show view
item.add(new LinkPanel("pathName", "list", displayPath, BlobPage.class, WicketUtils.newPathParameter(repositoryName, currentPatchset.tip, path), true));
} else if (entry.changeType.equals(ChangeType.DELETE)) {
// delete, show label
item.add(new Label("pathName", displayPath));
} else {
// mod, show diff
item.add(new LinkPanel("pathName", "list", displayPath, BlobDiffPage.class, WicketUtils.newPathParameter(repositoryName, currentPatchset.tip, path), true));
}
item.add(new DiffStatPanel("diffStat", entry.insertions, entry.deletions, true));
}
// quick links
if (entry.isSubmodule()) {
// submodule
item.add(setNewTarget(new BookmarkablePageLink<Void>("diff", BlobDiffPage.class, WicketUtils.newPathParameter(repositoryName, entry.commitId, entry.path))).setEnabled(!entry.changeType.equals(ChangeType.ADD)));
item.add(new BookmarkablePageLink<Void>("view", CommitPage.class, WicketUtils.newObjectParameter(submodulePath, entry.objectId)).setEnabled(hasSubmodule));
} else {
// tree or blob
item.add(setNewTarget(new BookmarkablePageLink<Void>("diff", BlobDiffPage.class, WicketUtils.newBlobDiffParameter(repositoryName, currentPatchset.base, currentPatchset.tip, entry.path))).setEnabled(!entry.changeType.equals(ChangeType.ADD) && !entry.changeType.equals(ChangeType.DELETE)));
item.add(setNewTarget(new BookmarkablePageLink<Void>("view", BlobPage.class, WicketUtils.newPathParameter(repositoryName, currentPatchset.tip, entry.path))).setEnabled(!entry.changeType.equals(ChangeType.DELETE)));
}
WicketUtils.setAlternatingBackground(item, counter);
counter++;
}
};
panel.add(pathsView);
addPtCheckoutInstructions(user, repository, panel);
addGitCheckoutInstructions(user, repository, panel);
return panel;
}
use of com.gitblit.models.TicketModel.Patchset in project gitblit by gitblit.
the class TicketPage method review.
protected void review(Score score) {
UserModel user = GitBlitWebSession.get().getUser();
Patchset ps = ticket.getCurrentPatchset();
Change change = new Change(user.username);
change.review(ps, score, !ticket.isReviewer(user.username));
if (!ticket.isWatching(user.username)) {
change.watch(user.username);
}
TicketModel updatedTicket = app().tickets().updateTicket(getRepositoryModel(), ticket.number, change);
app().tickets().createNotifier().sendMailing(updatedTicket);
redirectTo(TicketsPage.class, getPageParameters());
}
use of com.gitblit.models.TicketModel.Patchset in project gitblit by gitblit.
the class ITicketService method deletePatchset.
/**
* Deletes a patchset from a ticket.
*
* @param ticket
* @param patchset
* the patchset to delete (should be the highest revision)
* @param userName
* the user deleting the commit
* @return the revised ticket if the deletion was successful
* @since 1.8.0
*/
public final TicketModel deletePatchset(TicketModel ticket, Patchset patchset, String userName) {
Change deletion = new Change(userName);
deletion.patchset = new Patchset();
deletion.patchset.number = patchset.number;
deletion.patchset.rev = patchset.rev;
deletion.patchset.type = PatchsetType.Delete;
//Find and delete references to tickets by the removed commits
List<TicketLink> patchsetTicketLinks = JGitUtils.identifyTicketsBetweenCommits(repositoryManager.getRepository(ticket.repository), settings, patchset.base, patchset.tip);
for (TicketLink link : patchsetTicketLinks) {
link.isDelete = true;
}
deletion.pendingLinks = patchsetTicketLinks;
RepositoryModel repositoryModel = repositoryManager.getRepositoryModel(ticket.repository);
TicketModel revisedTicket = updateTicket(repositoryModel, ticket.number, deletion);
return revisedTicket;
}
Aggregations