Package org.eclipse.egit.ui.internal.synchronize

Source Code of org.eclipse.egit.ui.internal.synchronize.GitModelSynchronizeParticipant

/*******************************************************************************
* Copyright (C) 2010, 2014 Dariusz Luksza <dariusz@luksza.org> 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:
*     Dariusz Luksza <dariusz@luksza.org> - initial API and implementation
*     Laurent Goubet <laurent.goubet@obeo.fr> - Logical Model enhancements
*     Gunnar Wagenknecht <gunnar@wagenknecht.org> - Logical Model enhancements
*******************************************************************************/
package org.eclipse.egit.ui.internal.synchronize;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;

import org.eclipse.compare.CompareNavigator;
import org.eclipse.compare.ITypedElement;
import org.eclipse.compare.ResourceNode;
import org.eclipse.compare.structuremergeviewer.ICompareInput;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IEncodedStorage;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.resources.mapping.ModelProvider;
import org.eclipse.core.resources.mapping.ResourceMapping;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.jobs.IJobChangeEvent;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.core.runtime.jobs.JobChangeAdapter;
import org.eclipse.egit.core.AdapterUtils;
import org.eclipse.egit.core.internal.storage.WorkspaceFileRevision;
import org.eclipse.egit.core.internal.util.ResourceUtil;
import org.eclipse.egit.core.project.GitProjectData;
import org.eclipse.egit.core.project.RepositoryMapping;
import org.eclipse.egit.core.synchronize.GitResourceVariantTreeSubscriber;
import org.eclipse.egit.core.synchronize.GitSubscriberMergeContext;
import org.eclipse.egit.core.synchronize.GitSubscriberResourceMappingContext;
import org.eclipse.egit.core.synchronize.dto.GitSynchronizeData;
import org.eclipse.egit.core.synchronize.dto.GitSynchronizeDataSet;
import org.eclipse.egit.ui.Activator;
import org.eclipse.egit.ui.UIPreferences;
import org.eclipse.egit.ui.internal.UIText;
import org.eclipse.egit.ui.internal.revision.FileRevisionTypedElement;
import org.eclipse.egit.ui.internal.revision.GitCompareFileRevisionEditorInput;
import org.eclipse.egit.ui.internal.synchronize.model.GitModelBlob;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.osgi.util.NLS;
import org.eclipse.team.core.TeamException;
import org.eclipse.team.core.history.IFileRevision;
import org.eclipse.team.core.mapping.ISynchronizationContext;
import org.eclipse.team.core.mapping.ISynchronizationScopeManager;
import org.eclipse.team.core.mapping.provider.MergeContext;
import org.eclipse.team.core.mapping.provider.SynchronizationScopeManager;
import org.eclipse.team.core.subscribers.Subscriber;
import org.eclipse.team.core.subscribers.SubscriberMergeContext;
import org.eclipse.team.internal.ui.mapping.ResourceDiffCompareInput;
import org.eclipse.team.ui.TeamUI;
import org.eclipse.team.ui.synchronize.ISynchronizePageConfiguration;
import org.eclipse.team.ui.synchronize.ModelSynchronizeParticipant;
import org.eclipse.ui.IMemento;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.PartInitException;

/**
* Git model synchronization participant
*/
@SuppressWarnings("restriction")
public class GitModelSynchronizeParticipant extends ModelSynchronizeParticipant {

  /**
   * Key value for obtaining {@link GitSynchronizeDataSet} from {@link ISynchronizePageConfiguration}
   */
  public static final String SYNCHRONIZATION_DATA = "GIT_SYNCHRONIZE_DATA_SET"; //$NON-NLS-1$

  /**
   * Id of model compare participant
   */
  public static final String ID = "org.eclipse.egit.ui.modelCompareParticipant"; //$NON-NLS-1$

  /**
   * Id of model synchronization participant
   */
  public static final String VIEWER_ID = "org.eclipse.egit.ui.compareSynchronization"; //$NON-NLS-1$

  private static final String P_NAVIGATOR = "org.eclipse.team.ui.P_NAVIGATOR"; //$NON-NLS-1$

  private static final String WORKSPACE_MODEL_PROVIDER_ID = "org.eclipse.core.resources.modelProvider"; //$NON-NLS-1$

  private static final String DATA_NODE_KEY = "gitSynchronizeData"; //$NON-NLS-1$

  private static final String INCLUDED_PATHS_NODE_KEY = "includedPaths"; //$NON-NLS-1$

  private static final String INCLUDED_PATH_KEY = "path"; //$NON-NLS-1$

  private static final String CONTAINER_PATH_KEY = "container"; //$NON-NLS-1$

  private static final String SRC_REV_KEY = "srcRev"; //$NON-NLS-1$

  private static final String DST_REV_KEY = "dstRev"; //$NON-NLS-1$

  private static final String INCLUDE_LOCAL_KEY = "inludeLocal"; //$NON-NLS-1$

  private static final String FORCE_FETCH_KEY = "forceFetch"; //$NON-NLS-1$


  private GitSynchronizeDataSet gsds;

  /**
   * DO NOT USE. This constructor is preserved for dynamic initialization when
   * synchronization context is restored
   */
  public GitModelSynchronizeParticipant() {
  }

  /**
   * Creates {@link GitModelSynchronizeParticipant} for given context
   *
   * @param context
   */
  public GitModelSynchronizeParticipant(GitSubscriberMergeContext context) {
    super(context);
    gsds = context.getSyncData();

    try {
      setInitializationData(TeamUI.getSynchronizeManager()
          .getParticipantDescriptor(ID));
    } catch (CoreException e) {
      Activator.logError(e.getMessage(), e);
    }

    setSecondaryId(Long.toString(System.currentTimeMillis()));
  }

  protected void initializeConfiguration(
      final ISynchronizePageConfiguration configuration) {
    configuration.setProperty(ISynchronizePageConfiguration.P_VIEWER_ID,
        VIEWER_ID);
    String modelProvider = WORKSPACE_MODEL_PROVIDER_ID;
    final IPreferenceStore preferenceStore = Activator.getDefault()
        .getPreferenceStore();
    if (!gsds.containsFolderLevelSynchronizationRequest()) {
      if (preferenceStore
          .getBoolean(UIPreferences.SYNC_VIEW_ALWAYS_SHOW_CHANGESET_MODEL)) {
        modelProvider = GitChangeSetModelProvider.ID;
      } else {
        String lastSelectedModel = preferenceStore.getString(UIPreferences.SYNC_VIEW_LAST_SELECTED_MODEL);
        if (!"".equals(lastSelectedModel)) //$NON-NLS-1$
          modelProvider = lastSelectedModel;
      }
    }

    configuration.setProperty(
        ModelSynchronizeParticipant.P_VISIBLE_MODEL_PROVIDER,
        modelProvider);

    configuration.setProperty(SYNCHRONIZATION_DATA, gsds);

    super.initializeConfiguration(configuration);

    configuration.addActionContribution(new GitActionContributor());

    configuration.addPropertyChangeListener(new IPropertyChangeListener() {

      public void propertyChange(PropertyChangeEvent event) {
        String property = event.getProperty();
        if (property.equals(
            ModelSynchronizeParticipant.P_VISIBLE_MODEL_PROVIDER)) {
          String newValue = (String) event.getNewValue();
          preferenceStore.setValue(
              UIPreferences.SYNC_VIEW_LAST_SELECTED_MODEL,
              newValue);
        } else if (property.equals(P_NAVIGATOR)) {
          Object oldNavigator = configuration
              .getProperty(P_NAVIGATOR);
          if (!(oldNavigator instanceof GitTreeCompareNavigator))
            configuration.setProperty(P_NAVIGATOR,
                new GitTreeCompareNavigator(
                    (CompareNavigator) oldNavigator));
        }
      }
    });
  }

  @Override
  public ModelProvider[] getEnabledModelProviders() {
    ModelProvider[] avaliableProviders = super.getEnabledModelProviders();

    for (ModelProvider provider : avaliableProviders)
      if (provider.getId().equals(GitChangeSetModelProvider.ID))
        return avaliableProviders;

    int capacity = avaliableProviders.length + 1;
    ArrayList<ModelProvider> providers = new ArrayList<ModelProvider>(
        capacity);
    providers.add(GitChangeSetModelProvider.getProvider());

    return providers.toArray(new ModelProvider[providers.size()]);
  }

  @Override
  public boolean hasCompareInputFor(Object object) {
    if (object instanceof GitModelBlob || object instanceof IFile)
      return true;

    // in Java Workspace model Java source files are passed as type
    // CompilationUnit which can be adapted to IResource
    IResource res = AdapterUtils.adapt(object, IResource.class);
    if (res != null && res.getType() == IResource.FILE)
      return true;

    // fallback to super ISynchronizationCompareAdapter
    return super.hasCompareInputFor(object);
  }

  @Override
  public ICompareInput asCompareInput(Object object) {
    final ICompareInput input = super.asCompareInput(object);
    final ISynchronizationContext ctx = getContext();

    if (input instanceof ResourceDiffCompareInput && ctx instanceof SubscriberMergeContext) {
      // Team only considers local resources as "left"
      // We'll use the cached data instead as left could be remote
      final IResource resource = ((ResourceNode) input.getLeft())
          .getResource();
      final Subscriber subscriber = ((SubscriberMergeContext)ctx).getSubscriber();

      if (resource instanceof IFile
          && subscriber instanceof GitResourceVariantTreeSubscriber) {
        try {
          final IFileRevision revision = ((GitResourceVariantTreeSubscriber) subscriber)
              .getSourceFileRevision((IFile) resource);
          if (revision == null) {
            final ITypedElement newSource = new GitCompareFileRevisionEditorInput.EmptyTypedElement(
                resource.getName());
            ((ResourceDiffCompareInput) input).setLeft(newSource);
          } else if (!(revision instanceof WorkspaceFileRevision)) {
            final ITypedElement newSource = new FileRevisionTypedElement(
                revision, getLocalEncoding(resource));
            ((ResourceDiffCompareInput) input).setLeft(newSource);
          }
        } catch (TeamException e) {
          // Keep the input from super as-is
          String error = NLS
              .bind(UIText.GitModelSynchronizeParticipant_noCachedSourceVariant,
                  resource.getName());
          Activator.logError(error, e);
        }
      }
    }

    return input;
  }

  private static String getLocalEncoding(IResource resource) {
    if (resource instanceof IEncodedStorage) {
      IEncodedStorage es = (IEncodedStorage) resource;
      try {
        return es.getCharset();
      } catch (CoreException e) {
        Activator.logError(e.getMessage(), e);
      }
    }
    return null;
  }

  @Override
  public void run(final IWorkbenchPart part) {
    boolean fetchPossible = false;
    for (GitSynchronizeData data : gsds)
      if (data.getDstRemoteName() != null)
        fetchPossible = true;

    boolean launchFetch = Activator.getDefault().getPreferenceStore()
        .getBoolean(UIPreferences.SYNC_VIEW_FETCH_BEFORE_LAUNCH);
    if (fetchPossible && (launchFetch || gsds.forceFetch())) {
      Job fetchJob = new SynchronizeFetchJob(gsds);
      fetchJob.setUser(true);
      fetchJob.addJobChangeListener(new JobChangeAdapter() {
        @Override
        public void done(IJobChangeEvent event) {
          GitModelSynchronizeParticipant.super.run(part);
        }
      });

      fetchJob.schedule();
    } else
      super.run(part);
  }

  @Override
  public void saveState(IMemento memento) {
    super.saveState(memento);
    for (GitSynchronizeData gsd : gsds) {
      Repository repo = gsd.getRepository();
      RepositoryMapping mapping = RepositoryMapping.findRepositoryMapping(repo);
      if (mapping != null) {
        IMemento child = memento.createChild(DATA_NODE_KEY);
        child.putString(CONTAINER_PATH_KEY,
            getPathForResource(mapping.getContainer()));
        child.putString(SRC_REV_KEY, gsd.getSrcRev());
        child.putString(DST_REV_KEY, gsd.getDstRev());
        child.putBoolean(INCLUDE_LOCAL_KEY, gsd.shouldIncludeLocal());
        Set<IResource> includedResources = gsd.getIncludedResources();
        if (includedResources != null && !includedResources.isEmpty()) {
          IMemento paths = child.createChild(INCLUDED_PATHS_NODE_KEY);
          for (IResource resource : includedResources) {
            String path = getPathForResource(resource);
            paths.createChild(INCLUDED_PATH_KEY).putString(
                INCLUDED_PATH_KEY, path);
          }
        }
      }
    }
    memento.putBoolean(FORCE_FETCH_KEY, gsds.forceFetch());
  }

  @Override
  public void init(String secondaryId, IMemento memento)
      throws PartInitException {
    try {
      boolean forceFetchPref = Activator.getDefault().getPreferenceStore()
          .getBoolean(UIPreferences.SYNC_VIEW_FETCH_BEFORE_LAUNCH);
      boolean forceFetch = getBoolean(memento.getBoolean(FORCE_FETCH_KEY), forceFetchPref);
      gsds = new GitSynchronizeDataSet(forceFetch);
      IMemento[] children = memento.getChildren(DATA_NODE_KEY);
      if (children != null)
        restoreSynchronizationData(children);
    } finally {
      super.init(secondaryId, memento);
    }
  }

  @Override
  protected MergeContext restoreContext(ISynchronizationScopeManager manager)
      throws CoreException {
    GitResourceVariantTreeSubscriber subscriber = new GitResourceVariantTreeSubscriber(
        gsds);
    subscriber.init(new NullProgressMonitor());
    return new GitSubscriberMergeContext(subscriber, manager, gsds);
  }

  @Override
  protected ISynchronizationScopeManager createScopeManager(
      ResourceMapping[] mappings) {
    GitResourceVariantTreeSubscriber subscriber = new GitResourceVariantTreeSubscriber(
        gsds);
    subscriber.init(new NullProgressMonitor());
    GitSubscriberResourceMappingContext context = new GitSubscriberResourceMappingContext(
        subscriber, gsds);
    return new SynchronizationScopeManager(
        UIText.GitModelSynchronizeParticipant_initialScopeName,
        mappings, context, true);
  }

  private void restoreSynchronizationData(IMemento[] children) {
    for (IMemento child : children) {
      String containerPath = child.getString(CONTAINER_PATH_KEY);
      Repository repo = getRepositoryForPath(containerPath);
      if (repo == null)
        continue;
      String srcRev = child.getString(SRC_REV_KEY);
      String dstRev = child.getString(DST_REV_KEY);
      boolean includeLocal = getBoolean(
          child.getBoolean(INCLUDE_LOCAL_KEY), true);
      Set<IResource> includedResources = getIncludedResources(child);
      try {
        GitSynchronizeData data = new GitSynchronizeData(repo, srcRev,
            dstRev, includeLocal);
        if (includedResources != null)
          data.setIncludedResources(includedResources);
        gsds.add(data);
      } catch (IOException e) {
        Activator.logError(e.getMessage(), e);
        continue;
      }
    }
  }

  private Repository getRepositoryForPath(String containerPath) {
    IPath path = Path.fromPortableString(containerPath);
    IContainer mappedContainer = ResourcesPlugin.getWorkspace().getRoot()
        .getContainerForLocation(path);
    GitProjectData projectData = GitProjectData.get((IProject) mappedContainer);
    if (projectData == null)
      return null;
    RepositoryMapping mapping = projectData.getRepositoryMapping(mappedContainer);
    if (mapping != null)
      return mapping.getRepository();
    return null;
  }

  private boolean getBoolean(Boolean value, boolean defaultValue) {
    return value != null ? value.booleanValue() : defaultValue;
  }

  private String getPathForResource(IResource resource) {
    return resource.getLocation().toPortableString();
  }

  private Set<IResource> getIncludedResources(IMemento memento) {
    IMemento child = memento.getChild(INCLUDED_PATHS_NODE_KEY);
    Set<IResource> result = new HashSet<IResource>();
    if (child != null) {
      IMemento[] pathNode = child.getChildren(INCLUDED_PATH_KEY);
      if (pathNode != null) {
        for (IMemento path : pathNode) {
          String includedPath = path.getString(INCLUDED_PATH_KEY);
          IResource resource = ResourceUtil
              .getResourceForLocation(new Path(includedPath));
          if (resource != null)
            result.add(resource);
        }
        return result;
      }
    }
    return null;
  }

}
TOP

Related Classes of org.eclipse.egit.ui.internal.synchronize.GitModelSynchronizeParticipant

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.