Package org.eclipse.egit.core.synchronize.dto

Source Code of org.eclipse.egit.core.synchronize.dto.GitSynchronizeData$RemoteAndMerge

/*******************************************************************************
* 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
*******************************************************************************/
package org.eclipse.egit.core.synchronize.dto;

import static org.eclipse.core.runtime.Assert.isNotNull;
import static org.eclipse.egit.core.RevUtils.getCommonAncestor;
import static org.eclipse.jgit.lib.Constants.R_HEADS;

import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.regex.Pattern;

import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.egit.core.project.RepositoryMapping;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.ObjectWalk;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.transport.RefSpec;
import org.eclipse.jgit.transport.RemoteConfig;
import org.eclipse.jgit.treewalk.filter.PathFilterGroup;
import org.eclipse.jgit.treewalk.filter.TreeFilter;

/**
* Simple data transfer object containing all necessary information for
* launching synchronization
*/
public class GitSynchronizeData {

  private static final IWorkspaceRoot ROOT = ResourcesPlugin.getWorkspace()
          .getRoot();

  /**
   * Matches all strings that start from R_HEADS
   */
  public static final Pattern BRANCH_NAME_PATTERN = Pattern.compile("^" + R_HEADS + ".*?"); //$NON-NLS-1$ //$NON-NLS-2$

  private final boolean includeLocal;

  private final Repository repo;

  private final String dstRemote;

  private final String dstMerge;

  private RevCommit srcRevCommit;

  private RevCommit dstRevCommit;

  private RevCommit ancestorRevCommit;

  private final Set<IProject> projects;

  private final String repoParentPath;

  private final String srcRev;

  private final String dstRev;

  private TreeFilter pathFilter;

  private Set<IResource> includedResources;

  private static class RemoteAndMerge {
    final String remote;
    final String merge;

    public RemoteAndMerge(String remote, String merge) {
      this.remote = remote;
      this.merge = merge;
    }
  }

  /**
   * Constructs {@link GitSynchronizeData} object for all resources.
   * Equivalent to
   * <code>new GitSynchronizeData(repository, srcRev, dstRev, includeLocal, null)</code>
   * .
   *
   * @param repository
   * @param srcRev
   * @param dstRev
   * @param includeLocal
   *            <code>true</code> if local changes should be included in
   *            comparison
   * @throws IOException
   */
  public GitSynchronizeData(Repository repository, String srcRev,
      String dstRev, boolean includeLocal) throws IOException {
    this(repository, srcRev, dstRev, includeLocal, null);
  }

  /**
   * Constructs a {@link GitSynchronizeData} object while restricting it to a
   * set of resources.
   *
   * @param repository
   * @param srcRev
   * @param dstRev
   * @param includeLocal
   * @param includedResources
   *            either the set of resources to include in synchronization or
   *            {@code null} to synchronize all resources.
   * @throws IOException
   */
  public GitSynchronizeData(Repository repository, String srcRev,
      String dstRev, boolean includeLocal,
      Set<IResource> includedResources) throws IOException {
    isNotNull(repository);
    isNotNull(srcRev);
    isNotNull(dstRev);
    this.repo = repository;
    this.srcRev = srcRev;
    this.dstRev = dstRev;
    this.includeLocal = includeLocal;

    RemoteAndMerge dstRemoteAndMerge = extractRemoteAndMergeForDst(dstRev);

    dstRemote = dstRemoteAndMerge.remote;
    dstMerge = dstRemoteAndMerge.merge;

    repoParentPath = repo.getDirectory().getParentFile().getAbsolutePath();

    projects = new HashSet<IProject>();
    final Iterable<? extends IResource> includedResourceIterable;
    if (includedResources == null)
      // include all project in synchronization
      includedResourceIterable = Arrays.asList(ROOT.getProjects());
    else
      includedResourceIterable = includedResources;
    for (IResource res : includedResourceIterable) {
      IProject project = res.getProject();
      RepositoryMapping mapping = RepositoryMapping.getMapping(project);
      if (mapping != null && mapping.getRepository() == repo)
        projects.add(project);
    }

    // do not set field if includedResources is null, some methods expect
    // #getIncludedResources() to return <null> to know it should
    // synchronize all resources.
    if (includedResources != null)
      setIncludedResources(includedResources);

    updateRevs();
  }

  /**
   * Recalculates source, destination and ancestor Rev commits
   *
   * @throws IOException
   */
  public void updateRevs() throws IOException {
    ObjectWalk ow = new ObjectWalk(repo);
    try {
      srcRevCommit = getCommit(srcRev, ow);
      dstRevCommit = getCommit(dstRev, ow);
    } finally {
      ow.release();
    }

    if (this.dstRevCommit != null && this.srcRevCommit != null)
      this.ancestorRevCommit = getCommonAncestor(repo, this.srcRevCommit,
          this.dstRevCommit);
    else
      this.ancestorRevCommit = null;
  }

  /**
   * @return instance of repository that should be synchronized
   */
  public Repository getRepository() {
    return repo;
  }

  /**
   * @return {@code null}
   * @deprecated
   */
  @Deprecated
  public String getSrcRemoteName() {
    return null;
  }

  /**
   * @return ref specification of destination merge branch
   */
  public String getDstMerge() {
    return dstMerge;
  }

  /**
   * @return {@code null}
   * @deprecated
   */
  @Deprecated
  public String getSrcMerge() {
    return null;
  }

  /**
   * @return name of destination remote or {@code null} when destination
   *         branch is not a remote branch
   */
  public String getDstRemoteName() {
    return dstRemote;
  }

  /**
   * @return synchronize source rev name
   */
  public RevCommit getSrcRevCommit() {
    return srcRevCommit;
  }

  /**
   * @return synchronize destination rev name
   */
  public RevCommit getDstRevCommit() {
    return dstRevCommit;
  }

  /**
   * @return list of project's that are connected with this repository
   */
  public Set<IProject> getProjects() {
    return Collections.unmodifiableSet(projects);
  }

  /**
   * @param file
   * @return <true> if given {@link File} is contained by this repository
   */
  public boolean contains(File file) {
    return file.getAbsoluteFile().toString().startsWith(repoParentPath);
  }

  /**
   * @return <code>true</code> if local changes should be included in
   *         comparison
   */
  public boolean shouldIncludeLocal() {
    return includeLocal;
  }

  /**
   * @return common ancestor commit
   */
  public RevCommit getCommonAncestorRev() {
    return ancestorRevCommit;
  }

  /**
   * @param includedResources
   *            list of resources to be synchronized
   */
  public void setIncludedResources(Set<IResource> includedResources) {
    this.includedResources = includedResources;
    Set<String> paths = new HashSet<String>();
    RepositoryMapping rm = RepositoryMapping.findRepositoryMapping(repo);
    for (IResource resource : includedResources) {
      String repoRelativePath = rm.getRepoRelativePath(resource);
      if (repoRelativePath != null && repoRelativePath.length() > 0)
        paths.add(repoRelativePath);
    }

    if (!paths.isEmpty())
      pathFilter = PathFilterGroup.createFromStrings(paths);
  }

  /**
   * @return set of included resources or {@code null} when all resources
   *         should be included
   */
  public Set<IResource> getIncludedResources() {
    return includedResources;
  }

  /**
   * Disposes all nested resources
   */
  public void dispose() {
    if (projects != null)
      projects.clear();
    if (includedResources != null)
      includedResources.clear();
  }

  /**
   * @return instance of {@link TreeFilter} when synchronization was launched
   *         from nested node (like folder) or {@code null} otherwise
   */
  public TreeFilter getPathFilter() {
    return pathFilter;
  }

  /**
   * @return synchronization source rev
   */
  public String getSrcRev() {
    return srcRev;
  }

  /**
   * @return synchronization destination rev
   */
  public String getDstRev() {
    return dstRev;
  }

  private RemoteAndMerge extractRemoteAndMergeForDst(String rev) {
    // destination remote name is used for fetch and push, so check if this
    // is a remote-tracking branch
    try {
      List<RemoteConfig> remoteConfigs = RemoteConfig
          .getAllRemoteConfigs(repo.getConfig());
      for (RemoteConfig remoteConfig : remoteConfigs) {
        List<RefSpec> fetchRefSpecs = remoteConfig.getFetchRefSpecs();
        for (RefSpec fetchRefSpec : fetchRefSpecs) {
          if (fetchRefSpec.matchDestination(rev)) {
            RefSpec expanded = fetchRefSpec
                .expandFromDestination(rev);
            return new RemoteAndMerge(remoteConfig.getName(),
                expanded.getSource());
          }
        }
      }
    } catch (URISyntaxException e) {
      // Fall back to returning empty result below
    }
    return new RemoteAndMerge(null, null);
  }

  private RevCommit getCommit(String rev, ObjectWalk ow) throws IOException {
    if (rev.length() > 0) {
      ObjectId id = repo.resolve(rev);
      return id != null ? ow.parseCommit(id) : null;
    } else
      return null;
  }

}
TOP

Related Classes of org.eclipse.egit.core.synchronize.dto.GitSynchronizeData$RemoteAndMerge

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.