Mercurial > hg4j
diff src/org/tmatesoft/hg/repo/HgDirstate.java @ 526:2f9ed6bcefa2
Initial support for Revert command with accompanying minor refactoring
author | Artem Tikhomirov <tikhomirov.artem@gmail.com> |
---|---|
date | Tue, 15 Jan 2013 17:07:19 +0100 |
parents | 0be5be8d57e9 |
children |
line wrap: on
line diff
--- a/src/org/tmatesoft/hg/repo/HgDirstate.java Fri Jan 11 18:12:39 2013 +0100 +++ b/src/org/tmatesoft/hg/repo/HgDirstate.java Tue Jan 15 17:07:19 2013 +0100 @@ -16,15 +16,6 @@ */ package org.tmatesoft.hg.repo; -import static org.tmatesoft.hg.core.Nodeid.NULL; -import static org.tmatesoft.hg.repo.HgRepositoryFiles.Dirstate; -import static org.tmatesoft.hg.util.LogFacility.Severity.Debug; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileReader; -import java.io.IOException; import java.util.Collections; import java.util.HashMap; import java.util.LinkedHashMap; @@ -32,13 +23,11 @@ import java.util.TreeSet; import org.tmatesoft.hg.core.Nodeid; -import org.tmatesoft.hg.internal.DataAccess; -import org.tmatesoft.hg.internal.EncodingHelper; +import org.tmatesoft.hg.internal.DirstateReader; import org.tmatesoft.hg.internal.Internals; import org.tmatesoft.hg.util.Pair; import org.tmatesoft.hg.util.Path; import org.tmatesoft.hg.util.PathRewrite; -import org.tmatesoft.hg.util.LogFacility.Severity; /** @@ -75,7 +64,6 @@ } /*package-local*/ void read() throws HgInvalidControlFileException { - EncodingHelper encodingHelper = repo.buildFileNameEncodingHelper(); normal = added = removed = merged = Collections.<Path, Record>emptyMap(); parents = new Pair<Nodeid,Nodeid>(Nodeid.NULL, Nodeid.NULL); if (canonicalPathRewrite != null) { @@ -83,87 +71,45 @@ } else { canonical2dirstateName = Collections.emptyMap(); } - File dirstateFile = getDirstateFile(repo); - if (dirstateFile == null || !dirstateFile.exists()) { - return; - } - DataAccess da = repo.getDataAccess().create(dirstateFile); - try { - if (da.isEmpty()) { - return; - } - // not sure linked is really needed here, just for ease of debug - normal = new LinkedHashMap<Path, Record>(); - added = new LinkedHashMap<Path, Record>(); - removed = new LinkedHashMap<Path, Record>(); - merged = new LinkedHashMap<Path, Record>(); + // not sure linked is really needed here, just for ease of debug + normal = new LinkedHashMap<Path, Record>(); + added = new LinkedHashMap<Path, Record>(); + removed = new LinkedHashMap<Path, Record>(); + merged = new LinkedHashMap<Path, Record>(); + + DirstateReader dirstateReader = new DirstateReader(repo, pathPool); + dirstateReader.readInto(new Inspector() { - parents = internalReadParents(da); - // hg init; hg up produces an empty repository where dirstate has parents (40 bytes) only - while (!da.isEmpty()) { - final byte state = da.readByte(); - final int fmode = da.readInt(); - final int size = da.readInt(); - final int time = da.readInt(); - final int nameLen = da.readInt(); - String fn1 = null, fn2 = null; - byte[] name = new byte[nameLen]; - da.readBytes(name, 0, nameLen); - for (int i = 0; i < nameLen; i++) { - if (name[i] == 0) { - fn1 = encodingHelper.fromDirstate(name, 0, i); - fn2 = encodingHelper.fromDirstate(name, i+1, nameLen - i - 1); - break; - } - } - if (fn1 == null) { - fn1 = encodingHelper.fromDirstate(name, 0, nameLen); - } - Record r = new Record(fmode, size, time, pathPool.path(fn1), fn2 == null ? null : pathPool.path(fn2)); + public boolean next(EntryKind kind, Record r) { if (canonicalPathRewrite != null) { - Path canonicalPath = pathPool.path(canonicalPathRewrite.rewrite(fn1).toString()); + Path canonicalPath = pathPool.path(canonicalPathRewrite.rewrite(r.name())); if (canonicalPath != r.name()) { // == as they come from the same pool assert !canonical2dirstateName.containsKey(canonicalPath); // otherwise there's already a file with same canonical name // which can't happen for case-insensitive file system (or there's erroneous PathRewrite, perhaps doing smth else) canonical2dirstateName.put(canonicalPath, r.name()); } - if (fn2 != null) { + if (r.copySource() != null) { // not sure I need copy origin in the map, I don't seem to use it anywhere, // but I guess I'll have to use it some day. - canonicalPath = pathPool.path(canonicalPathRewrite.rewrite(fn2).toString()); + canonicalPath = pathPool.path(canonicalPathRewrite.rewrite(r.copySource())); if (canonicalPath != r.copySource()) { canonical2dirstateName.put(canonicalPath, r.copySource()); } } } - if (state == 'n') { - normal.put(r.name1, r); - } else if (state == 'a') { - added.put(r.name1, r); - } else if (state == 'r') { - removed.put(r.name1, r); - } else if (state == 'm') { - merged.put(r.name1, r); - } else { - repo.getSessionContext().getLog().dump(getClass(), Severity.Warn, "Dirstate record for file %s (size: %d, tstamp:%d) has unknown state '%c'", r.name1, r.size(), r.time, state); + switch (kind) { + case Normal : normal.put(r.name(), r); break; + case Added : added.put(r.name(), r); break; + case Removed : removed.put(r.name(), r); break; + case Merged : merged.put(r.name1, r); break; + default: throw new HgInvalidStateException(String.format("Unexpected entry in the dirstate: %s", kind)); } + return true; } - } catch (IOException ex) { - throw new HgInvalidControlFileException("Dirstate read failed", ex, dirstateFile); - } finally { - da.done(); - } + }); + parents = dirstateReader.parents(); } - private static Pair<Nodeid, Nodeid> internalReadParents(DataAccess da) throws IOException { - byte[] parents = new byte[40]; - da.readBytes(parents, 0, 40); - Nodeid n1 = Nodeid.fromBinary(parents, 0); - Nodeid n2 = Nodeid.fromBinary(parents, 20); - parents = null; - return new Pair<Nodeid, Nodeid>(n1, n2); - } - /** * @return pair of working copy parents, with {@link Nodeid#NULL} for missing values. */ @@ -172,58 +118,6 @@ return parents; } - private static File getDirstateFile(Internals repo) { - return repo.getFileFromRepoDir(Dirstate.getName()); - } - - /** - * @return pair of parents, both {@link Nodeid#NULL} if dirstate is not available - */ - /*package-local*/ static Pair<Nodeid, Nodeid> readParents(Internals internalRepo) throws HgInvalidControlFileException { - // do not read whole dirstate if all we need is WC parent information - File dirstateFile = getDirstateFile(internalRepo); - if (dirstateFile == null || !dirstateFile.exists()) { - return new Pair<Nodeid,Nodeid>(NULL, NULL); - } - DataAccess da = internalRepo.getDataAccess().create(dirstateFile); - try { - if (da.isEmpty()) { - return new Pair<Nodeid,Nodeid>(NULL, NULL); - } - return internalReadParents(da); - } catch (IOException ex) { - throw new HgInvalidControlFileException("Error reading working copy parents from dirstate", ex, dirstateFile); - } finally { - da.done(); - } - } - - /** - * TODO [post-1.0] it's really not a proper place for the method, need WorkingCopyContainer or similar - * @return branch associated with the working directory - */ - /*package-local*/ static String readBranch(Internals internalRepo) throws HgInvalidControlFileException { - File branchFile = internalRepo.getFileFromRepoDir("branch"); - String branch = HgRepository.DEFAULT_BRANCH_NAME; - if (branchFile.exists()) { - try { - BufferedReader r = new BufferedReader(new FileReader(branchFile)); - String b = r.readLine(); - if (b != null) { - b = b.trim().intern(); - } - branch = b == null || b.length() == 0 ? HgRepository.DEFAULT_BRANCH_NAME : b; - r.close(); - } catch (FileNotFoundException ex) { - internalRepo.getSessionContext().getLog().dump(HgDirstate.class, Debug, ex, null); // log verbose debug, exception might be legal here - // IGNORE - } catch (IOException ex) { - throw new HgInvalidControlFileException("Error reading file with branch information", ex, branchFile); - } - } - return branch; - } - // new, modifiable collection /*package-local*/ TreeSet<Path> all() { assert normal != null;