/* * ==================================================================== * Copyright (c) 2004-2012 TMate Software Ltd. All rights reserved. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms * are also available at http://svnkit.com/license.html. * If newer versions of this license are posted there, you may use a * newer version instead, at your option. * ==================================================================== */ package org.tmatesoft.svn.core.wc; import java.io.File; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import org.tmatesoft.svn.core.SVNException; import org.tmatesoft.svn.core.SVNProperties; import org.tmatesoft.svn.core.SVNProperty; import org.tmatesoft.svn.core.internal.util.SVNPathUtil; import org.tmatesoft.svn.core.internal.wc.SVNAdminUtil; import org.tmatesoft.svn.core.internal.wc.SVNFileUtil; import org.tmatesoft.svn.core.internal.wc.admin.SVNAdminArea; import org.tmatesoft.svn.core.internal.wc.admin.SVNLog; /** * The <b>SVNMergeFileSet</b> class holds information about the file that is to be merged. * This information includes references to <code>File</code> objects with working, base, repository contents; * file mimeType; labels to append to the file name to produce conflict files in case a merge fails with a * conflict, and so on. * * @version 1.3 * @author TMate Software Ltd. * @since 1.2 */ public class SVNMergeFileSet { private String myLocalFilePath; private String myBaseFilePath; private String myRepositoryFilePath; private String myWCFilePath; private String myMergeResultFilePath; private String myMimeType; private SVNAdminArea myAdminArea; private SVNLog myLog; private String myLocalLabel; private String myBaseLabel; private String myRepositoryLabel; private File myLocalFile; private File myBaseFile; private File myRepositoryFile; private File myMergeResultFile; private File myCopyFromFile; private Collection myTmpPaths = new ArrayList(); /** * Creates a new <code>SVNMergeFileSet</code> object given the data prepared for * merging a file. * * <p/> * Note: This is intended for internal use only, not for API users. * * @param adminArea admin area the file is controlled under * @param log log object * @param baseFile file with pristine contents * @param localFile file with translated working contents * @param wcPath working copy path relative to the location of <code>adminArea</code> * @param reposFile file contents from the repository * @param resultFile file where the resultant merged contents will be written to * @param copyFromFile contents of the copy source file (if any) * @param mimeType file mime type */ public SVNMergeFileSet(SVNAdminArea adminArea, SVNLog log, File baseFile, File localFile, String wcPath, File reposFile, File resultFile, File copyFromFile, String mimeType) { myAdminArea = adminArea; myLog = log; myLocalFile = localFile; myBaseFile = baseFile; myRepositoryFile = reposFile; myWCFilePath = wcPath; myMergeResultFile = resultFile; myCopyFromFile = copyFromFile; myMimeType = mimeType; if (myBaseFile != null) { if(myAdminArea!=null) { myBaseFilePath = SVNPathUtil.isAncestor(myAdminArea.getAdminDirectory().getAbsolutePath(), myBaseFile.getAbsolutePath()) ? SVNFileUtil.getBasePath(myBaseFile) : null; } else { myBaseFilePath = myBaseFile.getAbsolutePath(); } } if (myLocalFile != null) { myLocalFilePath = SVNFileUtil.getBasePath(myLocalFile); } if (myRepositoryFile != null) { if(myAdminArea!=null) { myRepositoryFilePath = SVNPathUtil.isAncestor(myAdminArea.getAdminDirectory().getAbsolutePath(), myRepositoryFile.getAbsolutePath()) ? SVNFileUtil.getBasePath(myRepositoryFile) : null; } else { myRepositoryFilePath = myRepositoryFile.getAbsolutePath(); } } if (myMergeResultFile != null) { myMergeResultFilePath = SVNFileUtil.getBasePath(myMergeResultFile); } } /** * Sets the labels for conflict files. * * <p/> * If <code>baseLabel</code> is <span class="javakeyword">null</span>, * <span class="javastring">".old"</span> will be set by default. * If <code>localLabel</code> is <span class="javakeyword">null</span>, * <span class="javastring">".working"</span> will be set by default. * If <code>repositoryLabel</code> is <span class="javakeyword">null</span>, * <span class="javastring">".new"</span> will be set by default. * * @param baseLabel base file label * @param localLabel working file label * @param repositoryLabel repository file label */ public void setMergeLabels(String baseLabel, String localLabel, String repositoryLabel) { myLocalLabel = localLabel == null ? ".working" : localLabel; myBaseLabel = baseLabel == null ? ".old" : baseLabel; myRepositoryLabel = repositoryLabel == null ? ".new" : repositoryLabel; } /** * Returns the log object. * * <p/> * Note: This is intended for internal use only, not for API users. * * @return wc modification commands logger */ public SVNLog getLog() { return myLog; } /** * Returns the base file label. * * @return base label string */ public String getBaseLabel() { return myBaseLabel; } /** * Returns the local file label. * * @return working file label */ public String getLocalLabel() { return myLocalLabel; } /** * Returns the repository file label. * * @return label of the repository file version */ public String getRepositoryLabel() { return myRepositoryLabel; } /** * Returns the base file path. * * <p/> * If the {@link #getBaseFile() base file} is located under the * {@link #getAdminArea() admin area}, then the return path will be just a relevant to the admin area path * of the base file. Otherwise (in case the repository file is located not under the admin area) this * method will create a temporary file in the <code>.svn/tmp</code> area of the admin area and copy the * contents of the base file into it; the return path will be again relative to the location of * the admin area. * * @return path of the file with pristine contents * @throws SVNException */ public String getBasePath() throws SVNException { if (myBaseFilePath == null && myBaseFile != null) { File tmp = SVNAdminUtil.createTmpFile(myAdminArea); SVNFileUtil.copyFile(myBaseFile, tmp, false); myBaseFilePath = SVNFileUtil.getBasePath(tmp); myTmpPaths.add(myBaseFilePath); } return myBaseFilePath; } /** * Returns the path of the detranslated version of the working copy file. * Detranslating of a working copy file takes place in case it's a symlink, or it has keywords or * eol-style properties set on it. * * @return path to the file with detranslated working contents; it's relevant to the * {@link #getAdminArea() admin area} location */ public String getLocalPath() { return myLocalFilePath; } /** * Returns the path of the working copy file. * * @return path of the working copy file; it's relevant to the {@link #getAdminArea() admin area} location */ public String getWCPath() { return myWCFilePath; } /** * Returns the path to the file containing the contents of the repository version of the file. * * <p/> * If the {@link #getRepositoryFile() repository file} is located under the * {@link #getAdminArea() admin area}, then the return path will be just a relevant to the admin area path * of the repository file. Otherwise (in case the repository file is located not under the admin area) this * method will create a temporary file in the <code>.svn/tmp</code> area of the admin area and copy the * contents of the repository file into it; the return path will be again relative to the location of * the admin area. * * @return path of the file containing file contents that come from the repository * @throws SVNException */ public String getRepositoryPath() throws SVNException { if (myRepositoryFilePath == null && myRepositoryFile != null) { File tmp = SVNAdminUtil.createTmpFile(myAdminArea); SVNFileUtil.copyFile(myRepositoryFile, tmp, false); myRepositoryFilePath = SVNFileUtil.getBasePath(tmp); myTmpPaths.add(myRepositoryFilePath); } return myRepositoryFilePath; } /** * Returns the path of the file where the merged resultant text is written to. * * @return path of the result file; it's relevant to the {@link #getAdminArea() admin area} location */ public String getResultPath() { return myMergeResultFilePath; } /** * Returns the file containing the pristine file contents. * @return base file */ public File getBaseFile() { return myBaseFile; } /** * Returns the working copy file as it presents in the working copy. * @return working copy file */ public File getWCFile() { if(myAdminArea!=null) { return myAdminArea.getFile(myWCFilePath); } return myWCFilePath!=null? new File(myWCFilePath) : null; } /** * Returns the detranslated working copy file. * Detranslating of a working copy file takes place in case it's a symlink, or it has keywords or * eol-style properties set on it. * * @return detranslated working copy file */ public File getLocalFile() { return myLocalFile; } /** * Returns the repository version of the file. * @return repository file */ public File getRepositoryFile() { return myRepositoryFile; } /** * Returns the file where the merged resultant text is written to. * @return merge result file */ public File getResultFile() { return myMergeResultFile; } /** * Tells whether this file is binary or textual. * The result will depend on the value of the file {@link #getMimeType() mime type}. * * @return <span class="javakeyword">true</span> if binary */ public boolean isBinary() { return SVNProperty.isBinaryMimeType(myMimeType); } /** * Returns the mime type of the file. * @return file mime type */ public String getMimeType() { return myMimeType; } /** * Returns the admin area which controls the file. * * <p/> * Note: this method is not intended for API users. * @return admin area */ public SVNAdminArea getAdminArea() { return myAdminArea; } /** * Disposes this object. * * <p/> * Note: this method is not intended for API users. * @throws SVNException */ public void dispose() throws SVNException { // add deletion commands to the log file. SVNProperties command = new SVNProperties(); for (Iterator paths = myTmpPaths.iterator(); paths.hasNext();) { String path = (String) paths.next(); command.put(SVNLog.NAME_ATTR, path); myLog.addCommand(SVNLog.DELETE, command, false); command.clear(); } } /** * Returns the file which is the copy source for the file being merged. * @return copy source file */ public File getCopyFromFile() { return myCopyFromFile; } /** * Returns the copy source path. * * @return path of the copy source file; * it's relevant to the {@link #getAdminArea() admin area} location * @since 1.3 */ public String getCopyFromPath() { String root = myAdminArea.getRoot().getAbsolutePath().replace(File.separatorChar, '/'); String copyFrom = getCopyFromFile().getAbsolutePath().replace(File.separatorChar, '/'); String copyFromPath = copyFrom.substring(root.length()); copyFromPath = copyFromPath.startsWith("/") ? copyFromPath.substring("/".length()) : copyFromPath; return copyFromPath; } }