| | |
| | | import java.text.MessageFormat; |
| | | import java.util.ArrayList; |
| | | import java.util.Arrays; |
| | | import java.util.Collection; |
| | | import java.util.Collections; |
| | | import java.util.HashSet; |
| | | import java.util.List; |
| | |
| | | import java.util.concurrent.atomic.AtomicLong; |
| | | |
| | | 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.events.RefsChangedEvent; |
| | | import org.eclipse.jgit.events.RefsChangedListener; |
| | | import org.eclipse.jgit.internal.JGitText; |
| | | import org.eclipse.jgit.lib.CommitBuilder; |
| | | 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.Ref; |
| | | import org.eclipse.jgit.lib.RefRename; |
| | | import org.eclipse.jgit.lib.RefUpdate; |
| | | import org.eclipse.jgit.lib.RefUpdate.Result; |
| | | import org.eclipse.jgit.lib.Repository; |
| | | import org.eclipse.jgit.revwalk.RevCommit; |
| | |
| | | Set<String> ignorePaths = new HashSet<String>(); |
| | | ignorePaths.add(file); |
| | | |
| | | for (DirCacheEntry entry : getTreeEntries(db, ignorePaths)) { |
| | | for (DirCacheEntry entry : JGitUtils.getTreeEntries(db, BRANCH, ignorePaths)) { |
| | | builder.add(entry); |
| | | } |
| | | |
| | |
| | | } |
| | | } |
| | | |
| | | for (DirCacheEntry entry : getTreeEntries(db, ignorePaths)) { |
| | | for (DirCacheEntry entry : JGitUtils.getTreeEntries(db, BRANCH, ignorePaths)) { |
| | | builder.add(entry); |
| | | } |
| | | |
| | |
| | | return newIndex; |
| | | } |
| | | |
| | | /** |
| | | * Returns all tree entries that do not match the ignore paths. |
| | | * |
| | | * @param db |
| | | * @param ignorePaths |
| | | * @param dcBuilder |
| | | * @throws IOException |
| | | */ |
| | | private List<DirCacheEntry> getTreeEntries(Repository db, Collection<String> ignorePaths) throws IOException { |
| | | List<DirCacheEntry> list = new ArrayList<DirCacheEntry>(); |
| | | TreeWalk tw = null; |
| | | try { |
| | | ObjectId treeId = db.resolve(BRANCH + "^{tree}"); |
| | | if (treeId == null) { |
| | | // branch does not exist yet, could be migrating tickets |
| | | return list; |
| | | } |
| | | tw = new TreeWalk(db); |
| | | int hIdx = tw.addTree(treeId); |
| | | tw.setRecursive(true); |
| | | |
| | | while (tw.next()) { |
| | | String path = tw.getPathString(); |
| | | CanonicalTreeParser hTree = null; |
| | | if (hIdx != -1) { |
| | | hTree = tw.getTree(hIdx, CanonicalTreeParser.class); |
| | | } |
| | | if (!ignorePaths.contains(path)) { |
| | | // add all other tree entries |
| | | if (hTree != null) { |
| | | final DirCacheEntry entry = new DirCacheEntry(path); |
| | | entry.setObjectId(hTree.getEntryObjectId()); |
| | | entry.setFileMode(hTree.getEntryFileMode()); |
| | | list.add(entry); |
| | | } |
| | | } |
| | | } |
| | | } finally { |
| | | if (tw != null) { |
| | | tw.close(); |
| | | } |
| | | } |
| | | return list; |
| | | } |
| | | |
| | | private boolean commitIndex(Repository db, DirCache index, String author, String message) throws IOException, ConcurrentRefUpdateException { |
| | | final boolean forceCommit = true; |
| | | boolean success = false; |
| | | |
| | | ObjectId headId = db.resolve(BRANCH + "^{commit}"); |
| | | if (headId == null) { |
| | | // create the branch |
| | | createTicketsBranch(db); |
| | | headId = db.resolve(BRANCH + "^{commit}"); |
| | | } |
| | | ObjectInserter odi = db.newObjectInserter(); |
| | | try { |
| | | // Create the in-memory index of the new/updated ticket |
| | | ObjectId indexTreeId = index.writeTree(odi); |
| | | |
| | | // Create a commit object |
| | | PersonIdent ident = new PersonIdent(author, "gitblit@localhost"); |
| | | CommitBuilder commit = new CommitBuilder(); |
| | | commit.setAuthor(ident); |
| | | commit.setCommitter(ident); |
| | | commit.setEncoding(Constants.ENCODING); |
| | | commit.setMessage(message); |
| | | commit.setParentId(headId); |
| | | commit.setTreeId(indexTreeId); |
| | | success = JGitUtils.commitIndex(db, BRANCH, index, headId, forceCommit, author, "gitblit@localhost", message); |
| | | |
| | | // Insert the commit into the repository |
| | | ObjectId commitId = odi.insert(commit); |
| | | odi.flush(); |
| | | |
| | | RevWalk revWalk = new RevWalk(db); |
| | | try { |
| | | RevCommit revCommit = revWalk.parseCommit(commitId); |
| | | RefUpdate ru = db.updateRef(BRANCH); |
| | | 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: |
| | | success = true; |
| | | break; |
| | | case REJECTED: |
| | | case LOCK_FAILURE: |
| | | throw new ConcurrentRefUpdateException(JGitText.get().couldNotLockHEAD, |
| | | ru.getRef(), rc); |
| | | default: |
| | | throw new JGitInternalException(MessageFormat.format( |
| | | JGitText.get().updatingRefFailed, BRANCH, commitId.toString(), |
| | | rc)); |
| | | } |
| | | } finally { |
| | | revWalk.close(); |
| | | } |
| | | } finally { |
| | | odi.close(); |
| | | } |
| | | return success; |
| | | } |
| | | |