package com.perforce.cvs; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.perforce.config.CFG; import com.perforce.config.Config; import com.perforce.cvs.parser.RcsReader; import com.perforce.cvs.parser.rcstypes.RcsObjectDelta; import com.perforce.cvs.parser.rcstypes.RcsObjectNum; import com.perforce.cvs.parser.rcstypes.RcsObjectNumList; import com.perforce.cvs.parser.rcstypes.RcsObjectTag; import com.perforce.cvs.parser.rcstypes.RcsObjectTagList; public abstract class RcsNavigator { private Logger logger = LoggerFactory.getLogger(RcsNavigator.class); protected abstract void foundBranchEntry(String name, RevisionEntry entry); protected abstract void foundBranchPoint(String name, RevisionEntry entry); private RcsReader rcsRevision; private Map<RcsObjectNum, String> labelMap = new HashMap<RcsObjectNum, String>(); private Map<RcsObjectNum, String> branchMap = new HashMap<RcsObjectNum, String>(); protected RcsReader getRcsRevision() { return rcsRevision; } protected Set<Entry<RcsObjectNum, String>> getBranchMap() { return branchMap.entrySet(); } protected Set<Entry<RcsObjectNum, String>> getLabelMap() { return labelMap.entrySet(); } /** * Takes an RCS file; navigates the RCS to find all revisions, then adds * them to the list for sorting. * * @param rcs * @throws Exception */ public void add(RcsReader rcs) throws Exception { rcsRevision = rcs; if (logger.isDebugEnabled()) { logger.debug("RCS file: " + rcs.getRcsFile().getName()); } // get label and branch names RcsObjectTagList tags = rcs.getAdmin().getSymbols(); for (RcsObjectTag tag : tags.getList()) { buildMaps(tag); } // Process HEAD code-line and recurse branches RcsObjectNum head = rcs.getAdmin().getHead(); followCodeLine(head, null); // xxx populateFullBranch(); } /** * Follow all the revisions in code-line starting with RcsObjectNum 'id' * * @return * * @throws Exception */ protected void followCodeLine(RcsObjectNum id, RevisionEntry parent) throws Exception { do { RcsObjectDelta revision = rcsRevision.getDelta(id); RevisionEntry entry = new RevisionEntry(revision); // look for IDs matching a tag in the branch map for (Entry<RcsObjectNum, String> br : getBranchMap()) { String tagName = br.getValue(); RcsObjectNum brId = getBranchId(br.getKey()); if (brId.equals(id)) { String state = revision.getState(); if (!"dead".equals(state)) { foundBranchPoint(tagName, entry); } } } // get tmp content name String tmp = (String) Config.get(CFG.CVS_TMPDIR); String basePath = rcsRevision.getPath(); entry.setTmpFile(tmp + "/" + basePath + "/" + id.toString()); // fetch from id RcsObjectNum from = null; if (parent != null) { from = parent.getId(); } // if branch, get name and add to list of revisions to sort String branchName = getBranchName(id, from); if (branchName != null) { if (!"main".equals(branchName) && id.getMinor() == 1) { String fromBranch = getParentName(from); String fromPath = fromBranch + "/" + basePath; entry.setFromPath(fromPath); } entry.setPath(branchName + "/" + basePath); foundBranchEntry(branchName, entry); } // add label to revision String labelName = getLabelName(id); if (labelName != null) { entry.addLabel(labelName); } // follow tags off code line [recursive] RcsObjectNumList tagList = revision.getBranches(); if (!tagList.isEmpty()) { for (RcsObjectNum tag : tagList.getList()) { followCodeLine(tag, entry); } } // next... id = revision.getNext(); } while (id != null); } /** * Check if a branch ID contains '0' and return short branch ID. e.g. * 1.56.0.2 ==> 1.56.2, else leave as-is for label * * @param id * @return */ protected void buildMaps(RcsObjectTag tag) { RcsObjectNum id = tag.getId(); String name = tag.getTag(); if (id.getValues().contains(0)) { List<Integer> branch = new ArrayList<Integer>(id.getValues()); int index = branch.size() - 2; branch.remove(index); RcsObjectNum branchId = new RcsObjectNum(branch); if (logger.isDebugEnabled()) { logger.debug("\tbranch: '" + name + "' " + branchId.toString()); } branchMap.put(branchId, name); } else { if (logger.isDebugEnabled()) { logger.debug("\tlabel: '" + name + "'"); } labelMap.put(id, name); } } /** * Return shortened branch ID e.g. 1.56.2.1 ==> 1.56.2 * * @param id * @return */ protected RcsObjectNum getBranchId(RcsObjectNum id) { List<Integer> branch = new ArrayList<Integer>(id.getValues()); int index = branch.size() - 1; branch.remove(index); return new RcsObjectNum(branch); } private String getBranchName(RcsObjectNum id, RcsObjectNum from) { // check for mainline if (from == null) { return "main"; } // return branch name RcsObjectNum branchId = getBranchId(id); if (branchMap.containsKey(branchId)) { return branchMap.get(branchId); } return null; } private String getLabelName(RcsObjectNum id) { if (labelMap.containsKey(id)) { return labelMap.get(id); } return null; } protected String getParentName(RcsObjectNum from) { if (from == null) { return null; } if (branchMap.containsKey(from)) { return branchMap.get(from); } return "main"; } }
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#21 | 13920 | Paul Allen | copy part 2 (no errors) | ||
#20 | 13776 | Paul Allen |
CVS: Update to node Action detection. The RCS State is normally set to 'Exp' and 'dead', but this change allows more user defined states. - Move Action class to common.node package. - Modified test case061 to test custom states. |
||
#19 | 12535 | Paul Allen |
CVS/SVN: Substitute spaces with an '_' for label names. - update SVN test case118 to verify substitution. |
||
#18 | 12516 | Paul Allen |
CVS: Label format fix. CVS branches downgraded to labels were missed during formatting. |
||
#17 | 12440 | Paul Allen | CVS: More efficient parsing of RCS files. | ||
#16 | 12319 | Paul Allen |
CVS: Format label names using com.p4convert.cvs.labelFormat. Default is: '{symbol}' the string is replaced by the CVS symbol used for that label. |
||
#15 | 12300 | Paul Allen | CVS: Prevent first entry 'dead' revisions (n*.1) from showing up as branched revisions. | ||
#14 | 12195 | Paul Allen |
CVS - Use the RCS 'expand' field to detect BINARY files. If set this will take precedence over the type map. - Added test case061 |
||
#13 | 12001 | Paul Allen |
CVS: Fix 'dead' 1.1 revisions from showing up as branched revisions. - Updated testcases 35, 50, 51 #review-12002 @rjackson @nmorse |
||
#12 | 11226 | Paul Allen | Tidy imports and unused code. | ||
#11 | 11144 | Paul Allen |
CVS: Bug fix for strange case of a (dead) 1.1 revision. This seems to occur when the source is from another branch. Not a perfect solution as I change this action to an add, but it allows the conversion to complete and no content is lost. |
||
#10 | 11064 | Paul Allen |
CVS: added detection and support for +x revisions - extended testcase 040 to test for exec bits |
||
#9 | 11006 | Paul Allen | CVS: remove experimental code (not required) | ||
#8 | 10984 | Paul Allen |
CVS: Tidy up logging - added revision count. |
||
#7 | 10978 | Paul Allen |
CVS redesign of RCS Revision Navigation. - Disabled reverse RCS tag lookup for the moment. |
||
#6 | 10945 | Paul Allen |
CVS branch of a branch RCS ID was not calculated for branch. - added test case 050 |
||
#5 | 10943 | Paul Allen |
CVS fix extra branches. Clear labelMap and branchMap between adding new revisions. ---------------------------------------------------- 6608.0 B:F - main/tc_crypt_utils/tests/certpriv.pem (UNKNOWN) [pool-1-thread-1] ERROR node.NodeConvert: CASE-SENSITIVITY ISSUE: Cannot branch a deleted revision to a non-existant or deleted revision. Please check case options and platform types. com.p4convert.p4.caseMode = NONE com.p4convert.p4.lowerCase = false [pool-1-thread-1] ERROR process.ProcessChange: Caught exception on exit java.lang.RuntimeException: CASE-SENSITIVITY ISSUE: Cannot branch a deleted revision to a non-existant or deleted revision. Please check case options and platform types. com.p4convert.p4.caseMode = NONE com.p4convert.p4.lowerCase = false at com.perforce.svn.node.NodeConvert.fileAction(NodeConvert.java:179) at com.perforce.svn.node.NodeConvert.action(NodeConvert.java:79) at com.perforce.cvs.process.CvsProcessNode.processFile(CvsProcessNode.java:119) at com.perforce.common.process.ProcessNode.process(ProcessNode.java:42) at com.perforce.cvs.process.CvsProcessChange.addEntry(CvsProcessChange.java:310) at com.perforce.cvs.process.CvsProcessChange.nextEntry(CvsProcessChange.java:268) at com.perforce.cvs.process.CvsProcessChange.processChange(CvsProcessChange.java:105) at com.perforce.common.process.ProcessChange.runSingle(ProcessChange.java:86) at com.perforce.common.process.ProcessChange.call(ProcessChange.java:49) at com.perforce.common.process.ProcessChange.call(ProcessChange.java:19) at java.util.concurrent.FutureTask.run(FutureTask.java:262) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) at java.lang.Thread.run(Thread.java:745) Caught EXIT shutting down ... |
||
#4 | 10912 | Paul Allen |
Back out changelist 10911 - Tmp file look to be in error |
||
#3 | 10911 | Paul Allen |
CVS memory optimisation - Calculate tmp file (has some risk, but saves lots of memory) - String.intern() must use with java 7 or later. |
||
#2 | 10839 | Paul Allen |
Update Import Test framework (CVS/SVN) to support labels. CVS test case 030 update and code cleanup. |
||
#1 | 10728 | Paul Allen |
CVS: new Label feature. Scans the RCS tree counting revisions on a branch. If the branch only has one revision it gets downgraded to a Label. Support added for Import and Convert mode. Activate using: com.p4convert.cvs.labels=true or in java Config.set(CFG.CVS_LABELS, true); (manual testing only -- automated tests will follow this change) |