Package org.eclipse.egit.ui.internal.commit

Source Code of org.eclipse.egit.ui.internal.commit.CommitUI$CountingVisitor

/*******************************************************************************
* Copyright (C) 2007, Dave Watson <dwatson@mimvista.com>
* Copyright (C) 2007, Jing Xue <jingxue@digizenstudio.com>
* Copyright (C) 2007, Robin Rosenberg <me@lathund.dewire.com>
* Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
* Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
* Copyright (C) 2010, Stefan Lay <stefan.lay@sap.com>
* Copyright (C) 2011, Jens Baumgart <jens.baumgart@sap.com>
* Copyright (C) 2012, Robin Stocker <robin@nibor.org>
*
* 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
*******************************************************************************/
package org.eclipse.egit.ui.internal.commit;


import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.net.URI;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceVisitor;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.egit.core.EclipseGitProgressTransformer;
import org.eclipse.egit.core.IteratorService;
import org.eclipse.egit.core.op.CommitOperation;
import org.eclipse.egit.core.project.RepositoryMapping;
import org.eclipse.egit.ui.Activator;
import org.eclipse.egit.ui.UIUtils;
import org.eclipse.egit.ui.internal.UIText;
import org.eclipse.egit.ui.internal.dialogs.BasicConfigurationDialog;
import org.eclipse.egit.ui.internal.dialogs.CommitDialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.IndexDiff;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.treewalk.WorkingTreeIterator;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.PlatformUI;

/**
* UI component for performing a commit
*/
public class CommitUI  {

  private IndexDiff indexDiff;

  private Set<String> notIndexed;

  private Set<String> indexChanges;

  private Set<String> notTracked;

  private Set<String> files;

  private boolean amending;

  private Shell shell;

  private Repository repo;

  private IResource[] selectedResources;

  private boolean preselectAll;

  /**
   * Constructs a CommitUI object
   * @param shell
   *            Shell to use for UI interaction. Must not be null.
   * @param repo
   *            Repository to commit. Must not be null
   * @param selectedResources
   *            Resources selected by the user. A file is preselected in the
   *            commit dialog if the file is contained in selectedResources or
   *            if selectedResources contains a resource that is parent of the
   *            file. selectedResources must not be null.
   * @param preselectAll
   *         preselect all changed files in the commit dialog.
   *         If set to true selectedResources are ignored.
   */
  public CommitUI(Shell shell, Repository repo,
      IResource[] selectedResources, boolean preselectAll) {
    this.shell = shell;
    this.repo = repo;
    this.selectedResources = new IResource[selectedResources.length];
    // keep our own copy
    System.arraycopy(selectedResources, 0, this.selectedResources, 0,
        selectedResources.length);
    this.preselectAll = preselectAll;
  }

  /**1
   * Performs a commit
   * @return true if a commit operation was triggered
   */
  public boolean commit() {
    // let's see if there is any dirty editor around and
    // ask the user if they want to save or abort
    if (!UIUtils.saveAllEditors(repo))
      return false;

    BasicConfigurationDialog.show(new Repository[]{repo});

    resetState();
    final IProject[] projects = getProjectsOfRepositories();
    try {
      PlatformUI.getWorkbench().getProgressService().busyCursorWhile(new IRunnableWithProgress() {

        public void run(IProgressMonitor monitor) throws InvocationTargetException,
            InterruptedException {
          try {
            buildIndexHeadDiffList(projects, monitor);
          } catch (IOException e) {
            throw new InvocationTargetException(e);
          }
        }
      });
    } catch (InvocationTargetException e) {
      Activator.handleError(UIText.CommitAction_errorComputingDiffs, e.getCause(),
          true);
      return false;
    } catch (InterruptedException e) {
      return false;
    }

    CommitHelper commitHelper = new CommitHelper(repo);

    if (!commitHelper.canCommit()) {
      MessageDialog.openError(
          shell,
          UIText.CommitAction_cannotCommit,
          commitHelper.getCannotCommitMessage());
      return false;
    }
    boolean amendAllowed = commitHelper.amendAllowed();
    if (files.isEmpty()) {
      if (amendAllowed && commitHelper.getPreviousCommit() != null) {
        boolean result = MessageDialog.openQuestion(shell,
            UIText.CommitAction_noFilesToCommit,
            UIText.CommitAction_amendCommit);
        if (!result)
          return false;
        amending = true;
      } else {
        MessageDialog.openWarning(shell,
            UIText.CommitAction_noFilesToCommit,
            UIText.CommitAction_amendNotPossible);
        return false;
      }
    }

    CommitDialog commitDialog = new CommitDialog(shell);
    commitDialog.setAmending(amending);
    commitDialog.setAmendAllowed(amendAllowed);
    commitDialog.setFiles(repo, files, indexDiff);
    commitDialog.setPreselectedFiles(getSelectedFiles());
    commitDialog.setPreselectAll(preselectAll);
    commitDialog.setAuthor(commitHelper.getAuthor());
    commitDialog.setCommitter(commitHelper.getCommitter());
    commitDialog.setAllowToChangeSelection(!commitHelper.isMergedResolved && !commitHelper.isCherryPickResolved);
    commitDialog.setCommitMessage(commitHelper.getCommitMessage());

    if (commitDialog.open() != IDialogConstants.OK_ID)
      return false;

    final CommitOperation commitOperation;
    try {
      commitOperation= new CommitOperation(
          repo,
          commitDialog.getSelectedFiles(), notTracked, commitDialog.getAuthor(),
          commitDialog.getCommitter(), commitDialog.getCommitMessage());
    } catch (CoreException e1) {
      Activator.handleError(UIText.CommitUI_commitFailed, e1, true);
      return false;
    }
    if (commitDialog.isAmending())
      commitOperation.setAmending(true);
    commitOperation.setComputeChangeId(commitDialog.getCreateChangeId());
    commitOperation.setCommitAll(commitHelper.isMergedResolved);
    if (commitHelper.isMergedResolved)
      commitOperation.setRepository(repo);
    Job commitJob = new CommitJob(repo, commitOperation).
        setPushUpstream(commitDialog.isPushRequested());
    commitJob.schedule();

    return true;
  }

  private IProject[] getProjectsOfRepositories() {
    Set<IProject> ret = new HashSet<IProject>();
    final IProject[] projects = ResourcesPlugin.getWorkspace().getRoot()
        .getProjects();
    for (IProject project : projects) {
      RepositoryMapping mapping = RepositoryMapping.getMapping(project);
      if (mapping != null && mapping.getRepository() == repo)
        ret.add(project);
    }
    return ret.toArray(new IProject[ret.size()]);
  }

  private void resetState() {
    files = new LinkedHashSet<String>();
    notIndexed = new LinkedHashSet<String>();
    indexChanges = new LinkedHashSet<String>();
    notTracked = new LinkedHashSet<String>();
    amending = false;
    indexDiff = null;
  }

  /**
   * Retrieves a collection of files that may be committed based on the user's
   * selection when they performed the commit action. That is, even if the
   * user only selected one folder when the action was performed, if the
   * folder contains any files that could be committed, they will be returned.
   *
   * @return a collection of files that is eligible to be committed based on
   *         the user's selection
   */
  private Set<String> getSelectedFiles() {
    Set<String> preselectionCandidates = new LinkedHashSet<String>();
    IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();
    // iterate through all the files that may be committed
    for (String fileName : files) {
      URI uri = new File(repo.getWorkTree(), fileName).toURI();
      IFile[] workspaceFiles = root.findFilesForLocationURI(uri);
      if (workspaceFiles.length > 0) {
        IFile file = workspaceFiles[0];
        for (IResource resource : selectedResources) {
          // if any selected resource contains the file, add it as a
          // preselection candidate
          if (resource.contains(file)) {
            preselectionCandidates.add(fileName);
            break;
          }
        }
      } else {
        // could be file outside of workspace
        for (IResource resource : selectedResources) {
          if(resource.getFullPath().toFile().equals(new File(uri))) {
            preselectionCandidates.add(fileName);
          }
        }
      }
    }
    return preselectionCandidates;
  }

  private void buildIndexHeadDiffList(IProject[] selectedProjects,
      IProgressMonitor monitor) throws IOException,
      OperationCanceledException {

    monitor.beginTask(UIText.CommitActionHandler_calculatingChanges, 1000);
    EclipseGitProgressTransformer jgitMonitor = new EclipseGitProgressTransformer(
        monitor);
    CountingVisitor counter = new CountingVisitor();
    for (IProject p : selectedProjects) {
      try {
        p.accept(counter);
      } catch (CoreException e) {
        // ignore
      }
    }
    WorkingTreeIterator it = IteratorService.createInitialIterator(repo);
    if (it == null)
      throw new OperationCanceledException(); // workspace is closed
    indexDiff = new IndexDiff(repo, Constants.HEAD, it);
    indexDiff.diff(jgitMonitor, counter.count, 0, NLS.bind(
        UIText.CommitActionHandler_repository, repo.getDirectory()
            .getPath()));

    includeList(indexDiff.getAdded(), indexChanges);
    includeList(indexDiff.getChanged(), indexChanges);
    includeList(indexDiff.getRemoved(), indexChanges);
    includeList(indexDiff.getMissing(), notIndexed);
    includeList(indexDiff.getModified(), notIndexed);
    includeList(indexDiff.getUntracked(), notTracked);
    if (monitor.isCanceled())
      throw new OperationCanceledException();
    monitor.done();
  }

  static class CountingVisitor implements IResourceVisitor {
    int count;
    public boolean visit(IResource resource) throws CoreException {
      count++;
      return true;
    }
  }

  private void includeList(Set<String> added, Set<String> category) {
    for (String filename : added) {
      if (!files.contains(filename))
        files.add(filename);
      category.add(filename);
    }
  }

}
TOP

Related Classes of org.eclipse.egit.ui.internal.commit.CommitUI$CountingVisitor

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.