private static void assertV3TreeEntry( int indexPosition, String path, boolean skipWorkTree, boolean intentToAdd, DirCache dc) { final DirCacheEntry entry = dc.getEntry(indexPosition); assertEquals(path, entry.getPathString()); assertEquals(skipWorkTree, entry.isSkipWorkTree()); assertEquals(intentToAdd, entry.isIntentToAdd()); }
private void assumeUnchanged(String path) throws IOException { final DirCache dirc = db.lockDirCache(); final DirCacheEntry ent = dirc.getEntry(path); if (ent != null) ent.setAssumeValid(true); dirc.write(); if (!dirc.commit()) throw new IOException("could not commit"); }
@Test public void testUnsupportedOptionalExtension() throws Exception { final DirCache dc = new DirCache(pathOf("gitgit.index.ZZZZ"), FS.DETECTED); dc.read(); assertEquals(1, dc.getEntryCount()); assertEquals("A", dc.getEntry(0).getPathString()); }
@Test public void testReadIndex_LsFiles() throws Exception { final Map<String, CGitIndexRecord> ls = readLsFiles(); final DirCache dc = new DirCache(index, FS.DETECTED); assertEquals(0, dc.getEntryCount()); dc.read(); assertEquals(ls.size(), dc.getEntryCount()); { final Iterator<CGitIndexRecord> rItr = ls.values().iterator(); for (int i = 0; rItr.hasNext(); i++) assertEqual(rItr.next(), dc.getEntry(i)); } }
@Test public void testPathsResetOnUnbornBranch() throws Exception { git = new Git(db); writeTrashFile("a.txt", "content"); git.add().addFilepattern("a.txt").call(); // Should assume an empty tree, like in C Git 1.8.2 git.reset().addPath("a.txt").call(); DirCache cache = db.readDirCache(); DirCacheEntry aEntry = cache.getEntry("a.txt"); assertNull(aEntry); }
@Test public void testMixedResetRetainsSizeAndModifiedTime() throws Exception { git = new Git(db); writeTrashFile("a.txt", "a").setLastModified(System.currentTimeMillis() - 60 * 1000); assertNotNull(git.add().addFilepattern("a.txt").call()); assertNotNull(git.commit().setMessage("a commit").call()); writeTrashFile("b.txt", "b").setLastModified(System.currentTimeMillis() - 60 * 1000); assertNotNull(git.add().addFilepattern("b.txt").call()); RevCommit commit2 = git.commit().setMessage("b commit").call(); assertNotNull(commit2); DirCache cache = db.readDirCache(); DirCacheEntry aEntry = cache.getEntry("a.txt"); assertNotNull(aEntry); assertTrue(aEntry.getLength() > 0); assertTrue(aEntry.getLastModified() > 0); DirCacheEntry bEntry = cache.getEntry("b.txt"); assertNotNull(bEntry); assertTrue(bEntry.getLength() > 0); assertTrue(bEntry.getLastModified() > 0); git.reset().setMode(ResetType.MIXED).setRef(commit2.getName()).call(); cache = db.readDirCache(); DirCacheEntry mixedAEntry = cache.getEntry("a.txt"); assertNotNull(mixedAEntry); assertEquals(aEntry.getLastModified(), mixedAEntry.getLastModified()); assertEquals(aEntry.getLastModified(), mixedAEntry.getLastModified()); DirCacheEntry mixedBEntry = cache.getEntry("b.txt"); assertNotNull(mixedBEntry); assertEquals(bEntry.getLastModified(), mixedBEntry.getLastModified()); assertEquals(bEntry.getLastModified(), mixedBEntry.getLastModified()); }
@Test public void testHardResetOnUnbornBranch() throws Exception { git = new Git(db); File fileA = writeTrashFile("a.txt", "content"); git.add().addFilepattern("a.txt").call(); // Should assume an empty tree, like in C Git 1.8.2 git.reset().setMode(ResetType.HARD).call(); DirCache cache = db.readDirCache(); DirCacheEntry aEntry = cache.getEntry("a.txt"); assertNull(aEntry); assertFalse(fileA.exists()); assertNull(db.resolve(Constants.HEAD)); }
/** * Reverts the worktree after an unsuccessful merge. We know that for all modified files the old * content was in the old index and the index contained only stage 0. In case if inCore operation * just clear the history of modified files. * * @throws IOException * @throws CorruptObjectException * @throws NoWorkTreeException * @since 3.4 */ protected void cleanUp() throws NoWorkTreeException, CorruptObjectException, IOException { if (inCore) { modifiedFiles.clear(); return; } DirCache dc = db.readDirCache(); Iterator<String> mpathsIt = modifiedFiles.iterator(); while (mpathsIt.hasNext()) { String mpath = mpathsIt.next(); DirCacheEntry entry = dc.getEntry(mpath); if (entry != null) DirCacheCheckout.checkoutEntry(db, entry, reader); mpathsIt.remove(); } }
@Test public void testEntriesWithin() throws Exception { final DirCache dc = db.readDirCache(); final String[] paths = {"a.", "a/b", "a/c", "a/d", "a0b"}; final DirCacheEntry[] ents = new DirCacheEntry[paths.length]; for (int i = 0; i < paths.length; i++) { ents[i] = new DirCacheEntry(paths[i]); ents[i].setFileMode(FileMode.REGULAR_FILE); } final int aFirst = 1; final int aLast = 3; final DirCacheBuilder b = dc.builder(); for (int i = 0; i < ents.length; i++) b.add(ents[i]); b.finish(); assertEquals(paths.length, dc.getEntryCount()); for (int i = 0; i < ents.length; i++) assertSame(ents[i], dc.getEntry(i)); { final DirCacheEntry[] aContents = dc.getEntriesWithin("a"); assertNotNull(aContents); assertEquals(aLast - aFirst + 1, aContents.length); for (int i = aFirst, j = 0; i <= aLast; i++, j++) assertSame(ents[i], aContents[j]); } { final DirCacheEntry[] aContents = dc.getEntriesWithin("a/"); assertNotNull(aContents); assertEquals(aLast - aFirst + 1, aContents.length); for (int i = aFirst, j = 0; i <= aLast; i++, j++) assertSame(ents[i], aContents[j]); } { final DirCacheEntry[] aContents = dc.getEntriesWithin(""); assertNotNull(aContents); assertEquals(ents.length, aContents.length); for (int i = 0; i < ents.length; i++) assertSame(ents[i], aContents[i]); } assertNotNull(dc.getEntriesWithin("a.")); assertEquals(0, dc.getEntriesWithin("a.").length); assertNotNull(dc.getEntriesWithin("a0b")); assertEquals(0, dc.getEntriesWithin("a0b.").length); assertNotNull(dc.getEntriesWithin("zoo")); assertEquals(0, dc.getEntriesWithin("zoo.").length); }
/** * Update the submodules in one branch of one repository. * * @param subscriber the branch of the repository which should be changed. * @param updates submodule updates which should be updated to. * @throws SubmoduleException */ private void updateGitlinks( ReviewDb db, Branch.NameKey subscriber, Collection<SubmoduleSubscription> updates) throws SubmoduleException { PersonIdent author = null; Repository pdb = null; RevWalk recRw = null; StringBuilder msgbuf = new StringBuilder("Updated git submodules\n\n"); try { boolean sameAuthorForAll = true; pdb = repoManager.openRepository(subscriber.getParentKey()); if (pdb.getRef(subscriber.get()) == null) { throw new SubmoduleException( "The branch was probably deleted from the subscriber repository"); } DirCache dc = readTree(pdb, pdb.getRef(subscriber.get())); DirCacheEditor ed = dc.editor(); for (SubmoduleSubscription s : updates) { try (Repository subrepo = repoManager.openRepository(s.getSubmodule().getParentKey()); RevWalk rw = CodeReviewCommit.newRevWalk(subrepo)) { Ref ref = subrepo.getRefDatabase().exactRef(s.getSubmodule().get()); if (ref == null) { ed.add(new DeletePath(s.getPath())); continue; } final ObjectId updateTo = ref.getObjectId(); RevCommit newCommit = rw.parseCommit(updateTo); if (author == null) { author = newCommit.getAuthorIdent(); } else if (!author.equals(newCommit.getAuthorIdent())) { sameAuthorForAll = false; } DirCacheEntry dce = dc.getEntry(s.getPath()); ObjectId oldId = null; if (dce != null) { if (!dce.getFileMode().equals(FileMode.GITLINK)) { log.error( "Requested to update gitlink " + s.getPath() + " in " + s.getSubmodule().getParentKey().get() + " but entry " + "doesn't have gitlink file mode."); continue; } oldId = dce.getObjectId(); } else { // This submodule did not exist before. We do not want to add // the full submodule history to the commit message, so omit it. oldId = updateTo; } ed.add( new PathEdit(s.getPath()) { @Override public void apply(DirCacheEntry ent) { ent.setFileMode(FileMode.GITLINK); ent.setObjectId(updateTo); } }); if (verboseSuperProject) { msgbuf.append("Project: " + s.getSubmodule().getParentKey().get()); msgbuf.append(" " + s.getSubmodule().getShortName()); msgbuf.append(" " + updateTo.getName()); msgbuf.append("\n\n"); try { rw.markStart(newCommit); if (oldId != null) { rw.markUninteresting(rw.parseCommit(oldId)); } for (RevCommit c : rw) { msgbuf.append(c.getFullMessage() + "\n\n"); } } catch (IOException e) { logAndThrowSubmoduleException( "Could not perform a revwalk to " + "create superproject commit message", e); } } } } ed.finish(); if (!sameAuthorForAll || author == null) { author = myIdent; } ObjectInserter oi = pdb.newObjectInserter(); ObjectId tree = dc.writeTree(oi); ObjectId currentCommitId = pdb.getRef(subscriber.get()).getObjectId(); CommitBuilder commit = new CommitBuilder(); commit.setTreeId(tree); commit.setParentIds(new ObjectId[] {currentCommitId}); commit.setAuthor(author); commit.setCommitter(myIdent); commit.setMessage(msgbuf.toString()); oi.insert(commit); oi.flush(); ObjectId commitId = oi.idFor(Constants.OBJ_COMMIT, commit.build()); final RefUpdate rfu = pdb.updateRef(subscriber.get()); rfu.setForceUpdate(false); rfu.setNewObjectId(commitId); rfu.setExpectedOldObjectId(currentCommitId); rfu.setRefLogMessage("Submit to " + subscriber.getParentKey().get(), true); switch (rfu.update()) { case NEW: case FAST_FORWARD: gitRefUpdated.fire(subscriber.getParentKey(), rfu); changeHooks.doRefUpdatedHook(subscriber, rfu, account); // TODO since this is performed "in the background" no mail will be // sent to inform users about the updated branch break; default: throw new IOException(rfu.getResult().name()); } recRw = new RevWalk(pdb); // Recursive call: update subscribers of the subscriber updateSuperProjects(db, Sets.newHashSet(subscriber)); } catch (IOException e) { throw new SubmoduleException("Cannot update gitlinks for " + subscriber.get(), e); } finally { if (recRw != null) { recRw.close(); } if (pdb != null) { pdb.close(); } } }
private boolean isInIndex(Repository db, String path) throws IOException { DirCache dc = DirCache.read(db.getIndexFile(), db.getFS()); return dc.getEntry(path) != null; }
private boolean doCheckout() throws CorruptObjectException, IOException, MissingObjectException, IncorrectObjectTypeException, CheckoutConflictException, IndexWriteException { toBeDeleted.clear(); ObjectReader objectReader = repo.getObjectDatabase().newReader(); try { if (headCommitTree != null) preScanTwoTrees(); else prescanOneTree(); if (!conflicts.isEmpty()) { if (failOnConflict) throw new CheckoutConflictException(conflicts.toArray(new String[conflicts.size()])); else cleanUpConflicts(); } // update our index builder.finish(); File file = null; String last = ""; // $NON-NLS-1$ // when deleting files process them in the opposite order as they have // been reported. This ensures the files are deleted before we delete // their parent folders for (int i = removed.size() - 1; i >= 0; i--) { String r = removed.get(i); file = new File(repo.getWorkTree(), r); if (!file.delete() && file.exists()) { // The list of stuff to delete comes from the index // which will only contain a directory if it is // a submodule, in which case we shall not attempt // to delete it. A submodule is not empty, so it // is safe to check this after a failed delete. if (!file.isDirectory()) toBeDeleted.add(r); } else { if (!isSamePrefix(r, last)) removeEmptyParents(new File(repo.getWorkTree(), last)); last = r; } } if (file != null) removeEmptyParents(file); for (String path : updated.keySet()) { // ... create/overwrite this file ... file = new File(repo.getWorkTree(), path); if (!file.getParentFile().mkdirs()) { // ignore } DirCacheEntry entry = dc.getEntry(path); // submodules are handled with separate operations if (FileMode.GITLINK.equals(entry.getRawMode())) continue; checkoutEntry(repo, file, entry, objectReader); } // commit the index builder - a new index is persisted if (!builder.commit()) throw new IndexWriteException(); } finally { objectReader.release(); } return toBeDeleted.size() == 0; }
public int getDirCacheEntryLength(String path) throws IOException { String repoPath = getRepoRelativePath(path); DirCache dc = DirCache.read(repository.getIndexFile(), repository.getFS()); return dc.getEntry(repoPath).getLength(); }
public long lastModifiedInIndex(String path) throws IOException { String repoPath = getRepoRelativePath(path); DirCache dc = DirCache.read(repository.getIndexFile(), repository.getFS()); return dc.getEntry(repoPath).getLastModified(); }
public boolean inIndex(String path) throws IOException { String repoPath = getRepoRelativePath(path); DirCache dc = DirCache.read(repository.getIndexFile(), repository.getFS()); return dc.getEntry(repoPath) != null; }
@Override protected void run() throws Exception { if (file == null) { if (revision == null) throw die(CLIText.get().fileIsRequired); file = revision; revision = null; } boolean autoAbbrev = abbrev == 0; if (abbrev == 0) abbrev = db.getConfig().getInt("core", "abbrev", 7); // $NON-NLS-1$ //$NON-NLS-2$ if (!showBlankBoundary) root = db.getConfig().getBoolean("blame", "blankboundary", false); // $NON-NLS-1$ //$NON-NLS-2$ if (!root) root = db.getConfig().getBoolean("blame", "showroot", false); // $NON-NLS-1$ //$NON-NLS-2$ if (showRawTimestamp) dateFmt = new SimpleDateFormat("ZZZZ"); // $NON-NLS-1$ else dateFmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss ZZZZ"); // $NON-NLS-1$ reader = db.newObjectReader(); try (BlameGenerator generator = new BlameGenerator(db, file)) { RevFlag scanned = generator.newFlag("SCANNED"); // $NON-NLS-1$ generator.setTextComparator(comparator); if (!reverseRange.isEmpty()) { RevCommit rangeStart = null; List<RevCommit> rangeEnd = new ArrayList<RevCommit>(2); for (RevCommit c : reverseRange) { if (c.has(RevFlag.UNINTERESTING)) rangeStart = c; else rangeEnd.add(c); } generator.reverse(rangeStart, rangeEnd); } else if (revision != null) { generator.push(null, db.resolve(revision + "^{commit}")); // $NON-NLS-1$ } else { generator.push(null, db.resolve(Constants.HEAD)); if (!db.isBare()) { DirCache dc = db.readDirCache(); int entry = dc.findEntry(file); if (0 <= entry) generator.push(null, dc.getEntry(entry).getObjectId()); File inTree = new File(db.getWorkTree(), file); if (db.getFS().isFile(inTree)) generator.push(null, new RawText(inTree)); } } blame = BlameResult.create(generator); begin = 0; end = blame.getResultContents().size(); if (rangeString != null) parseLineRangeOption(); blame.computeRange(begin, end); int authorWidth = 8; int dateWidth = 8; int pathWidth = 1; int maxSourceLine = 1; for (int line = begin; line < end; line++) { RevCommit c = blame.getSourceCommit(line); if (c != null && !c.has(scanned)) { c.add(scanned); if (autoAbbrev) abbrev = Math.max(abbrev, uniqueAbbrevLen(c)); authorWidth = Math.max(authorWidth, author(line).length()); dateWidth = Math.max(dateWidth, date(line).length()); pathWidth = Math.max(pathWidth, path(line).length()); } while (line + 1 < end && blame.getSourceCommit(line + 1) == c) line++; maxSourceLine = Math.max(maxSourceLine, blame.getSourceLine(line)); } String pathFmt = MessageFormat.format(" %{0}s", valueOf(pathWidth)); // $NON-NLS-1$ String numFmt = MessageFormat.format( " %{0}d", //$NON-NLS-1$ valueOf(1 + (int) Math.log10(maxSourceLine + 1))); String lineFmt = MessageFormat.format( " %{0}d) ", //$NON-NLS-1$ valueOf(1 + (int) Math.log10(end + 1))); String authorFmt = MessageFormat.format( " (%-{0}s %{1}s", //$NON-NLS-1$ valueOf(authorWidth), valueOf(dateWidth)); for (int line = begin; line < end; ) { RevCommit c = blame.getSourceCommit(line); String commit = abbreviate(c); String author = null; String date = null; if (!noAuthor) { author = author(line); date = date(line); } do { outw.print(commit); if (showSourcePath) outw.format(pathFmt, path(line)); if (showSourceLine) outw.format(numFmt, valueOf(blame.getSourceLine(line) + 1)); if (!noAuthor) outw.format(authorFmt, author, date); outw.format(lineFmt, valueOf(line + 1)); outw.flush(); blame.getResultContents().writeLine(outs, line); outs.flush(); outw.print('\n'); } while (++line < end && blame.getSourceCommit(line) == c); } } finally { reader.close(); } }