Package org.eclipse.egit.ui.internal.branch

Source Code of org.eclipse.egit.ui.internal.branch.BranchProjectTracker

/******************************************************************************
*  Copyright (c) 2012 GitHub Inc.
*  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:
*    Kevin Sawicki (GitHub Inc.) - initial API and implementation
*****************************************************************************/
package org.eclipse.egit.ui.internal.branch;

import java.io.File;
import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IProjectDescription;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.egit.core.GitProvider;
import org.eclipse.egit.core.internal.util.ProjectUtil;
import org.eclipse.egit.ui.Activator;
import org.eclipse.egit.ui.internal.clone.ProjectRecord;
import org.eclipse.egit.ui.internal.clone.ProjectUtils;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.team.core.RepositoryProvider;
import org.eclipse.ui.IMemento;
import org.eclipse.ui.WorkbenchException;
import org.eclipse.ui.XMLMemento;

/**
* Class to track which projects are imported for each branch.
* <p>
* A unique preference is set for each repository/branch combination that is
* persisted that includes information to be able to restore projects when the
* branch is later checked out.
*
* <p>
* The workflow is as follows:
* <p>
* 1. Call {@link #snapshot()} to get the current projects for the currently
* checked out branch
* <p>
* 2. Call {@link #save(IMemento)} after the new branch has been successfully
* checked out with the memento returned from step 1
* <p>
* 3. Call {@link #restore(IProgressMonitor)} to restore the projects for the
* newly checked out branch
*
*/
class BranchProjectTracker {

  private static final String PREFIX = "BranchProjectTracker_"; //$NON-NLS-1$

  private static final String KEY_PROJECTS = "projects"; //$NON-NLS-1$

  private static final String KEY_PROJECT = "project"; //$NON-NLS-1$

  private static final String KEY_BRANCH = "branch"; //$NON-NLS-1$

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

  private final Repository repository;

  /**
   * Create tracker for repository
   *
   * @param repository
   */
  public BranchProjectTracker(final Repository repository) {
    this.repository = repository;
  }

  private String getBranch() {
    try {
      return repository.getBranch();
    } catch (IOException e) {
      return null;
    }
  }

  /**
   * Get preference key for branch. This will be unique to the repository and
   * branch.
   *
   * @param branch
   * @return key
   */
  public String getPreference(final String branch) {
    if (branch == null)
      throw new IllegalArgumentException("Branch cannot be null"); //$NON-NLS-1$
    if (branch.length() == 0)
      throw new IllegalArgumentException("Branch cannot be empty"); //$NON-NLS-1$

    return PREFIX + '_' + repository.getDirectory().getAbsolutePath() + '_'
        + branch;
  }

  /**
   * Snapshot the projects currently associated with the repository
   * <p>
   * The memento returned can be later passed to {@link #save(IMemento)} to
   * persist it
   *
   * @see #save(IMemento)
   * @return memento, will be null on failures
   */
  public IMemento snapshot() {
    String branch = getBranch();
    if (branch == null)
      return null;

    IProject[] projects;
    try {
      projects = ProjectUtil.getValidOpenProjects(repository);
    } catch (CoreException e) {
      return null;
    }
    XMLMemento memento = XMLMemento.createWriteRoot(KEY_PROJECTS);
    memento.putString(KEY_BRANCH, branch);
    final String workDir = repository.getWorkTree().getAbsolutePath();
    for (IProject project : projects) {
      IPath path = project.getLocation();
      if (path == null)
        continue;
      // Only remember mapped projects
      if (!(RepositoryProvider.getProvider(project) instanceof GitProvider))
        continue;
      String fullPath = path.toOSString();
      if (fullPath.startsWith(workDir)) {
        String relative = fullPath.substring(workDir.length());
        if (relative.length() == 0)
          relative = REPO_ROOT;
        IMemento child = memento.createChild(KEY_PROJECT);
        child.putTextData(relative);
      }
    }
    return memento;
  }

  /**
   * Associate projects with branch. The specified memento must the one
   * previously returned from a call to {@link #snapshot()}.
   *
   * @see #snapshot()
   * @param memento
   * @return this tracker
   */
  public BranchProjectTracker save(final IMemento memento) {
    if (!(memento instanceof XMLMemento))
      throw new IllegalArgumentException("Invalid memento"); //$NON-NLS-1$

    String branch = memento.getString(KEY_BRANCH);
    IPreferenceStore store = Activator.getDefault().getPreferenceStore();
    String pref = getPreference(branch);
    StringWriter writer = new StringWriter();
    try {
      ((XMLMemento) memento).save(writer);
      store.setValue(pref, writer.toString());
    } catch (IOException e) {
      Activator.logError("Error writing branch-project associations", e); //$NON-NLS-1$
    }
    return this;
  }

  /**
   * Load the project paths associated with the currently checked out branch.
   * These paths will be relative to the repository root.
   *
   * @return non-null but possibly empty array of projects
   */
  public String[] getProjectPaths() {
    String branch = getBranch();
    if (branch == null)
      return new String[0];
    return getProjectPaths(branch);
  }

  /**
   * Load the project paths associated with the given branch. These paths will
   * be relative to the repository root.
   *
   * @param branch
   * @return non-null but possibly empty array of projects
   */
  public String[] getProjectPaths(final String branch) {
    String pref = getPreference(branch);
    String value = Activator.getDefault().getPreferenceStore()
        .getString(pref);
    if (value.length() == 0)
      return new String[0];
    XMLMemento memento;
    try {
      memento = XMLMemento.createReadRoot(new StringReader(value));
    } catch (WorkbenchException e) {
      Activator.logError("Error reading branch-project associations", e); //$NON-NLS-1$
      return new String[0];
    }
    IMemento[] children = memento.getChildren(KEY_PROJECT);
    if (children.length == 0)
      return new String[0];
    List<String> projects = new ArrayList<String>(children.length);
    for (int i = 0; i < children.length; i++) {
      String path = children[i].getTextData();
      if (path != null && path.length() > 0)
        projects.add(path);
    }
    return projects.toArray(new String[projects.size()]);
  }

  /**
   * Restore projects associated with the currently checked out branch to the
   * workspace
   *
   * @param monitor
   */
  public void restore(final IProgressMonitor monitor) {
    String branch = getBranch();
    if (branch != null)
      restore(branch, monitor);
  }

  /**
   * Restore projects associated with the given branch to the workspace
   *
   * @param branch
   * @param monitor
   */
  public void restore(final String branch, final IProgressMonitor monitor) {
    String[] paths = getProjectPaths(branch);
    if (paths.length == 0)
      return;

    Set<ProjectRecord> records = new LinkedHashSet<ProjectRecord>();
    File parent = repository.getWorkTree();
    for (String path : paths) {
      File root;
      if (!REPO_ROOT.equals(path))
        root = new File(parent, path);
      else
        root = parent;

      if (!root.isDirectory())
        continue;
      File projectDescription = new File(root,
          IProjectDescription.DESCRIPTION_FILE_NAME);
      if (!projectDescription.isFile())
        continue;
      records.add(new ProjectRecord(projectDescription));
    }
    if (records.isEmpty())
      return;
    IProgressMonitor importMonitor;
    if (monitor != null)
      importMonitor = monitor;
    else
      importMonitor = new NullProgressMonitor();
    try {
      ProjectUtils.createProjects(records, true, null, importMonitor);
    } catch (InvocationTargetException e) {
      Activator
          .logError("Error restoring branch-project associations", e); //$NON-NLS-1$
    } catch (InterruptedException ignored) {
      // Ignored
    }
  }
}
TOP

Related Classes of org.eclipse.egit.ui.internal.branch.BranchProjectTracker

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.