001: /*
002: * ====================================================================
003: * Copyright (c) 2004-2008 TMate Software Ltd. All rights reserved.
004: *
005: * This software is licensed as described in the file COPYING, which
006: * you should have received as part of this distribution. The terms
007: * are also available at http://svnkit.com/license.html
008: * If newer versions of this license are posted there, you may use a
009: * newer version instead, at your option.
010: * ====================================================================
011: */
012: package org.tmatesoft.svn.core.internal.io.fs;
013:
014: import java.io.IOException;
015: import java.nio.ByteBuffer;
016: import java.nio.charset.CharacterCodingException;
017: import java.nio.charset.Charset;
018: import java.nio.charset.CharsetDecoder;
019: import java.util.Map;
020:
021: import org.tmatesoft.svn.core.SVNErrorCode;
022: import org.tmatesoft.svn.core.SVNErrorMessage;
023: import org.tmatesoft.svn.core.SVNException;
024: import org.tmatesoft.svn.core.internal.wc.SVNErrorManager;
025:
026: /**
027: * @version 1.1.1
028: * @author TMate Software Ltd.
029: */
030: public class FSRevisionRoot extends FSRoot {
031: private long myRevision;
032: private long myRootOffset;
033: private long myChangesOffset;
034:
035: public FSRevisionRoot(FSFS owner, long revision) {
036: super (owner);
037: myRevision = revision;
038: myRootOffset = -1;
039: myChangesOffset = -1;
040: }
041:
042: public long getRevision() {
043: return myRevision;
044: }
045:
046: public Map getChangedPaths() throws SVNException {
047: FSFile file = getOwner().getRevisionFile(getRevision());
048: loadOffsets(file);
049: try {
050: file.seek(myChangesOffset);
051: return fetchAllChanges(file, true);
052: } finally {
053: file.close();
054: }
055: }
056:
057: public FSCopyInheritance getCopyInheritance(FSParentPath child)
058: throws SVNException {
059: return null;
060: }
061:
062: public FSRevisionNode getRootRevisionNode() throws SVNException {
063: if (myRootRevisionNode == null) {
064: FSFile file = getOwner().getRevisionFile(getRevision());
065: try {
066: loadOffsets(file);
067: file.seek(myRootOffset);
068: Map headers = file.readHeader();
069: myRootRevisionNode = FSRevisionNode.fromMap(headers);
070: } finally {
071: file.close();
072: }
073: }
074: return myRootRevisionNode;
075: }
076:
077: private void loadOffsets(FSFile file) throws SVNException {
078: if (myRootOffset >= 0) {
079: return;
080: }
081: ByteBuffer buffer = ByteBuffer.allocate(64);
082: file.seek(file.size() - 64);
083: try {
084: file.read(buffer);
085: } catch (IOException e) {
086: }
087: buffer.flip();
088: if (buffer.get(buffer.limit() - 1) != '\n') {
089: SVNErrorMessage err = SVNErrorMessage.create(
090: SVNErrorCode.FS_CORRUPT,
091: "Revision file lacks trailing newline");
092: SVNErrorManager.error(err);
093: }
094: int spaceIndex = -1;
095: int eolIndex = -1;
096: for (int i = buffer.limit() - 2; i >= 0; i--) {
097: byte b = buffer.get(i);
098: if (b == ' ' && spaceIndex < 0) {
099: spaceIndex = i;
100: } else if (b == '\n' && eolIndex < 0) {
101: eolIndex = i;
102: break;
103: }
104: }
105: if (eolIndex < 0) {
106: SVNErrorMessage err = SVNErrorMessage
107: .create(SVNErrorCode.FS_CORRUPT,
108: "Final line in revision file longer than 64 characters");
109: SVNErrorManager.error(err);
110: }
111: if (spaceIndex < 0) {
112: SVNErrorMessage err = SVNErrorMessage.create(
113: SVNErrorCode.FS_CORRUPT,
114: "Final line in revision file missing space");
115: SVNErrorManager.error(err);
116: }
117: CharsetDecoder decoder = Charset.forName("UTF-8").newDecoder();
118: try {
119: buffer.limit(buffer.limit() - 1);
120: buffer.position(spaceIndex + 1);
121: String line = decoder.decode(buffer).toString();
122: myChangesOffset = Long.parseLong(line);
123:
124: buffer.limit(spaceIndex);
125: buffer.position(eolIndex + 1);
126: line = decoder.decode(buffer).toString();
127: myRootOffset = Long.parseLong(line);
128: } catch (NumberFormatException nfe) {
129: SVNErrorMessage err = SVNErrorMessage
130: .create(SVNErrorCode.FS_CORRUPT,
131: "Final line in revision file missing changes and root offsets");
132: SVNErrorManager.error(err, nfe);
133: } catch (CharacterCodingException e) {
134: SVNErrorMessage err = SVNErrorMessage
135: .create(SVNErrorCode.FS_CORRUPT,
136: "Final line in revision file missing changes and root offsets");
137: SVNErrorManager.error(err, e);
138: }
139: }
140:
141: }
|