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

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

/*******************************************************************************
* 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.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.concurrent.TimeUnit;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;

import org.eclipse.core.runtime.CoreException;
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.Git;
import org.eclipse.jgit.api.PushCommand;
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.Repository;
import org.eclipse.jgit.storage.file.FileRepositoryBuilder;
import org.eclipse.jgit.transport.CredentialsProvider;
import org.eclipse.jgit.transport.PushResult;
import org.eclipse.jgit.transport.RefSpec;
import org.eclipse.jgit.transport.RemoteConfig;
import org.eclipse.jgit.transport.RemoteRefUpdate;
import org.eclipse.jgit.transport.TrackingRefUpdate;
import org.eclipse.jgit.transport.Transport;
import org.eclipse.jgit.transport.TransportHttp;
import org.eclipse.orion.server.core.ServerStatus;
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;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

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

  private Path path;
  private String remote;
  private String branch;
  private String srcRef;
  private boolean tags;
  private boolean force;

  public PushJob(String userRunningTask, CredentialsProvider credentials, Path path, String srcRef, boolean tags, boolean force) {
    super(userRunningTask, true, (GitCredentialsProvider) credentials);
    this.path = path;
    this.remote = path.segment(0);
    this.branch = GitUtils.decode(path.segment(1));
    this.srcRef = srcRef;
    this.tags = tags;
    this.force = force;
    setFinalMessage(NLS.bind("Pushing {0} done", path.segment(0)));
    setTaskExpirationTime(TimeUnit.DAYS.toMillis(7));
  }

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

  private IStatus doPush(IProgressMonitor monitor) throws IOException, CoreException, URISyntaxException, GitAPIException {
    ProgressMonitor gitMonitor = new EclipseGitProgressTransformer(monitor);
    // /git/remote/{remote}/{branch}/file/{path}
    File gitDir = GitUtils.getGitDir(path.removeFirstSegments(2));
    Repository db = null;
    JSONObject result = new JSONObject();
    try {
      db = FileRepositoryBuilder.create(gitDir);
      Git git = new Git(db);

      PushCommand pushCommand = git.push();
      pushCommand.setProgressMonitor(gitMonitor);
      pushCommand.setTransportConfigCallback(new TransportConfigCallback() {
        @Override
        public void configure(Transport t) {
          credentials.setUri(t.getURI());
          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);
          }
        }
      });
      RemoteConfig remoteConfig = new RemoteConfig(git.getRepository().getConfig(), remote);
      credentials.setUri(remoteConfig.getURIs().get(0));
      pushCommand.setCredentialsProvider(credentials);

      boolean pushToGerrit = branch.startsWith("for/");
      RefSpec spec = new RefSpec(srcRef + ':' + (pushToGerrit ? "refs/" : Constants.R_HEADS) + branch);
      pushCommand.setRemote(remote).setRefSpecs(spec);
      if (tags)
        pushCommand.setPushTags();
      pushCommand.setForce(force);
      Iterable<PushResult> resultIterable = pushCommand.call();
      if (monitor.isCanceled()) {
        return new Status(IStatus.CANCEL, GitActivator.PI_GIT, "Cancelled");
      }
      PushResult pushResult = resultIterable.iterator().next();
      boolean error = false;
      JSONArray updates = new JSONArray();
      result.put(GitConstants.KEY_COMMIT_MESSAGE, pushResult.getMessages());
      result.put(GitConstants.KEY_UPDATES, updates);
      for (final RemoteRefUpdate rru : pushResult.getRemoteUpdates()) {
        if (monitor.isCanceled()) {
          return new Status(IStatus.CANCEL, GitActivator.PI_GIT, "Cancelled");
        }
        final String rm = rru.getRemoteName();
        // check status only for branch given in the URL or tags
        if (branch.equals(Repository.shortenRefName(rm)) || rm.startsWith(Constants.R_TAGS)) {
          JSONObject object = new JSONObject();
          RemoteRefUpdate.Status status = rru.getStatus();
          if (status != RemoteRefUpdate.Status.UP_TO_DATE || !rm.startsWith(Constants.R_TAGS)) {
            object.put(GitConstants.KEY_COMMIT_MESSAGE, rru.getMessage());
            object.put(GitConstants.KEY_RESULT, status.name());
            TrackingRefUpdate refUpdate = rru.getTrackingRefUpdate();
            if (refUpdate != null) {
              object.put(GitConstants.KEY_REMOTENAME, Repository.shortenRefName(refUpdate.getLocalName()));
              object.put(GitConstants.KEY_LOCALNAME, Repository.shortenRefName(refUpdate.getRemoteName()));
            } else {
              object.put(GitConstants.KEY_REMOTENAME, Repository.shortenRefName(rru.getSrcRef()));
              object.put(GitConstants.KEY_LOCALNAME, Repository.shortenRefName(rru.getRemoteName()));
            }
            updates.put(object);
          }
          if (status != RemoteRefUpdate.Status.OK && status != RemoteRefUpdate.Status.UP_TO_DATE)
            error = true;
        }
        // TODO: return results for all updated branches once push is available for remote, see bug 352202
      }
      // needs to handle multiple
      result.put("Severity", error ? "Error" : "Normal");
    } catch (JSONException e) {
    } finally {
      if (db != null) {
        db.close();
      }
    }
    return new ServerStatus(Status.OK_STATUS, HttpServletResponse.SC_OK, result);
  }

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

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

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.