kitaev@213: /* kitaev@213: * Copyright (c) 2010-2011 TMate Software Ltd kitaev@213: * kitaev@213: * This program is free software; you can redistribute it and/or modify kitaev@213: * it under the terms of the GNU General Public License as published by kitaev@213: * the Free Software Foundation; version 2 of the License. kitaev@213: * kitaev@213: * This program is distributed in the hope that it will be useful, kitaev@213: * but WITHOUT ANY WARRANTY; without even the implied warranty of kitaev@213: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the kitaev@213: * GNU General Public License for more details. kitaev@213: * kitaev@213: * For information on how to redistribute this software under kitaev@213: * the terms of a license other than GNU General Public License kitaev@213: * contact TMate Software at support@hg4j.com kitaev@213: */ kitaev@213: package org.tmatesoft.hg.repo; kitaev@213: kitaev@213: import java.io.IOException; kitaev@213: kitaev@213: import org.tmatesoft.hg.core.HgBadStateException; kitaev@213: import org.tmatesoft.hg.core.Nodeid; kitaev@213: import org.tmatesoft.hg.internal.DataAccess; kitaev@213: import org.tmatesoft.hg.internal.Pool; kitaev@213: import org.tmatesoft.hg.internal.RevlogStream; kitaev@213: kitaev@213: kitaev@213: /** kitaev@213: * kitaev@213: * @author Artem Tikhomirov kitaev@213: * @author TMate Software Ltd. kitaev@213: */ kitaev@213: public class HgManifest extends Revlog { kitaev@213: kitaev@213: /*package-local*/ HgManifest(HgRepository hgRepo, RevlogStream content) { kitaev@213: super(hgRepo, content); kitaev@213: } kitaev@213: kitaev@213: public void walk(int start, int end, final Inspector inspector) { kitaev@213: if (inspector == null) { kitaev@213: throw new IllegalArgumentException(); kitaev@213: } kitaev@213: content.iterate(start, end, true, new ManifestParser(inspector)); kitaev@213: } kitaev@213: kitaev@213: public interface Inspector { kitaev@213: boolean begin(int revision, Nodeid nid); kitaev@213: boolean next(Nodeid nid, String fname, String flags); kitaev@213: boolean end(int revision); kitaev@213: } kitaev@213: kitaev@213: private static class ManifestParser implements RevlogStream.Inspector { kitaev@213: private boolean gtg = true; // good to go kitaev@213: private final Inspector inspector; kitaev@213: private final Pool nodeidPool; kitaev@213: private final Pool fnamePool; kitaev@213: private final Pool flagsPool; kitaev@213: kitaev@213: public ManifestParser(Inspector delegate) { kitaev@213: assert delegate != null; kitaev@213: inspector = delegate; kitaev@213: nodeidPool = new Pool(); kitaev@213: fnamePool = new Pool(); kitaev@213: flagsPool = new Pool(); kitaev@213: } kitaev@213: kitaev@213: public void next(int revisionNumber, int actualLen, int baseRevision, int linkRevision, int parent1Revision, int parent2Revision, byte[] nodeid, DataAccess da) { kitaev@213: if (!gtg) { kitaev@213: return; kitaev@213: } kitaev@213: try { kitaev@213: gtg = gtg && inspector.begin(revisionNumber, new Nodeid(nodeid, true)); kitaev@213: int i; kitaev@213: String fname = null; kitaev@213: String flags = null; kitaev@213: Nodeid nid = null; kitaev@213: byte[] data = da.byteArray(); kitaev@213: for (i = 0; gtg && i < actualLen; i++) { kitaev@213: int x = i; kitaev@213: for( ; data[i] != '\n' && i < actualLen; i++) { kitaev@213: if (fname == null && data[i] == 0) { kitaev@213: fname = fnamePool.unify(new String(data, x, i - x)); kitaev@213: x = i+1; kitaev@213: } kitaev@213: } kitaev@213: if (i < actualLen) { kitaev@213: assert data[i] == '\n'; kitaev@213: int nodeidLen = i - x < 40 ? i-x : 40; kitaev@213: nid = nodeidPool.unify(Nodeid.fromAscii(data, x, nodeidLen)); kitaev@213: if (nodeidLen + x < i) { kitaev@213: // 'x' and 'l' for executable bits and symlinks? kitaev@213: // hg --debug manifest shows 644 for each regular file in my repo kitaev@213: flags = flagsPool.unify(new String(data, x + nodeidLen, i-x-nodeidLen)); kitaev@213: } kitaev@213: gtg = gtg && inspector.next(nid, fname, flags); kitaev@213: } kitaev@213: nid = null; kitaev@213: fname = flags = null; kitaev@213: } kitaev@213: gtg = gtg && inspector.end(revisionNumber); kitaev@213: } catch (IOException ex) { kitaev@213: throw new HgBadStateException(ex); kitaev@213: } kitaev@213: } kitaev@213: } kitaev@213: }