/** * Creates an in-memory index of the ticket change. * * @param changeId * @param change * @return an in-memory index * @throws IOException */ private DirCache createIndex(Repository db, long ticketId, Change change) throws IOException, ClassNotFoundException, NoSuchFieldException { String ticketPath = toTicketPath(ticketId); DirCache newIndex = DirCache.newInCore(); DirCacheBuilder builder = newIndex.builder(); Set<String> ignorePaths = new TreeSet<String>(); try (ObjectInserter inserter = db.newObjectInserter()) { // create/update the journal // exclude the attachment content List<Change> changes = getJournal(db, ticketId); changes.add(change); String journal = TicketSerializer.serializeJournal(changes).trim(); byte[] journalBytes = journal.getBytes(Constants.ENCODING); String journalPath = ticketPath + "/" + JOURNAL; final DirCacheEntry journalEntry = new DirCacheEntry(journalPath); journalEntry.setLength(journalBytes.length); journalEntry.setLastModified(change.date.getTime()); journalEntry.setFileMode(FileMode.REGULAR_FILE); journalEntry.setObjectId( inserter.insert(org.eclipse.jgit.lib.Constants.OBJ_BLOB, journalBytes)); // add journal to index builder.add(journalEntry); ignorePaths.add(journalEntry.getPathString()); // Add any attachments to the index if (change.hasAttachments()) { for (Attachment attachment : change.attachments) { // build a path name for the attachment and mark as ignored String path = toAttachmentPath(ticketId, attachment.name); ignorePaths.add(path); // create an index entry for this attachment final DirCacheEntry entry = new DirCacheEntry(path); entry.setLength(attachment.content.length); entry.setLastModified(change.date.getTime()); entry.setFileMode(FileMode.REGULAR_FILE); // insert object entry.setObjectId( inserter.insert(org.eclipse.jgit.lib.Constants.OBJ_BLOB, attachment.content)); // add to temporary in-core index builder.add(entry); } } for (DirCacheEntry entry : getTreeEntries(db, ignorePaths)) { builder.add(entry); } // finish the index builder.finish(); } return newIndex; }
protected DirCache readTree(RevTree tree) throws IOException, MissingObjectException, IncorrectObjectTypeException { DirCache dc = DirCache.newInCore(); if (tree != null) { DirCacheBuilder b = dc.builder(); b.addTree(new byte[0], DirCacheEntry.STAGE_0, reader, tree); b.finish(); } return dc; }
private static DirCache readTree(final Repository pdb, final Ref branch) throws MissingObjectException, IncorrectObjectTypeException, IOException { try (RevWalk rw = new RevWalk(pdb)) { final DirCache dc = DirCache.newInCore(); final DirCacheBuilder b = dc.builder(); b.addTree( new byte[0], // no prefix path DirCacheEntry.STAGE_0, // standard stage pdb.newObjectReader(), rw.parseTree(branch.getObjectId())); b.finish(); return dc; } }
/** * Construct a tree from a specific listing of file entries. * * @param entries the files to include in the tree. The collection does not need to be sorted * properly and may be empty. * @return reference to the tree specified by the entry list. * @throws Exception */ public RevTree tree(final DirCacheEntry... entries) throws Exception { final DirCache dc = DirCache.newInCore(); final DirCacheBuilder b = dc.builder(); for (final DirCacheEntry e : entries) b.add(e); b.finish(); ObjectId root; try { root = dc.writeTree(inserter); inserter.flush(); } finally { inserter.release(); } return pool.lookupTree(root); }
/** * Writes a file to the tickets branch. * * @param db * @param file * @param content * @param createdBy * @param msg */ private void writeTicketsFile( Repository db, String file, String content, String createdBy, String msg) { if (getTicketsBranch(db) == null) { createTicketsBranch(db); } DirCache newIndex = DirCache.newInCore(); DirCacheBuilder builder = newIndex.builder(); try (ObjectInserter inserter = db.newObjectInserter()) { // create an index entry for the revised index final DirCacheEntry idIndexEntry = new DirCacheEntry(file); idIndexEntry.setLength(content.length()); idIndexEntry.setLastModified(System.currentTimeMillis()); idIndexEntry.setFileMode(FileMode.REGULAR_FILE); // insert new ticket index idIndexEntry.setObjectId( inserter.insert( org.eclipse.jgit.lib.Constants.OBJ_BLOB, content.getBytes(Constants.ENCODING))); // add to temporary in-core index builder.add(idIndexEntry); Set<String> ignorePaths = new HashSet<String>(); ignorePaths.add(file); for (DirCacheEntry entry : getTreeEntries(db, ignorePaths)) { builder.add(entry); } // finish temporary in-core index used for this commit builder.finish(); // commit the change commitIndex(db, newIndex, createdBy, msg); } catch (ConcurrentRefUpdateException e) { log.error("", e); } catch (IOException e) { log.error("", e); } }
/** * @param local * @param inCore */ protected ResolveMerger(Repository local, boolean inCore) { super(local); SupportedAlgorithm diffAlg = local .getConfig() .getEnum( ConfigConstants.CONFIG_DIFF_SECTION, null, ConfigConstants.CONFIG_KEY_ALGORITHM, SupportedAlgorithm.HISTOGRAM); mergeAlgorithm = new MergeAlgorithm(DiffAlgorithm.getAlgorithm(diffAlg)); commitNames = new String[] {"BASE", "OURS", "THEIRS"}; // $NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ this.inCore = inCore; if (inCore) { implicitDirCache = false; dircache = DirCache.newInCore(); } else { implicitDirCache = true; } }
private DirCache createTemporaryIndex(ObjectId headId, DirCache index, RevWalk rw) throws IOException { ObjectInserter inserter = null; // get DirCacheBuilder for existing index DirCacheBuilder existingBuilder = index.builder(); // get DirCacheBuilder for newly created in-core index to build a // temporary index for this commit DirCache inCoreIndex = DirCache.newInCore(); DirCacheBuilder tempBuilder = inCoreIndex.builder(); onlyProcessed = new boolean[only.size()]; boolean emptyCommit = true; try (TreeWalk treeWalk = new TreeWalk(repo)) { treeWalk.setOperationType(OperationType.CHECKIN_OP); int dcIdx = treeWalk.addTree(new DirCacheBuildIterator(existingBuilder)); FileTreeIterator fti = new FileTreeIterator(repo); fti.setDirCacheIterator(treeWalk, 0); int fIdx = treeWalk.addTree(fti); int hIdx = -1; if (headId != null) hIdx = treeWalk.addTree(rw.parseTree(headId)); treeWalk.setRecursive(true); String lastAddedFile = null; while (treeWalk.next()) { String path = treeWalk.getPathString(); // check if current entry's path matches a specified path int pos = lookupOnly(path); CanonicalTreeParser hTree = null; if (hIdx != -1) hTree = treeWalk.getTree(hIdx, CanonicalTreeParser.class); DirCacheIterator dcTree = treeWalk.getTree(dcIdx, DirCacheIterator.class); if (pos >= 0) { // include entry in commit FileTreeIterator fTree = treeWalk.getTree(fIdx, FileTreeIterator.class); // check if entry refers to a tracked file boolean tracked = dcTree != null || hTree != null; if (!tracked) continue; // for an unmerged path, DirCacheBuildIterator will yield 3 // entries, we only want to add one if (path.equals(lastAddedFile)) continue; lastAddedFile = path; if (fTree != null) { // create a new DirCacheEntry with data retrieved from // disk final DirCacheEntry dcEntry = new DirCacheEntry(path); long entryLength = fTree.getEntryLength(); dcEntry.setLength(entryLength); dcEntry.setLastModified(fTree.getEntryLastModified()); dcEntry.setFileMode(fTree.getIndexFileMode(dcTree)); boolean objectExists = (dcTree != null && fTree.idEqual(dcTree)) || (hTree != null && fTree.idEqual(hTree)); if (objectExists) { dcEntry.setObjectId(fTree.getEntryObjectId()); } else { if (FileMode.GITLINK.equals(dcEntry.getFileMode())) dcEntry.setObjectId(fTree.getEntryObjectId()); else { // insert object if (inserter == null) inserter = repo.newObjectInserter(); long contentLength = fTree.getEntryContentLength(); InputStream inputStream = fTree.openEntryStream(); try { dcEntry.setObjectId( inserter.insert(Constants.OBJ_BLOB, contentLength, inputStream)); } finally { inputStream.close(); } } } // add to existing index existingBuilder.add(dcEntry); // add to temporary in-core index tempBuilder.add(dcEntry); if (emptyCommit && (hTree == null || !hTree.idEqual(fTree) || hTree.getEntryRawMode() != fTree.getEntryRawMode())) // this is a change emptyCommit = false; } else { // if no file exists on disk, neither add it to // index nor to temporary in-core index if (emptyCommit && hTree != null) // this is a change emptyCommit = false; } // keep track of processed path onlyProcessed[pos] = true; } else { // 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 tempBuilder.add(dcEntry); } // preserve existing entry in index if (dcTree != null) existingBuilder.add(dcTree.getDirCacheEntry()); } } } // there must be no unprocessed paths left at this point; otherwise an // untracked or unknown path has been specified for (int i = 0; i < onlyProcessed.length; i++) if (!onlyProcessed[i]) throw new JGitInternalException( MessageFormat.format(JGitText.get().entryNotFoundByPath, only.get(i))); // there must be at least one change if (emptyCommit) throw new JGitInternalException(JGitText.get().emptyCommit); // update index existingBuilder.commit(); // finish temporary in-core index used for this commit tempBuilder.finish(); return inCoreIndex; }
@Test public void testFindOnEmpty() throws Exception { final DirCache dc = DirCache.newInCore(); final byte[] path = Constants.encode("a"); assertEquals(-1, dc.findEntry(path, path.length)); }
/** * Deletes a ticket from the repository. * * @param ticket * @return true if successful */ @Override protected synchronized boolean deleteTicketImpl( RepositoryModel repository, TicketModel ticket, String deletedBy) { if (ticket == null) { throw new RuntimeException("must specify a ticket!"); } boolean success = false; Repository db = repositoryManager.getRepository(ticket.repository); try { RefModel ticketsBranch = getTicketsBranch(db); if (ticketsBranch == null) { throw new RuntimeException(BRANCH + " does not exist!"); } String ticketPath = toTicketPath(ticket.number); try { ObjectId treeId = db.resolve(BRANCH + "^{tree}"); // Create the in-memory index of the new/updated ticket DirCache index = DirCache.newInCore(); DirCacheBuilder builder = index.builder(); // Traverse HEAD to add all other paths try (TreeWalk treeWalk = new TreeWalk(db)) { int hIdx = -1; if (treeId != null) { hIdx = treeWalk.addTree(treeId); } treeWalk.setRecursive(true); while (treeWalk.next()) { String path = treeWalk.getPathString(); CanonicalTreeParser hTree = null; if (hIdx != -1) { hTree = treeWalk.getTree(hIdx, CanonicalTreeParser.class); } if (!path.startsWith(ticketPath)) { // add entries from HEAD for all other paths if (hTree != null) { final DirCacheEntry entry = new DirCacheEntry(path); entry.setObjectId(hTree.getEntryObjectId()); entry.setFileMode(hTree.getEntryFileMode()); // add to temporary in-core index builder.add(entry); } } } } // finish temporary in-core index used for this commit builder.finish(); success = commitIndex(db, index, deletedBy, "- " + ticket.number); } catch (Throwable t) { log.error( MessageFormat.format( "Failed to delete ticket {0,number,0} from {1}", ticket.number, db.getDirectory()), t); } } finally { db.close(); } return success; }
/** Helper to generate a commit. */ public class CommitBuilder { private final BranchBuilder branch; private final DirCache tree = DirCache.newInCore(); private final List<RevCommit> parents = new ArrayList<RevCommit>(2); private int tick = 1; private String message = ""; private RevCommit self; CommitBuilder() { branch = null; } CommitBuilder(BranchBuilder b) throws Exception { branch = b; Ref ref = db.getRef(branch.ref); if (ref != null) { parent(pool.parseCommit(ref.getObjectId())); } } CommitBuilder(CommitBuilder prior) throws Exception { branch = prior.branch; DirCacheBuilder b = tree.builder(); for (int i = 0; i < prior.tree.getEntryCount(); i++) b.add(prior.tree.getEntry(i)); b.finish(); parents.add(prior.create()); } public CommitBuilder parent(RevCommit p) throws Exception { if (parents.isEmpty()) { DirCacheBuilder b = tree.builder(); parseBody(p); b.addTree(new byte[0], DirCacheEntry.STAGE_0, pool.getObjectReader(), p.getTree()); b.finish(); } parents.add(p); return this; } public CommitBuilder noParents() { parents.clear(); return this; } public CommitBuilder noFiles() { tree.clear(); return this; } public CommitBuilder add(String path, String content) throws Exception { return add(path, blob(content)); } public CommitBuilder add(String path, final RevBlob id) throws Exception { return edit( new PathEdit(path) { @Override public void apply(DirCacheEntry ent) { ent.setFileMode(FileMode.REGULAR_FILE); ent.setObjectId(id); } }); } public CommitBuilder edit(PathEdit edit) { DirCacheEditor e = tree.editor(); e.add(edit); e.finish(); return this; } public CommitBuilder rm(String path) { DirCacheEditor e = tree.editor(); e.add(new DeletePath(path)); e.add(new DeleteTree(path)); e.finish(); return this; } public CommitBuilder message(String m) { message = m; return this; } public CommitBuilder tick(int secs) { tick = secs; return this; } public RevCommit create() throws Exception { if (self == null) { TestRepository.this.tick(tick); final org.eclipse.jgit.lib.CommitBuilder c; c = new org.eclipse.jgit.lib.CommitBuilder(); c.setParentIds(parents); setAuthorAndCommitter(c); c.setMessage(message); ObjectId commitId; try { c.setTreeId(tree.writeTree(inserter)); commitId = inserter.insert(c); inserter.flush(); } finally { inserter.release(); } self = pool.lookupCommit(commitId); if (branch != null) branch.update(self); } return self; } public CommitBuilder child() throws Exception { return new CommitBuilder(this); } }