/* * Copyright 2013 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.text.DateFormat; import java.text.MessageFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.List; import java.util.TimeZone; import org.apache.wicket.markup.html.basic.Label; 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.eclipse.jgit.lib.Repository; import org.eclipse.jgit.transport.ReceiveCommand.Type; import com.gitblit.Constants; import com.gitblit.Keys; import com.gitblit.models.RefLogEntry; import com.gitblit.models.RepositoryCommit; import com.gitblit.models.RepositoryModel; import com.gitblit.models.UserModel; import com.gitblit.utils.RefLogUtils; import com.gitblit.utils.StringUtils; import com.gitblit.utils.TimeUtils; import com.gitblit.wicket.WicketUtils; import com.gitblit.wicket.pages.CommitPage; import com.gitblit.wicket.pages.ComparePage; import com.gitblit.wicket.pages.ReflogPage; import com.gitblit.wicket.pages.TagPage; import com.gitblit.wicket.pages.TicketsPage; import com.gitblit.wicket.pages.TreePage; import com.gitblit.wicket.pages.UserPage; public class ReflogPanel extends BasePanel { private static final long serialVersionUID = 1L; private final boolean hasChanges; private boolean hasMore; public ReflogPanel(String wicketId, final RepositoryModel model, Repository r, int limit, int pageOffset) { super(wicketId); boolean pageResults = limit <= 0; int changesPerPage = app().settings().getInteger(Keys.web.reflogChangesPerPage, 10); if (changesPerPage <= 1) { changesPerPage = 10; } List changes; if (pageResults) { changes = RefLogUtils.getLogByRef(model.name, r, pageOffset * changesPerPage, changesPerPage); } else { changes = RefLogUtils.getLogByRef(model.name, r, limit); } // inaccurate way to determine if there are more commits. // works unless commits.size() represents the exact end. hasMore = changes.size() >= changesPerPage; hasChanges = changes.size() > 0; setup(changes); // determine to show pager, more, or neither if (limit <= 0) { // no display limit add(new Label("moreChanges").setVisible(false)); } else { if (pageResults) { // paging add(new Label("moreChanges").setVisible(false)); } else { // more if (changes.size() == limit) { // show more add(new LinkPanel("moreChanges", "link", new StringResourceModel("gb.moreChanges", this, null), ReflogPage.class, WicketUtils.newRepositoryParameter(model.name))); } else { // no more add(new Label("moreChanges").setVisible(false)); } } } } public ReflogPanel(String wicketId, List changes) { super(wicketId); hasChanges = changes.size() > 0; setup(changes); add(new Label("moreChanges").setVisible(false)); } protected void setup(List changes) { ListDataProvider dp = new ListDataProvider(changes); DataView changeView = new DataView("change", dp) { private static final long serialVersionUID = 1L; @Override public void populateItem(final Item changeItem) { final RefLogEntry change = changeItem.getModelObject(); String dateFormat = app().settings().getString(Keys.web.datetimestampLongFormat, "EEEE, MMMM d, yyyy HH:mm Z"); TimeZone timezone = getTimeZone(); DateFormat df = new SimpleDateFormat(dateFormat); df.setTimeZone(timezone); Calendar cal = Calendar.getInstance(timezone); String fullRefName = change.getChangedRefs().get(0); String shortRefName = fullRefName; String ticketId = null; boolean isTag = false; boolean isTicket = false; if (shortRefName.startsWith(Constants.R_TICKET)) { ticketId = fullRefName.substring(Constants.R_TICKET.length()); shortRefName = MessageFormat.format(getString("gb.ticketN"), ticketId); isTicket = true; } else if (shortRefName.startsWith(Constants.R_HEADS)) { shortRefName = shortRefName.substring(Constants.R_HEADS.length()); } else if (shortRefName.startsWith(Constants.R_TAGS)) { shortRefName = shortRefName.substring(Constants.R_TAGS.length()); isTag = true; } String fuzzydate; TimeUtils tu = getTimeUtils(); Date changeDate = change.date; if (TimeUtils.isToday(changeDate, timezone)) { fuzzydate = tu.today(); } else if (TimeUtils.isYesterday(changeDate, timezone)) { fuzzydate = tu.yesterday(); } else { // calculate a fuzzy time ago date cal.setTime(changeDate); cal.set(Calendar.HOUR_OF_DAY, 0); cal.set(Calendar.MINUTE, 0); cal.set(Calendar.SECOND, 0); cal.set(Calendar.MILLISECOND, 0); Date date = cal.getTime(); fuzzydate = getTimeUtils().timeAgo(date); } changeItem.add(new Label("whenChanged", fuzzydate + ", " + df.format(changeDate))); Label changeIcon = new Label("changeIcon"); if (Type.DELETE.equals(change.getChangeType(fullRefName))) { WicketUtils.setCssClass(changeIcon, "iconic-trash-stroke"); } else if (isTag) { WicketUtils.setCssClass(changeIcon, "iconic-tag"); } else if (isTicket) { WicketUtils.setCssClass(changeIcon, "fa fa-ticket"); } else { WicketUtils.setCssClass(changeIcon, "iconic-upload"); } changeItem.add(changeIcon); if (change.user.username.equals(change.user.emailAddress) && change.user.emailAddress.indexOf('@') > -1) { // username is an email address - 1.2.1 push log bug changeItem.add(new Label("whoChanged", change.user.getDisplayName())); } else if (change.user.username.equals(UserModel.ANONYMOUS.username)) { // anonymous change changeItem.add(new Label("whoChanged", getString("gb.anonymousUser"))); } else { // link to user account page changeItem.add(new LinkPanel("whoChanged", null, change.user.getDisplayName(), UserPage.class, WicketUtils.newUsernameParameter(change.user.username))); } boolean isDelete = false; boolean isRewind = false; String what; String by = null; switch(change.getChangeType(fullRefName)) { case CREATE: if (isTag) { // new tag what = getString("gb.pushedNewTag"); } else { // new branch what = getString("gb.pushedNewBranch"); } break; case DELETE: isDelete = true; if (isTag) { what = getString("gb.deletedTag"); } else { what = getString("gb.deletedBranch"); } break; case UPDATE_NONFASTFORWARD: isRewind = true; default: what = MessageFormat.format(change.getCommitCount() > 1 ? getString("gb.pushedNCommitsTo") : getString("gb.pushedOneCommitTo"), change.getCommitCount()); if (change.getAuthorCount() == 1) { by = MessageFormat.format(getString("gb.byOneAuthor"), change.getAuthorIdent().getName()); } else { by = MessageFormat.format(getString("gb.byNAuthors"), change.getAuthorCount()); } break; } changeItem.add(new Label("whatChanged", what)); changeItem.add(new Label("byAuthors", by).setVisible(!StringUtils.isEmpty(by))); changeItem.add(new Label("refRewind", getString("gb.rewind")).setVisible(isRewind)); if (isDelete) { // can't link to deleted ref changeItem.add(new Label("refChanged", shortRefName)); } else if (isTag) { // link to tag changeItem.add(new LinkPanel("refChanged", null, shortRefName, TagPage.class, WicketUtils.newObjectParameter(change.repository, fullRefName))); } else if (isTicket) { // link to ticket changeItem.add(new LinkPanel("refChanged", null, shortRefName, TicketsPage.class, WicketUtils.newObjectParameter(change.repository, ticketId))); } else { // link to tree changeItem.add(new LinkPanel("refChanged", null, shortRefName, TreePage.class, WicketUtils.newObjectParameter(change.repository, fullRefName))); } int maxCommitCount = 5; List commits = change.getCommits(); if (commits.size() > maxCommitCount) { commits = new ArrayList(commits.subList(0, maxCommitCount)); } // compare link String compareLinkText = null; if ((change.getCommitCount() <= maxCommitCount) && (change.getCommitCount() > 1)) { compareLinkText = MessageFormat.format(getString("gb.viewComparison"), commits.size()); } else if (change.getCommitCount() > maxCommitCount) { int diff = change.getCommitCount() - maxCommitCount; compareLinkText = MessageFormat.format(diff > 1 ? getString("gb.nMoreCommits") : getString("gb.oneMoreCommit"), diff); } if (StringUtils.isEmpty(compareLinkText)) { changeItem.add(new Label("compareLink").setVisible(false)); } else { String endRangeId = change.getNewId(fullRefName); String startRangeId = change.getOldId(fullRefName); changeItem.add(new LinkPanel("compareLink", null, compareLinkText, ComparePage.class, WicketUtils.newRangeParameter(change.repository, startRangeId, endRangeId))); } ListDataProvider cdp = new ListDataProvider(commits); DataView commitsView = new DataView("commit", cdp) { private static final long serialVersionUID = 1L; @Override public void populateItem(final Item commitItem) { final RepositoryCommit commit = commitItem.getModelObject(); // author gravatar commitItem.add(new AvatarImage("commitAuthor", commit.getAuthorIdent(), null, 16, false)); // merge icon if (commit.getParentCount() > 1) { commitItem.add(WicketUtils.newImage("commitIcon", "commit_merge_16x16.png")); } else { commitItem.add(WicketUtils.newBlankImage("commitIcon")); } // short message String shortMessage = commit.getShortMessage(); String trimmedMessage = shortMessage; if (commit.getRefs() != null && commit.getRefs().size() > 0) { trimmedMessage = StringUtils.trimString(shortMessage, Constants.LEN_SHORTLOG_REFS); } else { trimmedMessage = StringUtils.trimString(shortMessage, Constants.LEN_SHORTLOG); } LinkPanel shortlog = new LinkPanel("commitShortMessage", "list", trimmedMessage, CommitPage.class, WicketUtils.newObjectParameter( change.repository, commit.getName())); if (!shortMessage.equals(trimmedMessage)) { WicketUtils.setHtmlTooltip(shortlog, shortMessage); } commitItem.add(shortlog); // commit hash link int hashLen = app().settings().getInteger(Keys.web.shortCommitIdLength, 6); LinkPanel commitHash = new LinkPanel("hashLink", null, commit.getName().substring(0, hashLen), CommitPage.class, WicketUtils.newObjectParameter( change.repository, commit.getName())); WicketUtils.setCssClass(commitHash, "shortsha1"); WicketUtils.setHtmlTooltip(commitHash, commit.getName()); commitItem.add(commitHash); } }; changeItem.add(commitsView); } }; add(changeView); } public boolean hasMore() { return hasMore; } public boolean hideIfEmpty() { setVisible(hasChanges); return hasChanges; } }