public static void getManifestChangeLog(ExternalRefs.Reference latestRef,
                                            Archive archive,
                                            ArchiveResolver resolver,
                                            ChangeLogCallback callback) throws IOException {

        if (archive.getRootObject(RootObjectKind.FILE_MANIFEST).isNullDigest()) {
            throw new IOException("No FILE_MANIFEST in root objects: " +
                                  latestRef.toString());
        }

        Map<String, LinkDigest> currentMap = FileManifest.fromArchiveRootObject(archive).getMap();
        ExternalRefs.Reference currentRef = latestRef;
        while (currentRef != ExternalRefs.NULL_ARCHIVE) {
            ExternalRefs.Reference nextRef = ExternalRefs.NULL_ARCHIVE;
            Map<String, LinkDigest> nextMap = new HashMap<String, LinkDigest>();

            LinkDigest digest = archive.getRootObject(RootObjectKind.PARENT_REFERENCES);
            if (!digest.isNullDigest()) {
                ExternalRefs refs = ExternalRefs.fromBytes(archive.getFile(digest));

                if (refs.mRefs.size() > 1) {
                    throw new IOException("Code too dumb to deal with multiple parents. Sorry :-(");
                }

                if (refs.mRefs.size() > 0) {
                    nextRef = refs.mRefs.get(0);
                    archive = resolver.resolve(nextRef);

                    if (archive.getRootObject(RootObjectKind.FILE_MANIFEST).isNullDigest()) {
                        throw new IOException("No FILE_MANIFEST in root objects: " +
                                              nextRef.toString());
                    }

                    nextMap = FileManifest.fromArchiveRootObject(archive).getMap();
                }
            }

            if (!callback.onChangeEntry(currentRef, nextRef, FileManifest.diff(nextMap, currentMap))) {
                break; // Client code told us to give up.
            }

            currentRef = nextRef;
            currentMap = nextMap;
        }
    }