Java tutorial
/* * Copyright 2012 gitblit.com. * * 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 com.gitblit.build; 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.errors.ConcurrentRefUpdateException; 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.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.revwalk.RevCommit; import org.eclipse.jgit.revwalk.RevWalk; import org.eclipse.jgit.storage.file.FileRepository; import org.eclipse.jgit.treewalk.CanonicalTreeParser; import org.eclipse.jgit.treewalk.TreeWalk; import org.eclipse.jgit.util.FS; import com.beust.jcommander.JCommander; import com.beust.jcommander.Parameter; import com.beust.jcommander.ParameterException; import com.beust.jcommander.Parameters; import com.gitblit.models.RefModel; import com.gitblit.utils.JGitUtils; import com.gitblit.utils.StringUtils; /** * Creates or updates a gh-pages branch with the specified content. * * @author James Moger * */ public class BuildGhPages { public static void main(String[] args) { Params params = new Params(); JCommander jc = new JCommander(params); try { jc.parse(args); } catch (ParameterException t) { System.err.println(t.getMessage()); jc.usage(); } File source = new File(params.sourceFolder); String ghpages = "refs/heads/gh-pages"; try { File gitDir = FileKey.resolve(new File(params.repositoryFolder), FS.DETECTED); Repository repository = new FileRepository(gitDir); RefModel issuesBranch = JGitUtils.getPagesBranch(repository); if (issuesBranch == 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, source, params.obliterate); ObjectId indexTreeId = index.writeTree(odi); // Create a commit object PersonIdent author = new PersonIdent("Gitblit", "gitblit@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> files = new ArrayList<File>(); for (File file : folder.listFiles()) { if (file.isDirectory()) { files.addAll(listFiles(file)); } else { files.add(file); } } return files; } /** * JCommander Parameters class for BuildGhPages. */ @Parameters(separators = " ") private static class Params { @Parameter(names = { "--sourceFolder" }, description = "Source folder for pages", required = true) public String sourceFolder; @Parameter(names = { "--repository" }, description = "Repository folder", required = true) public String repositoryFolder; @Parameter(names = { "--obliterate" }, description = "Replace gh-pages tree with only the content in your sourcefolder") public boolean obliterate; } }