package com.perforce.svn.change; import java.util.ArrayList; import java.util.List; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.perforce.common.ConverterException; import com.perforce.common.asset.ContentType; import com.perforce.common.asset.TranslateCharsetType; import com.perforce.common.client.Connection; import com.perforce.common.client.ConnectionFactory; import com.perforce.common.client.P4Factory; import com.perforce.common.depot.DepotImport; import com.perforce.common.process.ChangeInfo; import com.perforce.common.process.ProcessFactory; import com.perforce.config.CFG; import com.perforce.config.CaseSensitivity; import com.perforce.config.Config; import com.perforce.config.ConfigException; import com.perforce.p4java.client.IClient; import com.perforce.p4java.core.ChangelistStatus; import com.perforce.p4java.core.IChangelist; import com.perforce.p4java.core.file.FileSpecBuilder; import com.perforce.p4java.core.file.IFileSpec; import com.perforce.p4java.impl.generic.core.Changelist; import com.perforce.p4java.server.IOptionsServer; import com.perforce.svn.history.ChangeAction; import com.perforce.svn.history.ChangeAction.Action; import com.perforce.svn.node.NodeAttributes; import com.perforce.svn.parser.Content; import com.perforce.svn.parser.Property; import com.perforce.svn.process.MergeInfo; import com.perforce.svn.process.MergeSource; import com.perforce.svn.query.QueryPerforce; public class ChangeImport implements ChangeInterface { private static Logger logger = LoggerFactory.getLogger(ChangeImport.class); private IClient iclient; private IChangelist ichangelist; private long change; private DepotImport depot; private ChangeInfo changeInfo; private List<MergeInfo> mergeInfoList = new ArrayList<MergeInfo>(); private MergeSource mergeSource; public ChangeImport(long c, ChangeInfo i, DepotImport d) throws Exception { changeInfo = i; depot = d; String description = i.getDescription(); Connection p4 = ConnectionFactory.getConnection(); iclient = p4.getIclient(); IChangelist implChangelist = new Changelist(); implChangelist.setClientId((String) Config.get(CFG.P4_CLIENT)); implChangelist.setDescription(description); implChangelist.setDate(changeInfo.getDate()); ichangelist = iclient.createChangelist(implChangelist); change = ichangelist.getId(); } @Override public void setCounter(String key, String value) throws Exception { Connection p4 = ConnectionFactory.getConnection(); IOptionsServer iserver = p4.getIserver(); iserver.setCounter(key, value, false); } @Override public void submit() throws Exception { ichangelist.refresh(); // check for empty changelist if (ichangelist.getFiles(true).isEmpty()) { delete(); // client won't submit empty change :-( } // submit change else { if (logger.isDebugEnabled()) { StringBuffer msg = new StringBuffer(); msg.append(" submitting changelist "); msg.append(ichangelist.getId()); msg.append(" by user "); msg.append(changeInfo.getUser()); logger.debug(msg.toString()); } // call submit and check returned spec List<IFileSpec> submitted = ichangelist.submit(null); String ignore = "Submitted as change"; P4Factory.validateFileSpecs(submitted, ignore); // Clean up workspace cleanWorkspace(); ichangelist.setDate(changeInfo.getDate()); ichangelist.setUsername(changeInfo.getUser()); ichangelist.update(true); // check if there was a problem if (ichangelist.getStatus() == ChangelistStatus.PENDING) { throw new ConverterException("Could not submit changelist!"); } } if (logger.isTraceEnabled()) { logger.trace("done.\n\n"); } } /** * Remove (unsync) files from clients local workspace * * @throws Exception */ private void cleanWorkspace() throws Exception { List<IFileSpec> fileSpecs; fileSpecs = FileSpecBuilder.makeFileSpecList(depot.getBase() + "...#none"); List<IFileSpec> syncMsg = iclient.sync(fileSpecs, null); P4Factory.validateFileSpecs(syncMsg, "file(s) up-to-date."); } /** * Delete pending changelist */ @Override public void delete() throws Exception { if (getNumberOfRevisions() > 0) throw new ConverterException("Changelist contains files"); // logging if (logger.isDebugEnabled()) { StringBuffer msg = new StringBuffer(); msg.append("deleting changelist "); msg.append(ichangelist.getId()); msg.append(" by user "); msg.append(ichangelist.getUsername()); logger.debug(msg.toString()); } IOptionsServer iserver = depot.getIServer(); iserver.setUserName(ichangelist.getUsername()); iserver.deletePendingChangelist(ichangelist.getId()); } public void addPath(Action nodeAction, String toPath, ArrayList<MergeSource> fromList, Property property, boolean subBlock) throws Exception { // Path syntax translation String depotToPath = depot.getBase() + toPath; // Deal with null paths and don't add extra '/' if (toPath == null) depotToPath = "//" + depot.getName(); // get a RevisionImport helper RevisionImport rev = new RevisionImport(iclient, ichangelist, depot, changeInfo.getDate()); switch (nodeAction) { case ADD: case EDIT: // find properties and store if required createDirProperty(toPath, property); break; case UPDATE: // remove directory or file rev.deletePath(depotToPath); removeAction(rev, depotToPath, false); addPath(Action.EDIT, toPath, fromList, property, subBlock); break; case COPY: // remove directory or file rev.deletePath(depotToPath); removeAction(rev, depotToPath, false); addPath(Action.BRANCH, toPath, fromList, property, subBlock); break; case REMOVE: // remove directory or file rev.deletePath(depotToPath); removeAction(rev, depotToPath, false); break; case BRANCH: for (MergeSource from : fromList) { String fromPath = from.getFromPath(); long fromChange = from.getEndFromChange(); String depotFromPath = depot.getBase() + fromPath; // Deal with null paths and don't add extra '/' if (fromPath == null || fromPath.isEmpty()) depotFromPath = "//" + depot.getName(); if (pathMatch(depotToPath, depotFromPath)) { rev.rollBackBranch(depotToPath, depotFromPath, fromChange); } else { rev.branchPath(depotFromPath, fromChange, depotToPath); } } // find properties and store if required createDirProperty(toPath, property); break; default: throw new ConverterException("Node-action(" + nodeAction + ")"); } } private void createDirProperty(String toPath, Property property) throws Exception { if (!(Boolean) Config.get(CFG.SVN_PROP_ENABLED) || property == null) return; // Property file path String propPath = toPath; if (!toPath.isEmpty()) { propPath += "/"; } propPath += Config.get(CFG.SVN_PROP_NAME); // Create attributes content and node Content content = new Content(); NodeAttributes attributes = new NodeAttributes(property); content.setAttributes(attributes); // Query perforce for last action QueryPerforce query = (QueryPerforce) ProcessFactory.getQuery(depot); ChangeAction lastProp = query.findLastAction(propPath, change); int headRev = query.findHeadRevision(propPath, change); // Determine necessary action Action act = null; if (!property.isEmpty()) { if ((lastProp != null) && (lastProp.getAction() != Action.REMOVE)) act = Action.EDIT; else act = Action.ADD; } else { if ((lastProp != null) && (lastProp.getAction() != Action.REMOVE)) act = Action.REMOVE; } if (act != null) { // Write header to content headRev += 1; // add as pending revision is not added on content.getAttributes().setHeader(propPath, change, headRev); addRevision(act, propPath, null, content, false, false); } } public void addRevision(Action nodeAction, String toPath, ArrayList<MergeSource> fromList, Content content, boolean subBlock, boolean pendingBlock) throws Exception { // Path syntax translation String depotToPath = depot.getBase() + toPath; // Get last 'to' action QueryPerforce query = (QueryPerforce) ProcessFactory.getQuery(depot); ChangeAction lastTo = query.findLastAction(toPath, change - 1); // get a RevisionImport helper RevisionImport rev = new RevisionImport(iclient, ichangelist, depot, changeInfo.getDate()); if (logger.isTraceEnabled()) { logger.trace("addRevision (" + nodeAction + ")"); } // down grade content type for non unicode servers from utf8 to text or // utf32 to binary if ((Boolean) Config.get(CFG.P4_UNICODE) == false) { if ((content.getType() == ContentType.UTF_32BE) || (content.getType() == ContentType.UTF_32LE)) { if (logger.isInfoEnabled()) { logger.info("... Non-unicode server, downgrading utf32 file to binary"); } content.setType(ContentType.P4_BINARY); } if (content.getType().getP4Type() == TranslateCharsetType.UTF8) { if (logger.isInfoEnabled()) { logger.info("... Non-unicode server, downgrading file to text"); } content.setType(ContentType.P4_TEXT); } } // Determine action and down grade if required switch (nodeAction) { case ADD: case EDIT: if (rev.isFile(depotToPath)) { // revert any pending actions (typically deletes) if (rev.openedFile(depotToPath, Action.REMOVE)) { rev.revertFile(depotToPath); if (logger.isDebugEnabled()) { logger.debug("reverting file: " + depotToPath); } } rev.editFile(depotToPath, content); } else { rev.addFile(depotToPath, content); } break; case UPDATE: // remove directory or file rev.deletePath(depotToPath); removeAction(rev, depotToPath, false); addRevision(Action.EDIT, toPath, fromList, content, subBlock, pendingBlock); break; case COPY: // remove directory or file rev.deletePath(depotToPath); removeAction(rev, depotToPath, false); addRevision(Action.BRANCH, toPath, fromList, content, subBlock, pendingBlock); break; case REMOVE: removeAction(rev, depotToPath, true); break; case BRANCH: case MERGE: // revert any pending actions (typically deletes) if (rev.openedFile(depotToPath)) { rev.revertFile(depotToPath); if (logger.isDebugEnabled()) { logger.debug("reverting file: " + depotToPath); } } for (MergeSource from : fromList) { String fromPath = from.getFromPath(); long startFromChange = from.getStartFromChange(); long endFromChange = from.getEndFromChange(); String depotFromPath = depot.getBase() + fromPath; if (pathMatch(depotToPath, depotFromPath)) { // roll back action rev.rollBackFile(depotToPath, content, depotFromPath, endFromChange); continue; } // Normal branch (no target or deleted target) if (lastTo == null || lastTo.getAction() == Action.REMOVE) { rev.branchFile(depotToPath, content, depotFromPath, endFromChange); } else { rev.integFile(depotToPath, content, depotFromPath, startFromChange, endFromChange, from.getMergeAction()); } } break; default: throw new ConverterException("Node-action(" + nodeAction + ")"); } } private void removeAction(RevisionImport rev, String depotToPath, boolean remove) throws Exception { if (rev.openedFile(depotToPath)) { if (!remove) { if (logger.isTraceEnabled()) { logger.trace("addRevision (reverting): " + depotToPath); } rev.revertFile(depotToPath); } else { rev.revertFile(depotToPath); rev.deleteFile(depotToPath); } } else { rev.deleteFile(depotToPath); } } @Override public int getNumberOfRevisions() throws Exception { List<IFileSpec> files = ichangelist.getFiles(true); return files.size(); } @Override public String getUser() { return changeInfo.getUser(); } @Override public long getChange() { return change; } @Override public void close() throws Exception { setCounter("p4-convert.svn.version", (String) Config.get(CFG.VERSION)); ConnectionFactory.close(); } @Override public long getSvnRevision() { return changeInfo.getScmChange(); } private boolean pathMatch(String toPath, String fromPath) throws ConfigException { boolean match = false; CaseSensitivity mode = (CaseSensitivity) Config.get(CFG.P4_CASE); // For case insensitive platforms ignore case when down grading if (mode == CaseSensitivity.NONE) { match = toPath.equals(fromPath); } else { match = toPath.equalsIgnoreCase(fromPath); } return match; } @Override public void setMergeInfo(MergeInfo m) { mergeInfoList.add(m); } @Override public List<MergeInfo> getMergeInfoList() { return mergeInfoList; } @Override public void setMergeSource(MergeSource m) { mergeSource = m; } @Override public MergeSource getMergeSource() { return mergeSource; } @Override public boolean isPendingRevision(String toPath) throws Exception { RevisionImport rev = new RevisionImport(iclient, ichangelist, depot, changeInfo.getDate()); String depotToPath = depot.getBase() + toPath; return rev.openedFile(depotToPath); } }
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#1 | 10152 | alan_petersen |
Populate //guest/alan_petersen/p4convert/... from //guest/perforce_software/p4convert/.... |
||
//guest/perforce_software/p4convert/src/com/perforce/svn/change/ChangeImport.java | |||||
#1 | 9807 | Paul Allen | Initial import of p4-convert (from change 894340) |