com.gitblit.wicket.pages.ComparePage.java Source code

Java tutorial

Introduction

Here is the source code for com.gitblit.wicket.pages.ComparePage.java

Source

/*
 * 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.pages;

import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;

import org.apache.wicket.request.http.handler.RedirectRequestHandler;
import org.apache.wicket.request.mapper.parameter.PageParameters;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.CheckBox;
import org.apache.wicket.markup.html.form.DropDownChoice;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.markup.html.link.BookmarkablePageLink;
import org.apache.wicket.markup.html.link.ExternalLink;
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.IModel;
import org.apache.wicket.model.Model;
import org.apache.wicket.protocol.http.RequestUtils;
import org.eclipse.jgit.diff.DiffEntry.ChangeType;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;

import com.gitblit.Keys;
import com.gitblit.models.PathModel.PathChangeModel;
import com.gitblit.models.RefModel;
import com.gitblit.models.RepositoryModel;
import com.gitblit.models.SubmoduleModel;
import com.gitblit.servlet.RawServlet;
import com.gitblit.utils.DiffUtils;
import com.gitblit.utils.GitBlitRequestUtils;
import com.gitblit.utils.DiffUtils.DiffComparator;
import com.gitblit.utils.DiffUtils.DiffOutput;
import com.gitblit.utils.DiffUtils.DiffOutputType;
import com.gitblit.utils.JGitUtils;
import com.gitblit.utils.StringUtils;
import com.gitblit.wicket.SessionlessForm;
import com.gitblit.wicket.WicketUtils;
import com.gitblit.wicket.panels.CommitLegendPanel;
import com.gitblit.wicket.panels.DiffStatPanel;
import com.gitblit.wicket.panels.LinkPanel;
import com.gitblit.wicket.panels.LogPanel;

/**
 * The compare page allows you to compare two branches, tags, or hash ids.
 *
 * @author James Moger
 *
 */
public class ComparePage extends RepositoryPage {

    IModel<String> fromCommitId = new Model<String>("");
    IModel<String> toCommitId = new Model<String>("");

    IModel<String> fromRefId = new Model<String>("");
    IModel<String> toRefId = new Model<String>("");

    IModel<Boolean> ignoreWhitespace = Model.of(true);

    public ComparePage(PageParameters params) {
        super(params);
        Repository r = getRepository();
        RepositoryModel repository = getRepositoryModel();

        if (StringUtils.isEmpty(objectId)) {
            // seleciton form
            add(new Label("comparison").setVisible(false));
        } else {
            // active comparison
            Fragment comparison = new Fragment("comparison", "comparisonFragment", ComparePage.this);
            add(comparison);

            RevCommit fromCommit;
            RevCommit toCommit;

            String[] parts = objectId.split("\\.\\.");
            if (parts[0].startsWith("refs/") && parts[1].startsWith("refs/")) {
                // set the ref models
                fromRefId.setObject(parts[0]);
                toRefId.setObject(parts[1]);

                fromCommit = getCommit(r, fromRefId.getObject());
                toCommit = getCommit(r, toRefId.getObject());
            } else {
                // set the id models
                fromCommitId.setObject(parts[0]);
                toCommitId.setObject(parts[1]);

                fromCommit = getCommit(r, fromCommitId.getObject());
                toCommit = getCommit(r, toCommitId.getObject());
            }

            // prepare submodules
            getSubmodules(toCommit);

            final String startId = fromCommit.getId().getName();
            final String endId = toCommit.getId().getName();

            // commit ids
            fromCommitId.setObject(startId);
            toCommitId.setObject(endId);

            final List<String> imageExtensions = app().settings().getStrings(Keys.web.imageExtensions);
            final ImageDiffHandler handler = new ImageDiffHandler(this, repositoryName, fromCommit.getName(),
                    toCommit.getName(), imageExtensions);
            final DiffComparator diffComparator = WicketUtils.getDiffComparator(params);
            final int tabLength = app().settings().getInteger(Keys.web.tabLength, 4);
            final DiffOutput diff = DiffUtils.getDiff(r, fromCommit, toCommit, diffComparator, DiffOutputType.HTML,
                    handler, tabLength);
            if (handler.getImgDiffCount() > 0) {
                addBottomScript("scripts/imgdiff.js"); // Tiny support script for image diffs
            }

            // add compare diffstat
            int insertions = 0;
            int deletions = 0;
            for (PathChangeModel pcm : diff.stat.paths) {
                insertions += pcm.insertions;
                deletions += pcm.deletions;
            }
            comparison.add(new DiffStatPanel("diffStat", insertions, deletions));

            // compare page links
            //         comparison.add(new BookmarkablePageLink<Void>("patchLink", PatchPage.class,
            //               WicketUtils.newRangeParameter(repositoryName, fromCommitId.toString(), toCommitId.getObject())));

            // display list of commits
            comparison.add(
                    new LogPanel("commitList", repositoryName, objectId, r, 0, 0, repository.showRemoteBranches));

            // changed paths list
            comparison.add(new CommitLegendPanel("commitLegend", diff.stat.paths));
            ListDataProvider<PathChangeModel> pathsDp = new ListDataProvider<PathChangeModel>(diff.stat.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);
                    item.add(new DiffStatPanel("diffStat", entry.insertions, entry.deletions, true));

                    boolean hasSubmodule = false;
                    String submodulePath = null;
                    if (entry.isTree()) {
                        // tree
                        item.add(new LinkPanel("pathName", null, entry.path, TreePage.class,
                                WicketUtils.newPathParameter(repositoryName, endId, entry.path)));
                    } else if (entry.isSubmodule()) {
                        // submodule
                        String submoduleId = entry.objectId;
                        SubmoduleModel submodule = getSubmodule(entry.path);
                        submodulePath = submodule.gitblitPath;
                        hasSubmodule = submodule.hasSubmodule;

                        // add relative link
                        item.add(new LinkPanel("pathName", "list",
                                entry.path + " @ " + getShortObjectId(submoduleId), "#n" + entry.objectId));
                    } else {
                        // add relative link
                        item.add(new LinkPanel("pathName", "list", entry.path, "#n" + entry.objectId));
                    }

                    // quick links
                    if (entry.isSubmodule()) {
                        // submodule
                        item.add(new ExternalLink("patch", "").setEnabled(false));
                        item.add(new BookmarkablePageLink<Void>("view", CommitPage.class,
                                WicketUtils.newObjectParameter(submodulePath, entry.objectId))
                                        .setEnabled(hasSubmodule));
                        item.add(new ExternalLink("raw", "").setEnabled(false));
                        item.add(new ExternalLink("blame", "").setEnabled(false));
                        item.add(new BookmarkablePageLink<Void>("history", HistoryPage.class,
                                WicketUtils.newPathParameter(repositoryName, endId, entry.path))
                                        .setEnabled(!entry.changeType.equals(ChangeType.ADD)));
                    } else {
                        // tree or blob
                        item.add(new BookmarkablePageLink<Void>("patch", PatchPage.class,
                                WicketUtils.newBlobDiffParameter(repositoryName, startId, endId, entry.path))
                                        .setEnabled(!entry.changeType.equals(ChangeType.DELETE)));
                        item.add(new BookmarkablePageLink<Void>("view", BlobPage.class,
                                WicketUtils.newPathParameter(repositoryName, endId, entry.path))
                                        .setEnabled(!entry.changeType.equals(ChangeType.DELETE)));
                        String rawUrl = RawServlet.asLink(getContextUrl(), repositoryName, endId, entry.path);
                        item.add(new ExternalLink("raw", rawUrl)
                                .setEnabled(!entry.changeType.equals(ChangeType.DELETE)));
                        item.add(new BookmarkablePageLink<Void>("blame", BlamePage.class,
                                WicketUtils.newPathParameter(repositoryName, endId, entry.path))
                                        .setEnabled(!entry.changeType.equals(ChangeType.ADD)
                                                && !entry.changeType.equals(ChangeType.DELETE)));
                        item.add(new BookmarkablePageLink<Void>("history", HistoryPage.class,
                                WicketUtils.newPathParameter(repositoryName, endId, entry.path))
                                        .setEnabled(!entry.changeType.equals(ChangeType.ADD)));
                    }
                    WicketUtils.setAlternatingBackground(item, counter);
                    counter++;
                }
            };
            comparison.add(pathsView);
            comparison.add(new Label("diffText", diff.content).setEscapeModelStrings(false));
        }

        // set the default DiffComparator
        DiffComparator diffComparator = WicketUtils.getDiffComparator(params);
        ignoreWhitespace.setObject(DiffComparator.IGNORE_WHITESPACE == diffComparator);

        //
        // ref selection form
        //
        SessionlessForm<Void> refsForm = new SessionlessForm<Void>("compareRefsForm", getClass(),
                getPageParameters()) {

            private static final long serialVersionUID = 1L;

            @Override
            public void onSubmit() {
                String from = ComparePage.this.fromRefId.getObject();
                String to = ComparePage.this.toRefId.getObject();
                boolean ignoreWS = ignoreWhitespace.getObject();

                PageParameters params = WicketUtils.newRangeParameter(repositoryName, from, to);
                if (ignoreWS) {
                    params.add("w", 1);
                }

                String absoluteUrl = GitBlitRequestUtils.toAbsoluteUrl(ComparePage.class, params);
                getRequestCycle().scheduleRequestHandlerAfterCurrent(new RedirectRequestHandler(absoluteUrl));
            }
        };

        List<String> refs = new ArrayList<String>();
        for (RefModel ref : JGitUtils.getLocalBranches(r, true, -1)) {
            refs.add(ref.getName());
        }
        if (repository.showRemoteBranches) {
            for (RefModel ref : JGitUtils.getRemoteBranches(r, true, -1)) {
                refs.add(ref.getName());
            }
        }
        for (RefModel ref : JGitUtils.getTags(r, true, -1)) {
            refs.add(ref.getName());
        }
        refsForm.add(new DropDownChoice<String>("fromRef", fromRefId, refs).setEnabled(refs.size() > 0));
        refsForm.add(new DropDownChoice<String>("toRef", toRefId, refs).setEnabled(refs.size() > 0));
        refsForm.add(new Label("ignoreWhitespaceLabel",
                getString(DiffComparator.IGNORE_WHITESPACE.getTranslationKey())));
        refsForm.add(new CheckBox("ignoreWhitespaceCheckbox", ignoreWhitespace));
        add(refsForm);

        //
        // manual ids form
        //
        SessionlessForm<Void> idsForm = new SessionlessForm<Void>("compareIdsForm", getClass(),
                getPageParameters()) {

            private static final long serialVersionUID = 1L;

            @Override
            public void onSubmit() {
                String from = ComparePage.this.fromCommitId.getObject();
                String to = ComparePage.this.toCommitId.getObject();
                boolean ignoreWS = ignoreWhitespace.getObject();

                PageParameters params = WicketUtils.newRangeParameter(repositoryName, from, to);
                if (ignoreWS) {
                    params.add("w", 1);
                }
                String absoluteUrl = GitBlitRequestUtils.toAbsoluteUrl(ComparePage.class, params);
                getRequestCycle().scheduleRequestHandlerAfterCurrent(new RedirectRequestHandler(absoluteUrl));
            }
        };

        TextField<String> fromIdField = new TextField<String>("fromId", fromCommitId);
        WicketUtils.setInputPlaceholder(fromIdField, getString("gb.from") + "...");
        idsForm.add(fromIdField);

        TextField<String> toIdField = new TextField<String>("toId", toCommitId);
        WicketUtils.setInputPlaceholder(toIdField, getString("gb.to") + "...");
        idsForm.add(toIdField);
        idsForm.add(new Label("ignoreWhitespaceLabel",
                getString(DiffComparator.IGNORE_WHITESPACE.getTranslationKey())));
        idsForm.add(new CheckBox("ignoreWhitespaceCheckbox", ignoreWhitespace));
        add(idsForm);

        r.close();
    }

    @Override
    protected String getPageName() {
        return getString("gb.compare");
    }

    @Override
    protected Class<? extends BasePage> getRepoNavPageClass() {
        return ComparePage.class;
    }

    private RevCommit getCommit(Repository r, String rev) {
        RevCommit otherCommit = JGitUtils.getCommit(r, rev);
        if (otherCommit == null) {
            error(MessageFormat.format(getString("gb.failedToFindCommit"), rev, repositoryName, getPageName()),
                    true);
        }
        return otherCommit;
    }
}