Package org.nbgit.ui.commit

Source Code of org.nbgit.ui.commit.CommitAction

/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
*
* The contents of this file are subject to the terms of either the GNU
* General Public License Version 2 only ("GPL") or the Common
* Development and Distribution License("CDDL") (collectively, the
* "License"). You may not use this file except in compliance with the
* License. You can obtain a copy of the License at
* http://www.netbeans.org/cddl-gplv2.html
* or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
* specific language governing permissions and limitations under the
* License.  When distributing the software, include this License Header
* Notice in each file and include the License file at
* nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the GPL Version 2 section of the License file that
* accompanied this code. If applicable, add the following below the
* License Header, with the fields enclosed by brackets [] replaced by
* your own identifying information:
* "Portions Copyrighted [year] [name of copyright owner]"
*
* Contributor(s):
*
* The Original Software is NetBeans. The Initial Developer of the Original
* Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
* Microsystems, Inc. All Rights Reserved.
* Portions Copyright 2008 Alexander Coles (Ikonoklastik Productions).
*
* If you wish your version of this file to be governed by only the CDDL
* or only the GPL Version 2, indicate your decision by adding
* "[Contributor] elects to include this software in this distribution
* under the [CDDL or GPL Version 2] license." If you do not indicate a
* single choice of license, a recipient has the option to distribute
* your version of this file under either the CDDL, the GPL Version 2 or
* to extend the choice of license to its licensees as provided above.
* However, if you add GPL Version 2 code and therefore, elected the GPL
* Version 2 license, then the option applies only if the new code is
* made subject to such option by the copyright holder.
*/
package org.nbgit.ui.commit;

import java.awt.BorderLayout;
import java.awt.Dialog;
import java.awt.event.ActionEvent;
import java.io.File;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.ResourceBundle;
import java.util.Set;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JOptionPane;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import org.nbgit.StatusInfo;
import org.nbgit.StatusCache;
import org.nbgit.Git;
import org.nbgit.GitModuleConfig;
import org.nbgit.GitProgressSupport;
import org.nbgit.OutputLogger;
import org.nbgit.client.CommitBuilder;
import org.nbgit.ui.GitFileNode;
import org.nbgit.ui.ContextAction;
import org.nbgit.util.GitProjectUtils;
import org.nbgit.util.GitUtils;
import org.netbeans.modules.versioning.spi.VCSContext;
import org.netbeans.modules.versioning.util.DialogBoundsPreserver;
import org.netbeans.modules.versioning.util.Utils;
import org.netbeans.modules.versioning.util.VersioningEvent;
import org.netbeans.modules.versioning.util.VersioningListener;
import org.openide.DialogDescriptor;
import org.openide.DialogDisplayer;
import org.openide.util.HelpCtx;
import org.openide.util.NbBundle;
import org.openide.util.RequestProcessor;

/**
* Commit action for Git:
* git commit - commit the specified files or all outstanding changes
*
* @author John Rice
*/
public class CommitAction extends ContextAction {

    static final String RECENT_COMMIT_MESSAGES = "recentCommitMessage"; // NOI18N
    static final String SIGN_OFF_MESSAGE = "signOffMessage"; // NOI18N

    public CommitAction(String name, VCSContext context) {
        super(name, context);
    }

    @Override
    public boolean isEnabled() {
        StatusCache cache = Git.getInstance().getStatusCache();
        return cache.containsFileOfStatus(context, StatusInfo.STATUS_LOCAL_CHANGE);
    }

    public void performAction(ActionEvent e) {
        final File root = GitUtils.getRootFile(context);
        if (root == null) {
            OutputLogger logger = OutputLogger.getLogger(Git.GIT_OUTPUT_TAB_TITLE);
            logger.outputInRed(NbBundle.getMessage(CommitAction.class, "MSG_COMMIT_TITLE")); // NOI18N
            logger.outputInRed(NbBundle.getMessage(CommitAction.class, "MSG_COMMIT_TITLE_SEP")); // NOI18N
            logger.outputInRed(
                    NbBundle.getMessage(CommitAction.class, "MSG_COMMIT_NOT_SUPPORTED_INVIEW_INFO")); // NOI18N
            logger.output(""); // NOI18N
            logger.closeLog();
            JOptionPane.showMessageDialog(null,
                    NbBundle.getMessage(CommitAction.class, "MSG_COMMIT_NOT_SUPPORTED_INVIEW"),// NOI18N
                    NbBundle.getMessage(CommitAction.class, "MSG_COMMIT_NOT_SUPPORTED_INVIEW_TITLE"),// NOI18N
                    JOptionPane.INFORMATION_MESSAGE);
            return;
        }
        String contentTitle = Utils.getContextDisplayName(context);

        commit(contentTitle, context);
    }

    public static void commit(String contentTitle, final VCSContext ctx) {
        StatusCache cache = Git.getInstance().getStatusCache();
        File[] roots = ctx.getRootFiles().toArray(new File[ctx.getRootFiles().size()]);
        if (roots == null || roots.length == 0) {
            return;
        }
        final File repository = GitUtils.getRootFile(ctx);
        if (repository == null) {
            return;
        }
        String projName = GitProjectUtils.getProjectName(repository);
        if (projName == null) {
            File projFile = GitUtils.getProjectFile(ctx);
            projName = GitProjectUtils.getProjectName(projFile);
        }
        final String prjName = projName;

        File[][] split = Utils.splitFlatOthers(roots);
        List<File> fileList = new ArrayList<File>();
        for (int c = 0; c < split.length; c++) {
            roots = split[c];
            boolean recursive = c == 1;
            if (recursive) {
                File[] files = cache.listFiles(ctx, StatusInfo.STATUS_LOCAL_CHANGE);
                for (int i = 0; i < files.length; i++) {
                    for (int r = 0; r < roots.length; r++) {
                        if (GitUtils.isParentOrEqual(roots[r], files[i])) {
                            if (!fileList.contains(files[i])) {
                                fileList.add(files[i]);
                            }
                        }
                    }
                }
            } else {
                File[] files = GitUtils.flatten(roots, StatusInfo.STATUS_LOCAL_CHANGE);
                for (int i = 0; i < files.length; i++) {
                    if (!fileList.contains(files[i])) {
                        fileList.add(files[i]);
                    }
                }
            }
        }

        if (fileList.size() == 0) {
            return;        // show commit dialog
        }
        final CommitPanel panel = new CommitPanel();
        final CommitTable data = new CommitTable(panel.filesLabel, CommitTable.COMMIT_COLUMNS, new String[]{CommitTableModel.COLUMN_NAME_PATH});

        panel.setCommitTable(data);

        Properties props = GitModuleConfig.getDefault().getProperties(repository);
        String signOff = props.getProperty("nbgit.signoff");
        if (signOff.equals("yes")) {
            signOff = "Signed-off-by: " +props.getProperty("user.name")
                    + " <" + props.getProperty("user.email") + ">";
            panel.putClientProperty(SIGN_OFF_MESSAGE, signOff);
        }

        GitFileNode[] nodes;
        ArrayList<GitFileNode> nodesList = new ArrayList<GitFileNode>(fileList.size());

        for (File file : fileList) {
            GitFileNode node = new GitFileNode(file);
            nodesList.add(node);
        }
        nodes = nodesList.toArray(new GitFileNode[fileList.size()]);
        data.setNodes(nodes);

        JComponent component = data.getComponent();
        panel.filesPanel.setLayout(new BorderLayout());
        panel.filesPanel.add(component, BorderLayout.CENTER);

        DialogDescriptor dd = new DialogDescriptor(panel, org.openide.util.NbBundle.getMessage(CommitAction.class, "CTL_CommitDialog_Title", contentTitle)); // NOI18N
        dd.setModal(true);
        final JButton commitButton = new JButton();
        org.openide.awt.Mnemonics.setLocalizedText(commitButton, org.openide.util.NbBundle.getMessage(CommitAction.class, "CTL_Commit_Action_Commit"));
        commitButton.getAccessibleContext().setAccessibleName(org.openide.util.NbBundle.getMessage(CommitAction.class, "ACSN_Commit_Action_Commit"));
        commitButton.getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getMessage(CommitAction.class, "ACSD_Commit_Action_Commit"));
        final JButton cancelButton = new JButton(org.openide.util.NbBundle.getMessage(CommitAction.class, "CTL_Commit_Action_Cancel")); // NOI18N
        org.openide.awt.Mnemonics.setLocalizedText(cancelButton, org.openide.util.NbBundle.getMessage(CommitAction.class, "CTL_Commit_Action_Cancel"));
        cancelButton.getAccessibleContext().setAccessibleName(org.openide.util.NbBundle.getMessage(CommitAction.class, "ACSN_Commit_Action_Cancel"));
        cancelButton.getAccessibleContext().setAccessibleDescription(org.openide.util.NbBundle.getMessage(CommitAction.class, "ACSD_Commit_Action_Cancel"));

        commitButton.setEnabled(false);
        dd.setOptions(new Object[]{commitButton, cancelButton});
        dd.setHelpCtx(new HelpCtx(CommitAction.class));
        panel.addVersioningListener(new VersioningListener() {

            public void versioningEvent(VersioningEvent event) {
                refreshCommitDialog(panel, data, commitButton);
            }
        });
        data.getTableModel().addTableModelListener(new TableModelListener() {

            public void tableChanged(TableModelEvent e) {
                refreshCommitDialog(panel, data, commitButton);
            }
        });
        commitButton.setEnabled(containsCommitable(data));

        panel.putClientProperty("contentTitle", contentTitle)// NOI18N
        panel.putClientProperty("DialogDescriptor", dd); // NOI18N
        final Dialog dialog = DialogDisplayer.getDefault().createDialog(dd);

        dialog.addWindowListener(new DialogBoundsPreserver(GitModuleConfig.getDefault().getPreferences(), "git.commit.dialog")); // NOI18N
        dialog.pack();
        dialog.setVisible(true);

        if (dd.getValue() == commitButton) {

            final Map<GitFileNode, CommitOptions> commitFiles = data.getCommitFiles();
            String origMessage = panel.messageTextArea.getText();
            String stripSpace = props.getProperty("nbgit.stripspace");
            if (stripSpace.equals("yes")) {
                origMessage = stripSpace(origMessage);
            }
            final String message = origMessage;
            org.netbeans.modules.versioning.util.Utils.insert(GitModuleConfig.getDefault().getPreferences(), RECENT_COMMIT_MESSAGES, origMessage, 20);
            RequestProcessor rp = Git.getInstance().getRequestProcessor(repository.getAbsolutePath());
            GitProgressSupport support = new GitProgressSupport() {

                public void perform() {
                    OutputLogger logger = getLogger();
                    performCommit(message, commitFiles, ctx, this, prjName, logger);
                }
            };
            support.start(rp, repository.getAbsolutePath(), org.openide.util.NbBundle.getMessage(CommitAction.class, "LBL_Commit_Progress")); // NOI18N
        }
    }

    private static boolean containsCommitable(CommitTable data) {
        Map<GitFileNode, CommitOptions> map = data.getCommitFiles();
        for (CommitOptions co : map.values()) {
            if (co != CommitOptions.EXCLUDE) {
                return true;
            }
        }
        return false;
    }

    /**
     * User changed a commit action.
     *
     * @param panel
     * @param commit
     */
    private static void refreshCommitDialog(CommitPanel panel, CommitTable table, JButton commit) {
        ResourceBundle loc = NbBundle.getBundle(CommitAction.class);
        Map<GitFileNode, CommitOptions> files = table.getCommitFiles();
        Set<String> stickyTags = new HashSet<String>();
        boolean conflicts = false;

        boolean enabled = commit.isEnabled();

        for (GitFileNode fileNode : files.keySet()) {

            CommitOptions options = files.get(fileNode);
            if (options == CommitOptions.EXCLUDE) {
                continue;
            //stickyTags.add(GitUtils.getCopy(fileNode.getFile()));
            }
            int status = fileNode.getInformation().getStatus();
            if ((status & StatusInfo.STATUS_REMOTE_CHANGE) != 0 || status == StatusInfo.STATUS_VERSIONED_CONFLICT) {
                enabled = false;
                String msg = (status == StatusInfo.STATUS_VERSIONED_CONFLICT) ? loc.getString("MSG_CommitForm_ErrorConflicts") : // NOI18N
                        loc.getString("MSG_CommitForm_ErrorRemoteChanges"); // NOI18N
                panel.setErrorLabel("<html><font color=\"#002080\">" + msg + "</font></html>")// NOI18N
                conflicts = true;
            }
        //stickyTags.add(GitUtils.getCopy(fileNode.getFile()));

        }

        if (stickyTags.size() > 1) {
            table.setColumns(new String[]{CommitTableModel.COLUMN_NAME_NAME, CommitTableModel.COLUMN_NAME_BRANCH, CommitTableModel.COLUMN_NAME_STATUS,
                        CommitTableModel.COLUMN_NAME_ACTION, CommitTableModel.COLUMN_NAME_PATH
                    });
        } else {
            table.setColumns(new String[]{CommitTableModel.COLUMN_NAME_NAME, CommitTableModel.COLUMN_NAME_STATUS,
                        CommitTableModel.COLUMN_NAME_ACTION, CommitTableModel.COLUMN_NAME_PATH
                    });
        }
        String contentTitle = (String) panel.getClientProperty("contentTitle"); // NOI18N
// NOI18N
        DialogDescriptor dd = (DialogDescriptor) panel.getClientProperty("DialogDescriptor"); // NOI18N
        String errorLabel;
        if (stickyTags.size() <= 1) {
            String stickyTag = stickyTags.size() == 0 ? null : stickyTags.iterator().next();
            if (stickyTag == null) {
                dd.setTitle(MessageFormat.format(loc.getString("CTL_CommitDialog_Title"), new Object[]{contentTitle})); // NOI18N
                errorLabel = ""; // NOI18N
            } else {
                dd.setTitle(MessageFormat.format(loc.getString("CTL_CommitDialog_Title_Branch"), new Object[]{contentTitle, stickyTag})); // NOI18N
                String msg = MessageFormat.format(loc.getString("MSG_CommitForm_InfoBranch"), new Object[]{stickyTag}); // NOI18N
                errorLabel = "<html><font color=\"#002080\">" + msg + "</font></html>"; // NOI18N
            }
        } else {
            dd.setTitle(MessageFormat.format(loc.getString("CTL_CommitDialog_Title_Branches"), new Object[]{contentTitle})); // NOI18N
            String msg = loc.getString("MSG_CommitForm_ErrorMultipleBranches"); // NOI18N
            errorLabel = "<html><font color=\"#CC0000\">" + msg + "</font></html>"; // NOI18N
        }
        if (!conflicts) {
            panel.setErrorLabel(errorLabel);
            enabled = true;
        }
        commit.setEnabled(enabled && containsCommitable(table));
    }

    private static void performCommit(String message, Map<GitFileNode, CommitOptions> commitFiles,
            VCSContext ctx, GitProgressSupport support, String prjName, OutputLogger logger) {
        StatusCache cache = Git.getInstance().getStatusCache();
        final File repository = GitUtils.getRootFile(ctx);
        List<File> addCandidates = new ArrayList<File>();
        List<File> deleteCandidates = new ArrayList<File>();
        int commitCandidates = 0;

        List<String> excPaths = new ArrayList<String>();
        List<String> incPaths = new ArrayList<String>();
        for (GitFileNode node : commitFiles.keySet()) {
            if (support.isCanceled()) {
                return;
            }
            CommitOptions option = commitFiles.get(node);
            if (option != CommitOptions.EXCLUDE) {
                int status = cache.getStatus(node.getFile()).getStatus();
                if ((status & StatusInfo.STATUS_NOTVERSIONED_NEWLOCALLY) != 0) {
                    addCandidates.add(node.getFile());
                } else if ((status & StatusInfo.STATUS_VERSIONED_DELETEDLOCALLY) != 0) {
                    deleteCandidates.add(node.getFile());
                } else {
                    addCandidates.add(node.getFile());
                }
                commitCandidates++;
                incPaths.add(node.getFile().getAbsolutePath());
            } else {
                excPaths.add(node.getFile().getAbsolutePath());
            }
        }
        if (support.isCanceled()) {
            return;
        }
        if (!excPaths.isEmpty()) {
            GitModuleConfig.getDefault().addExclusionPaths(excPaths);
        }
        if (!incPaths.isEmpty()) {
            GitModuleConfig.getDefault().removeExclusionPaths(incPaths);
        }
        try {
            logger.outputInRed(
                    NbBundle.getMessage(CommitAction.class,
                    "MSG_COMMIT_TITLE")); // NOI18N
            logger.outputInRed(
                    NbBundle.getMessage(CommitAction.class,
                    "MSG_COMMIT_TITLE_SEP")); // NOI18N
            logger.output(message); // NOI18N

            CommitBuilder.create(repository).
                    log(logger).
                    addAll(addCandidates).
                    deleteAll(deleteCandidates).
                    message(message).
                    write();

            if (commitCandidates == 1) {
                logger.output(
                        NbBundle.getMessage(CommitAction.class,
                        "MSG_COMMIT_INIT_SEP_ONE", commitCandidates, prjName));
            } else {
                logger.output(
                        NbBundle.getMessage(CommitAction.class,
                        "MSG_COMMIT_INIT_SEP", commitCandidates, prjName));
            }
        } catch (Exception ex) {
            notifyLater(ex);
        } finally {
            cache.refreshCached(ctx);
            logger.outputInRed(NbBundle.getMessage(CommitAction.class, "MSG_COMMIT_DONE")); // NOI18N
            logger.output(""); // NOI18N
        }
    }

    static String stripSpace(String message) {
        StringBuilder builder = new StringBuilder();
        String[] lines = message.split("\n");
        String sep = "\n";
        int i = 0;

        for (String line : lines) {
            int j = line.length();

            while (j > 0) {
                if (!Character.isWhitespace(line.charAt(j - 1))) {
                    break;
                }
                j--;
            }

            if (j > 0) {
                if (builder.length() > 0) {
                    builder.append(sep);
                }
                builder.append(line, 0, j);
                builder.append("\n");
                sep = "";
            } else if (sep.length() == 0) {
                sep = "\n";
            } else {
                continue;
            }
        }

        return builder.toString();
    }
}
TOP

Related Classes of org.nbgit.ui.commit.CommitAction

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.