/* * Copyright 2011 gitblit.com. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.gitblit.wicket.panels; import java.io.IOException; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Collections; import java.util.List; import org.apache.wicket.PageParameters; import org.apache.wicket.markup.html.basic.Label; import org.apache.wicket.markup.html.link.BookmarkablePageLink; import org.apache.wicket.markup.html.link.ExternalLink; import org.apache.wicket.markup.html.link.Link; import org.apache.wicket.markup.html.panel.Fragment; import org.apache.wicket.markup.repeater.Item; import org.apache.wicket.markup.repeater.data.DataView; import org.apache.wicket.markup.repeater.data.ListDataProvider; import org.apache.wicket.model.StringResourceModel; import org.apache.wicket.protocol.http.RequestUtils; import org.apache.wicket.request.target.basic.RedirectRequestTarget; import org.eclipse.jgit.lib.Ref; import org.eclipse.jgit.lib.Repository; import com.gitblit.Constants; import com.gitblit.models.RefModel; import com.gitblit.models.RepositoryModel; import com.gitblit.models.UserModel; import com.gitblit.servlet.RawServlet; import com.gitblit.servlet.SyndicationServlet; import com.gitblit.utils.CommitCache; import com.gitblit.utils.JGitUtils; import com.gitblit.utils.RefLogUtils; import com.gitblit.utils.StringUtils; import com.gitblit.wicket.GitBlitWebSession; import com.gitblit.wicket.WicketUtils; import com.gitblit.wicket.pages.BranchesPage; import com.gitblit.wicket.pages.CommitPage; import com.gitblit.wicket.pages.GitSearchPage; import com.gitblit.wicket.pages.LogPage; import com.gitblit.wicket.pages.MetricsPage; import com.gitblit.wicket.pages.TreePage; public class BranchesPanel extends BasePanel { private static final long serialVersionUID = 1L; private final boolean hasBranches; public BranchesPanel(String wicketId, final RepositoryModel model, Repository r, final int maxCount, final boolean showAdmin) { super(wicketId); // branches List branches = new ArrayList(); UserModel user = GitBlitWebSession.get().getUser(); if (user == null) { user = UserModel.ANONYMOUS; } List localBranches = JGitUtils.getLocalBranches(r, false, -1); for (RefModel refModel : localBranches) { if (user.canView(model, refModel.reference.getName())) { branches.add(refModel); } } if (model.showRemoteBranches) { List remoteBranches = JGitUtils.getRemoteBranches(r, false, -1); for (RefModel refModel : remoteBranches) { if (user.canView(model, refModel.reference.getName())) { branches.add(refModel); } } } Collections.sort(branches); Collections.reverse(branches); if (maxCount > 0 && branches.size() > maxCount) { branches = new ArrayList(branches.subList(0, maxCount)); } if (maxCount > 0) { // summary page // show branches page link add(new LinkPanel("branches", "title", new StringResourceModel("gb.branches", this, null), BranchesPage.class, WicketUtils.newRepositoryParameter(model.name))); } else { // branches page add(new Label("branches", new StringResourceModel("gb.branches", this, null))); } // only allow delete if we have multiple branches final boolean showDelete = showAdmin && branches.size() > 1; ListDataProvider branchesDp = new ListDataProvider(branches); DataView branchesView = new DataView("branch", branchesDp) { private static final long serialVersionUID = 1L; int counter; @Override public void populateItem(final Item item) { final RefModel entry = item.getModelObject(); PageParameters shortUniqRef = WicketUtils.newObjectParameter(model.name, Repository.shortenRefName(entry.getName())); item.add(WicketUtils.createDateLabel("branchDate", entry.getDate(), getTimeZone(), getTimeUtils())); item.add(new LinkPanel("branchName", "list name", StringUtils.trimString( entry.displayName, 28), LogPage.class, shortUniqRef)); String author = entry.getAuthorIdent().getName(); LinkPanel authorLink = new LinkPanel("branchAuthor", "list", author, GitSearchPage.class, WicketUtils.newSearchParameter(model.name, entry.getName(), author, Constants.SearchType.AUTHOR)); setPersonSearchTooltip(authorLink, author, Constants.SearchType.AUTHOR); item.add(authorLink); // short message String shortMessage = entry.getShortMessage(); String trimmedMessage = StringUtils.trimString(shortMessage, Constants.LEN_SHORTLOG); LinkPanel shortlog = new LinkPanel("branchLog", "list subject", trimmedMessage, CommitPage.class, shortUniqRef); if (!shortMessage.equals(trimmedMessage)) { shortlog.setTooltip(shortMessage); } item.add(shortlog); if (maxCount <= 0) { Fragment fragment = new Fragment("branchLinks", showDelete? "branchPageAdminLinks" : "branchPageLinks", this); fragment.add(new BookmarkablePageLink("log", LogPage.class, shortUniqRef)); fragment.add(new BookmarkablePageLink("tree", TreePage.class, shortUniqRef)); String rawUrl = RawServlet.asLink(getContextUrl(), model.name, Repository.shortenRefName(entry.getName()), null); fragment.add(new ExternalLink("raw", rawUrl)); fragment.add(new BookmarkablePageLink("metrics", MetricsPage.class, shortUniqRef)); fragment.add(new ExternalLink("syndication", SyndicationServlet.asLink( getRequest().getRelativePathPrefixToContextRoot(), model.name, Repository.shortenRefName(entry.getName()), 0))); if (showDelete) { fragment.add(createDeleteBranchLink(model, entry)); } item.add(fragment); } else { Fragment fragment = new Fragment("branchLinks", "branchPanelLinks", this); fragment.add(new BookmarkablePageLink("log", LogPage.class, shortUniqRef)); fragment.add(new BookmarkablePageLink("tree", TreePage.class, shortUniqRef)); String rawUrl = RawServlet.asLink(getContextUrl(), model.name, Repository.shortenRefName(entry.getName()), null); fragment.add(new ExternalLink("raw", rawUrl)); item.add(fragment); } WicketUtils.setAlternatingBackground(item, counter); counter++; } }; add(branchesView); if (branches.size() < maxCount || maxCount <= 0) { add(new Label("allBranches", "").setVisible(false)); } else { add(new LinkPanel("allBranches", "link", new StringResourceModel("gb.allBranches", this, null), BranchesPage.class, WicketUtils.newRepositoryParameter(model.name))); } // We always have 1 branch hasBranches = (branches.size() > 1) || ((branches.size() == 1) && !branches.get(0).displayName .equalsIgnoreCase("master")); } public BranchesPanel hideIfEmpty() { setVisible(hasBranches); return this; } private Link createDeleteBranchLink(final RepositoryModel repositoryModel, final RefModel entry) { Link deleteLink = new Link("deleteBranch") { private static final long serialVersionUID = 1L; @Override public void onClick() { Repository r = app().repositories().getRepository(repositoryModel.name); if (r == null) { if (app().repositories().isCollectingGarbage(repositoryModel.name)) { error(MessageFormat.format(getString("gb.busyCollectingGarbage"), repositoryModel.name)); } else { error(MessageFormat.format("Failed to find repository {0}", repositoryModel.name)); } return; } final String branch = entry.getName(); Ref ref = null; try { ref = r.getRef(branch); if (ref == null && !branch.startsWith(Constants.R_HEADS)) { ref = r.getRef(Constants.R_HEADS + branch); } } catch (IOException e) { } if (ref != null) { boolean success = JGitUtils.deleteBranchRef(r, ref.getName()); if (success) { // clear commit cache CommitCache.instance().clear(repositoryModel.name, branch); // optionally update reflog if (RefLogUtils.hasRefLogBranch(r)) { UserModel user = GitBlitWebSession.get().getUser(); RefLogUtils.deleteRef(user, r, ref); } } if (success) { info(MessageFormat.format("Branch \"{0}\" deleted", branch)); } else { error(MessageFormat.format("Failed to delete branch \"{0}\"", branch)); } } r.close(); // redirect to the owning page PageParameters params = WicketUtils.newRepositoryParameter(repositoryModel.name); String relativeUrl = urlFor(getPage().getClass(), params).toString(); String absoluteUrl = RequestUtils.toAbsolutePath(relativeUrl); getRequestCycle().setRequestTarget(new RedirectRequestTarget(absoluteUrl)); } }; deleteLink.add(new JavascriptEventConfirmation("onclick", MessageFormat.format( "Delete branch \"{0}\"?", entry.displayName ))); return deleteLink; } }