tikhomirov@36: /* tikhomirov@36: * Copyright (c) 2011 Artem Tikhomirov tikhomirov@36: */ tikhomirov@36: package com.tmate.hgkit.ll; tikhomirov@36: tikhomirov@36: import java.io.File; tikhomirov@36: import java.io.IOException; tikhomirov@36: import java.util.LinkedList; tikhomirov@36: import java.util.List; tikhomirov@36: tikhomirov@36: import com.tmate.hgkit.fs.DataAccess; tikhomirov@36: import com.tmate.hgkit.fs.DataAccessProvider; tikhomirov@36: tikhomirov@36: /** tikhomirov@36: * @see http://mercurial.selenic.com/wiki/BundleFormat tikhomirov@36: * tikhomirov@36: * @author artem tikhomirov@36: */ tikhomirov@36: public class HgBundle { tikhomirov@36: tikhomirov@36: private final File bundleFile; tikhomirov@36: private final DataAccessProvider accessProvider; tikhomirov@36: tikhomirov@36: public HgBundle(DataAccessProvider dap, File bundle) { tikhomirov@36: accessProvider = dap; tikhomirov@36: bundleFile = bundle; tikhomirov@36: } tikhomirov@36: tikhomirov@36: public void read() throws IOException { tikhomirov@36: DataAccess da = accessProvider.create(bundleFile); tikhomirov@36: try { tikhomirov@36: LinkedList names = new LinkedList(); tikhomirov@36: if (!da.isEmpty()) { tikhomirov@36: System.out.println("Changelog group"); tikhomirov@36: List changelogGroup = readGroup(da); tikhomirov@36: for (GroupElement ge : changelogGroup) { tikhomirov@36: System.out.printf(" %s %s %s %s; patches:%d\n", ge.node(), ge.firstParent(), ge.secondParent(), ge.cs(), ge.patches.size()); tikhomirov@36: } tikhomirov@36: System.out.println("Manifest group"); tikhomirov@36: List manifestGroup = readGroup(da); tikhomirov@36: for (GroupElement ge : manifestGroup) { tikhomirov@36: System.out.printf(" %s %s %s %s; patches:%d\n", ge.node(), ge.firstParent(), ge.secondParent(), ge.cs(), ge.patches.size()); tikhomirov@36: } tikhomirov@36: while (!da.isEmpty()) { tikhomirov@36: int fnameLen = da.readInt(); tikhomirov@36: if (fnameLen <= 4) { tikhomirov@36: break; // null chunk, the last one. tikhomirov@36: } tikhomirov@36: byte[] fname = new byte[fnameLen - 4]; tikhomirov@36: da.readBytes(fname, 0, fname.length); tikhomirov@36: names.add(new String(fname)); tikhomirov@36: List fileGroup = readGroup(da); tikhomirov@36: System.out.println(names.getLast()); tikhomirov@36: for (GroupElement ge : fileGroup) { tikhomirov@36: System.out.printf(" %s %s %s %s; patches:%d\n", ge.node(), ge.firstParent(), ge.secondParent(), ge.cs(), ge.patches.size()); tikhomirov@36: } tikhomirov@36: } tikhomirov@36: } tikhomirov@36: System.out.println(names.size()); tikhomirov@36: for (String s : names) { tikhomirov@36: System.out.println(s); tikhomirov@36: } tikhomirov@36: } finally { tikhomirov@36: da.done(); tikhomirov@36: } tikhomirov@36: } tikhomirov@36: tikhomirov@36: private static List readGroup(DataAccess da) throws IOException { tikhomirov@36: int len = da.readInt(); tikhomirov@36: LinkedList rv = new LinkedList(); tikhomirov@36: while (len > 4 && !da.isEmpty()) { tikhomirov@36: byte[] nb = new byte[80]; tikhomirov@36: da.readBytes(nb, 0, 80); tikhomirov@36: int dataLength = len-84; tikhomirov@36: LinkedList patches = new LinkedList(); tikhomirov@36: while (dataLength > 0) { tikhomirov@36: RevlogStream.PatchRecord pr = RevlogStream.PatchRecord.read(da); tikhomirov@36: patches.add(pr); tikhomirov@36: dataLength -= pr.len + 12; tikhomirov@36: } tikhomirov@36: rv.add(new GroupElement(nb, patches)); tikhomirov@36: len = da.isEmpty() ? 0 : da.readInt(); tikhomirov@36: } tikhomirov@36: return rv; tikhomirov@36: } tikhomirov@36: tikhomirov@36: static class GroupElement { tikhomirov@36: private byte[] header; // byte[80] takes 120 bytes, 4 Nodeids - 192 tikhomirov@36: private List patches; tikhomirov@36: tikhomirov@36: GroupElement(byte[] fourNodeids, List patchList) { tikhomirov@36: assert fourNodeids != null && fourNodeids.length == 80; tikhomirov@36: // patchList.size() > 0 tikhomirov@36: header = fourNodeids; tikhomirov@36: patches = patchList; tikhomirov@36: } tikhomirov@36: public Nodeid node() { tikhomirov@36: return Nodeid.fromBinary(header, 0); tikhomirov@36: } tikhomirov@36: public Nodeid firstParent() { tikhomirov@36: return Nodeid.fromBinary(header, 20); tikhomirov@36: } tikhomirov@36: public Nodeid secondParent() { tikhomirov@36: return Nodeid.fromBinary(header, 40); tikhomirov@36: } tikhomirov@36: public Nodeid cs() { tikhomirov@36: return Nodeid.fromBinary(header, 60); tikhomirov@36: } tikhomirov@36: tikhomirov@36: } tikhomirov@36: }