Package ch.cmbntr.modulizer.filetree

Source Code of ch.cmbntr.modulizer.filetree.Restore

package ch.cmbntr.modulizer.filetree;

import static java.util.Collections.emptySet;
import static java.util.Collections.singleton;

import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URL;
import java.util.Collection;
import java.util.Set;
import java.util.concurrent.Future;
import java.util.logging.Logger;

import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.ResetCommand.ResetType;
import org.eclipse.jgit.api.Status;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.errors.NoWorkTreeException;
import org.eclipse.jgit.lib.NullProgressMonitor;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.RepositoryCache;
import org.eclipse.jgit.transport.FetchConnection;
import org.eclipse.jgit.transport.Transport;
import org.eclipse.jgit.transport.TransportBundleStream;
import org.eclipse.jgit.transport.URIish;

import ch.cmbntr.modulizer.bootstrap.util.Resources;

public class Restore {

  private static final Logger LOG = Logger.getAnonymousLogger();

  private Restore() {
    super();
  }

  private static void log(final String msg, final Object... args) {
    LOG.fine(String.format(msg, args));
  }

  public static void restore(final File destination, final String branch, final String requiredRef,
      final Future<URI> bundle, final String bundleRef, final CleanupMode cleanup) throws IOException, GitAPIException {
    try {
      final Git git = exists(destination);
      try {
        if (git == null || !headAt(git, requiredRef)) {
          final URI b = Resources.get(bundle, "failed to get bundle");
          explodeBundle(destination, branch, bundleRef, b, cleanup);
        } else {
          bundle.cancel(true);
          ensureClean(git, cleanup);
        }
      } finally {
        if (git != null) {
          git.getRepository().close();
        }
      }
    } finally {
      RepositoryCache.clear();
    }
    log("prepared");
  }

  private static void ensureClean(final Git git, final CleanupMode cleanup) throws NoWorkTreeException, GitAPIException {

    if (CleanupMode.NONE.equals(cleanup)) {
      log("skip cleanup");
      return;
    }
    //TODO handle all cleanup modes properly
    final Status st = git.status().call();
    if (st.isClean()) {
      log("ready");
    } else {
      log("not clean");
      git.reset().setMode(ResetType.HARD).call();
      final Status st2 = git.status().call();
      if (st2.isClean() || !st.getUntracked().isEmpty()) {
        log("ready");
      }
    }
  }

  private static Git exists(final File worktree) {
    try {
      return Git.open(worktree);

    } catch (final IOException e) {
      return null;
    }
  }

  private static boolean headAt(final Git git, final String required) {
    try {
      final Repository repo = git.getRepository();
      final String branch = repo.getFullBranch();

      final Ref ref = repo.getRef(branch);
      return ref != null && required.equals(ref.getObjectId().getName());

    } catch (final IOException e) {
      return false;
    }
  }

  private static String explodeBundle(final File worktree, final String branchName, final String refName,
      final URI bundle, final CleanupMode cleanup) throws IOException, GitAPIException {

    if (!worktree.exists() && !worktree.mkdirs()) {
      throw new IOException("could not create " + worktree);
    }
    if (!worktree.canWrite()) {
      throw new IOException("not writable: " + worktree);
    }

    final Git git = Git.init().setDirectory(worktree).call();
    try {

      // fetch
      final String ref = fetchBundle(git, bundle, refName);

      // branch
      git.branchCreate().setName(branchName).setForce(true).setStartPoint(ref).call();

      // checkout
      final String head = git.checkout().setName(branchName).call().getObjectId().getName();

      // clean workspace
      ensureClean(git, cleanup);

      return head;

    } finally {
      // close repository
      git.getRepository().close();
    }

  }

  private static String fetchBundle(final Git git, final URI bundle, final String refName) throws IOException {
    final URL loc = bundle.toURL();
    final URIish uri = new URIish(loc);

    final Transport t = new TransportBundleStream(git.getRepository(), uri, loc.openStream());
    try {
      final FetchConnection src = t.openFetch();
      final Ref target = src.getRef(refName);

      final Collection<Ref> want = singleton(target);
      final Set<ObjectId> have = emptySet();
      src.fetch(NullProgressMonitor.INSTANCE, want, have);

      return target.getObjectId().getName();

    } finally {
      t.close();
    }
  }

  public enum CleanupMode {
    NONE, RESET_ONLY, FULL
  }

}
TOP

Related Classes of ch.cmbntr.modulizer.filetree.Restore

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.