From: James Moger Date: Wed, 11 Jan 2012 21:18:02 +0000 (-0500) Subject: Update the gh-pages branch on release with the built site X-Git-Tag: v0.8.0~3 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=746aaf82146a8621523004eebeb348766f611674;p=gitblit.git Update the gh-pages branch on release with the built site --- diff --git a/build.xml b/build.xml index 0d906ed6..7bb09cfd 100644 --- a/build.xml +++ b/build.xml @@ -857,6 +857,26 @@ + + + + + + + + + + + + + + + + - + Uploading Gitblit ${gb.version} website diff --git a/src/com/gitblit/build/BuildGhPages.java b/src/com/gitblit/build/BuildGhPages.java new file mode 100644 index 00000000..efeb43c4 --- /dev/null +++ b/src/com/gitblit/build/BuildGhPages.java @@ -0,0 +1,259 @@ +/* + * 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.JGitText; +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.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 ignorePaths = new TreeSet(); + List 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 listFiles(File folder) { + List files = new ArrayList(); + 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; + + } +}