Package org.eclipse.orion.server.git.jobs

Source Code of org.eclipse.orion.server.git.jobs.FetchJob

/*******************************************************************************
* Copyright (c) 2011, 2013 IBM Corporation 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:
*     IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.orion.server.git.jobs;

import java.io.IOException;
import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.concurrent.TimeUnit;

import javax.servlet.http.Cookie;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.jgit.api.FetchCommand;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.TransportConfigCallback;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.api.errors.InvalidRemoteException;
import org.eclipse.jgit.api.errors.JGitInternalException;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ProgressMonitor;
import org.eclipse.jgit.lib.RefUpdate.Result;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.storage.file.FileRepositoryBuilder;
import org.eclipse.jgit.transport.CredentialsProvider;
import org.eclipse.jgit.transport.FetchResult;
import org.eclipse.jgit.transport.RefSpec;
import org.eclipse.jgit.transport.RemoteConfig;
import org.eclipse.jgit.transport.TrackingRefUpdate;
import org.eclipse.jgit.transport.Transport;
import org.eclipse.jgit.transport.TransportHttp;
import org.eclipse.orion.server.git.GitActivator;
import org.eclipse.orion.server.git.GitConstants;
import org.eclipse.orion.server.git.GitCredentialsProvider;
import org.eclipse.orion.server.git.servlets.GitUtils;
import org.eclipse.osgi.util.NLS;

/**
* A job to perform a fetch operation in the background
*/
public class FetchJob extends GitJob {

  private IPath path;
  private String remote;
  private boolean force;
  private String branch; // can be null if fetching the whole branch

  public FetchJob(String userRunningTask, CredentialsProvider credentials, Path path, boolean force) {
    super(userRunningTask, true, (GitCredentialsProvider) credentials);
    // path: {remote}[/{branch}]/file/{...}
    this.path = path;
    this.remote = path.segment(0);
    this.force = force;
    this.branch = path.segment(1).equals("file") ? null : GitUtils.decode(path.segment(1)); //$NON-NLS-1$
    builtMessages();
    setTaskExpirationTime(TimeUnit.DAYS.toMillis(7));
  }

  public FetchJob(String userRunningTask, CredentialsProvider credentials, Path path, boolean force, Object cookie) {
    this(userRunningTask, credentials, path, force);
    this.cookie = (Cookie) cookie;
  }

  private void builtMessages() {
    // path is either : {remote}/file/{workspaceId}/{projectName}
    // or {remote}/{branch}/file/{workspaceId}/{projectName}
    String cloneName = path.lastSegment();
    if (branch == null) {
      Object[] bindings = new String[] { remote, cloneName };
      setName(NLS.bind("Fetching {0} for {1}", bindings));
      setFinalMessage(NLS.bind("Fetching {0} for {1} done.", bindings));
    } else {
      Object[] bindings = new String[] { remote, branch, cloneName };
      setName(NLS.bind("Fetching {0}/{1} for {2}", bindings));
      setFinalMessage(NLS.bind("Fetching {0}/{1} for {2} done.", bindings));
    }
  }

  private IStatus doFetch(IProgressMonitor monitor) throws IOException, CoreException, URISyntaxException, GitAPIException {
    ProgressMonitor gitMonitor = new EclipseGitProgressTransformer(monitor);
    Repository db = null;
    try {
      db = getRepository();
      Git git = new Git(db);
      FetchCommand fc = git.fetch();
      fc.setProgressMonitor(gitMonitor);

      RemoteConfig remoteConfig = new RemoteConfig(git.getRepository().getConfig(), remote);
      credentials.setUri(remoteConfig.getURIs().get(0));
      if (this.cookie != null) {
        fc.setTransportConfigCallback(new TransportConfigCallback() {
          @Override
          public void configure(Transport t) {
            if (t instanceof TransportHttp && cookie != null) {
              HashMap<String, String> map = new HashMap<String, String>();
              map.put(GitConstants.KEY_COOKIE, cookie.getName() + "=" + cookie.getValue());
              ((TransportHttp) t).setAdditionalHeaders(map);
            }
          }
        });
      }
      fc.setCredentialsProvider(credentials);
      fc.setRemote(remote);
      if (branch != null) {
        // refs/heads/{branch}:refs/remotes/{remote}/{branch}
        String remoteBranch = branch;
        if (branch.startsWith("for/")) {
          remoteBranch = branch.substring(4);
        }

        RefSpec spec = new RefSpec(Constants.R_HEADS + remoteBranch + ":" + Constants.R_REMOTES + remote + "/" + branch); //$NON-NLS-1$ //$NON-NLS-2$
        spec = spec.setForceUpdate(force);
        fc.setRefSpecs(spec);
      }
      FetchResult fetchResult = fc.call();
      if (monitor.isCanceled()) {
        return new Status(IStatus.CANCEL, GitActivator.PI_GIT, "Cancelled");
      }
      GitJobUtils.packRefs(db, gitMonitor);
      if (monitor.isCanceled()) {
        return new Status(IStatus.CANCEL, GitActivator.PI_GIT, "Cancelled");
      }
      return handleFetchResult(fetchResult);
    } finally {
      if (db != null) {
        db.close();
      }
    }
  }

  static IStatus handleFetchResult(FetchResult fetchResult) {
    // handle result
    for (TrackingRefUpdate updateRes : fetchResult.getTrackingRefUpdates()) {
      Result res = updateRes.getResult();
      switch (res) {
      case NOT_ATTEMPTED:
      case NO_CHANGE:
      case NEW:
      case FORCED:
      case FAST_FORWARD:
      case RENAMED:
        // do nothing, as these statuses are OK
        break;
      case REJECTED:
        return new Status(IStatus.WARNING, GitActivator.PI_GIT, "Fetch rejected, not a fast-forward.");
      case REJECTED_CURRENT_BRANCH:
        return new Status(IStatus.WARNING, GitActivator.PI_GIT, "Rejected because trying to delete the current branch.");
      default:
        return new Status(IStatus.ERROR, GitActivator.PI_GIT, res.name());
      }
    }
    return Status.OK_STATUS;
  }

  private Repository getRepository() throws IOException, CoreException {
    IPath p = null;
    if (path.segment(1).equals("file")) //$NON-NLS-1$
      p = path.removeFirstSegments(1);
    else
      p = path.removeFirstSegments(2);
    return FileRepositoryBuilder.create(GitUtils.getGitDir(p));
  }

  @Override
  protected IStatus performJob(IProgressMonitor monitor) {
    IStatus result = Status.OK_STATUS;
    try {
      result = doFetch(monitor);
    } catch (IOException e) {
      result = new Status(IStatus.ERROR, GitActivator.PI_GIT, "Error fetching git remote", e);
    } catch (CoreException e) {
      result = e.getStatus();
    } catch (InvalidRemoteException e) {
      result = new Status(IStatus.ERROR, GitActivator.PI_GIT, "Error fetching git remote", e);
    } catch (GitAPIException e) {
      result = getGitAPIExceptionStatus(e, "Error fetching git remote");
    } catch (JGitInternalException e) {
      result = getJGitInternalExceptionStatus(e, "Error fetching git remote");
    } catch (Exception e) {
      result = new Status(IStatus.ERROR, GitActivator.PI_GIT, "Error fetching git remote", e);
    }
    return result;
  }
}
TOP

Related Classes of org.eclipse.orion.server.git.jobs.FetchJob

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.