| /* |
| * 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<RefLogEntry> 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<RefLogEntry> changes) { |
| super(wicketId); |
| hasChanges = changes.size() > 0; |
| setup(changes); |
| add(new Label("moreChanges").setVisible(false)); |
| } |
| |
| protected void setup(List<RefLogEntry> changes) { |
| |
| ListDataProvider<RefLogEntry> dp = new ListDataProvider<RefLogEntry>(changes); |
| DataView<RefLogEntry> changeView = new DataView<RefLogEntry>("change", dp) { |
| private static final long serialVersionUID = 1L; |
| |
| @Override |
| public void populateItem(final Item<RefLogEntry> 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<RepositoryCommit> commits = change.getCommits(); |
| if (commits.size() > maxCommitCount) { |
| commits = new ArrayList<RepositoryCommit>(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<RepositoryCommit> cdp = new ListDataProvider<RepositoryCommit>(commits); |
| DataView<RepositoryCommit> commitsView = new DataView<RepositoryCommit>("commit", cdp) { |
| private static final long serialVersionUID = 1L; |
| |
| @Override |
| public void populateItem(final Item<RepositoryCommit> commitItem) { |
| final RepositoryCommit commit = commitItem.getModelObject(); |
| |
| // author gravatar |
| commitItem.add(new GravatarImage("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; |
| } |
| } |