Package org.moxie.utils

Source Code of org.moxie.utils.JGitUtils

/*
* Copyright 2012 James Moger
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.moxie.utils;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

import org.eclipse.jgit.api.AddCommand;
import org.eclipse.jgit.api.CommitCommand;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.TagCommand;
import org.eclipse.jgit.api.errors.ConcurrentRefUpdateException;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.api.errors.JGitInternalException;
import org.eclipse.jgit.dircache.DirCache;
import org.eclipse.jgit.dircache.DirCacheBuilder;
import org.eclipse.jgit.dircache.DirCacheEntry;
import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.internal.storage.file.FileRepository;
import org.eclipse.jgit.lib.CommitBuilder;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.FileMode;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectInserter;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.RefUpdate;
import org.eclipse.jgit.lib.RefUpdate.Result;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.RepositoryCache.FileKey;
import org.eclipse.jgit.lib.TreeFormatter;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.treewalk.CanonicalTreeParser;
import org.eclipse.jgit.treewalk.TreeWalk;
import org.eclipse.jgit.util.FS;
import org.moxie.MoxieException;

public class JGitUtils {

  public static File findRepositoryDir(File dir) {
    File resolved = FileKey.resolve(dir, FS.detect());
    if (resolved != null) {
      return resolved;
    } else {
      resolved = FileKey.resolve(dir.getParentFile(), FS.detect());
      if (resolved != null) {
        return resolved;
      }
    }
    return null;
  }

  public static String getCommitId(File folder) {
    // try specified folder or subfolder
    File gitDir = FileKey.resolve(folder, FS.DETECTED);

    if (gitDir == null || !gitDir.exists()) {
      // try parent folder
      gitDir = FileKey.resolve(folder.getParentFile(), FS.DETECTED);
    }
    if (gitDir == null || !gitDir.exists()) {
      throw new MoxieException("Can not find .git folder for " + folder);
    }

    String hashid = "";
    try {
      Repository repository = new FileRepository(gitDir);
      ObjectId objectId = repository
          .resolve(org.eclipse.jgit.lib.Constants.HEAD);
      hashid = objectId.getName().toString();
      repository.close();
    } catch (IOException io) {
      io.printStackTrace();
      throw new MoxieException("IOException accessing "
          + gitDir.getAbsolutePath(), io);
    }
    return hashid;
  }

  /**
   * Create an orphaned branch in a repository.
   *
   * @param repository
   * @param branchName
   * @param author
   *            if unspecified, Moxie will be the author of this new branch
   * @return true if successful
   */
  public static boolean createOrphanBranch(Repository repository,
      String branchName, PersonIdent author) {
    boolean success = false;
    String message = "Created branch " + branchName;
    if (author == null) {
      author = new PersonIdent("Moxie", "moxie@localhost");
    }
    try {
      ObjectInserter odi = repository.newObjectInserter();
      try {
        // Create a blob object to insert into a tree
        ObjectId blobId = odi.insert(Constants.OBJ_BLOB,
            message.getBytes(Constants.CHARACTER_ENCODING));

        // Create a tree object to reference from a commit
        TreeFormatter tree = new TreeFormatter();
        tree.append("NEWBRANCH", FileMode.REGULAR_FILE, blobId);
        ObjectId treeId = odi.insert(tree);

        // Create a commit object
        CommitBuilder commit = new CommitBuilder();
        commit.setAuthor(author);
        commit.setCommitter(author);
        commit.setEncoding(Constants.CHARACTER_ENCODING);
        commit.setMessage(message);
        commit.setTreeId(treeId);

        // Insert the commit into the repository
        ObjectId commitId = odi.insert(commit);
        odi.flush();

        RevWalk revWalk = new RevWalk(repository);
        try {
          RevCommit revCommit = revWalk.parseCommit(commitId);
          if (!branchName.startsWith("refs/")) {
            branchName = "refs/heads/" + branchName;
          }
          RefUpdate ru = repository.updateRef(branchName);
          ru.setNewObjectId(commitId);
          ru.setRefLogMessage(
              "commit: " + revCommit.getShortMessage(), false);
          Result rc = ru.forceUpdate();
          switch (rc) {
          case NEW:
          case FORCED:
          case FAST_FORWARD:
            success = true;
            break;
          default:
            success = false;
          }
        } finally {
          revWalk.release();
        }
      } finally {
        odi.release();
      }
    } catch (Throwable t) {
      t.printStackTrace();
    }
    return success;
  }

  public static void updateGhPages(File repositoryFolder, File sourceFolder,
      boolean obliterate) {
    String ghpages = "refs/heads/gh-pages";
    try {
      File gitDir = FileKey.resolve(repositoryFolder, FS.DETECTED);
      Repository repository = new FileRepository(gitDir);

      ObjectId objectId = repository.resolve(ghpages);
      if (objectId == null) {
        JGitUtils.createOrphanBranch(repository, "gh-pages", null);
      }

      System.out.println("Updating gh-pages branch...");
      ObjectId headId = repository.resolve(ghpages + "^{commit}");
      ObjectInserter odi = repository.newObjectInserter();
      try {
        // Create the in-memory index of the new/updated issue.
        DirCache index = createIndex(repository, headId, sourceFolder,
            obliterate);
        ObjectId indexTreeId = index.writeTree(odi);

        // Create a commit object
        PersonIdent author = new PersonIdent("Moxie",
            "moxie@localhost");
        CommitBuilder commit = new CommitBuilder();
        commit.setAuthor(author);
        commit.setCommitter(author);
        commit.setEncoding(Constants.CHARACTER_ENCODING);
        commit.setMessage("updated pages");
        commit.setParentId(headId);
        commit.setTreeId(indexTreeId);

        // Insert the commit into the repository
        ObjectId commitId = odi.insert(commit);
        odi.flush();

        RevWalk revWalk = new RevWalk(repository);
        try {
          RevCommit revCommit = revWalk.parseCommit(commitId);
          RefUpdate ru = repository.updateRef(ghpages);
          ru.setNewObjectId(commitId);
          ru.setExpectedOldObjectId(headId);
          ru.setRefLogMessage(
              "commit: " + revCommit.getShortMessage(), false);
          Result rc = ru.forceUpdate();
          switch (rc) {
          case NEW:
          case FORCED:
          case FAST_FORWARD:
            break;
          case REJECTED:
          case LOCK_FAILURE:
            throw new ConcurrentRefUpdateException(
                JGitText.get().couldNotLockHEAD, ru.getRef(),
                rc);
          default:
            throw new JGitInternalException(MessageFormat.format(
                JGitText.get().updatingRefFailed, ghpages,
                commitId.toString(), rc));
          }
        } finally {
          revWalk.release();
        }
      } finally {
        odi.release();
      }
      System.out.println("gh-pages updated.");
    } catch (Throwable t) {
      t.printStackTrace();
    }
  }

  /**
   * Creates an in-memory index of the issue change.
   *
   * @param repo
   * @param headId
   * @param sourceFolder
   * @param obliterate
   *            if true the source folder tree is used as the new tree for
   *            gh-pages and non-existent files are considered deleted
   * @return an in-memory index
   * @throws IOException
   */
  private static DirCache createIndex(Repository repo, ObjectId headId,
      File sourceFolder, boolean obliterate) throws IOException {

    DirCache inCoreIndex = DirCache.newInCore();
    DirCacheBuilder dcBuilder = inCoreIndex.builder();
    ObjectInserter inserter = repo.newObjectInserter();

    try {
      // Add all files to the temporary index
      Set<String> ignorePaths = new TreeSet<String>();
      List<File> files = listFiles(sourceFolder);
      for (File file : files) {
        // create an index entry for the file
        final DirCacheEntry dcEntry = new DirCacheEntry(
            StringUtils.getRelativePath(sourceFolder.getPath(),
                file.getPath()));
        dcEntry.setLength(file.length());
        dcEntry.setLastModified(file.lastModified());
        dcEntry.setFileMode(FileMode.REGULAR_FILE);

        // add this entry to the ignore paths set
        ignorePaths.add(dcEntry.getPathString());

        // insert object
        InputStream inputStream = new FileInputStream(file);
        try {
          dcEntry.setObjectId(inserter.insert(Constants.OBJ_BLOB,
              file.length(), inputStream));
        } finally {
          inputStream.close();
        }

        // add to temporary in-core index
        dcBuilder.add(dcEntry);
      }

      if (!obliterate) {
        // Traverse HEAD to add all other paths
        TreeWalk treeWalk = new TreeWalk(repo);
        int hIdx = -1;
        if (headId != null)
          hIdx = treeWalk
              .addTree(new RevWalk(repo).parseTree(headId));
        treeWalk.setRecursive(true);

        while (treeWalk.next()) {
          String path = treeWalk.getPathString();
          CanonicalTreeParser hTree = null;
          if (hIdx != -1)
            hTree = treeWalk.getTree(hIdx,
                CanonicalTreeParser.class);
          if (!ignorePaths.contains(path)) {
            // add entries from HEAD for all other paths
            if (hTree != null) {
              // create a new DirCacheEntry with data retrieved
              // from
              // HEAD
              final DirCacheEntry dcEntry = new DirCacheEntry(
                  path);
              dcEntry.setObjectId(hTree.getEntryObjectId());
              dcEntry.setFileMode(hTree.getEntryFileMode());

              // add to temporary in-core index
              dcBuilder.add(dcEntry);
            }
          }
        }

        // release the treewalk
        treeWalk.release();
      }

      // finish temporary in-core index used for this commit
      dcBuilder.finish();
    } finally {
      inserter.release();
    }
    return inCoreIndex;
  }

  private static List<File> listFiles(File folder) {
    List<File> list = new ArrayList<File>();
    File [] files = folder.listFiles();
    if (files == null) {
      return list;
    }
    for (File file : files) {
      if (file.isDirectory()) {
        list.addAll(listFiles(file));
      } else {
        list.add(file);
      }
    }
    return list;
  }

  public static String commitFiles(File dir, List<String> files, String message,
      String tagName, String tagMessage) throws IOException, GitAPIException {
    Git git = Git.open(dir);
    AddCommand add = git.add();
    for (String file : files) {
      add.addFilepattern(file);
    }
    add.call();

    // execute the commit
    CommitCommand commit = git.commit();
    commit.setMessage(message);
    RevCommit revCommit = commit.call();

    if (!StringUtils.isEmpty(tagName) && !StringUtils.isEmpty(tagMessage)) {
      // tag the commit
      TagCommand tagCommand = git.tag();
      tagCommand.setName(tagName);
      tagCommand.setMessage(tagMessage);
      tagCommand.setForceUpdate(true);
      tagCommand.setObjectId(revCommit);
      tagCommand.call();
    }
    git.getRepository().close();
    return revCommit.getId().getName();
  }
}
TOP

Related Classes of org.moxie.utils.JGitUtils

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.