/** * Run consistency checks against the object database. * * <p>This method completes silently if the checks pass. A temporary revision pool is constructed * during the checking. * * @param tips the tips to start checking from; if not supplied the refs of the repository are * used instead. * @throws MissingObjectException * @throws IncorrectObjectTypeException * @throws IOException */ public void fsck(RevObject... tips) throws MissingObjectException, IncorrectObjectTypeException, IOException { ObjectWalk ow = new ObjectWalk(db); if (tips.length != 0) { for (RevObject o : tips) ow.markStart(ow.parseAny(o)); } else { for (Ref r : db.getAllRefs().values()) ow.markStart(ow.parseAny(r.getObjectId())); } ObjectChecker oc = new ObjectChecker(); for (; ; ) { final RevCommit o = ow.next(); if (o == null) break; final byte[] bin = db.open(o, o.getType()).getCachedBytes(); oc.checkCommit(bin); assertHash(o, bin); } for (; ; ) { final RevObject o = ow.nextObject(); if (o == null) break; final byte[] bin = db.open(o, o.getType()).getCachedBytes(); oc.check(o.getType(), bin); assertHash(o, bin); } }
/** * Pop the next most recent object. * * @return next most recent object; null if traversal is over. * @throws MissingObjectException one or or more of the next objects are not available from the * object database, but were thought to be candidates for traversal. This usually indicates a * broken link. * @throws IncorrectObjectTypeException one or or more of the objects in a tree do not match the * type indicated. * @throws IOException a pack file or loose object could not be read. */ public RevObject nextObject() throws MissingObjectException, IncorrectObjectTypeException, IOException { if (last != null) treeWalk = last instanceof RevTree ? enter(last) : treeWalk.next(); while (!treeWalk.eof()) { final FileMode mode = treeWalk.getEntryFileMode(); switch (mode.getObjectType()) { case Constants.OBJ_BLOB: { treeWalk.getEntryObjectId(idBuffer); final RevBlob o = lookupBlob(idBuffer); if ((o.flags & SEEN) != 0) break; o.flags |= SEEN; if (shouldSkipObject(o)) break; last = o; return o; } case Constants.OBJ_TREE: { treeWalk.getEntryObjectId(idBuffer); final RevTree o = lookupTree(idBuffer); if ((o.flags & SEEN) != 0) break; o.flags |= SEEN; if (shouldSkipObject(o)) break; last = o; return o; } default: if (FileMode.GITLINK.equals(mode)) break; treeWalk.getEntryObjectId(idBuffer); throw new CorruptObjectException( MessageFormat.format( JGitText.get().corruptObjectInvalidMode3, mode, idBuffer.name(), treeWalk.getEntryPathString(), currentTree.name())); } treeWalk = treeWalk.next(); } last = null; for (; ; ) { final RevObject o = pendingObjects.next(); if (o == null) return null; if ((o.flags & SEEN) != 0) continue; o.flags |= SEEN; if (shouldSkipObject(o)) continue; if (o instanceof RevTree) { currentTree = (RevTree) o; treeWalk = treeWalk.resetRoot(db, currentTree, curs); } return o; } }
private void markCommon(final RevObject obj, final AckNackResult anr) throws IOException { if (statelessRPC && anr == AckNackResult.ACK_COMMON && !obj.has(STATE)) { StringBuilder s; s = new StringBuilder(6 + Constants.OBJECT_ID_STRING_LENGTH); s.append("have "); // $NON-NLS-1$ s.append(obj.name()); s.append('\n'); pckState.writeString(s.toString()); obj.add(STATE); } obj.add(COMMON); if (obj instanceof RevCommit) ((RevCommit) obj).carry(COMMON); }
private static byte[] getDelta(ObjectReader reader, RevObject obj) throws IOException, MissingObjectException, StoredObjectRepresentationNotAvailableException { ObjectReuseAsIs asis = (ObjectReuseAsIs) reader; ObjectToPack target = asis.newObjectToPack(obj, obj.getType()); PackWriter pw = new PackWriter(reader) { @Override public void select(ObjectToPack otp, StoredObjectRepresentation next) { otp.select(next); } }; ByteArrayOutputStream buf = new ByteArrayOutputStream(); asis.selectObjectRepresentation( pw, NullProgressMonitor.INSTANCE, Collections.singleton(target)); asis.copyObjectAsIs(new PackOutputStream(NullProgressMonitor.INSTANCE, buf, pw), target, true); // At this point the object header has no delta information, // because it was output as though it were a whole object. // Skip over the header and inflate. // byte[] bufArray = buf.toByteArray(); int ptr = 0; while ((bufArray[ptr] & 0x80) != 0) ptr++; ptr++; @SuppressWarnings("resource" /* java 7 */) TemporaryBuffer.Heap raw = new TemporaryBuffer.Heap(bufArray.length); InflaterInputStream inf = new InflaterInputStream(new ByteArrayInputStream(bufArray, ptr, bufArray.length)); raw.copy(inf); inf.close(); return raw.toByteArray(); }
/** * Mark an object to not produce in the output. * * <p>Uninteresting objects denote not just themselves but also their entire reachable chain, back * until the merge base of an uninteresting commit and an otherwise interesting commit. * * <p>Callers are encouraged to use {@link RevWalk#parseAny(AnyObjectId)} instead of {@link * RevWalk#lookupAny(AnyObjectId, int)}, as this method requires the object to be parsed before it * can be added as a root for the traversal. * * <p>The method will automatically parse an unparsed object, but error handling may be more * difficult for the application to explain why a RevObject is not actually valid. The object pool * of this walker would also be 'poisoned' by the invalid RevObject. * * <p>This method will automatically call {@link RevWalk#markStart(RevCommit)} if passed RevCommit * instance, or a RevTag that directly (or indirectly) references a RevCommit. * * @param o the object to start traversing from. The object passed must be * @throws MissingObjectException the object supplied is not available from the object database. * This usually indicates the supplied object is invalid, but the reference was constructed * during an earlier invocation to {@link RevWalk#lookupAny(AnyObjectId, int)}. * @throws IncorrectObjectTypeException the object was not parsed yet and it was discovered during * parsing that it is not actually the type of the instance passed in. This usually indicates * the caller used the wrong type in a {@link RevWalk#lookupAny(AnyObjectId, int)} call. * @throws IOException a pack file or loose object could not be read. */ public void markUninteresting(RevObject o) throws MissingObjectException, IncorrectObjectTypeException, IOException { while (o instanceof RevTag) { o.flags |= UNINTERESTING; if (hasRevSort(RevSort.BOUNDARY)) addObject(o); o = ((RevTag) o).getObject(); parseHeaders(o); } if (o instanceof RevCommit) super.markUninteresting((RevCommit) o); else if (o instanceof RevTree) markTreeUninteresting((RevTree) o); else o.flags |= UNINTERESTING; if (o.getType() != Constants.OBJ_COMMIT && hasRevSort(RevSort.BOUNDARY)) { addObject(o); } }
private static void assertHash(RevObject id, byte[] bin) { MessageDigest md = Constants.newMessageDigest(); md.update(Constants.encodedTypeString(id.getType())); md.update((byte) ' '); md.update(Constants.encodeASCII(bin.length)); md.update((byte) 0); md.update(bin); assertEquals(id, ObjectId.fromRaw(md.digest())); }
@Override protected void run() throws Exception { ObjectReader reader = db.newObjectReader(); RevObject obj = new RevWalk(reader).parseAny(objectId); byte[] delta = getDelta(reader, obj); // We're crossing our fingers that this will be a delta. Double // check the size field in the header, it should match. // long size = reader.getObjectSize(obj, obj.getType()); try { if (BinaryDelta.getResultSize(delta) != size) throw die("Object " + obj.name() + " is not a delta"); } catch (ArrayIndexOutOfBoundsException bad) { throw die("Object " + obj.name() + " is not a delta"); } outw.println(BinaryDelta.format(delta)); }
@NotNull public ConvertTask convertTask(@NotNull ObjectReader reader, @NotNull TaskKey key) throws IOException { switch (key.getType()) { case Simple: { if (!reader.has(key.getObjectId())) { return keepMissingTask(key.getObjectId()); } final RevObject revObject = new RevWalk(reader).parseAny(key.getObjectId()); if (revObject instanceof RevCommit) { return convertCommitTask((RevCommit) revObject); } if (revObject instanceof RevTree) { return convertTreeTask(reader, revObject, false); } if (revObject instanceof RevBlob) { return copyTask(reader, revObject); } if (revObject instanceof RevTag) { return convertTagTask((RevTag) revObject); } throw new IllegalStateException( "Unsupported object type: " + key + " (" + revObject.getClass().getName() + ")"); } case Root: { final RevObject revObject = new RevWalk(reader).parseAny(key.getObjectId()); if (revObject instanceof RevTree) { return convertTreeTask(reader, revObject, true); } throw new IllegalStateException( "Unsupported object type: " + key + " (" + revObject.getClass().getName() + ")"); } case Attribute: return createAttributesTask(reader, key.getObjectId()); case UploadLfs: return convertLfsTask(reader, key.getObjectId()); default: throw new IllegalStateException("Unknwon task key type: " + key.getType()); } }
protected static RevCommit resolveCommitIdByTagName(Repository repository, String tagName) throws IOException, GitAPIException { if (tagName == null || tagName.isEmpty()) return null; RevCommit revCommit = null; Map<String, Ref> tagMap = repository.getTags(); Ref ref = tagMap.get(tagName); if (ref != null) { RevWalk walk = new RevWalk(repository); // some reduce memory effors as described in jgit user guide walk.setRetainBody(false); ObjectId from; from = repository.resolve("refs/heads/master"); if (from == null) { Git git = new Git(repository); String lastTagName = git.describe().call(); from = repository.resolve("refs/tags/" + lastTagName); } ObjectId to = repository.resolve("refs/remotes/origin/master"); if (from == null) { throw new IllegalStateException("cannot determinate start commit"); } walk.markStart(walk.parseCommit(from)); walk.markUninteresting(walk.parseCommit(to)); try { RevObject revObject = walk.parseAny(ref.getObjectId()); if (revObject != null) { revCommit = walk.parseCommit(revObject.getId()); } } finally { walk.close(); } } return revCommit; }
private void checkConnectivity() throws IOException { ObjectIdSubclassMap<ObjectId> baseObjects = null; ObjectIdSubclassMap<ObjectId> providedObjects = null; if (checkReferencedIsReachable) { baseObjects = parser.getBaseObjectIds(); providedObjects = parser.getNewObjectIds(); } parser = null; final ObjectWalk ow = new ObjectWalk(db); ow.setRetainBody(false); if (checkReferencedIsReachable) { ow.sort(RevSort.TOPO); if (!baseObjects.isEmpty()) ow.sort(RevSort.BOUNDARY, true); } for (final ReceiveCommand cmd : commands) { if (cmd.getResult() != Result.NOT_ATTEMPTED) continue; if (cmd.getType() == ReceiveCommand.Type.DELETE) continue; ow.markStart(ow.parseAny(cmd.getNewId())); } for (final ObjectId have : advertisedHaves) { RevObject o = ow.parseAny(have); ow.markUninteresting(o); if (checkReferencedIsReachable && !baseObjects.isEmpty()) { o = ow.peel(o); if (o instanceof RevCommit) o = ((RevCommit) o).getTree(); if (o instanceof RevTree) ow.markUninteresting(o); } } RevCommit c; while ((c = ow.next()) != null) { if (checkReferencedIsReachable // && !c.has(RevFlag.UNINTERESTING) // && !providedObjects.contains(c)) throw new MissingObjectException(c, Constants.TYPE_COMMIT); } RevObject o; while ((o = ow.nextObject()) != null) { if (o.has(RevFlag.UNINTERESTING)) continue; if (checkReferencedIsReachable) { if (providedObjects.contains(o)) continue; else throw new MissingObjectException(o, o.getType()); } if (o instanceof RevBlob && !db.hasObject(o)) throw new MissingObjectException(o, Constants.TYPE_BLOB); } if (checkReferencedIsReachable) { for (ObjectId id : baseObjects) { o = ow.parseAny(id); if (!o.has(RevFlag.UNINTERESTING)) throw new MissingObjectException(o, o.getType()); } } }
private void addObject(final RevObject o) { if ((o.flags & IN_PENDING) == 0) { o.flags |= IN_PENDING; pendingObjects.add(o); } }