org.tigris.subversion.subclipse.ui.subscriber.CommitSynchronizeOperation.java Source code

Java tutorial

Introduction

Here is the source code for org.tigris.subversion.subclipse.ui.subscriber.CommitSynchronizeOperation.java

Source

/*******************************************************************************
 * Copyright (c) 2004, 2006 Subclipse project and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     Subclipse project committers - initial API and implementation
 ******************************************************************************/
package org.tigris.subversion.subclipse.ui.subscriber;

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.eclipse.compare.structuremergeviewer.IDiffElement;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.team.core.RepositoryProvider;
import org.eclipse.team.core.synchronize.SyncInfoSet;
import org.eclipse.team.internal.core.subscribers.ActiveChangeSet;
import org.eclipse.team.internal.core.subscribers.ChangeSet;
import org.eclipse.team.ui.synchronize.ISynchronizePageConfiguration;
import org.tigris.subversion.subclipse.core.ISVNLocalResource;
import org.tigris.subversion.subclipse.core.SVNException;
import org.tigris.subversion.subclipse.core.SVNProviderPlugin;
import org.tigris.subversion.subclipse.core.SVNTeamProvider;
import org.tigris.subversion.subclipse.core.resources.SVNWorkspaceRoot;
import org.tigris.subversion.subclipse.core.util.File2Resource;
import org.tigris.subversion.subclipse.core.util.Util;
import org.tigris.subversion.subclipse.ui.ISVNUIConstants;
import org.tigris.subversion.subclipse.ui.Policy;
import org.tigris.subversion.subclipse.ui.SVNUIPlugin;
import org.tigris.subversion.subclipse.ui.dialogs.CommitToTagsWarningDialog;
import org.tigris.subversion.subclipse.ui.operations.CommitOperation;
import org.tigris.subversion.subclipse.ui.settings.ProjectProperties;
import org.tigris.subversion.subclipse.ui.wizards.dialogs.SvnWizard;
import org.tigris.subversion.subclipse.ui.wizards.dialogs.SvnWizardCommitPage;
import org.tigris.subversion.subclipse.ui.wizards.dialogs.SvnWizardDialog;

/**
 * Sync view operation for putting file system resources
 */
public class CommitSynchronizeOperation extends SVNSynchronizeOperation {
    private String commitComment;
    private IResource[] resourcesToCommit;
    private String url;
    private ChangeSet changeSet;
    private boolean commit;
    private boolean keepLocks;
    private String proposedComment;
    private ISynchronizePageConfiguration configuration;

    protected CommitSynchronizeOperation(ISynchronizePageConfiguration configuration, IDiffElement[] elements,
            String url, String proposedComment) {
        super(configuration, elements);
        this.configuration = configuration;
        this.url = url;
        this.proposedComment = proposedComment;
    }

    private boolean confirmCommit(SyncInfoSet set) {
        commit = false;
        IResource[] modified = set.getResources();
        List conflictFiles = new ArrayList();
        List filteredModified = new ArrayList();
        boolean switched = false;
        for (int i = 0; i < modified.length; i++) {
            IResource resource = modified[i];
            filteredModified.add(resource);
            if (!(resource instanceof IContainer)) {
                ISVNLocalResource svnResource = SVNWorkspaceRoot.getSVNResourceFor(resource);
                try {
                    if (svnResource.isManaged() && svnResource.getStatus().isTextConflicted()) {
                        IFile conflictNewFile = (IFile) File2Resource
                                .getResource(svnResource.getStatus().getConflictNew());
                        if (conflictNewFile != null)
                            conflictFiles.add(conflictNewFile);
                        IFile conflictOldFile = (IFile) File2Resource
                                .getResource(svnResource.getStatus().getConflictOld());
                        if (conflictOldFile != null)
                            conflictFiles.add(conflictOldFile);
                        IFile conflictWorkingFile = (IFile) File2Resource
                                .getResource(svnResource.getStatus().getConflictWorking());
                        if (conflictWorkingFile != null)
                            conflictFiles.add(conflictWorkingFile);
                    }
                    if (svnResource.getStatus().isSwitched()) {
                        url = svnResource.getStatus().getUrlString();
                        switched = true;
                    }
                } catch (SVNException e) {
                }
            }
        }
        if (switched && modified.length > 1) {
            url = null;
        }
        if (conflictFiles.size() > 0) {
            Iterator iter = conflictFiles.iterator();
            while (iter.hasNext()) {
                IFile conflictFile = (IFile) iter.next();
                filteredModified.remove(conflictFile);
            }
            modified = new IResource[filteredModified.size()];
            filteredModified.toArray(modified);
        }
        if (modified.length > 0) {
            try {
                IPreferenceStore preferenceStore = SVNUIPlugin.getPlugin().getPreferenceStore();
                boolean commitToTagsPathWithoutWarning = preferenceStore
                        .getBoolean(ISVNUIConstants.PREF_COMMIT_TO_TAGS_PATH_WITHOUT_WARNING);
                if (!commitToTagsPathWithoutWarning && onTagPath(modified)) {
                    commit = true;
                    getShell().getDisplay().syncExec(new Runnable() {
                        public void run() {
                            CommitToTagsWarningDialog dialog = new CommitToTagsWarningDialog(getShell());
                            commit = dialog.open() == CommitToTagsWarningDialog.OK;
                        }
                    });
                    if (!commit) {
                        return false;
                    }
                }

                ProjectProperties projectProperties = ProjectProperties.getProjectProperties(modified[0]);

                SvnWizardCommitPage commitPage = new SvnWizardCommitPage(modified, url, projectProperties,
                        new HashMap(), changeSet, true);
                if (proposedComment == null || proposedComment.length() == 0)
                    commitPage.setComment(getProposedComment(modified));
                else
                    commitPage.setComment(proposedComment);
                commitPage.setSyncInfoSet(set);
                SvnWizard wizard = new SvnWizard(commitPage);
                final SvnWizardDialog dialog = new SvnWizardDialog(getShell(), wizard);
                wizard.setParentDialog(dialog);
                getShell().getDisplay().syncExec(new Runnable() {
                    public void run() {
                        commit = (dialog.open() == SvnWizardDialog.OK);
                    }
                });
                if (commit) {
                    resourcesToCommit = commitPage.getSelectedResources();
                    keepLocks = commitPage.isKeepLocks();
                }
                commitComment = commitPage.getComment();
            } catch (SVNException e) {
                if (!e.operationInterrupted()) {
                    SVNUIPlugin.log(IStatus.ERROR, e.getMessage(), e);
                }
            }
        }
        return commit;
    }

    /* (non-Javadoc)
    * @see org.eclipse.team.examples.filesystem.ui.FileSystemSynchronizeOperation#promptForConflictHandling(org.eclipse.swt.widgets.Shell, org.eclipse.team.core.synchronize.SyncInfoSet)
    */
    protected boolean promptForConflictHandling(Shell shell, SyncInfoSet syncSet) {
        return true;
    }

    /*
     * Get a proposed comment by looking at the active change sets
     */
    private String getProposedComment(IResource[] resourcesToCommit) {
        StringBuffer comment = new StringBuffer();
        ChangeSet[] sets = SVNProviderPlugin.getPlugin().getChangeSetManager().getSets();
        int numMatchedSets = 0;
        for (int i = 0; i < sets.length; i++) {
            ChangeSet set = sets[i];
            if (isUserSet(set) && containsOne(set, resourcesToCommit)) {
                if (numMatchedSets > 0)
                    comment.append(System.getProperty("line.separator")); //$NON-NLS-1$
                comment.append(set.getComment());
                numMatchedSets++;
            }
        }
        return comment.toString();
    }

    private boolean isUserSet(ChangeSet set) {
        if (set instanceof ActiveChangeSet) {
            ActiveChangeSet acs = (ActiveChangeSet) set;
            return acs.isUserCreated();
        }
        return false;
    }

    private boolean containsOne(ChangeSet set, IResource[] resourcesToCommit) {
        for (int j = 0; j < resourcesToCommit.length; j++) {
            IResource resource = resourcesToCommit[j];
            if (set.contains(resource)) {
                return true;
            }
            if (set instanceof ActiveChangeSet) {
                ActiveChangeSet acs = (ActiveChangeSet) set;
                if (acs.getDiffTree().members(resource).length > 0)
                    return true;
            }
        }
        return false;
    }

    /**
     * Prompts the user to determine how conflicting changes should be handled.
     * Note: This method is designed to be overridden by test cases.
     * @return 0 to sync conflicts, 1 to sync all non-conflicts, 2 to cancel
     */
    private int promptForConflicts(Shell shell, SyncInfoSet syncSet) {
        String[] buttons = new String[] { IDialogConstants.YES_LABEL, IDialogConstants.NO_LABEL };
        String title = Policy.bind("SyncAction.commit.conflict.title"); //$NON-NLS-1$
        String question = Policy.bind("SyncAction.commit.conflict.question"); //$NON-NLS-1$
        final MessageDialog dialog = new MessageDialog(shell, title, null, question, MessageDialog.QUESTION,
                buttons, 0);
        shell.getDisplay().syncExec(new Runnable() {
            public void run() {
                dialog.open();
            }
        });
        return dialog.getReturnCode();
    }

    //   private IResource[] getUnaddedResources(SyncInfoSet set) {
    //       IResource[] resources = set.getResources();
    //      List result = new ArrayList();
    //      for (int i = 0; i < resources.length; i++) {
    //         IResource resource = resources[i];
    //         if (isAdded(resource)) {
    //            result.add(resource);
    //         }
    //      }
    //      return (IResource[]) result.toArray(new IResource[result.size()]);
    //   }

    //   private boolean isAdded(IResource resource) {
    //       ISVNLocalResource svnResource = SVNWorkspaceRoot.getSVNResourceFor(resource);
    //      try {
    //         if (svnResource.isIgnored())
    //            return false;
    //         // visit the children of shared resources
    //         if (svnResource.isManaged())
    //            return false;
    //         if ((resource.getType() == IResource.FOLDER) && isSymLink(resource)) // don't traverse into symlink folders
    //            return false;
    //      } catch (SVNException e) {
    //          SVNUIPlugin.log(IStatus.ERROR, e.getMessage(), e);
    //          return false;
    //      }
    //      return true;
    //    }

    //   private boolean isSymLink(IResource resource) {
    //      File file = resource.getLocation().toFile();
    //       try {
    //          if (!file.exists())
    //             return true;
    //          else {
    //             String cnnpath = file.getCanonicalPath();
    //             String abspath = file.getAbsolutePath();
    //             return !abspath.equals(cnnpath);
    //          }
    //       } catch(IOException ex) {
    //         return true;
    //       }   
    //   }

    public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
        // First, ask the user if they want to include conflicts
        SyncInfoSet syncSet = getSyncInfoSet();
        if (!promptForConflictHandling(getShell(), syncSet))
            return;
        // Divide the sync info by project
        final Map projectSyncInfos = getProjectSyncInfoSetMap(syncSet);
        Iterator iter = projectSyncInfos.keySet().iterator();
        final IProject project = (IProject) iter.next();
        SVNTeamProvider provider = (SVNTeamProvider) RepositoryProvider.getProvider(project,
                SVNUIPlugin.PROVIDER_ID);
        monitor.beginTask(null, projectSyncInfos.size() * 100);
        run(provider, syncSet, Policy.subMonitorFor(monitor, 100));
        monitor.done();
    }

    /* (non-Javadoc)
    * @see org.eclipse.team.examples.filesystem.ui.FileSystemSynchronizeOperation#run(org.eclipse.team.examples.filesystem.FileSystemProvider, org.eclipse.team.core.synchronize.SyncInfoSet, org.eclipse.core.runtime.IProgressMonitor)
    */
    protected void run(SVNTeamProvider provider, SyncInfoSet set, IProgressMonitor monitor) {
        if (set.hasConflicts() || set.hasIncomingChanges()) {
            switch (promptForConflicts(getShell(), set)) {
            case 0:
                // Yes, commit non-conflicts
                set.removeConflictingNodes();
                set.removeIncomingNodes();
                break;
            case 1:
                // No, stop here
                return;
            default:
                return;
            }
        }
        if (confirmCommit(set)) {
            final IResource[][] resourcesToBeAdded = new IResource[][] { null };
            final IResource[][] resourcesToBeDeleted = new IResource[][] { null };
            List toBeAddedList = new ArrayList();
            List toBeDeletedList = new ArrayList();
            for (int i = 0; i < resourcesToCommit.length; i++) {
                IResource resource = resourcesToCommit[i];
                ISVNLocalResource svnResource = SVNWorkspaceRoot.getSVNResourceFor(resource);
                try {
                    if (!svnResource.isManaged())
                        toBeAddedList.add(resource);
                    if (svnResource.getStatus().isMissing())
                        toBeDeletedList.add(resource);
                } catch (SVNException e) {
                    SVNUIPlugin.log(IStatus.ERROR, e.getMessage(), e);
                }
            }
            resourcesToBeAdded[0] = new IResource[toBeAddedList.size()];
            toBeAddedList.toArray(resourcesToBeAdded[0]);
            resourcesToBeDeleted[0] = new IResource[toBeDeletedList.size()];
            toBeDeletedList.toArray(resourcesToBeDeleted[0]);
            try {
                CommitOperation commit = new CommitOperation(getPart(), resourcesToCommit, resourcesToBeAdded[0],
                        resourcesToBeDeleted[0], resourcesToCommit, commitComment, keepLocks);
                commit.run();
            } catch (InvocationTargetException e) {
                SVNUIPlugin.log(IStatus.ERROR, e.getMessage(), e);
            } catch (InterruptedException e) {
                SVNUIPlugin.log(IStatus.ERROR, e.getMessage(), e);
            }
        }
    }

    public void setChangeSet(ChangeSet changeSet) {
        this.changeSet = changeSet;
    }

    private boolean onTagPath(IResource[] modifiedResources) throws SVNException {
        // Multiple resources selected.
        if (url == null) {
            IResource resource = modifiedResources[0];
            ISVNLocalResource svnResource = SVNWorkspaceRoot.getSVNResourceFor(resource);
            String firstUrl = svnResource.getStatus().getUrlString();
            if ((firstUrl == null) || (resource.getType() == IResource.FILE))
                firstUrl = Util.getParentUrl(svnResource);
            if (firstUrl.indexOf("/tags/") != -1) //$NON-NLS-1$
                return true;
        }
        // One resource selected.
        else if (url.indexOf("/tags/") != -1) //$NON-NLS-1$
            return true;
        return false;
    }

}