tikhomirov@10: /* tikhomirov@10: * Copyright (c) 2010 Artem Tikhomirov tikhomirov@10: */ tikhomirov@10: package com.tmate.hgkit.ll; tikhomirov@10: tikhomirov@10: import java.io.File; tikhomirov@10: import java.io.IOException; tikhomirov@10: import java.util.Collections; tikhomirov@10: import java.util.LinkedList; tikhomirov@10: import java.util.List; tikhomirov@10: tikhomirov@10: import com.tmate.hgkit.fs.DataAccess; tikhomirov@10: import com.tmate.hgkit.fs.DataAccessProvider; tikhomirov@10: tikhomirov@10: /** tikhomirov@10: * @see http://mercurial.selenic.com/wiki/DirState tikhomirov@10: * @see http://mercurial.selenic.com/wiki/FileFormats#dirstate tikhomirov@10: * @author artem tikhomirov@10: */ tikhomirov@10: public class HgDirstate { tikhomirov@10: tikhomirov@10: private final LocalHgRepo repo; tikhomirov@10: private final File dirstateFile; tikhomirov@10: private List normal; tikhomirov@10: private List added; tikhomirov@10: private List removed; tikhomirov@10: private List merged; tikhomirov@10: tikhomirov@10: public HgDirstate(LocalHgRepo hgRepo, File dirstate) { tikhomirov@10: this.repo = hgRepo; tikhomirov@10: this.dirstateFile = dirstate; tikhomirov@10: } tikhomirov@10: tikhomirov@10: private void read() { tikhomirov@10: normal = added = removed = merged = Collections.emptyList(); tikhomirov@10: if (!dirstateFile.exists()) { tikhomirov@10: return; tikhomirov@10: } tikhomirov@10: DataAccessProvider dap = repo.getDataAccess(); tikhomirov@10: DataAccess da = dap.create(dirstateFile); tikhomirov@10: if (da.isEmpty()) { tikhomirov@10: return; tikhomirov@10: } tikhomirov@10: normal = new LinkedList(); tikhomirov@10: added = new LinkedList(); tikhomirov@10: removed = new LinkedList(); tikhomirov@10: merged = new LinkedList(); tikhomirov@10: try { tikhomirov@10: // XXX skip(40) if we don't need these? tikhomirov@10: byte[] parents = new byte[40]; tikhomirov@10: da.readBytes(parents, 0, 40); tikhomirov@10: parents = null; tikhomirov@10: do { tikhomirov@10: final byte state = da.readByte(); tikhomirov@10: final int fmode = da.readInt(); tikhomirov@10: final int size = da.readInt(); tikhomirov@10: final int time = da.readInt(); tikhomirov@10: final int nameLen = da.readInt(); tikhomirov@10: String fn1 = null, fn2 = null; tikhomirov@10: byte[] name = new byte[nameLen]; tikhomirov@10: da.readBytes(name, 0, nameLen); tikhomirov@10: for (int i = 0; i < nameLen; i++) { tikhomirov@10: if (name[i] == 0) { tikhomirov@11: fn1 = new String(name, 0, i, "UTF-8"); // XXX unclear from documentation what encoding is used there tikhomirov@11: fn2 = new String(name, i+1, nameLen - i - 1, "UTF-8"); // need to check with different system codepages tikhomirov@10: break; tikhomirov@10: } tikhomirov@10: } tikhomirov@10: if (fn1 == null) { tikhomirov@10: fn1 = new String(name); tikhomirov@10: } tikhomirov@10: Record r = new Record(fmode, size, time, fn1, fn2); tikhomirov@10: if (state == 'n') { tikhomirov@10: normal.add(r); tikhomirov@10: } else if (state == 'a') { tikhomirov@10: added.add(r); tikhomirov@10: } else if (state == 'r') { tikhomirov@10: removed.add(r); tikhomirov@10: } else if (state == 'm') { tikhomirov@10: merged.add(r); tikhomirov@10: } else { tikhomirov@10: // FIXME log error? tikhomirov@10: } tikhomirov@10: } while (!da.isEmpty()); tikhomirov@10: } catch (IOException ex) { tikhomirov@10: ex.printStackTrace(); // FIXME log error, clean dirstate? tikhomirov@10: } finally { tikhomirov@10: da.done(); tikhomirov@10: } tikhomirov@10: } tikhomirov@10: tikhomirov@10: public void dump() { tikhomirov@10: read(); tikhomirov@10: @SuppressWarnings("unchecked") tikhomirov@10: List[] all = new List[] { normal, added, removed, merged }; tikhomirov@10: char[] x = new char[] {'n', 'a', 'r', 'm' }; tikhomirov@10: for (int i = 0; i < all.length; i++) { tikhomirov@10: for (Record r : all[i]) { tikhomirov@10: System.out.printf("%c %3o%6d %30tc\t\t%s", x[i], r.mode, r.size, (long) r.time, r.name1); tikhomirov@10: if (r.name2 != null) { tikhomirov@10: System.out.printf(" --> %s", r.name2); tikhomirov@10: } tikhomirov@10: System.out.println(); tikhomirov@10: } tikhomirov@10: System.out.println(); tikhomirov@10: } tikhomirov@10: } tikhomirov@10: tikhomirov@10: private static class Record { tikhomirov@10: final int mode; tikhomirov@10: final int size; tikhomirov@10: final int time; tikhomirov@10: final String name1; tikhomirov@10: final String name2; tikhomirov@10: tikhomirov@10: public Record(int fmode, int fsize, int ftime, String name1, String name2) { tikhomirov@10: mode = fmode; tikhomirov@10: size = fsize; tikhomirov@10: time = ftime; tikhomirov@10: this.name1 = name1; tikhomirov@10: this.name2 = name2; tikhomirov@10: tikhomirov@10: } tikhomirov@10: } tikhomirov@10: }