package com.perforce.cvs.asset; import java.util.ArrayList; import java.util.Collections; import java.util.List; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.perforce.common.asset.AssetWriter; import com.perforce.config.CFG; import com.perforce.config.Config; import com.perforce.cvs.parser.RcsDeltaAction; import com.perforce.cvs.parser.RcsReader; import com.perforce.cvs.parser.rcstypes.RcsObjectBlock; import com.perforce.cvs.parser.rcstypes.RcsObjectDelta; import com.perforce.cvs.parser.rcstypes.RcsObjectNum; import com.perforce.cvs.parser.rcstypes.RcsObjectNumList; import com.perforce.svn.parser.Content; public class CvsContentReader { private static Logger logger = LoggerFactory .getLogger(CvsContentReader.class); private RcsReader rcsDelta; private RcsObjectNum rcsHEAD; private RcsObjectBlock rcsBlock; public CvsContentReader(RcsReader rcs) { this.rcsDelta = rcs; this.rcsHEAD = rcs.getAdmin().getID(); RcsObjectDelta deltaHEAD = rcs.getDelta(rcsHEAD); this.rcsBlock = deltaHEAD.getBlock(); } public RcsObjectBlock xxxgetContent(RcsObjectNum rcs) throws Exception { RcsObjectDelta deltaNow = rcsDelta.getDelta(rcsHEAD); RcsObjectBlock blockFull = deltaNow.getBlock(); while (deltaNow.getNext() != null && !rcs.equals(rcsHEAD)) { RcsObjectNum rcsNEXT = deltaNow.getNext(); RcsObjectDelta deltaNext = rcsDelta.getDelta(rcsNEXT); RcsObjectBlock blockNext = deltaNext.getBlock(); if (logger.isTraceEnabled()) { logger.trace("undelta rev: " + rcsNEXT); } blockFull = undelta(blockFull, blockNext); if (rcsNEXT.equals(rcs)) { break; } else { deltaNow = deltaNext; } } return blockFull; } /** * Writes out all RCS text revisions in full. Stores the text content in a * temporary directory, using the RCS id as a file name. * * @param id * @throws Exception */ public void cacheContent() throws Exception { cacheContent(rcsHEAD, rcsHEAD, this.rcsBlock); } /** * [RECURSIVE] * * @param id * @throws Exception */ private void cacheContent(RcsObjectNum id, RcsObjectNum last, RcsObjectBlock fullBlock) throws Exception { RcsObjectBlock lastBlock = new RcsObjectBlock(fullBlock); do { if (logger.isTraceEnabled()) { logger.trace("processing: " + last + " > " + id); } RcsObjectDelta delta = rcsDelta.getDelta(id); // undelta text; skip HEAD as it is already in full text if (!rcsHEAD.equals(id)) { RcsObjectBlock blockDelta = delta.getBlock(); lastBlock = undelta(lastBlock, blockDelta); } // build tmp path from rev id and base path String tmp = (String) Config.get(CFG.CVS_TMPDIR); String base = rcsDelta.getPath(); String path = tmp + "/" + base + "/" + id; // write blockFull to tmp file AssetWriter asset = new AssetWriter(path); Content content = new Content(lastBlock); asset.write(content); // recurse on branches RcsObjectNumList tags = delta.getBranches(); if (!tags.isEmpty()) { for (RcsObjectNum tag : tags.getList()) { cacheContent(tag, id, lastBlock); } } last = id; id = delta.getNext(); } while (id != null); } private List<RcsDeltaAction> parse(RcsObjectBlock delta) throws Exception { List<RcsDeltaAction> list = new ArrayList<RcsDeltaAction>(); RcsDeltaAction last = null; for (String d : delta) { RcsDeltaAction act = new RcsDeltaAction(d); switch (act.getAction()) { case ADD: case DELETE: list.add(act); last = act; break; case TEXT: last.addLine(d); break; default: StringBuffer sb = new StringBuffer(); sb.append("unknown type: " + act.getAction()); logger.error(sb.toString()); throw new Exception(sb.toString()); } } return list; } /** * Rebuilds the delta given the full file * * @param full * @param delta * @return * @throws Exception */ private RcsObjectBlock undelta(RcsObjectBlock full, RcsObjectBlock delta) throws Exception { List<RcsDeltaAction> list = parse(delta); // Apply deltas in reverse order to preserve index references Collections.reverse(list); for (RcsDeltaAction d : list) { switch (d.getAction()) { case ADD: full.insert(d.getLine(), d.getBlock()); break; case DELETE: full.remove(d.getLine(), d.getLength()); break; default: StringBuffer sb = new StringBuffer(); sb.append("unknown type: " + d.getAction()); logger.error(sb.toString()); throw new Exception(sb.toString()); } } // full.clean(); if (logger.isTraceEnabled()) { logger.trace("result: " + full); } return full; } }
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#8 | 13920 | Paul Allen | copy part 2 (no errors) | ||
#7 | 11745 | Paul Allen |
CVS: Parse non-standard RCS file, where 'log' and 'text' are on the same line. Support alternative delete method - added test case 054 to support parse changes - added test case 055 to support alternatice delete method |
||
#6 | 11453 | Paul Allen |
CVS: Write empty files for corrupt RCS revisions. Fix for CVS crash on corrupt RCS data. Unable to process file: /Users/Workspaces/cvsroot/xxx,v java.lang.IndexOutOfBoundsException: Index: 24405, Size: 11725 at java.util.ArrayList.rangeCheckForAdd(ArrayList.java:612) at java.util.ArrayList.addAll(ArrayList.java:554) at com.perforce.cvs.parser.rcstypes.RcsObjectBlock.insert(RcsObjectBlock.java:31) at com.perforce.cvs.asset.CvsContentReader.undelta(CvsContentReader.java:214) at com.perforce.cvs.asset.CvsContentReader.cacheContent(CvsContentReader.java:98) at com.perforce.cvs.asset.CvsContentReader.cacheContent(CvsContentReader.java:71) at com.perforce.cvs.process.CvsProcessChange.buildRevisionList(CvsProcessChange.java:247) at com.perforce.cvs.process.CvsProcessChange.processChange(CvsProcessChange.java:74) at com.perforce.common.process.ProcessChange.runSingle(ProcessChange.java:90) at com.perforce.common.process.ProcessChange.call(ProcessChange.java:53) at com.perforce.common.process.ProcessChange.call(ProcessChange.java:20) at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334) at java.util.concurrent.FutureTask.run(FutureTask.java:166) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603) at java.lang.Thread.run(Thread.java:722) |
||
#5 | 10987 | Paul Allen |
CVS new RCS undelta parser. Searches for the exact number of added lines, before looking for the next delta action. Should read RCS data with versioned RCS data inside it. - Updated logging. |
||
#4 | 10957 | Paul Allen |
CVS parse RCS delta fix to regex. - added more debugging |
||
#3 | 10877 | Paul Allen |
Fix to add a warning if data block is missing. Unbranch operation fixes to follow (when unrelated files are added to branches off main) |
||
#2 | 10497 | Paul Allen |
New low-level RCS reader using a byte[] to manage CVS lines. Designed to help with the processing of BINARY data in RCS files. The line reading code still looks for a unix style '\n', but has a MAX LINE (hard coded to 10K). The RcsObjectBlock uses a ByteArrayOutputStream to store lines and parsers uses byte logic. (passes basic cvs/svn unit tests) |
||
#1 | 9807 | Paul Allen | Initial import of p4-convert (from change 894340) |